Config.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <?php
  2. /**
  3. * Functions related to configuration management.
  4. */
  5. /**
  6. * Re-write configuration file according to given array.
  7. * Requires mandatory fields listed in $MANDATORY_FIELDS.
  8. *
  9. * @param array $config contains all configuration fields.
  10. * @param bool $isLoggedIn true if user is logged in.
  11. *
  12. * @return void
  13. *
  14. * @throws MissingFieldConfigException: a mandatory field has not been provided in $config.
  15. * @throws UnauthorizedConfigException: user is not authorize to change configuration.
  16. * @throws Exception: an error occured while writing the new config file.
  17. */
  18. function writeConfig($config, $isLoggedIn)
  19. {
  20. // These fields are required in configuration.
  21. $MANDATORY_FIELDS = array(
  22. 'login', 'hash', 'salt', 'timezone', 'title', 'titleLink',
  23. 'redirector', 'disablesessionprotection', 'privateLinkByDefault'
  24. );
  25. if (!isset($config['config']['CONFIG_FILE'])) {
  26. throw new MissingFieldConfigException('CONFIG_FILE');
  27. }
  28. // Only logged in user can alter config.
  29. if (is_file($config['config']['CONFIG_FILE']) && !$isLoggedIn) {
  30. throw new UnauthorizedConfigException();
  31. }
  32. // Check that all mandatory fields are provided in $config.
  33. foreach ($MANDATORY_FIELDS as $field) {
  34. if (!isset($config[$field])) {
  35. throw new MissingFieldConfigException($field);
  36. }
  37. }
  38. $configStr = '<?php '. PHP_EOL;
  39. $configStr .= '$GLOBALS[\'login\'] = '.var_export($config['login'], true).';'. PHP_EOL;
  40. $configStr .= '$GLOBALS[\'hash\'] = '.var_export($config['hash'], true).';'. PHP_EOL;
  41. $configStr .= '$GLOBALS[\'salt\'] = '.var_export($config['salt'], true).'; '. PHP_EOL;
  42. $configStr .= '$GLOBALS[\'timezone\'] = '.var_export($config['timezone'], true).';'. PHP_EOL;
  43. $configStr .= 'date_default_timezone_set('.var_export($config['timezone'], true).');'. PHP_EOL;
  44. $configStr .= '$GLOBALS[\'title\'] = '.var_export($config['title'], true).';'. PHP_EOL;
  45. $configStr .= '$GLOBALS[\'titleLink\'] = '.var_export($config['titleLink'], true).'; '. PHP_EOL;
  46. $configStr .= '$GLOBALS[\'redirector\'] = '.var_export($config['redirector'], true).'; '. PHP_EOL;
  47. $configStr .= '$GLOBALS[\'disablesessionprotection\'] = '.var_export($config['disablesessionprotection'], true).'; '. PHP_EOL;
  48. $configStr .= '$GLOBALS[\'privateLinkByDefault\'] = '.var_export($config['privateLinkByDefault'], true).'; '. PHP_EOL;
  49. // Store all $config['config']
  50. foreach ($config['config'] as $key => $value) {
  51. $configStr .= '$GLOBALS[\'config\'][\''. $key .'\'] = '.var_export($config['config'][$key], true).';'. PHP_EOL;
  52. }
  53. if (isset($config['plugins'])) {
  54. foreach ($config['plugins'] as $key => $value) {
  55. $configStr .= '$GLOBALS[\'plugins\'][\''. $key .'\'] = '.var_export($config['plugins'][$key], true).';'. PHP_EOL;
  56. }
  57. }
  58. if (!file_put_contents($config['config']['CONFIG_FILE'], $configStr)
  59. || strcmp(file_get_contents($config['config']['CONFIG_FILE']), $configStr) != 0
  60. ) {
  61. throw new Exception(
  62. 'Shaarli could not create the config file.
  63. Please make sure Shaarli has the right to write in the folder is it installed in.'
  64. );
  65. }
  66. }
  67. /**
  68. * Process plugin administration form data and save it in an array.
  69. *
  70. * @param array $formData Data sent by the plugin admin form.
  71. *
  72. * @return array New list of enabled plugin, ordered.
  73. *
  74. * @throws PluginConfigOrderException Plugins can't be sorted because their order is invalid.
  75. */
  76. function save_plugin_config($formData)
  77. {
  78. // Make sure there are no duplicates in orders.
  79. if (!validate_plugin_order($formData)) {
  80. throw new PluginConfigOrderException();
  81. }
  82. $plugins = array();
  83. $newEnabledPlugins = array();
  84. foreach ($formData as $key => $data) {
  85. if (startsWith($key, 'order')) {
  86. continue;
  87. }
  88. // If there is no order, it means a disabled plugin has been enabled.
  89. if (isset($formData['order_' . $key])) {
  90. $plugins[(int) $formData['order_' . $key]] = $key;
  91. }
  92. else {
  93. $newEnabledPlugins[] = $key;
  94. }
  95. }
  96. // New enabled plugins will be added at the end of order.
  97. $plugins = array_merge($plugins, $newEnabledPlugins);
  98. // Sort plugins by order.
  99. if (!ksort($plugins)) {
  100. throw new PluginConfigOrderException();
  101. }
  102. $finalPlugins = array();
  103. // Make plugins order continuous.
  104. foreach ($plugins as $plugin) {
  105. $finalPlugins[] = $plugin;
  106. }
  107. return $finalPlugins;
  108. }
  109. /**
  110. * Validate plugin array submitted.
  111. * Will fail if there is duplicate orders value.
  112. *
  113. * @param array $formData Data from submitted form.
  114. *
  115. * @return bool true if ok, false otherwise.
  116. */
  117. function validate_plugin_order($formData)
  118. {
  119. $orders = array();
  120. foreach ($formData as $key => $value) {
  121. // No duplicate order allowed.
  122. if (in_array($value, $orders)) {
  123. return false;
  124. }
  125. if (startsWith($key, 'order')) {
  126. $orders[] = $value;
  127. }
  128. }
  129. return true;
  130. }
  131. /**
  132. * Affect plugin parameters values into plugins array.
  133. *
  134. * @param mixed $plugins Plugins array ($plugins[<plugin_name>]['parameters']['param_name'] = <value>.
  135. * @param mixed $config Plugins configuration.
  136. *
  137. * @return mixed Updated $plugins array.
  138. */
  139. function load_plugin_parameter_values($plugins, $config)
  140. {
  141. $out = $plugins;
  142. foreach ($plugins as $name => $plugin) {
  143. if (empty($plugin['parameters'])) {
  144. continue;
  145. }
  146. foreach ($plugin['parameters'] as $key => $param) {
  147. if (!empty($config[$key])) {
  148. $out[$name]['parameters'][$key] = $config[$key];
  149. }
  150. }
  151. }
  152. return $out;
  153. }
  154. /**
  155. * Milestone 0.9 - shaarli/Shaarli#41: options.php is not supported anymore.
  156. * ==> if user is loggedIn, merge its content with config.php, then delete options.php.
  157. *
  158. * @param array $config contains all configuration fields.
  159. * @param bool $isLoggedIn true if user is logged in.
  160. *
  161. * @return void
  162. */
  163. function mergeDeprecatedConfig($config, $isLoggedIn)
  164. {
  165. $config_file = $config['config']['CONFIG_FILE'];
  166. if (is_file($config['config']['DATADIR'].'/options.php') && $isLoggedIn) {
  167. include $config['config']['DATADIR'].'/options.php';
  168. // Load GLOBALS into config
  169. foreach ($GLOBALS as $key => $value) {
  170. $config[$key] = $value;
  171. }
  172. $config['config']['CONFIG_FILE'] = $config_file;
  173. writeConfig($config, $isLoggedIn);
  174. unlink($config['config']['DATADIR'].'/options.php');
  175. }
  176. }
  177. /**
  178. * Exception used if a mandatory field is missing in given configuration.
  179. */
  180. class MissingFieldConfigException extends Exception
  181. {
  182. public $field;
  183. /**
  184. * Construct exception.
  185. *
  186. * @param string $field field name missing.
  187. */
  188. public function __construct($field)
  189. {
  190. $this->field = $field;
  191. $this->message = 'Configuration value is required for '. $this->field;
  192. }
  193. }
  194. /**
  195. * Exception used if an unauthorized attempt to edit configuration has been made.
  196. */
  197. class UnauthorizedConfigException extends Exception
  198. {
  199. /**
  200. * Construct exception.
  201. */
  202. public function __construct()
  203. {
  204. $this->message = 'You are not authorized to alter config.';
  205. }
  206. }
  207. /**
  208. * Exception used if an error occur while saving plugin configuration.
  209. */
  210. class PluginConfigOrderException extends Exception
  211. {
  212. /**
  213. * Construct exception.
  214. */
  215. public function __construct()
  216. {
  217. $this->message = 'An error occurred while trying to save plugins loading order.';
  218. }
  219. }