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;
104 /* attribute list for save action */
105 var $attributes= array();
106 var $objectclasses= array();
107 var $new= TRUE;
108 var $saved_attributes= array();
110 /*! \brief plugin constructor
112 If 'dn' is set, the node loads the given 'dn' from LDAP
114 \param dn Distinguished name to initialize plugin from
115 \sa plugin()
116 */
117 function plugin ($config, $dn= NULL, $parent= NULL)
118 {
119 /* Configuration is fine, allways */
120 $this->config= $config;
121 $this->dn= $dn;
123 /* Handle new accounts, don't read information from LDAP */
124 if ($dn == "new"){
125 return;
126 }
128 /* Get LDAP descriptor */
129 $ldap= $this->config->get_ldap_link();
130 if ($dn != NULL){
132 /* Load data to 'attrs' and save 'dn' */
133 if ($parent != NULL){
134 $this->attrs= $parent->attrs;
135 } else {
136 $ldap->cat ($dn);
137 $this->attrs= $ldap->fetch();
138 }
140 /* Copy needed attributes */
141 foreach ($this->attributes as $val){
142 $found= array_key_ics($val, $this->attrs);
143 if ($found != ""){
144 $this->$val= $this->attrs["$found"][0];
145 }
146 }
148 /* gosaUnitTag loading... */
149 if (isset($this->attrs['gosaUnitTag'][0])){
150 $this->gosaUnitTag= $this->attrs['gosaUnitTag'][0];
151 }
153 /* Set the template flag according to the existence of objectClass
154 gosaUserTemplate */
155 if (isset($this->attrs['objectClass'])){
156 if (in_array ("gosaUserTemplate", $this->attrs['objectClass'])){
157 $this->is_template= TRUE;
158 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
159 "found", "Template check");
160 }
161 }
163 /* Is Account? */
164 error_reporting(0);
165 $found= TRUE;
166 foreach ($this->objectclasses as $obj){
167 if (preg_match('/top/i', $obj)){
168 continue;
169 }
170 if (!isset($this->attrs['objectClass']) || !in_array_ics ($obj, $this->attrs['objectClass'])){
171 $found= FALSE;
172 break;
173 }
174 }
175 error_reporting(E_ALL);
176 if ($found){
177 $this->is_account= TRUE;
178 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
179 "found", "Object check");
180 }
182 /* Prepare saved attributes */
183 $this->saved_attributes= $this->attrs;
184 foreach ($this->saved_attributes as $index => $value){
185 if (preg_match('/^[0-9]+$/', $index)){
186 unset($this->saved_attributes[$index]);
187 continue;
188 }
189 if (!in_array($index, $this->attributes) && $index != "objectClass"){
190 unset($this->saved_attributes[$index]);
191 continue;
192 }
193 if ($this->saved_attributes[$index]["count"] == 1){
194 $tmp= $this->saved_attributes[$index][0];
195 unset($this->saved_attributes[$index]);
196 $this->saved_attributes[$index]= $tmp;
197 continue;
198 }
200 unset($this->saved_attributes["$index"]["count"]);
201 }
202 }
204 /* Save initial account state */
205 $this->initially_was_account= $this->is_account;
206 }
208 /*! \brief execute plugin
210 Generates the html output for this node
211 */
212 function execute()
213 {
214 # This one is empty currently. Fabian - please fill in the docu code
215 $_SESSION['current_class_for_help'] = get_class($this);
216 /* Reset Lock message POST/GET check array, to prevent perg_match errors*/
217 $_SESSION['LOCK_VARS_TO_USE'] =array();
218 }
220 /*! \brief execute plugin
221 Removes object from parent
222 */
223 function remove_from_parent()
224 {
225 /* include global link_info */
226 $ldap= $this->config->get_ldap_link();
228 /* Get current objectClasses in order to add the required ones */
229 $ldap->cat($this->dn);
230 $tmp= $ldap->fetch ();
231 if (isset($tmp['objectClass'])){
232 $oc= $tmp['objectClass'];
233 } else {
234 $oc= array("count" => 0);
235 }
237 /* Remove objectClasses from entry */
238 $ldap->cd($this->dn);
239 $this->attrs= array();
240 $this->attrs['objectClass']= array();
241 for ($i= 0; $i<$oc["count"]; $i++){
242 if (!in_array_ics($oc[$i], $this->objectclasses)){
243 $this->attrs['objectClass'][]= $oc[$i];
244 }
245 }
247 /* Unset attributes from entry */
248 foreach ($this->attributes as $val){
249 $this->attrs["$val"]= array();
250 }
252 /* Unset account info */
253 $this->is_account= FALSE;
255 /* Do not write in plugin base class, this must be done by
256 children, since there are normally additional attribs,
257 lists, etc. */
258 /*
259 $ldap->modify($this->attrs);
260 */
261 }
264 /* Save data to object */
265 function save_object()
266 {
267 /* Save values to object */
268 foreach ($this->attributes as $val){
269 if (chkacl ($this->acl, "$val") == "" && isset ($_POST["$val"])){
270 /* Check for modifications */
271 if ((get_magic_quotes_gpc()) && !is_array($_POST["$val"])) {
272 $data= stripcslashes($_POST["$val"]);
273 } else {
274 $data= $this->$val = $_POST["$val"];
275 }
276 if ($this->$val != $data){
277 $this->is_modified= TRUE;
278 }
280 /* Okay, how can I explain this fix ...
281 * In firefox, disabled option fields aren't selectable ... but in IE you can select these fileds.
282 * So IE posts these 'unselectable' option, with value = chr(194)
283 * chr(194) seems to be the in between the ...option> </option.. because there is no value=".." specified in these option fields
284 * This was added for W3c compliance, but now causes these ... ldap errors ...
285 * So we set these Fields to ""; a normal empty string, and we can check these values in plugin::check() again ...
286 */
287 if(isset($data[0]) && $data[0] == chr(194)) {
288 $data = "";
289 }
290 $this->$val= $data;
291 }
292 }
293 }
296 /* Save data to LDAP, depending on is_account we save or delete */
297 function save()
298 {
299 /* include global link_info */
300 $ldap= $this->config->get_ldap_link();
302 /* Start with empty array */
303 $this->attrs= array();
305 /* Get current objectClasses in order to add the required ones */
306 $ldap->cat($this->dn);
308 $tmp= $ldap->fetch ();
310 if (isset($tmp['objectClass'])){
311 $oc= $tmp["objectClass"];
312 $this->new= FALSE;
313 } else {
314 $oc= array("count" => 0);
315 $this->new= TRUE;
316 }
318 /* Load (minimum) attributes, add missing ones */
319 $this->attrs['objectClass']= $this->objectclasses;
320 for ($i= 0; $i<$oc["count"]; $i++){
321 if (!in_array_ics($oc[$i], $this->objectclasses)){
322 $this->attrs['objectClass'][]= $oc[$i];
323 }
324 }
326 /* Copy standard attributes */
327 foreach ($this->attributes as $val){
328 if ($this->$val != ""){
329 $this->attrs["$val"]= $this->$val;
330 } elseif (!$this->new) {
331 $this->attrs["$val"]= array();
332 }
333 }
335 }
338 function cleanup()
339 {
340 foreach ($this->attrs as $index => $value){
342 /* Convert arrays with one element to non arrays, if the saved
343 attributes are no array, too */
344 if (is_array($this->attrs[$index]) &&
345 count ($this->attrs[$index]) == 1 &&
346 isset($this->saved_attributes[$index]) &&
347 !is_array($this->saved_attributes[$index])){
349 $tmp= $this->attrs[$index][0];
350 $this->attrs[$index]= $tmp;
351 }
353 /* Remove emtpy arrays if they do not differ */
354 if (is_array($this->attrs[$index]) &&
355 count($this->attrs[$index]) == 0 &&
356 !isset($this->saved_attributes[$index])){
358 unset ($this->attrs[$index]);
359 continue;
360 }
362 /* Remove single attributes that do not differ */
363 if (!is_array($this->attrs[$index]) &&
364 isset($this->saved_attributes[$index]) &&
365 !is_array($this->saved_attributes[$index]) &&
366 $this->attrs[$index] == $this->saved_attributes[$index]){
368 unset ($this->attrs[$index]);
369 continue;
370 }
372 /* Remove arrays that do not differ */
373 if (is_array($this->attrs[$index]) &&
374 isset($this->saved_attributes[$index]) &&
375 is_array($this->saved_attributes[$index])){
377 if (!array_differs($this->attrs[$index],$this->saved_attributes[$index])){
378 unset ($this->attrs[$index]);
379 continue;
380 }
381 }
382 }
383 }
385 /* Check formular input */
386 function check()
387 {
388 $message= array();
390 /* Skip if we've no config object */
391 if (!isset($this->config)){
392 return $message;
393 }
395 /* Find hooks entries for this class */
396 $command= search_config($this->config->data['MENU'], get_class($this), "CHECK");
397 if ($command == "" && isset($this->config->data['TABS'])){
398 $command= search_config($this->config->data['TABS'], get_class($this), "CHECK");
399 }
401 if ($command != ""){
403 if (!check_command($command)){
404 $message[]= sprintf(_("Command '%s', specified as CHECK hook for plugin '%s' doesn't seem to exist."), $command,
405 get_class($this));
406 } else {
408 /* Generate "ldif" for check hook */
409 $ldif= "dn: $this->dn\n";
411 /* ... objectClasses */
412 foreach ($this->objectclasses as $oc){
413 $ldif.= "objectClass: $oc\n";
414 }
416 /* ... attributes */
417 foreach ($this->attributes as $attr){
418 if ($this->$attr == ""){
419 continue;
420 }
421 if (is_array($this->$attr)){
422 foreach ($this->$attr as $val){
423 $ldif.= "$attr: $val\n";
424 }
425 } else {
426 $ldif.= "$attr: ".$this->$attr."\n";
427 }
428 }
430 /* Append empty line */
431 $ldif.= "\n";
433 /* Feed "ldif" into hook and retrieve result*/
434 $descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w"));
435 $fh= proc_open($command, $descriptorspec, $pipes);
436 if (is_resource($fh)) {
437 fwrite ($pipes[0], $ldif);
438 fclose($pipes[0]);
440 $result= stream_get_contents($pipes[1]);
441 if ($result != ""){
442 $message[]= $result;
443 }
445 fclose($pipes[1]);
446 fclose($pipes[2]);
447 proc_close($fh);
448 }
449 }
451 }
453 return ($message);
454 }
456 /* Adapt from template, using 'dn' */
457 function adapt_from_template($dn)
458 {
459 /* Include global link_info */
460 $ldap= $this->config->get_ldap_link();
462 /* Load requested 'dn' to 'attrs' */
463 $ldap->cat ($dn);
464 $this->attrs= $ldap->fetch();
466 /* Walk through attributes */
467 foreach ($this->attributes as $val){
469 if (isset($this->attrs["$val"][0])){
471 /* If attribute is set, replace dynamic parts:
472 %sn, %givenName and %uid. Fill these in our local variables. */
473 $value= $this->attrs["$val"][0];
475 foreach (array("sn", "givenName", "uid") as $repl){
476 if (preg_match("/%$repl/i", $value)){
477 $value= preg_replace ("/%$repl/i", $this->parent->$repl, $value);
478 }
479 }
480 $this->$val= $value;
481 }
482 }
484 /* Is Account? */
485 $found= TRUE;
486 foreach ($this->objectclasses as $obj){
487 if (preg_match('/top/i', $obj)){
488 continue;
489 }
490 if (!in_array_ics ($obj, $this->attrs['objectClass'])){
491 $found= FALSE;
492 break;
493 }
494 }
495 if ($found){
496 $this->is_account= TRUE;
497 }
498 }
500 /* Indicate whether a password change is needed or not */
501 function password_change_needed()
502 {
503 return FALSE;
504 }
506 /* Show header message for tab dialogs */
507 function show_header($button_text, $text, $disabled= FALSE)
508 {
509 $state = "disabled";
510 if($this->is_account && $this->acl == "#all#"){
511 $state= "";
512 }elseif(!$this->is_account && chkacl($this->acl,"create") == ""){
513 $state= "";
514 }
516 if ($disabled == TRUE){
517 $state= "disabled";
518 }
520 $display= "<table summary=\"\" width=\"100%\"><tr>\n<td colspan=2><p><b>$text</b></p>\n";
521 $display.= "<input type=submit value=\"$button_text\" name=\"modify_state\" ".$state.">".
522 "<p class=\"seperator\"> </p></td></tr></table>";
524 return($display);
525 }
527 function postcreate($add_attrs= array())
528 {
529 /* Find postcreate entries for this class */
530 $command= search_config($this->config->data['MENU'], get_class($this), "POSTCREATE");
531 if ($command == "" && isset($this->config->data['TABS'])){
532 $command= search_config($this->config->data['TABS'], get_class($this), "POSTCREATE");
533 }
535 if ($command != ""){
536 /* Walk through attribute list */
537 foreach ($this->attributes as $attr){
538 if (!is_array($this->$attr)){
539 $command= preg_replace("/%$attr/", $this->$attr, $command);
540 }
541 }
542 $command= preg_replace("/%dn/", $this->dn, $command);
544 /* Additional attributes */
545 foreach ($add_attrs as $name => $value){
546 $command= preg_replace("/%$name/", $value, $command);
547 }
549 if (check_command($command)){
550 @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
551 $command, "Execute");
553 exec($command);
554 } else {
555 $message= sprintf(_("Command '%s', specified as POSTCREATE for plugin '%s' doesn't seem to exist."), $command, get_class($this));
556 print_red ($message);
557 }
558 }
559 }
561 function postmodify($add_attrs= array())
562 {
563 /* Find postcreate entries for this class */
564 $command= search_config($this->config->data['MENU'], get_class($this), "POSTMODIFY");
565 if ($command == "" && isset($this->config->data['TABS'])){
566 $command= search_config($this->config->data['TABS'], get_class($this), "POSTMODIFY");
567 }
569 if ($command != ""){
570 /* Walk through attribute list */
571 foreach ($this->attributes as $attr){
572 if (!is_array($this->$attr)){
573 $command= preg_replace("/%$attr/", $this->$attr, $command);
574 }
575 }
576 $command= preg_replace("/%dn/", $this->dn, $command);
578 /* Additional attributes */
579 foreach ($add_attrs as $name => $value){
580 $command= preg_replace("/%$name/", $value, $command);
581 }
583 if (check_command($command)){
584 @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
585 $command, "Execute");
587 exec($command);
588 } else {
589 $message= sprintf(_("Command '%s', specified as POSTMODIFY for plugin '%s' doesn't seem to exist."), $command, get_class($this));
590 print_red ($message);
591 }
592 }
593 }
595 function postremove($add_attrs= array())
596 {
597 /* Find postremove entries for this class */
598 $command= search_config($this->config->data['MENU'], get_class($this), "POSTREMOVE");
599 if ($command == "" && isset($this->config->data['TABS'])){
600 $command= search_config($this->config->data['TABS'], get_class($this), "POSTREMOVE");
601 }
603 if ($command != ""){
604 /* Walk through attribute list */
605 foreach ($this->attributes as $attr){
606 if (!is_array($this->$attr)){
607 $command= preg_replace("/%$attr/", $this->$attr, $command);
608 }
609 }
610 $command= preg_replace("/%dn/", $this->dn, $command);
612 /* Additional attributes */
613 foreach ($add_attrs as $name => $value){
614 $command= preg_replace("/%$name/", $value, $command);
615 }
617 if (check_command($command)){
618 @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
619 $command, "Execute");
621 exec($command);
622 } else {
623 $message= sprintf(_("Command '%s', specified as POSTREMOVE for plugin '%s' doesn't seem to exist."), $command, get_class($this));
624 print_red ($message);
625 }
626 }
627 }
629 /* Create unique DN */
630 function create_unique_dn($attribute, $base)
631 {
632 $ldap= $this->config->get_ldap_link();
633 $base= preg_replace("/^,*/", "", $base);
635 /* Try to use plain entry first */
636 $dn= "$attribute=".$this->$attribute.",$base";
637 $ldap->cat ($dn, array('dn'));
638 if (!$ldap->fetch()){
639 return ($dn);
640 }
642 /* Look for additional attributes */
643 foreach ($this->attributes as $attr){
644 if ($attr == $attribute || $this->$attr == ""){
645 continue;
646 }
648 $dn= "$attribute=".$this->$attribute."+$attr=".$this->$attr.",$base";
649 $ldap->cat ($dn, array('dn'));
650 if (!$ldap->fetch()){
651 return ($dn);
652 }
653 }
655 /* None found */
656 return ("none");
657 }
659 function rebind($ldap, $referral)
660 {
661 $credentials= LDAP::get_credentials($referral, $this->config->current['REFERRAL']);
662 if (ldap_bind($ldap, $credentials['ADMIN'], $credentials['PASSWORD'])) {
663 $this->error = "Success";
664 $this->hascon=true;
665 $this->reconnect= true;
666 return (0);
667 } else {
668 $this->error = "Could not bind to " . $credentials['ADMIN'];
669 return NULL;
670 }
671 }
673 /* This is a workaround function. */
674 function copy($src_dn, $dst_dn)
675 {
676 /* Rename dn in possible object groups */
677 $ldap= $this->config->get_ldap_link();
678 $ldap->search('(&(objectClass=gosaGroupOfNames)(member='.@LDAP::fix($src_dn).'))',
679 array('cn'));
680 while ($attrs= $ldap->fetch()){
681 $og= new ogroup($this->config, $ldap->getDN());
682 unset($og->member[$src_dn]);
683 $og->member[$dst_dn]= $dst_dn;
684 $og->save ();
685 }
687 $ldap->cat($dst_dn);
688 $attrs= $ldap->fetch();
689 if (count($attrs)){
690 trigger_error("Trying to overwrite ".@LDAP::fix($dst_dn).", which already exists.",
691 E_USER_WARNING);
692 return (FALSE);
693 }
695 $ldap->cat($src_dn);
696 $attrs= $ldap->fetch();
697 if (!count($attrs)){
698 trigger_error("Trying to move ".@LDAP::fix($src_dn).", which does not seem to exist.",
699 E_USER_WARNING);
700 return (FALSE);
701 }
703 /* Grummble. This really sucks. PHP ldap doesn't support rdn stuff. */
704 $ds= ldap_connect($this->config->current['SERVER']);
705 ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
706 if (function_exists("ldap_set_rebind_proc") && isset($this->config->current['REFERRAL'])) {
707 ldap_set_rebind_proc($ds, array(&$this, "rebind"));
708 }
710 $r=ldap_bind($ds,$this->config->current['ADMIN'], $this->config->current['PASSWORD']);
711 error_reporting (0);
712 $sr=ldap_read($ds, @LDAP::fix($src_dn), "objectClass=*");
714 /* Fill data from LDAP */
715 $new= array();
716 if ($sr) {
717 $ei=ldap_first_entry($ds, $sr);
718 if ($ei) {
719 foreach($attrs as $attr => $val){
720 if ($info = ldap_get_values_len($ds, $ei, $attr)){
721 for ($i= 0; $i<$info['count']; $i++){
722 if ($info['count'] == 1){
723 $new[$attr]= $info[$i];
724 } else {
725 $new[$attr][]= $info[$i];
726 }
727 }
728 }
729 }
730 }
731 }
733 /* close conncetion */
734 error_reporting (E_ALL);
735 ldap_unbind($ds);
737 /* Adapt naming attribute */
738 $dst_name= preg_replace("/^([^=]+)=.*$/", "\\1", $dst_dn);
739 $dst_val = preg_replace("/^[^=]+=([^,+]+).*,.*$/", "\\1", $dst_dn);
740 $new[$dst_name]= @LDAP::fix($dst_val);
742 /* Check if this is a department.
743 * If it is a dep. && there is a , override in his ou
744 * change \2C to , again, else this entry can't be saved ...
745 */
746 if((isset($new['ou'])) &&( preg_match("/\\,/",$new['ou']))){
747 $new['ou'] = preg_replace("/\\\\,/",",",$new['ou']);
748 }
750 /* Save copy */
751 $ldap->connect();
752 $ldap->cd($this->config->current['BASE']);
754 $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $dst_dn));
756 /* FAIvariable=.../..., cn=..
757 could not be saved, because the attribute FAIvariable was different to
758 the dn FAIvariable=..., cn=... */
759 if(in_array_ics("FAIdebconfInfo",$new['objectClass'])){
760 $new['FAIvariable'] = $ldap->fix($new['FAIvariable']);
761 }
762 $ldap->cd($dst_dn);
763 $ldap->add($new);
765 if ($ldap->error != "Success"){
766 trigger_error("Trying to save $dst_dn failed.",
767 E_USER_WARNING);
768 return(FALSE);
769 }
771 return (TRUE);
772 }
775 function move($src_dn, $dst_dn)
776 {
777 /* Copy source to destination */
778 if (!$this->copy($src_dn, $dst_dn)){
779 return (FALSE);
780 }
782 /* Delete source */
783 $ldap= $this->config->get_ldap_link();
784 $ldap->rmdir($src_dn);
785 if ($ldap->error != "Success"){
786 trigger_error("Trying to delete $src_dn failed.",
787 E_USER_WARNING);
788 return (FALSE);
789 }
791 return (TRUE);
792 }
795 /* Move/Rename complete trees */
796 function recursive_move($src_dn, $dst_dn)
797 {
798 /* Check if the destination entry exists */
799 $ldap= $this->config->get_ldap_link();
801 /* Check if destination exists - abort */
802 $ldap->cat($dst_dn, array('dn'));
803 if ($ldap->fetch()){
804 trigger_error("recursive_move $dst_dn already exists.",
805 E_USER_WARNING);
806 return (FALSE);
807 }
809 /* Perform a search for all objects to be moved */
810 $objects= array();
811 $ldap->cd($src_dn);
812 $ldap->search("(objectClass=*)", array("dn"));
813 while($attrs= $ldap->fetch()){
814 $dn= $attrs['dn'];
815 $objects[$dn]= strlen($dn);
816 }
818 /* Sort objects by indent level */
819 asort($objects);
820 reset($objects);
822 /* Copy objects from small to big indent levels by replacing src_dn by dst_dn */
823 foreach ($objects as $object => $len){
824 $src= $object;
825 $dst= preg_replace("/$src_dn$/", "$dst_dn", $object);
826 if (!$this->copy($src, $dst)){
827 return (FALSE);
828 }
829 }
831 /* Remove src_dn */
832 $ldap->cd($src_dn);
833 $ldap->recursive_remove();
834 return (TRUE);
835 }
838 function handle_post_events($mode, $add_attrs= array())
839 {
840 switch ($mode){
841 case "add":
842 $this->postcreate($add_attrs);
843 break;
845 case "modify":
846 $this->postmodify($add_attrs);
847 break;
849 case "remove":
850 $this->postremove($add_attrs);
851 break;
852 }
853 }
856 function saveCopyDialog(){
857 }
860 function getCopyDialog(){
861 return(array("string"=>"","status"=>""));
862 }
865 function PrepareForCopyPaste($source){
866 $todo = $this->attributes;
867 if(isset($this->CopyPasteVars)){
868 $todo = array_merge($todo,$this->CopyPasteVars);
869 }
870 $todo[] = "is_account";
871 foreach($todo as $var){
872 if (isset($source->$var)){
873 $this->$var= $source->$var;
874 }
875 }
876 }
879 function handle_object_tagging($dn= "", $tag= "", $show= false)
880 {
881 //FIXME: How to optimize this? We have at least two
882 // LDAP accesses per object. It would be a good
883 // idea to have it integrated.
885 /* No dn? Self-operation... */
886 if ($dn == ""){
887 $dn= $this->dn;
889 /* No tag? Find it yourself... */
890 if ($tag == ""){
891 $len= strlen($dn);
893 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "No tag for $dn - looking for one...", "Tagging");
894 $relevant= array();
895 foreach ($this->config->adepartments as $key => $ntag){
897 /* This one is bigger than our dn, its not relevant... */
898 if ($len <= strlen($key)){
899 continue;
900 }
902 /* This one matches with the latter part. Break and don't fix this entry */
903 if (preg_match('/(^|,)'.normalizePreg($key).'$/', $dn)){
904 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "DEBUG: Possibly relevant: $key", "Tagging");
905 $relevant[strlen($key)]= $ntag;
906 continue;
907 }
909 }
911 /* If we've some relevant tags to set, just get the longest one */
912 if (count($relevant)){
913 ksort($relevant);
914 $tmp= array_keys($relevant);
915 $idx= end($tmp);
916 $tag= $relevant[$idx];
917 $this->gosaUnitTag= $tag;
918 }
919 }
920 }
923 /* Set tag? */
924 if ($tag != ""){
925 /* Set objectclass and attribute */
926 $ldap= $this->config->get_ldap_link();
927 $ldap->cat($dn, array('gosaUnitTag', 'objectClass'));
928 $attrs= $ldap->fetch();
929 if(isset($attrs['gosaUnitTag'][0]) && $attrs['gosaUnitTag'][0] == $tag){
930 if ($show) {
931 echo sprintf(_("Object '%s' is already tagged"), @LDAP::fix($dn))."<br>";
932 flush();
933 }
934 return;
935 }
936 if (count($attrs)){
937 if ($show){
938 echo sprintf(_("Adding tag (%s) to object '%s'"), $tag, @LDAP::fix($dn))."<br>";
939 flush();
940 }
941 $nattrs= array("gosaUnitTag" => $tag);
942 $nattrs['objectClass']= array();
943 for ($i= 0; $i<$attrs['objectClass']['count']; $i++){
944 $oc= $attrs['objectClass'][$i];
945 if ($oc != "gosaAdministrativeUnitTag"){
946 $nattrs['objectClass'][]= $oc;
947 }
948 }
949 $nattrs['objectClass'][]= "gosaAdministrativeUnitTag";
950 $ldap->cd($dn);
951 $ldap->modify($nattrs);
952 show_ldap_error($ldap->get_error(), _("Handle object tagging failed"));
953 } else {
954 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "Not tagging ($tag) $dn - seems to have moved away", "Tagging");
955 }
957 } else {
958 /* Remove objectclass and attribute */
959 $ldap= $this->config->get_ldap_link();
960 $ldap->cat($dn, array('gosaUnitTag', 'objectClass'));
961 $attrs= $ldap->fetch();
962 if (isset($attrs['objectClass']) && !in_array_ics("gosaAdministrativeUnitTag", $attrs['objectClass'])){
963 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "$dn is not tagged", "Tagging");
964 return;
965 }
966 if (count($attrs)){
967 if ($show){
968 echo sprintf(_("Removing tag from object '%s'"), @LDAP::fix($dn))."<br>";
969 flush();
970 }
971 $nattrs= array("gosaUnitTag" => array());
972 $nattrs['objectClass']= array();
973 for ($i= 0; $i<$attrs['objectClass']['count']; $i++){
974 $oc= $attrs['objectClass'][$i];
975 if ($oc != "gosaAdministrativeUnitTag"){
976 $nattrs['objectClass'][]= $oc;
977 }
978 }
979 $ldap->cd($dn);
980 $ldap->modify($nattrs);
981 show_ldap_error($ldap->get_error(), _("Handle object tagging failed"));
982 } else {
983 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "Not removing tag ($tag) $dn - seems to have moved away", "Tagging");
984 }
985 }
987 }
990 /* Add possibility to stop remove process */
991 function allow_remove()
992 {
993 $reason= "";
994 return $reason;
995 }
997 }
998 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
999 ?>