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 /* This can be set to render the tabulators in another stylesheet */
111 var $pl_notify= FALSE;
113 /*! \brief plugin constructor
115 If 'dn' is set, the node loads the given 'dn' from LDAP
117 \param dn Distinguished name to initialize plugin from
118 \sa plugin()
119 */
120 function plugin ($config, $dn= NULL, $parent= NULL)
121 {
122 /* Configuration is fine, allways */
123 $this->config= $config;
124 $this->dn= $dn;
126 /* Handle new accounts, don't read information from LDAP */
127 if ($dn == "new"){
128 return;
129 }
131 /* Get LDAP descriptor */
132 $ldap= $this->config->get_ldap_link();
133 if ($dn != NULL){
135 /* Load data to 'attrs' and save 'dn' */
136 if ($parent != NULL){
137 $this->attrs= $parent->attrs;
138 } else {
139 $ldap->cat ($dn);
140 $this->attrs= $ldap->fetch();
141 }
143 /* Copy needed attributes */
144 foreach ($this->attributes as $val){
145 $found= array_key_ics($val, $this->attrs);
146 if ($found != ""){
147 $this->$val= $this->attrs["$found"][0];
148 }
149 }
151 /* gosaUnitTag loading... */
152 if (isset($this->attrs['gosaUnitTag'][0])){
153 $this->gosaUnitTag= $this->attrs['gosaUnitTag'][0];
154 }
156 /* Set the template flag according to the existence of objectClass
157 gosaUserTemplate */
158 if (isset($this->attrs['objectClass'])){
159 if (in_array ("gosaUserTemplate", $this->attrs['objectClass'])){
160 $this->is_template= TRUE;
161 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
162 "found", "Template check");
163 }
164 }
166 /* Is Account? */
167 error_reporting(0);
168 $found= TRUE;
169 foreach ($this->objectclasses as $obj){
170 if (preg_match('/top/i', $obj)){
171 continue;
172 }
173 if (!isset($this->attrs['objectClass']) || !in_array_ics ($obj, $this->attrs['objectClass'])){
174 $found= FALSE;
175 break;
176 }
177 }
178 error_reporting(E_ALL);
179 if ($found){
180 $this->is_account= TRUE;
181 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
182 "found", "Object check");
183 }
185 /* Prepare saved attributes */
186 $this->saved_attributes= $this->attrs;
187 foreach ($this->saved_attributes as $index => $value){
188 if (preg_match('/^[0-9]+$/', $index)){
189 unset($this->saved_attributes[$index]);
190 continue;
191 }
192 if (!in_array($index, $this->attributes) && $index != "objectClass"){
193 unset($this->saved_attributes[$index]);
194 continue;
195 }
196 if ($this->saved_attributes[$index]["count"] == 1){
197 $tmp= $this->saved_attributes[$index][0];
198 unset($this->saved_attributes[$index]);
199 $this->saved_attributes[$index]= $tmp;
200 continue;
201 }
203 unset($this->saved_attributes["$index"]["count"]);
204 }
205 }
207 /* Save initial account state */
208 $this->initially_was_account= $this->is_account;
209 }
211 /*! \brief execute plugin
213 Generates the html output for this node
214 */
215 function execute()
216 {
217 # This one is empty currently. Fabian - please fill in the docu code
218 $_SESSION['current_class_for_help'] = get_class($this);
219 /* Reset Lock message POST/GET check array, to prevent perg_match errors*/
220 $_SESSION['LOCK_VARS_TO_USE'] =array();
221 }
223 /*! \brief execute plugin
224 Removes object from parent
225 */
226 function remove_from_parent()
227 {
228 /* include global link_info */
229 $ldap= $this->config->get_ldap_link();
231 /* Get current objectClasses in order to add the required ones */
232 $ldap->cat($this->dn);
233 $tmp= $ldap->fetch ();
234 if (isset($tmp['objectClass'])){
235 $oc= $tmp['objectClass'];
236 } else {
237 $oc= array("count" => 0);
238 }
240 /* Remove objectClasses from entry */
241 $ldap->cd($this->dn);
242 $this->attrs= array();
243 $this->attrs['objectClass']= array();
244 for ($i= 0; $i<$oc["count"]; $i++){
245 if (!in_array_ics($oc[$i], $this->objectclasses)){
246 $this->attrs['objectClass'][]= $oc[$i];
247 }
248 }
250 /* Unset attributes from entry */
251 foreach ($this->attributes as $val){
252 $this->attrs["$val"]= array();
253 }
255 /* Unset account info */
256 $this->is_account= FALSE;
258 /* Do not write in plugin base class, this must be done by
259 children, since there are normally additional attribs,
260 lists, etc. */
261 /*
262 $ldap->modify($this->attrs);
263 */
264 }
267 /* Save data to object */
268 function save_object()
269 {
270 /* Save values to object */
271 foreach ($this->attributes as $val){
272 if (chkacl ($this->acl, "$val") == "" && isset ($_POST["$val"])){
273 /* Check for modifications */
274 if ((get_magic_quotes_gpc()) && !is_array($_POST["$val"])) {
275 $data= stripcslashes($_POST["$val"]);
276 } else {
277 $data= $this->$val = $_POST["$val"];
278 }
279 if ($this->$val != $data){
280 $this->is_modified= TRUE;
281 }
283 /* Okay, how can I explain this fix ...
284 * In firefox, disabled option fields aren't selectable ... but in IE you can select these fileds.
285 * So IE posts these 'unselectable' option, with value = chr(194)
286 * chr(194) seems to be the in between the ...option> </option.. because there is no value=".." specified in these option fields
287 * This was added for W3c compliance, but now causes these ... ldap errors ...
288 * So we set these Fields to ""; a normal empty string, and we can check these values in plugin::check() again ...
289 */
290 if(isset($data[0]) && $data[0] == chr(194)) {
291 $data = "";
292 }
293 $this->$val= $data;
294 }
295 }
296 }
299 /* Save data to LDAP, depending on is_account we save or delete */
300 function save()
301 {
302 /* include global link_info */
303 $ldap= $this->config->get_ldap_link();
305 /* Start with empty array */
306 $this->attrs= array();
308 /* Get current objectClasses in order to add the required ones */
309 $ldap->cat($this->dn);
311 $tmp= $ldap->fetch ();
313 if (isset($tmp['objectClass'])){
314 $oc= $tmp["objectClass"];
315 $this->new= FALSE;
316 } else {
317 $oc= array("count" => 0);
318 $this->new= TRUE;
319 }
321 /* Load (minimum) attributes, add missing ones */
322 $this->attrs['objectClass']= $this->objectclasses;
323 for ($i= 0; $i<$oc["count"]; $i++){
324 if (!in_array_ics($oc[$i], $this->objectclasses)){
325 $this->attrs['objectClass'][]= $oc[$i];
326 }
327 }
329 /* Copy standard attributes */
330 foreach ($this->attributes as $val){
331 if ($this->$val != ""){
332 $this->attrs["$val"]= $this->$val;
333 } elseif (!$this->new) {
334 $this->attrs["$val"]= array();
335 }
336 }
338 /* Handle tagging */
339 $this->tag_attrs(&$this->attrs);
340 }
343 function cleanup()
344 {
345 foreach ($this->attrs as $index => $value){
347 /* Convert arrays with one element to non arrays, if the saved
348 attributes are no array, too */
349 if (is_array($this->attrs[$index]) &&
350 count ($this->attrs[$index]) == 1 &&
351 isset($this->saved_attributes[$index]) &&
352 !is_array($this->saved_attributes[$index])){
354 $tmp= $this->attrs[$index][0];
355 $this->attrs[$index]= $tmp;
356 }
358 /* Remove emtpy arrays if they do not differ */
359 if (is_array($this->attrs[$index]) &&
360 count($this->attrs[$index]) == 0 &&
361 !isset($this->saved_attributes[$index])){
363 unset ($this->attrs[$index]);
364 continue;
365 }
367 /* Remove single attributes that do not differ */
368 if (!is_array($this->attrs[$index]) &&
369 isset($this->saved_attributes[$index]) &&
370 !is_array($this->saved_attributes[$index]) &&
371 $this->attrs[$index] == $this->saved_attributes[$index]){
373 unset ($this->attrs[$index]);
374 continue;
375 }
377 /* Remove arrays that do not differ */
378 if (is_array($this->attrs[$index]) &&
379 isset($this->saved_attributes[$index]) &&
380 is_array($this->saved_attributes[$index])){
382 if (!array_differs($this->attrs[$index],$this->saved_attributes[$index])){
383 unset ($this->attrs[$index]);
384 continue;
385 }
386 }
387 }
389 /* Update saved attributes and ensure that next cleanups will be successful too */
390 foreach($this->attrs as $name => $value){
391 $this->saved_attributes[$name] = $value;
392 }
393 }
395 /* Check formular input */
396 function check()
397 {
398 $message= array();
400 /* Skip if we've no config object */
401 if (!isset($this->config)){
402 return $message;
403 }
405 /* Find hooks entries for this class */
406 $command= search_config($this->config->data['MENU'], get_class($this), "CHECK");
407 if ($command == "" && isset($this->config->data['TABS'])){
408 $command= search_config($this->config->data['TABS'], get_class($this), "CHECK");
409 }
411 if ($command != ""){
413 if (!check_command($command)){
414 $message[]= sprintf(_("Command '%s', specified as CHECK hook for plugin '%s' doesn't seem to exist."), $command,
415 get_class($this));
416 } else {
418 /* Generate "ldif" for check hook */
419 $ldif= "dn: $this->dn\n";
421 /* ... objectClasses */
422 foreach ($this->objectclasses as $oc){
423 $ldif.= "objectClass: $oc\n";
424 }
426 /* ... attributes */
427 foreach ($this->attributes as $attr){
428 if ($this->$attr == ""){
429 continue;
430 }
431 if (is_array($this->$attr)){
432 foreach ($this->$attr as $val){
433 $ldif.= "$attr: $val\n";
434 }
435 } else {
436 $ldif.= "$attr: ".$this->$attr."\n";
437 }
438 }
440 /* Append empty line */
441 $ldif.= "\n";
443 /* Feed "ldif" into hook and retrieve result*/
444 $descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w"));
445 $fh= proc_open($command, $descriptorspec, $pipes);
446 if (is_resource($fh)) {
447 fwrite ($pipes[0], $ldif);
448 fclose($pipes[0]);
450 $result= stream_get_contents($pipes[1]);
451 if ($result != ""){
452 $message[]= $result;
453 }
455 fclose($pipes[1]);
456 fclose($pipes[2]);
457 proc_close($fh);
458 }
459 }
461 }
463 return ($message);
464 }
466 /* Adapt from template, using 'dn' */
467 function adapt_from_template($dn)
468 {
469 /* Include global link_info */
470 $ldap= $this->config->get_ldap_link();
472 /* Load requested 'dn' to 'attrs' */
473 $ldap->cat ($dn);
474 $this->attrs= $ldap->fetch();
476 /* Walk through attributes */
477 foreach ($this->attributes as $val){
479 if (isset($this->attrs["$val"][0])){
481 /* If attribute is set, replace dynamic parts:
482 %sn, %givenName and %uid. Fill these in our local variables. */
483 $value= $this->attrs["$val"][0];
485 foreach (array("sn", "givenName", "uid") as $repl){
486 if (preg_match("/%$repl/i", $value)){
487 $value= preg_replace ("/%$repl/i", $this->parent->$repl, $value);
488 }
489 }
490 $this->$val= $value;
491 }
492 }
494 /* Is Account? */
495 $found= TRUE;
496 foreach ($this->objectclasses as $obj){
497 if (preg_match('/top/i', $obj)){
498 continue;
499 }
500 if (!in_array_ics ($obj, $this->attrs['objectClass'])){
501 $found= FALSE;
502 break;
503 }
504 }
505 if ($found){
506 $this->is_account= TRUE;
507 }
508 }
510 /* Indicate whether a password change is needed or not */
511 function password_change_needed()
512 {
513 return FALSE;
514 }
516 /* Show header message for tab dialogs */
517 function show_header($button_text, $text, $disabled= FALSE)
518 {
519 $state = "disabled";
520 if($this->is_account && $this->acl == "#all#"){
521 $state= "";
522 }elseif(!$this->is_account && chkacl($this->acl,"create") == ""){
523 $state= "";
524 }
526 if ($disabled == TRUE){
527 $state= "disabled";
528 }
530 $display= "<table summary=\"\" width=\"100%\"><tr>\n<td colspan=2><p><b>$text</b></p>\n";
531 $display.= "<input type=submit value=\"$button_text\" name=\"modify_state\" ".$state.">".
532 "<p class=\"seperator\"> </p></td></tr></table>";
534 return($display);
535 }
537 function postcreate($add_attrs= array())
538 {
539 /* Find postcreate entries for this class */
540 $command= search_config($this->config->data['MENU'], get_class($this), "POSTCREATE");
541 if ($command == "" && isset($this->config->data['TABS'])){
542 $command= search_config($this->config->data['TABS'], get_class($this), "POSTCREATE");
543 }
545 if ($command != ""){
547 /* Additional attributes */
548 foreach ($add_attrs as $name => $value){
549 $command= preg_replace("/%$name/", $value, $command);
550 }
552 /* Walk through attribute list */
553 foreach ($this->attributes as $attr){
554 if (!is_array($this->$attr)){
555 $command= preg_replace("/%$attr/", $this->$attr, $command);
556 }
557 }
558 $command= preg_replace("/%dn/", $this->dn, $command);
560 if (check_command($command)){
561 @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
562 $command, "Execute");
564 exec($command);
565 } else {
566 $message= sprintf(_("Command '%s', specified as POSTCREATE for plugin '%s' doesn't seem to exist."), $command, get_class($this));
567 print_red ($message);
568 }
569 }
570 }
572 function postmodify($add_attrs= array())
573 {
574 /* Find postcreate entries for this class */
575 $command= search_config($this->config->data['MENU'], get_class($this), "POSTMODIFY");
576 if ($command == "" && isset($this->config->data['TABS'])){
577 $command= search_config($this->config->data['TABS'], get_class($this), "POSTMODIFY");
578 }
580 if ($command != ""){
582 /* Additional attributes */
583 foreach ($add_attrs as $name => $value){
584 $command= preg_replace("/%$name/", $value, $command);
585 }
587 /* Walk through attribute list */
588 foreach ($this->attributes as $attr){
589 if (!is_array($this->$attr)){
590 $command= preg_replace("/%$attr/", $this->$attr, $command);
591 }
592 }
593 $command= preg_replace("/%dn/", $this->dn, $command);
595 if (check_command($command)){
596 @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
597 $command, "Execute");
599 exec($command);
600 } else {
601 $message= sprintf(_("Command '%s', specified as POSTMODIFY for plugin '%s' doesn't seem to exist."), $command, get_class($this));
602 print_red ($message);
603 }
604 }
605 }
607 function postremove($add_attrs= array())
608 {
609 /* Find postremove entries for this class */
610 $command= search_config($this->config->data['MENU'], get_class($this), "POSTREMOVE");
611 if ($command == "" && isset($this->config->data['TABS'])){
612 $command= search_config($this->config->data['TABS'], get_class($this), "POSTREMOVE");
613 }
615 if ($command != ""){
617 /* Additional attributes */
618 foreach ($add_attrs as $name => $value){
619 $command= preg_replace("/%$name/", $value, $command);
620 }
622 /* Walk through attribute list */
623 foreach ($this->attributes as $attr){
624 if (!is_array($this->$attr)){
625 $command= preg_replace("/%$attr/", $this->$attr, $command);
626 }
627 }
628 $command= preg_replace("/%dn/", $this->dn, $command);
630 /* Additional attributes */
631 foreach ($add_attrs as $name => $value){
632 $command= preg_replace("/%$name/", $value, $command);
633 }
635 if (check_command($command)){
636 @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
637 $command, "Execute");
639 exec($command);
640 } else {
641 $message= sprintf(_("Command '%s', specified as POSTREMOVE for plugin '%s' doesn't seem to exist."), $command, get_class($this));
642 print_red ($message);
643 }
644 }
645 }
647 /* Create unique DN */
648 function create_unique_dn($attribute, $base)
649 {
650 $ldap= $this->config->get_ldap_link();
651 $base= preg_replace("/^,*/", "", $base);
653 /* Try to use plain entry first */
654 $dn= "$attribute=".$this->$attribute.",$base";
655 $ldap->cat ($dn, array('dn'));
656 if (!$ldap->fetch()){
657 return ($dn);
658 }
660 /* Look for additional attributes */
661 foreach ($this->attributes as $attr){
662 if ($attr == $attribute || $this->$attr == ""){
663 continue;
664 }
666 $dn= "$attribute=".$this->$attribute."+$attr=".$this->$attr.",$base";
667 $ldap->cat ($dn, array('dn'));
668 if (!$ldap->fetch()){
669 return ($dn);
670 }
671 }
673 /* None found */
674 return ("none");
675 }
677 function rebind($ldap, $referral)
678 {
679 $credentials= LDAP::get_credentials($referral, $this->config->current['REFERRAL']);
680 if (ldap_bind($ldap, $credentials['ADMIN'], $credentials['PASSWORD'])) {
681 $this->error = "Success";
682 $this->hascon=true;
683 $this->reconnect= true;
684 return (0);
685 } else {
686 $this->error = "Could not bind to " . $credentials['ADMIN'];
687 return NULL;
688 }
689 }
691 /* This is a workaround function. */
692 function copy($src_dn, $dst_dn)
693 {
694 /* Rename dn in possible object groups */
695 $ldap= $this->config->get_ldap_link();
696 $ldap->search('(&(objectClass=gosaGroupOfNames)(member='.@LDAP::prepare4filter($src_dn).'))',
697 array('cn'));
698 while ($attrs= $ldap->fetch()){
699 $og= new ogroup($this->config, $ldap->getDN());
700 unset($og->member[$src_dn]);
701 $og->member[$dst_dn]= $dst_dn;
702 $og->save ();
703 }
705 $ldap->cat($dst_dn);
706 $attrs= $ldap->fetch();
707 if (count($attrs)){
708 trigger_error("Trying to overwrite ".@LDAP::fix($dst_dn).", which already exists.",
709 E_USER_WARNING);
710 return (FALSE);
711 }
713 $ldap->cat($src_dn);
714 $attrs= $ldap->fetch();
715 if (!count($attrs)){
716 trigger_error("Trying to move ".@LDAP::fix($src_dn).", which does not seem to exist.",
717 E_USER_WARNING);
718 return (FALSE);
719 }
721 /* Grummble. This really sucks. PHP ldap doesn't support rdn stuff. */
722 $ds= ldap_connect($this->config->current['SERVER']);
723 ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
724 if (function_exists("ldap_set_rebind_proc") && isset($this->config->current['REFERRAL'])) {
725 ldap_set_rebind_proc($ds, array(&$this, "rebind"));
726 }
728 $r=ldap_bind($ds,$this->config->current['ADMIN'], $this->config->current['PASSWORD']);
729 error_reporting (0);
730 $sr=ldap_read($ds, @LDAP::fix($src_dn), "objectClass=*");
732 /* Fill data from LDAP */
733 $new= array();
734 if ($sr) {
735 $ei=ldap_first_entry($ds, $sr);
736 if ($ei) {
737 foreach($attrs as $attr => $val){
738 if ($info = ldap_get_values_len($ds, $ei, $attr)){
739 for ($i= 0; $i<$info['count']; $i++){
740 if ($info['count'] == 1){
741 $new[$attr]= $info[$i];
742 } else {
743 $new[$attr][]= $info[$i];
744 }
745 }
746 }
747 }
748 }
749 }
751 /* close conncetion */
752 error_reporting (E_ALL);
753 ldap_unbind($ds);
755 /* Adapt naming attribute */
756 $dst_name= preg_replace("/^([^=]+)=.*$/", "\\1", $dst_dn);
757 $dst_val = preg_replace("/^[^=]+=([^,+]+).*,.*$/", "\\1", $dst_dn);
758 $new[$dst_name]= @LDAP::fix($dst_val);
760 /* Check if this is a department.
761 * If it is a dep. && there is a , override in his ou
762 * change \2C to , again, else this entry can't be saved ...
763 */
764 if((isset($new['ou'])) &&( preg_match("/\\,/",$new['ou']))){
765 $new['ou'] = preg_replace("/\\\\,/",",",$new['ou']);
766 }
768 /* Save copy */
769 $ldap->connect();
770 $ldap->cd($this->config->current['BASE']);
772 $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $dst_dn));
774 /* FAIvariable=.../..., cn=..
775 could not be saved, because the attribute FAIvariable was different to
776 the dn FAIvariable=..., cn=... */
777 if(in_array_ics("FAIdebconfInfo",$new['objectClass'])){
778 $new['FAIvariable'] = $ldap->fix($new['FAIvariable']);
779 }
780 $ldap->cd($dst_dn);
781 $ldap->add($new);
783 if ($ldap->error != "Success"){
784 trigger_error("Trying to save $dst_dn failed.",
785 E_USER_WARNING);
786 return(FALSE);
787 }
789 return (TRUE);
790 }
793 function move($src_dn, $dst_dn)
794 {
795 /* Copy source to destination */
796 if (!$this->copy($src_dn, $dst_dn)){
797 return (FALSE);
798 }
800 /* Delete source */
801 $ldap= $this->config->get_ldap_link();
802 $ldap->rmdir($src_dn);
803 if ($ldap->error != "Success"){
804 trigger_error("Trying to delete $src_dn failed.",
805 E_USER_WARNING);
806 return (FALSE);
807 }
809 return (TRUE);
810 }
813 /* Move/Rename complete trees */
814 function recursive_move($src_dn, $dst_dn)
815 {
816 /* Check if the destination entry exists */
817 $ldap= $this->config->get_ldap_link();
819 /* Check if destination exists - abort */
820 $ldap->cat($dst_dn, array('dn'));
821 if ($ldap->fetch()){
822 trigger_error("recursive_move $dst_dn already exists.",
823 E_USER_WARNING);
824 return (FALSE);
825 }
827 /* Perform a search for all objects to be moved */
828 $objects= array();
829 $ldap->cd($src_dn);
830 $ldap->search("(objectClass=*)", array("dn"));
831 while($attrs= $ldap->fetch()){
832 $dn= $attrs['dn'];
833 $objects[$dn]= strlen($dn);
834 }
836 /* Sort objects by indent level */
837 asort($objects);
838 reset($objects);
840 /* Copy objects from small to big indent levels by replacing src_dn by dst_dn */
841 foreach ($objects as $object => $len){
842 $src= $object;
843 $dst= preg_replace("/$src_dn$/", "$dst_dn", $object);
844 if (!$this->copy($src, $dst)){
845 return (FALSE);
846 }
847 }
849 /* Remove src_dn */
850 $ldap->cd($src_dn);
851 $ldap->recursive_remove();
852 return (TRUE);
853 }
856 function handle_post_events($mode, $add_attrs= array())
857 {
858 switch ($mode){
859 case "add":
860 $this->postcreate($add_attrs);
861 break;
863 case "modify":
864 $this->postmodify($add_attrs);
865 break;
867 case "remove":
868 $this->postremove($add_attrs);
869 break;
870 }
871 }
874 function saveCopyDialog(){
875 }
878 function getCopyDialog(){
879 return(array("string"=>"","status"=>""));
880 }
883 function PrepareForCopyPaste($source){
884 $todo = $this->attributes;
885 if(isset($this->CopyPasteVars)){
886 $todo = array_merge($todo,$this->CopyPasteVars);
887 }
888 $todo[] = "is_account";
889 foreach($todo as $var){
890 if (isset($source->$var)){
891 $this->$var= $source->$var;
892 }
893 }
894 }
897 function tag_attrs($at, $dn= "", $tag= "", $show= false)
898 {
899 /* No dn? Self-operation... */
900 if ($dn == ""){
901 $dn= $this->dn;
903 /* No tag? Find it yourself... */
904 if ($tag == ""){
905 $len= strlen($dn);
907 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "No tag for $dn - looking for one...", "Tagging");
908 $relevant= array();
909 foreach ($this->config->adepartments as $key => $ntag){
911 /* This one is bigger than our dn, its not relevant... */
912 if ($len <= strlen($key)){
913 continue;
914 }
916 /* This one matches with the latter part. Break and don't fix this entry */
917 if (preg_match('/(^|,)'.normalizePreg($key).'$/', $dn)){
918 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "DEBUG: Possibly relevant: $key", "Tagging");
919 $relevant[strlen($key)]= $ntag;
920 continue;
921 }
923 }
925 /* If we've some relevant tags to set, just get the longest one */
926 if (count($relevant)){
927 ksort($relevant);
928 $tmp= array_keys($relevant);
929 $idx= end($tmp);
930 $tag= $relevant[$idx];
931 $this->gosaUnitTag= $tag;
932 }
933 }
934 }
936 /* Remove tags that may already be here... */
937 remove_objectClass("gosaAdministrativeUnitTag", &$at);
938 if (isset($at['gosaUnitTag'])){
939 unset($at['gosaUnitTag']);
940 }
942 /* Set tag? */
943 if ($tag != ""){
944 add_objectClass("gosaAdministrativeUnitTag", &$at);
945 $at['gosaUnitTag']= $tag;
946 }
947 }
950 function handle_object_tagging($dn= "", $tag= "", $show= false)
951 {
952 //FIXME: How to optimize this? We have at least two
953 // LDAP accesses per object. It would be a good
954 // idea to have it integrated.
956 /* No dn? Self-operation... */
957 if ($dn == ""){
958 $dn= $this->dn;
960 /* No tag? Find it yourself... */
961 if ($tag == ""){
962 $len= strlen($dn);
964 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "No tag for $dn - looking for one...", "Tagging");
965 $relevant= array();
966 foreach ($this->config->adepartments as $key => $ntag){
968 /* This one is bigger than our dn, its not relevant... */
969 if ($len <= strlen($key)){
970 continue;
971 }
973 /* This one matches with the latter part. Break and don't fix this entry */
974 if (preg_match('/(^|,)'.normalizePreg($key).'$/', $dn)){
975 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "DEBUG: Possibly relevant: $key", "Tagging");
976 $relevant[strlen($key)]= $ntag;
977 continue;
978 }
980 }
982 /* If we've some relevant tags to set, just get the longest one */
983 if (count($relevant)){
984 ksort($relevant);
985 $tmp= array_keys($relevant);
986 $idx= end($tmp);
987 $tag= $relevant[$idx];
988 $this->gosaUnitTag= $tag;
989 }
990 }
991 }
994 /* Set tag? */
995 if ($tag != ""){
996 /* Set objectclass and attribute */
997 $ldap= $this->config->get_ldap_link();
998 $ldap->cat($dn, array('gosaUnitTag', 'objectClass'));
999 $attrs= $ldap->fetch();
1000 if(isset($attrs['gosaUnitTag'][0]) && $attrs['gosaUnitTag'][0] == $tag){
1001 if ($show) {
1002 echo sprintf(_("Object '%s' is already tagged"), @LDAP::fix($dn))."<br>";
1003 flush();
1004 }
1005 return;
1006 }
1007 if (count($attrs)){
1008 if ($show){
1009 echo sprintf(_("Adding tag (%s) to object '%s'"), $tag, @LDAP::fix($dn))."<br>";
1010 flush();
1011 }
1012 $nattrs= array("gosaUnitTag" => $tag);
1013 $nattrs['objectClass']= array();
1014 for ($i= 0; $i<$attrs['objectClass']['count']; $i++){
1015 $oc= $attrs['objectClass'][$i];
1016 if ($oc != "gosaAdministrativeUnitTag"){
1017 $nattrs['objectClass'][]= $oc;
1018 }
1019 }
1020 $nattrs['objectClass'][]= "gosaAdministrativeUnitTag";
1021 $ldap->cd($dn);
1022 $ldap->modify($nattrs);
1023 show_ldap_error($ldap->get_error(), _("Handle object tagging failed"));
1024 } else {
1025 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "Not tagging ($tag) $dn - seems to have moved away", "Tagging");
1026 }
1028 } else {
1029 /* Remove objectclass and attribute */
1030 $ldap= $this->config->get_ldap_link();
1031 $ldap->cat($dn, array('gosaUnitTag', 'objectClass'));
1032 $attrs= $ldap->fetch();
1033 if (isset($attrs['objectClass']) && !in_array_ics("gosaAdministrativeUnitTag", $attrs['objectClass'])){
1034 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "$dn is not tagged", "Tagging");
1035 return;
1036 }
1037 if (count($attrs)){
1038 if ($show){
1039 echo sprintf(_("Removing tag from object '%s'"), @LDAP::fix($dn))."<br>";
1040 flush();
1041 }
1042 $nattrs= array("gosaUnitTag" => array());
1043 $nattrs['objectClass']= array();
1044 for ($i= 0; $i<$attrs['objectClass']['count']; $i++){
1045 $oc= $attrs['objectClass'][$i];
1046 if ($oc != "gosaAdministrativeUnitTag"){
1047 $nattrs['objectClass'][]= $oc;
1048 }
1049 }
1050 $ldap->cd($dn);
1051 $ldap->modify($nattrs);
1052 show_ldap_error($ldap->get_error(), _("Handle object tagging failed"));
1053 } else {
1054 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "Not removing tag ($tag) $dn - seems to have moved away", "Tagging");
1055 }
1056 }
1058 }
1061 /* Add possibility to stop remove process */
1062 function allow_remove()
1063 {
1064 $reason= "";
1065 return $reason;
1066 }
1068 }
1069 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1070 ?>