Code

96dc1efc358c0d609c21df6a9a708158e1b8fbaa
[gosa.git] / gosa-core / include / class_gosaSupportDaemon.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  */
23 class gosaSupportDaemon
24 {
25   private $s_host       = "";
26   private $i_port       = 0;
27   private $s_encryption_key = "";
29   private $o_sock       = NULL;
30   private $f_timeout    = 2;
31   private $s_error      = "";
32   private $b_error      = FALSE;
34   private $is_connected     = FALSE;
37   /*! \brief  Creates a new gosaSupportDaemon object.
38     @param string   Host    The Host where the daemon is running on.  
39     @param integer  Port    The port which the daemon use.
40     @param string   Key     The encryption string.
41     @param boolean  Connect Directly connect to daemon socket.
42     @param float    Timeout The timelimit for all socket actions.
43    */
44   public function __construct($connect=TRUE,$timeout=0.2)
45   {
46     #FIXME: bad idea about referencing global variables from within classes
47     global $config;
49     # load from config, store statically
50     if (isset($config->current['GOSA_SI'])){
52       if ($this->s_host == ""){
53         $this->s_host= preg_replace("/^.*@([^:]+):.*$/", "$1", $config->current['GOSA_SI']);
54         $this->i_port= preg_replace("/^.*@[^:]+:(.*)$/", "$1", $config->current['GOSA_SI']);
55         $this->s_encryption_key = preg_replace("/^(.*)@[^:]+:.*$/", "$1", $config->current['GOSA_SI']);
56       }
58       $this->f_timeout = $timeout;
59       if($connect){
60         $this->connect();
61       }
62     }
63   }
66   /*! \brief  Establish daemon connection. 
67     @return boolean Returns true if the connection was succesfully established. 
68    */
69   public function connect()
70   {
71     $this->o_sock = new Socket_Client($this->s_host,$this->i_port,TRUE,$this->f_timeout);
72     if($this->o_sock->connected()){ 
73       $this->o_sock->setEncryptionKey($this->s_encryption_key); 
74       $this->is_connected = TRUE;
75     }else{
76       $this->set_error($this->o_sock->get_error());
77       $this->disconnect();
78     }
79     return($this->is_connected);
80   }
83   /*! \brief  Disconnect from gosa daemon.
84    */
85   public function disconnect()
86   {
87     $this->o_sock->close();
88     $this->is_connected = FALSE;
89   }
92   /*! \brief  Sets an error message, which can be returned with get_error().
93     @param  string  The Error message,
94    */
95   private function set_error($str)
96   {
97     $this->b_error = TRUE;
98     $this->s_error = $str;
99   }
102   /*! \brief  Sets an error message, which can be returned with get_error().
103     @param  string  The Error message,
104    */
105   private function reset_error()
106   {
107     $this->b_error = FALSE;
108     $this->s_error = "";
109   }
112   /*! \brief  Checks if an error occured.
113     @return boolean returns TRUE or FALSE, whether there is an error or not.
114    */
115   public function is_error()
116   {
117     return($this->b_error);
118   }
121   /*! \brief  Returns the last error. 
122     @return Returns the last error.
123    */
124   public function get_error()
125   {
126     $str = $this->s_error;
127     $str = preg_replace("/ /","&nbsp;",$str);
128     return($str);
129   }
132   /*! \brief  Returns an array containing all queued entries.
133     @return Array All queued entries as an array.
134    */
135   public function get_queued_entries($from=-1,$to=-1,$sort="timestamp DESC")
136   {
137     $this->reset_error();
138     $ret = array();
140     $xml_msg = "<xml>
141       <header>gosa_query_jobdb</header>
142       <target>GOSA</target>
143       <source>GOSA</source>
144       <orderby>".$sort."</orderby>";
145 if($from != -1 && $to != -1){
146 $xml_msg.= "
147       <limit>
148        <from>".$from."</from>
149        <to>".$to."</to>
150       </limit>";
152 $xml_msg.= "
153       </xml>";
155     if($this->connect()){
156       $this->o_sock->write($xml_msg);
157       $str = trim($this->o_sock->read());
158       $entries = $this->xml_to_array($str);
159       if(isset($entries['XML']) && is_array($entries['XML'])){
161         /* Check if returned values represent a valid answer */
162         if(isset($entries['XML'])){
163           
164           /* Unset header tags */
165           foreach(array("HEADER","SOURCE","TARGET") as $type){
166             unset($entries['XML'][$type]);
167           }
168           $ret = $entries['XML']; 
169         }
170       }
171     }
172     
173     return($ret);
174   }
177   /*! \brief  Checks if the given ids are used queue ids.
178     @param  Array   The ids we want to check..
179     @return Array   An array containing all ids as index and TRUE/FALSE as value. 
180    */
181   public function ids_exist($ids)
182   {
183     if(!is_array($ids)){
184       trigger_error("Requires an array as parameter.");
185       return;
186     }
187     $this->reset_error();
189     $ret = array();
191     $xml_msg = "<xml>
192       <header>gosa_query_jobdb</header>
193       <target>GOSA</target>
194       <source>GOSA</source>
195       <where>
196       <clause>
197       <connector>or</connector>";
198     foreach($ids as $id){
199       $xml_msg .= "<phrase>
200         <operator>eq</operator>
201         <id>".$id."</id>
202         </phrase>";
203     }
204     $xml_msg .= "</clause>
205       </where>
206       </xml>";
208     if($this->connect()){
209       $this->o_sock->write($xml_msg);
210       $str = trim($this->o_sock->read());
211       $entries = $this->xml_to_array($str);
212       if(isset($entries['XML']) && is_array($entries['XML'])){
213         foreach($entries['XML'] as $entry){
214           if(isset($entry['ID'])){
215             $ret[] = $entry['ID'];
216           }
217         }
218       }
219     }
220     return($ret);
221   }
224   /*! \brief  Returns an entry containing all requested ids.
225     @param  Array   The IDs of the entries we want to return.
226     @return Array   Of the requested entries. 
227    */
228   public function get_entries_by_id($ids)
229   {
230     if(!is_array($ids)){
231       trigger_error("Requires an array as parameter.");
232       return;
233     }
234     $this->reset_error();
236     $ret = array();
238     $xml_msg = "<xml>
239       <header>gosa_query_jobdb</header>
240       <target>GOSA</target>
241       <source>GOSA</source>
242       <where>
243       <clause>
244       <connector>or</connector>";
245     foreach($ids as $id){
246       $xml_msg .= "<phrase>
247         <operator>eq</operator>
248         <id>".$id."</id>
249         </phrase>";
250     }
251     $xml_msg .= "</clause>
252       </where>
253       </xml>";
255     if($this->connect()){
256       $this->o_sock->write($xml_msg);
257       $str = trim($this->o_sock->read());
258       $entries = $this->xml_to_array($str); 
259       if(isset($entries['XML'])){
260         foreach($entries['XML'] as $name => $entry){
261           if(preg_match("/^ANSWER[0-9]*$/",$name)){
262             $ret[$name] = $entry;
263           }
264         }
265       }
266     }
267     return($ret);
268   }
271   /*! \brief  Checks if the given id is in use.
272     @param  Integer The ID of the entry.
273     @return Boolean TRUE if entry exists. 
274    */
275   public function id_exists($id)
276   {
277     if(!is_numeric($id)){
278       trigger_error("Requires an integer as parameter.");
279       return;
280     }
282     $this->reset_error();
284     $xml_msg = "<xml>
285       <header>gosa_query_jobdb</header>
286       <target>GOSA</target>
287       <source>GOSA</source>
288       <where>
289       <clause>
290       <phrase>
291       <operator>eq</operator>
292       <id>".$id."</id>
293       </phrase>
294       </clause>
295       </where>
296       </xml>";
298     if($this->connect()){
299       $this->o_sock->write($xml_msg);
300       $str = trim($this->o_sock->read());
301       $entries = $this->xml_to_array($str); 
302       if( isset($entries['XML']['HEADER']) && 
303           $entries['XML']['HEADER']=="answer" && 
304           isset($entries['XML']['ANSWER1'])){
305         return(TRUE);
306       }
307     }
308     return(FALSE);
309   }
312   /*! \brief  Returns an entry from the gosaSupportQueue
313     @param  Integer The ID of the entry we want to return.
314     @return Array   Of the requested entry. 
315    */
316   public function get_entry_by_id($id)
317   {
318     if(!is_numeric($id)){
319       trigger_error("Requires an integer as parameter.");
320       return;
321     }
322     $this->reset_error();
323   
324     $ret = array();
325     $xml_msg = "<xml>
326       <header>gosa_query_jobdb</header>
327       <target>GOSA</target>
328       <source>GOSA</source>
329       <where>
330       <clause>
331       <phrase>
332       <operator>eq</operator>
333       <id>".$id."</id>
334       </phrase>
335       </clause>
336       </where>
337       </xml>";
338     if($this->connect()){
339       $this->o_sock->write($xml_msg);
340       $str = trim($this->o_sock->read());
341       $entries = $this->xml_to_array($str); 
342       if( isset($entries['XML']['HEADER']) &&
343           $entries['XML']['HEADER']=="answer" &&
344           isset($entries['XML']['ANSWER1'])){
345         $ret = $entries['XML']['ANSWER1'];
346       }
347     }
348     return($ret);
349   }
352   /*! \brief  Removes a set of entries from the GOsa support queue. 
353     @param  Array The IDs to remove.
354     @return Boolean True on success.
355    */
356   public function remove_entries($ids)
357   {
358     if(!is_array($ids)){
359       trigger_error("Requires an array as parameter.");
360       return;
361     }
363     $this->reset_error();
365     $ret = array();
367     $xml_msg = "<xml>
368       <header>gosa_delete_jobdb_entry</header>
369       <target>GOSA</target>
370       <source>GOSA</source>
371       <where>
372       <clause>
373       <connector>or</connector>";
374     foreach($ids as $id){
375       $xml_msg .= "<phrase>
376         <operator>eq</operator>
377         <id>".$id."</id>
378         </phrase>";
379     }
380     $xml_msg .= "</clause>
381       </where>
382       </xml>";
384     if($this->connect()){
385       $this->o_sock->write($xml_msg);
386       $str = $this->o_sock->read();
387       $entries = $this->xml_to_array($str);
388       if(isset($entries['XML'])){
389         return(TRUE);
390       }
391     }
392     return(FALSE);
393   }
397   /*! \brief  Removes an entry from the GOsa support queue. 
398     @param  Integer The ID of the entry we want to remove.
399     @return Boolean True on success.
400    */
401   public function remove_entry($id)
402   {
403     $this->reset_error();
405     $xml_msg = "<xml>
406       <header>gosa_delete_jobdb_entry</header>
407       <target>GOSA</target>
408       <source>GOSA</source>
409       <where>
410       <clause>
411       <phrase>
412       <operator>eq</operator>
413       <id>".$id."</id>
414       </phrase>
415       </clause>
416       </where>
417       </xml>";
418     if($this->connect()){
419       $this->o_sock->write($xml_msg);
420       $str = $this->o_sock->read();
421       $entries = $this->xml_to_array($str);
422       if(isset($entries['XML'])){
423         return(TRUE);
424       }
425     }
426     return(FALSE);
427   }
430   /*! \brief  Parses the given xml string into an array 
431     @param  String XML string  
432     @return Array Returns an array containing the xml structure. 
433    */
434   private function xml_to_array($xml)
435   {
436     $params = array();
437     $level = array();
438     $parser  = xml_parser_create_ns();
439     xml_parse_into_struct($parser, $xml, $vals, $index);
441     $err_id = xml_get_error_code($parser);
442     if($err_id){
443       xml_parser_free($parser);
444     }else{
445       xml_parser_free($parser);
447       foreach ($vals as $xml_elem) {
448         if ($xml_elem['type'] == 'open') {
449           if (array_key_exists('attributes',$xml_elem)) {
450             list($level[$xml_elem['level']],$extra) = array_values($xml_elem['attributes']);
451           } else {
452             $level[$xml_elem['level']] = $xml_elem['tag'];
453           }
454         }
455         if ($xml_elem['type'] == 'complete') {
456           $start_level = 1;
457           $php_stmt = '$params';
458           while($start_level < $xml_elem['level']) {
459             $php_stmt .= '[$level['.$start_level.']]';
460             $start_level++;
461           }
462           $php_stmt .= '[$xml_elem[\'tag\']] = $xml_elem[\'value\'];';
463           @eval($php_stmt);
464         }
465       }
466     }
468     if(!isset($params['XML'])){
469       if (!array_key_exists('XML', $params)){
470         $this->set_error(_("Could not parse XML."));
471       }
472       $params = array("COUNT" => 0);
473     }
475     return($params); 
476   }
479   /*! \brief  Updates an entry with a set of new values, 
480     @param  Integer The ID of the entry, we want to update.
481     @param  Array   The variables to update.   
482     @return Boolean Returns TRUE on success. 
483    */
484   public function update_entries($ids,$data)
485   {
486     $this->reset_error();
487     if(!is_array($ids)){
488       trigger_error("Requires an array as first parameter.");
489       return;
490     }
492     if(!is_array($data)){
493       trigger_error("Requires an array as second parameter.");
494       return;
495     }
497     $attr = "";
498     foreach($data as $key => $value){
499       if(is_array($value)){
500         foreach($value as $sub_value){
501           $attr.= "<$key>".strtolower($sub_value)."</$key>\n";
502         }
503       }else{
504         $attr.= "<$key>".strtolower($value)."</$key>\n";
505       }
506     }
508     $xml_msg = "<xml>
509       <header>gosa_update_status_jobdb_entry</header>
510       <target>GOSA</target>
511       <source>GOSA</source>
512       <where>
513       <clause>
514       <connector>or</connector>";
515     foreach($ids as $id){
516       $xml_msg .= "<phrase>
517         <operator>eq</operator>
518         <id>".$id."</id>
519         </phrase>";
520     }
521     $xml_msg .= "</clause>
522       </where>
523       <update>
524       ".$attr." 
525       </update>
526       </xml>";
528     if($this->connect()){
530       $this->o_sock->write($xml_msg);
531       $str      = trim($this->o_sock->read());
532       $entries = $this->xml_to_array($str);
533       if(isset($entries['XML'])){
534         if(isset($entries['XML']['ERROR_STRING'])) {
535           $this->set_error($entries['XML']['ERROR_STRING']);
536           return(FALSE);
537         }
538         return(TRUE);
539       }
540     }
541     return(FALSE);
542   }
545   /*! \brief  Returns the number of currently queued objects.
546       @return Integer  
547    */
548   public function number_of_queued_entries()
549   {
550     $xml_msg ="<xml><header>gosa_count_jobdb</header><target>GOSA</target><source>GOSA</source></xml>";
551     $this->connect();
552     if($this->connect()){
553       $this->o_sock->write($xml_msg);
554       $str     = trim($this->o_sock->read());
555       $entries = $this->xml_to_array($str);
556       if(isset($entries['XML'])){
557         return($entries['XML']['COUNT']);
558       }
559     }
560     return(-1);
561   } 
564   public function send_data($header, $to, $data= array(), $answer_expected = FALSE)
565   {
566     $xml_message= "";
568     /* Prepare data */
569     foreach ($data as $key => $value){
570       if(is_array($value)){
571         foreach($value as $sub_val){
572           $xml_message.= "<$key>$sub_value</$key>";
573         }
574       }else{
575         $xml_message.= "<$key>$value</$key>";
576       }
577     }
579     /* Multiple targets? */
580     if (!is_array($to)){
581       $to_targets= array($to);
582     } else {
583       $to_targets= $to;
584     }
586     /* Build target strings */
587     $target ="";
588     foreach($to_targets as $to){
589       $target.= "<target>$to</target>";
590     }
592     return $this->_send("<xml><header>$header</header><source>GOSA</source>$target".$xml_message."</xml>",$answer_expected);
593   }
596   /* Allows simply appending a new DaemonEvent 
597    */
598   public function append($event)
599   {
600     if(!($event instanceof DaemonEvent)){
601       return(FALSE);
602     }
603   
604     $this->reset_error();
606     /* Add to queue if new 
607      */
608     if($event->is_new()){
610       if($event->get_type() == SCHEDULED_EVENT){
611         $action = $event->get_schedule_action();
612       }elseif($event->get_type() == TRIGGERED_EVENT){
613         $action = $event->get_schedule_action();
614       }else{
615         trigger_error("Unknown type of queue event given.");
616         return(FALSE);
617       }
619       /* Get event informations, like targets..
620        */
621       $targets    = $event->get_targets();
622       $data       = $event->save();
624       /* Append an entry for each target 
625        */
626       foreach($targets as $target){
627         $data['macaddress'] = $target;
628         $this->send_data($action,$target,$data,TRUE);
630         if($this->is_error()){
631           return(FALSE);
632         }
633       }
634       return(TRUE);
635     }else{
637       /* Updated edited entry.
638        */
639       $id                 = $event->get_id();
640       $data               = $event->save();
641       return($this->update_entries(array($id),$data));
642     }
644     return(FALSE);
645   }
648 /*! \brief  Returns an array containing all queued entries.
649     @return Array All queued entries as an array.
650    */
651   public function _send($data, $answer_expected= FALSE)
652   {
653     $this->reset_error();
654     $ret = array();
656     if($this->connect()){
657       $this->o_sock->write($data);
658       if ($answer_expected){
659         $str = trim($this->o_sock->read());
660         $entries = $this->xml_to_array($str);
661         if(isset($entries['XML']) && is_array($entries['XML'])){
662           $ret = $entries;
663           if(isset($entries['XML']['ERROR_STRING'])) {
664             $this->set_error($entries['XML']['ERROR_STRING']);
665           }
666         }
667       }
668     }
669     return($ret);
670   }
673   static function send($header, $to, $data= array(), $answer_expected = FALSE)
674   {
675     $xml_message= "";
677     /* Get communication object */
678     $d= new gosaSupportDaemon(TRUE,10);
680     /* Prepare data */
681     foreach ($data as $key => $value){
682       if(is_array($value)){
683         foreach($value as $sub_val){
684           $xml_message.= "<$key>$sub_value</$key>";
685         }
686       }else{
687         $xml_message.= "<$key>$value</$key>";
688       }
689     }
691     /* Multiple targets? */
692     if (!is_array($to)){
693       $to_targets= array($to);
694     } else {
695       $to_targets= $to;
696     }
698     /* Build target strings */
699     $target ="";
700     foreach($to_targets as $to){
701       $target.= "<target>$to</target>";
702     }
704     return $d->_send("<xml><header>$header</header><source>GOSA</source>$target".$xml_message."</xml>",$answer_expected);
705   }
708 static function ping($target)
710   if (tests::is_mac($target)){
711     /* Get communication object */
712     $d= new gosaSupportDaemon(TRUE,0.5);
713     $answer= $d->_send("<xml><header>gosa_ping</header><source>GOSA</source><target>$target</target></xml>", TRUE);
714     return (count($answer) ? TRUE:FALSE);
715   }
717   return (FALSE);
722 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
723 ?>