80b214451c10f58d05de6984df66e304e9b856ed
1 <?php
2 /*
4 This code is part of GOsa (https://gosa.gonicus.de)
5 Copyright (C) 2008 Fabian Hickert
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 Function overview:
24 __construct - Create a new daemon handle.
25 connect - Connect to daemon socket.
26 disconnect - Disconnect from socket.
27 set_error - Sets a new error.
28 is_error - Returns TRUE if there was an error.
29 get_error - Returns the last error or "".
30 get_queued_entries - Returns all queued entries, with limitations.
31 ids_exist - Checks if the given id exists.
32 get_entries_by_id - Returns a set of entries.
33 id_exists - Checks if a set entries exists.
34 get_entry_by_id - Returns a single entry.
35 remove_entries - Remove a set of entries.
36 remove_entry - Removes a single entry.
37 update_entries - Updates a set of entries.
38 xml_to_array - XML to Array.
39 number_of_queued_entries - Returns the number of currently queued entries.
40 */
42 class gosaSupportDaemon
43 {
44 private $s_host = "";
45 private $i_port = 0;
46 private $s_encryption_key = "";
48 private $o_sock = NULL;
49 private $f_timeout = 2;
50 private $s_error = "";
51 private $b_error = FALSE;
53 private $is_connected = FALSE;
56 /*! \brief Creates a new gosaSupportDaemon object.
57 @param string Host The Host where the daemon is running on.
58 @param integer Port The port which the daemon use.
59 @param string Key The encryption string.
60 @param boolean Connect Directly connect to daemon socket.
61 @param float Timeout The timelimit for all socket actions.
62 */
63 public function __construct($connect=TRUE,$timeout=0.2)
64 {
65 #FIXME: bad idea about referencing global variables from within classes
66 global $config;
68 # load from config, store statically
69 if (isset($config->current['GOSA_SI'])){
71 if ($this->s_host == ""){
72 $this->s_host= preg_replace("/^.*@([^:]+):.*$/", "$1", $config->current['GOSA_SI']);
73 $this->i_port= preg_replace("/^.*@[^:]+:(.*)$/", "$1", $config->current['GOSA_SI']);
74 $this->s_encryption_key = preg_replace("/^(.*)@[^:]+:.*$/", "$1", $config->current['GOSA_SI']);
75 }
77 $this->f_timeout = $timeout;
78 if($connect){
79 $this->connect();
80 }
81 }
82 }
85 /*! \brief Establish daemon connection.
86 @return boolean Returns true if the connection was succesfully established.
87 */
88 public function connect()
89 {
90 $this->o_sock = new Socket_Client($this->s_host,$this->i_port,TRUE,$this->f_timeout);
91 if($this->o_sock->connected()){
92 $this->o_sock->setEncryptionKey($this->s_encryption_key);
93 $this->is_connected = TRUE;
94 }else{
95 $this->set_error($this->o_sock->get_error());
96 $this->disconnect();
97 }
98 return($this->is_connected);
99 }
102 /*! \brief Disconnect from gosa daemon.
103 */
104 public function disconnect()
105 {
106 $this->o_sock->close();
107 $this->is_connected = FALSE;
108 }
111 /*! \brief Sets an error message, which can be returned with get_error().
112 @param string The Error message,
113 */
114 private function set_error($str)
115 {
116 $this->b_error = TRUE;
117 $this->s_error = $str;
118 }
121 /*! \brief Sets an error message, which can be returned with get_error().
122 @param string The Error message,
123 */
124 private function reset_error()
125 {
126 $this->b_error = FALSE;
127 $this->s_error = "";
128 }
131 /*! \brief Checks if an error occured.
132 @return boolean returns TRUE or FALSE, whether there is an error or not.
133 */
134 public function is_error()
135 {
136 return($this->b_error);
137 }
140 /*! \brief Returns the last error.
141 @return Returns the last error.
142 */
143 public function get_error()
144 {
145 $str = $this->s_error;
146 $str = preg_replace("/ /"," ",$str);
147 return($str);
148 }
151 /*! \brief Returns an array containing all queued entries.
152 @return Array All queued entries as an array.
153 */
154 public function get_queued_entries($from=-1,$to=-1,$sort="timestamp DESC")
155 {
156 $this->reset_error();
157 $ret = array();
159 $xml_msg = "<xml>
160 <header>gosa_query_jobdb</header>
161 <target>GOSA</target>
162 <source>GOSA</source>
163 <orderby>".$sort."</orderby>";
164 if($from != -1 && $to != -1){
165 $xml_msg.= "
166 <limit>
167 <from>".$from."</from>
168 <to>".$to."</to>
169 </limit>";
170 }
171 $xml_msg.= "
172 </xml>";
174 if($this->connect()){
175 $this->o_sock->write($xml_msg);
176 $str = trim($this->o_sock->read());
177 $entries = $this->xml_to_array($str);
178 if(isset($entries['XML']) && is_array($entries['XML'])){
180 /* Check if returned values represent a valid answer */
181 if(isset($entries['XML'])){
183 /* Unset header tags */
184 foreach(array("HEADER","SOURCE","TARGET") as $type){
185 unset($entries['XML'][$type]);
186 }
187 $ret = $entries['XML'];
188 }
189 }
190 }
192 return($ret);
193 }
196 /*! \brief Checks if the given ids are used queue ids.
197 @param Array The ids we want to check..
198 @return Array An array containing all ids as index and TRUE/FALSE as value.
199 */
200 public function ids_exist($ids)
201 {
202 if(!is_array($ids)){
203 trigger_error("Requires an array as parameter.");
204 return;
205 }
206 $this->reset_error();
208 $ret = array();
210 $xml_msg = "<xml>
211 <header>gosa_query_jobdb</header>
212 <target>GOSA</target>
213 <source>GOSA</source>
214 <where>
215 <clause>
216 <connector>or</connector>";
217 foreach($ids as $id){
218 $xml_msg .= "<phrase>
219 <operator>eq</operator>
220 <id>".$id."</id>
221 </phrase>";
222 }
223 $xml_msg .= "</clause>
224 </where>
225 </xml>";
227 if($this->connect()){
228 $this->o_sock->write($xml_msg);
229 $str = trim($this->o_sock->read());
230 $entries = $this->xml_to_array($str);
231 if(isset($entries['XML']) && is_array($entries['XML'])){
232 foreach($entries['XML'] as $entry){
233 if(isset($entry['ID'])){
234 $ret[] = $entry['ID'];
235 }
236 }
237 }
238 }
239 return($ret);
240 }
243 /*! \brief Returns an entry containing all requested ids.
244 @param Array The IDs of the entries we want to return.
245 @return Array Of the requested entries.
246 */
247 public function get_entries_by_id($ids)
248 {
249 if(!is_array($ids)){
250 trigger_error("Requires an array as parameter.");
251 return;
252 }
253 $this->reset_error();
255 $ret = array();
257 $xml_msg = "<xml>
258 <header>gosa_query_jobdb</header>
259 <target>GOSA</target>
260 <source>GOSA</source>
261 <where>
262 <clause>
263 <connector>or</connector>";
264 foreach($ids as $id){
265 $xml_msg .= "<phrase>
266 <operator>eq</operator>
267 <id>".$id."</id>
268 </phrase>";
269 }
270 $xml_msg .= "</clause>
271 </where>
272 </xml>";
274 if($this->connect()){
275 $this->o_sock->write($xml_msg);
276 $str = trim($this->o_sock->read());
277 $entries = $this->xml_to_array($str);
278 if(isset($entries['XML'])){
279 foreach($entries['XML'] as $name => $entry){
280 if(preg_match("/^ANSWER[0-9]*$/",$name)){
281 $ret[$name] = $entry;
282 }
283 }
284 }
285 }
286 return($ret);
287 }
290 /*! \brief Checks if the given id is in use.
291 @param Integer The ID of the entry.
292 @return Boolean TRUE if entry exists.
293 */
294 public function id_exists($id)
295 {
296 if(!is_numeric($id)){
297 trigger_error("Requires an integer as parameter.");
298 return;
299 }
301 $this->reset_error();
303 $xml_msg = "<xml>
304 <header>gosa_query_jobdb</header>
305 <target>GOSA</target>
306 <source>GOSA</source>
307 <where>
308 <clause>
309 <phrase>
310 <operator>eq</operator>
311 <id>".$id."</id>
312 </phrase>
313 </clause>
314 </where>
315 </xml>";
317 if($this->connect()){
318 $this->o_sock->write($xml_msg);
319 $str = trim($this->o_sock->read());
320 $entries = $this->xml_to_array($str);
321 if( isset($entries['XML']['HEADER']) &&
322 $entries['XML']['HEADER']=="answer" &&
323 isset($entries['XML']['ANSWER1'])){
324 return(TRUE);
325 }
326 }
327 return(FALSE);
328 }
331 /*! \brief Returns an entry from the gosaSupportQueue
332 @param Integer The ID of the entry we want to return.
333 @return Array Of the requested entry.
334 */
335 public function get_entry_by_id($id)
336 {
337 if(!is_numeric($id)){
338 trigger_error("Requires an integer as parameter.");
339 return;
340 }
341 $this->reset_error();
343 $ret = array();
344 $xml_msg = "<xml>
345 <header>gosa_query_jobdb</header>
346 <target>GOSA</target>
347 <source>GOSA</source>
348 <where>
349 <clause>
350 <phrase>
351 <operator>eq</operator>
352 <id>".$id."</id>
353 </phrase>
354 </clause>
355 </where>
356 </xml>";
357 if($this->connect()){
358 $this->o_sock->write($xml_msg);
359 $str = trim($this->o_sock->read());
360 $entries = $this->xml_to_array($str);
361 if( isset($entries['XML']['HEADER']) &&
362 $entries['XML']['HEADER']=="answer" &&
363 isset($entries['XML']['ANSWER1'])){
364 $ret = $entries['XML']['ANSWER1'];
365 }
366 }
367 return($ret);
368 }
371 /*! \brief Removes a set of entries from the GOsa support queue.
372 @param Array The IDs to remove.
373 @return Boolean True on success.
374 */
375 public function remove_entries($ids)
376 {
377 if(!is_array($ids)){
378 trigger_error("Requires an array as parameter.");
379 return;
380 }
382 $this->reset_error();
384 $ret = array();
386 $xml_msg = "<xml>
387 <header>gosa_delete_jobdb_entry</header>
388 <target>GOSA</target>
389 <source>GOSA</source>
390 <where>
391 <clause>
392 <connector>or</connector>";
393 foreach($ids as $id){
394 $xml_msg .= "<phrase>
395 <operator>eq</operator>
396 <id>".$id."</id>
397 </phrase>";
398 }
399 $xml_msg .= "</clause>
400 </where>
401 </xml>";
403 if($this->connect()){
404 $this->o_sock->write($xml_msg);
405 $str = $this->o_sock->read();
406 $entries = $this->xml_to_array($str);
407 if(isset($entries['XML'])){
408 return(TRUE);
409 }
410 }
411 return(FALSE);
412 }
416 /*! \brief Removes an entry from the GOsa support queue.
417 @param Integer The ID of the entry we want to remove.
418 @return Boolean True on success.
419 */
420 public function remove_entry($id)
421 {
422 $this->reset_error();
424 $xml_msg = "<xml>
425 <header>gosa_delete_jobdb_entry</header>
426 <target>GOSA</target>
427 <source>GOSA</source>
428 <where>
429 <clause>
430 <phrase>
431 <operator>eq</operator>
432 <id>".$id."</id>
433 </phrase>
434 </clause>
435 </where>
436 </xml>";
437 if($this->connect()){
438 $this->o_sock->write($xml_msg);
439 $str = $this->o_sock->read();
440 $entries = $this->xml_to_array($str);
441 if(isset($entries['XML'])){
442 return(TRUE);
443 }
444 }
445 return(FALSE);
446 }
449 /*! \brief Parses the given xml string into an array
450 @param String XML string
451 @return Array Returns an array containing the xml structure.
452 */
453 private function xml_to_array($xml)
454 {
455 $params = array();
456 $level = array();
457 $parser = xml_parser_create_ns();
458 xml_parse_into_struct($parser, $xml, $vals, $index);
460 $err_id = xml_get_error_code($parser);
461 if($err_id){
462 xml_parser_free($parser);
463 }else{
464 xml_parser_free($parser);
466 foreach ($vals as $xml_elem) {
467 if ($xml_elem['type'] == 'open') {
468 if (array_key_exists('attributes',$xml_elem)) {
469 list($level[$xml_elem['level']],$extra) = array_values($xml_elem['attributes']);
470 } else {
471 $level[$xml_elem['level']] = $xml_elem['tag'];
472 }
473 }
474 if ($xml_elem['type'] == 'complete') {
475 $start_level = 1;
476 $php_stmt = '$params';
477 while($start_level < $xml_elem['level']) {
478 $php_stmt .= '[$level['.$start_level.']]';
479 $start_level++;
480 }
481 $php_stmt .= '[$xml_elem[\'tag\']] = $xml_elem[\'value\'];';
482 @eval($php_stmt);
483 }
484 }
485 }
487 if(!isset($params['XML'])){
488 if (!array_key_exists('XML', $params)){
489 $this->set_error(_("Could not parse XML."));
490 }
491 $params = array("COUNT" => 0);
492 }
494 return($params);
495 }
498 /*! \brief Updates an entry with a set of new values,
499 @param Integer The ID of the entry, we want to update.
500 @param Array The variables to update.
501 @return Boolean Returns TRUE on success.
502 */
503 public function update_entries($ids,$entry)
504 {
505 $this->reset_error();
506 if(!is_array($ids)){
507 trigger_error("Requires an array as first parameter.");
508 return;
509 }
511 if(!is_array($entry)){
512 trigger_error("Requires an array as second parameter.");
513 return;
514 }
516 $attr = "";
517 foreach($entry as $name => $entry){
518 $attr.="<".strtolower($name).">".$entry."</".strtolower($name).">\n";
519 }
520 $xml_msg = "<xml>
521 <header>gosa_update_status_jobdb_entry</header>
522 <target>GOSA</target>
523 <source>GOSA</source>
524 <where>
525 <clause>
526 <connector>or</connector>";
527 foreach($ids as $id){
528 $xml_msg .= "<phrase>
529 <operator>eq</operator>
530 <id>".$id."</id>
531 </phrase>";
532 }
533 $xml_msg .= "</clause>
534 </where>
535 <update>
536 ".$attr."
537 </update>
538 </xml>";
540 if($this->connect()){
541 $this->o_sock->write($xml_msg);
542 $str = trim($this->o_sock->read());
543 $entries = $this->xml_to_array($str);
544 if(isset($entries['XML'])){
545 if(isset($entries['XML']['ERROR_STRING'])) {
546 $this->set_error($entries['XML']['ERROR_STRING']);
547 return(FALSE);
548 }
549 return(TRUE);
550 }
551 }
552 return(FALSE);
553 }
556 /*! \brief Returns the number of currently queued objects.
557 @return Integer
558 */
559 public function number_of_queued_entries()
560 {
561 $xml_msg ="<xml><header>gosa_count_jobdb</header><target>GOSA</target><source>GOSA</source></xml>";
562 $this->connect();
563 if($this->connect()){
564 $this->o_sock->write($xml_msg);
565 $str = trim($this->o_sock->read());
566 $entries = $this->xml_to_array($str);
567 if(isset($entries['XML'])){
568 return($entries['XML']['COUNT']);
569 }
570 }
571 return(-1);
572 }
575 public function send_data($header, $to, $data= array(), $answer_expected = FALSE)
576 {
577 $xml_message= "";
579 /* Prepare data */
580 foreach ($data as $key => $value){
581 $xml_message.= "<$key>$value</$key>";
582 }
584 /* Multiple targets? */
585 if (!is_array($to)){
586 $to_targets= array($to);
587 } else {
588 $to_targets= $to;
589 }
591 /* Build target strings */
592 $target ="";
593 foreach($to_targets as $to){
594 $target.= "<target>$to</target>";
595 }
597 return $this->_send("<xml><header>$header</header><source>GOSA</source>$target".$xml_message."</xml>",$answer_expected);
598 }
601 /*! \brief Returns an array containing all queued entries.
602 @return Array All queued entries as an array.
603 */
604 public function _send($data, $answer_expected= FALSE)
605 {
606 $this->reset_error();
607 $ret = array();
609 if($this->connect()){
610 $this->o_sock->write($data);
611 if ($answer_expected){
612 $str = trim($this->o_sock->read());
613 $entries = $this->xml_to_array($str);
614 if(isset($entries['XML']) && is_array($entries['XML'])){
615 $ret = $entries;
616 if(isset($entries['XML']['ERROR_STRING'])) {
617 $this->set_error($entries['XML']['ERROR_STRING']);
618 }
619 }
620 }
621 }
622 return($ret);
623 }
626 static function send($header, $to, $data= array(), $answer_expected = FALSE)
627 {
628 $xml_message= "";
630 /* Get communication object */
631 $d= new gosaSupportDaemon(TRUE,10);
633 /* Prepare data */
634 foreach ($data as $key => $value){
635 $xml_message.= "<$key>$value</$key>";
636 }
638 /* Multiple targets? */
639 if (!is_array($to)){
640 $to_targets= array($to);
641 } else {
642 $to_targets= $to;
643 }
645 /* Build target strings */
646 $target ="";
647 foreach($to_targets as $to){
648 $target.= "<target>$to</target>";
649 }
651 return $d->_send("<xml><header>$header</header><source>GOSA</source>$target".$xml_message."</xml>",$answer_expected);
652 }
655 static function ping($target)
656 {
657 if (tests::is_mac($target)){
658 /* Get communication object */
659 $d= new gosaSupportDaemon(TRUE,0.5);
660 $answer= $d->_send("<xml><header>gosa_ping</header><source>GOSA</source><target>$target</target></xml>", TRUE);
661 return (count($answer) ? TRUE:FALSE);
662 }
664 return (FALSE);
665 }
667 }
669 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
670 ?>