1 <?php
2 /*
3 This code is part of GOsa (https://gosa.gonicus.de)
4 Copyright (C) 2003 Cajus Pollmeier
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
21 /*! \brief The plugin base class
22 \author Cajus Pollmeier <pollmeier@gonicus.de>
23 \version 2.00
24 \date 24.07.2003
26 This is the base class for all plugins. It can be used standalone or
27 can be included by the tabs class. All management should be done
28 within this class. Extend your plugins from this class.
29 */
31 class plugin
32 {
33 /*!
34 \brief Reference to parent object
36 This variable is used when the plugin is included in tabs
37 and keeps reference to the tab class. Communication to other
38 tabs is possible by 'name'. So the 'fax' plugin can ask the
39 'userinfo' plugin for the fax number.
41 \sa tab
42 */
43 var $parent= NULL;
45 /*!
46 \brief Configuration container
48 Access to global configuration
49 */
50 var $config= NULL;
52 /*!
53 \brief Mark plugin as account
55 Defines whether this plugin is defined as an account or not.
56 This has consequences for the plugin to be saved from tab
57 mode. If it is set to 'FALSE' the tab will call the delete
58 function, else the save function. Should be set to 'TRUE' if
59 the construtor detects a valid LDAP object.
61 \sa plugin::plugin()
62 */
63 var $is_account= FALSE;
64 var $initially_was_account= FALSE;
66 /*!
67 \brief Mark plugin as template
69 Defines whether we are creating a template or a normal object.
70 Has conseqences on the way execute() shows the formular and how
71 save() puts the data to LDAP.
73 \sa plugin::save() plugin::execute()
74 */
75 var $is_template= FALSE;
76 var $ignore_account= FALSE;
77 var $is_modified= FALSE;
79 /*!
80 \brief Represent temporary LDAP data
82 This is only used internally.
83 */
84 var $attrs= array();
86 /* Keep set of conflicting plugins */
87 var $conflicts= array();
89 /* Save unit tags */
90 var $gosaUnitTag= "";
92 /*!
93 \brief Used standard values
95 dn
96 */
97 var $dn= "";
98 var $uid= "";
99 var $sn= "";
100 var $givenName= "";
101 var $acl= "*none*";
102 var $dialog= FALSE;
103 var $snapDialog = NULL;
105 /* attribute list for save action */
106 var $attributes= array();
107 var $objectclasses= array();
108 var $is_new= TRUE;
109 var $saved_attributes= array();
111 var $acl_base= "";
112 var $acl_category= "";
114 /* Plugin identifier */
115 var $plHeadline= "";
116 var $plDescription= "";
118 /* This can be set to render the tabulators in another stylesheet */
119 var $pl_notify= FALSE;
121 /* The entries CSN value, if available */
122 var $entryCSN = "";
124 /* This variable indicates that this class can handle multiple dns at once. */
125 var $multiple_support = FALSE;
127 /* This aviable indicates, that we are currently in multiple edit handle */
128 var $multiple_support_active = FALSE;
129 var $selected_edit_values = array();
131 /*! \brief plugin constructor
133 If 'dn' is set, the node loads the given 'dn' from LDAP
135 \param dn Distinguished name to initialize plugin from
136 \sa plugin()
137 */
138 function plugin (&$config, $dn= NULL, $parent= NULL)
139 {
140 /* Configuration is fine, allways */
141 $this->config= &$config;
142 $this->dn= $dn;
144 /* Handle new accounts, don't read information from LDAP */
145 if ($dn == "new"){
146 return;
147 }
149 /* Save current dn as acl_base */
150 $this->acl_base= $dn;
152 /* Get LDAP descriptor */
153 $ldap= $this->config->get_ldap_link();
154 if ($dn !== NULL){
156 /* Try to get entry CSN for save checks later */
157 $ldap->cat($dn,array("entryCSN"));
158 $csn = $ldap->fetch();
159 if(isset($csn['entryCSN'][0])){
160 $this->entryCSN = $csn['entryCSN'][0];
161 }
163 /* Load data to 'attrs' and save 'dn' */
164 if ($parent !== NULL){
165 $this->attrs= $parent->attrs;
166 } else {
167 $ldap->cat ($dn);
168 $this->attrs= $ldap->fetch();
169 }
171 /* Copy needed attributes */
172 foreach ($this->attributes as $val){
173 $found= array_key_ics($val, $this->attrs);
174 if ($found != ""){
175 $this->$val= $this->attrs["$found"][0];
176 }
177 }
179 /* gosaUnitTag loading... */
180 if (isset($this->attrs['gosaUnitTag'][0])){
181 $this->gosaUnitTag= $this->attrs['gosaUnitTag'][0];
182 }
184 /* Set the template flag according to the existence of objectClass
185 gosaUserTemplate */
186 if (isset($this->attrs['objectClass'])){
187 if (in_array ("gosaUserTemplate", $this->attrs['objectClass'])){
188 $this->is_template= TRUE;
189 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
190 "found", "Template check");
191 }
192 }
194 /* Is Account? */
195 $found= TRUE;
196 foreach ($this->objectclasses as $obj){
197 if (preg_match('/top/i', $obj)){
198 continue;
199 }
200 if (!isset($this->attrs['objectClass']) || !in_array_ics ($obj, $this->attrs['objectClass'])){
201 $found= FALSE;
202 break;
203 }
204 }
205 if ($found){
206 $this->is_account= TRUE;
207 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
208 "found", "Object check");
209 }
211 /* Prepare saved attributes */
212 $this->saved_attributes= $this->attrs;
213 foreach ($this->saved_attributes as $index => $value){
214 if (preg_match('/^[0-9]+$/', $index)){
215 unset($this->saved_attributes[$index]);
216 continue;
217 }
218 if (!in_array($index, $this->attributes) && $index != "objectClass"){
219 unset($this->saved_attributes[$index]);
220 continue;
221 }
222 if ($this->saved_attributes[$index]["count"] == 1){
223 $tmp= $this->saved_attributes[$index][0];
224 unset($this->saved_attributes[$index]);
225 $this->saved_attributes[$index]= $tmp;
226 continue;
227 }
229 unset($this->saved_attributes["$index"]["count"]);
230 }
231 }
233 /* Save initial account state */
234 $this->initially_was_account= $this->is_account;
235 }
237 /*! \brief execute plugin
239 Generates the html output for this node
240 */
241 function execute()
242 {
243 /* This one is empty currently. Fabian - please fill in the docu code */
244 $_SESSION['current_class_for_help'] = get_class($this);
246 /* Reset Lock message POST/GET check array, to prevent perg_match errors*/
247 $_SESSION['LOCK_VARS_TO_USE'] = $_SESSION['LOCK_VARS_USED'] =array();
248 }
250 /*! \brief execute plugin
251 Removes object from parent
252 */
253 function remove_from_parent()
254 {
255 /* include global link_info */
256 $ldap= $this->config->get_ldap_link();
258 /* Get current objectClasses in order to add the required ones */
259 $ldap->cat($this->dn);
260 $tmp= $ldap->fetch ();
261 $oc= array();
262 if (isset($tmp['objectClass'])){
263 $oc= $tmp['objectClass'];
264 unset($oc['count']);
265 }
267 /* Remove objectClasses from entry */
268 $ldap->cd($this->dn);
269 $this->attrs= array();
270 $this->attrs['objectClass']= array_remove_entries($this->objectclasses,$oc);
272 /* Unset attributes from entry */
273 foreach ($this->attributes as $val){
274 $this->attrs["$val"]= array();
275 }
277 /* Unset account info */
278 $this->is_account= FALSE;
280 /* Do not write in plugin base class, this must be done by
281 children, since there are normally additional attribs,
282 lists, etc. */
283 /*
284 $ldap->modify($this->attrs);
285 */
286 }
289 /* Save data to object */
290 function save_object()
291 {
292 if($this->multiple_support_active){
293 foreach($this->attributes as $attr){
294 if(isset($_POST["use_".$attr])){
295 $this->selected_edit_values[$attr] = TRUE;
296 }else{
297 $this->selected_edit_values[$attr] = FALSE;
298 }
299 }
300 }
302 /* Save values to object */
303 foreach ($this->attributes as $val){
304 if ($this->acl_is_writeable($val) && isset ($_POST["$val"])){
305 /* Check for modifications */
306 if (get_magic_quotes_gpc()) {
307 $data= stripcslashes($_POST["$val"]);
308 } else {
309 $data= $this->$val = $_POST["$val"];
310 }
311 if ($this->$val != $data){
312 $this->is_modified= TRUE;
313 }
315 /* Okay, how can I explain this fix ...
316 * In firefox, disabled option fields aren't selectable ... but in IE you can select these fileds.
317 * So IE posts these 'unselectable' option, with value = chr(194)
318 * chr(194) seems to be the in between the ...option> </option.. because there is no value=".." specified in these option fields
319 * This was added for W3c compliance, but now causes these ... ldap errors ...
320 * So we set these Fields to ""; a normal empty string, and we can check these values in plugin::check() again ...
321 */
322 if(isset($data[0]) && $data[0] == chr(194)) {
323 $data = "";
324 }
325 $this->$val= $data;
326 //echo "<font color='blue'>".$val."</font><br>";
327 }else{
328 //echo "<font color='red'>".$val."</font><br>";
329 }
330 }
331 }
334 /* Save data to LDAP, depending on is_account we save or delete */
335 function save()
336 {
337 /* include global link_info */
338 $ldap= $this->config->get_ldap_link();
340 /* Start with empty array */
341 $this->attrs= array();
343 /* Get current objectClasses in order to add the required ones */
344 $ldap->cat($this->dn);
346 $tmp= $ldap->fetch ();
348 $oc= array();
349 if (isset($tmp['objectClass'])){
350 $oc= $tmp["objectClass"];
351 $this->is_new= FALSE;
352 unset($oc['count']);
353 } else {
354 $this->is_new= TRUE;
355 }
357 /* Load (minimum) attributes, add missing ones */
358 $this->attrs['objectClass']= gosa_array_merge($oc,$this->objectclasses);
360 /* Copy standard attributes */
361 foreach ($this->attributes as $val){
362 if ($this->$val != ""){
363 $this->attrs["$val"]= $this->$val;
364 } elseif (!$this->is_new) {
365 $this->attrs["$val"]= array();
366 }
367 }
369 }
372 function cleanup()
373 {
374 foreach ($this->attrs as $index => $value){
376 /* Convert arrays with one element to non arrays, if the saved
377 attributes are no array, too */
378 if (is_array($this->attrs[$index]) &&
379 count ($this->attrs[$index]) == 1 &&
380 isset($this->saved_attributes[$index]) &&
381 !is_array($this->saved_attributes[$index])){
383 $tmp= $this->attrs[$index][0];
384 $this->attrs[$index]= $tmp;
385 }
387 /* Remove emtpy arrays if they do not differ */
388 if (is_array($this->attrs[$index]) &&
389 count($this->attrs[$index]) == 0 &&
390 !isset($this->saved_attributes[$index])){
392 unset ($this->attrs[$index]);
393 continue;
394 }
396 /* Remove single attributes that do not differ */
397 if (!is_array($this->attrs[$index]) &&
398 isset($this->saved_attributes[$index]) &&
399 !is_array($this->saved_attributes[$index]) &&
400 $this->attrs[$index] == $this->saved_attributes[$index]){
402 unset ($this->attrs[$index]);
403 continue;
404 }
406 /* Remove arrays that do not differ */
407 if (is_array($this->attrs[$index]) &&
408 isset($this->saved_attributes[$index]) &&
409 is_array($this->saved_attributes[$index])){
411 if (!array_differs($this->attrs[$index],$this->saved_attributes[$index])){
412 unset ($this->attrs[$index]);
413 continue;
414 }
415 }
416 }
418 /* Update saved attributes and ensure that next cleanups will be successful too */
419 foreach($this->attrs as $name => $value){
420 $this->saved_attributes[$name] = $value;
421 }
422 }
424 /* Check formular input */
425 function check()
426 {
427 $message= array();
429 /* Skip if we've no config object */
430 if (!isset($this->config) || !is_object($this->config)){
431 return $message;
432 }
434 /* Find hooks entries for this class */
435 $command= $this->config->search(get_class($this), "CHECK", array('menu', 'tabs'));
437 if ($command != ""){
439 if (!check_command($command)){
440 $message[]= sprintf(_("Command '%s', specified as CHECK hook for plugin '%s' doesn't seem to exist."), $command,
441 get_class($this));
442 } else {
444 /* Generate "ldif" for check hook */
445 $ldif= "dn: $this->dn\n";
447 /* ... objectClasses */
448 foreach ($this->objectclasses as $oc){
449 $ldif.= "objectClass: $oc\n";
450 }
452 /* ... attributes */
453 foreach ($this->attributes as $attr){
454 if ($this->$attr == ""){
455 continue;
456 }
457 if (is_array($this->$attr)){
458 foreach ($this->$attr as $val){
459 $ldif.= "$attr: $val\n";
460 }
461 } else {
462 $ldif.= "$attr: ".$this->$attr."\n";
463 }
464 }
466 /* Append empty line */
467 $ldif.= "\n";
469 /* Feed "ldif" into hook and retrieve result*/
470 $descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w"));
471 $fh= proc_open($command, $descriptorspec, $pipes);
472 if (is_resource($fh)) {
473 fwrite ($pipes[0], $ldif);
474 fclose($pipes[0]);
476 $result= stream_get_contents($pipes[1]);
477 if ($result != ""){
478 $message[]= $result;
479 }
481 fclose($pipes[1]);
482 fclose($pipes[2]);
483 proc_close($fh);
484 }
485 }
487 }
489 /* Check if entry CSN has changed */
490 $ldap = $this->config->get_ldap_link();
491 $ldap->cat($this->dn,array("entryCSN"));
492 $csn = $ldap->fetch();
493 if(isset($csn['entryCSN'][0]) && !empty($this->entryCSN) && $this->entryCSN != $csn['entryCSN'][0]){
494 $this->entryCSN = $csn['entryCSN'][0];
495 $message[] = _("The object has changed since opened in GOsa. Please ensure that nobody has done serious changes that may get lost if you save this entry.");
496 }
498 return ($message);
499 }
501 /* Adapt from template, using 'dn' */
502 function adapt_from_template($dn)
503 {
504 /* Include global link_info */
505 $ldap= $this->config->get_ldap_link();
507 /* Load requested 'dn' to 'attrs' */
508 $ldap->cat ($dn);
509 $this->attrs= $ldap->fetch();
511 /* Walk through attributes */
512 foreach ($this->attributes as $val){
514 if (isset($this->attrs["$val"][0])){
516 /* If attribute is set, replace dynamic parts:
517 %sn, %givenName and %uid. Fill these in our local variables. */
518 $value= $this->attrs["$val"][0];
520 foreach (array("sn", "givenName", "uid") as $repl){
521 if (preg_match("/%$repl/i", $value)){
522 $value= preg_replace ("/%$repl/i", $this->parent->$repl, $value);
523 }
524 }
525 $this->$val= $value;
526 }
527 }
529 /* Is Account? */
530 $found= TRUE;
531 foreach ($this->objectclasses as $obj){
532 if (preg_match('/top/i', $obj)){
533 continue;
534 }
535 if (!in_array_ics ($obj, $this->attrs['objectClass'])){
536 $found= FALSE;
537 break;
538 }
539 }
540 if ($found){
541 $this->is_account= TRUE;
542 }
543 }
545 /* Indicate whether a password change is needed or not */
546 function password_change_needed()
547 {
548 return FALSE;
549 }
552 /* Show header message for tab dialogs */
553 function show_enable_header($button_text, $text, $disabled= FALSE)
554 {
555 if (($disabled == TRUE) || (!$this->acl_is_createable())){
556 $state= "disabled";
557 } else {
558 $state= "";
559 }
560 $display= "<table summary=\"\" width=\"100%\"><tr>\n<td colspan=2><p><b>$text</b></p>\n";
561 $display.= "<input type=submit value=\"$button_text\" name=\"modify_state\" ".$state.
562 "><p class=\"seperator\"> </p></td></tr></table>";
564 return($display);
565 }
568 /* Show header message for tab dialogs */
569 function show_disable_header($button_text, $text, $disabled= FALSE)
570 {
571 if (($disabled == TRUE) || !$this->acl_is_removeable()){
572 $state= "disabled";
573 } else {
574 $state= "";
575 }
576 $display= "<table summary=\"\" width=\"100%\"><tr>\n<td colspan=2><p><b>$text</b></p>\n";
577 $display.= "<input type=submit value=\"$button_text\" name=\"modify_state\" ".$state.
578 "><p class=\"seperator\"> </p></td></tr></table>";
580 return($display);
581 }
584 /* Show header message for tab dialogs */
585 function show_header($button_text, $text, $disabled= FALSE)
586 {
587 echo "FIXME: show_header should be replaced by show_disable_header and show_enable_header<br>";
588 if ($disabled == TRUE){
589 $state= "disabled";
590 } else {
591 $state= "";
592 }
593 $display= "<table summary=\"\" width=\"100%\"><tr>\n<td colspan=2><p><b>$text</b></p>\n";
594 $display.= "<input type=submit value=\"$button_text\" name=\"modify_state\" ".
595 ($this->acl_is_createable()?'':'disabled')." ".$state.
596 "><p class=\"seperator\"> </p></td></tr></table>";
598 return($display);
599 }
602 function postcreate($add_attrs= array())
603 {
604 /* Find postcreate entries for this class */
605 $command= $this->config->search(get_class($this), "POSTCREATE",array('menu', 'tabs'));
607 if ($command != ""){
609 /* Additional attributes */
610 foreach ($add_attrs as $name => $value){
611 $command= preg_replace("/%$name/", $value, $command);
612 }
614 /* Walk through attribute list */
615 foreach ($this->attributes as $attr){
616 if (!is_array($this->$attr)){
617 $command= preg_replace("/%$attr/", $this->$attr, $command);
618 }
619 }
620 $command= preg_replace("/%dn/", $this->dn, $command);
622 if (check_command($command)){
623 @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
624 $command, "Execute");
626 exec($command);
627 } else {
628 $message= sprintf(_("Command '%s', specified as POSTCREATE for plugin '%s' doesn't seem to exist."), $command, get_class($this));
629 print_red ($message);
630 }
631 }
632 }
634 function postmodify($add_attrs= array())
635 {
636 /* Find postcreate entries for this class */
637 $command= $this->config->search(get_class($this), "POSTMODIFY",array('menu','tabs'));
639 if ($command != ""){
641 /* Additional attributes */
642 foreach ($add_attrs as $name => $value){
643 $command= preg_replace("/%$name/", $value, $command);
644 }
646 /* Walk through attribute list */
647 foreach ($this->attributes as $attr){
648 if (!is_array($this->$attr)){
649 $command= preg_replace("/%$attr/", $this->$attr, $command);
650 }
651 }
652 $command= preg_replace("/%dn/", $this->dn, $command);
654 if (check_command($command)){
655 @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
656 $command, "Execute");
658 exec($command);
659 } else {
660 $message= sprintf(_("Command '%s', specified as POSTMODIFY for plugin '%s' doesn't seem to exist."), $command, get_class($this));
661 print_red ($message);
662 }
663 }
664 }
666 function postremove($add_attrs= array())
667 {
668 /* Find postremove entries for this class */
669 $command= $this->config->search(get_class($this), "POSTREMOVE",array('menu','tabs'));
670 if ($command != ""){
672 /* Additional attributes */
673 foreach ($add_attrs as $name => $value){
674 $command= preg_replace("/%$name/", $value, $command);
675 }
677 /* Walk through attribute list */
678 foreach ($this->attributes as $attr){
679 if (!is_array($this->$attr)){
680 $command= preg_replace("/%$attr/", $this->$attr, $command);
681 }
682 }
683 $command= preg_replace("/%dn/", $this->dn, $command);
685 /* Additional attributes */
686 foreach ($add_attrs as $name => $value){
687 $command= preg_replace("/%$name/", $value, $command);
688 }
690 if (check_command($command)){
691 @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
692 $command, "Execute");
694 exec($command);
695 } else {
696 $message= sprintf(_("Command '%s', specified as POSTREMOVE for plugin '%s' doesn't seem to exist."), $command, get_class($this));
697 print_red ($message);
698 }
699 }
700 }
702 /* Create unique DN */
703 function create_unique_dn($attribute, $base)
704 {
705 $ldap= $this->config->get_ldap_link();
706 $base= preg_replace("/^,*/", "", $base);
708 /* Try to use plain entry first */
709 $dn= "$attribute=".$this->$attribute.",$base";
710 $ldap->cat ($dn, array('dn'));
711 if (!$ldap->fetch()){
712 return ($dn);
713 }
715 /* Look for additional attributes */
716 foreach ($this->attributes as $attr){
717 if ($attr == $attribute || $this->$attr == ""){
718 continue;
719 }
721 $dn= "$attribute=".$this->$attribute."+$attr=".$this->$attr.",$base";
722 $ldap->cat ($dn, array('dn'));
723 if (!$ldap->fetch()){
724 return ($dn);
725 }
726 }
728 /* None found */
729 return ("none");
730 }
732 function rebind($ldap, $referral)
733 {
734 $credentials= LDAP::get_credentials($referral, $this->config->current['REFERRAL']);
735 if (ldap_bind($ldap, $credentials['ADMIN'], $credentials['PASSWORD'])) {
736 $this->error = "Success";
737 $this->hascon=true;
738 $this->reconnect= true;
739 return (0);
740 } else {
741 $this->error = "Could not bind to " . $credentials['ADMIN'];
742 return NULL;
743 }
744 }
746 /* This is a workaround function. */
747 function copy($src_dn, $dst_dn)
748 {
749 /* Rename dn in possible object groups */
750 $ldap= $this->config->get_ldap_link();
751 $ldap->search('(&(objectClass=gosaGroupOfNames)(member='.@LDAP::fix($src_dn).'))',
752 array('cn'));
753 while ($attrs= $ldap->fetch()){
754 $og= new ogroup($this->config, $ldap->getDN());
755 unset($og->member[$src_dn]);
756 $og->member[$dst_dn]= $dst_dn;
757 $og->save ();
758 }
760 $ldap->cat($dst_dn);
761 $attrs= $ldap->fetch();
762 if (count($attrs)){
763 trigger_error("Trying to overwrite ".@LDAP::fix($dst_dn).", which already exists.",
764 E_USER_WARNING);
765 return (FALSE);
766 }
768 $ldap->cat($src_dn);
769 $attrs= $ldap->fetch();
770 if (!count($attrs)){
771 trigger_error("Trying to move ".@LDAP::fix($src_dn).", which does not seem to exist.",
772 E_USER_WARNING);
773 return (FALSE);
774 }
776 /* Grummble. This really sucks. PHP ldap doesn't support rdn stuff. */
777 $ds= ldap_connect($this->config->current['SERVER']);
778 ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
779 if (function_exists("ldap_set_rebind_proc") && isset($this->config->current['REFERRAL'])) {
780 ldap_set_rebind_proc($ds, array(&$this, "rebind"));
781 }
783 $r=ldap_bind($ds,$this->config->current['ADMIN'], $this->config->current['PASSWORD']);
784 $sr=ldap_read($ds, @LDAP::fix($src_dn), "objectClass=*");
786 /* Fill data from LDAP */
787 $new= array();
788 if ($sr) {
789 $ei=ldap_first_entry($ds, $sr);
790 if ($ei) {
791 foreach($attrs as $attr => $val){
792 if ($info = @ldap_get_values_len($ds, $ei, $attr)){
793 for ($i= 0; $i<$info['count']; $i++){
794 if ($info['count'] == 1){
795 $new[$attr]= $info[$i];
796 } else {
797 $new[$attr][]= $info[$i];
798 }
799 }
800 }
801 }
802 }
803 }
805 /* close conncetion */
806 ldap_unbind($ds);
808 /* Adapt naming attribute */
809 $dst_name= preg_replace("/^([^=]+)=.*$/", "\\1", $dst_dn);
810 $dst_val = preg_replace("/^[^=]+=([^,+]+).*,.*$/", "\\1", $dst_dn);
811 $new[$dst_name]= @LDAP::fix($dst_val);
813 /* Check if this is a department.
814 * If it is a dep. && there is a , override in his ou
815 * change \2C to , again, else this entry can't be saved ...
816 */
817 if((isset($new['ou'])) &&( preg_match("/\\,/",$new['ou']))){
818 $new['ou'] = preg_replace("/\\\\,/",",",$new['ou']);
819 }
821 /* Save copy */
822 $ldap->connect();
823 $ldap->cd($this->config->current['BASE']);
825 $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $dst_dn));
827 /* FAIvariable=.../..., cn=..
828 could not be saved, because the attribute FAIvariable was different to
829 the dn FAIvariable=..., cn=... */
830 if(in_array_ics("FAIdebconfInfo",$new['objectClass'])){
831 $new['FAIvariable'] = $ldap->fix($new['FAIvariable']);
832 }
833 $ldap->cd($dst_dn);
834 $ldap->add($new);
836 if ($ldap->error != "Success"){
837 trigger_error("Trying to save $dst_dn failed.",
838 E_USER_WARNING);
839 return(FALSE);
840 }
842 return (TRUE);
843 }
846 function move($src_dn, $dst_dn)
847 {
848 /* Copy source to destination */
849 if (!$this->copy($src_dn, $dst_dn)){
850 return (FALSE);
851 }
853 /* Delete source */
854 $ldap= $this->config->get_ldap_link();
855 $ldap->rmdir($src_dn);
856 if ($ldap->error != "Success"){
857 trigger_error("Trying to delete $src_dn failed.",
858 E_USER_WARNING);
859 return (FALSE);
860 }
862 return (TRUE);
863 }
866 /* Move/Rename complete trees */
867 function recursive_move($src_dn, $dst_dn)
868 {
869 /* Check if the destination entry exists */
870 $ldap= $this->config->get_ldap_link();
872 /* Check if destination exists - abort */
873 $ldap->cat($dst_dn, array('dn'));
874 if ($ldap->fetch()){
875 trigger_error("recursive_move $dst_dn already exists.",
876 E_USER_WARNING);
877 return (FALSE);
878 }
880 /* Perform a search for all objects to be moved */
881 $objects= array();
882 $ldap->cd($src_dn);
883 $ldap->search("(objectClass=*)", array("dn"));
884 while($attrs= $ldap->fetch()){
885 $dn= $attrs['dn'];
886 $objects[$dn]= strlen($dn);
887 }
889 /* Sort objects by indent level */
890 asort($objects);
891 reset($objects);
893 /* Copy objects from small to big indent levels by replacing src_dn by dst_dn */
894 foreach ($objects as $object => $len){
895 $src= $object;
896 $dst= preg_replace("/$src_dn$/", "$dst_dn", $object);
897 if (!$this->copy($src, $dst)){
898 return (FALSE);
899 }
900 }
902 /* Remove src_dn */
903 $ldap->cd($src_dn);
904 $ldap->recursive_remove();
905 return (TRUE);
906 }
909 function handle_post_events($mode, $add_attrs= array())
910 {
911 switch ($mode){
912 case "add":
913 $this->postcreate($add_attrs);
914 break;
916 case "modify":
917 $this->postmodify($add_attrs);
918 break;
920 case "remove":
921 $this->postremove($add_attrs);
922 break;
923 }
924 }
927 function saveCopyDialog(){
928 }
931 function getCopyDialog(){
932 return(array("string"=>"","status"=>""));
933 }
936 function PrepareForCopyPaste($source)
937 {
938 $todo = $this->attributes;
939 if(isset($this->CopyPasteVars)){
940 $todo = array_merge($todo,$this->CopyPasteVars);
941 }
943 if(count($this->objectclasses)){
944 $this->is_account = TRUE;
945 foreach($this->objectclasses as $class){
946 if(!in_array($class,$source['objectClass'])){
947 $this->is_account = FALSE;
948 }
949 }
950 }
952 foreach($todo as $var){
953 if (isset($source[$var])){
954 if(isset($source[$var]['count'])){
955 if($source[$var]['count'] > 1){
956 $this->$var = array();
957 $tmp = array();
958 for($i = 0 ; $i < $source[$var]['count']; $i++){
959 $tmp = $source[$var][$i];
960 }
961 $this->$var = $tmp;
962 # echo $var."=".$tmp."<br>";
963 }else{
964 $this->$var = $source[$var][0];
965 # echo $var."=".$source[$var][0]."<br>";
966 }
967 }else{
968 $this->$var= $source[$var];
969 # echo $var."=".$source[$var]."<br>";
970 }
971 }
972 }
973 }
976 function handle_object_tagging($dn= "", $tag= "", $show= false)
977 {
978 //FIXME: How to optimize this? We have at least two
979 // LDAP accesses per object. It would be a good
980 // idea to have it integrated.
982 /* No dn? Self-operation... */
983 if ($dn == ""){
984 $dn= $this->dn;
986 /* No tag? Find it yourself... */
987 if ($tag == ""){
988 $len= strlen($dn);
990 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "No tag for $dn - looking for one...", "Tagging");
991 $relevant= array();
992 foreach ($this->config->adepartments as $key => $ntag){
994 /* This one is bigger than our dn, its not relevant... */
995 if ($len <= strlen($key)){
996 continue;
997 }
999 /* This one matches with the latter part. Break and don't fix this entry */
1000 if (preg_match('/(^|,)'.normalizePreg($key).'$/', $dn)){
1001 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "DEBUG: Possibly relevant: $key", "Tagging");
1002 $relevant[strlen($key)]= $ntag;
1003 continue;
1004 }
1006 }
1008 /* If we've some relevant tags to set, just get the longest one */
1009 if (count($relevant)){
1010 ksort($relevant);
1011 $tmp= array_keys($relevant);
1012 $idx= end($tmp);
1013 $tag= $relevant[$idx];
1014 $this->gosaUnitTag= $tag;
1015 }
1016 }
1017 }
1020 /* Set tag? */
1021 if ($tag != ""){
1022 /* Set objectclass and attribute */
1023 $ldap= $this->config->get_ldap_link();
1024 $ldap->cat($dn, array('gosaUnitTag', 'objectClass'));
1025 $attrs= $ldap->fetch();
1026 if(isset($attrs['gosaUnitTag'][0]) && $attrs['gosaUnitTag'][0] == $tag){
1027 if ($show) {
1028 echo sprintf(_("Object '%s' is already tagged"), @LDAP::fix($dn))."<br>";
1029 flush();
1030 }
1031 return;
1032 }
1033 if (count($attrs)){
1034 if ($show){
1035 echo sprintf(_("Adding tag (%s) to object '%s'"), $tag, @LDAP::fix($dn))."<br>";
1036 flush();
1037 }
1038 $nattrs= array("gosaUnitTag" => $tag);
1039 $nattrs['objectClass']= array();
1040 for ($i= 0; $i<$attrs['objectClass']['count']; $i++){
1041 $oc= $attrs['objectClass'][$i];
1042 if ($oc != "gosaAdministrativeUnitTag"){
1043 $nattrs['objectClass'][]= $oc;
1044 }
1045 }
1046 $nattrs['objectClass'][]= "gosaAdministrativeUnitTag";
1047 $ldap->cd($dn);
1048 $ldap->modify($nattrs);
1049 show_ldap_error($ldap->get_error(), sprintf(_("Handle object tagging with dn '%s' failed."),$dn));
1050 } else {
1051 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "Not tagging ($tag) $dn - seems to have moved away", "Tagging");
1052 }
1054 } else {
1055 /* Remove objectclass and attribute */
1056 $ldap= $this->config->get_ldap_link();
1057 $ldap->cat($dn, array('gosaUnitTag', 'objectClass'));
1058 $attrs= $ldap->fetch();
1059 if (isset($attrs['objectClass']) && !in_array_ics("gosaAdministrativeUnitTag", $attrs['objectClass'])){
1060 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "$dn is not tagged", "Tagging");
1061 return;
1062 }
1063 if (count($attrs)){
1064 if ($show){
1065 echo sprintf(_("Removing tag from object '%s'"), @LDAP::fix($dn))."<br>";
1066 flush();
1067 }
1068 $nattrs= array("gosaUnitTag" => array());
1069 $nattrs['objectClass']= array();
1070 for ($i= 0; $i<$attrs['objectClass']['count']; $i++){
1071 $oc= $attrs['objectClass'][$i];
1072 if ($oc != "gosaAdministrativeUnitTag"){
1073 $nattrs['objectClass'][]= $oc;
1074 }
1075 }
1076 $ldap->cd($dn);
1077 $ldap->modify($nattrs);
1078 show_ldap_error($ldap->get_error(), sprintf(_("Handle object tagging with dn '%s' failed."),$dn));
1079 } else {
1080 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "Not removing tag ($tag) $dn - seems to have moved away", "Tagging");
1081 }
1082 }
1084 }
1087 /* Add possibility to stop remove process */
1088 function allow_remove()
1089 {
1090 $reason= "";
1091 return $reason;
1092 }
1095 /* Create a snapshot of the current object */
1096 function create_snapshot($type= "snapshot", $description= array())
1097 {
1099 /* Check if snapshot functionality is enabled */
1100 if(!$this->snapshotEnabled()){
1101 return;
1102 }
1104 /* Get configuration from gosa.conf */
1105 $tmp = $this->config->current;
1107 /* Create lokal ldap connection */
1108 $ldap= $this->config->get_ldap_link();
1109 $ldap->cd($this->config->current['BASE']);
1111 /* check if there are special server configurations for snapshots */
1112 if(!isset($tmp['SNAPSHOT_SERVER'])){
1114 /* Source and destination server are both the same, just copy source to dest obj */
1115 $ldap_to = $ldap;
1116 $snapldapbase = $this->config->current['BASE'];
1118 }else{
1119 $server = $tmp['SNAPSHOT_SERVER'];
1120 $user = $tmp['SNAPSHOT_USER'];
1121 $password = $tmp['SNAPSHOT_PASSWORD'];
1122 $snapldapbase = $tmp['SNAPSHOT_BASE'];
1124 $ldap_to = new LDAP($user,$password, $server);
1125 $ldap_to -> cd($snapldapbase);
1126 show_ldap_error($ldap->get_error(), sprintf(_("Saving object snapshot with dn '%s' failed."),$snapldapbase));
1127 }
1129 /* check if the dn exists */
1130 if ($ldap->dn_exists($this->dn)){
1132 /* Extract seconds & mysecs, they are used as entry index */
1133 list($usec, $sec)= explode(" ", microtime());
1135 /* Collect some infos */
1136 $base = $this->config->current['BASE'];
1137 $snap_base = $tmp['SNAPSHOT_BASE'];
1138 $base_of_object = preg_replace ('/^[^,]+,/i', '', $this->dn);
1139 $new_base = preg_replace("/".normalizePreg($base)."$/","",$base_of_object).$snap_base;
1141 /* Create object */
1142 #$data = preg_replace('/^dn:.*\n/', '', $ldap->gen_ldif($this->dn,"(!(objectClass=gosaDepartment))"));
1143 $data = $ldap->gen_ldif($this->dn,"(&(!(objectClass=gosaDepartment))(!(objectClass=FAIclass)))");
1144 $newName = preg_replace("/\./", "", $sec."-".$usec);
1145 $target= array();
1146 $target['objectClass'] = array("top", "gosaSnapshotObject");
1147 $target['gosaSnapshotData'] = gzcompress($data, 6);
1148 $target['gosaSnapshotType'] = $type;
1149 $target['gosaSnapshotDN'] = $this->dn;
1150 $target['description'] = $description;
1151 $target['gosaSnapshotTimestamp'] = $newName;
1153 /* Insert the new snapshot
1154 But we have to check first, if the given gosaSnapshotTimestamp
1155 is already used, in this case we should increment this value till there is
1156 an unused value. */
1157 $new_dn = "gosaSnapshotTimestamp=".$newName.",".$new_base;
1158 $ldap_to->cat($new_dn);
1159 while($ldap_to->count()){
1160 $ldap_to->cat($new_dn);
1161 $newName = preg_replace("/\./", "", $sec."-".($usec++));
1162 $new_dn = "gosaSnapshotTimestamp=".$newName.",".$new_base;
1163 $target['gosaSnapshotTimestamp'] = $newName;
1164 }
1166 /* Inset this new snapshot */
1167 $ldap_to->cd($snapldapbase);
1168 $ldap_to->create_missing_trees($new_base);
1169 $ldap_to->cd($new_dn);
1170 $ldap_to->add($target);
1172 show_ldap_error($ldap->get_error(), sprintf(_("Saving object snapshot with dn '%s' failed."),$new_base));
1173 show_ldap_error($ldap_to->get_error(), sprintf(_("Saving object snapshot with dn '%s' failed."),$new_base));
1174 }
1175 }
1177 function remove_snapshot($dn)
1178 {
1179 $ui = get_userinfo();
1180 $old_dn = $this->dn;
1181 $this->dn = $dn;
1182 $ldap = $this->config->get_ldap_link();
1183 $ldap->cd($this->config->current['BASE']);
1184 $ldap->rmdir_recursive($dn);
1185 $this->dn = $old_dn;
1186 }
1189 /* returns true if snapshots are enabled, and false if it is disalbed
1190 There will also be some errors psoted, if the configuration failed */
1191 function snapshotEnabled()
1192 {
1193 $tmp = $this->config->current;
1194 if(isset($tmp['ENABLE_SNAPSHOT'])){
1195 if (preg_match("/^true$/i", $tmp['ENABLE_SNAPSHOT']) || preg_match("/yes/i", $tmp['ENABLE_SNAPSHOT'])){
1197 /* Check if the snapshot_base is defined */
1198 if(!isset($tmp['SNAPSHOT_BASE'])){
1199 print_red(sprintf(_("The snapshot functionality is enabled, but the required variable '%s' is not configured in your gosa.conf."),"SNAPSHOT_BASE"));
1200 return(FALSE);
1201 }
1203 /* check if there are special server configurations for snapshots */
1204 if(isset($tmp['SNAPSHOT_SERVER'])){
1206 /* check if all required vars are available to create a new ldap connection */
1207 $missing = "";
1208 foreach(array("SNAPSHOT_SERVER","SNAPSHOT_USER","SNAPSHOT_PASSWORD","SNAPSHOT_BASE") as $var){
1209 if(!isset($tmp[$var])){
1210 $missing .= $var." ";
1211 print_red(sprintf(_("The snapshot functionality is enabled, but the required variable(s) '%s' is not configured in your gosa.conf."),$missing));
1212 return(FALSE);
1213 }
1214 }
1215 }
1216 return(TRUE);
1217 }
1218 }
1219 return(FALSE);
1220 }
1223 /* Return available snapshots for the given base
1224 */
1225 function Available_SnapsShots($dn,$raw = false)
1226 {
1227 if(!$this->snapshotEnabled()) return(array());
1229 /* Create an additional ldap object which
1230 points to our ldap snapshot server */
1231 $ldap= $this->config->get_ldap_link();
1232 $ldap->cd($this->config->current['BASE']);
1233 $cfg= &$this->config->current;
1235 /* check if there are special server configurations for snapshots */
1237 if(isset($cfg['SERVER']) && isset($cfg['SNAPSHOT_SERVER']) && $cfg['SERVER'] == $cfg['SNAPSHOT_SERVER']){
1238 $ldap_to = $ldap;
1239 }elseif(isset($cfg['SNAPSHOT_SERVER'])){
1240 $server = $cfg['SNAPSHOT_SERVER'];
1241 $user = $cfg['SNAPSHOT_USER'];
1242 $password = $cfg['SNAPSHOT_PASSWORD'];
1243 $snapldapbase = $cfg['SNAPSHOT_BASE'];
1245 $ldap_to = new LDAP($user,$password, $server);
1246 $ldap_to -> cd ($snapldapbase);
1247 show_ldap_error($ldap->get_error(), sprintf(_("Method get available snapshots with dn '%s' failed."),$this->dn));
1248 }else{
1249 $ldap_to = $ldap;
1250 }
1252 /* Prepare bases and some other infos */
1253 $base = $this->config->current['BASE'];
1254 $snap_base = $cfg['SNAPSHOT_BASE'];
1255 $base_of_object = preg_replace ('/^[^,]+,/i', '', $dn);
1256 $new_base = preg_replace("/".normalizePreg($base)."$/","",$base_of_object).$snap_base;
1257 $tmp = array();
1259 /* Fetch all objects with gosaSnapshotDN=$dn */
1260 $ldap_to->cd($new_base);
1261 $ldap_to->ls("(&(objectClass=gosaSnapshotObject)(gosaSnapshotDN=".$dn."))",$new_base,
1262 array("gosaSnapshotType","gosaSnapshotTimestamp","gosaSnapshotDN","description"));
1264 /* Put results into a list and add description if missing */
1265 while($entry = $ldap_to->fetch()){
1266 if(!isset($entry['description'][0])){
1267 $entry['description'][0] = "";
1268 }
1269 $tmp[] = $entry;
1270 }
1272 /* Return the raw array, or format the result */
1273 if($raw){
1274 return($tmp);
1275 }else{
1276 $tmp2 = array();
1277 foreach($tmp as $entry){
1278 $tmp2[base64_encode($entry['dn'])] = $entry['description'][0];
1279 }
1280 }
1281 return($tmp2);
1282 }
1285 function getAllDeletedSnapshots($base_of_object,$raw = false)
1286 {
1287 if(!$this->snapshotEnabled()) return(array());
1289 /* Create an additional ldap object which
1290 points to our ldap snapshot server */
1291 $ldap= $this->config->get_ldap_link();
1292 $ldap->cd($this->config->current['BASE']);
1293 $cfg= &$this->config->current;
1295 /* check if there are special server configurations for snapshots */
1296 if(isset($cfg['SNAPSHOT_SERVER'])){
1297 $server = $cfg['SNAPSHOT_SERVER'];
1298 $user = $cfg['SNAPSHOT_USER'];
1299 $password = $cfg['SNAPSHOT_PASSWORD'];
1300 $snapldapbase = $cfg['SNAPSHOT_BASE'];
1301 $ldap_to = new LDAP($user,$password, $server);
1302 $ldap_to->cd ($snapldapbase);
1303 show_ldap_error($ldap_to->get_error(), sprintf(_("Method get deleted snapshots with dn '%s' failed."),$this->dn));
1304 }else{
1305 $ldap_to = $ldap;
1306 }
1308 /* Prepare bases */
1309 $base = $this->config->current['BASE'];
1310 $snap_base = $cfg['SNAPSHOT_BASE'];
1311 $new_base = preg_replace("/".normalizePreg($base)."$/","",$base_of_object).$snap_base;
1313 /* Fetch all objects and check if they do not exist anymore */
1314 $ui = get_userinfo();
1315 $tmp = array();
1316 $ldap_to->cd($new_base);
1317 $ldap_to->ls("(objectClass=gosaSnapshotObject)",$new_base,array("gosaSnapshotType","gosaSnapshotTimestamp","gosaSnapshotDN","description"));
1318 while($entry = $ldap_to->fetch()){
1320 $chk = str_replace($new_base,"",$entry['dn']);
1321 if(preg_match("/,ou=/",$chk)) continue;
1323 if(!isset($entry['description'][0])){
1324 $entry['description'][0] = "";
1325 }
1326 $tmp[] = $entry;
1327 }
1329 /* Check if entry still exists */
1330 foreach($tmp as $key => $entry){
1331 $ldap->cat($entry['gosaSnapshotDN'][0]);
1332 if($ldap->count()){
1333 unset($tmp[$key]);
1334 }
1335 }
1337 /* Format result as requested */
1338 if($raw) {
1339 return($tmp);
1340 }else{
1341 $tmp2 = array();
1342 foreach($tmp as $key => $entry){
1343 $tmp2[base64_encode($entry['dn'])] = $entry['description'][0];
1344 }
1345 }
1346 return($tmp2);
1347 }
1350 /* Restore selected snapshot */
1351 function restore_snapshot($dn)
1352 {
1353 if(!$this->snapshotEnabled()) return(array());
1355 $ldap= $this->config->get_ldap_link();
1356 $ldap->cd($this->config->current['BASE']);
1357 $cfg= &$this->config->current;
1359 /* check if there are special server configurations for snapshots */
1360 if(isset($cfg['SNAPSHOT_SERVER'])){
1361 $server = $cfg['SNAPSHOT_SERVER'];
1362 $user = $cfg['SNAPSHOT_USER'];
1363 $password = $cfg['SNAPSHOT_PASSWORD'];
1364 $snapldapbase = $cfg['SNAPSHOT_BASE'];
1365 $ldap_to = new LDAP($user,$password, $server);
1366 $ldap_to->cd ($snapldapbase);
1367 show_ldap_error($ldap->get_error(), sprintf(_("Restore snapshot with dn '%s' failed."),$snapldapbase));
1368 }else{
1369 $ldap_to = $ldap;
1370 }
1372 /* Get the snapshot */
1373 $ldap_to->cat($dn);
1374 $restoreObject = $ldap_to->fetch();
1376 /* Prepare import string */
1377 $data = gzuncompress($ldap_to->get_attribute($dn,'gosaSnapshotData'));
1379 /* Import the given data */
1380 $ldap->import_complete_ldif($data,$err,false,false);
1381 show_ldap_error($ldap->get_error(), sprintf(_("Restore snapshot with dn '%s' failed."),$dn));
1382 }
1385 function showSnapshotDialog($base,$baseSuffixe)
1386 {
1387 $once = true;
1388 foreach($_POST as $name => $value){
1390 /* Create a new snapshot, display a dialog */
1391 if(preg_match("/^CreateSnapShotDialog_/",$name) && $once){
1392 $once = false;
1393 $entry = preg_replace("/^CreateSnapShotDialog_/","",$name);
1394 $entry = base64_decode(preg_replace("/_[xy]$/","",$entry));
1395 $this->snapDialog = new SnapShotDialog($this->config,$entry,$this);
1396 }
1398 /* Restore a snapshot, display a dialog with all snapshots of the current object */
1399 if(preg_match("/^RestoreSnapShotDialog_/",$name) && $once){
1400 $once = false;
1401 $entry = preg_replace("/^RestoreSnapShotDialog_/","",$name);
1402 $entry = base64_decode(preg_replace("/_[xy]$/","",$entry));
1403 $this->snapDialog = new SnapShotDialog($this->config,$entry,$this);
1404 $this->snapDialog->display_restore_dialog = true;
1405 }
1407 /* Restore one of the already deleted objects */
1408 if(((isset($_POST['menu_action']) && $_POST['menu_action'] == "RestoreDeletedSnapShot")
1409 || preg_match("/^RestoreDeletedSnapShot_/",$name)) && $once){
1410 $once = false;
1411 $this->snapDialog = new SnapShotDialog($this->config,"",$this);
1412 $this->snapDialog->set_snapshot_bases($baseSuffixe);
1413 $this->snapDialog->display_restore_dialog = true;
1414 $this->snapDialog->display_all_removed_objects = true;
1415 }
1417 /* Restore selected snapshot */
1418 if(preg_match("/^RestoreSnapShot_/",$name) && $once){
1419 $once = false;
1420 $entry = preg_replace("/^RestoreSnapShot_/","",$name);
1421 $entry = base64_decode(trim(preg_replace("/_[xy]$/","",$entry)));
1422 if(!empty($entry)){
1423 $this->restore_snapshot($entry);
1424 $this->snapDialog = NULL;
1425 }
1426 }
1427 }
1429 /* Create a new snapshot requested, check
1430 the given attributes and create the snapshot*/
1431 if(isset($_POST['CreateSnapshot']) && is_object($this->snapDialog)){
1432 $this->snapDialog->save_object();
1433 $msgs = $this->snapDialog->check();
1434 if(count($msgs)){
1435 foreach($msgs as $msg){
1436 print_red($msg);
1437 }
1438 }else{
1439 $this->dn = $this->snapDialog->dn;
1440 $this->create_snapshot("snapshot",$this->snapDialog->CurrentDescription);
1441 $this->snapDialog = NULL;
1442 }
1443 }
1445 /* Restore is requested, restore the object with the posted dn .*/
1446 if((isset($_POST['RestoreSnapshot'])) && (isset($_POST['SnapShot']))){
1447 }
1449 if(isset($_POST['CancelSnapshot'])){
1450 $this->snapDialog = NULL;
1451 }
1453 if(is_object($this->snapDialog )){
1454 $this->snapDialog->save_object();
1455 return($this->snapDialog->execute());
1456 }
1457 }
1460 static function plInfo()
1461 {
1462 return array();
1463 }
1466 function set_acl_base($base)
1467 {
1468 $this->acl_base= $base;
1469 }
1472 function set_acl_category($category)
1473 {
1474 $this->acl_category= "$category/";
1475 }
1478 function acl_is_writeable($attribute,$skip_write = FALSE)
1479 {
1480 $ui= get_userinfo();
1481 return preg_match('/w/', $ui->get_permissions($this->acl_base, $this->acl_category.get_class($this), $attribute, $skip_write));
1482 }
1485 function acl_is_readable($attribute)
1486 {
1487 $ui= get_userinfo();
1488 return preg_match('/r/', $ui->get_permissions($this->acl_base, $this->acl_category.get_class($this), $attribute));
1489 }
1492 function acl_is_createable()
1493 {
1494 $ui= get_userinfo();
1495 return preg_match('/c/', $ui->get_permissions($this->acl_base, $this->acl_category.get_class($this), '0'));
1496 }
1499 function acl_is_removeable()
1500 {
1501 $ui= get_userinfo();
1502 return preg_match('/d/', $ui->get_permissions($this->acl_base, $this->acl_category.get_class($this), '0'));
1503 }
1506 function acl_is_moveable()
1507 {
1508 $ui= get_userinfo();
1509 return preg_match('/m/', $ui->get_permissions($this->acl_base, $this->acl_category.get_class($this), '0'));
1510 }
1513 function acl_have_any_permissions()
1514 {
1515 }
1518 function getacl($attribute,$skip_write= FALSE)
1519 {
1520 $ui= get_userinfo();
1521 return $ui->get_permissions($this->acl_base, $this->acl_category.get_class($this), $attribute,$skip_write);
1522 }
1524 /* Get all allowed bases to move an object to or to create a new object.
1525 Idepartments also contains all base departments which lead to the allowed bases */
1526 function get_allowed_bases($category = "")
1527 {
1528 $ui = get_userinfo();
1529 $deps = array();
1531 /* Set category */
1532 if(empty($category)){
1533 $category = $this->acl_category.get_class($this);
1534 }
1536 /* Is this a new object ? Or just an edited existing object */
1537 if(!$this->initially_was_account && $this->is_account){
1538 $new = true;
1539 }else{
1540 $new = false;
1541 }
1543 $cat_bases = $ui->get_module_departments(preg_replace("/\/.*$/","",$category));
1544 foreach($this->config->idepartments as $dn => $name){
1546 if(!in_array_ics($dn,$cat_bases)){
1547 continue;
1548 }
1550 $acl = $ui->get_permissions($dn,$category);
1551 if($new && preg_match("/c/",$acl)){
1552 $deps[$dn] = $name;
1553 }elseif(!$new && preg_match("/m/",$acl)){
1554 $deps[$dn] = $name;
1555 }
1556 }
1558 /* Add current base */
1559 if(isset($this->base) && isset($this->config->idepartments[$this->base])){
1560 $deps[$this->base] = $this->config->idepartments[$this->base];
1561 }else{
1562 echo "No default base found. ".$this->base."<br> ";
1563 }
1565 return($deps);
1566 }
1568 /* This function modifies object acls too, if an object is moved.
1569 * $old_dn specifies the actually used dn
1570 * $new_dn specifies the destiantion dn
1571 */
1572 function update_acls($old_dn,$new_dn,$output_changes = FALSE)
1573 {
1574 /* Check if old_dn is empty. This should never happen */
1575 if(empty($old_dn) || empty($new_dn)){
1576 trigger_error("Failed to check acl dependencies, wrong dn given.");
1577 return;
1578 }
1580 /* Update userinfo if necessary */
1581 if($_SESSION['ui']->dn == $old_dn){
1582 $_SESSION['ui']->dn = $new_dn;
1583 new log("view","acl/".get_class($this),$this->dn,array(),"Updated current user dn from '".$old_dn."' to '".$new_dn."'");
1584 }
1586 /* Object was moved, ensure that all acls will be moved too */
1587 if($new_dn != $old_dn && $old_dn != "new"){
1589 /* get_ldap configuration */
1590 $update = array();
1591 $ldap = $this->config->get_ldap_link();
1592 $ldap->cd ($this->config->current['BASE']);
1593 $ldap->search("(&(objectClass=gosaAcl)(gosaAclEntry=*))",array("cn","gosaAclEntry"));
1594 while($attrs = $ldap->fetch()){
1596 $acls = array();
1598 /* Walk through acls */
1599 for($i = 0 ; $i < $attrs['gosaAclEntry']['count'] ; $i ++ ){
1601 /* Reset vars */
1602 $found = false;
1604 /* Get Acl parts */
1605 $acl_parts = split(":",$attrs['gosaAclEntry'][$i]);
1607 /* Get every single member for this acl */
1608 $members = array();
1609 if(preg_match("/,/",$acl_parts[2])){
1610 $members = split(",",$acl_parts[2]);
1611 }else{
1612 $members = array($acl_parts[2]);
1613 }
1615 /* Check if member match current dn */
1616 foreach($members as $key => $member){
1617 $member = base64_decode($member);
1618 if($member == $old_dn){
1619 $found = true;
1620 $members[$key] = base64_encode($new_dn);
1621 }
1622 }
1624 /* Create new member string */
1625 $new_members = "";
1626 foreach($members as $member){
1627 $new_members .= $member.",";
1628 }
1629 $new_members = preg_replace("/,$/","",$new_members);
1630 $acl_parts[2] = $new_members;
1632 /* Reconstruckt acl entry */
1633 $acl_str ="";
1634 foreach($acl_parts as $t){
1635 $acl_str .= $t.":";
1636 }
1637 $acl_str = preg_replace("/:$/","",$acl_str);
1638 }
1640 /* Acls for this object must be adjusted */
1641 if($found){
1643 if($output_changes){
1644 echo "<font color='green'>".
1645 _("Changing ACL dn")." : <br> -"._("from")." <b> ".
1646 $old_dn.
1647 "</b><br> -"._("to")." <b>".
1648 $new_dn.
1649 "</b></font><br>";
1650 }
1651 $update[$attrs['dn']] =array();
1652 foreach($acls as $acl){
1653 $update[$attrs['dn']]['gosaAclEntry'][] = $acl;
1654 }
1655 }
1656 }
1658 /* Write updated acls */
1659 foreach($update as $dn => $attrs){
1660 $ldap->cd($dn);
1661 $ldap->modify($attrs);
1662 }
1663 }
1664 }
1667 function get_multi_edit_values()
1668 {
1669 $ret = array();
1670 foreach($this->selected_edit_values as $attr => $active){
1671 if($active){
1672 $ret[$attr] = $this->$attr;
1673 }
1674 }
1675 return($ret);
1676 }
1678 function set_multi_edit_value()
1679 {
1681 }
1683 }
1685 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1686 ?>