PageRenderTime 58ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/horde-3.3.13/lib/Horde/Config.php

#
PHP | 1464 lines | 1076 code | 68 blank | 320 comment | 92 complexity | 8a345bf0823ec3da8ac8c38a62c41239 MD5 | raw file
Possible License(s): LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * @package Horde_Framework
  4. */
  5. /**
  6. * Horde_DOM
  7. */
  8. include_once 'Horde/DOM.php';
  9. /**
  10. * Horde_Form
  11. */
  12. include_once 'Horde/Form.php';
  13. /**
  14. * Horde_Form_Renderer
  15. */
  16. include_once 'Horde/Form/Renderer.php';
  17. /**
  18. * The Config:: package provides a framework for managing the
  19. * configuration of Horde applications, writing conf.php files from
  20. * conf.xml source files, generating user interfaces, etc.
  21. *
  22. * $Horde: framework/Horde/Horde/Config.php,v 1.80.2.40 2009/02/25 05:35:42 chuck Exp $
  23. *
  24. * Copyright 2002-2009 The Horde Project (http://www.horde.org/)
  25. *
  26. * See the enclosed file COPYING for license information (LGPL). If you
  27. * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  28. *
  29. * @author Chuck Hagenbuch <chuck@horde.org>
  30. * @since Horde 3.0
  31. * @package Horde_Framework
  32. */
  33. class Horde_Config {
  34. /**
  35. * The name of the configured application.
  36. *
  37. * @var string
  38. */
  39. var $_app;
  40. /**
  41. * The XML tree of the configuration file traversed to an
  42. * associative array.
  43. *
  44. * @var array
  45. */
  46. var $_xmlConfigTree = null;
  47. /**
  48. * The content of the generated configuration file.
  49. *
  50. * @var string
  51. */
  52. var $_phpConfig;
  53. /**
  54. * The content of the old configuration file.
  55. *
  56. * @var string
  57. */
  58. var $_oldConfig;
  59. /**
  60. * The manual configuration in front of the generated configuration.
  61. *
  62. * @var string
  63. */
  64. var $_preConfig;
  65. /**
  66. * The manual configuration after the generated configuration.
  67. *
  68. * @var string
  69. */
  70. var $_postConfig;
  71. /**
  72. * The current $conf array of the configured application.
  73. *
  74. * @var array
  75. */
  76. var $_currentConfig = array();
  77. /**
  78. * The CVS version tag of the conf.xml file which will be copied into the
  79. * conf.php file.
  80. *
  81. * @var string
  82. */
  83. var $_versionTag = '';
  84. /**
  85. * The line marking the begin of the generated configuration.
  86. *
  87. * @var string
  88. */
  89. var $_configBegin = "/* CONFIG START. DO NOT CHANGE ANYTHING IN OR AFTER THIS LINE. */\n";
  90. /**
  91. * The line marking the end of the generated configuration.
  92. *
  93. * @var string
  94. */
  95. var $_configEnd = "/* CONFIG END. DO NOT CHANGE ANYTHING IN OR BEFORE THIS LINE. */\n";
  96. /**
  97. * Constructor.
  98. *
  99. * @param string $app The name of the application to be configured.
  100. */
  101. function Horde_Config($app)
  102. {
  103. $this->_app = $app;
  104. }
  105. /**
  106. * Reads the application's conf.xml file and builds an associative array
  107. * from its XML tree.
  108. *
  109. * @param array $custom_conf Any settings that shall be included in the
  110. * generated configuration.
  111. *
  112. * @return array An associative array representing the configuration tree.
  113. */
  114. function readXMLConfig($custom_conf = null)
  115. {
  116. if (is_null($this->_xmlConfigTree) || $custom_conf) {
  117. require_once 'Horde/Text.php';
  118. global $registry;
  119. $path = $registry->get('fileroot', $this->_app) . '/config';
  120. if ($custom_conf) {
  121. $this->_currentConfig = $custom_conf;
  122. } else {
  123. /* Fetch the current conf.php contents. */
  124. @eval($this->getPHPConfig());
  125. if (isset($conf)) {
  126. $this->_currentConfig = $conf;
  127. }
  128. }
  129. /* Load the DOM object. */
  130. $doc = Horde_DOM_Document::factory(array('filename' => $path . '/conf.xml'));
  131. /* Check if there is a CVS version tag and store it. */
  132. $node = $doc->first_child();
  133. while (!empty($node)) {
  134. if ($node->type == XML_COMMENT_NODE) {
  135. if (preg_match('/\$.*?conf\.xml,v .*? .*\$/', $node->node_value(), $match)) {
  136. $this->_versionTag = $match[0] . "\n";
  137. break;
  138. }
  139. }
  140. $node = $node->next_sibling();
  141. }
  142. /* Parse the config file. */
  143. $this->_xmlConfigTree = array();
  144. $root = $doc->root();
  145. if ($root->has_child_nodes()) {
  146. $this->_parseLevel($this->_xmlConfigTree, $root->child_nodes(), '');
  147. }
  148. }
  149. return $this->_xmlConfigTree;
  150. }
  151. /**
  152. * Returns the file content of the current configuration file.
  153. *
  154. * @return string The unparsed configuration file content.
  155. */
  156. function getPHPConfig()
  157. {
  158. if (is_null($this->_oldConfig)) {
  159. global $registry;
  160. $path = $registry->get('fileroot', $this->_app) . '/config';
  161. if (file_exists($path . '/conf.php')) {
  162. $this->_oldConfig = file_get_contents($path . '/conf.php');
  163. if (!empty($this->_oldConfig)) {
  164. $this->_oldConfig = preg_replace('/<\?php\n?/', '', $this->_oldConfig);
  165. $pos = strpos($this->_oldConfig, $this->_configBegin);
  166. if ($pos !== false) {
  167. $this->_preConfig = substr($this->_oldConfig, 0, $pos);
  168. $this->_oldConfig = substr($this->_oldConfig, $pos);
  169. }
  170. $pos = strpos($this->_oldConfig, $this->_configEnd);
  171. if ($pos !== false) {
  172. $this->_postConfig = substr($this->_oldConfig, $pos + strlen($this->_configEnd));
  173. $this->_oldConfig = substr($this->_oldConfig, 0, $pos);
  174. }
  175. }
  176. } else {
  177. $this->_oldConfig = '';
  178. }
  179. }
  180. return $this->_oldConfig;
  181. }
  182. /**
  183. * Generates the content of the application's configuration file.
  184. *
  185. * @param Variables $formvars The processed configuration form data.
  186. * @param array $custom_conf Any settings that shall be included in the
  187. * generated configuration.
  188. *
  189. * @return string The content of the generated configuration file.
  190. */
  191. function generatePHPConfig($formvars, $custom_conf = null)
  192. {
  193. $this->readXMLConfig($custom_conf);
  194. $this->getPHPConfig();
  195. $this->_phpConfig = "<?php\n";
  196. $this->_phpConfig .= $this->_preConfig;
  197. $this->_phpConfig .= $this->_configBegin;
  198. if (!empty($this->_versionTag)) {
  199. $this->_phpConfig .= '// ' . $this->_versionTag;
  200. }
  201. $this->_generatePHPConfig($this->_xmlConfigTree, '', $formvars);
  202. $this->_phpConfig .= $this->_configEnd;
  203. $this->_phpConfig .= $this->_postConfig;
  204. return $this->_phpConfig;
  205. }
  206. /**
  207. * Generates the configuration file items for a part of the configuration
  208. * tree.
  209. *
  210. * @access private
  211. *
  212. * @param array $section An associative array containing the part of the
  213. * traversed XML configuration tree that should be
  214. * processed.
  215. * @param string $prefix A configuration prefix determining the current
  216. * position inside the configuration file. This
  217. * prefix will be translated to keys of the $conf
  218. * array in the generated configuration file.
  219. * @param Variables $formvars The processed configuration form data.
  220. */
  221. function _generatePHPConfig($section, $prefix, $formvars)
  222. {
  223. if (!is_array($section)) {
  224. return;
  225. }
  226. foreach ($section as $name => $configitem) {
  227. $prefixedname = empty($prefix) ? $name : $prefix . '|' . $name;
  228. $configname = str_replace('|', '__', $prefixedname);
  229. $quote = !isset($configitem['quote']) || $configitem['quote'] !== false;
  230. if ($configitem == 'placeholder') {
  231. $this->_phpConfig .= '$conf[\'' . str_replace('|', '\'][\'', $prefix) . "'] = array();\n";
  232. } elseif (isset($configitem['switch'])) {
  233. $val = $formvars->getExists($configname, $wasset);
  234. if (!$wasset) {
  235. $val = isset($configitem['default']) ? $configitem['default'] : null;
  236. }
  237. if (isset($configitem['switch'][$val])) {
  238. $value = $val;
  239. if ($quote && $value != 'true' && $value != 'false') {
  240. $value = "'" . $value . "'";
  241. }
  242. $this->_generatePHPConfig($configitem['switch'][$val]['fields'], $prefix, $formvars);
  243. }
  244. } elseif (isset($configitem['_type'])) {
  245. $val = $formvars->getExists($configname, $wasset);
  246. if (!$wasset) {
  247. $val = isset($configitem['default']) ? $configitem['default'] : null;
  248. }
  249. $type = $configitem['_type'];
  250. switch ($type) {
  251. case 'multienum':
  252. if (is_array($val)) {
  253. $encvals = array();
  254. foreach ($val as $v) {
  255. $encvals[] = $this->_quote($v);
  256. }
  257. $arrayval = "'" . implode('\', \'', $encvals) . "'";
  258. if ($arrayval == "''") {
  259. $arrayval = '';
  260. }
  261. } else {
  262. $arrayval = '';
  263. }
  264. $value = 'array(' . $arrayval . ')';
  265. break;
  266. case 'boolean':
  267. if (is_bool($val)) {
  268. $value = $val ? 'true' : 'false';
  269. } else {
  270. $value = ($val == 'on') ? 'true' : 'false';
  271. }
  272. break;
  273. case 'stringlist':
  274. $values = explode(',', $val);
  275. if (!is_array($values)) {
  276. $value = "array('" . $this->_quote(trim($values)) . "')";
  277. } else {
  278. $encvals = array();
  279. foreach ($values as $v) {
  280. $encvals[] = $this->_quote(trim($v));
  281. }
  282. $arrayval = "'" . implode('\', \'', $encvals) . "'";
  283. if ($arrayval == "''") {
  284. $arrayval = '';
  285. }
  286. $value = 'array(' . $arrayval . ')';
  287. }
  288. break;
  289. case 'int':
  290. if ($val !== '') {
  291. $value = (int)$val;
  292. }
  293. break;
  294. case 'octal':
  295. $value = sprintf('0%o', octdec($val));
  296. break;
  297. case 'header':
  298. case 'description':
  299. break;
  300. default:
  301. if ($val != '') {
  302. $value = $val;
  303. if ($quote && $value != 'true' && $value != 'false') {
  304. $value = "'" . $this->_quote($value) . "'";
  305. }
  306. }
  307. break;
  308. }
  309. } else {
  310. $this->_generatePHPConfig($configitem, $prefixedname, $formvars);
  311. }
  312. if (isset($value)) {
  313. $this->_phpConfig .= '$conf[\'' . str_replace('__', '\'][\'', $configname) . '\'] = ' . $value . ";\n";
  314. }
  315. unset($value);
  316. }
  317. }
  318. /**
  319. * Parses one level of the configuration XML tree into the associative
  320. * array containing the traversed configuration tree.
  321. *
  322. * @access private
  323. *
  324. * @param array &$conf The already existing array where the processed
  325. * XML tree portion should be appended to.
  326. * @param array $children An array containing the XML nodes of the level
  327. * that should be parsed.
  328. * @param string $ctx A string representing the current position
  329. * (context prefix) inside the configuration XML
  330. * file.
  331. */
  332. function _parseLevel(&$conf, $children, $ctx)
  333. {
  334. require_once 'Horde/Text/Filter.php';
  335. foreach ($children as $node) {
  336. if ($node->type != XML_ELEMENT_NODE) {
  337. continue;
  338. }
  339. $name = $node->get_attribute('name');
  340. $desc = Text_Filter::filter($node->get_attribute('desc'), 'linkurls', array('callback' => 'Horde::externalUrl'));
  341. $required = !($node->get_attribute('required') == 'false');
  342. $quote = !($node->get_attribute('quote') == 'false');
  343. if (!empty($ctx)) {
  344. $curctx = $ctx . '|' . $name;
  345. } else {
  346. $curctx = $name;
  347. }
  348. switch ($node->tagname) {
  349. case 'configdescription':
  350. if (empty($name)) {
  351. $name = md5(uniqid(mt_rand(), true));
  352. }
  353. $conf[$name] = array('_type' => 'description',
  354. 'desc' => Text_Filter::filter($this->_default($curctx, $this->_getNodeOnlyText($node)), 'linkurls', array('callback' => 'Horde::externalUrl')));
  355. break;
  356. case 'configheader':
  357. if (empty($name)) {
  358. $name = md5(uniqid(mt_rand(), true));
  359. }
  360. $conf[$name] = array('_type' => 'header',
  361. 'desc' => $this->_default($curctx, $this->_getNodeOnlyText($node)));
  362. break;
  363. case 'configswitch':
  364. $values = $this->_getSwitchValues($node, $ctx);
  365. if ($quote) {
  366. list($default, $isDefault) = $this->__default($curctx, $this->_getNodeOnlyText($node));
  367. } else {
  368. list($default, $isDefault) = $this->__defaultRaw($curctx, $this->_getNodeOnlyText($node));
  369. }
  370. if ($default === '') {
  371. $default = key($values);
  372. }
  373. if (is_bool($default)) {
  374. $default = $default ? 'true' : 'false';
  375. }
  376. $conf[$name] = array('desc' => $desc,
  377. 'switch' => $values,
  378. 'default' => $default,
  379. 'is_default' => $isDefault);
  380. break;
  381. case 'configenum':
  382. $values = $this->_getEnumValues($node);
  383. if ($quote) {
  384. list($default, $isDefault) = $this->__default($curctx, $this->_getNodeOnlyText($node));
  385. } else {
  386. list($default, $isDefault) = $this->__defaultRaw($curctx, $this->_getNodeOnlyText($node));
  387. }
  388. if ($default === '') {
  389. $default = key($values);
  390. }
  391. if (is_bool($default)) {
  392. $default = $default ? 'true' : 'false';
  393. }
  394. $conf[$name] = array('_type' => 'enum',
  395. 'required' => $required,
  396. 'quote' => $quote,
  397. 'values' => $values,
  398. 'desc' => $desc,
  399. 'default' => $default,
  400. 'is_default' => $isDefault);
  401. break;
  402. case 'configlist':
  403. list($default, $isDefault) = $this->__default($curctx, null);
  404. if ($default === null) {
  405. $default = $this->_getNodeOnlyText($node);
  406. } elseif (is_array($default)) {
  407. $default = implode(', ', $default);
  408. }
  409. $conf[$name] = array('_type' => 'stringlist',
  410. 'required' => $required,
  411. 'desc' => $desc,
  412. 'default' => $default,
  413. 'is_default' => $isDefault);
  414. break;
  415. case 'configmultienum':
  416. $values = $this->_getEnumValues($node);
  417. require_once 'Horde/Array.php';
  418. list($default, $isDefault) = $this->__default($curctx, explode(',', $this->_getNodeOnlyText($node)));
  419. $conf[$name] = array('_type' => 'multienum',
  420. 'required' => $required,
  421. 'values' => $values,
  422. 'desc' => $desc,
  423. 'default' => Horde_Array::valuesToKeys($default),
  424. 'is_default' => $isDefault);
  425. break;
  426. case 'configpassword':
  427. $conf[$name] = array('_type' => 'password',
  428. 'required' => $required,
  429. 'desc' => $desc,
  430. 'default' => $this->_default($curctx, $this->_getNodeOnlyText($node)),
  431. 'is_default' => $this->_isDefault($curctx, $this->_getNodeOnlyText($node)));
  432. break;
  433. case 'configstring':
  434. $conf[$name] = array('_type' => 'text',
  435. 'required' => $required,
  436. 'desc' => $desc,
  437. 'default' => $this->_default($curctx, $this->_getNodeOnlyText($node)),
  438. 'is_default' => $this->_isDefault($curctx, $this->_getNodeOnlyText($node)));
  439. if ($conf[$name]['default'] === false) {
  440. $conf[$name]['default'] = 'false';
  441. } elseif ($conf[$name]['default'] === true) {
  442. $conf[$name]['default'] = 'true';
  443. }
  444. break;
  445. case 'configboolean':
  446. $default = $this->_getNodeOnlyText($node);
  447. if (empty($default) || $default === 'false') {
  448. $default = false;
  449. } else {
  450. $default = true;
  451. }
  452. $conf[$name] = array('_type' => 'boolean',
  453. 'required' => $required,
  454. 'desc' => $desc,
  455. 'default' => $this->_default($curctx, $default),
  456. 'is_default' => $this->_isDefault($curctx, $default));
  457. break;
  458. case 'configinteger':
  459. $values = $this->_getEnumValues($node);
  460. $conf[$name] = array('_type' => 'int',
  461. 'required' => $required,
  462. 'values' => $values,
  463. 'desc' => $desc,
  464. 'default' => $this->_default($curctx, $this->_getNodeOnlyText($node)),
  465. 'is_default' => $this->_isDefault($curctx, $this->_getNodeOnlyText($node)));
  466. if ($node->get_attribute('octal') == 'true' &&
  467. $conf[$name]['default'] != '') {
  468. $conf[$name]['_type'] = 'octal';
  469. $conf[$name]['default'] = sprintf('0%o', $this->_default($curctx, octdec($this->_getNodeOnlyText($node))));
  470. }
  471. break;
  472. case 'configphp':
  473. $conf[$name] = array('_type' => 'php',
  474. 'required' => $required,
  475. 'quote' => false,
  476. 'desc' => $desc,
  477. 'default' => $this->_defaultRaw($curctx, $this->_getNodeOnlyText($node)),
  478. 'is_default' => $this->_isDefaultRaw($curctx, $this->_getNodeOnlyText($node)));
  479. break;
  480. case 'configsecret':
  481. $conf[$name] = array('_type' => 'text',
  482. 'required' => true,
  483. 'desc' => $desc,
  484. 'default' => $this->_default($curctx, sha1(uniqid(mt_rand(), true))),
  485. 'is_default' => $this->_isDefault($curctx, $this->_getNodeOnlyText($node)));
  486. break;
  487. case 'configsql':
  488. $conf[$node->get_attribute('switchname')] = $this->_configSQL($ctx, $node);
  489. break;
  490. case 'configvfs':
  491. $conf[$node->get_attribute('switchname')] = $this->_configVFS($ctx, $node);
  492. break;
  493. case 'configsection':
  494. $conf[$name] = array();
  495. $cur = &$conf[$name];
  496. if ($node->has_child_nodes()) {
  497. $this->_parseLevel($cur, $node->child_nodes(), $curctx);
  498. }
  499. break;
  500. case 'configtab':
  501. $key = md5(uniqid(mt_rand(), true));
  502. $conf[$key] = array('tab' => $name,
  503. 'desc' => $desc);
  504. if ($node->has_child_nodes()) {
  505. $this->_parseLevel($conf, $node->child_nodes(), $ctx);
  506. }
  507. break;
  508. case 'configplaceholder':
  509. $conf[md5(uniqid(mt_rand(), true))] = 'placeholder';
  510. break;
  511. default:
  512. $conf[$name] = array();
  513. $cur = &$conf[$name];
  514. if ($node->has_child_nodes()) {
  515. $this->_parseLevel($cur, $node->child_nodes(), $curctx);
  516. }
  517. break;
  518. }
  519. }
  520. }
  521. /**
  522. * Returns the configuration tree for an SQL backend configuration to
  523. * replace a <configsql> tag.
  524. * Subnodes will be parsed and added to both the Horde defaults and the
  525. * Custom configuration parts.
  526. *
  527. * @access private
  528. *
  529. * @param string $ctx The context of the <configsql> tag.
  530. * @param DomNode $node The DomNode representation of the <configsql>
  531. * tag.
  532. * @param string $switchname If DomNode is not set, the value of the
  533. * tag's switchname attribute.
  534. *
  535. * @return array An associative array with the SQL configuration tree.
  536. */
  537. function _configSQL($ctx, $node = null, $switchname = 'driverconfig')
  538. {
  539. $persistent = array(
  540. '_type' => 'boolean',
  541. 'required' => false,
  542. 'desc' => 'Request persistent connections?',
  543. 'default' => $this->_default($ctx . '|persistent', false));
  544. $hostspec = array(
  545. '_type' => 'text',
  546. 'required' => true,
  547. 'desc' => 'Database server/host',
  548. 'default' => $this->_default($ctx . '|hostspec', ''));
  549. $username = array(
  550. '_type' => 'text',
  551. 'required' => true,
  552. 'desc' => 'Username to connect to the database as',
  553. 'default' => $this->_default($ctx . '|username', ''));
  554. $password = array(
  555. '_type' => 'text',
  556. 'required' => false,
  557. 'desc' => 'Password to connect with',
  558. 'default' => $this->_default($ctx . '|password', ''));
  559. $database = array(
  560. '_type' => 'text',
  561. 'required' => true,
  562. 'desc' => 'Database name to use',
  563. 'default' => $this->_default($ctx . '|database', ''));
  564. $socket = array(
  565. '_type' => 'text',
  566. 'required' => false,
  567. 'desc' => 'Location of UNIX socket',
  568. 'default' => $this->_default($ctx . '|socket', ''));
  569. $port = array(
  570. '_type' => 'int',
  571. 'required' => false,
  572. 'desc' => 'Port the DB is running on, if non-standard',
  573. 'default' => $this->_default($ctx . '|port', null));
  574. $protocol = array(
  575. 'desc' => 'How should we connect to the database?',
  576. 'default' => $this->_default($ctx . '|protocol', 'unix'),
  577. 'switch' => array(
  578. 'unix' => array(
  579. 'desc' => 'UNIX Sockets',
  580. 'fields' => array(
  581. 'socket' => $socket)),
  582. 'tcp' => array(
  583. 'desc' => 'TCP/IP',
  584. 'fields' => array(
  585. 'hostspec' => $hostspec,
  586. 'port' => $port))));
  587. $mysql_protocol = $protocol;
  588. $mysql_protocol['switch']['tcp']['fields']['port']['default'] = $this->_default($ctx . '|port', 3306);
  589. $charset = array(
  590. '_type' => 'text',
  591. 'required' => true,
  592. 'desc' => 'Internally used charset',
  593. 'default' => $this->_default($ctx . '|charset', 'utf-8'));
  594. $ssl = array(
  595. '_type' => 'boolean',
  596. 'required' => false,
  597. 'desc' => 'Use SSL to connect to the server?',
  598. 'default' => $this->_default($ctx . '|ssl', false));
  599. $ca = array(
  600. '_type' => 'text',
  601. 'required' => false,
  602. 'desc' => 'Certification Authority to use for SSL connections',
  603. 'default' => $this->_default($ctx . '|ca', ''));
  604. $oci8_fields = array(
  605. 'persistent' => $persistent,
  606. 'username' => $username,
  607. 'password' => $password);
  608. if (function_exists('oci_connect')) {
  609. $oci8_fields['database'] = array(
  610. '_type' => 'text',
  611. 'required' => true,
  612. 'desc' => 'Database name or Easy Connect parameter',
  613. 'default' => $this->_default($ctx . '|database', 'horde'));
  614. } else {
  615. $oci8_fields['hostspec'] = array(
  616. '_type' => 'text',
  617. 'required' => true,
  618. 'desc' => 'Database name or Easy Connect parameter',
  619. 'default' => $this->_default($ctx . '|hostspec', 'horde'));
  620. }
  621. $oci8_fields['charset'] = $charset;
  622. $read_hostspec = array(
  623. '_type' => 'text',
  624. 'required' => true,
  625. 'desc' => 'Read database server/host',
  626. 'default' => $this->_default($ctx . '|read|hostspec', ''));
  627. $read_port = array(
  628. '_type' => 'int',
  629. 'required' => false,
  630. 'desc' => 'Port the read DB is running on, if non-standard',
  631. 'default' => $this->_default($ctx . '|read|port', null));
  632. $splitread = array(
  633. '_type' => 'boolean',
  634. 'required' => false,
  635. 'desc' => 'Split reads to a different server?',
  636. 'default' => $this->_default($ctx . '|splitread', 'false'),
  637. 'switch' => array(
  638. 'false' => array(
  639. 'desc' => 'Disabled',
  640. 'fields' => array()),
  641. 'true' => array(
  642. 'desc' => 'Enabled',
  643. 'fields' => array(
  644. 'read' => array(
  645. 'persistent' => $persistent,
  646. 'username' => $username,
  647. 'password' => $password,
  648. 'protocol' => $mysql_protocol,
  649. 'database' => $database,
  650. 'charset' => $charset)))));
  651. $custom_fields = array(
  652. 'required' => true,
  653. 'desc' => 'What database backend should we use?',
  654. 'default' => $this->_default($ctx . '|phptype', 'false'),
  655. 'switch' => array(
  656. 'false' => array(
  657. 'desc' => '[None]',
  658. 'fields' => array()),
  659. 'dbase' => array(
  660. 'desc' => 'dBase',
  661. 'fields' => array(
  662. 'database' => array(
  663. '_type' => 'text',
  664. 'required' => true,
  665. 'desc' => 'Absolute path to the database file',
  666. 'default' => $this->_default($ctx . '|database', '')),
  667. 'mode' => array(
  668. '_type' => 'enum',
  669. 'desc' => 'The mode to open the file with',
  670. 'values' => array(
  671. 0 => 'Read Only',
  672. 2 => 'Read Write'),
  673. 'default' => $this->_default($ctx . '|mode', 2)),
  674. 'charset' => $charset)),
  675. 'ibase' => array(
  676. 'desc' => 'Firebird/InterBase',
  677. 'fields' => array(
  678. 'dbsyntax' => array(
  679. '_type' => 'enum',
  680. 'desc' => 'The database syntax variant to use',
  681. 'required' => false,
  682. 'values' => array(
  683. 'ibase' => 'InterBase',
  684. 'firebird' => 'Firebird'),
  685. 'default' => $this->_default($ctx . '|dbsyntax', 'firebird')),
  686. 'persistent' => $persistent,
  687. 'hostspec' => $hostspec,
  688. 'username' => $username,
  689. 'password' => $password,
  690. 'database' => $database,
  691. 'buffers' => array(
  692. '_type' => 'int',
  693. 'desc' => 'The number of database buffers to allocate',
  694. 'required' => false,
  695. 'default' => $this->_default($ctx . '|buffers', null)),
  696. 'dialect' => array(
  697. '_type' => 'int',
  698. 'desc' => 'The default SQL dialect for any statement executed within a connection.',
  699. 'required' => false,
  700. 'default' => $this->_default($ctx . '|dialect', null)),
  701. 'role' => array(
  702. '_type' => 'text',
  703. 'desc' => 'Role',
  704. 'required' => false,
  705. 'default' => $this->_default($ctx . '|role', null)),
  706. 'charset' => $charset)),
  707. 'fbsql' => array(
  708. 'desc' => 'Frontbase',
  709. 'fields' => array(
  710. 'persistent' => $persistent,
  711. 'hostspec' => $hostspec,
  712. 'username' => $username,
  713. 'password' => $password,
  714. 'database' => $database,
  715. 'charset' => $charset)),
  716. 'ifx' => array(
  717. 'desc' => 'Informix',
  718. 'fields' => array(
  719. 'persistent' => $persistent,
  720. 'username' => $username,
  721. 'password' => $password,
  722. 'database' => $database,
  723. 'charset' => $charset)),
  724. 'msql' => array(
  725. 'desc' => 'mSQL',
  726. 'fields' => array(
  727. 'persistent' => $persistent,
  728. 'hostspec' => $hostspec,
  729. 'username' => $username,
  730. 'password' => $password,
  731. 'port' => $port,
  732. 'database' => $database,
  733. 'charset' => $charset)),
  734. 'mssql' => array(
  735. 'desc' => 'MS SQL Server',
  736. 'fields' => array(
  737. 'persistent' => $persistent,
  738. 'hostspec' => $hostspec,
  739. 'username' => $username,
  740. 'password' => $password,
  741. 'port' => $port,
  742. 'database' => $database,
  743. 'charset' => $charset)),
  744. 'mysql' => array(
  745. 'desc' => 'MySQL',
  746. 'fields' => array(
  747. 'persistent' => $persistent,
  748. 'username' => $username,
  749. 'password' => $password,
  750. 'protocol' => $mysql_protocol,
  751. 'database' => $database,
  752. 'charset' => $charset,
  753. 'ssl' => $ssl,
  754. 'ca' => $ca,
  755. 'splitread' => $splitread)),
  756. 'mysqli' => array(
  757. 'desc' => 'MySQL (mysqli)',
  758. 'fields' => array(
  759. 'username' => $username,
  760. 'password' => $password,
  761. 'protocol' => $mysql_protocol,
  762. 'database' => $database,
  763. 'charset' => $charset,
  764. 'splitread' => $splitread,
  765. 'ssl' => $ssl,
  766. 'ca' => $ca
  767. )),
  768. 'oci8' => array(
  769. 'desc' => 'Oracle',
  770. 'fields' => $oci8_fields),
  771. 'odbc' => array(
  772. 'desc' => 'ODBC',
  773. 'fields' => array(
  774. 'persistent' => $persistent,
  775. 'username' => $username,
  776. 'password' => $password,
  777. 'hostspec' => array(
  778. '_type' => 'text',
  779. 'desc' => 'DSN',
  780. 'default' => $this->_default($ctx . '|hostspec', '')),
  781. 'dbsyntax' => array(
  782. '_type' => 'enum',
  783. 'desc' => 'The database syntax variant to use',
  784. 'required' => false,
  785. 'values' => array(
  786. 'sql92' => 'SQL92',
  787. 'access' => 'Access',
  788. 'db2' => 'DB2',
  789. 'solid' => 'Solid',
  790. 'navision' => 'Navision',
  791. 'mssql' => 'MS SQL Server',
  792. 'sybase' => 'Sybase',
  793. 'mysql' => 'MySQL',
  794. 'mysqli' => 'MySQL (mysqli)',
  795. ),
  796. 'default' => $this->_default($ctx . '|dbsyntax', 'sql92')),
  797. 'cursor' => array(
  798. '_type' => 'enum',
  799. 'desc' => 'Cursor type',
  800. 'quote' => false,
  801. 'required' => false,
  802. 'values' => array(
  803. 'null' => 'None',
  804. 'SQL_CUR_DEFAULT' => 'Default',
  805. 'SQL_CUR_USE_DRIVER' => 'Use Driver',
  806. 'SQL_CUR_USE_ODBC' => 'Use ODBC',
  807. 'SQL_CUR_USE_IF_NEEDED' => 'Use If Needed'),
  808. 'default' => $this->_default($ctx . '|cursor', null)),
  809. 'charset' => $charset)),
  810. 'pgsql' => array(
  811. 'desc' => 'PostgreSQL',
  812. 'fields' => array(
  813. 'persistent' => $persistent,
  814. 'username' => $username,
  815. 'password' => $password,
  816. 'protocol' => $protocol,
  817. 'database' => $database,
  818. 'charset' => $charset)),
  819. 'sqlite' => array(
  820. 'desc' => 'SQLite',
  821. 'fields' => array(
  822. 'database' => array(
  823. '_type' => 'text',
  824. 'required' => true,
  825. 'desc' => 'Absolute path to the database file',
  826. 'default' => $this->_default($ctx . '|database', '')),
  827. 'mode' => array(
  828. '_type' => 'text',
  829. 'desc' => 'The mode to open the file with',
  830. 'default' => $this->_default($ctx . '|mode', '0644')),
  831. 'charset' => $charset)),
  832. 'sybase' => array(
  833. 'desc' => 'Sybase',
  834. 'fields' => array(
  835. 'persistent' => $persistent,
  836. 'hostspec' => $hostspec,
  837. 'username' => $username,
  838. 'password' => $password,
  839. 'database' => $database,
  840. 'appname' => array(
  841. '_type' => 'text',
  842. 'desc' => 'Application Name',
  843. 'required' => false,
  844. 'default' => $this->_default($ctx . '|appname', '')),
  845. 'charset' => $charset))));
  846. if (isset($node) && $node->get_attribute('baseconfig') == 'true') {
  847. return $custom_fields;
  848. }
  849. list($default, $isDefault) = $this->__default($ctx . '|' . (isset($node) ? $node->get_attribute('switchname') : $switchname), 'horde');
  850. $config = array(
  851. 'desc' => 'Driver configuration',
  852. 'default' => $default,
  853. 'is_default' => $isDefault,
  854. 'switch' => array(
  855. 'horde' => array(
  856. 'desc' => 'Horde defaults',
  857. 'fields' => array()),
  858. 'custom' => array(
  859. 'desc' => 'Custom parameters',
  860. 'fields' => array(
  861. 'phptype' => $custom_fields))));
  862. if (isset($node) && $node->has_child_nodes()) {
  863. $cur = array();
  864. $this->_parseLevel($cur, $node->child_nodes(), $ctx);
  865. $config['switch']['horde']['fields'] = array_merge($config['switch']['horde']['fields'], $cur);
  866. $config['switch']['custom']['fields'] = array_merge($config['switch']['custom']['fields'], $cur);
  867. }
  868. return $config;
  869. }
  870. /**
  871. * Returns the configuration tree for a VFS backend configuration to
  872. * replace a <configvfs> tag.
  873. * Subnodes will be parsed and added to both the Horde defaults and the
  874. * Custom configuration parts.
  875. *
  876. * @access private
  877. *
  878. * @param string $ctx The context of the <configvfs> tag.
  879. * @param DomNode $node The DomNode representation of the <configvfs>
  880. * tag.
  881. *
  882. * @return array An associative array with the VFS configuration tree.
  883. */
  884. function _configVFS($ctx, $node)
  885. {
  886. $sql = $this->_configSQL($ctx . '|params');
  887. $default = $node->get_attribute('default');
  888. $default = (empty($default)) ? 'none' : $default;
  889. list($default, $isDefault) = $this->__default($ctx . '|' . $node->get_attribute('switchname'), $default);
  890. $config =
  891. array(
  892. 'desc' => 'What VFS driver should we use?',
  893. 'default' => $default,
  894. 'is_default' => $isDefault,
  895. 'switch' => array(
  896. 'none' => array(
  897. 'desc' => 'None',
  898. 'fields' => array()),
  899. 'file' => array(
  900. 'desc' => 'Files on the local system',
  901. 'fields' => array(
  902. 'params' => array(
  903. 'vfsroot' => array(
  904. '_type' => 'text',
  905. 'desc' => 'Where on the real filesystem should Horde use as root of the virtual filesystem?',
  906. 'default' => $this->_default($ctx . '|params|vfsroot', '/tmp'))))),
  907. 'sql' => array(
  908. 'desc' => 'SQL database',
  909. 'fields' => array(
  910. 'params' => array(
  911. 'driverconfig' => $sql)))));
  912. if (isset($node) && $node->get_attribute('baseconfig') != 'true') {
  913. $config['switch']['horde'] = array(
  914. 'desc' => 'Horde defaults',
  915. 'fields' => array());
  916. }
  917. $cases = $this->_getSwitchValues($node, $ctx . '|params');
  918. foreach ($cases as $case => $fields) {
  919. if (isset($config['switch'][$case])) {
  920. $config['switch'][$case]['fields']['params'] = array_merge($config['switch'][$case]['fields']['params'], $fields['fields']);
  921. }
  922. }
  923. return $config;
  924. }
  925. /**
  926. * Returns a certain value from the current configuration array or
  927. * a default value, if not found.
  928. *
  929. * @access private
  930. *
  931. * @param string $ctx A string representing the key of the
  932. * configuration array to return.
  933. * @param mixed $default The default value to return if the key wasn't
  934. * found.
  935. *
  936. * @return mixed Either the value of the configuration array's requested
  937. * key or the default value if the key wasn't found.
  938. */
  939. function _default($ctx, $default)
  940. {
  941. list ($ptr,) = $this->__default($ctx, $default);
  942. return $ptr;
  943. }
  944. /**
  945. * Returns whether a certain value from the current configuration array
  946. * exists or a default value will be used.
  947. *
  948. * @access private
  949. *
  950. * @param string $ctx A string representing the key of the
  951. * configuration array to return.
  952. * @param mixed $default The default value to return if the key wasn't
  953. * found.
  954. *
  955. * @return boolean Whether the default value will be used.
  956. */
  957. function _isDefault($ctx, $default)
  958. {
  959. list (,$isDefault) = $this->__default($ctx, $default);
  960. return $isDefault;
  961. }
  962. /**
  963. * Returns a certain value from the current configuration array or a
  964. * default value, if not found, and which of the values have been
  965. * returned.
  966. *
  967. * @access private
  968. *
  969. * @param string $ctx A string representing the key of the
  970. * configuration array to return.
  971. * @param mixed $default The default value to return if the key wasn't
  972. * found.
  973. *
  974. * @return array First element: either the value of the configuration
  975. * array's requested key or the default value if the key
  976. * wasn't found.
  977. * Second element: whether the returned value was the
  978. * default value.
  979. */
  980. function __default($ctx, $default)
  981. {
  982. $ctx = explode('|', $ctx);
  983. $ptr = $this->_currentConfig;
  984. for ($i = 0; $i < count($ctx); $i++) {
  985. if (!isset($ptr[$ctx[$i]])) {
  986. return array($default, true);
  987. } else {
  988. $ptr = $ptr[$ctx[$i]];
  989. }
  990. }
  991. if (is_string($ptr)) {
  992. $ptr = String::convertCharset($ptr, 'iso-8859-1');
  993. }
  994. return array($ptr, false);
  995. }
  996. /**
  997. * Returns a certain value from the current configuration file or
  998. * a default value, if not found.
  999. * It does NOT return the actual value, but the PHP expression as used
  1000. * in the configuration file.
  1001. *
  1002. * @access private
  1003. *
  1004. * @param string $ctx A string representing the key of the
  1005. * configuration array to return.
  1006. * @param mixed $default The default value to return if the key wasn't
  1007. * found.
  1008. *
  1009. * @return mixed Either the value of the configuration file's requested
  1010. * key or the default value if the key wasn't found.
  1011. */
  1012. function _defaultRaw($ctx, $default)
  1013. {
  1014. list ($ptr,) = $this->__defaultRaw($ctx, $default);
  1015. return $ptr;
  1016. }
  1017. /**
  1018. * Returns whether a certain value from the current configuration array
  1019. * exists or a default value will be used.
  1020. *
  1021. * @access private
  1022. *
  1023. * @param string $ctx A string representing the key of the
  1024. * configuration array to return.
  1025. * @param mixed $default The default value to return if the key wasn't
  1026. * found.
  1027. *
  1028. * @return boolean Whether the default value will be used.
  1029. */
  1030. function _isDefaultRaw($ctx, $default)
  1031. {
  1032. list (,$isDefault) = $this->__defaultRaw($ctx, $default);
  1033. return $isDefault;
  1034. }
  1035. /**
  1036. * Returns a certain value from the current configuration file or
  1037. * a default value, if not found, and which of the values have been
  1038. * returned.
  1039. *
  1040. * It does NOT return the actual value, but the PHP expression as used
  1041. * in the configuration file.
  1042. *
  1043. * @access private
  1044. *
  1045. * @param string $ctx A string representing the key of the
  1046. * configuration array to return.
  1047. * @param mixed $default The default value to return if the key wasn't
  1048. * found.
  1049. *
  1050. * @return array First element: either the value of the configuration
  1051. * array's requested key or the default value if the key
  1052. * wasn't found.
  1053. * Second element: whether the returned value was the
  1054. * default value.
  1055. */
  1056. function __defaultRaw($ctx, $default)
  1057. {
  1058. $ctx = explode('|', $ctx);
  1059. $pattern = '/^\$conf\[\'' . implode("'\]\['", $ctx) . '\'\] = (.*);\r?$/m';
  1060. if (preg_match($pattern, $this->getPHPConfig(), $matches)) {
  1061. return array($matches[1], false);
  1062. }
  1063. return array($default, true);
  1064. }
  1065. /**
  1066. * Returns the content of all text node children of the specified node.
  1067. *
  1068. * @access private
  1069. *
  1070. * @param DomNode $node A DomNode object whose text node children to return.
  1071. *
  1072. * @return string The concatenated values of all text nodes.
  1073. */
  1074. function _getNodeOnlyText($node)
  1075. {
  1076. $text = '';
  1077. if (!$node->has_child_nodes()) {
  1078. return $node->get_content();
  1079. }
  1080. foreach ($node->child_nodes() as $tnode) {
  1081. if ($tnode->type == XML_TEXT_NODE) {
  1082. $text .= $tnode->content;
  1083. }
  1084. }
  1085. return trim($text);
  1086. }
  1087. /**
  1088. * Returns an associative array containing all possible values of the
  1089. * specified <configenum> tag.
  1090. *
  1091. * The keys contain the actual enum values while the values contain their
  1092. * corresponding descriptions.
  1093. *
  1094. * @access private
  1095. *
  1096. * @param DomNode $node The DomNode representation of the <configenum> tag
  1097. * whose values should be returned.
  1098. *
  1099. * @return array An associative array with all possible enum values.
  1100. */
  1101. function _getEnumValues($node)
  1102. {
  1103. $values = array();
  1104. if (!$node->has_child_nodes()) {
  1105. return array();
  1106. }
  1107. foreach ($node->child_nodes() as $vnode) {
  1108. if ($vnode->type == XML_ELEMENT_NODE &&
  1109. $vnode->tagname == 'values') {
  1110. if (!$vnode->has_child_nodes()) {
  1111. return array();
  1112. }
  1113. foreach ($vnode->child_nodes() as $value) {
  1114. if ($value->type == XML_ELEMENT_NODE) {
  1115. if ($value->tagname == 'configspecial') {
  1116. return $this->_handleSpecials($value);
  1117. } elseif ($value->tagname == 'value') {
  1118. $text = $value->get_content();
  1119. $desc = $value->get_attribute('desc');
  1120. if (!empty($desc)) {
  1121. $values[$text] = $desc;
  1122. } else {
  1123. $values[$text] = $text;
  1124. }
  1125. }
  1126. }
  1127. }
  1128. }
  1129. }
  1130. return $values;
  1131. }
  1132. /**
  1133. * Returns a multidimensional associative array representing the specified
  1134. * <configswitch> tag.
  1135. *
  1136. * @access private
  1137. *
  1138. * @param DomNode &$node The DomNode representation of the <configswitch>
  1139. * tag to process.
  1140. *
  1141. * @return array An associative array representing the node.
  1142. */
  1143. function _getSwitchValues(&$node, $curctx)
  1144. {
  1145. if (!$node->has_child_nodes()) {
  1146. return array();
  1147. }
  1148. $values = array();
  1149. foreach ($node->child_nodes() as $case) {
  1150. if ($case->type == XML_ELEMENT_NODE) {
  1151. $name = $case->get_attribute('name');
  1152. $values[$name] = array();
  1153. $values[$name]['desc'] = $case->get_attribute('desc');
  1154. $values[$name]['fields'] = array();
  1155. if ($case->has_child_nodes()) {
  1156. $this->_parseLevel($values[$name]['fields'], $case->child_nodes(), $curctx);
  1157. }
  1158. }
  1159. }
  1160. return $values;
  1161. }
  1162. /**
  1163. * Returns an associative array containing the possible values of a
  1164. * <configspecial> tag as …

Large files files are truncated, but you can click here to view the full file