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