Code

2bde4c9d6535f3871386d8350033d933585d9d2a
[gosa.git] / gosa-plugins / systems / admin / systems / class_systemManagement.inc
1 <?php
2 /*
3  * This code is part of GOsa (http://www.gosa-project.org)
4  * Copyright (C) 2003-2008 GONICUS GmbH
5  *
6  * ID: $$Id$$
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
24 #
25 # NewDevices 
26 # -> Edit
27 #     |- SelectDeviceType()        (Allows to select target SystemType and OGroup)
28 # -> Save
29 #     |-> systemTypeChosen()       (Queue entry to be activated) 
30 #     |-> handleActivationQueue()  (Now acticvate queued objects)
31 #       |-> Ogroup selected   
32 #       | |-> Try to adapt values from ogroup and save directly.
33 #       |
34 #       |-> NO Ogroup selected
35 #       |  |-> Open dialogs of the target system type and allow modifcations.
36 #       |
37 #       |->activate_new_device()   (Finally activate the device - FAIsate=..)
38 #
39 #
40 # NewArpDevices (NewUnknwonDevices )
41 # -> Edit
42 #     |-> editEntry - ArpNewDeviceTabs
43 # -> Save       
44 #     |-> NO gotoIntegeration 
45 #     | |-> Save DHCP and DNS entries, then remove the source entry from ldap.
46 #     |
47 #     |-> gotoIntegration selected (Handle object like a NewDevice now)
48 #     |-> systemTypeChosen()       (Queue entry to be activated)
49 #     |-> handleActivationQueue()  (Now acticvate queued objects)
50 #       |-> Ogroup selected
51 #       | |-> Try to adapt values from ogroup and save directly.
52 #       |
53 #       |-> NO Ogroup selected
54 #       |  |-> Open dialogs of the target system type and allow modifcations.
55 #       |
56 #       |->activate_new_device()   (Finally activate the device - FAIsate=..)
57 #
58  
62 class systemManagement extends management
63 {
64   var $plHeadline     = "Systems";
65   var $plDescription  = "List of systems";
66   var $plIcon  = "plugins/systems/images/plugin.png";
68   // Tab definition 
69   protected $tabClass = "";
70   protected $tabType = "";
71   protected $aclCategory = "";
72   protected $aclPlugin   = "";
73   protected $objectName   = "system";
74   protected $objectInfo = array();
75   protected $opsi = NULL;
76   protected $activationQueue  = array();
78   function __construct($config,$ui)
79   {
80     $this->config = $config;
81     $this->ui = $ui;
83     // Set storage points 
84     $tD = $this->getObjectDefinitions(); 
85     $sP = array();
86     foreach($tD as $entry){
87       if(!empty($entry['ou']))
88         $sP[] = $entry['ou'];
89     }
90     $this->storagePoints = array_unique($sP);
92     // Build filter
93     if (session::global_is_set(get_class($this)."_filter")){
94       $filter= session::global_get(get_class($this)."_filter");
95     } else {
96       $filter = new filter(get_template_path("system-filter.xml", true));
97       $filter->setObjectStorage($this->storagePoints);
98     }
99     $this->setFilter($filter);
101     // Build headpage
102     $headpage = new listing(get_template_path("system-list.xml", true));
103     $headpage->setFilter($filter);
104     $filter->setConverter('INCOMING', 'systemManagement::incomingFilterConverter');
106     // Register Daemon Events
107     if(class_available("DaemonEvent") && class_available("gosaSupportDaemon")){
108       $events = DaemonEvent::get_event_types(SYSTEM_EVENT | HIDDEN_EVENT);
109       foreach($events['TRIGGERED'] as $name => $data){
110         $this->registerAction("T_".$name,"handleEvent");
111         $this->registerAction("S_".$name,"handleEvent");
112       }
113       $this->registerAction("activateMultiple","activateMultiple");
114     }
115     $this->registerAction("saveEvent","saveEventDialog");
116     $this->registerAction("createISO","createISO");
117     $this->registerAction("initiateISOcreation","initiateISOcreation");
118     $this->registerAction("performIsoCreation","performIsoCreation");
119     $this->registerAction("systemTypeChosen","systemTypeChosen");
120     $this->registerAction("handleActivationQueue","handleActivationQueue");
122     $this->registerAction("new_goServer",         "newEntry");
123     $this->registerAction("new_gotoWorkstation",  "newEntry");
124     $this->registerAction("new_gotoTerminal",     "newEntry");
125     $this->registerAction("new_gotoPrinter",      "newEntry");
126     $this->registerAction("new_goFonHardware",    "newEntry");
127     $this->registerAction("new_ieee802Device",    "newEntry");
128     $this->registerAction("new_FAKE_OC_OpsiHost", "newEntry");
130     $this->registerAction("setPassword", "setPassword");
131     $this->registerAction("passwordChangeConfirmed", "passwordChangeConfirmed");
133     // Add copy&paste and snapshot handler.
134     if ($this->config->boolValueIsTrue("main", "copyPaste")){
135       $this->cpHandler = new CopyPasteHandler($this->config);
136     }
137     if($this->config->get_cfg_value("enableSnapshots") == "true"){
138       $this->snapHandler = new SnapshotHandler($this->config);
139     }
141     // Check if we are able to communicate with the GOsa supprot daemon
142     if(class_available("gosaSupportDaemon")){
143       $o = new gosaSupportDaemon();
144       $this->si_active = $o->connect() && class_available("DaemonEvent");
145     }
147     // Check if we are able to communicate with the GOsa supprot daemon
148     if(class_available("opsi")){
149       $this->opsi = new opsi($this->config);
150     }
151     parent::__construct($config, $ui, "systems", $headpage);
152   }
155   function setPassword($action,$target)
156   {
157     if(count($target) == 1){
158       $tDefs= $this->getObjectDefinitions();
159       $headpage = $this->getHeadpage();
160       $dn = array_pop($target);
161       $type = $headpage->getType($dn);
162       $entry = $headpage->getEntry($dn);
163       $ui       = get_userinfo();
164       $smarty = get_smarty();
165       if(in_array("FAKE_OC_PWD_changeAble", $entry['objectClass'])){
166         $acl = $tDefs[$type]['aclCategory'].'/'.$tDefs[$type]['aclClass'];
167         $tabacl   = $ui->get_permissions($dn,$acl,"userPassword");
168         if(preg_match("/w/",$tabacl)){
169           $this->dn= $dn;
170           set_object_info($this->dn);
171           return ($smarty->fetch(get_template_path('password.tpl', TRUE)));
172         }else{
173           msg_dialog::display(_("Permission error"), _("You have no permission to change this password!"), ERROR_DIALOG);
174         }
175       }
176     }
177   }
181 /*! \brief  This method is used to queue and process copy&paste actions.
182    *          Allows to copy, cut and paste mutliple entries at once.
183    *  @param  String  'action'  The name of the action which was the used as trigger.
184    *  @param  Array   'target'  A list of object dns, which should be affected by this method.
185    *  @param  Array   'all'     A combination of both 'action' and 'target'.
186    */
187   function copyPasteHandler($action="",$target=array(),$all=array(),
188       $altTabClass ="", $altTabType = "", $altAclCategory="",$altAclPlugin="")
189   {
190     // Return without any actions while copy&paste handler is disabled.
191     if(!is_object($this->cpHandler))  return("");
193     // Save user input
194     $this->cpHandler->save_object();
196     // Add entries to queue
197     if($action == "copy" || $action == "cut"){
199       $tDefs= $this->getObjectDefinitions();
200       $headpage = $this->getHeadpage();
201       $ui       = get_userinfo();
202       $this->cpHandler->cleanup_queue();
203       foreach($target as $dn){
205         $type = $headpage->getType($dn);
206         $entry = $headpage->getEntry($dn);
207   
208         $aclCategory = $tDefs[$type]['aclCategory'];
209         $aclPlugin = $tDefs[$type]['aclClass'];
210         $tabClass = $tDefs[$type]['tabClass'];
211         $tabType = $tDefs[$type]['tabDesc'];
213         if($action == "copy" && $this->ui->is_copyable($dn,$aclCategory,$aclPlugin)){
214           $this->cpHandler->add_to_queue($dn,"copy",$tabClass,$tabType,$aclCategory,$this);
215           @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$dn,"Entry copied!");
216         }
217         if($action == "cut" && $this->ui->is_cutable($dn,$aclCategory,$aclPlugin)){
218           $this->cpHandler->add_to_queue($dn,"cut",$tabClass,$tabType,$aclCategory,$this);
219           @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$dn,"Entry cutted!");
220         }
221       }
222     }
224     // Initiate pasting
225     if($action == "paste"){
226       $this->cpPastingStarted = TRUE;
227     }
229     // Display any c&p dialogs, eg. object modifications required before pasting.
230     if($this->cpPastingStarted && $this->cpHandler->entries_queued()){
231       $headpage = $this->getHeadpage();
232       $this->cpHandler->SetVar("base",$headpage->getBase());
233       $data = $this->cpHandler->execute();
234       if(!empty($data)){
235         return($data);
236       }
237     }
239     // Automatically disable pasting process since there is no entry left to paste.
240     if(!$this->cpHandler->entries_queued()){
241       $this->cpPastingStarted = FALSE;
242     }
243     return("");
244   }
247   function passwordChangeConfirmed()
248   {
249     $tDefs= $this->getObjectDefinitions();
250     $headpage = $this->getHeadpage();
251     $type = $headpage->getType($this->dn);
252     $entry = $headpage->getEntry($this->dn);
253     $ui       = get_userinfo();
254     $smarty = get_smarty();
256     if(!in_array('FAKE_OC_PWD_changeAble', $entry['objectClass'])){
257       trigger_error("Tried to change pwd, for invalid object!");
258     }elseif ($_POST['new_password'] != $_POST['repeated_password']){
259       msg_dialog::display(_("Error"), 
260           _("The passwords you've entered as 'New password' and 'Repeated password' do not   match!"), ERROR_DIALOG);
261       return($smarty->fetch(get_template_path('password.tpl', TRUE)));
262     }else{
263       $acl = $tDefs[$type]['aclCategory'].'/'.$tDefs[$type]['aclClass'];
264       $tabacl   = $ui->get_permissions($this->dn,$acl,"userPassword");
266       // Check acls
267       if(!preg_match("/w/",$tabacl)){
268         msg_dialog::display(_("Permission error"), _("You have no permission to change this password!"), ERROR_DIALOG);
269       }else{
270         $ldap = $this->config->get_ldap_link();
271         $ldap->cd($this->dn);
272         $ldap->cat($this->dn);
273         $old_attrs = $ldap->fetch();
275         $attrs= array();
276         if ($_POST['new_password'] == ""){
278           /* Remove password attribute
279            */
280           if(in_array("simpleSecurityObject",$old_attrs['objectClass'])){
281             $attrs['objectClass'] = array();
282             for($i = 0 ; $i < $old_attrs['objectClass']['count'] ; $i ++){
283               if(!preg_match("/simpleSecurityObject/i",$old_attrs['objectClass'][$i])){
284                 $attrs['objectClass'][] = $old_attrs['objectClass'][$i];
285               }
286             }
287           }
288           $attrs['userPassword']= array();
289         } else {
291           /* Add/modify password attribute
292            */
293           if(!in_array("simpleSecurityObject",$old_attrs['objectClass'])){
294             $attrs['objectClass'] = array();
295             for($i = 0 ; $i < $old_attrs['objectClass']['count'] ; $i ++){
296               $attrs['objectClass'][] = $old_attrs['objectClass'][$i];
297             }
298             $attrs['objectClass'][] = "simpleSecurityObject";
299           }
301           if(class_available("passwordMethodCrypt")){
302             $pwd_m = new passwordMethodCrypt($this->config);
303             $pwd_m->set_hash("crypt/md5");
304             $attrs['userPassword'] = $pwd_m->generate_hash($_POST['new_password']);
305           }else{
306             msg_dialog::display(_("Password method"),_("Password method crypt is missing. Cannot set system password."));
307             $attrs = array();
308           }
309         }
310         $ldap->modify($attrs);
311         if (!$ldap->success()){
312           msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_MOD, $type));
313         }else{
314           if(class_available($tDefs[$type]['plugClass'])){
315             $plug = $tDefs[$type]['plugClass'];
316             $p = new $plug($this->config,$this->dn);
317             $p->handle_post_events("modify");
318           }
319         }
320         new log("security","systems/".get_class($this),$this->dn,array_keys($attrs),$ldap->get_error());
321       }
322       set_object_info();
323     }
324   }
327   function createISO($action,$target)
328   {
329     if(count($target) == 1){
330       $smarty = get_smarty();
331       $this->dn= array_pop($target);
332       set_object_info($this->dn);
333       return ($smarty->fetch(get_template_path('goto/gencd.tpl', TRUE)));
335     }
336   }
337   
338   function initiateISOcreation()
339   {
340     $smarty = get_smarty();
341     $smarty->assign("src", "?plug=".$_GET['plug']."&amp;PerformIsoCreation");
342     return ($smarty->fetch(get_template_path('goto/gencd_frame.tpl', TRUE)));  
343   }
346   function performIsoCreation()
347   {
348     $return_button   = "<form method='get' action='main.php' target='_parent'>
349       <input type='submit' value='"._("Back")."'>
350       <input type='hidden' name='plug' value='".$_GET['plug']."'/>
351       </form>";
353     $dsc   = array(0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w"));
355     /* Get and check command */
356     $command= $this->config->search("workgeneric", "SYSTEMISOHOOK",array('tabs'));
357     if (check_command($command)){
358       @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, $command, "Execute");
360       /* Print out html introduction */
361       echo '  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
362         <html>
363         <head>
364         <title></title>
365         <style type="text/css">@import url("themes/default/style.css");</style>
366         <script language="javascript" src="include/focus.js" type="text/javascript"></script>
367         </head>
368         <body style="background: none; margin:4px;" id="body" >
369         <pre>';
371       /* Open process handle and check if it is a valid process */
372       $process= proc_open($command." '".$this->dn."'", $dsc, $pipes);
373       if (is_resource($process)) {
374         fclose($pipes[0]);
376         /* Print out returned lines && write JS to scroll down each line */
377         while (!feof($pipes[1])){
378           $cur_dat = fgets($pipes[1], 1024);
379           echo $cur_dat;
380           echo '<script language="javascript" type="text/javascript">scrollDown2();</script>' ;
381           flush();
382         }
383       }
385       /* Get error string && close streams */
386       $buffer= stream_get_contents($pipes[2]);
388       fclose($pipes[1]);
389       fclose($pipes[2]);
390       echo "</pre>";
392       /* Check return code */
393       $ret= proc_close($process);
394       if ($ret != 0){
395         echo "<h1 style='color:red'>"._("Creating the image failed. Please see the report below.")."</h1>";
396         echo "<pre style='color:red'>$buffer</pre>";
397       }
398       echo $return_button."<br>";
399     } else {
400       $tmp= "<h1 style='color:red'>".sprintf(_("Command '%s', specified for ISO creation doesn't seem to exist."), $command)."</h1>";
401       echo $tmp;
402       echo $return_button."<br>";
403     }
405     /* Scroll down completly */
406     echo '<script language="javascript" type="text/javascript">scrollDown2();</script>' ;
407     echo '</body></html>';
408     flush();
409     exit;
410   }
413   /*! \brief    Handle GOsa-si events
414    *            All events are handled here.
415    */
416   function handleEvent($action="",$target=array(),$all=array())
417   {
418     // Detect whether this event is scheduled or triggered.
419     $triggered = TRUE;
420     if(preg_match("/^S_/",$action)){
421       $triggered = FALSE;
422     }
424     // Detect triggere or scheduled actions 
425     $headpage = $this->getHeadpage();
426     if(preg_match("/^[TS]_/", $action)){
428       // Send special reinstall action for opsi hosts
429       $event = preg_replace("/^[TS]_/","",$action); 
430       if($event == "DaemonEvent_reinstall" && $this->si_active && $this->opsi){
431         foreach($target as $key => $dn){
432           $type = $headpage->getType($dn);
434           // Send Reinstall event for opsi hosts
435           if($type == "FAKE_OC_OpsiHost"){
436             $obj = $headpage->getEntry($dn);
437             $this->opsi->job_opsi_install_client($obj['cn'][0],$obj['macAddress'][0]);
438             unset($target[$key]);
439           }
440         }
441       }
442     } 
444     // Now send remaining FAI/GOsa-si events here.
445     if(count($target) && $this->si_active){
446       $mac= array();
448       // Collect target mac addresses
449       $ldap = $this->config->get_ldap_link();
450       $tD = $this->getObjectDefinitions();
451       $events = DaemonEvent::get_event_types(SYSTEM_EVENT);
452       $o_queue = new gosaSupportDaemon();
453       foreach($target as $dn){
454         $type = $headpage->getType($dn);
455         if($tD[$type]['sendEvents']){
456           $obj = $headpage->getEntry($dn);
457           if(isset($obj['macAddress'][0])){
458             $mac[] = $obj['macAddress'][0];
459           }
460         }
461       }
463       /* Skip installation or update trigerred events,
464        *  if this entry is currently processing.
465        */
466       if($triggered && in_array($event,array("DaemonEvent_reinstall","DaemonEvent_update"))){
467         foreach($mac as $key => $mac_address){
468           foreach($o_queue->get_entries_by_mac(array($mac_address)) as $entry){
469             $entry['STATUS'] = strtoupper($entry['STATUS']);
470             if($entry['STATUS'] == "PROCESSING" &&
471                 isset($events['QUEUED'][$entry['HEADERTAG']]) &&
472                 in_array($events['QUEUED'][$entry['HEADERTAG']],array("DaemonEvent_reinstall","DaemonEvent_update"))){
473               unset($mac[$key]);
475               new log("security","systems/".get_class($this),"",array(),"Skip adding 'DaemonEvent::".$type."' for mac '".$mac_address."', there is already a job in progress.");
476               break;
477             }
478           }
479         }
480       }
482       // Prepare event to be added
483       if(count($mac) && isset($events['BY_CLASS'][$event]) && $this->si_active){
484         $event = $events['BY_CLASS'][$event];
485         $this->dialogObject = new $event['CLASS_NAME']($this->config);
486         $this->dialogObject->add_targets($mac);
488         if($triggered){
489           $this->dialogObject->set_type(TRIGGERED_EVENT);
490           $o_queue->append($this->dialogObject);
491           if($o_queue->is_error()){
492             msg_dialog::display(_("Service infrastructure"),msgPool::siError($o_queue->get_error()),ERROR_DIALOG);
493           }else{
494             $this->closeDialogs();
495           }
496         }else{
497           $this->dialogObject->set_type(SCHEDULED_EVENT);
498         }
499       }
500     }
501   }
503   function cancelEdit()
504   {
505     management::cancelEdit();
506     $this->activationQueue = array();
507   }
508   
509   
510   function saveEventDialog()
511   {
512     $o_queue = new gosaSupportDaemon();
513     $o_queue->append($this->dialogObject);
514     if($o_queue->is_error()){
515       msg_dialog::display(_("Service infrastructure"),msgPool::siError($o_queue->get_error()),ERROR_DIALOG);
516     }else{
517       $this->closeDialogs();
518     }
519  
520   }
521  
523   /*! \brief    Update filter part for INCOMING.
524    *            Allows us to search for "systemIncomingRDN".
525    */
526   static function incomingFilterConverter($filter)
527   {
528     $rdn = preg_replace("/^[^=]*=/", "", get_ou('systemIncomingRDN'));
529     $rdn = preg_replace("/,.*$/","",$rdn);
530     return(preg_replace("/%systemIncomingRDN/", $rdn,$filter));
531   }
533  
534   /*! \brief    Queue selected objects to be removed. 
535    *            Checks ACLs, Locks and ask for confirmation.
536    */
537   protected function removeEntryRequested($action="",$target=array(),$all=array())
538   {
539     $disallowed = array();
540     $this->dns = array();
542     @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$target,"Entry removel requested!");
544     // Check permissons for each target
545     $tInfo = $this->getObjectDefinitions();
546     $headpage = $this->getHeadpage();
547     foreach($target as $dn){
548       $type = $headpage->getType($dn);
549       if(!isset($tInfo[$type])){
550         trigger_error("Unknown object type received '".$type."' please update systemManagement::getObjectDefinitions()!");
551       }else{
552         $info = $tInfo[$type];
553         $acl = $this->ui->get_permissions($dn, $info['aclCategory']."/".$info['aclClass']);
554         if(preg_match("/d/",$acl)){
555           $this->dns[] = $dn;
556         }else{
557           $disallowed[] = $dn;
558         }
559       }
560     }
561     if(count($disallowed)){
562       msg_dialog::display(_("Permission"),msgPool::permDelete($disallowed),INFO_DIALOG);
563     }
565     // We've at least one entry to delete.
566     if(count($this->dns)){
568       // check locks
569       if ($user= get_multiple_locks($this->dns)){
570         return(gen_locked_message($user,$this->dns));
571       }
573       // Add locks
574       $dns_names = array();
575       foreach($this->dns as $dn){
576         $dns_names[] =LDAP::fix($dn);
577       }
578       add_lock ($this->dns, $this->ui->dn);
580       // Display confirmation dialog.
581       $smarty = get_smarty();
582       $smarty->assign("info", msgPool::deleteInfo($dns_names,_($this->objectName)));
583       $smarty->assign("multiple", true);
584       return($smarty->fetch(get_template_path('remove.tpl', TRUE)));
585     }
586   }
589   /*! \brief  Object removal was confirmed, now remove the requested entries.
590    *
591    *  @param  String  'action'  The name of the action which was the used as trigger.
592    *  @param  Array   'target'  A list of object dns, which should be affected by this method.
593    *  @param  Array   'all'     A combination of both 'action' and 'target'.
594    */
595   function removeEntryConfirmed($action="",$target=array(),$all=array(),
596       $altTabClass="",$altTabType="",$altAclCategory="")
597   {
598     @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$target,"Entry removel confirmed!");
600     // Check permissons for each target
601     $tInfo = $this->getObjectDefinitions();
602     $headpage = $this->getHeadpage();
603     $disallowed = array();
604     foreach($this->dns as $key => $dn){
605       $type = $headpage->getType($dn);
606       if(!isset($tInfo[$type])){
607         trigger_error("Unknown object type received '".$type."' please update systemManagement::getObjectDefinitions()!");
608       }else{
610         $info = $tInfo[$type];
611         $acl = $this->ui->get_permissions($dn, $info['aclCategory']."/".$info['aclClass']);
612         if(preg_match("/d/",$acl)){
614           // Delete the object
615           $this->dn = $dn;
616           $this->tabObject= new $info['tabClass']($this->config,$this->config->data['TABS'][$info['tabDesc']], 
617               $this->dn, $info['aclCategory'], true, true);
618           $this->tabObject->set_acl_base($this->dn);
619           $this->tabObject->parent = &$this;
620           $this->tabObject->delete ();
622           // Remove the lock for the current object.
623           del_lock($this->dn);
625         }else{
626           $disallowed[] = $dn;
627           new log("security","system/".get_class($this),$dn,array(),"Tried to trick deletion.");
628         }
629       }
630     }
631     if(count($disallowed)){
632       msg_dialog::display(_("Permission"),msgPool::permDelete($disallowed),INFO_DIALOG);
633     }
635     // Cleanup
636     $this->remove_lock();
637     $this->closeDialogs();
638   }
641   /*! \brief  Edit the selected system type.
642    *
643    *  @param  String  'action'  The name of the action which was the used as trigger.
644    *  @param  Array   'target'  A list of object dns, which should be affected by this method.
645    *  @param  Array   'all'     A combination of both 'action' and 'target'.
646    */
647   function editEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory="")
648   {
649     if(count($target) == 1){
650       $tInfo = $this->getObjectDefinitions();
651       $headpage = $this->getHeadpage();
652       $dn = $target[0];
653       $type =$headpage->getType($dn);
654       $tData = $tInfo[$type];
656       if($type == "FAKE_OC_ArpNewDevice"){
657         if(!class_available("ArpNewDeviceTabs")){
658           msg_dialog::display(_("Error"), msgPool::class_not_found("ArpNewDevice"), ERROR_DIALOG);
659         }else{
660           return(management::editEntry($action,$target,$all,"ArpNewDeviceTabs","ARPNEWDEVICETABS","incoming"));
661         }
662       }elseif($type == "FAKE_OC_NewDevice"){
663         if(!class_available("SelectDeviceType")){
664           msg_dialog::display(_("Error"), msgPool::class_not_found("SelectDeviceType"), ERROR_DIALOG);
665         }else{
666           $this->activationQueue[$dn] = array();
667           $this->dialogObject = new SelectDeviceType($this->config,$dn);
668           $this->skipFooter = TRUE;
669           $this->displayApplyBtn = FALSE;
670           // see condition  -$s_action == "::systemTypeChosen"-  for further handling
671         }
672       }else{
673          return(management::editEntry($action,$target,$all,$tData['tabClass'],$tData['tabDesc'],$tData['aclCategory']));
674       }
675     }
676   }
679   /*! \brief  Edit the selected system type.
680    *
681    *  @param  String  'action'  The name of the action which was the used as trigger.
682    *  @param  Array   'target'  A list of object dns, which should be affected by this method.
683    *  @param  Array   'all'     A combination of both 'action' and 'target'.
684    */
685   function newEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory="")
686   {
687     $tInfo = $this->getObjectDefinitions();
688     $info = preg_replace("/^new_/","",$action);
689     if(!isset($tInfo[$info])){
690       trigger_error("Unknown action type '".$action."' cant create a new system!");
691     }else{
692       management::newEntry($action,$target,$all, 
693           $tInfo[$info]['tabClass'],
694           $tInfo[$info]['tabDesc'],
695           $tInfo[$info]['aclCategory']);
696     }
697   }
700   function activateMultiple($action,$target)
701   {
702     $headpage = $this->getHeadpage();
703     foreach($target as $dn) {
704       if($headpage->getType($dn) == "FAKE_OC_NewDevice"){
705         $this->activationQueue[$dn] = array();
706       }
707     }
708     if(count($this->activationQueue)){
709       $this->dialogObject = new SelectDeviceType($this->config, array_keys($this->activationQueue));
710       $this->skipFooter = TRUE;
711     }
712   }
717   function systemTypeChosen()
718   {
719     // Detect the systems target type 
720     $tInfo = $this->getObjectDefinitions();
721     $selected_group = "none";
722     if(isset($_POST['ObjectGroup'])){
723       $selected_group = $_POST['ObjectGroup'];
724     }
725     $selected_system = $_POST['SystemType'];
726     $tmp = array();
727     foreach($this->activationQueue as $dn => $data){
728       $tmp[$dn]['OG'] = $selected_group;
729       $tmp[$dn]['SS'] = $selected_system;
730     }
731     $this->closeDialogs();
732     $this->activationQueue = $tmp;
733     return($this->handleActivationQueue());
734   }
737   function handleActivationQueue()
738   {
739     @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
740         'Entries left: '.count($this->activationQueue), "<b>Handling system activation queue!</b>");
742     if(!count($this->activationQueue)) return("");
744     $ldap     = $this->config->get_ldap_link();
745     $pInfo    = $this->getObjectDefinitions(); 
746     $ui       = get_userinfo();
747     $headpage = $this->getHeadpage();
748     $ldap->cd($this->config->current['BASE']);
750     // Walk through systems to activate
751     while(count($this->activationQueue)){
752  
753       // Get next entry 
754       reset($this->activationQueue);
755       $dn = key($this->activationQueue);
756       $data= $this->activationQueue[$dn];
758       // Validate the given system type.
759       if(!isset($data['SS'])) continue;
760       $sysType = $data['SS'];
761       if(!isset($pInfo[$sysType])){
762         trigger_error('Unknown type \''.$sysType.'\'!');
763         continue;
764       }
765       $type = $pInfo[$sysType];
767       @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
768           $dn, "<b>Try to activate:</b>");
770       // Get target type definition 
771       $plugClass    = $type["plugClass"];
772       $tabClass     = $type["tabClass"];
773       $aclCategory  = $type["aclCategory"];
774       $tabDesc      = $type["tabDesc"];
776       if(!class_available($tabClass)){
777         msg_dialog::display(_("Error"), msgPool::class_not_found($tabclass), ERROR_DIALOG);
778         unset($this->activationQueue[$dn]);
779         continue;
780       }else{
782         @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
783             $sysType, "<b>System type:</b>");
785         // Load permissions for selected 'dn' and check if we're allowed to create this 'dn' 
786         $this->dn = $dn;
787         $acls   = $ui->get_permissions($this->dn,$aclCategory."/".$plugClass);
789         // Check permissions
790         if(!preg_match("/c/",$acls)){
791           unset($this->activationQueue[$dn]);
792           msg_dialog::display(_("Error"), msgPool::permCreate(), ERROR_DIALOG);
794           @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
795               $acls, "<b>Insufficient permissions!</b>");
796           continue;
797         }else{
799           // Open object an preset some values like the objects base 
800           del_lock($dn);
801           management::editEntry('editEntry',array($dn),array(),$tabClass,$tabDesc, $aclCategory);
802           $this->displayApplyBtn = FALSE;
803           $this->tabObject->set_acl_base($headpage->getBase());
805           @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
806               $data['OG'], "<b>Selected ogroup:</b>");
808           if($data['OG'] != "none"){
809             $this->tabObject->base = preg_replace("/^[^,]+,".preg_quote(get_ou('ogroupRDN'), '/')."/i", "", $data['OG']);
810             $this->tabObject->by_object[$plugClass]->base = $this->tabObject->base;
811           } else {
812             $this->tabObject->by_object[$plugClass]->base = $headpage->getBase();
813             $this->tabObject->base = $headpage->getBase();
814           }
816           // Assign some default values for opsi hosts
817           if($this->tabObject instanceOf opsi_tabs){
818             $ldap = $this->config->get_ldap_link();
819             $ldap->cat($dn);
820             $source_attrs = $ldap->fetch();
821             foreach(array("macAddress" => "mac" ,"cn" => "hostId","description" => "description") as $src => $attr){
822               if(isset($source_attrs[$src][0])){
823                 $this->tabObject->by_object['opsiGeneric']->$attr = $source_attrs[$src][0];
824               }
825             }
826             @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
827                 "", "<b>OPSI attributes adapted</b>");
828           }
830           // Queue entry to be activated, when it is saved.
831           if($data['OG'] != "none"){
833             // Set gotoMode to active if there was an ogroup selected.
834             $found = false;
835             foreach(array("workgeneric"=>"active","servgeneric"=>"active","termgeneric"=>"active") as $tab => $value){
836               if(isset($this->tabObject->by_object[$tab]->gotoMode)) {
837                 $found = true;
838                 $this->tabObject->by_object[$tab]->gotoMode = $value;
839                 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
840                     $tab."->gotoMode = {$value}", "<b>Setting gotoMode to: </b>");
841               }
842             }
843             if(!$found){
844               msg_dialog::display(_("Internal error"), _("Cannot set mode to 'active'!"), ERROR_DIALOG);
845             }
847             // Update object group membership
848             $og = new ogroup($this->config,$data['OG']);
849             if($og){
850               $og->AddDelMembership($this->tabObject->dn);
851               $og->save();
852               @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
853                   $og->dn, "<b>Adding system to ogroup</b>");
854             }
856             // Set default system specific attributes
857             foreach (array("workgeneric", "termgeneric") as $cls){
858               if (isset($this->tabObject->by_object[$cls])){
859                 $this->tabObject->by_object[$cls]->set_everything_to_inherited();
860                 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
861                     $og->dn, "<b>Calling {$cls}->set_everything_to_inherited()</b>");
862               }
863             }
865             // Enable activation
866             foreach (array("servgeneric", "workgeneric", "termgeneric") as $cls){
867               if (isset($this->tabObject->by_object[$cls])){
868                 $this->tabObject->by_object[$cls]->auto_activate= TRUE;
869                 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
870                     $cls, "<b>Setting auto_activate=TRUE for</b>");
871               }
872             }
874             // Enable sending of LDAP events
875             if (isset($this->tabObject->by_object["workstartup"])){
876               $this->tabObject->by_object["workstartup"]->gotoLdap_inherit= TRUE;
877               @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
878                   "", "<b>Setting workstartup->gotoLdap_inherit=TRUE</b>");
879             }
880           }
882           // Try to inherit everythin from the selected object group and then save
883           //  the entry, normally this should work without any problems. 
884           // But if there is any, then display the dialogs.
885           if($data['OG'] != "none"){
886             $str = $this->saveChanges();
888             // There was a problem, skip activation here and allow to fix the problems..
889             if(is_object($this->tabObject)){
890               @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
891                   "", "<b>Automatic saving failed, let the user fix the issues now.</b>");
892               return;
893             }
894             @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
895                 "", "<b>System activated!</b>");
896           }else{
897             @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
898                 "", "<b>Open dialogs now</b>");
899             return;
900           }
901         }
902       }
903     }
904   }
907   protected function saveChanges()
908   {
909     @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
910         get_class($this->tabObject).": ".$this->tabObject->dn, "<b>Save</b>");
911  
912     // Handle 'New Unknown Devices' here.
913     if($this->tabObject instanceOf ArpNewDeviceTabs){
914       $this->tabObject->save_object();
916       if($this->tabObject->by_object['ArpNewDevice']->gotoIntegration){
917         $message = $this->tabObject->check();
918         if(count($message)){
919           msg_dialog::displayChecks($message);
920         }else{
921           @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
922               get_class($this->tabObject).": ".$this->tabObject->dn, "<b>Queued for goto activation</b>");
923           $this->tabObject->save();
924           $this->activationQueue[$this->tabObject->dn]=array();
925           $this->closeDialogs();
926           $this->systemTypeChosen();
927         }
928         return;
929       }
930     }
932     //
933     $str = management::saveChanges();
934     if($this->tabObject) return("");
936     if(isset($this->activationQueue[$this->last_dn])){
937       $dn = $this->last_tabObject->dn;
938       $this->activate_new_device($dn);
939       unset($this->activationQueue[$this->last_dn]);
940     }
942     /* Post handling for activated systems
943        target opsi -> Remove source.
944        target gosa -> Activate system.
945      */
946     if($this->last_tabObject instanceOf opsi_tabs){
947       $ldap = $this->config->get_ldap_link();
948       $ldap->cd($this->config->current['BASE']);
949       $ldap->rmdir ($this->last_tabObject->dn);
950       @DEBUG(DEBUG_LDAP,__LINE__, __FUNCTION__, __FILE__,
951           "Source removed: ".$this->tabObject->dn,"<b>Opsi host activated</b>");
953       $hostId =  $this->last_tabObject->by_object['opsiGeneric']->hostId;
954       $mac    =  $this->last_tabObject->by_object['opsiGeneric']->mac;
955       $this->opsi->job_opsi_activate_client($hostId,$mac);
957     }elseif(isset($this->last_tabObject->was_activated) && $this->last_tabObject->was_activated){
958       $this->activate_new_device($this->last_tabObject->dn);
959     }
961     // Avoid using values from an older input dialog
962     $_POST = array();
963     $this->handleActivationQueue();
964   }
967   protected function applyChanges()
968   {
969     $str = management::applyChanges();
970     if($str) return($str);
972     /* Post handling for activated systems
973        target opsi -> Remove source.
974        target gosa -> Activate system.
975      */
976     if($this->tabObject instanceOf opsi_tabs){
977       $ldap = $this->config->get_ldap_link();
978       $ldap->cd($this->config->current['BASE']);
979       $ldap->rmdir ($this->tabObject->dn);
980       @DEBUG(DEBUG_LDAP,__LINE__, __FUNCTION__, __FILE__,
981           "Source removed: ".$this->tabObject->dn,"<b>Opsi host activated</b>");
983       $hostId =  $this->tabObject->by_object['opsiGeneric']->hostId;
984       $mac    =  $this->tabObject->by_object['opsiGeneric']->mac;
985       $this->opsi->job_opsi_activate_client($hostId,$mac);
987     }elseif(isset($this->tabObject->was_activated) && $this->tabObject->was_activated){
988       $this->activate_new_device($this->tabObject->dn);
989     }
990   }
991   
993   /*! \brief  Sets FAIstate to "install" for "New Devices".
994     This function is some kind of "Post handler" for activated systems,
995     it is called directly after the object (workstabs,servtabs) gets saved.
996     @param  String  $dn   The dn of the newly activated object.
997     @return Boolean TRUE if activated else FALSE
998    */
999   function activate_new_device($dn)
1000   {
1001     @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
1002         $dn, "<b>Activating system:</b>");
1003     $ldap = $this->config->get_ldap_link();
1004     $ldap->cd($this->config->current['BASE']);
1005     $ldap->cat($dn);
1006     if($ldap->count()){
1007       $attrs = $ldap->fetch();
1008       if(count(array_intersect(array('goServer','gotoWorkstation'), $attrs['objectClass']))){
1009         $ocs = $attrs['objectClass'];
1010         unset($ocs['count']);
1011         $new_attrs = array();
1012         if(!in_array("FAIobject",$ocs)){
1013           $ocs[] = "FAIobject";
1014           $new_attrs['objectClass'] = $ocs;
1015         }
1016         $new_attrs['FAIstate'] = "install";
1017         $ldap->cd($dn);
1018         $ldap->modify($new_attrs);
1019         if (!$ldap->success()){
1020           msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn,
1021                 LDAP_MOD, "activate_new_device($dn)"));
1022           @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
1023               $dn, "<b>Failed!</b>");
1024         }else{
1025           @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
1026               $dn, "<b>Success</b>");
1027           return(TRUE);
1028         }
1029       }else{
1030         @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
1031             $dn, "<b>FAIstate not set to install, this is only done for gotoWorkstation/goServer!</b>");
1032       }
1033     }
1034     return(FALSE);
1035   }
1039  /*! \brief  Detects actions/events send by the ui
1040    *           and the corresponding targets.
1041    */
1042   function detectPostActions()
1043   {
1044     $action= management::detectPostActions();
1045     if(isset($_POST['abort_event_dialog']))  $action['action'] = "cancel";
1046     if(isset($_POST['save_event_dialog']))  $action['action'] = "saveEvent";
1047     if(isset($_POST['cd_create']))  $action['action'] = "initiateISOcreation";
1048     if(isset($_GET['PerformIsoCreation']))  $action['action'] = "performIsoCreation";
1049     if(isset($_POST['SystemTypeAborted']))  $action['action'] = "cancel";
1050     if(isset($_POST['password_cancel']))  $action['action'] = "cancel";
1051     if(isset($_POST['password_finish']))  $action['action'] = "passwordChangeConfirmed";
1053     if(isset($_POST['new_goServer']))  $action['action'] = "new_goServer";
1054     if(isset($_POST['new_gotoWorkstation']))  $action['action'] = "new_gotoWorkstation";
1055     if(isset($_POST['new_gotoTerminal']))  $action['action'] = "new_gotoTerminal";
1056     if(isset($_POST['new_gotoPrinter']))  $action['action'] = "new_gotoPrinter";
1057     if(isset($_POST['new_goFonHardware']))  $action['action'] = "new_goFonHardware";
1058     if(isset($_POST['new_ieee802Device']))  $action['action'] = "new_ieee802Device";
1059     if(isset($_POST['new_FAKE_OC_OpsiHost']))  $action['action'] = "new_FAKE_OC_OpsiHost";
1061     if(!is_object($this->tabObject) && !is_object($this->dialogObject)){
1062       if(count($this->activationQueue)) $action['action'] = "handleActivationQueue";
1063     }
1065     if(isset($_POST['systemTypeChosen']))  $action['action'] = "systemTypeChosen";
1067     return($action);
1068   }
1071   /*! \brief   Overridden render method of class management.
1072    *            this allows us to add a release selection box.
1073    */
1074   function renderList()
1075   {
1076     $headpage = $this->getHeadpage();
1077     $headpage->update();
1079     $tD = $this->getObjectDefinitions();
1080     $smarty = get_smarty();
1081     foreach($tD as $name => $obj){
1082       $smarty->assign("USE_".$name, (empty($obj['TABNAME']) || class_available($obj['TABNAME'])));
1083     }
1085     $display = $headpage->render();
1086     return($this->getHeader().$display);
1087   }
1090   public function getObjectDefinitions()
1091   {
1092     $tabs = array(
1093         "FAKE_OC_OpsiHost" => array(
1094           "ou"          => "",
1095           "plugClass"   => "opsiGeneric",
1096           "tabClass"    => "opsi_tabs",
1097           "tabDesc"     => "OPSITABS",
1098           "aclClass"    => "opsiGeneric",
1099           "sendEvents"  => TRUE,
1100           "aclCategory" => "opsi"),
1102         "goServer" => array(
1103           "ou"          => get_ou('serverRDN'),
1104           "plugClass"   => "servgeneric",
1105           "tabClass"    => "servtabs",
1106           "tabDesc"     => "SERVTABS",
1107           "aclClass"    => "servgeneric",
1108           "sendEvents"  => TRUE,
1109           "aclCategory" => "server"),
1111         "gotoWorkstation" => array(
1112           "ou"          => get_ou('workstationRDN'),
1113           "plugClass"   => "workgeneric",
1114           "tabClass"    => "worktabs",
1115           "tabDesc"     => "WORKTABS",
1116           "aclClass"    => "workstation",
1117           "sendEvents"  => TRUE,
1118           "aclCategory" => "workgeneric"),
1120         "gotoTerminal" => array(
1121             "ou"          => get_ou('terminalRDN'),
1122             "plugClass"   => "termgeneric",
1123             "tabClass"    => "termtabs",
1124             "sendEvents"  => TRUE,
1125             "tabDesc"     => "TERMTABS",
1126             "aclClass"    => "terminal",
1127             "aclCategory" => "termgeneric"),
1129         "gotoPrinter" => array(
1130             "ou"          => get_ou('printerRDN'),
1131             "plugClass"   => "printgeneric",
1132             "tabClass"    => "printtabs",
1133             "tabDesc"     => "PRINTTABS",
1134             "aclClass"    => "printer",
1135             "sendEvents"  => FALSE,
1136             "aclCategory" => "printgeneric"),
1138         "FAKE_OC_NewDevice" => array(
1139             "ou"          => get_ou('systemIncomingRDN'),
1140             "plugClass"   => "termgeneric",
1141             "tabClass"    => "termtabs",
1142             "sendEvents"  => TRUE,
1143             "tabDesc"     => "TERMTABS",
1144             "aclClass"    => "terminal",
1145             "aclCategory" => "termgeneric"),
1147         "goFonHardware" => array(
1148             "ou"          => get_ou('phoneRDN'),
1149             "plugClass"   => "phoneGeneric",
1150             "tabClass"    => "phonetabs",
1151             "tabDesc"     => "PHONETABS",
1152             "sendEvents"  => FALSE,
1153             "aclClass"    => "phone",
1154             "aclCategory" => "phoneGeneric"),
1156         "FAKE_OC_winstation" => array(
1157             "ou"          => get_winstations_ou(),
1158             "plugClass"   => "wingeneric",
1159             "sendEvents"  => TRUE,
1160             "tabClass"    => "wintabs",
1161             "tabDesc"     => "WINTABS",
1162             "aclClass"    => "wingeneric",
1163             "aclCategory" => "winworkstation"),
1165         "ieee802Device" => array(
1166             "ou"          => get_ou('componentRDN'),
1167             "plugClass"   => "componentGeneric",
1168             "sendEvents"  => FALSE,
1169             "tabClass"    => "componenttabs",
1170             "tabDesc"     => "COMPONENTTABS",
1171             "aclClass"    => "componentGeneric",
1172             "aclCategory" => "component"),
1173         );
1175     // Now map some special types
1176     $tabs['FAKE_OC_NewWorkstation'] = &$tabs['gotoWorkstation'];
1177     $tabs['FAKE_OC_NewTerminal'] = &$tabs['gotoTerminal'];
1178     $tabs['FAKE_OC_NewServer'] = &$tabs['gotoWorkstation'];
1179     $tabs['gotoWorkstation__IS_BUSY'] = &$tabs['gotoWorkstation'];
1180     $tabs['gotoWorkstation__IS_ERROR'] = &$tabs['gotoWorkstation'];
1181     $tabs['gotoWorkstation__IS_LOCKED'] = &$tabs['gotoWorkstation'];
1182     $tabs['gotoTerminal__IS_BUSY'] = &$tabs['gotoTerminal'];
1183     $tabs['gotoTerminal__IS_ERROR'] = &$tabs['gotoTerminal'];
1184     $tabs['gotoTerminal__IS_LOCKED'] = &$tabs['gotoTerminal'];
1185     $tabs['goServer__IS_BUSY'] = &$tabs['goServer'];
1186     $tabs['goServer__IS_ERROR'] = &$tabs['goServer'];
1187     $tabs['goServer__IS_LOCKED'] = &$tabs['goServer'];
1189     $tabs['FAKE_OC_ArpNewDevice'] = &$tabs['FAKE_OC_NewDevice'];
1191     return($tabs);
1192   }
1193
1194 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1195 ?>