⚝
One Hat Cyber Team
⚝
Your IP:
216.73.216.72
Server IP:
41.128.143.86
Server:
Linux host.raqmix.cloud 6.8.0-1025-azure #30~22.04.1-Ubuntu SMP Wed Mar 12 15:28:20 UTC 2025 x86_64
Server Software:
Apache
PHP Version:
8.3.23
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
usr
/
share
/
psa-pear
/
pear
/
php
/
Horde
/
Edit File: Config.php
<?php /** * The Horde_Config:: package provides a framework for managing the * configuration of Horde applications, writing conf.php files from * conf.xml source files, generating user interfaces, etc. * * Copyright 2002-2017 Horde LLC (http://www.horde.org/) * * See the enclosed file COPYING for license information (LGPL). If you * did not receive this file, see http://www.horde.org/licenses/lgpl21. * * @author Chuck Hagenbuch <chuck@horde.org> * @category Horde * @package Core */ class Horde_Config { /** * The name of the configured application. * * @var string */ protected $_app; /** * The XML tree of the configuration file traversed to an * associative array. * * @var array */ protected $_xmlConfigTree = null; /** * The content of the generated configuration file. * * @var string */ protected $_phpConfig; /** * The content of the old configuration file. * * @var string */ protected $_oldConfig; /** * The manual configuration in front of the generated configuration. * * @var string */ protected $_preConfig; /** * The manual configuration after the generated configuration. * * @var string */ protected $_postConfig; /** * The current $conf array of the configured application. * * @var array */ protected $_currentConfig = array(); /** * The SHA-1 hash of the conf.xml file which will be copied into the * conf.php file. * * @var string */ protected $_configHash = ''; /** * The version tag of the conf.xml file which will be copied into the * conf.php file. * * @var string * @deprecated * @todo Remove for Horde 6 */ protected $_versionTag = ''; /** * The line marking the begin of the generated configuration. * * @var string */ protected $_configBegin = "/* CONFIG START. DO NOT CHANGE ANYTHING IN OR AFTER THIS LINE. */\n"; /** * The line marking the end of the generated configuration. * * @var string */ protected $_configEnd = "/* CONFIG END. DO NOT CHANGE ANYTHING IN OR BEFORE THIS LINE. */\n"; /** * Horde URL to check version information. * * @var string */ protected $_versionUrl = 'https://pear.horde.org/packages.json'; /** * Constructor. * * @param string $app The name of the application to be configured. */ public function __construct($app = 'horde') { $this->_app = $app; } /** * Contact Horde servers and get version information. * * @return array Keys are app names, values are arrays with two keys: * 'version' and 'url'. * @throws Horde_Exception * @throws Horde_Http_Exception, Horde_Exception */ public function checkVersions() { $response = $GLOBALS['injector'] ->getInstance('Horde_Core_Factory_HttpClient') ->create(array( 'request.timeout' => 60, 'request.userAgent' => 'Horde ' . $GLOBALS['registry']->getVersion('horde', true) )) ->get($this->_versionUrl); if ($response->code != 200) { throw new Horde_Exception('Unexpected response from server.'); } if (!is_array($result = json_decode($response->getBody(), true))) { throw new Horde_Exception('Unexpected response from server.'); } $versions = array(); foreach ($result as $package) { uksort($package['versions'], 'version_compare'); $version = end($package['versions']); $versions[str_replace('pear-horde/', '', $package['name'])] = array( 'version' => $version['version'], 'url' => 'https://pear.horde.org/' ); } return $versions; } /** */ public function configFile() { $path = $GLOBALS['registry']->get('fileroot', $this->_app) . '/config'; $configFile = $path . '/conf.php'; if (is_link($configFile)) { $configFile = readlink($configFile); } return $configFile; } /** * Reads the application's conf.xml file and builds an associative array * from its XML tree. * * @param array $custom_conf Any settings that shall be included in the * generated configuration. * * @return array An associative array representing the configuration * tree. */ public function readXMLConfig($custom_conf = null) { if (!is_null($this->_xmlConfigTree) && !$custom_conf) { return $this->_xmlConfigTree; } $path = $GLOBALS['registry']->get('fileroot', $this->_app) . '/config'; if ($custom_conf) { $this->_currentConfig = $custom_conf; } else { /* Fetch the current conf.php contents. */ @eval($this->getPHPConfig()); if (isset($conf)) { $this->_currentConfig = $conf; } } /* Load the DOM object. */ $dom = new DOMDocument(); $dom->loadXML(file_get_contents($path . '/conf.xml')); /* Create config file hash. */ $this->_configHash = hash_file('sha1', $path . '/conf.xml'); /* Check if there is a CVS/Git version tag and store it. */ /* TODO: Remove for Horde 6. */ $node = $dom->firstChild; while (!empty($node)) { if (($node->nodeType == XML_COMMENT_NODE) && ($vers_tag = $this->getVersion($node->nodeValue))) { $this->_versionTag = $vers_tag . "\n"; break; } $node = $node->nextSibling; } /* Parse the config file. */ $this->_xmlConfigTree = array(); $root = $dom->documentElement; if ($root->hasChildNodes()) { $this->_parseLevel($this->_xmlConfigTree, $root->childNodes, ''); } /* Parse additional config files. */ foreach (glob($path . '/conf.d/*.xml') as $additional) { $dom = new DOMDocument(); $dom->load($additional); $root = $dom->documentElement; if ($root->hasChildNodes()) { $tree = array(); $this->_parseLevel($tree, $root->childNodes, ''); $this->_xmlConfigTree = array_replace_recursive($this->_xmlConfigTree, $tree); } } return $this->_xmlConfigTree; } /** * Get the Horde version string for a config file. * * @param string $text The text to parse. * * @return string The version string or false if not found. */ public function getVersion($text) { // Old CVS tag if (preg_match('/\$.*?conf\.xml,v .*? .*\$/', $text, $match) || // New Git tag preg_match('/\$Id:\s*[0-9a-f]+\s*\$/', $text, $match)) { return $match[0]; } return false; } /** * Returns the file content of the current configuration file. * * @return string The unparsed configuration file content. */ public function getPHPConfig() { if (!is_null($this->_oldConfig)) { return $this->_oldConfig; } $path = $GLOBALS['registry']->get('fileroot', $this->_app) . '/config'; if (file_exists($path . '/conf.php')) { $this->_oldConfig = file_get_contents($path . '/conf.php'); if (!empty($this->_oldConfig)) { $this->_oldConfig = preg_replace('/<\?php\n?/', '', $this->_oldConfig); $pos = strpos($this->_oldConfig, $this->_configBegin); if ($pos !== false) { $this->_preConfig = substr($this->_oldConfig, 0, $pos); $this->_oldConfig = substr($this->_oldConfig, $pos); } $pos = strpos($this->_oldConfig, $this->_configEnd); if ($pos !== false) { $this->_postConfig = substr($this->_oldConfig, $pos + strlen($this->_configEnd)); $this->_oldConfig = substr($this->_oldConfig, 0, $pos); } } } else { $this->_oldConfig = ''; } return $this->_oldConfig; } /** * Generates and writes the content of the application's configuration * file. * * @param Horde_Variables $formvars The processed configuration form * data. * @param string $php The content of the generated * configuration file. * * @return boolean True if the configuration file could be written * immediately to the file system. */ public function writePHPConfig($formvars, &$php = null) { $php = $this->generatePHPConfig($formvars); $path = $GLOBALS['registry']->get('fileroot', $this->_app) . '/config'; $configFile = $this->configFile(); if (file_exists($configFile)) { if (@copy($configFile, $path . '/conf.bak.php')) { $GLOBALS['notification']->push(sprintf(Horde_Core_Translation::t("Successfully saved the backup configuration file %s."), Horde_Util::realPath($path . '/conf.bak.php')), 'horde.success'); } else { $GLOBALS['notification']->push(sprintf(Horde_Core_Translation::t("Could not save the backup configuration file %s."), Horde_Util::realPath($path . '/conf.bak.php')), 'horde.warning'); } } if ($fp = @fopen($configFile, 'w')) { /* Can write, so output to file. */ fwrite($fp, $php); fclose($fp); $GLOBALS['registry']->rebuild(); $GLOBALS['notification']->push(sprintf(Horde_Core_Translation::t("Successfully wrote %s"), Horde_Util::realPath($configFile)), 'horde.success'); return true; } /* Cannot write. Save to session. */ $GLOBALS['session']->set('horde', 'config/' . $this->_app, $php); return false; } /** * Generates the content of the application's configuration file. * * @param Horde_Variables $formvars The processed configuration form * data. * @param array $custom_conf Any settings that shall be included * in the generated configuration. * * @return string The content of the generated configuration file. */ public function generatePHPConfig($formvars, $custom_conf = null) { $this->readXMLConfig($custom_conf); $this->getPHPConfig(); $this->_phpConfig = "<?php\n" . $this->_preConfig . $this->_configBegin . '// $Hash: ' . $this->_configHash . "\n"; if (!empty($this->_versionTag)) { $this->_phpConfig .= '// ' . $this->_versionTag; } $this->_generatePHPConfig($this->_xmlConfigTree, '', $formvars); $this->_phpConfig .= $this->_configEnd . $this->_postConfig; return $this->_phpConfig; } /** * Generates the configuration file items for a part of the configuration * tree. * * @param array $section An associative array containing the * part of the traversed XML * configuration tree that should be * processed. * @param string $prefix A configuration prefix determining * the current position inside the * configuration file. This prefix will * be translated to keys of the $conf * array in the generated configuration * file. * @param Horde_Variables $formvars The processed configuration form * data. */ protected function _generatePHPConfig($section, $prefix, $formvars) { if (!is_array($section)) { return; } foreach ($section as $name => $configitem) { if (is_array($configitem) && isset($configitem['tab'])) { continue; } $prefixedname = empty($prefix) ? $name : $prefix . '|' . $name; $configname = str_replace('|', '__', $prefixedname); $quote = (!isset($configitem['quote']) || $configitem['quote'] !== false); if ($configitem == 'placeholder') { $this->_phpConfig .= '$conf[\'' . str_replace('|', '\'][\'', $prefix) . "'] = array();\n"; } elseif (isset($configitem['switch'])) { $val = $formvars->getExists($configname, $wasset); if (!$wasset) { $val = isset($configitem['default']) ? $configitem['default'] : null; } if (isset($configitem['switch'][$val])) { $value = $val; if ($quote && $value != 'true' && $value != 'false') { $value = "'" . $value . "'"; } $this->_generatePHPConfig($configitem['switch'][$val]['fields'], $prefix, $formvars); } } elseif (isset($configitem['_type'])) { $val = $formvars->getExists($configname, $wasset); if (!$wasset && ((array_key_exists('is_default', $configitem) && $configitem['is_default']) || !array_key_exists('is_default', $configitem))) { $val = isset($configitem['default']) ? $configitem['default'] : null; } $type = $configitem['_type']; switch ($type) { case 'multienum': if (is_array($val)) { $encvals = array(); foreach ($val as $v) { $encvals[] = $this->_quote($v); } $arrayval = "'" . implode('\', \'', $encvals) . "'"; if ($arrayval == "''") { $arrayval = ''; } } else { $arrayval = ''; } $value = 'array(' . $arrayval . ')'; break; case 'boolean': if (is_bool($val)) { $value = $val ? 'true' : 'false'; } else { $value = ($val == 'on') ? 'true' : 'false'; } break; case 'stringlist': $values = explode(',', $val); if (!is_array($values)) { $value = "array('" . $this->_quote(trim($values)) . "')"; } else { $encvals = array(); foreach ($values as $v) { $encvals[] = $this->_quote(trim($v)); } $arrayval = "'" . implode('\', \'', $encvals) . "'"; if ($arrayval == "''") { $arrayval = ''; } $value = 'array(' . $arrayval . ')'; } break; case 'int': if (strlen($val)) { $value = (int)$val; } break; case 'octal': $value = sprintf('0%o', octdec($val)); break; case 'header': case 'description': break; default: if ($val != '') { $value = $val; if ($quote && $value != 'true' && $value != 'false') { $value = "'" . $this->_quote($value) . "'"; } } break; } } else { $this->_generatePHPConfig($configitem, $prefixedname, $formvars); } if (isset($value)) { $this->_phpConfig .= '$conf[\'' . str_replace('__', '\'][\'', $configname) . '\'] = ' . $value . ";\n"; } unset($value); } } /** * Parses one level of the configuration XML tree into the associative * array containing the traversed configuration tree. * * @param array &$conf The already existing array where the * processed XML tree portion should be * appended to. * @param DOMNodeList $children The XML nodes of the level that should * be parsed. * @param string $ctx A string representing the current * position (context prefix) inside the * configuration XML file. */ protected function _parseLevel(&$conf, $children, $ctx) { foreach ($children as $node) { if ($node->nodeType != XML_ELEMENT_NODE) { continue; } $name = $node->getAttribute('name'); $desc = $GLOBALS['injector']->getInstance('Horde_Core_Factory_TextFilter')->filter($node->getAttribute('desc'), 'linkurls'); $required = !($node->getAttribute('required') == 'false'); $quote = !($node->getAttribute('quote') == 'false'); $curctx = empty($ctx) ? $name : $ctx . '|' . $name; switch ($node->tagName) { case 'configdescription': if (empty($name)) { $name = uniqid(mt_rand()); } $conf[$name] = array( '_type' => 'description', 'desc' => $GLOBALS['injector']->getInstance('Horde_Core_Factory_TextFilter')->filter($this->_default($curctx, $this->_getNodeOnlyText($node)), 'linkurls') ); break; case 'configheader': if (empty($name)) { $name = uniqid(mt_rand()); } $conf[$name] = array( '_type' => 'header', 'desc' => $this->_default($curctx, $this->_getNodeOnlyText($node)) ); break; case 'configswitch': $values = $this->_getSwitchValues($node, $ctx); list($default, $isDefault) = $quote ? $this->__default($curctx, $this->_getNodeOnlyText($node)) : $this->__defaultRaw($curctx, $this->_getNodeOnlyText($node)); if ($default === '') { $default = key($values); } if (is_bool($default)) { $default = $default ? 'true' : 'false'; } $conf[$name] = array( 'desc' => $desc, 'switch' => $values, 'default' => $default, 'is_default' => $isDefault, 'quote' => $quote ); break; case 'configenum': $values = $this->_getEnumValues($node); list($default, $isDefault) = $quote ? $this->__default($curctx, $this->_getNodeOnlyText($node)) : $this->__defaultRaw($curctx, $this->_getNodeOnlyText($node)); if ($default === '') { $default = key($values); } if (is_bool($default)) { $default = $default ? 'true' : 'false'; } $conf[$name] = array( '_type' => 'enum', 'required' => $required, 'quote' => $quote, 'values' => $values, 'desc' => $desc, 'default' => $default, 'is_default' => $isDefault ); break; case 'configlist': list($default, $isDefault) = $this->__default($curctx, null); if (is_null($default)) { $default = $this->_getNodeOnlyText($node); } elseif (is_array($default)) { $default = implode(', ', $default); } $conf[$name] = array( '_type' => 'stringlist', 'required' => $required, 'desc' => $desc, 'default' => $default, 'is_default' => $isDefault ); break; case 'configmultienum': $default = $this->_getNodeOnlyText($node); if (strlen($default)) { $default = explode(',', $default); } else { $default = array(); } list($default, $isDefault) = $this->__default($curctx, $default); $conf[$name] = array( '_type' => 'multienum', 'required' => $required, 'values' => $this->_getEnumValues($node), 'desc' => $desc, 'default' => Horde_Array::valuesToKeys($default), 'is_default' => $isDefault ); break; case 'configpassword': $conf[$name] = array( '_type' => 'password', 'required' => $required, 'desc' => $desc, 'default' => $this->_default($curctx, $this->_getNodeOnlyText($node)), 'is_default' => $this->_isDefault($curctx, $this->_getNodeOnlyText($node)) ); break; case 'configstring': $conf[$name] = array( '_type' => 'text', 'required' => $required, 'desc' => $desc, 'default' => $this->_default($curctx, $this->_getNodeOnlyText($node)), 'is_default' => $this->_isDefault($curctx, $this->_getNodeOnlyText($node)) ); if ($conf[$name]['default'] === false) { $conf[$name]['default'] = 'false'; } elseif ($conf[$name]['default'] === true) { $conf[$name]['default'] = 'true'; } break; case 'configboolean': $default = $this->_getNodeOnlyText($node); $default = !(empty($default) || $default === 'false'); $conf[$name] = array( '_type' => 'boolean', 'required' => $required, 'desc' => $desc, 'default' => $this->_default($curctx, $default), 'is_default' => $this->_isDefault($curctx, $default) ); break; case 'configinteger': $values = $this->_getEnumValues($node); $conf[$name] = array( '_type' => 'int', 'required' => $required, 'values' => $values, 'desc' => $desc, 'default' => $this->_default($curctx, $this->_getNodeOnlyText($node)), 'is_default' => $this->_isDefault($curctx, $this->_getNodeOnlyText($node)) ); if ($node->getAttribute('octal') == 'true' && $conf[$name]['default'] != '') { $conf[$name]['_type'] = 'octal'; $conf[$name]['default'] = sprintf('0%o', $this->_default($curctx, octdec($this->_getNodeOnlyText($node)))); } break; case 'configldap': $conf[$node->getAttribute('switchname')] = $this->_configLDAP($ctx, $node); break; case 'configldapuser': $conf = array_merge($conf, $this->_configLDAPUser($ctx, $node)); break; case 'configphp': $conf[$name] = array( '_type' => 'php', 'required' => $required, 'quote' => false, 'desc' => $desc, 'default' => $this->_defaultRaw($curctx, $this->_getNodeOnlyText($node)), 'is_default' => $this->_isDefaultRaw($curctx, $this->_getNodeOnlyText($node)) ); break; case 'configsecret': $conf[$name] = array( '_type' => 'text', 'required' => true, 'desc' => $desc, 'default' => $this->_default($curctx, strval(new Horde_Support_Randomid())), 'is_default' => $this->_isDefault($curctx, $this->_getNodeOnlyText($node)) ); break; case 'configsql': $conf[$node->getAttribute('switchname')] = $this->configSQL($ctx, $node); break; case 'confignosql': $conf[$node->getAttribute('switchname')] = $this->configNoSQL($ctx, $node); break; case 'configvfs': $conf[$node->getAttribute('switchname')] = $this->_configVFS($ctx, $node); break; case 'configsection': $conf[$name] = array(); $cur = &$conf[$name]; if ($node->hasChildNodes()) { $this->_parseLevel($cur, $node->childNodes, $curctx); } break; case 'configtab': $key = uniqid(mt_rand()); $conf[$key] = array( 'tab' => $name, 'desc' => $desc ); if ($node->hasChildNodes()) { $this->_parseLevel($conf, $node->childNodes, $ctx); } break; case 'configplaceholder': $conf[uniqid(mt_rand())] = 'placeholder'; break; default: $conf[$name] = array(); $cur = &$conf[$name]; if ($node->hasChildNodes()) { $this->_parseLevel($cur, $node->childNodes, $curctx); } break; } } } /** * Returns the configuration tree for an LDAP backend configuration to * replace a <configldap> tag. * Subnodes will be parsed and added to both the Horde defaults and the * Custom configuration parts. * * @param string $ctx The context of the <configldap> tag. * @param DomNode $node The DomNode representation of the * <configldap> tag. * @param string $switchname If $node is not set, the value of the tag's * switchname attribute. * * @return array An associative array with the LDAP configuration tree. */ protected function _configLDAP($ctx, $node = null, $switchname = 'driverconfig') { if ($node) { $xpath = new DOMXPath($node->ownerDocument); } $host = $node ? explode(',', ($xpath->evaluate('string(configstring[@name="hostspec"])', $node) ?: '')) : array(); $host = $this->_default($ctx . '|hostspec', $host); $fields = array( 'hostspec' => array( '_type' => 'stringlist', 'required' => true, 'desc' => 'LDAP server(s)/hostname(s)', 'default' => is_array($host) ? implode(',', $host) : $host, ), 'port' => array( '_type' => 'int', 'required' => false, 'desc' => 'Port on which LDAP is listening, if non-standard', 'default' => $this->_default( $ctx . '|port', $node ? ($xpath->evaluate('string(configinteger[@name="port"])', $node) ?: null) : null ) ), 'tls' => array( '_type' => 'boolean', 'required' => false, 'desc' => 'Use TLS to connect to the server?', 'default' => $this->_default( $ctx . '|tls', $node ? ($xpath->evaluate('string(configboolean[@name="tls"])', $node) ?: false) : false ) ), 'timeout' => array( '_type' => 'int', 'required' => false, 'desc' => 'Connection timeout', 'default' => $this->_default( $ctx . '|timeout', $node ? ($xpath->evaluate('string(configinteger[@name="timeout"])', $node) ?: 5) : 5 ) ), 'version' => array( '_type' => 'int', 'required' => true, 'quote' => false, 'desc' => 'LDAP protocol version', 'default' => $this->_default( $ctx . '|version', $node ? ($xpath->evaluate('normalize-space(configswitch[@name="version"]/text())', $node) ?: 3) : 3 ), 'switch' => array( '2' => array( 'desc' => '2 (deprecated)', 'fields' => array() ), '3' => array( 'desc' => '3', 'fields' => array() ) ), ), 'bindas' => array( 'desc' => 'Bind to LDAP as which user?', 'default' => $this->_default( $ctx . '|bindas', $node ? ($xpath->evaluate('normalize-space(configswitch[@name="bindas"]/text())', $node) ?: 'admin') : 'admin' ), 'switch' => array( 'anon' => array( 'desc' => 'Bind anonymously', 'fields' => $this->_configLDAPUser($ctx, $node) ), 'user' => array( 'desc' => 'Bind as the currently logged-in user', 'fields' => $this->_configLDAPUser($ctx, $node) ), 'admin' => array( 'desc' => 'Bind with administrative/system credentials', 'fields' => array_merge( array( 'binddn' => array( '_type' => 'text', 'required' => true, 'desc' => 'DN used to bind to LDAP', 'default' => $this->_default( $ctx . '|binddn', $node ? ($xpath->evaluate('string(configsection/configstring[@name="binddn"])', $node) ?: '') : '' ) ), 'bindpw' => array( '_type' => 'text', 'required' => true, 'desc' => 'Password for bind DN', 'default' => $this->_default( $ctx . '|bindpw', $node ? ($xpath->evaluate('string(configsection/configstring[@name="bindpw"])', $node) ?: '') : '') ) ), $this->_configLDAPUser($ctx, $node) ), ), ) ), ); if (isset($node) && $node->getAttribute('excludebind')) { $excludes = explode(',', $node->getAttribute('excludebind')); foreach ($excludes as $exclude) { unset($fields['bindas']['switch'][$exclude]); } } if (isset($node) && $node->getAttribute('baseconfig') == 'true') { return array( 'desc' => 'Use LDAP?', 'default' => $this->_default( $ctx . '|' . $node->getAttribute('switchname'), $node ? ($xpath->evaluate('normalize-space(text())', $node) ?: false) : false ), 'switch' => array( 'false' => array( 'desc' => 'No', 'fields' => array() ), 'true' => array( 'desc' => 'Yes', 'fields' => $fields ), ) ); } $standardFields = array( 'basedn' => array( '_type' => 'text', 'required' => true, 'desc' => 'Base DN', 'default' => $this->_default( $ctx . '|basedn', $node ? ($xpath->evaluate('string(configstring[@name="basedn"])', $node) ?: '') : '' ) ), 'scope' => array( '_type' => 'enum', 'required' => true, 'desc' => 'Search scope', 'default' => $this->_default( $ctx . '|scope', $node ? ($xpath->evaluate('normalize-space(configenum[@name="scope"]/text())', $node) ?: '') : ''), 'values' => array( 'sub' => 'Subtree search', 'one' => 'One level'), ), ); list($default, $isDefault) = $this->__default($ctx . '|' . (isset($node) ? $node->getAttribute('switchname') : $switchname), 'horde'); $config = array( 'desc' => 'Driver configuration', 'default' => $default, 'is_default' => $isDefault, 'switch' => array( 'horde' => array( 'desc' => 'Horde defaults', 'fields' => $standardFields, ), 'custom' => array( 'desc' => 'Custom parameters', 'fields' => $fields + $standardFields, ) ) ); if (isset($node) && $node->hasChildNodes()) { $cur = array(); $this->_parseLevel($cur, $node->childNodes, $ctx); $config['switch']['horde']['fields'] = array_merge($config['switch']['horde']['fields'], $cur); $config['switch']['custom']['fields'] = array_merge($config['switch']['custom']['fields'], $cur); } return $config; } /** * Returns the configuration tree for an LDAP configuration to search user * DNs to replace a <configldapuser> tag. * * Subnodes will be parsed and added. * * @param string $ctx The context of the <configldapuser> tag. * @param DomNode $node The DomNode representation of the * <configldapuser> tag. * * @return array A list of associative arrays with the LDAP configuration * tree. */ protected function _configLDAPUser($ctx, $node = null) { if ($node) { $xpath = new DOMXPath($node->ownerDocument); } return array( 'user' => array( 'basedn' => array( '_type' => 'text', 'required' => false, 'desc' => 'Base DN for searching the user\'s DN', 'default' => $this->_default( $ctx . '|user|basedn', $node ? ($xpath->evaluate('string(configsection/configstring[@name="basedn"])', $node) ?: '') : '' ) ), 'uid' => array( '_type' => 'text', 'required' => true, 'desc' => 'The username search key (set to samaccountname for AD).', 'default' => $this->_default( $ctx . '|user|uid', $node ? ($xpath->evaluate('string(configsection/configstring[@name="uid"])', $node) ?: 'uid') : 'uid' ) ), 'filter_type' => array( 'required' => false, 'desc' => 'How to specify a filter for the user lists.', 'default' => $this->_default( $ctx . '|user|filter_type', $node ? ($xpath->evaluate('normalize-space(configsection/configswitch[@name="filter_type"]/text())', $node) ?: 'objectclass') : 'objectclass'), 'switch' => array( 'filter' => array( 'desc' => 'LDAP filter string', 'fields' => array( 'filter' => array( '_type' => 'text', 'required' => true, 'desc' => 'The LDAP filter string used to search for users.', 'default' => $this->_default( $ctx . '|user|filter', $node ? ($xpath->evaluate('string(configsection/configstring[@name="filter"])', $node) ?: '(objectClass=*)') : '(objectClass=*)' ) ), ), ), 'objectclass' => array( 'desc' => 'List of objectClasses', 'fields' => array( 'objectclass' => array( '_type' => 'stringlist', 'required' => true, 'desc' => 'The objectclass filter used to search for users. Can be a single objectclass or a comma-separated list.', 'default' => implode(', ', $this->_default( $ctx . '|user|objectclass', $node ? ($xpath->evaluate('string(configsection/configlist[@name="objectclass"])', $node) ?: array('*')) : array('*'))) ), ), ), ), ), ), ); } /** * Returns the configuration tree for a NoSQL backend configuration to * replace a <confignosql> tag. * Subnodes will be parsed and added to both the Horde defaults and the * custom configuration parts. * * @param string $ctx The context of the <confignosql> tag. * @param DomNode $node The DomNode representation of the * <confignosql> tag. * @param string $switchname If DomNode is not set, the value of the * tag's switchname attribute. * * @return array An associative array with the SQL configuration tree. */ public function configNoSQL($ctx, $node = null, $switchname = 'driverconfig') { if ($node) { $xpath = new DOMXPath($node->ownerDocument); } $custom_fields = array( 'required' => true, 'desc' => 'What database backend should we use?', 'default' => $this->_default( $ctx . '|phptype', $node ? $node->getAttribute('default') : '' ), 'switch' => array( 'false' => array( 'desc' => '[None]', 'fields' => array() ), 'mongo' => array( 'desc' => 'MongoDB', 'fields' => array( 'hostspec' => array( '_type' => 'text', 'required' => false, 'desc' => 'Server specification (format: "mongodb://[username:password@]host1[:port1][,host2[:port2:],...]/db"; see http://www.php.net/manual/en/mongoclient.construct.php for further details)', 'default' => $this->_default( $ctx . '|hostspec', $node ? ($xpath->evaluate('string(configstring[@name="hostspec"])', $node) ?: '') : '' ) ), 'dbname' => array( '_type' => 'text', 'required' => false, 'desc' => 'Database name to use', 'default' => $this->_default( $ctx . '|dbname', $node ? ($xpath->evaluate('string(configstring[@name="dbname"])', $node) ?: '') : '' ) ) ) ) ) ); if (isset($node) && $node->getAttribute('baseconfig') == 'true') { return $custom_fields; } list($default, $isDefault) = $this->__default($ctx . '|' . (isset($node) ? $node->getAttribute('switchname') : $switchname), 'horde'); $config = array( 'desc' => 'NoSQL driver configuration', 'default' => $default, 'is_default' => $isDefault, 'switch' => array( 'horde' => array( 'desc' => 'Horde defaults', 'fields' => array() ), 'custom' => array( 'desc' => 'Custom parameters', 'fields' => array( 'phptype' => $custom_fields ) ) ) ); if (isset($node) && $node->hasChildNodes()) { $cur = array(); $this->_parseLevel($cur, $node->childNodes, $ctx); $config['switch']['horde']['fields'] = array_merge($config['switch']['horde']['fields'], $cur); $config['switch']['custom']['fields'] = array_merge($config['switch']['custom']['fields'], $cur); } return $config; } /** * Returns the configuration tree for an SQL backend configuration to * replace a <configsql> tag. * Subnodes will be parsed and added to both the Horde defaults and the * Custom configuration parts. * * @param string $ctx The context of the <configsql> tag. * @param DomNode $node The DomNode representation of the <configsql> * tag. * @param string $switchname If DomNode is not set, the value of the * tag's switchname attribute. * * @return array An associative array with the SQL configuration tree. */ public function configSQL($ctx, $node = null, $switchname = 'driverconfig') { if ($node) { $xpath = new DOMXPath($node->ownerDocument); } $hostspec = array( '_type' => 'text', 'required' => true, 'desc' => 'Database server/host', 'default' => $this->_default( $ctx . '|hostspec', $node ? ($xpath->evaluate('string(configstring[@name="hostspec"])', $node) ?: '') : '' ) ); $username = array( '_type' => 'text', 'required' => true, 'desc' => 'Username to connect to the database as', 'default' => $this->_default( $ctx . '|username', $node ? ($xpath->evaluate('string(configstring[@name="username"])', $node) ?: '') : '' ) ); $password = array( '_type' => 'text', 'required' => false, 'desc' => 'Password to connect with', 'default' => $this->_default( $ctx . '|password', $node ? ($xpath->evaluate('string(configstring[@name="password"])', $node) ?: '') : '' ) ); $database = array( '_type' => 'text', 'required' => true, 'desc' => 'Database name to use', 'default' => $this->_default( $ctx . '|database', $node ? ($xpath->evaluate('string(configstring[@name="database"])', $node) ?: '') : '' ) ); $socket = array( '_type' => 'text', 'required' => false, 'desc' => 'Location of UNIX socket', 'default' => $this->_default( $ctx . '|socket', $node ? ($xpath->evaluate('string(configstring[@name="socket"])', $node) ?: '') : '' ) ); $port = array( '_type' => 'int', 'required' => false, 'desc' => 'Port the DB is running on, if non-standard', 'default' => $this->_default( $ctx . '|port', $node ? ($xpath->evaluate('string(configinteger[@name="port"])', $node) ?: null) : null) ); $protocol = array( 'desc' => 'How should we connect to the database?', 'default' => $this->_default( $ctx . '|protocol', $node ? ($xpath->evaluate('normalize-space(configswitch[@name="protocol"]/text())', $node) ?: 'unix') : 'unix'), 'switch' => array( 'unix' => array( 'desc' => 'UNIX Sockets', 'fields' => array( 'socket' => $socket ) ), 'tcp' => array( 'desc' => 'TCP/IP', 'fields' => array( 'hostspec' => $hostspec, 'port' => $port ) ) ) ); $mysql_protocol = $protocol; $mysql_protocol['switch']['tcp']['fields']['port']['default'] = $this->_default( $ctx . '|port', $node ? ($xpath->evaluate('string(configinteger[@name="port"])', $node) ?: 3306) : 3306 ); $pgsql_protocol = $protocol; $pgsql_protocol['switch']['unix']['fields']['port'] = $port; $charset = array( '_type' => 'text', 'required' => true, 'desc' => 'Internally used charset', 'default' => $this->_default( $ctx . '|charset', $node ? ($xpath->evaluate('string(configstring[@name="charset"])', $node) ?: 'utf-8') : 'utf-8') ); $ssl = array( '_type' => 'boolean', 'required' => false, 'desc' => 'Use SSL to connect to the server?', 'default' => $this->_default( $ctx . '|ssl', $node ? ($xpath->evaluate('string(configboolean[@name="ssl"])', $node) ?: false) : false), 'switch' => array( 'false' => array('desc' => 'No', 'fields' => array()), 'true' => array( 'desc' => 'Yes', 'fields' => array( 'ca' => array( '_type' => 'text', 'required' => false, 'desc' => 'Certification Authority to use for SSL connections', 'default' => $this->_default( $ctx . '|ca', $node ? ($xpath->evaluate('string(configstring[@name="ca"])', $node) ?: '') : '' ) ) ) ) ) ); list($default, $isDefault) = $this->__default( $ctx . '|logqueries', $node ? ($xpath->evaluate('string(configboolean[@name="logqueries"])', $node) ?: false) : false); $logqueries = array( '_type' => 'boolean', 'required' => false, 'desc' => 'Should Horde log all queries. If selected, queries will be logged at the DEBUG level to your configured logger.', 'default' => $default, 'is_default' => $isDefault, ); $custom_fields = array( 'required' => true, 'desc' => 'What database backend should we use?', 'default' => $this->_default( $ctx . '|phptype', $node ? $node->getAttribute('default') : '' ), 'switch' => array( 'false' => array( 'desc' => '[None]', 'fields' => array() ), 'mysql' => array( 'desc' => 'MySQL / PDO', 'fields' => array( 'username' => $username, 'password' => $password, 'protocol' => $mysql_protocol, 'database' => $database, 'charset' => $charset, 'ssl' => $ssl, 'splitread' => $this->_configSQLSplitRead($ctx, $node, 'mysql'), 'logqueries' => $logqueries, ) ), 'mysqli' => array( 'desc' => 'MySQL (mysqli)', 'fields' => array( 'username' => $username, 'password' => $password, 'protocol' => $mysql_protocol, 'database' => $database, 'charset' => $charset, 'ssl' => $ssl, 'splitread' => $this->_configSQLSplitRead($ctx, $node, 'mysqli'), 'logqueries' => $logqueries, ) ), 'oci8' => array( 'desc' => 'Oracle', 'fields' => array( 'username' => $username, 'password' => $password, 'charset' => $charset, 'method' => array( 'desc' => 'How should the database connection be specified', 'default' => $this->_default( $ctx . '|method', $node ? ($xpath->evaluate('normalize-space(configswitch[@name="method"]/text())', $node) ?: 'easy') : 'easy'), 'switch' => array( 'tns' => array( 'desc' => 'TNS', 'fields' => array( 'tns' => array( '_type' => 'text', 'required' => true, 'desc' => 'Connect name from tnsnames.ora', 'default' => $this->_default( $ctx . '|tns', $node ? ($xpath->evaluate('string(configstring[@name="tns"])', $node) ?: false) : false), ), ), ), 'easy' => array( 'desc' => 'Easy Connect', 'fields' => array( 'hostspec' => $hostspec, 'port' => $port, 'service' => array( '_type' => 'text', 'required' => false, 'desc' => 'Service name', 'default' => $this->_default( $ctx . '|service', $node ? ($xpath->evaluate('string(configstring[@name="service"])', $node) ?: false) : false), ), 'type' => array( '_type' => 'text', 'required' => false, 'desc' => 'Server type', 'default' => $this->_default( $ctx . '|type', $node ? ($xpath->evaluate('string(configstring[@name="type"])', $node) ?: false) : false), ), 'instance' => array( '_type' => 'text', 'required' => false, 'desc' => 'Instance name', 'default' => $this->_default( $ctx . '|instance', $node ? ($xpath->evaluate('string(configstring[@name="instance"])', $node) ?: false) : false), ), ), ), ), ), 'logqueries' => $logqueries, ), ), 'pgsql' => array( 'desc' => 'PostgreSQL', 'fields' => array( 'username' => $username, 'password' => $password, 'protocol' => $pgsql_protocol, 'database' => $database, 'charset' => $charset, 'splitread' => $this->_configSQLSplitRead($ctx, $node, 'pgsql'), 'logqueries' => $logqueries, ) ), 'sqlite' => array( 'desc' => 'SQLite', 'fields' => array( 'database' => array( '_type' => 'text', 'required' => true, 'desc' => 'Absolute path to the database file', 'default' => $this->_default( $ctx . '|database', $node ? ($xpath->evaluate('string(configstring[@name="database"])', $node) ?: '') : '' ) ), 'charset' => $charset, 'logqueries' => $logqueries, ) ) ) ); if (isset($node) && $node->getAttribute('baseconfig') == 'true') { return $custom_fields; } list($default, $isDefault) = $this->__default($ctx . '|' . (isset($node) ? $node->getAttribute('switchname') : $switchname), 'horde'); $config = array( 'desc' => 'Driver configuration', 'default' => $default, 'is_default' => $isDefault, 'switch' => array( 'horde' => array( 'desc' => 'Horde defaults', 'fields' => array() ), 'custom' => array( 'desc' => 'Custom parameters', 'fields' => array( 'phptype' => $custom_fields ) ) ) ); if (isset($node) && $node->hasChildNodes()) { $cur = array(); $this->_parseLevel($cur, $node->childNodes, $ctx); $config['switch']['horde']['fields'] = array_merge($config['switch']['horde']['fields'], $cur); $config['switch']['custom']['fields'] = array_merge($config['switch']['custom']['fields'], $cur); } return $config; } /** * Returns the configuration items for split-read database setups. * * @param string $ctx The context of the <configsql> tag. * @param DomNode $node The DomNode representation of the <configsql> * tag. * @param string $phptype The SQL backend name. * * @return array An associative array with the split-read SQL * configuration tree. */ protected function _configSQLSplitRead($ctx, $node, $phptype) { if (preg_match('/\|read$/', $ctx)) { return null; } if ($node) { $xpath = new DOMXPath($node->ownerDocument); } $splitread_fields = $this->configSQL($ctx . '|read'); $splitread_fields = $splitread_fields['switch']['custom']['fields']['phptype']['switch'][$phptype]['fields']; return array( '_type' => 'boolean', 'required' => false, 'desc' => 'Split reads to a different server?', 'default' => $this->_default( $ctx . '|splitread', $node ? ($xpath->evaluate('normalize-space(configswitch[@name="splitread"]/text())', $node) ?: 'false') : 'false'), 'switch' => array( 'false' => array( 'desc' => 'Disabled', 'fields' => array() ), 'true' => array( 'desc' => 'Enabled', 'fields' => array('read' => $splitread_fields) ) ) ); } /** * Returns the configuration tree for a VFS backend configuration to * replace a <configvfs> tag. * Subnodes will be parsed and added to both the Horde defaults and the * Custom configuration parts. * * @param string $ctx The context of the <configvfs> tag. * @param DomNode $node The DomNode representation of the <configvfs> * tag. * * @return array An associative array with the VFS configuration tree. */ protected function _configVFS($ctx, $node) { $nosql = $this->configNoSQL($ctx . '|params'); $sql = $this->configSQL($ctx . '|params'); $default = $node->getAttribute('default'); $default = empty($default) ? 'horde' : $default; list($default, $isDefault) = $this->__default($ctx . '|' . $node->getAttribute('switchname'), $default); $xpath = new DOMXPath($node->ownerDocument); $config = array( 'desc' => 'What VFS driver should we use?', 'default' => $default, 'is_default' => $isDefault, 'switch' => array( 'None' => array( 'desc' => 'None', 'fields' => array() ), 'File' => array( 'desc' => 'Files on the local system', 'fields' => array( 'params' => array( 'vfsroot' => array( '_type' => 'text', 'desc' => 'Where on the real filesystem should Horde use as root of the virtual filesystem?', 'default' => $this->_default( $ctx . '|params|vfsroot', $xpath->evaluate('string(configsection/configstring[@name="vfsroot"])', $node) ?: '/tmp' ) ) ) ) ), 'Nosql' => array( 'desc' => 'NoSQL database', 'fields' => array( 'params' => array( 'driverconfig' => $nosql ) ) ), 'Sql' => array( 'desc' => 'SQL database', 'fields' => array( 'params' => array( 'driverconfig' => $sql ) ) ), 'Ssh2' => array( 'desc' => 'SSH2 (SFTP)', 'fields' => array( 'params' => array( 'hostspec' => array( '_type' => 'text', 'required' => true, 'desc' => 'SSH server/host', 'default' => $this->_default( $ctx . '|hostspec', $xpath->evaluate('string(configsection/configstring[@name="hostspec"])', $node) ?: '' ) ), 'port' => array( '_type' => 'text', 'required' => false, 'desc' => 'Port number on which SSH listens', 'default' => $this->_default( $ctx . '|port', $xpath->evaluate('string(configsection/configstring[@name="port"])', $node) ?: '22' ) ), 'username' => array( '_type' => 'text', 'required' => true, 'desc' => 'Username to connect to the SSH server', 'default' => $this->_default( $ctx . '|username', $xpath->evaluate('string(configsection/configstring[@name="username"])', $node) ?: '' ) ), 'password' => array( '_type' => 'text', 'required' => true, 'desc' => 'Password with which to connect', 'default' => $this->_default( $ctx . '|password', $xpath->evaluate('string(configsection/configstring[@name="password"])', $node) ?: '' ) ), 'vfsroot' => array( '_type' => 'text', 'desc' => 'Where on the real filesystem should Horde use as root of the virtual filesystem?', 'default' => $this->_default( $ctx . '|vfsroot', $xpath->evaluate('string(configsection/configstring[@name="vfsroot"])', $node) ?: '/tmp') ) ) ) ) ) ); if (isset($node) && $node->getAttribute('baseconfig') != 'true') { $config['switch']['horde'] = array( 'desc' => 'Horde defaults', 'fields' => array() ); } $cases = $this->_getSwitchValues($node, $ctx . '|params'); foreach ($cases as $case => $fields) { if (isset($config['switch'][$case])) { $config['switch'][$case]['fields']['params'] = array_merge($config['switch'][$case]['fields']['params'], $fields['fields']); } } return $config; } /** * Returns a certain value from the current configuration array or * a default value, if not found. * * @param string $ctx A string representing the key of the * configuration array to return. * @param mixed $default The default value to return if the key wasn't * found. * * @return mixed Either the value of the configuration array's requested * key or the default value if the key wasn't found. */ protected function _default($ctx, $default) { list ($ptr,) = $this->__default($ctx, $default); return $ptr; } /** * Returns whether a certain value from the current configuration array * exists or a default value will be used. * * @param string $ctx A string representing the key of the * configuration array to return. * @param mixed $default The default value to return if the key wasn't * found. * * @return boolean Whether the default value will be used. */ protected function _isDefault($ctx, $default) { list (,$isDefault) = $this->__default($ctx, $default); return $isDefault; } /** * Returns a certain value from the current configuration array or a * default value, if not found, and which of the values have been * returned. * * @param string $ctx A string representing the key of the * configuration array to return. * @param mixed $default The default value to return if the key wasn't * found. * * @return array First element: either the value of the configuration * array's requested key or the default value if the key * wasn't found. * Second element: whether the returned value was the * default value. */ protected function __default($ctx, $default) { $ctx = explode('|', $ctx); $ptr = $this->_currentConfig; for ($i = 0, $ctx_count = count($ctx); $i < $ctx_count; ++$i) { if (!isset($ptr[$ctx[$i]])) { return array($default, true); } $ptr = $ptr[$ctx[$i]]; } return array($ptr, false); } /** * Returns a certain value from the current configuration file or * a default value, if not found. * It does NOT return the actual value, but the PHP expression as used * in the configuration file. * * @param string $ctx A string representing the key of the * configuration array to return. * @param mixed $default The default value to return if the key wasn't * found. * * @return mixed Either the value of the configuration file's requested * key or the default value if the key wasn't found. */ protected function _defaultRaw($ctx, $default) { list ($ptr,) = $this->__defaultRaw($ctx, $default); return $ptr; } /** * Returns whether a certain value from the current configuration array * exists or a default value will be used. * * @param string $ctx A string representing the key of the * configuration array to return. * @param mixed $default The default value to return if the key wasn't * found. * * @return boolean Whether the default value will be used. */ protected function _isDefaultRaw($ctx, $default) { list (,$isDefault) = $this->__defaultRaw($ctx, $default); return $isDefault; } /** * Returns a certain value from the current configuration file or * a default value, if not found, and which of the values have been * returned. * * It does NOT return the actual value, but the PHP expression as used * in the configuration file. * * @param string $ctx A string representing the key of the * configuration array to return. * @param mixed $default The default value to return if the key wasn't * found. * * @return array First element: either the value of the configuration * array's requested key or the default value if the key * wasn't found. * Second element: whether the returned value was the * default value. */ protected function __defaultRaw($ctx, $default) { $ctx = explode('|', $ctx); $pattern = '/^\$conf\[\'' . implode("'\]\['", $ctx) . '\'\] = (.*);\r?$/m'; return preg_match($pattern, $this->getPHPConfig(), $matches) ? array($matches[1], false) : array($default, true); } /** * Returns the content of all text node children of the specified node. * * @param DomNode $node A DomNode object whose text node children to * return. * * @return string The concatenated values of all text nodes. */ protected function _getNodeOnlyText($node) { $text = ''; if (!$node->hasChildNodes()) { return $node->textContent; } foreach ($node->childNodes as $tnode) { if ($tnode->nodeType == XML_TEXT_NODE) { $text .= $tnode->textContent; } } return trim($text); } /** * Returns an associative array containing all possible values of the * specified <configenum> tag. * * The keys contain the actual enum values while the values contain their * corresponding descriptions. * * @param DomNode $node The DomNode representation of the <configenum> * tag whose values should be returned. * * @return array An associative array with all possible enum values. */ protected function _getEnumValues($node) { $values = array(); if (!$node->hasChildNodes()) { return $values; } foreach ($node->childNodes as $vnode) { if ($vnode->nodeType == XML_ELEMENT_NODE && $vnode->tagName == 'values') { if (!$vnode->hasChildNodes()) { return array(); } foreach ($vnode->childNodes as $value) { if ($value->nodeType == XML_ELEMENT_NODE) { if ($value->tagName == 'configspecial') { return $this->_handleSpecials($value); } if ($value->tagName == 'value') { $text = $value->textContent; $desc = $value->getAttribute('desc'); $values[$text] = empty($desc) ? $text : $desc; } } } } } return $values; } /** * Returns a multidimensional associative array representing the specified * <configswitch> tag. * * @param DomNode &$node The DomNode representation of the <configswitch> * tag to process. * * @return array An associative array representing the node. */ protected function _getSwitchValues(&$node, $curctx) { $values = array(); if (!$node->hasChildNodes()) { return $values; } foreach ($node->childNodes as $case) { if ($case->nodeType == XML_ELEMENT_NODE) { $name = $case->getAttribute('name'); $values[$name] = array( 'desc' => $case->getAttribute('desc'), 'fields' => array() ); if ($case->hasChildNodes()) { $this->_parseLevel($values[$name]['fields'], $case->childNodes, $curctx); } } } return $values; } /** * Returns an associative array containing the possible values of a * <configspecial> tag as used inside of enum configurations. * * @param DomNode $node The DomNode representation of the <configspecial> * tag. * * @return array An associative array with the possible values. */ protected function _handleSpecials($node) { $app = $node->getAttribute('application'); try { if (!in_array($app, $GLOBALS['registry']->listApps())) { $app = $GLOBALS['registry']->hasInterface($app); } } catch (Horde_Exception $e) { return array(); } if (!$app) { return array(); } try { return $GLOBALS['registry']->callAppMethod($app, 'configSpecialValues', array('args' => array($node->getAttribute('name')), 'noperms' => true)); } catch (Horde_Exception $e) { return array(); } } /** * Returns the specified string with escaped single quotes * * @param string $string A string to escape. * * @return string The specified string with single quotes being escaped. */ protected function _quote($string) { return str_replace("'", "\'", $string); } }
Simpan