FusionDirectory
 All Data Structures Files Functions Variables
class_simpleManagement.inc
1 <?php
2 /*
3  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
4  Copyright (C) 2013-2016 FusionDirectory
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20 
22 {
23  protected $simpleManagement;
24  protected $type;
25  protected $template = NULL;
26  protected $templates;
27  protected $target = NULL;
28 
29  protected $tabObject;
30 
31  protected $post_finish = 'template_continue';
32  protected $post_cancel = 'template_cancel';
33 
34  function __construct($simpleManagement, $type, $dn = NULL, $target = NULL)
35  {
36  $this->simpleManagement = $simpleManagement;
37  $this->type = $type;
38  $this->templates = objects::getTemplates($this->type);
39  if ($dn !== NULL) {
40  if (isset($this->templates[$dn])) {
41  $this->template = new template($this->type, $dn);
42  } else {
43  trigger_error('Unknown template "'.$dn.'"');
44  }
45  }
46  $this->target = $target;
47  }
48 
49  function save_object ()
50  {
51  if ($this->target === NULL) {
52  if (isset($_POST[$this->post_cancel])) {
53  return $this->handle_cancel();
54  }
55  if ((isset($_POST[$this->post_finish]) || isset($_GET[$this->post_finish])) && is_object($this->template)) {
56  $this->template->save_object();
57  return $this->handle_finish();
58  }
59  }
60 
61  if (
62  isset($_POST['template']) &&
63  isset($this->templates[$_POST['template']])
64  ) {
65  if (is_object($this->template)) {
66  trigger_error('redefining template object');
67  }
68  $this->template = new template($this->type, $_POST['template']);
69  /* This method can loop if there are several targets */
70  unset($_POST['template']);
71  }
72  if (is_object($this->template)) {
73  if ($this->target !== NULL) {
74  $this->simpleManagement->openTabObject($this->template->apply($this->target), $this->template->getBase());
75  $this->simpleManagement->handleTemplateApply();
76  return FALSE;
77  } else {
78  $this->template->save_object();
79  }
80  }
81 
82  return TRUE;
83  }
84 
85  function setNextTarget ($target)
86  {
87  $this->target = $target;
88  $this->template->reset();
89  }
90 
91  function execute ()
92  {
93  $smarty = get_smarty();
94  if (is_object($this->template)) {
95  $smarty->assign('template_dialog', $this->template->execute());
96  } else {
97  $smarty->assign('templates', $this->templates);
98  }
99  $display = $smarty->fetch(get_template_path('template.tpl'));
100  return $display;
101  }
102 
103  function handle_finish ()
104  {
105  $this->simpleManagement->closeDialogs();
106  $this->simpleManagement->openTabObject($this->template->apply(), $this->template->getBase());
107  return FALSE;
108  }
109 
110  function handle_cancel ()
111  {
112  $this->simpleManagement->closeDialogs();
113  return FALSE;
114  }
115 }
116 
118 {
119  // The currently used object(s) (e.g. in edit, removal)
120  // $dn is public due to some compatibility problems with class plugin..
121  public $dn = '';
122  protected $dns = array();
123 
124  // The last used object(s).
125  protected $last_dn = '';
126  protected $last_dns = array();
127 
128  // The common places the displayed objects are stored in. (e.g. array("ou=groups,",".."))
129  protected $storagePoints = array();
130 
131  // The opened object.
132  protected $tabObject = NULL;
133  protected $dialogObject = NULL;
134 
135  // The last opened object.
136  protected $last_tabObject = NULL;
137  protected $last_dialogObject = NULL;
138 
139  // Whether to display the apply button or not
140  protected $displayApplyBtn = FALSE;
141 
142  // Whether to display a header or not.
143  protected $skipHeader = FALSE;
144 
145  // Whether to display a footer or not.
146  protected $skipFooter = FALSE;
147 
148  // Copy&Paste handler
149  protected $cpHandler = NULL;
150 
151  // Indicates that we want to paste objects right now.
152  protected $cpPastingStarted = FALSE;
153 
154  // The Snapshot handler class.
155  protected $snapHandler = NULL;
156 
157  // The listing handlers
158  protected $headpage = NULL;
159  protected $filter = NULL;
160 
161  // A list of configured actions/events
162  protected $actions = array();
163 
164  // Some management classes are used in tab groups and needs this
165  public $is_template = FALSE;
166  public $attributes = array();
167 
168  /* Attributes that child classes should override */
169  protected $objectTypes = array();
170 
171  /* Attributes that child classes can override */
172  protected $departmentBrowser = TRUE;
173  protected $departmentRootVisible = TRUE;
174  protected $baseMode = TRUE;
175  protected $multiSelect = TRUE;
176 
177  protected $filterXMLPath = NULL;
178  protected $listXMLPath = NULL;
179  protected $autoFilter = TRUE;
180  protected $autoActions = TRUE;
181  protected $skipCpHandler = FALSE;
182  protected $skipSnapHandler = FALSE;
183 
184  protected $autoFilterAttributes = array('dn', 'cn', 'description');
185 
186  protected $headpageClass = "listing";
187 
188  public static $skipTemplates = TRUE;
189 
190  function __construct()
191  {
192  global $config;
193 
194  if ($this->filterXMLPath === NULL) {
195  $this->filterXMLPath = get_template_path('simple-filter.xml', TRUE, dirname(__FILE__));
196  }
197  if ($this->listXMLPath === NULL) {
198  $this->listXMLPath = get_template_path('simple-list.xml', TRUE, dirname(__FILE__));
199  }
200 
201  foreach ($this->objectTypes as &$object) {
202  $object = strtoupper($object);
203  }
204  unset($object);
205 
206  $this->storagePoints = array();
207  foreach ($this->objectTypes as $key => $object) {
208  try {
209  $i = objects::infos($object);
210  } catch (NonExistingObjectTypeException $e) {
211  /* Remove objectTypes which are not existing */
212  unset($this->objectTypes[$key]);
213  continue;
214  }
215  if ($i['ou'] !== NULL) {
216  $this->storagePoints[] = $i['ou'];
217  }
218  }
219  $this->storagePoints = array_unique($this->storagePoints);
220  if (count($this->storagePoints) == 0) {
221  $this->storagePoints[] = '';
222  }
223 
224  // Build filter
225  if (session::global_is_set(get_class($this).'_filter')) {
226  $filter = session::global_get(get_class($this).'_filter');
227  } else {
228  $filter = new filter($this->filterXMLPath);
229  $filter->setObjectStorage($this->storagePoints);
230  }
231  $this->setFilter($filter);
232 
233  // Build headpage
234  $this->headpage = new $this->headpageClass($this->parseXML($this->listXMLPath));
235  $this->headpage->setFilter($filter);
236 
237  // Add copy&paste and snapshot handler.
238  if (!$this->skipCpHandler) {
239  $this->cpHandler = new CopyPasteHandler();
240  $this->headpage->setCopyPasteHandler($this->cpHandler);
241  $this->registerAction('copy', 'copyPasteHandler');
242  $this->registerAction('cut', 'copyPasteHandler');
243  $this->registerAction('paste', 'copyPasteHandler');
244  }
245  if (!$this->skipSnapHandler && ($config->get_cfg_value('enableSnapshots') == 'TRUE')) {
246  $this->snapHandler = new SnapshotHandler();
247  $this->headpage->setSnapshotHandler($this->snapHandler);
248  $this->registerAction('snapshot', 'createSnapshotDialog');
249  $this->registerAction('restore', 'restoreSnapshotDialog');
250  }
251 
252  // Register default actions
253  $this->registerAction('new', 'newEntry');
254  $this->registerAction('edit', 'editEntry');
255  $this->registerAction('apply', 'applyChanges');
256  $this->registerAction('save', 'saveChanges');
257 
258  $this->registerAction('cancel', 'cancelEdit');
259  $this->registerAction('cancelDelete', 'cancelEdit');
260 
261  $this->registerAction('remove', 'removeEntryRequested');
262  $this->registerAction('removeConfirmed', 'removeEntryConfirmed');
263 
264  $this->configureHeadpage();
265  $this->configureFilter();
266  if ($this->baseMode === FALSE) {
267  $this->headpage->setBase($config->current['BASE']);
268  }
269  }
270 
271  /* Build the action menu, fill the object definition, etc, based on objectTypes info */
272  function configureHeadpage ()
273  {
274  if ($this->autoActions) {
275  if (static::$skipTemplates) {
276  $this->headpage->xmlData['actionmenu']['action'][0]['action'] = array();
277  } else {
278  $this->headpage->xmlData['actionmenu']['action'][0]['action'] = array(
279  array(
280  'type' => 'sub',
281  'image' => 'geticon.php?context=devices&icon=template&size=16',
282  'label' => _('Template'),
283  'action' => array(),
284  ),
285  array(
286  'type' => 'sub',
287  'image' => 'geticon.php?context=actions&icon=document-new&size=16',
288  'label' => _('From template'),
289  'action' => array(),
290  ),
291  );
292  }
293  }
294  $this->configureHeadline();
295  foreach ($this->objectTypes as $object) {
296  $i = objects::infos($object);
297 
298  if (!isset($i['icon'])) {
299  trigger_error('Missing icon for type '.$object);
300  $i['icon'] = '';
301  }
302 
303  $filterObject = objects::getFilterObject($object);
304  $this->headpage->objectTypes[$object] =
305  array(
306  'label' => $i['name'],
307  'category' => $i['aclCategory'],
308  'class' => $i['mainTab'],
309  'image' => $i['icon'],
310  'filter' => $filterObject,
311  'nameAttr' => $i['nameAttr'],
312  );
313  if (!static::$skipTemplates) {
314  $this->headpage->objectTypes['template_'.$object] =
315  array(
316  'label' => sprintf(_('%s template'), $i['name']),
317  'category' => $i['aclCategory'],
318  'class' => 'template',
319  'image' => 'geticon.php?context=devices&icon=template&size=16',
320  'filter' =>
321  new ldapFilter(
322  '&',
323  array(
324  new ldapFilterLeaf('objectClass', '=', 'fdTemplate'),
325  fdTemplateFilter($filterObject),
326  )
327  ),
328  'nameAttr' => $i['nameAttr'],
329  );
330  }
331  $this->headpage->categories[] = $i['aclCategory'];
332  if ($this->autoActions) {
333  $this->registerAction('new_'.$object, 'newEntry');
334  $icon = 'geticon.php?context=actions&amp;icon=document-new&amp;size=16';
335  if (isset($i['icon'])) {
336  $icon = $i['icon'];
337  } else {
338  $infos = pluglist::pluginInfos($i['mainTab']);
339  if (isset($infos['plIcon'])) {
340  $icon = $infos['plIcon'];
341  }
342  }
343  $this->headpage->xmlData['actionmenu']['action'][0]['action'][] = array(
344  'name' => 'new_'.$object,
345  'type' => 'entry',
346  'image' => $icon,
347  'label' => $i['name'],
348  'acl' => $i['aclCategory'].'/'.$i['mainTab'].'[c]',
349  );
350  if (!static::$skipTemplates) {
351  $this->registerAction('new_template_'.$object, 'newEntryTemplate');
352  $this->registerAction('template_apply_'.$object, 'newEntryFromTemplate');
353  $this->headpage->xmlData['actionmenu']['action'][0]['action'][0]['action'][] = array(
354  'name' => 'new_template_'.$object,
355  'type' => 'entry',
356  'image' => $icon,
357  'label' => $i['name'],
358  'acl' => $i['aclCategory'].'/template[c]',
359  );
360  $this->headpage->xmlData['actionmenu']['action'][0]['action'][1]['action'][] = array(
361  'name' => 'template_apply_'.$object,
362  'type' => 'entry',
363  'image' => $icon,
364  'label' => $i['name'],
365  'acl' => $i['aclCategory'].'/'.$i['mainTab'].'[c]',
366  );
367  }
368  }
369  }
370  if ($this->autoActions && !static::$skipTemplates) {
371  $this->registerAction('template_apply', 'newEntryFromTemplate');
372  }
373  $this->headpage->refreshBasesList();
374  }
375 
376  function configureHeadline ()
377  {
378  $pInfos = pluglist::pluginInfos(get_class($this));
379  $this->headpage->headline = $pInfos['plShortName'];
380  }
381 
382  function configureFilterCategory ()
383  {
384  $pInfos = pluglist::pluginInfos(get_class($this));
385  $cat = NULL;
386  if (isset($pInfos['plCategory'])) {
387  $cat = key($pInfos['plCategory']);
388  if (is_numeric($cat)) {
389  $cat = $pInfos['plCategory'][$cat];
390  }
391  } elseif (isset($pInfos['plObjectType'])) {
392  $ot = key($pInfos['plObjectType']);
393  if (is_numeric($ot)) {
394  $ot = $pInfos['plObjectType'][$ot];
395  }
396  $infos = objects::infos($ot);
397  $cat = $infos['aclCategory'];
398  }
399  if ($cat === NULL) {
400  trigger_error('Could not find a category for '.get_class($this));
401  }
402  $this->filter->category = $cat;
403  }
404 
405  /* Build the filter(s) based on objectTypes info */
406  function configureFilter ()
407  {
408  if ($this->autoFilter) {
409  $this->configureFilterCategory();
410  $attributes = $this->autoFilterAttributes;
411  $filter = '(|';
412  foreach ($this->objectTypes as $object) {
413  $tag = 'FILTER'.$object;
414  $filter .= '$'.$tag;
415  $i = objects::infos($object);
416  $this->filter->elements[$tag] = array(
417  'type' => 'checkbox',
418  'tag' => $tag,
419  'default' => TRUE,
420  'unset' => array(),
421  'set' => preg_replace('/\$/', '\\\$', $i['filter'])
422  );
423  $this->filter->elementValues[$tag] = TRUE;
424 
425  if ($i['mainAttr']) {
426  $attributes[] = $i['mainAttr'];
427  }
428  if ($i['nameAttr']) {
429  $attributes[] = $i['nameAttr'];
430  }
431  }
432  if (!static::$skipTemplates) {
433  $tag = 'FILTERTEMPLATE';
434  $filter .= '$'.$tag;
435  $this->filter->elements[$tag] = array(
436  'type' => 'checkbox',
437  'tag' => $tag,
438  'default' => TRUE,
439  'unset' => array(),
440  'set' => '(objectClass=fdTemplate)'
441  );
442  $this->filter->elementValues[$tag] = TRUE;
443  $attributes[] = 'fdTemplateField';
444  }
445  $filter .= ')';
446  $attributes = array_values(array_unique($attributes));
447  $this->filter->query[0]['filter'] = '(&'.$filter.'$NAME)';
448  $this->filter->query[0]['attribute'] = $attributes;
449  $this->filter->elements['NAME']['set'] = '(|('.join('=*$*)(', $attributes).'=*$*))';
450  $this->filter->elements['NAME']['autocomplete']['filter'] = '(&'.$filter.'(|('.join('=*$NAME*)(', $attributes).'=*$NAME*))'.')';
451  $this->filter->elements['NAME']['autocomplete']['attribute'] = $attributes;
452  uasort($this->filter->elements, 'strlenSort');
453  $this->filter->elements = array_reverse($this->filter->elements);
454  }
455  }
456 
457  function parseXML ($file)
458  {
459  $contents = file_get_contents($file);
460  $data = xml::xml2array($contents, 1);
461  foreach (array('departmentBrowser','departmentRootVisible','baseMode','multiSelect') as $var) {
462  $data['list']['definition']["$var"] = ($this->$var ? 'true' : 'false');
463  }
464  return $data;
465  }
466 
467  function getHeadpage()
468  {
469  return $this->headpage;
470  }
471 
472  function getFilter()
473  {
474  return $this->filter;
475  }
476 
482  function setFilter($filter)
483  {
484  $this->filter = $filter;
485  }
486 
494  function registerAction($action, $target)
495  {
496  $this->actions[$action] = $target;
497  }
498 
499  function getType($dn)
500  {
501  return $this->getHeadpage()->getType($dn);
502  }
503 
504  function renderList()
505  {
506  global $config;
507  $smarty = get_smarty();
508  $filters = array();
509  foreach ($this->objectTypes as $object) {
510  $filters[] = array(
511  'id' => 'FILTER'.$object,
512  'label' => sprintf(_('Show %s'), $config->data['OBJECTS'][$object]['name'])
513  );
514  }
515  if (!static::$skipTemplates) {
516  $filters[] = array(
517  'id' => 'FILTERTEMPLATE',
518  'label' => sprintf(_('Show %s'), _('Template'))
519  );
520  }
521  $smarty->assign('objectFilters', $filters);
522  $this->headpage->update();
523  $display = $this->headpage->render();
524  return $this->getHeader().$display;
525  }
526 
531  function execute()
532  {
533  // Ensure that html posts and gets are kept even if we see a 'Entry islocked' dialog.
534  $vars = array('/^act$/','/^listing/','/^PID$/');
535  session::set('LOCK_VARS_TO_USE', $vars);
536 
537  /* Display the copy & paste dialog, if it is currently open */
538  $ret = $this->copyPasteHandler();
539  if ($ret) {
540  return $this->getHeader().$ret;
541  }
542 
543  // Update filter
544  if ($this->filter) {
545  $this->filter->update();
546  session::global_set(get_class($this).'_filter', $this->filter);
547  session::set('autocomplete', $this->filter);
548  if (!$this->filter->isValid()) {
549  msg_dialog::display(_('Filter error'), _('The filter is incomplete!'), ERROR_DIALOG);
550  }
551  }
552 
553  // Handle actions (POSTs and GETs)
554  $str = $this->handleActions($this->detectPostActions());
555  if ($str) {
556  return $this->getHeader().$str;
557  }
558 
559  // Open single dialog objects
560  if (is_object($this->dialogObject)) {
561  if (method_exists($this->dialogObject, 'save_object')) {
562  $this->dialogObject->save_object();
563  }
564  if (method_exists($this->dialogObject, 'execute')) {
565  $display = $this->dialogObject->execute();
566  $display .= $this->_getTabFooter();
567  return $this->getHeader().$display;
568  }
569  }
570 
571  // Display tab object.
572  if ($this->tabObject instanceOf simpleTabs) {
573  $this->tabObject->save_object();
574  $display = $this->tabObject->execute();
575  $display .= $this->_getTabFooter();
576  return $this->getHeader().$display;
577  }
578 
579  // Set current restore base for snapshot handling.
580  if (is_object($this->snapHandler)) {
581  $bases = array();
582  foreach ($this->storagePoints as $sp) {
583  $bases[] = $sp.$this->headpage->getBase();
584  }
585 
586  // No bases specified? Try base
587  if (!count($bases)) {
588  $bases[] = $this->headpage->getBase();
589  }
590 
591  $this->snapHandler->setSnapshotBases($bases);
592  }
593 
594  // Display list
595  return $this->renderList();
596  }
597 
601  protected function getHeader()
602  {
603  if ($this->skipHeader) {
604  return '';
605  }
606 
607  $plInfos = pluglist::pluginInfos(get_class($this));
608  $plTitle = $plInfos['plTitle'];
609  $plIcon = $plInfos['plIcon'];
610 
611  if (!preg_match('/^geticon/', $plIcon)) {
612  $plIcon = get_template_path($plIcon);
613  }
614  return print_header($plIcon, $plTitle, get_object_info());
615  }
616 
620  protected function _getTabFooter()
621  {
622  // Do not display tab footer for non tab objects
623  if (!($this->tabObject instanceOf simpleTabs)) {
624  return '';
625  }
626 
627  // Check if there is a dialog opened - We don't need any buttons in this case.
628  if ($this->tabObject->dialogOpened()) {
629  return '';
630  }
631 
632  // Skip footer if requested;
633  if ($this->skipFooter) {
634  return '';
635  }
636 
637  // In case an of locked entry, we may have opened a read-only tab.
638  $str = '';
639  if ($this->tabObject->readOnly()) {
640  $str .= '<p class="plugbottom">'."\n".
641  '<input type="submit" name="edit_cancel" value="'.msgPool::cancelButton().'">'."\n".
642  '</p>';
643  return $str;
644  } else {
645  // Display ok, (apply) and cancel buttons
646  $str .= '<p class="plugbottom">'."\n";
647  $str .= '<input type="submit" name="edit_finish" style="width:80px" value="'.msgPool::okButton().'"/>'."\n";
648  $str .= "&nbsp;\n";
649  if ($this->displayApplyBtn) {
650  $str .= '<input type="submit" name="edit_apply" value="'.msgPool::applyButton().'"/>'."\n";
651  $str .= "&nbsp;\n";
652  }
653  $str .= '<input type="submit" name="edit_cancel" value="'.msgPool::cancelButton().'"/>'."\n";
654  $str .= '</p>';
655  }
656  return $str;
657  }
658 
668  function newEntry($action, array $target, array $all)
669  {
670  $type = strtoupper(preg_replace('/^new_/', '', $action));
671 
672  $this->displayApplyBtn = FALSE;
673  $this->dn = 'new';
674  $this->is_single_edit = FALSE;
675 
676  set_object_info($this->dn);
677 
678  // Open object
679  $this->openTabObject(objects::open($this->dn, $type), $this->headpage->getBase());
680  @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dn, "Create new entry initiated!");
681  }
682 
683  function newEntryTemplate($action, array $target, array $all)
684  {
685  if (static::$skipTemplates) {
686  return;
687  }
688  $action = preg_replace('/^new_template_/', 'new_', $action);
689  $this->newEntry($action, $target, $all);
690  $this->tabObject->setTemplateMode('template_cn');
691  }
692 
693  function newEntryFromTemplate($action, array $target, array $all)
694  {
695  if (static::$skipTemplates) {
696  return;
697  }
698  if (isset ($target[0])) {
699  $dn = $target[0];
700  } else {
701  $dn = NULL;
702  }
703  if ($action == 'template_apply') {
704  if ($dn === NULL) {
705  return;
706  }
707  $type = $this->getType($dn);
708  $type = preg_replace('/^template_/', '', $type);
709  } else {
710  $type = preg_replace('/^template_apply_/', '', $action);
711  }
712  $this->dialogObject = new templateDialog($this, $type, $dn);
713  }
714 
715  function applyTemplateToEntry($action, array $target, array $all)
716  {
717  global $ui;
718  if (static::$skipTemplates) {
719  return;
720  }
721  if (empty($target)) {
722  return;
723  }
724  $type = preg_replace('/^template_apply_to_/', '', $action);
725  $this->dns = $target;
726 
727  // check locks
728  if ($locks = get_locks($this->dns)) {
729  return gen_locked_message($locks, $this->dns);
730  }
731 
732  // Add locks
733  add_lock ($this->dns, $ui->dn);
734 
735  $this->dn = array_shift($this->dns);
736  $this->dialogObject = new templateDialog($this, $type, NULL, $this->dn);
737  }
738 
739  function handleTemplateApply ($cancel = FALSE)
740  {
741  if (static::$skipTemplates) {
742  return;
743  }
744  if ($cancel) {
745  $msgs = array();
746  } else {
747  $msgs = $this->tabObject->save();
748  }
749  if (count($msgs)) {
750  msg_dialog::displayChecks($msgs);
751  return;
752  } else {
753  if (!$cancel) {
754  @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dn, 'Template applied!');
755  }
756  del_lock($this->dn);
757  if (empty($this->dns)) {
758  $this->closeDialogs();
759  } else {
760  $this->last_tabObject = $this->tabObject;
761  $this->tabObject = NULL;
762  $this->dn = array_shift($this->dns);
763  $this->dialogObject->setNextTarget($this->dn);
764  $this->dialogObject->save_object();
765  }
766  }
767  }
768 
774  protected function saveChanges()
775  {
776  if (($this->tabObject instanceOf simpleTabs) && ($this->dialogObject instanceOf templateDialog)) {
777  $this->tabObject->save_object();
778  $this->handleTemplateApply();
779  return;
780  }
781  if ($this->tabObject instanceOf simpleTabs) {
782  $this->tabObject->save_object();
783  $msgs = $this->tabObject->save();
784  if (count($msgs)) {
785  msg_dialog::displayChecks($msgs);
786  return;
787  } else {
788  @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dns, 'Entry saved!');
789  $this->remove_lock();
790  $this->closeDialogs();
791  }
792  } elseif ($this->dialogObject instanceOf simplePlugin) {
793  $this->dialogObject->save_object();
794  $msgs = $this->dialogObject->check();
795  if (count($msgs)) {
796  msg_dialog::displayChecks($msgs);
797  return;
798  } else {
799  $this->dialogObject->save();
800  @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dns, 'Entry saved!');
801  $this->remove_lock();
802  $this->closeDialogs();
803  }
804  }
805  }
806 
810  protected function applyChanges()
811  {
812  if ($this->tabObject instanceOf simpleTabs) {
813  $this->tabObject->save_object();
814  $msgs = $this->tabObject->save();
815  if (count($msgs)) {
816  msg_dialog::displayChecks($msgs);
817  } else {
818  @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dns, 'Modifications applied!');
819  $this->tabObject->re_init();
820  }
821  }
822  }
823 
828  protected function cancelEdit()
829  {
830  if (($this->tabObject instanceOf simpleTabs) && ($this->dialogObject instanceOf templateDialog)) {
831  $this->handleTemplateApply(TRUE);
832  return;
833  }
834  $this->remove_lock();
835  $this->closeDialogs();
836  }
837 
847  function editEntry($action, array $target, array $all)
848  {
849  global $ui;
850  // Do not create a new tabObject while there is already one opened,
851  // the user may have just pressed F5 to reload the page.
852  if (is_object($this->tabObject)) {
853  return;
854  }
855 
856  $this->displayApplyBtn = (count($target) == 1);
857 
858  // Single edit - we only got one object dn.
859  if (count($target) == 1) {
860  $type = $this->getType($target[0]);
861  if (preg_match('/^template_/', $type) && !static::$skipTemplates) {
862  $type = preg_replace('/^template_/', '', $type);
863  }
864 
865  $this->is_single_edit = TRUE;
866 
867  // Get the dn of the object and creates lock
868  $this->dn = array_pop($target);
869  set_object_info($this->dn);
870  if ($locks = get_locks($this->dn, TRUE)) {
871  return gen_locked_message($locks, $this->dn, TRUE);
872  }
873  add_lock ($this->dn, $ui->dn);
874 
875  // Open object
876  $this->openTabObject(objects::open($this->dn, $type), $this->dn);
877  @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dn, "Edit entry initiated!");
878  if (isset($all['subaction'])) {
879  if ($this->handleSubAction($all) == FALSE) {
880  trigger_error('Was not able to handle subaction: '.$all['subaction']);
881  }
882  }
883  }
884  }
885 
890  function detectPostActions()
891  {
892  if (!is_object($this->headpage)) {
893  trigger_error("No valid headpage given....!");
894  return array();
895  }
896  $action = $this->headpage->getAction();
897  if (isset($_POST['edit_cancel'])) {
898  $action['action'] = 'cancel';
899  } elseif (isset($_POST['edit_finish'])) {
900  $action['action'] = 'save';
901  } elseif (isset($_POST['edit_apply'])) {
902  $action['action'] = 'apply';
903  }
904  if (!$this->is_modal_dialog()) {
905  if (isset($_POST['delete_confirmed'])) {
906  $action['action'] = 'removeConfirmed';
907  }
908  if (isset($_POST['delete_cancel'])) {
909  $action['action'] = 'cancelDelete';
910  }
911  }
912 
913  return $action;
914  }
915 
919  function handleActions($action)
920  {
921  // Start action
922  if (isset($this->actions[$action['action']])) {
923  $func = $this->actions[$action['action']];
924  if (!isset($action['targets'])) {
925  $action['targets'] = array();
926  }
927  return $this->$func($action['action'], $action['targets'], $action);
928  }
929  }
930 
931  protected function handleSubAction($all)
932  {
933  if (preg_match('/^tab_/', $all['subaction'])) {
934  $tab = preg_replace('/^tab_/', '', $all['subaction']);
935  if (isset($this->tabObject->by_object[$tab])) {
936  $this->tabObject->current = $tab;
937  } else {
938  trigger_error('Unknown tab: '.$tab);
939  }
940  return TRUE;
941  }
942  return FALSE;
943  }
944 
945  function openTabObject($object, $base)
946  {
947  $this->tabObject = $object;
948  $this->tabObject->set_acl_base($base);
949  $this->tabObject->parent = &$this;
950  }
951 
956  public function closeDialogs()
957  {
958  $this->last_dn = $this->dn;
959  $this->dn = "";
960  $this->last_dns = $this->dns;
961  $this->dns = array();
962 
963  $this->last_tabObject = $this->tabObject;
964  $this->tabObject = NULL;
965  $this->last_dialogObject = $this->dialogObject;
966  $this->dialogObject = NULL;
967 
968  $this->skipFooter = FALSE;
969  set_object_info();
970  }
971 
978  function remove_lock()
979  {
980  if (!empty($this->dn) && $this->dn != "new") {
981  del_lock($this->dn);
982  }
983  if (count($this->dns)) {
984  del_lock($this->dns);
985  }
986  }
987 
988  function is_modal_dialog()
989  {
990  return (is_object($this->tabObject) || is_object($this->dialogObject));
991  }
992 
996  protected function removeEntryRequested($action, array $target, array $all)
997  {
998  global $ui;
999  $disallowed = array();
1000  $this->dns = array();
1001 
1002  @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $target, "Entry removal requested!");
1003 
1004  // Check permissons for each target
1005  foreach ($target as $dn) {
1006  $type = $this->getType($dn);
1007  if (preg_match('/^template_/', $type) && !static::$skipTemplates) {
1008  $type = preg_replace('/^template_/', '', $type);
1009  }
1010  try {
1011  $info = objects::infos($type);
1012  $acl = $ui->get_permissions($dn, $info['aclCategory'].'/'.$info['mainTab']);
1013  if (preg_match('/d/', $acl)) {
1014  $this->dns[] = $dn;
1015  } else {
1016  $disallowed[] = $dn;
1017  }
1018  } catch (NonExistingObjectTypeException $e) {
1019  trigger_error("Unknown object type received :".$e->getMessage());
1020  }
1021  }
1022  if (count($disallowed)) {
1023  msg_dialog::display(_('Permission'), msgPool::permDelete($disallowed), INFO_DIALOG);
1024  }
1025 
1026  // We've at least one entry to delete.
1027  if (count($this->dns)) {
1028 
1029  // check locks
1030  if ($locks = get_locks($this->dns)) {
1031  return gen_locked_message($locks, $this->dns);
1032  }
1033 
1034  // Add locks
1035  $objects = array();
1036  foreach ($this->dns as $dn) {
1037  $type = $this->getType($dn);
1038  if (preg_match('/^template_/', $type) && !static::$skipTemplates) {
1039  $type = preg_replace('/^template_/', '', $type);
1040  $info = objects::infos($type);
1041  $info['mainAttr'] = 'cn';
1042  } else {
1043  $info = objects::infos($type);
1044  }
1045  $entry = $this->getHeadpage()->getEntry($dn);
1046  $objects[] = array(
1047  'name' => $entry[$info['mainAttr']][0],
1048  'dn' => $dn,
1049  'icon' => $info['icon'],
1050  'type' => $info['name']
1051  );
1052  }
1053  add_lock ($this->dns, $ui->dn);
1054 
1055  // Display confirmation dialog.
1056  $smarty = get_smarty();
1057  $smarty->assign('objects', $objects);
1058  $smarty->assign('multiple', TRUE);
1059  return $smarty->fetch(get_template_path('simple-remove.tpl'));
1060  }
1061  }
1062 
1063  function removeEntryConfirmed($action, array $target, array $all)
1064  {
1065  global $ui;
1066  @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $target, "Entry removal confirmed!");
1067 
1068  foreach ($this->dns as $dn) {
1069  $type = $this->getType($dn);
1070  if (empty($type)) {
1071  continue;
1072  }
1073  if (preg_match('/^template_/', $type) && !static::$skipTemplates) {
1074  $type = preg_replace('/^template_/', '', $type);
1075  }
1076  $infos = objects::infos($type);
1077  // Check permissions, are we allowed to remove this object?
1078  $acl = $ui->get_permissions($dn, $infos['aclCategory']."/".$infos['mainTab']);
1079  if (preg_match("/d/", $acl)) {
1080  // Delete the object
1081  $this->dn = $dn;
1082  $this->openTabObject(objects::open($this->dn, $type), $this->dn);
1083  $this->tabObject->delete();
1084 
1085  // Remove the lock for the current object.
1086  del_lock($this->dn);
1087  } else {
1088  msg_dialog::display(_('Permission error'), msgPool::permDelete(), ERROR_DIALOG);
1089  logging::log('security', 'simpleManagement/'.get_class($this), $dn, array(), 'Tried to trick deletion.');
1090  }
1091  }
1092 
1093  // Cleanup
1094  $this->remove_lock();
1095  $this->closeDialogs();
1096  }
1097 
1107  function createSnapshotDialog($action, array $target)
1108  {
1109  global $config, $ui;
1110  @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $target, 'Snaptshot creation initiated!');
1111 
1112  if (count($target) == 1) {
1113  $this->dn = array_pop($target);
1114  if (empty($this->dn)) {
1115  return;
1116  }
1117  $aclCategory = $config->data['OBJECTS'][$this->getType($this->dn)]['aclCategory'];
1118  if ($ui->allow_snapshot_create($this->dn, $aclCategory)) {
1119  $this->dialogObject = new SnapshotCreateDialog($this->dn, $this, $aclCategory);
1120  $this->dialogObject->set_acl_base($this->dn);
1121  } else {
1122  msg_dialog::display(_('Permission'), sprintf(_('You are not allowed to create a snapshot for %s.'), $this->dn),
1123  ERROR_DIALOG);
1124  }
1125  }
1126  }
1127 
1138  function restoreSnapshotDialog($action, array $target)
1139  {
1140  global $config, $ui;
1141  // Set current restore base for snapshot handling.
1142  if (is_object($this->snapHandler)) {
1143  $bases = array();
1144  foreach ($this->storagePoints as $sp) {
1145  $bases[] = $sp.$this->headpage->getBase();
1146  }
1147  }
1148 
1149  // No bases specified? Try base
1150  if (!count($bases)) {
1151  $bases[] = $this->headpage->getBase();
1152  }
1153 
1154  if (!count($target)) {
1155  // No target, open the restore removed object dialog.
1156  $this->dn = $this->headpage->getBase();
1157  $aclCategory = $this->headpage->categories;
1158  } else {
1159  // Display the restore points for a given object.
1160  $this->dn = $target[0];
1161  if (empty($this->dn)) {
1162  return;
1163  }
1164  $aclCategory = $config->data['OBJECTS'][$this->getType($this->dn)]['aclCategory'];
1165  }
1166 
1167  if ($ui->allow_snapshot_restore($this->dn, $aclCategory)) {
1168  @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dn, 'Snaptshot restoring initiated!');
1169  $this->snapHandler->setSnapshotBases($bases);
1170  $this->dialogObject = new SnapshotRestoreDialog($this->dn, $this, !count($target), $aclCategory);
1171  $this->dialogObject->set_acl_base($this->dn);
1172  } else {
1173  msg_dialog::display(_('Permission'), sprintf(_('You are not allowed to restore a snapshot for %s.'), $this->dn),
1174  ERROR_DIALOG);
1175  }
1176  }
1177 
1184  function copyPasteHandler($action = '', array $target = array(), array $all = array())
1185  {
1186  global $ui;
1187  // Return without any actions while copy&paste handler is disabled.
1188  if (!is_object($this->cpHandler)) {
1189  return FALSE;
1190  }
1191 
1192  // Save user input
1193  $this->cpHandler->save_object();
1194 
1195  // Add entries to queue
1196  if (($action == 'copy') || ($action == 'cut')) {
1197  $this->cpHandler->cleanup_queue();
1198  foreach ($target as $dn) {
1199  $type = $this->getType($dn);
1200  if (preg_match('/^template_/', $type) && !static::$skipTemplates) {
1201  $type = preg_replace('/^template_/', '', $type);
1202  }
1203  $infos = objects::infos($type);
1204 
1205  if (($action == 'copy') && $ui->is_copyable($dn, $infos['aclCategory'])) {
1206  $this->cpHandler->add_to_queue($dn, 'copy', $type);
1207  @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Entry copied!');
1208  }
1209  if (($action == 'cut') && $ui->is_cutable($dn, $infos['aclCategory'], $infos['mainTab'])) {
1210  $this->cpHandler->add_to_queue($dn, 'cut', $type);
1211  @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Entry cut!');
1212  }
1213  }
1214  }
1215 
1216  // Initiate pasting
1217  if ($action == "paste") {
1218  $this->cpPastingStarted = TRUE;
1219  }
1220 
1221  // Display any c&p dialogs, eg. object modifications required before pasting.
1222  if ($this->cpPastingStarted && $this->cpHandler->entries_queued()) {
1223  $data = $this->cpHandler->execute($this->headpage->getBase());
1224  if (!empty($data)) {
1225  return $data;
1226  }
1227  }
1228 
1229  // Automatically disable pasting process since there is no entry left to paste.
1230  if (!$this->cpHandler->entries_queued()) {
1231  $this->cpPastingStarted = FALSE;
1232  $this->cpHandler->resetPaste();
1233  }
1234  return "";
1235  }
1236 
1237  /* Methods related to Snapshots */
1238 
1242  function createSnapshot($dn, $description)
1243  {
1244  global $ui;
1245  if ($this->dn !== $dn) {
1246  trigger_error('There was a problem with the snapshot workflow');
1247  return;
1248  }
1249  if (!empty($dn) && $ui->allow_snapshot_create($dn, $this->dialogObject->aclCategory)) {
1250  $this->snapHandler->createSnapshot($dn, $description);
1251  @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snaptshot created!');
1252  } else {
1253  msg_dialog::display(_('Permission'), sprintf(_('You are not allowed to restore a snapshot for %s.'), $dn),
1254  ERROR_DIALOG);
1255  }
1256  }
1257 
1263  function restoreSnapshot($dn)
1264  {
1265  global $ui;
1266  if (!empty($dn) && $ui->allow_snapshot_restore($dn, $this->dialogObject->aclCategory)) {
1267  $this->snapHandler->restoreSnapshot($dn);
1268  @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snaptshot restored');
1269  $this->closeDialogs();
1270  } else {
1271  msg_dialog::display(_('Permission'), sprintf(_('You are not allowed to restore a snapshot for %s.'), $dn),
1272  ERROR_DIALOG);
1273  }
1274  }
1275 
1282  {
1283  $tmp = array();
1284  $snapshotBases = $this->snapHandler->getSnapshotBases();
1285  if (is_array($snapshotBases)) {
1286  foreach ($snapshotBases as $base) {
1287  $tmp = array_merge($tmp, $this->snapHandler->getAllDeletedSnapshots($base));
1288  }
1289  } else {
1290  $tmp = $this->snapHandler->getAllDeletedSnapshots($snapshotBases);
1291  }
1292  return $tmp;
1293  }
1294 
1295  /*
1296  * \brief Return available snapshots for the given base
1297  *
1298  * \param string $dn The DN
1299  */
1300  function getAvailableSnapsShots($dn)
1301  {
1302  return $this->snapHandler->getAvailableSnapsShots($dn);
1303  }
1304 
1310  function removeSnapshot($dn)
1311  {
1312  $this->snapHandler->removeSnapshot($dn);
1313  }
1314 
1315  static function mainInc ($classname)
1316  {
1317  global $remove_lock, $cleanup, $display;
1318 
1319  /* Remove locks */
1320  if ($remove_lock && session::is_set($classname)) {
1321  $macl = session::get($classname);
1322  $macl->remove_lock();
1323  }
1324 
1325  if ($cleanup) {
1326  /* Clean up */
1327  session::un_set($classname);
1328  } else {
1329  if (!session::is_set($classname) || (isset($_GET['reset']) && $_GET['reset'] == 1)) {
1330  /* Create the object if missing or reset requested */
1331  $managementObject = new $classname();
1332  } else {
1333  /* Retrieve the object from session */
1334  $managementObject = session::get($classname);
1335  }
1336  /* Execute and display */
1337  $display = $managementObject->execute();
1338 
1339  /* Store the object in the session */
1340  session::set($classname, $managementObject);
1341  }
1342  }
1343 }
1344 ?>
This class is made for easy plugin creation for editing LDAP attributes.
saveChanges()
Save object modifications and closes dialogs (returns to object listing).
Class for applying a template.
createSnapshot($dn, $description)
Creates a new snapshot entry.
getHeader()
Generates the plugin header which is displayed whenever a tab object is opened.
This class contains all function to manage tabs classes.
del_lock($object)
Remove a lock for object(s)
Definition: functions.inc:670
This class contains all the function needed to manage filter.
get_template_path($filename= '', $plugin=FALSE, $path= '')
Return themed path for specified base file.
Definition: functions.inc:296
This class contains all function to copy and paste.
_getTabFooter()
Generates the footer which is used whenever a tab object is displayed.
update()
Update.
copyPasteHandler($action= '', array $target=array(), array $all=array())
This method is used to queue and process copy&paste actions. Allows to copy, cut and paste mutliple e...
isValid()
Check if a filter is valid.
static set($name, $value)
Set a value in a session.
setFilter($filter)
Set a new filter.
This class allows to parse and execute on a array an LDAP filter Example: $filter = ldapFilter::parse...
static & get($name)
Accessor of a session.
detectPostActions()
Detects actions/events send by the ui and the corresponding targets.
& get_smarty()
Get global smarty object.
Definition: functions.inc:934
createSnapshotDialog($action, array $target)
Opens the snapshot creation dialog for the given target.
static global_set($name, $value)
Set a value in a session.
query()
Query.
applyChanges()
Save object modifications and keep dialogs opened.
gen_locked_message($locks, $dn, $allow_readonly=FALSE)
Generate a lock message.
Definition: functions.inc:1170
static log($action, $objecttype, $object, array $changes_array=array(), $result= '')
logging method
closeDialogs()
This method closes dialogs and cleans up the cached object info and the ui.
static un_set($name)
Unset a session.
get_locks($objects, $allow_readonly=FALSE)
Get locks for objects.
Definition: functions.inc:782
DEBUG($level, $line, $function, $file, $data, $info= '')
Debug level action.
Definition: functions.inc:200
static permDelete($name="")
Display that we have no permission to delete an object.
removeSnapshot($dn)
Delete a snapshot.
remove_lock()
Removes ldap object locks created by this class. Whenever an object is edited, we create locks to avo...
print_header($image, $headline, $info= '')
Print plugin HTML header.
Definition: functions.inc:1349
getAllDeletedSnapshots()
Get all deleted snapshots.
This class contains all the function needed to handle the snapshot functionality. ...
static global_get($name)
Accessor of a session var.
removeEntryRequested($action, array $target, array $all)
Queue selected objects to be removed. Checks ACLs, Locks and ask for confirmation.
registerAction($action, $target)
Every click in the list user interface sends an event here can we connect those events to a method...
restoreSnapshotDialog($action, array $target)
Displays the "Restore snapshot dialog" for a given target. If no target is specified, open the restore removed object dialog.
static display($s_title, $s_message, $i_type=INFO_DIALOG)
Display a message dialog.
restoreSnapshot($dn)
Restores a snapshot object.
static open($dn, $type)
Create the tab object for the given dn.
static global_is_set($name)
Check if a session is defined.
static is_set($name)
Check if the name of the session is set.
cancelEdit()
Editing an object was caneled. Close dialogs/tabs and remove locks.
newEntry($action, array $target, array $all)
This method intiates the object creation.
handleActions($action)
Calls the registered method for a given action/event.
add_lock($object, $user)
Add a lock for object(s)
Definition: functions.inc:600
execute()
Execute this plugin Handle actions/events, locking, snapshots, dialogs, tabs,...
static xml2array($contents, $get_attributes=1, $priority= 'tag')
Transform a xml document to an array.
Definition: class_xml.inc:41
editEntry($action, array $target, array $all)
This method opens an existing object or a list of existing objects to be edited.