aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorArthurHoaro <arthur@hoa.ro>2015-06-29 12:23:00 +0200
committerArthurHoaro <arthur@hoa.ro>2015-07-09 20:46:03 +0200
commitdd484b90b1c15989210d7379e51256d545856d95 (patch)
treec7300dc1c54388699ca45055cae58b2740525c80
parenteee711c0a8583e1c2ea2186544795d59fa41d9f6 (diff)
downloadShaarli-dd484b90b1c15989210d7379e51256d545856d95.tar.gz
Shaarli-dd484b90b1c15989210d7379e51256d545856d95.tar.zst
Shaarli-dd484b90b1c15989210d7379e51256d545856d95.zip
All settings are now stored in config.php
Isolate functions related to config in Config.php + add unit tests + code_sniffer. options.php is not supported anymore, but its content will be automatically saved into config.php Fixes #shaarli/Shaarli#41 *TODO*: update [documentation](https://github.com/shaarli/Shaarli/wiki#configuration).
-rwxr-xr-xapplication/Config.php129
-rw-r--r--index.php94
-rwxr-xr-xtests/ConfigTest.php177
3 files changed, 362 insertions, 38 deletions
diff --git a/application/Config.php b/application/Config.php
new file mode 100755
index 00000000..0b01b524
--- /dev/null
+++ b/application/Config.php
@@ -0,0 +1,129 @@
1<?php
2/**
3 * Functions related to configuration management.
4 */
5
6/**
7 * Re-write configuration file according to given array.
8 * Requires mandatory fields listed in $MANDATORY_FIELDS.
9 *
10 * @param array $config contains all configuration fields.
11 * @param bool $isLoggedIn true if user is logged in.
12 *
13 * @return void
14 *
15 * @throws MissingFieldConfigException: a mandatory field has not been provided in $config.
16 * @throws UnauthorizedConfigException: user is not authorize to change configuration.
17 * @throws Exception: an error occured while writing the new config file.
18 */
19function writeConfig($config, $isLoggedIn)
20{
21 // These fields are required in configuration.
22 $MANDATORY_FIELDS = [
23 'login', 'hash', 'salt', 'timezone', 'title', 'titleLink',
24 'redirector', 'disablesessionprotection', 'privateLinkByDefault'
25 ];
26
27 if (!isset($config['config']['CONFIG_FILE'])) {
28 throw new MissingFieldConfigException('CONFIG_FILE');
29 }
30
31 // Only logged in user can alter config.
32 if (is_file($config['config']['CONFIG_FILE']) && !$isLoggedIn) {
33 throw new UnauthorizedConfigException();
34 }
35
36 // Check that all mandatory fields are provided in $config.
37 foreach ($MANDATORY_FIELDS as $field) {
38 if (!isset($config[$field])) {
39 throw new MissingFieldConfigException($field);
40 }
41 }
42
43 $configStr = '<?php '. PHP_EOL;
44 $configStr .= '$GLOBALS[\'login\'] = '.var_export($config['login'], true).';'. PHP_EOL;
45 $configStr .= '$GLOBALS[\'hash\'] = '.var_export($config['hash'], true).';'. PHP_EOL;
46 $configStr .= '$GLOBALS[\'salt\'] = '.var_export($config['salt'], true).'; '. PHP_EOL;
47 $configStr .= '$GLOBALS[\'timezone\'] = '.var_export($config['timezone'], true).';'. PHP_EOL;
48 $configStr .= 'date_default_timezone_set('.var_export($config['timezone'], true).');'. PHP_EOL;
49 $configStr .= '$GLOBALS[\'title\'] = '.var_export($config['title'], true).';'. PHP_EOL;
50 $configStr .= '$GLOBALS[\'titleLink\'] = '.var_export($config['titleLink'], true).'; '. PHP_EOL;
51 $configStr .= '$GLOBALS[\'redirector\'] = '.var_export($config['redirector'], true).'; '. PHP_EOL;
52 $configStr .= '$GLOBALS[\'disablesessionprotection\'] = '.var_export($config['disablesessionprotection'], true).'; '. PHP_EOL;
53 $configStr .= '$GLOBALS[\'privateLinkByDefault\'] = '.var_export($config['privateLinkByDefault'], true).'; '. PHP_EOL;
54
55 // Store all $config['config']
56 foreach ($config['config'] as $key => $value) {
57 $configStr .= '$GLOBALS[\'config\'][\''. $key .'\'] = '.var_export($config['config'][$key], true).';'. PHP_EOL;
58 }
59 $configStr .= '?>';
60
61 if (!file_put_contents($config['config']['CONFIG_FILE'], $configStr)
62 || strcmp(file_get_contents($config['config']['CONFIG_FILE']), $configStr) != 0
63 ) {
64 throw new Exception(
65 'Shaarli could not create the config file.
66 Please make sure Shaarli has the right to write in the folder is it installed in.'
67 );
68 }
69}
70
71/**
72 * Milestone 0.9 - shaarli/Shaarli#41: options.php is not supported anymore.
73 * ==> if user is loggedIn, merge its content with config.php, then delete options.php.
74 *
75 * @param array $config contains all configuration fields.
76 * @param bool $isLoggedIn true if user is logged in.
77 *
78 * @return void
79 */
80function mergeDeprecatedConfig($config, $isLoggedIn)
81{
82 $config_file = $config['config']['CONFIG_FILE'];
83
84 if (is_file($config['config']['DATADIR'].'/options.php') && $isLoggedIn) {
85 include $config['config']['DATADIR'].'/options.php';
86
87 // Load GLOBALS into config
88 foreach ($GLOBALS as $key => $value) {
89 $config[$key] = $value;
90 }
91 $config['config']['CONFIG_FILE'] = $config_file;
92 writeConfig($config, $isLoggedIn);
93
94 unlink($config['config']['DATADIR'].'/options.php');
95 }
96}
97
98/**
99 * Exception used if a mandatory field is missing in given configuration.
100 */
101class MissingFieldConfigException extends Exception
102{
103 public $field;
104
105 /**
106 * Construct exception.
107 *
108 * @param string $field field name missing.
109 */
110 public function __construct($field)
111 {
112 $this->field = $field;
113 $this->message = 'Configuration value is required for '. $this->field;
114 }
115}
116
117/**
118 * Exception used if an unauthorized attempt to edit configuration has been made.
119 */
120class UnauthorizedConfigException extends Exception
121{
122 /**
123 * Construct exception.
124 */
125 public function __construct()
126 {
127 $this->message = 'You are not authorized to alter config.';
128 }
129} \ No newline at end of file
diff --git a/index.php b/index.php
index bbe302a6..b73e0b98 100644
--- a/index.php
+++ b/index.php
@@ -11,7 +11,8 @@
11date_default_timezone_set('UTC'); 11date_default_timezone_set('UTC');
12 12
13// ----------------------------------------------------------------------------------------------- 13// -----------------------------------------------------------------------------------------------
14// Hardcoded parameter (These parameters can be overwritten by creating the file /data/options.php) 14// Hardcoded parameter (These parameters can be overwritten by editing the file /data/config.php)
15// You should not touch any code below (or at your own risks!)
15$GLOBALS['config']['DATADIR'] = 'data'; // Data subdirectory 16$GLOBALS['config']['DATADIR'] = 'data'; // Data subdirectory
16$GLOBALS['config']['CONFIG_FILE'] = $GLOBALS['config']['DATADIR'].'/config.php'; // Configuration file (user login/password) 17$GLOBALS['config']['CONFIG_FILE'] = $GLOBALS['config']['DATADIR'].'/config.php'; // Configuration file (user login/password)
17$GLOBALS['config']['DATASTORE'] = $GLOBALS['config']['DATADIR'].'/datastore.php'; // Data storage file. 18$GLOBALS['config']['DATASTORE'] = $GLOBALS['config']['DATADIR'].'/datastore.php'; // Data storage file.
@@ -36,10 +37,6 @@ $GLOBALS['config']['ARCHIVE_ORG'] = false; // For each link, add a link to an ar
36$GLOBALS['config']['ENABLE_RSS_PERMALINKS'] = true; // Enable RSS permalinks by default. This corresponds to the default behavior of shaarli before this was added as an option. 37$GLOBALS['config']['ENABLE_RSS_PERMALINKS'] = true; // Enable RSS permalinks by default. This corresponds to the default behavior of shaarli before this was added as an option.
37$GLOBALS['config']['HIDE_PUBLIC_LINKS'] = false; 38$GLOBALS['config']['HIDE_PUBLIC_LINKS'] = false;
38// ----------------------------------------------------------------------------------------------- 39// -----------------------------------------------------------------------------------------------
39// You should not touch below (or at your own risks!)
40// Optional config file.
41if (is_file($GLOBALS['config']['DATADIR'].'/options.php')) require($GLOBALS['config']['DATADIR'].'/options.php');
42
43define('shaarli_version','0.0.45beta'); 40define('shaarli_version','0.0.45beta');
44// http://server.com/x/shaarli --> /shaarli/ 41// http://server.com/x/shaarli --> /shaarli/
45define('WEB_PATH', substr($_SERVER["REQUEST_URI"], 0, 1+strrpos($_SERVER["REQUEST_URI"], '/', 0))); 42define('WEB_PATH', substr($_SERVER["REQUEST_URI"], 0, 1+strrpos($_SERVER["REQUEST_URI"], '/', 0)));
@@ -69,6 +66,7 @@ error_reporting(E_ALL^E_WARNING); // See all error except warnings.
69// Shaarli library 66// Shaarli library
70require_once 'application/LinkDB.php'; 67require_once 'application/LinkDB.php';
71require_once 'application/Utils.php'; 68require_once 'application/Utils.php';
69require_once 'application/Config.php';
72 70
73include "inc/rain.tpl.class.php"; //include Rain TPL 71include "inc/rain.tpl.class.php"; //include Rain TPL
74raintpl::$tpl_dir = $GLOBALS['config']['RAINTPL_TPL']; // template directory 72raintpl::$tpl_dir = $GLOBALS['config']['RAINTPL_TPL']; // template directory
@@ -100,7 +98,6 @@ if (empty($GLOBALS['title'])) $GLOBALS['title']='Shared links on '.escape(indexU
100if (empty($GLOBALS['timezone'])) $GLOBALS['timezone']=date_default_timezone_get(); 98if (empty($GLOBALS['timezone'])) $GLOBALS['timezone']=date_default_timezone_get();
101if (empty($GLOBALS['redirector'])) $GLOBALS['redirector']=''; 99if (empty($GLOBALS['redirector'])) $GLOBALS['redirector']='';
102if (empty($GLOBALS['disablesessionprotection'])) $GLOBALS['disablesessionprotection']=false; 100if (empty($GLOBALS['disablesessionprotection'])) $GLOBALS['disablesessionprotection']=false;
103if (empty($GLOBALS['disablejquery'])) $GLOBALS['disablejquery']=false;
104if (empty($GLOBALS['privateLinkByDefault'])) $GLOBALS['privateLinkByDefault']=false; 101if (empty($GLOBALS['privateLinkByDefault'])) $GLOBALS['privateLinkByDefault']=false;
105if (empty($GLOBALS['titleLink'])) $GLOBALS['titleLink']='?'; 102if (empty($GLOBALS['titleLink'])) $GLOBALS['titleLink']='?';
106// I really need to rewrite Shaarli with a proper configuation manager. 103// I really need to rewrite Shaarli with a proper configuation manager.
@@ -709,7 +706,7 @@ function showRSS()
709 if (!empty($_GET['searchterm'])) $linksToDisplay = $LINKSDB->filterFulltext($_GET['searchterm']); 706 if (!empty($_GET['searchterm'])) $linksToDisplay = $LINKSDB->filterFulltext($_GET['searchterm']);
710 else if (!empty($_GET['searchtags'])) $linksToDisplay = $LINKSDB->filterTags(trim($_GET['searchtags'])); 707 else if (!empty($_GET['searchtags'])) $linksToDisplay = $LINKSDB->filterTags(trim($_GET['searchtags']));
711 else $linksToDisplay = $LINKSDB; 708 else $linksToDisplay = $LINKSDB;
712 709
713 $nblinksToDisplay = 50; // Number of links to display. 710 $nblinksToDisplay = 50; // Number of links to display.
714 if (!empty($_GET['nb'])) // In URL, you can specificy the number of links. Example: nb=200 or nb=all for all links. 711 if (!empty($_GET['nb'])) // In URL, you can specificy the number of links. Example: nb=200 or nb=all for all links.
715 { 712 {
@@ -789,7 +786,7 @@ function showATOM()
789 if (!empty($_GET['searchterm'])) $linksToDisplay = $LINKSDB->filterFulltext($_GET['searchterm']); 786 if (!empty($_GET['searchterm'])) $linksToDisplay = $LINKSDB->filterFulltext($_GET['searchterm']);
790 else if (!empty($_GET['searchtags'])) $linksToDisplay = $LINKSDB->filterTags(trim($_GET['searchtags'])); 787 else if (!empty($_GET['searchtags'])) $linksToDisplay = $LINKSDB->filterTags(trim($_GET['searchtags']));
791 else $linksToDisplay = $LINKSDB; 788 else $linksToDisplay = $LINKSDB;
792 789
793 $nblinksToDisplay = 50; // Number of links to display. 790 $nblinksToDisplay = 50; // Number of links to display.
794 if (!empty($_GET['nb'])) // In URL, you can specificy the number of links. Example: nb=200 or nb=all for all links. 791 if (!empty($_GET['nb'])) // In URL, you can specificy the number of links. Example: nb=200 or nb=all for all links.
795 { 792 {
@@ -1041,7 +1038,7 @@ function renderPage()
1041 if (!empty($_GET['searchterm'])) $links = $LINKSDB->filterFulltext($_GET['searchterm']); 1038 if (!empty($_GET['searchterm'])) $links = $LINKSDB->filterFulltext($_GET['searchterm']);
1042 elseif (!empty($_GET['searchtags'])) $links = $LINKSDB->filterTags(trim($_GET['searchtags'])); 1039 elseif (!empty($_GET['searchtags'])) $links = $LINKSDB->filterTags(trim($_GET['searchtags']));
1043 else $links = $LINKSDB; 1040 else $links = $LINKSDB;
1044 1041
1045 $body=''; 1042 $body='';
1046 $linksToDisplay=array(); 1043 $linksToDisplay=array();
1047 1044
@@ -1056,7 +1053,7 @@ function renderPage()
1056 $linksToDisplay[]=$link; // Add to array. 1053 $linksToDisplay[]=$link; // Add to array.
1057 } 1054 }
1058 } 1055 }
1059 1056
1060 $PAGE = new pageBuilder; 1057 $PAGE = new pageBuilder;
1061 $PAGE->assign('linkcount',count($LINKSDB)); 1058 $PAGE->assign('linkcount',count($LINKSDB));
1062 $PAGE->assign('linksToDisplay',$linksToDisplay); 1059 $PAGE->assign('linksToDisplay',$linksToDisplay);
@@ -1214,7 +1211,19 @@ function renderPage()
1214 // Save new password 1211 // Save new password
1215 $GLOBALS['salt'] = sha1(uniqid('',true).'_'.mt_rand()); // Salt renders rainbow-tables attacks useless. 1212 $GLOBALS['salt'] = sha1(uniqid('',true).'_'.mt_rand()); // Salt renders rainbow-tables attacks useless.
1216 $GLOBALS['hash'] = sha1($_POST['setpassword'].$GLOBALS['login'].$GLOBALS['salt']); 1213 $GLOBALS['hash'] = sha1($_POST['setpassword'].$GLOBALS['login'].$GLOBALS['salt']);
1217 writeConfig(); 1214 try {
1215 writeConfig($GLOBALS, isLoggedIn());
1216 }
1217 catch(Exception $e) {
1218 error_log(
1219 'ERROR while writing config file after changing password.' . PHP_EOL .
1220 $e->getMessage()
1221 );
1222
1223 // TODO: do not handle exceptions/errors in JS.
1224 echo '<script>alert("'. $e->getMessage() .'");document.location=\'?do=tools\';</script>';
1225 exit;
1226 }
1218 echo '<script>alert("Your password has been changed.");document.location=\'?do=tools\';</script>'; 1227 echo '<script>alert("Your password has been changed.");document.location=\'?do=tools\';</script>';
1219 exit; 1228 exit;
1220 } 1229 }
@@ -1243,12 +1252,23 @@ function renderPage()
1243 $GLOBALS['titleLink']=$_POST['titleLink']; 1252 $GLOBALS['titleLink']=$_POST['titleLink'];
1244 $GLOBALS['redirector']=$_POST['redirector']; 1253 $GLOBALS['redirector']=$_POST['redirector'];
1245 $GLOBALS['disablesessionprotection']=!empty($_POST['disablesessionprotection']); 1254 $GLOBALS['disablesessionprotection']=!empty($_POST['disablesessionprotection']);
1246 $GLOBALS['disablejquery']=!empty($_POST['disablejquery']);
1247 $GLOBALS['privateLinkByDefault']=!empty($_POST['privateLinkByDefault']); 1255 $GLOBALS['privateLinkByDefault']=!empty($_POST['privateLinkByDefault']);
1248 $GLOBALS['config']['ENABLE_RSS_PERMALINKS']= !empty($_POST['enableRssPermalinks']); 1256 $GLOBALS['config']['ENABLE_RSS_PERMALINKS']= !empty($_POST['enableRssPermalinks']);
1249 $GLOBALS['config']['ENABLE_UPDATECHECK'] = !empty($_POST['updateCheck']); 1257 $GLOBALS['config']['ENABLE_UPDATECHECK'] = !empty($_POST['updateCheck']);
1250 $GLOBALS['config']['HIDE_PUBLIC_LINKS'] = !empty($_POST['hidePublicLinks']); 1258 $GLOBALS['config']['HIDE_PUBLIC_LINKS'] = !empty($_POST['hidePublicLinks']);
1251 writeConfig(); 1259 try {
1260 writeConfig($GLOBALS, isLoggedIn());
1261 }
1262 catch(Exception $e) {
1263 error_log(
1264 'ERROR while writing config file after configuration update.' . PHP_EOL .
1265 $e->getMessage()
1266 );
1267
1268 // TODO: do not handle exceptions/errors in JS.
1269 echo '<script>alert("'. $e->getMessage() .'");document.location=\'?do=tools\';</script>';
1270 exit;
1271 }
1252 echo '<script>alert("Configuration was saved.");document.location=\'?do=tools\';</script>'; 1272 echo '<script>alert("Configuration was saved.");document.location=\'?do=tools\';</script>';
1253 exit; 1273 exit;
1254 } 1274 }
@@ -2007,7 +2027,19 @@ function install()
2007 $GLOBALS['hash'] = sha1($_POST['setpassword'].$GLOBALS['login'].$GLOBALS['salt']); 2027 $GLOBALS['hash'] = sha1($_POST['setpassword'].$GLOBALS['login'].$GLOBALS['salt']);
2008 $GLOBALS['title'] = (empty($_POST['title']) ? 'Shared links on '.escape(indexUrl()) : $_POST['title'] ); 2028 $GLOBALS['title'] = (empty($_POST['title']) ? 'Shared links on '.escape(indexUrl()) : $_POST['title'] );
2009 $GLOBALS['config']['ENABLE_UPDATECHECK'] = !empty($_POST['updateCheck']); 2029 $GLOBALS['config']['ENABLE_UPDATECHECK'] = !empty($_POST['updateCheck']);
2010 writeConfig(); 2030 try {
2031 writeConfig($GLOBALS, isLoggedIn());
2032 }
2033 catch(Exception $e) {
2034 error_log(
2035 'ERROR while writing config file after installation.' . PHP_EOL .
2036 $e->getMessage()
2037 );
2038
2039 // TODO: do not handle exceptions/errors in JS.
2040 echo '<script>alert("'. $e->getMessage() .'");document.location=\'?\';</script>';
2041 exit;
2042 }
2011 echo '<script>alert("Shaarli is now configured. Please enter your login/password and start shaaring your links!");document.location=\'?do=login\';</script>'; 2043 echo '<script>alert("Shaarli is now configured. Please enter your login/password and start shaaring your links!");document.location=\'?do=login\';</script>';
2012 exit; 2044 exit;
2013 } 2045 }
@@ -2121,30 +2153,7 @@ if (!function_exists('json_encode')) {
2121 } 2153 }
2122} 2154}
2123 2155
2124// Re-write configuration file according to globals. 2156
2125// Requires some $GLOBALS to be set (login,hash,salt,title).
2126// If the config file cannot be saved, an error message is displayed and the user is redirected to "Tools" menu.
2127// (otherwise, the function simply returns.)
2128function writeConfig()
2129{
2130 if (is_file($GLOBALS['config']['CONFIG_FILE']) && !isLoggedIn()) die('You are not authorized to alter config.'); // Only logged in user can alter config.
2131 $config='<?php $GLOBALS[\'login\']='.var_export($GLOBALS['login'],true).'; $GLOBALS[\'hash\']='.var_export($GLOBALS['hash'],true).'; $GLOBALS[\'salt\']='.var_export($GLOBALS['salt'],true).'; ';
2132 $config .='$GLOBALS[\'timezone\']='.var_export($GLOBALS['timezone'],true).'; date_default_timezone_set('.var_export($GLOBALS['timezone'],true).'); $GLOBALS[\'title\']='.var_export($GLOBALS['title'],true).';';
2133 $config .= '$GLOBALS[\'titleLink\']='.var_export($GLOBALS['titleLink'],true).'; ';
2134 $config .= '$GLOBALS[\'redirector\']='.var_export($GLOBALS['redirector'],true).'; ';
2135 $config .= '$GLOBALS[\'disablesessionprotection\']='.var_export($GLOBALS['disablesessionprotection'],true).'; ';
2136 $config .= '$GLOBALS[\'disablejquery\']='.var_export($GLOBALS['disablejquery'],true).'; ';
2137 $config .= '$GLOBALS[\'privateLinkByDefault\']='.var_export($GLOBALS['privateLinkByDefault'],true).'; ';
2138 $config .= '$GLOBALS[\'config\'][\'ENABLE_RSS_PERMALINKS\']='.var_export($GLOBALS['config']['ENABLE_RSS_PERMALINKS'], true).'; ';
2139 $config .= '$GLOBALS[\'config\'][\'ENABLE_UPDATECHECK\']='.var_export($GLOBALS['config']['ENABLE_UPDATECHECK'], true).'; ';
2140 $config .= '$GLOBALS[\'config\'][\'HIDE_PUBLIC_LINKS\']='.var_export($GLOBALS['config']['HIDE_PUBLIC_LINKS'], true).'; ';
2141 $config .= ' ?>';
2142 if (!file_put_contents($GLOBALS['config']['CONFIG_FILE'],$config) || strcmp(file_get_contents($GLOBALS['config']['CONFIG_FILE']),$config)!=0)
2143 {
2144 echo '<script>alert("Shaarli could not create the config file. Please make sure Shaarli has the right to write in the folder is it installed in.");document.location=\'?\';</script>';
2145 exit;
2146 }
2147}
2148 2157
2149/* Because some f*cking services like flickr require an extra HTTP request to get the thumbnail URL, 2158/* Because some f*cking services like flickr require an extra HTTP request to get the thumbnail URL,
2150 I have deported the thumbnail URL code generation here, otherwise this would slow down page generation. 2159 I have deported the thumbnail URL code generation here, otherwise this would slow down page generation.
@@ -2373,6 +2382,15 @@ function invalidateCaches()
2373 pageCache::purgeCache(); // Purge page cache shared by sessions. 2382 pageCache::purgeCache(); // Purge page cache shared by sessions.
2374} 2383}
2375 2384
2385try {
2386 mergeDeprecatedConfig($GLOBALS, isLoggedIn());
2387} catch(Exception $e) {
2388 error_log(
2389 'ERROR while merging deprecated options.php file.' . PHP_EOL .
2390 $e->getMessage()
2391 );
2392}
2393
2376if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=genthumbnail')) { genThumbnail(); exit; } // Thumbnail generation/cache does not need the link database. 2394if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=genthumbnail')) { genThumbnail(); exit; } // Thumbnail generation/cache does not need the link database.
2377if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=rss')) { showRSS(); exit; } 2395if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=rss')) { showRSS(); exit; }
2378if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=atom')) { showATOM(); exit; } 2396if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=atom')) { showATOM(); exit; }
diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php
new file mode 100755
index 00000000..4279c57e
--- /dev/null
+++ b/tests/ConfigTest.php
@@ -0,0 +1,177 @@
1<?php
2/**
3 * Config' tests
4 */
5
6require_once 'application/Config.php';
7
8/**
9 * Unitary tests for Shaarli config related functions
10 */
11class ConfigTest extends PHPUnit_Framework_TestCase
12{
13 // Configuration input set.
14 private static $_configFields;
15
16 /**
17 * Executed before each test.
18 */
19 public function setUp()
20 {
21 self::$_configFields = [
22 'login' => 'login',
23 'hash' => 'hash',
24 'salt' => 'salt',
25 'timezone' => 'Europe/Paris',
26 'title' => 'title',
27 'titleLink' => 'titleLink',
28 'redirector' => '',
29 'disablesessionprotection' => false,
30 'privateLinkByDefault' => false,
31 'config' => [
32 'CONFIG_FILE' => 'tests/config.php',
33 'DATADIR' => 'tests',
34 'config1' => 'config1data',
35 'config2' => 'config2data',
36 ]
37 ];
38 }
39
40 /**
41 * Executed after each test.
42 *
43 * @return void
44 */
45 public function tearDown()
46 {
47 if (is_file(self::$_configFields['config']['CONFIG_FILE'])) {
48 unlink(self::$_configFields['config']['CONFIG_FILE']);
49 }
50 }
51
52 /**
53 * Test writeConfig function, valid use case, while being logged in.
54 */
55 public function testWriteConfig()
56 {
57 writeConfig(self::$_configFields, true);
58
59 include self::$_configFields['config']['CONFIG_FILE'];
60 $this->assertEquals(self::$_configFields['login'], $GLOBALS['login']);
61 $this->assertEquals(self::$_configFields['hash'], $GLOBALS['hash']);
62 $this->assertEquals(self::$_configFields['salt'], $GLOBALS['salt']);
63 $this->assertEquals(self::$_configFields['timezone'], $GLOBALS['timezone']);
64 $this->assertEquals(self::$_configFields['title'], $GLOBALS['title']);
65 $this->assertEquals(self::$_configFields['titleLink'], $GLOBALS['titleLink']);
66 $this->assertEquals(self::$_configFields['redirector'], $GLOBALS['redirector']);
67 $this->assertEquals(self::$_configFields['disablesessionprotection'], $GLOBALS['disablesessionprotection']);
68 $this->assertEquals(self::$_configFields['privateLinkByDefault'], $GLOBALS['privateLinkByDefault']);
69 $this->assertEquals(self::$_configFields['config']['config1'], $GLOBALS['config']['config1']);
70 $this->assertEquals(self::$_configFields['config']['config2'], $GLOBALS['config']['config2']);
71 }
72
73 /**
74 * Test writeConfig option while logged in:
75 * 1. init fields.
76 * 2. update fields, add new sub config, add new root config.
77 * 3. rewrite config.
78 * 4. check result.
79 */
80 public function testWriteConfigFieldUpdate()
81 {
82 writeConfig(self::$_configFields, true);
83 self::$_configFields['title'] = 'ok';
84 self::$_configFields['config']['config1'] = 'ok';
85 self::$_configFields['config']['config_new'] = 'ok';
86 self::$_configFields['new'] = 'should not be saved';
87 writeConfig(self::$_configFields, true);
88
89 include self::$_configFields['config']['CONFIG_FILE'];
90 $this->assertEquals('ok', $GLOBALS['title']);
91 $this->assertEquals('ok', $GLOBALS['config']['config1']);
92 $this->assertEquals('ok', $GLOBALS['config']['config_new']);
93 $this->assertFalse(isset($GLOBALS['new']));
94 }
95
96 /**
97 * Test writeConfig function with an empty array.
98 *
99 * @expectedException MissingFieldConfigException
100 */
101 public function testWriteConfigEmpty()
102 {
103 writeConfig(array(), true);
104 }
105
106 /**
107 * Test writeConfig function with a missing mandatory field.
108 *
109 * @expectedException MissingFieldConfigException
110 */
111 public function testWriteConfigMissingField()
112 {
113 unset(self::$_configFields['login']);
114 writeConfig(self::$_configFields, true);
115 }
116
117 /**
118 * Test writeConfig function while being logged out, and there is no config file existing.
119 */
120 public function testWriteConfigLoggedOutNoFile()
121 {
122 writeConfig(self::$_configFields, false);
123 }
124
125 /**
126 * Test writeConfig function while being logged out, and a config file already exists.
127 *
128 * @expectedException UnauthorizedConfigException
129 */
130 public function testWriteConfigLoggedOutWithFile()
131 {
132 file_put_contents(self::$_configFields['config']['CONFIG_FILE'], '');
133 writeConfig(self::$_configFields, false);
134 }
135
136 /**
137 * Test mergeDeprecatedConfig while being logged in:
138 * 1. init a config file.
139 * 2. init a options.php file with update value.
140 * 3. merge.
141 * 4. check updated value in config file.
142 */
143 public function testMergeDeprecatedConfig()
144 {
145 // init
146 writeConfig(self::$_configFields, true);
147 $configCopy = self::$_configFields;
148 $invert = !$configCopy['privateLinkByDefault'];
149 $configCopy['privateLinkByDefault'] = $invert;
150
151 // Use writeConfig to create a options.php
152 $configCopy['config']['CONFIG_FILE'] = 'tests/options.php';
153 writeConfig($configCopy, true);
154
155 $this->assertTrue(is_file($configCopy['config']['CONFIG_FILE']));
156
157 // merge configs
158 mergeDeprecatedConfig(self::$_configFields, true);
159
160 // make sure updated field is changed
161 include self::$_configFields['config']['CONFIG_FILE'];
162 $this->assertEquals($invert, $GLOBALS['privateLinkByDefault']);
163 $this->assertFalse(is_file($configCopy['config']['CONFIG_FILE']));
164 }
165
166 /**
167 * Test mergeDeprecatedConfig while being logged in without options file.
168 */
169 public function testMergeDeprecatedConfigNoFile()
170 {
171 writeConfig(self::$_configFields, true);
172 mergeDeprecatedConfig(self::$_configFields, true);
173
174 include self::$_configFields['config']['CONFIG_FILE'];
175 $this->assertEquals(self::$_configFields['login'], $GLOBALS['login']);
176 }
177} \ No newline at end of file