diff options
Diffstat (limited to 'application/config')
-rw-r--r-- | application/config/ConfigJson.php | 33 | ||||
-rw-r--r-- | application/config/ConfigManager.php | 83 | ||||
-rw-r--r-- | application/config/ConfigPhp.php | 45 |
3 files changed, 115 insertions, 46 deletions
diff --git a/application/config/ConfigJson.php b/application/config/ConfigJson.php index cbafbf6d..94693c86 100644 --- a/application/config/ConfigJson.php +++ b/application/config/ConfigJson.php | |||
@@ -8,29 +8,15 @@ | |||
8 | class ConfigJson implements ConfigIO | 8 | class ConfigJson implements ConfigIO |
9 | { | 9 | { |
10 | /** | 10 | /** |
11 | * The JSON data is wrapped in a PHP file for security purpose. | ||
12 | * This way, even if the file is accessible, credentials and configuration won't be exposed. | ||
13 | * | ||
14 | * @var string PHP start tag and comment tag. | ||
15 | */ | ||
16 | public static $PHP_HEADER; | ||
17 | |||
18 | public function __construct() | ||
19 | { | ||
20 | // The field can't be initialized directly with concatenation before PHP 5.6. | ||
21 | self::$PHP_HEADER = '<?php /*'. PHP_EOL; | ||
22 | } | ||
23 | |||
24 | /** | ||
25 | * @inheritdoc | 11 | * @inheritdoc |
26 | */ | 12 | */ |
27 | function read($filepath) | 13 | function read($filepath) |
28 | { | 14 | { |
29 | if (! file_exists($filepath) || ! is_readable($filepath)) { | 15 | if (! is_readable($filepath)) { |
30 | return array(); | 16 | return array(); |
31 | } | 17 | } |
32 | $data = file_get_contents($filepath); | 18 | $data = file_get_contents($filepath); |
33 | $data = str_replace(self::$PHP_HEADER, '', $data); | 19 | $data = str_replace(self::getPhpHeaders(), '', $data); |
34 | $data = json_decode($data, true); | 20 | $data = json_decode($data, true); |
35 | if ($data === null) { | 21 | if ($data === null) { |
36 | $error = json_last_error(); | 22 | $error = json_last_error(); |
@@ -46,7 +32,7 @@ class ConfigJson implements ConfigIO | |||
46 | { | 32 | { |
47 | // JSON_PRETTY_PRINT is available from PHP 5.4. | 33 | // JSON_PRETTY_PRINT is available from PHP 5.4. |
48 | $print = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0; | 34 | $print = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0; |
49 | $data = self::$PHP_HEADER . json_encode($conf, $print); | 35 | $data = self::getPhpHeaders() . json_encode($conf, $print); |
50 | if (!file_put_contents($filepath, $data)) { | 36 | if (!file_put_contents($filepath, $data)) { |
51 | throw new IOException( | 37 | throw new IOException( |
52 | $filepath, | 38 | $filepath, |
@@ -63,4 +49,17 @@ class ConfigJson implements ConfigIO | |||
63 | { | 49 | { |
64 | return '.json.php'; | 50 | return '.json.php'; |
65 | } | 51 | } |
52 | |||
53 | /** | ||
54 | * The JSON data is wrapped in a PHP file for security purpose. | ||
55 | * This way, even if the file is accessible, credentials and configuration won't be exposed. | ||
56 | * | ||
57 | * Note: this isn't a static field because concatenation isn't supported in field declaration before PHP 5.6. | ||
58 | * | ||
59 | * @return string PHP start tag and comment tag. | ||
60 | */ | ||
61 | public static function getPhpHeaders() | ||
62 | { | ||
63 | return '<?php /*'. PHP_EOL; | ||
64 | } | ||
66 | } | 65 | } |
diff --git a/application/config/ConfigManager.php b/application/config/ConfigManager.php index 70456737..a663a071 100644 --- a/application/config/ConfigManager.php +++ b/application/config/ConfigManager.php | |||
@@ -116,6 +116,11 @@ class ConfigManager | |||
116 | */ | 116 | */ |
117 | public function get($setting, $default = '') | 117 | public function get($setting, $default = '') |
118 | { | 118 | { |
119 | // During the ConfigIO transition, map legacy settings to the new ones. | ||
120 | if ($this->configIO instanceof ConfigPhp && isset(ConfigPhp::$LEGACY_KEYS_MAPPING[$setting])) { | ||
121 | $setting = ConfigPhp::$LEGACY_KEYS_MAPPING[$setting]; | ||
122 | } | ||
123 | |||
119 | $settings = explode('.', $setting); | 124 | $settings = explode('.', $setting); |
120 | $value = self::getConfig($settings, $this->loadedConfig); | 125 | $value = self::getConfig($settings, $this->loadedConfig); |
121 | if ($value === self::$NOT_FOUND) { | 126 | if ($value === self::$NOT_FOUND) { |
@@ -142,6 +147,11 @@ class ConfigManager | |||
142 | throw new Exception('Invalid setting key parameter. String expected, got: '. gettype($setting)); | 147 | throw new Exception('Invalid setting key parameter. String expected, got: '. gettype($setting)); |
143 | } | 148 | } |
144 | 149 | ||
150 | // During the ConfigIO transition, map legacy settings to the new ones. | ||
151 | if ($this->configIO instanceof ConfigPhp && isset(ConfigPhp::$LEGACY_KEYS_MAPPING[$setting])) { | ||
152 | $setting = ConfigPhp::$LEGACY_KEYS_MAPPING[$setting]; | ||
153 | } | ||
154 | |||
145 | $settings = explode('.', $setting); | 155 | $settings = explode('.', $setting); |
146 | self::setConfig($settings, $value, $this->loadedConfig); | 156 | self::setConfig($settings, $value, $this->loadedConfig); |
147 | if ($write) { | 157 | if ($write) { |
@@ -160,6 +170,11 @@ class ConfigManager | |||
160 | */ | 170 | */ |
161 | public function exists($setting) | 171 | public function exists($setting) |
162 | { | 172 | { |
173 | // During the ConfigIO transition, map legacy settings to the new ones. | ||
174 | if ($this->configIO instanceof ConfigPhp && isset(ConfigPhp::$LEGACY_KEYS_MAPPING[$setting])) { | ||
175 | $setting = ConfigPhp::$LEGACY_KEYS_MAPPING[$setting]; | ||
176 | } | ||
177 | |||
163 | $settings = explode('.', $setting); | 178 | $settings = explode('.', $setting); |
164 | $value = self::getConfig($settings, $this->loadedConfig); | 179 | $value = self::getConfig($settings, $this->loadedConfig); |
165 | if ($value === self::$NOT_FOUND) { | 180 | if ($value === self::$NOT_FOUND) { |
@@ -183,8 +198,15 @@ class ConfigManager | |||
183 | { | 198 | { |
184 | // These fields are required in configuration. | 199 | // These fields are required in configuration. |
185 | $mandatoryFields = array( | 200 | $mandatoryFields = array( |
186 | 'login', 'hash', 'salt', 'timezone', 'title', 'titleLink', | 201 | 'credentials.login', |
187 | 'redirector', 'disablesessionprotection', 'privateLinkByDefault' | 202 | 'credentials.hash', |
203 | 'credentials.salt', | ||
204 | 'security.session_protection_disabled', | ||
205 | 'general.timezone', | ||
206 | 'general.title', | ||
207 | 'general.header_link', | ||
208 | 'general.default_private_links', | ||
209 | 'extras.redirector', | ||
188 | ); | 210 | ); |
189 | 211 | ||
190 | // Only logged in user can alter config. | 212 | // Only logged in user can alter config. |
@@ -265,75 +287,78 @@ class ConfigManager | |||
265 | protected function setDefaultValues() | 287 | protected function setDefaultValues() |
266 | { | 288 | { |
267 | // Data subdirectory | 289 | // Data subdirectory |
268 | $this->setEmpty('config.DATADIR', 'data'); | 290 | $this->setEmpty('path.data_dir', 'data'); |
269 | 291 | ||
270 | // Main configuration file | 292 | // Main configuration file |
271 | $this->setEmpty('config.CONFIG_FILE', 'data/config.php'); | 293 | $this->setEmpty('path.config', 'data/config.php'); |
272 | 294 | ||
273 | // Link datastore | 295 | // Link datastore |
274 | $this->setEmpty('config.DATASTORE', 'data/datastore.php'); | 296 | $this->setEmpty('path.datastore', 'data/datastore.php'); |
275 | 297 | ||
276 | // Banned IPs | 298 | // Banned IPs |
277 | $this->setEmpty('config.IPBANS_FILENAME', 'data/ipbans.php'); | 299 | $this->setEmpty('path.ban_file', 'data/ipbans.php'); |
278 | 300 | ||
279 | // Processed updates file. | 301 | // Processed updates file. |
280 | $this->setEmpty('config.UPDATES_FILE', 'data/updates.txt'); | 302 | $this->setEmpty('path.updates', 'data/updates.txt'); |
281 | 303 | ||
282 | // Access log | 304 | // Access log |
283 | $this->setEmpty('config.LOG_FILE', 'data/log.txt'); | 305 | $this->setEmpty('path.log', 'data/log.txt'); |
284 | 306 | ||
285 | // For updates check of Shaarli | 307 | // For updates check of Shaarli |
286 | $this->setEmpty('config.UPDATECHECK_FILENAME', 'data/lastupdatecheck.txt'); | 308 | $this->setEmpty('path.update_check', 'data/lastupdatecheck.txt'); |
287 | 309 | ||
288 | // Set ENABLE_UPDATECHECK to disabled by default. | 310 | // Set ENABLE_UPDATECHECK to disabled by default. |
289 | $this->setEmpty('config.ENABLE_UPDATECHECK', false); | 311 | $this->setEmpty('general.check_updates', false); |
290 | 312 | ||
291 | // RainTPL cache directory (keep the trailing slash!) | 313 | // RainTPL cache directory (keep the trailing slash!) |
292 | $this->setEmpty('config.RAINTPL_TMP', 'tmp/'); | 314 | $this->setEmpty('path.raintpl_tmp', 'tmp/'); |
293 | // Raintpl template directory (keep the trailing slash!) | 315 | // Raintpl template directory (keep the trailing slash!) |
294 | $this->setEmpty('config.RAINTPL_TPL', 'tpl/'); | 316 | $this->setEmpty('path.raintpl_tpl', 'tpl/'); |
295 | 317 | ||
296 | // Thumbnail cache directory | 318 | // Thumbnail cache directory |
297 | $this->setEmpty('config.CACHEDIR', 'cache'); | 319 | $this->setEmpty('path.thumbnails_cache', 'cache'); |
298 | 320 | ||
299 | // Atom & RSS feed cache directory | 321 | // Atom & RSS feed cache directory |
300 | $this->setEmpty('config.PAGECACHE', 'pagecache'); | 322 | $this->setEmpty('path.page_cache', 'pagecache'); |
301 | 323 | ||
302 | // Ban IP after this many failures | 324 | // Ban IP after this many failures |
303 | $this->setEmpty('config.BAN_AFTER', 4); | 325 | $this->setEmpty('security.ban_after', 4); |
304 | // Ban duration for IP address after login failures (in seconds) | 326 | // Ban duration for IP address after login failures (in seconds) |
305 | $this->setEmpty('config.BAN_DURATION', 1800); | 327 | $this->setEmpty('security.ban_after', 1800); |
306 | 328 | ||
307 | // Feed options | 329 | // Feed options |
308 | // Enable RSS permalinks by default. | 330 | // Enable RSS permalinks by default. |
309 | // This corresponds to the default behavior of shaarli before this was added as an option. | 331 | // This corresponds to the default behavior of shaarli before this was added as an option. |
310 | $this->setEmpty('config.ENABLE_RSS_PERMALINKS', true); | 332 | $this->setEmpty('general.rss_permalinks', true); |
311 | // If true, an extra "ATOM feed" button will be displayed in the toolbar | 333 | // If true, an extra "ATOM feed" button will be displayed in the toolbar |
312 | $this->setEmpty('config.SHOW_ATOM', false); | 334 | $this->setEmpty('extras.show_atom', false); |
313 | 335 | ||
314 | // Link display options | 336 | // Link display options |
315 | $this->setEmpty('config.HIDE_PUBLIC_LINKS', false); | 337 | $this->setEmpty('extras.hide_public_links', false); |
316 | $this->setEmpty('config.HIDE_TIMESTAMPS', false); | 338 | $this->setEmpty('extras.hide_timestamps', false); |
317 | $this->setEmpty('config.LINKS_PER_PAGE', 20); | 339 | $this->setEmpty('general.links_per_page', 20); |
340 | |||
341 | // Private checkbox is checked by default | ||
342 | $this->setEmpty('general.default_private_links', false); | ||
318 | 343 | ||
319 | // Open Shaarli (true): anyone can add/edit/delete links without having to login | 344 | // Open Shaarli (true): anyone can add/edit/delete links without having to login |
320 | $this->setEmpty('config.OPEN_SHAARLI', false); | 345 | $this->setEmpty('extras.open_shaarli', false); |
321 | 346 | ||
322 | // Thumbnails | 347 | // Thumbnails |
323 | // Display thumbnails in links | 348 | // Display thumbnails in links |
324 | $this->setEmpty('config.ENABLE_THUMBNAILS', true); | 349 | $this->setEmpty('general.enable_thumbnails', true); |
325 | // Store thumbnails in a local cache | 350 | // Store thumbnails in a local cache |
326 | $this->setEmpty('config.ENABLE_LOCALCACHE', true); | 351 | $this->setEmpty('general.enable_localcache', true); |
327 | 352 | ||
328 | // Update check frequency for Shaarli. 86400 seconds=24 hours | 353 | // Update check frequency for Shaarli. 86400 seconds=24 hours |
329 | $this->setEmpty('config.UPDATECHECK_BRANCH', 'stable'); | 354 | $this->setEmpty('general.check_updates_branch', 'stable'); |
330 | $this->setEmpty('config.UPDATECHECK_INTERVAL', 86400); | 355 | $this->setEmpty('general.check_updates_interval', 86400); |
331 | 356 | ||
332 | $this->setEmpty('redirector', ''); | 357 | $this->setEmpty('extras.redirector', ''); |
333 | $this->setEmpty('config.REDIRECTOR_URLENCODE', true); | 358 | $this->setEmpty('extras.redirector_encode_url', true); |
334 | 359 | ||
335 | // Enabled plugins. | 360 | // Enabled plugins. |
336 | $this->setEmpty('config.ENABLED_PLUGINS', array('qrcode')); | 361 | $this->setEmpty('general.enabled_plugins', array('qrcode')); |
337 | 362 | ||
338 | // Initialize plugin parameters array. | 363 | // Initialize plugin parameters array. |
339 | $this->setEmpty('plugins', array()); | 364 | $this->setEmpty('plugins', array()); |
diff --git a/application/config/ConfigPhp.php b/application/config/ConfigPhp.php index f99073af..b122f4f1 100644 --- a/application/config/ConfigPhp.php +++ b/application/config/ConfigPhp.php | |||
@@ -24,6 +24,51 @@ class ConfigPhp implements ConfigIO | |||
24 | ); | 24 | ); |
25 | 25 | ||
26 | /** | 26 | /** |
27 | * Map legacy config keys with the new ones. | ||
28 | * If ConfigPhp is used, getting <newkey> will actually look for <legacykey>. | ||
29 | * The Updater will use this array to transform keys when switching to JSON. | ||
30 | * | ||
31 | * @var array current key => legacy key. | ||
32 | */ | ||
33 | public static $LEGACY_KEYS_MAPPING = array( | ||
34 | 'credentials.login' => 'login', | ||
35 | 'credentials.hash' => 'hash', | ||
36 | 'credentials.salt' => 'salt', | ||
37 | 'path.data_dir' => 'config.DATADIR', | ||
38 | 'path.config' => 'config.CONFIG_FILE', | ||
39 | 'path.datastore' => 'config.DATASTORE', | ||
40 | 'path.updates' => 'config.UPDATES_FILE', | ||
41 | 'path.log' => 'config.LOG_FILE', | ||
42 | 'path.update_check' => 'config.UPDATECHECK_FILENAME', | ||
43 | 'path.raintpl_tpl' => 'config.RAINTPL_TPL', | ||
44 | 'path.raintpl_tmp' => 'config.RAINTPL_TMP', | ||
45 | 'path.thumbnails_cache' => 'config.CACHEDIR', | ||
46 | 'path.page_cache' => 'config.PAGECACHE', | ||
47 | 'path.ban_file' => 'config.IPBANS_FILENAME', | ||
48 | 'security.session_protection_disabled' => 'disablesessionprotection', | ||
49 | 'security.ban_after' => 'config.BAN_AFTER', | ||
50 | 'security.ban_duration' => 'config.BAN_DURATION', | ||
51 | 'general.title' => 'title', | ||
52 | 'general.timezone' => 'timezone', | ||
53 | 'general.header_link' => 'titleLink', | ||
54 | 'general.check_updates' => 'config.ENABLE_UPDATECHECK', | ||
55 | 'general.check_updates_branch' => 'config.UPDATECHECK_BRANCH', | ||
56 | 'general.check_updates_interval' => 'config.UPDATECHECK_INTERVAL', | ||
57 | 'general.default_private_links' => 'privateLinkByDefault', | ||
58 | 'general.rss_permalinks' => 'config.ENABLE_RSS_PERMALINKS', | ||
59 | 'general.links_per_page' => 'config.LINKS_PER_PAGE', | ||
60 | 'general.enable_thumbnails' => 'config.ENABLE_THUMBNAILS', | ||
61 | 'general.enable_localcache' => 'config.ENABLE_LOCALCACHE', | ||
62 | 'general.enabled_plugins' => 'config.ENABLED_PLUGINS', | ||
63 | 'extras.redirector' => 'redirector', | ||
64 | 'extras.redirector_encode_url' => 'config.REDIRECTOR_URLENCODE', | ||
65 | 'extras.show_atom' => 'config.SHOW_ATOM', | ||
66 | 'extras.hide_public_links' => 'config.HIDE_PUBLIC_LINKS', | ||
67 | 'extras.hide_timestamps' => 'config.HIDE_TIMESTAMPS', | ||
68 | 'extras.open_shaarli' => 'config.OPEN_SHAARLI', | ||
69 | ); | ||
70 | |||
71 | /** | ||
27 | * @inheritdoc | 72 | * @inheritdoc |
28 | */ | 73 | */ |
29 | function read($filepath) | 74 | function read($filepath) |