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 if ($disabled == TRUE){
510 $state= "disabled";
511 } else {
512 $state= "";
513 }
514 $display= "<table summary=\"\" width=\"100%\"><tr>\n<td colspan=2><p><b>$text</b></p>\n";
515 $display.= "<input type=submit value=\"$button_text\" name=\"modify_state\" ".
516 chkacl($this->acl, "all")." ".$state.
517 "><p class=\"seperator\"> </p></td></tr></table>";
519 return($display);
520 }
522 function postcreate($add_attrs= array())
523 {
524 /* Find postcreate entries for this class */
525 $command= search_config($this->config->data['MENU'], get_class($this), "POSTCREATE");
526 if ($command == "" && isset($this->config->data['TABS'])){
527 $command= search_config($this->config->data['TABS'], get_class($this), "POSTCREATE");
528 }
530 if ($command != ""){
531 /* Walk through attribute list */
532 foreach ($this->attributes as $attr){
533 if (!is_array($this->$attr)){
534 $command= preg_replace("/%$attr/", $this->$attr, $command);
535 }
536 }
537 $command= preg_replace("/%dn/", $this->dn, $command);
539 /* Additional attributes */
540 foreach ($add_attrs as $name => $value){
541 $command= preg_replace("/%$name/", $value, $command);
542 }
544 if (check_command($command)){
545 @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
546 $command, "Execute");
548 exec($command);
549 } else {
550 $message= sprintf(_("Command '%s', specified as POSTCREATE for plugin '%s' doesn't seem to exist."), $command, get_class($this));
551 print_red ($message);
552 }
553 }
554 }
556 function postmodify($add_attrs= array())
557 {
558 /* Find postcreate entries for this class */
559 $command= search_config($this->config->data['MENU'], get_class($this), "POSTMODIFY");
560 if ($command == "" && isset($this->config->data['TABS'])){
561 $command= search_config($this->config->data['TABS'], get_class($this), "POSTMODIFY");
562 }
564 if ($command != ""){
565 /* Walk through attribute list */
566 foreach ($this->attributes as $attr){
567 if (!is_array($this->$attr)){
568 $command= preg_replace("/%$attr/", $this->$attr, $command);
569 }
570 }
571 $command= preg_replace("/%dn/", $this->dn, $command);
573 /* Additional attributes */
574 foreach ($add_attrs as $name => $value){
575 $command= preg_replace("/%$name/", $value, $command);
576 }
578 if (check_command($command)){
579 @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
580 $command, "Execute");
582 exec($command);
583 } else {
584 $message= sprintf(_("Command '%s', specified as POSTMODIFY for plugin '%s' doesn't seem to exist."), $command, get_class($this));
585 print_red ($message);
586 }
587 }
588 }
590 function postremove($add_attrs= array())
591 {
592 /* Find postremove entries for this class */
593 $command= search_config($this->config->data['MENU'], get_class($this), "POSTREMOVE");
594 if ($command == "" && isset($this->config->data['TABS'])){
595 $command= search_config($this->config->data['TABS'], get_class($this), "POSTREMOVE");
596 }
598 if ($command != ""){
599 /* Walk through attribute list */
600 foreach ($this->attributes as $attr){
601 if (!is_array($this->$attr)){
602 $command= preg_replace("/%$attr/", $this->$attr, $command);
603 }
604 }
605 $command= preg_replace("/%dn/", $this->dn, $command);
607 /* Additional attributes */
608 foreach ($add_attrs as $name => $value){
609 $command= preg_replace("/%$name/", $value, $command);
610 }
612 if (check_command($command)){
613 @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
614 $command, "Execute");
616 exec($command);
617 } else {
618 $message= sprintf(_("Command '%s', specified as POSTREMOVE for plugin '%s' doesn't seem to exist."), $command, get_class($this));
619 print_red ($message);
620 }
621 }
622 }
624 /* Create unique DN */
625 function create_unique_dn($attribute, $base)
626 {
627 $ldap= $this->config->get_ldap_link();
628 $base= preg_replace("/^,*/", "", $base);
630 /* Try to use plain entry first */
631 $dn= "$attribute=".$this->$attribute.",$base";
632 $ldap->cat ($dn, array('dn'));
633 if (!$ldap->fetch()){
634 return ($dn);
635 }
637 /* Look for additional attributes */
638 foreach ($this->attributes as $attr){
639 if ($attr == $attribute || $this->$attr == ""){
640 continue;
641 }
643 $dn= "$attribute=".$this->$attribute."+$attr=".$this->$attr.",$base";
644 $ldap->cat ($dn, array('dn'));
645 if (!$ldap->fetch()){
646 return ($dn);
647 }
648 }
650 /* None found */
651 return ("none");
652 }
654 function rebind($ldap, $referral)
655 {
656 $credentials= LDAP::get_credentials($referral, $this->config->current['REFERRAL']);
657 if (ldap_bind($ldap, $credentials['ADMIN'], $credentials['PASSWORD'])) {
658 $this->error = "Success";
659 $this->hascon=true;
660 $this->reconnect= true;
661 return (0);
662 } else {
663 $this->error = "Could not bind to " . $credentials['ADMIN'];
664 return NULL;
665 }
666 }
668 /* This is a workaround function. */
669 function copy($src_dn, $dst_dn)
670 {
671 /* Rename dn in possible object groups */
672 $ldap= $this->config->get_ldap_link();
673 $ldap->search('(&(objectClass=gosaGroupOfNames)(member='.@LDAP::fix($src_dn).'))',
674 array('cn'));
675 while ($attrs= $ldap->fetch()){
676 $og= new ogroup($this->config, $ldap->getDN());
677 unset($og->member[$src_dn]);
678 $og->member[$dst_dn]= $dst_dn;
679 $og->save ();
680 }
682 $ldap->cat($dst_dn);
683 $attrs= $ldap->fetch();
684 if (count($attrs)){
685 trigger_error("Trying to overwrite ".@LDAP::fix($dst_dn).", which already exists.",
686 E_USER_WARNING);
687 return (FALSE);
688 }
690 $ldap->cat($src_dn);
691 $attrs= $ldap->fetch();
692 if (!count($attrs)){
693 trigger_error("Trying to move ".@LDAP::fix($src_dn).", which does not seem to exist.",
694 E_USER_WARNING);
695 return (FALSE);
696 }
698 /* Grummble. This really sucks. PHP ldap doesn't support rdn stuff. */
699 $ds= ldap_connect($this->config->current['SERVER']);
700 ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
701 if (function_exists("ldap_set_rebind_proc") && isset($this->config->current['REFERRAL'])) {
702 ldap_set_rebind_proc($ds, array(&$this, "rebind"));
703 }
705 $r=ldap_bind($ds,$this->config->current['ADMIN'], $this->config->current['PASSWORD']);
706 error_reporting (0);
707 $sr=ldap_read($ds, @LDAP::fix($src_dn), "objectClass=*");
709 /* Fill data from LDAP */
710 $new= array();
711 if ($sr) {
712 $ei=ldap_first_entry($ds, $sr);
713 if ($ei) {
714 foreach($attrs as $attr => $val){
715 if ($info = ldap_get_values_len($ds, $ei, $attr)){
716 for ($i= 0; $i<$info['count']; $i++){
717 if ($info['count'] == 1){
718 $new[$attr]= $info[$i];
719 } else {
720 $new[$attr][]= $info[$i];
721 }
722 }
723 }
724 }
725 }
726 }
728 /* close conncetion */
729 error_reporting (E_ALL);
730 ldap_unbind($ds);
732 /* Adapt naming attribute */
733 $dst_name= preg_replace("/^([^=]+)=.*$/", "\\1", $dst_dn);
734 $dst_val = preg_replace("/^[^=]+=([^,+]+).*,.*$/", "\\1", $dst_dn);
735 $new[$dst_name]= @LDAP::fix($dst_val);
737 /* Check if this is a department.
738 * If it is a dep. && there is a , override in his ou
739 * change \2C to , again, else this entry can't be saved ...
740 */
741 if((isset($new['ou'])) &&( preg_match("/\\,/",$new['ou']))){
742 $new['ou'] = preg_replace("/\\\\,/",",",$new['ou']);
743 }
745 /* Save copy */
746 $ldap->connect();
747 $ldap->cd($this->config->current['BASE']);
749 $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $dst_dn));
751 /* FAIvariable=.../..., cn=..
752 could not be saved, because the attribute FAIvariable was different to
753 the dn FAIvariable=..., cn=... */
754 if(in_array_ics("FAIdebconfInfo",$new['objectClass'])){
755 $new['FAIvariable'] = $ldap->fix($new['FAIvariable']);
756 }
757 $ldap->cd($dst_dn);
758 $ldap->add($new);
760 if ($ldap->error != "Success"){
761 trigger_error("Trying to save $dst_dn failed.",
762 E_USER_WARNING);
763 return(FALSE);
764 }
766 return (TRUE);
767 }
770 function move($src_dn, $dst_dn)
771 {
772 /* Copy source to destination */
773 if (!$this->copy($src_dn, $dst_dn)){
774 return (FALSE);
775 }
777 /* Delete source */
778 $ldap= $this->config->get_ldap_link();
779 $ldap->rmdir($src_dn);
780 if ($ldap->error != "Success"){
781 trigger_error("Trying to delete $src_dn failed.",
782 E_USER_WARNING);
783 return (FALSE);
784 }
786 return (TRUE);
787 }
790 /* Move/Rename complete trees */
791 function recursive_move($src_dn, $dst_dn)
792 {
793 /* Check if the destination entry exists */
794 $ldap= $this->config->get_ldap_link();
796 /* Check if destination exists - abort */
797 $ldap->cat($dst_dn, array('dn'));
798 if ($ldap->fetch()){
799 trigger_error("recursive_move $dst_dn already exists.",
800 E_USER_WARNING);
801 return (FALSE);
802 }
804 /* Perform a search for all objects to be moved */
805 $objects= array();
806 $ldap->cd($src_dn);
807 $ldap->search("(objectClass=*)", array("dn"));
808 while($attrs= $ldap->fetch()){
809 $dn= $attrs['dn'];
810 $objects[$dn]= strlen($dn);
811 }
813 /* Sort objects by indent level */
814 asort($objects);
815 reset($objects);
817 /* Copy objects from small to big indent levels by replacing src_dn by dst_dn */
818 foreach ($objects as $object => $len){
819 $src= $object;
820 $dst= preg_replace("/$src_dn$/", "$dst_dn", $object);
821 if (!$this->copy($src, $dst)){
822 return (FALSE);
823 }
824 }
826 /* Remove src_dn */
827 $ldap->cd($src_dn);
828 $ldap->recursive_remove();
829 return (TRUE);
830 }
833 function handle_post_events($mode, $add_attrs= array())
834 {
835 switch ($mode){
836 case "add":
837 $this->postcreate($add_attrs);
838 break;
840 case "modify":
841 $this->postmodify($add_attrs);
842 break;
844 case "remove":
845 $this->postremove($add_attrs);
846 break;
847 }
848 }
851 function saveCopyDialog(){
852 }
855 function getCopyDialog(){
856 return(array("string"=>"","status"=>""));
857 }
860 function PrepareForCopyPaste($source){
861 $todo = $this->attributes;
862 if(isset($this->CopyPasteVars)){
863 $todo = array_merge($todo,$this->CopyPasteVars);
864 }
865 $todo[] = "is_account";
866 foreach($todo as $var){
867 if (isset($source->$var)){
868 $this->$var= $source->$var;
869 }
870 }
871 }
874 function handle_object_tagging($dn= "", $tag= "", $show= false)
875 {
876 //FIXME: How to optimize this? We have at least two
877 // LDAP accesses per object. It would be a good
878 // idea to have it integrated.
880 /* No dn? Self-operation... */
881 if ($dn == ""){
882 $dn= $this->dn;
884 /* No tag? Find it yourself... */
885 if ($tag == ""){
886 $len= strlen($dn);
888 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "No tag for $dn - looking for one...", "Tagging");
889 $relevant= array();
890 foreach ($this->config->adepartments as $key => $ntag){
892 /* This one is bigger than our dn, its not relevant... */
893 if ($len <= strlen($key)){
894 continue;
895 }
897 /* This one matches with the latter part. Break and don't fix this entry */
898 if (preg_match('/(^|,)'.normalizePreg($key).'$/', $dn)){
899 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "DEBUG: Possibly relevant: $key", "Tagging");
900 $relevant[strlen($key)]= $ntag;
901 continue;
902 }
904 }
906 /* If we've some relevant tags to set, just get the longest one */
907 if (count($relevant)){
908 ksort($relevant);
909 $tmp= array_keys($relevant);
910 $idx= end($tmp);
911 $tag= $relevant[$idx];
912 $this->gosaUnitTag= $tag;
913 }
914 }
915 }
918 /* Set tag? */
919 if ($tag != ""){
920 /* Set objectclass and attribute */
921 $ldap= $this->config->get_ldap_link();
922 $ldap->cat($dn, array('gosaUnitTag', 'objectClass'));
923 $attrs= $ldap->fetch();
924 if(isset($attrs['gosaUnitTag'][0]) && $attrs['gosaUnitTag'][0] == $tag){
925 if ($show) {
926 echo sprintf(_("Object '%s' is already tagged"), @LDAP::fix($dn))."<br>";
927 flush();
928 }
929 return;
930 }
931 if (count($attrs)){
932 if ($show){
933 echo sprintf(_("Adding tag (%s) to object '%s'"), $tag, @LDAP::fix($dn))."<br>";
934 flush();
935 }
936 $nattrs= array("gosaUnitTag" => $tag);
937 $nattrs['objectClass']= array();
938 for ($i= 0; $i<$attrs['objectClass']['count']; $i++){
939 $oc= $attrs['objectClass'][$i];
940 if ($oc != "gosaAdministrativeUnitTag"){
941 $nattrs['objectClass'][]= $oc;
942 }
943 }
944 $nattrs['objectClass'][]= "gosaAdministrativeUnitTag";
945 $ldap->cd($dn);
946 $ldap->modify($nattrs);
947 show_ldap_error($ldap->get_error(), _("Handle object tagging failed"));
948 } else {
949 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "Not tagging ($tag) $dn - seems to have moved away", "Tagging");
950 }
952 } else {
953 /* Remove objectclass and attribute */
954 $ldap= $this->config->get_ldap_link();
955 $ldap->cat($dn, array('gosaUnitTag', 'objectClass'));
956 $attrs= $ldap->fetch();
957 if (isset($attrs['objectClass']) && !in_array_ics("gosaAdministrativeUnitTag", $attrs['objectClass'])){
958 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "$dn is not tagged", "Tagging");
959 return;
960 }
961 if (count($attrs)){
962 if ($show){
963 echo sprintf(_("Removing tag from object '%s'"), @LDAP::fix($dn))."<br>";
964 flush();
965 }
966 $nattrs= array("gosaUnitTag" => array());
967 $nattrs['objectClass']= array();
968 for ($i= 0; $i<$attrs['objectClass']['count']; $i++){
969 $oc= $attrs['objectClass'][$i];
970 if ($oc != "gosaAdministrativeUnitTag"){
971 $nattrs['objectClass'][]= $oc;
972 }
973 }
974 $ldap->cd($dn);
975 $ldap->modify($nattrs);
976 show_ldap_error($ldap->get_error(), _("Handle object tagging failed"));
977 } else {
978 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "Not removing tag ($tag) $dn - seems to have moved away", "Tagging");
979 }
980 }
982 }
985 /* Add possibility to stop remove process */
986 function allow_remove()
987 {
988 $reason= "";
989 return $reason;
990 }
992 }
993 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
994 ?>