1cb7a819072fc2dcf4de7c175e055f889d6c2544
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->s_error = $this->o_sock->get_error();
96 $this->b_error = TRUE;
97 $this->disconnect();
98 }
99 return($this->is_connected);
100 }
103 /*! \brief Disconnect from gosa daemon.
104 */
105 public function disconnect()
106 {
107 $this->o_sock->close();
108 $this->is_connected = FALSE;
109 }
112 /*! \brief Sets an error message, which can be returned with get_error().
113 @param string The Error message,
114 */
115 private function set_error($str)
116 {
117 $this->b_error = TRUE;
118 $this->s_error = $str;
119 }
122 /*! \brief Checks if an error occured.
123 @return boolean returns TRUE or FALSE, whether there is an error or not.
124 */
125 public function is_error()
126 {
127 return($this->b_error);
128 }
131 /*! \brief Returns the last error.
132 @return Returns the last error.
133 */
134 public function get_error()
135 {
136 return($this->s_error);
137 }
140 /*! \brief Returns an array containing all queued entries.
141 @return Array All queued entries as an array.
142 */
143 public function get_queued_entries($from=-1,$to=-1,$sort="timestamp DESC")
144 {
145 $this->b_error = FALSE;
146 $this->s_error = "";
147 $ret = array();
149 $xml_msg = "<xml>
150 <header>gosa_query_jobdb</header>
151 <target>GOSA</target>
152 <source>GOSA</source>
153 <orderby>".$sort."</orderby>";
154 if($from != -1 && $to != -1){
155 $xml_msg.= "
156 <limit>
157 <from>".$from."</from>
158 <to>".$to."</to>
159 </limit>";
160 }
161 $xml_msg.= "
162 </xml>";
164 if($this->connect()){
165 $this->o_sock->write($xml_msg);
166 $str = trim($this->o_sock->read());
167 $entries = $this->xml_to_array($str);
168 if(isset($entries['XML']) && is_array($entries['XML'])){
170 /* Check if returned values represent a valid answer */
171 if(isset($entries['XML'])){
173 /* Unset header tags */
174 foreach(array("HEADER","SOURCE","TARGET") as $type){
175 unset($entries['XML'][$type]);
176 }
177 $ret = $entries['XML'];
178 }
179 }
180 }
182 return($ret);
183 }
186 /*! \brief Checks if the given ids are used queue ids.
187 @param Array The ids we want to check..
188 @return Array An array containing all ids as index and TRUE/FALSE as value.
189 */
190 public function ids_exist($ids)
191 {
192 if(!is_array($ids)){
193 trigger_error("Requires an array as parameter.");
194 return;
195 }
196 $this->b_error = FALSE;
197 $this->s_error = "";
199 $ret = array();
201 $xml_msg = "<xml>
202 <header>gosa_query_jobdb</header>
203 <target>GOSA</target>
204 <source>GOSA</source>
205 <where>
206 <clause>
207 <connector>or</connector>";
208 foreach($ids as $id){
209 $xml_msg .= "<phrase>
210 <operator>eq</operator>
211 <id>".$id."</id>
212 </phrase>";
213 }
214 $xml_msg .= "</clause>
215 </where>
216 </xml>";
218 if($this->connect()){
219 $this->o_sock->write($xml_msg);
220 $str = trim($this->o_sock->read());
221 $entries = $this->xml_to_array($str);
222 if(isset($entries['XML']) && is_array($entries['XML'])){
223 foreach($entries['XML'] as $entry){
224 if(isset($entry['ID'])){
225 $ret[] = $entry['ID'];
226 }
227 }
228 }
229 }
230 return($ret);
231 }
234 /*! \brief Returns an entry containing all requested ids.
235 @param Array The IDs of the entries we want to return.
236 @return Array Of the requested entries.
237 */
238 public function get_entries_by_id($ids)
239 {
240 if(!is_array($ids)){
241 trigger_error("Requires an array as parameter.");
242 return;
243 }
244 $this->b_error = FALSE;
245 $this->s_error = "";
247 $ret = array();
249 $xml_msg = "<xml>
250 <header>gosa_query_jobdb</header>
251 <target>GOSA</target>
252 <source>GOSA</source>
253 <where>
254 <clause>
255 <connector>or</connector>";
256 foreach($ids as $id){
257 $xml_msg .= "<phrase>
258 <operator>eq</operator>
259 <id>".$id."</id>
260 </phrase>";
261 }
262 $xml_msg .= "</clause>
263 </where>
264 </xml>";
266 if($this->connect()){
267 $this->o_sock->write($xml_msg);
268 $str = trim($this->o_sock->read());
269 $entries = $this->xml_to_array($str);
270 if(isset($entries['XML'])){
271 foreach($entries['XML'] as $name => $entry){
272 if(preg_match("/^ANSWER[0-9]*$/",$name)){
273 $ret[$name] = $entry;
274 }
275 }
276 }
277 }
278 return($ret);
279 }
282 /*! \brief Checks if the given id is in use.
283 @param Integer The ID of the entry.
284 @return Boolean TRUE if entry exists.
285 */
286 public function id_exists($id)
287 {
288 if(!is_numeric($id)){
289 trigger_error("Requires an integer as parameter.");
290 return;
291 }
293 $this->b_error = FALSE;
294 $this->s_error = "";
295 $xml_msg = "<xml>
296 <header>gosa_query_jobdb</header>
297 <target>GOSA</target>
298 <source>GOSA</source>
299 <where>
300 <clause>
301 <phrase>
302 <operator>eq</operator>
303 <id>".$id."</id>
304 </phrase>
305 </clause>
306 </where>
307 </xml>";
309 if($this->connect()){
310 $this->o_sock->write($xml_msg);
311 $str = trim($this->o_sock->read());
312 $entries = $this->xml_to_array($str);
313 if( isset($entries['XML']['HEADER']) &&
314 $entries['XML']['HEADER']=="answer" &&
315 isset($entries['XML']['ANSWER1'])){
316 return(TRUE);
317 }
318 }
319 return(FALSE);
320 }
323 /*! \brief Returns an entry from the gosaSupportQueue
324 @param Integer The ID of the entry we want to return.
325 @return Array Of the requested entry.
326 */
327 public function get_entry_by_id($id)
328 {
329 if(!is_numeric($id)){
330 trigger_error("Requires an integer as parameter.");
331 return;
332 }
334 $this->b_error = FALSE;
335 $this->s_error = "";
336 $ret = array();
337 $xml_msg = "<xml>
338 <header>gosa_query_jobdb</header>
339 <target>GOSA</target>
340 <source>GOSA</source>
341 <where>
342 <clause>
343 <phrase>
344 <operator>eq</operator>
345 <id>".$id."</id>
346 </phrase>
347 </clause>
348 </where>
349 </xml>";
350 if($this->connect()){
351 $this->o_sock->write($xml_msg);
352 $str = trim($this->o_sock->read());
353 $entries = $this->xml_to_array($str);
354 if( isset($entries['XML']['HEADER']) &&
355 $entries['XML']['HEADER']=="answer" &&
356 isset($entries['XML']['ANSWER1'])){
357 $ret = $entries['XML']['ANSWER1'];
358 }
359 }
360 return($ret);
361 }
364 /*! \brief Removes a set of entries from the GOsa support queue.
365 @param Array The IDs to remove.
366 @return Boolean True on success.
367 */
368 public function remove_entries($ids)
369 {
370 if(!is_array($ids)){
371 trigger_error("Requires an array as parameter.");
372 return;
373 }
374 $this->b_error = FALSE;
375 $this->s_error = "";
377 $ret = array();
379 $xml_msg = "<xml>
380 <header>gosa_delete_jobdb_entry</header>
381 <target>GOSA</target>
382 <source>GOSA</source>
383 <where>
384 <clause>
385 <connector>or</connector>";
386 foreach($ids as $id){
387 $xml_msg .= "<phrase>
388 <operator>eq</operator>
389 <id>".$id."</id>
390 </phrase>";
391 }
392 $xml_msg .= "</clause>
393 </where>
394 </xml>";
395 $this->b_error = FALSE;
396 $this->s_error = "";
398 if($this->connect()){
399 $this->o_sock->write($xml_msg);
400 $str = $this->o_sock->read();
401 $entries = $this->xml_to_array($str);
402 if(isset($entries['XML'])){
403 return(TRUE);
404 }
405 }
406 return(FALSE);
407 }
411 /*! \brief Removes an entry from the GOsa support queue.
412 @param Integer The ID of the entry we want to remove.
413 @return Boolean True on success.
414 */
415 public function remove_entry($id)
416 {
417 $this->b_error = FALSE;
418 $this->s_error = "";
420 $xml_msg = "<xml>
421 <header>gosa_delete_jobdb_entry</header>
422 <target>GOSA</target>
423 <source>GOSA</source>
424 <where>
425 <clause>
426 <phrase>
427 <operator>eq</operator>
428 <id>".$id."</id>
429 </phrase>
430 </clause>
431 </where>
432 </xml>";
433 if($this->connect()){
434 $this->o_sock->write($xml_msg);
435 $str = $this->o_sock->read();
436 $entries = $this->xml_to_array($str);
437 if(isset($entries['XML'])){
438 return(TRUE);
439 }
440 }
441 return(FALSE);
442 }
445 /*! \brief Parses the given xml string into an array
446 @param String XML string
447 @return Array Returns an array containing the xml structure.
448 */
449 private function xml_to_array($xml)
450 {
451 $params = array();
452 $level = array();
453 $parser = xml_parser_create_ns();
454 xml_parse_into_struct($parser, $xml, $vals, $index);
456 $err_id = xml_get_error_code($parser);
457 if($err_id){
458 xml_parser_free($parser);
459 }else{
460 xml_parser_free($parser);
462 foreach ($vals as $xml_elem) {
463 if ($xml_elem['type'] == 'open') {
464 if (array_key_exists('attributes',$xml_elem)) {
465 list($level[$xml_elem['level']],$extra) = array_values($xml_elem['attributes']);
466 } else {
467 $level[$xml_elem['level']] = $xml_elem['tag'];
468 }
469 }
470 if ($xml_elem['type'] == 'complete') {
471 $start_level = 1;
472 $php_stmt = '$params';
473 while($start_level < $xml_elem['level']) {
474 $php_stmt .= '[$level['.$start_level.']]';
475 $start_level++;
476 }
477 $php_stmt .= '[$xml_elem[\'tag\']] = $xml_elem[\'value\'];';
478 @eval($php_stmt);
479 }
480 }
481 }
483 if(!isset($params['XML'])){
484 if (!array_key_exists('XML', $params)){
485 $this->set_error(_("Could not parse XML."));
486 }
487 $params = array("COUNT" => 0);
488 }
490 return($params);
491 }
494 /*! \brief Updates an entry with a set of new values,
495 @param Integer The ID of the entry, we want to update.
496 @param Array The variables to update.
497 @return Boolean Returns TRUE on success.
498 */
499 public function update_entries($ids,$entry)
500 {
501 $this->b_error = FALSE;
502 $this->s_error = "";
503 if(!is_array($ids)){
504 trigger_error("Requires an array as first parameter.");
505 return;
506 }
508 if(!is_array($entry)){
509 trigger_error("Requires an array as second parameter.");
510 return;
511 }
513 $attr = "";
514 foreach($entry as $name => $entry){
515 $attr.="<".strtolower($name).">".$entry."</".strtolower($name).">\n";
516 }
517 $xml_msg = "<xml>
518 <header>gosa_update_status_jobdb_entry</header>
519 <target>GOSA</target>
520 <source>GOSA</source>
521 <where>
522 <clause>
523 <connector>or</connector>";
524 foreach($ids as $id){
525 $xml_msg .= "<phrase>
526 <operator>eq</operator>
527 <id>".$id."</id>
528 </phrase>";
529 }
530 $xml_msg .= "</clause>
531 </where>
532 <update>
533 ".$attr."
534 </update>
535 </xml>";
536 if($this->connect()){
537 $this->o_sock->write($xml_msg);
538 $str = trim($this->o_sock->read());
539 $entries = $this->xml_to_array($str);
540 if(isset($entries['XML'])){
541 return(TRUE);
542 }
543 }
544 return(FALSE);
545 }
548 /*! \brief Returns the number of currently queued objects.
549 @return Integer
550 */
551 public function number_of_queued_entries()
552 {
553 $xml_msg ="<xml><header>gosa_count_jobdb</header><target>GOSA</target><source>GOSA</source></xml>";
554 $this->connect();
555 if($this->connect()){
556 $this->o_sock->write($xml_msg);
557 $str = trim($this->o_sock->read());
558 $entries = $this->xml_to_array($str);
559 if(isset($entries['XML'])){
560 return($entries['XML']['COUNT']);
561 }
562 }
563 return(-1);
564 }
567 /*! \brief Returns an array containing all queued entries.
568 @return Array All queued entries as an array.
569 */
570 public function _send($data, $answer_expected= FALSE)
571 {
572 $this->b_error = FALSE;
573 $this->s_error = "";
574 $ret = array();
576 if($this->connect()){
577 $this->o_sock->write($data);
578 if ($answer_expected){
579 $str = trim($this->o_sock->read());
580 $entries = $this->xml_to_array($str);
581 if(isset($entries['XML']) && is_array($entries['XML'])){
582 $ret = $entries;
583 if(isset($entries['XML']['ERROR_STRING'])) {
584 $this->set_error($entries['XML']['ERROR_STRING']);
585 }
586 }
587 }
588 }
589 return($ret);
590 }
593 static function send($header, $to, $data= array(), $answer_expected = FALSE)
594 {
595 $xml_message= "";
597 /* Get communication object */
598 $d= new gosaSupportDaemon(TRUE,10);
600 /* Prepare data */
601 foreach ($data as $key => $value){
602 $xml_message.= "<$key>$value</$key>";
603 }
605 /* Multiple targets? */
606 if (!is_array($to)){
607 $to_targets= array($to);
608 } else {
609 $to_targets= $to;
610 }
612 /* Build target strings */
613 $target ="";
614 foreach($to_targets as $to){
615 $target.= "<target>$to</target>";
616 }
618 return $d->_send("<xml><header>$header</header><source>GOSA</source>$target".$xml_message."</xml>",$answer_expected);
619 }
622 static function ping($target)
623 {
624 if (tests::is_mac($target)){
625 /* Get communication object */
626 $d= new gosaSupportDaemon(TRUE,0.5);
627 $answer= $d->_send("<xml><header>gosa_ping</header><source>GOSA</source><target>$target</target></xml>", TRUE);
628 return (count($answer) ? TRUE:FALSE);
629 }
631 return (FALSE);
632 }
634 }
636 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
637 ?>