96dc1efc358c0d609c21df6a9a708158e1b8fbaa
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("/ /"," ",$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>";
151 }
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'])){
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 }
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();
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 }
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)
709 {
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);
718 }
720 }
722 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
723 ?>