Code

Branch for testing
[gosa.git] / include / class_plugin.inc
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         }
272     
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 &nbsp; in between the ...option>&nbsp;</option.. because there is no value=".." specified in these option fields  
277          * This &nbsp; 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);
300     
301     $tmp= $ldap->fetch ();
302     
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])){
341           
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])){
350           
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])){
369           
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";
403         
404         /* ... objectClasses */
405         foreach ($this->objectclasses as $oc){
406           $ldif.= "objectClass: $oc\n";
407         }
408         
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]);
432           
433           $result= stream_get_contents($pipes[1]);
434           if ($result != ""){
435             $message[]= $result;
436           }
437           
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\">&nbsp;</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     
742     $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $dst_dn));
744     /* FAIvariable=.../..., cn=.. 
745         could not be saved, because the attribute FAIvariable was different to 
746         the dn FAIvariable=..., cn=... */
747     if(in_array_ics("FAIdebconfInfo",$new['objectClass'])){
748       $new['FAIvariable'] = $ldap->fix($new['FAIvariable']);
749     }
750     $ldap->cd($dst_dn);
751     $ldap->add($new);
753     if ($ldap->error != "Success"){
754       trigger_error("Trying to save $dst_dn failed.",
755           E_USER_WARNING);
756       return(FALSE);
757     }
759     return (TRUE);
760   }
763   function move($src_dn, $dst_dn)
764   {
765     /* Copy source to destination */
766     if (!$this->copy($src_dn, $dst_dn)){
767       return (FALSE);
768     }
770     /* Delete source */
771     $ldap= $this->config->get_ldap_link();
772     $ldap->rmdir($src_dn);
773     if ($ldap->error != "Success"){
774       trigger_error("Trying to delete $src_dn failed.",
775           E_USER_WARNING);
776       return (FALSE);
777     }
779     return (TRUE);
780   }
783   /* Move/Rename complete trees */
784   function recursive_move($src_dn, $dst_dn)
785   {
786     /* Check if the destination entry exists */
787     $ldap= $this->config->get_ldap_link();
789     /* Check if destination exists - abort */
790     $ldap->cat($dst_dn, array('dn'));
791     if ($ldap->fetch()){
792       trigger_error("recursive_move $dst_dn already exists.",
793           E_USER_WARNING);
794       return (FALSE);
795     }
797     /* Perform a search for all objects to be moved */
798     $objects= array();
799     $ldap->cd($src_dn);
800     $ldap->search("(objectClass=*)", array("dn"));
801     while($attrs= $ldap->fetch()){
802       $dn= $attrs['dn'];
803       $objects[$dn]= strlen($dn);
804     }
806     /* Sort objects by indent level */
807     asort($objects);
808     reset($objects);
810     /* Copy objects from small to big indent levels by replacing src_dn by dst_dn */
811     foreach ($objects as $object => $len){
812       $src= $object;
813       $dst= preg_replace("/$src_dn$/", "$dst_dn", $object);
814       if (!$this->copy($src, $dst)){
815         return (FALSE);
816       }
817     }
819     /* Remove src_dn */
820     $ldap->cd($src_dn);
821     $ldap->recursive_remove();
822     return (TRUE);
823   }
826   function handle_post_events($mode, $add_attrs= array())
827   {
828     switch ($mode){
829       case "add":
830         $this->postcreate($add_attrs);
831       break;
833       case "modify":
834         $this->postmodify($add_attrs);
835       break;
837       case "remove":
838         $this->postremove($add_attrs);
839       break;
840     }
841   }
844   function saveCopyDialog(){
845   }
848   function getCopyDialog(){
849     return(array("string"=>"","status"=>""));
850   }
853   function PrepareForCopyPaste($source){
854     $todo = $this->attributes;
855     if(isset($this->CopyPasteVars)){
856       $todo = array_merge($todo,$this->CopyPasteVars);
857     }
858     $todo[] = "is_account";
859     foreach($todo as $var){
860       $this->$var = $source->$var;
861     }
862   }
865   function handle_object_tagging($dn= "", $tag= "", $show= false)
866   {
867     //FIXME: How to optimize this? We have at least two
868     //       LDAP accesses per object. It would be a good
869     //       idea to have it integrated.
870   
871     /* No dn? Self-operation... */
872     if ($dn == ""){
873       $dn= $this->dn;
874     
875       /* No tag? Find it yourself... */
876       if ($tag == ""){
877         $len= strlen($dn);
879         @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "No tag for $dn - looking for one...", "Tagging");
880         $relevant= array();
881         foreach ($this->config->adepartments as $key => $ntag){
883           /* This one is bigger than our dn, its not relevant... */
884           if ($len <= strlen($key)){
885             continue;
886           }
888           /* This one matches with the latter part. Break and don't fix this entry */
889           if (preg_match('/(^|,)'.normalizePreg($key).'$/', $dn)){
890             @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "DEBUG: Possibly relevant: $key", "Tagging");
891             $relevant[strlen($key)]= $ntag;
892             continue;
893           }
895         }
897         /* If we've some relevant tags to set, just get the longest one */
898         if (count($relevant)){
899           ksort($relevant);
900           $tmp= array_keys($relevant);
901           $idx= end($tmp);
902           $tag= $relevant[$idx];
903           $this->gosaUnitTag= $tag;
904         }
905       }
906     }
907  
909     /* Set tag? */
910     if ($tag != ""){
911       /* Set objectclass and attribute */
912       $ldap= $this->config->get_ldap_link();
913       $ldap->cat($dn, array('gosaUnitTag', 'objectClass'));
914       $attrs= $ldap->fetch();
915       if(isset($attrs['gosaUnitTag'][0]) && $attrs['gosaUnitTag'][0] == $tag){
916         if ($show) {
917           echo sprintf(_("Object '%s' is already tagged"), @LDAP::fix($dn))."<br>";
918           flush();
919         }
920         return;
921       }
922       if (count($attrs)){
923         if ($show){
924           echo sprintf(_("Adding tag (%s) to object '%s'"), $tag, @LDAP::fix($dn))."<br>";
925           flush();
926         }
927         $nattrs= array("gosaUnitTag" => $this->gosaUnitTag);
928         $nattrs['objectClass']= array();
929         for ($i= 0; $i<$attrs['objectClass']['count']; $i++){
930           $oc= $attrs['objectClass'][$i];
931           if ($oc != "gosaAdministrativeUnitTag"){
932             $nattrs['objectClass'][]= $oc;
933           }
934         }
935         $nattrs['objectClass'][]= "gosaAdministrativeUnitTag";
936         $ldap->cd($dn);
937         $ldap->modify($nattrs);
938         show_ldap_error($ldap->get_error(), _("Handle object tagging failed"));
939       } else {
940         @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "Not tagging ($tag) $dn - seems to have moved away", "Tagging");
941       }
942       
943     } else {
944       /* Remove objectclass and attribute */
945       $ldap= $this->config->get_ldap_link();
946       $ldap->cat($dn, array('gosaUnitTag', 'objectClass'));
947       $attrs= $ldap->fetch();
948       if (isset($attrs['objectClass']) && !in_array_ics("gosaAdministrativeUnitTag", $attrs['objectClass'])){
949         @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "$dn is not tagged", "Tagging");
950         return;
951       }
952       if (count($attrs)){
953         if ($show){
954           echo sprintf(_("Removing tag from object '%s'"), @LDAP::fix($dn))."<br>";
955           flush();
956         }
957         $nattrs= array("gosaUnitTag" => array());
958         $nattrs['objectClass']= array();
959         for ($i= 0; $i<$attrs['objectClass']['count']; $i++){
960           $oc= $attrs['objectClass'][$i];
961           if ($oc != "gosaAdministrativeUnitTag"){
962             $nattrs['objectClass'][]= $oc;
963           }
964         }
965         $ldap->cd($dn);
966         $ldap->modify($nattrs);
967         show_ldap_error($ldap->get_error(), _("Handle object tagging failed"));
968       } else {
969         @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "Not removing tag ($tag) $dn - seems to have moved away", "Tagging");
970       }
971     }
972     
973   }
976 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
977 ?>