diff --git a/lib/classes/config/class.ConfigDaemon.php b/lib/classes/config/class.ConfigDaemon.php new file mode 100644 index 00000000..14aae6ab --- /dev/null +++ b/lib/classes/config/class.ConfigDaemon.php @@ -0,0 +1,277 @@ + + * @author Froxlor team (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Classes + * + * @since 0.9.34 + */ + + +/** + * Class ConfigDaemon + * + * Parses a distributions XML - file and gives access to the configuration + * Not to be used directly + * + * @copyright (c) the authors + * @author Florian Aders + * @author Froxlor team (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Classes + */ +class ConfigDaemon { + private $orders = array(); + + private $fullxml; + + private $daemon; + + private $xpath; + + public $title; + + private $isparsed = false; + + public function __construct($xml, $xpath) { + $this->fullxml = $xml; + $this->xpath = $xpath; + $this->daemon = $this->fullxml->xpath($this->xpath); + $attributes = $this->daemon[0]->attributes(); + if ($attributes['title'] != '') { + $this->title = $this->_parseContent((string)$attributes['title']); + } + } + + private function _parse() { + if ($this->isparsed) { + return; + } + $preparsed = array(); + // First: let's handle push everything into an array and expand all includes + foreach ($this->daemon[0]->children() as $order) { + switch((string)$order->getName()) { + case "install": + case "file": + case "command": + // Normal stuff, just add it to the preparsed - array + $preparsed[] = $order; break; + case "include": + // Includes, get the part we want via xpath + $includes = $this->fullxml->xpath((string)$order); + foreach ($includes[0] as $include) { + // The "include" is also a child, so just skip it, would make a mess later + if ((string)$include->getName() == 'include') { + continue; + } + $preparsed[] = $include; + } + break; + default: continue; + } + } + + // Go through every preparsed order and evaluate what should happen to it + foreach ($preparsed as $order) { + $parsedorder = $this->_parseOrder($order); + // We got an array (= valid order) and the array already has a type -> add to stack + if (is_array($parsedorder) && array_key_exists('type', $parsedorder)) { + $this->orders[] = $parsedorder; + // We got an array, but no type, means we got multiple orders back, at them to the stack one at a time + } elseif (is_array($parsedorder)) { + foreach($parsedorder as $neworder) { + $this->orders[] = $neworder; + } + } + } + $this->isparsed = true; + } + + /** + * Parse a single order and return it in a format for easier usage + * + * @param SimpleXMLElement object holding a single order from the distribution - XML + * @return array|string + */ + private function _parseOrder($order) { + $attributes = array(); + foreach($order->attributes() as $key => $value) { + $attributes[(string)$key] = (string)$value; + } + + $parsedorder = ''; + switch((string)$order->getName()) { + case "file": $parsedorder = $this->_parseFile($order, $attributes); break; + case "command": $parsedorder = $this->_parseCommand($order, $attributes); break; + case "install": $parsedorder = $this->_parseInstall($order, $attributes); break; + default: throw new \Exception('Invalid order: ' . (string)$order->getName()); + } + + return $parsedorder; + } + + /** + * Parse a install - order and return it in a format for easier usage + * + * @param SimpleXMLElement object holding a single install from the distribution - XML + * @return array|string + */ + private function _parseInstall($order, $attributes) { + // No sub - elements, so the content can be returned directly + if ($order->count() == 0) { + return array('type' => 'install', 'content' => (string)$order); + } + // Hold the results + $visibility = 1; + $content = ''; + foreach($order->children() as $child) { + switch((string)$child->getName()) { + case "visibility": $visibility += $this->_checkVisibility($child); break; + case "content": $content = $this->_parseContent((string)$child); break; + } + } + + if ($visibility > 0) { + return array('type' => 'install', 'content' => $content); + } else { + return ''; + } + } + + /** + * Parse a command - order and return it in a format for easier usage + * + * @param SimpleXMLElement object holding a single command from the distribution - XML + * @return array|string + */ + private function _parseCommand($order, $attributes) { + // No sub - elements, so the content can be returned directly + if ($order->count() == 0) { + return array('type' => 'command', 'content' => (string)$order); + } + // Hold the results + $visibility = 1; + $content = ''; + foreach($order->children() as $child) { + switch((string)$child->getName()) { + case "visibility": $visibility += $this->_checkVisibility($child); break; + case "content": $content = $this->_parseContent((string)$child); break; + } + } + + if ($visibility > 0) { + return array('type' => 'command', 'content' => $content); + } else { + return ''; + } + } + + /** + * Parse a file - order and return it in a format for easier usage + * + * @param SimpleXMLElement object holding a single file from the distribution - XML + * @return array|string + */ + private function _parseFile($order, $attributes) { + // No sub - elements, so the content can be returned directly + if ($order->count() == 0) { + return array('type' => 'file', 'content' => (string)$order, 'name' => $attributes['name']); + } + // Hold the results + $visibility = 1; + $content = ''; + foreach($order->children() as $child) { + switch((string)$child->getName()) { + case "visibility": $visibility += $this->_checkVisibility($child); break; + case "content": $content = $this->_parseContent((string)$child); break; + } + } + + $return = array(); + // Check if the original file should be backupped + // @TODO: Maybe have a backup - space somewhere? + // @TODO: Use IO - class + if (array_key_exists('backup', $attributes)) { + $return[] = array('type' => 'command', 'content' => 'mv "' . $attributes['name'] . '" "' . $attributes['name'] . '.frx.bak"'); + } + + // Now the content of the file can be written + $return[] = array('type' => 'file', 'content' => $content, 'name' => $attributes['name']); + + // Let's check if the mode of the file should be changed + if (array_key_exists('chmod', $attributes)) { + $return[] = array('type' => 'command', 'content' => 'chmod ' . $attributes['chmod'] . ' "' . $attributes['name'] . '"'); + } + + // Let's check if the owner of the file should be changed + if (array_key_exists('chown', $attributes)) { + $return[] = array('type' => 'command', 'content' => 'chown ' . $attributes['chown'] . ' "' . $attributes['name'] . '"'); + } + + if ($visibility > 0) { + return $return; + } else { + return ''; + } + } + + /** + * Replace placeholders with content + * @param string $content + * @return string $content w/o placeholder + */ + private function _parseContent($content) { + return preg_replace_callback('/{{(.*)}}/Ui', function ($matches) { + if (preg_match('/^settings\.(.*)$/', $matches[1], $match)) { + return Settings::Get($match[1]); + } elseif (preg_match('/^lng\.(.*)$/', $matches[1], $match)) { + $lngvar = str_replace('.', '"]["', $match[1]); + $lngvar = str_replace('lng"]', 'lng', $lngvar); + $lngvar .= '"]'; + return ${$lngvar}; + } + }, $content); + } + + /** + * Check if visibility should be changed + * @param SimpleXMLElement $order + * @return int 0|-1 + */ + private function _checkVisibility($order) { + $attributes = array(); + foreach($order->attributes() as $key => $value) { + $attributes[(string)$key] = (string)$value; + } + $order = $this->_parseContent((string)$order); + if (!array_key_exists('mode', $attributes)) { + throw new \Exception('"' . $order . '" is missing mode'); + } + switch ($attributes['mode']) { + case "isfile": if (!is_file($order)) { return -1; }; break; + case "isdir": if (!is_dir($order)) { return -1; }; break; + case "isdir": if (!is_dir($order)) { return -1; }; break; + case "false": if ($order == true) { return -1; }; break; + case "true": if ($order == false) { return -1; }; break; + case "userexists": if (true) { return 0; }; break; + case "groupexists": if (true) { return 0; }; break; + } + return 0; + } + + public function getConfig() { + $this->_parse(); + return $this->orders; + + } +} \ No newline at end of file diff --git a/lib/classes/config/class.ConfigParser.php b/lib/classes/config/class.ConfigParser.php new file mode 100644 index 00000000..caec269f --- /dev/null +++ b/lib/classes/config/class.ConfigParser.php @@ -0,0 +1,96 @@ + + * @author Froxlor team (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Classes + * + * @since 0.9.34 + */ + +/** + * Class ConfigParser + * + * Parses a distributions XML - file and gives access to the configuration + * + * @copyright (c) the authors + * @author Florian Aders + * @author Froxlor team (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Classes + */ +class ConfigParser { + /** + * Holding the available services in the XML + * @var array + */ + private $services = array(); + + /** + * Store the parsed SimpleXMLElement for usage + * @var SimpleXMLElement + */ + private $xml; + + /** + * Constructor + * + * Initialize the XML - ConfigParser + * @param string $filename filename of the froxlor - configurationfile + * @return void + */ + public function __construct($filename) { + if (!is_readable($filename)) { + throw new Exception('File not readable'); + } + $this->xml = simplexml_load_file($filename); + if ($this->xml === false) { + $error = ''; + foreach(libxml_get_errors() as $error) { + $error .= "\t" . $error->message; + } + throw new Exception($error); + } + $this->parse(); + } + + /** + * Parse the XML and populate $this->services + * @return void + */ + private function parse() { + // Get all services + $services = $this->xml->xpath('//services/service'); + foreach ($services as $service) { + // We don't want comments + if ($service->getName() == 'comment') { + continue; + } + // Search the attributes for "type" + foreach ($service->attributes() as $key => $value) { + if ($key == 'type') { + $this->services[(string)$value] = new ConfigService($this->xml, '//services/service[@type="' . (string)$value . '"]'); + } + } + } + } + + /** + * Return all services defined by the XML + * + * The array will hold ConfigService - Objects for further handling + * @return array + */ + public function getServices() { + return $this->services; + } +} \ No newline at end of file diff --git a/lib/classes/config/class.ConfigService.php b/lib/classes/config/class.ConfigService.php new file mode 100644 index 00000000..3744c93e --- /dev/null +++ b/lib/classes/config/class.ConfigService.php @@ -0,0 +1,89 @@ + + * @author Froxlor team (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Classes + * + * @since 0.9.34 + */ + + +/** + * Class ConfigService + * + * Parses a distributions XML - file and gives access to the services within + * Not to be used directly + * + * @copyright (c) the authors + * @author Florian Aders + * @author Froxlor team (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Classes + */ +class ConfigService { + private $daemons = array(); + + private $fullxml; + + private $service; + + private $xpath; + + public $title; + + public function __construct($xml, $xpath) { + $this->fullxml = $xml; + $this->xpath = $xpath; + $this->service = $this->fullxml->xpath($this->xpath); + $attributes = $this->service[0]->attributes(); + if ($attributes['title'] != '') { + $this->title = (string)$attributes['title']; + } + $this->parse(); + } + + private function parse() { + $daemons = $this->fullxml->xpath($this->xpath . '/daemon'); + foreach ($daemons as $daemon) { + if ($daemon->getName() == 'comment') { + continue; + } + $name = ''; + $nametag = ''; + $versiontag = ''; + foreach($daemon->attributes() as $key => $value) { + if ($key == 'name' && $name == '') { + $name = (string)$value; + $nametag = "[@name='" . $value . "']"; + } elseif ($key == 'name' && $name != '') { + $name = (string)$value . '_' . $name; + $nametag = "[@name='" . $value . "']"; + } elseif ($key == 'version' && $name == '') { + $name = str_replace('.', '', $value); + $versiontag = "[@version='" . $value . "']"; + } elseif ($key == 'version' && $name != '') { + $name = $name . str_replace('.', '', $value); + $versiontag = "[@version='" . $value . "']"; + } + } + if ($name == '') { + throw new Exception ('No name attribute for daemon'); + } + $this->daemons[$name] = new ConfigDaemon($this->fullxml, $this->xpath . "/daemon" . $nametag . $versiontag); + } + } + + public function getDaemons() { + return $this->daemons; + } +} \ No newline at end of file