diff options
-rw-r--r-- | .travis.yml | 3 | ||||
-rw-r--r-- | Makefile | 10 | ||||
-rwxr-xr-x[-rw-r--r--] | README.md | 6 | ||||
-rwxr-xr-x | application/Config.php | 6 | ||||
-rw-r--r-- | application/TimeZone.php | 110 | ||||
-rw-r--r-- | application/Utils.php | 23 | ||||
-rw-r--r-- | index.php | 113 | ||||
-rw-r--r-- | shaarli_version.php | 2 | ||||
-rwxr-xr-x | tests/ConfigTest.php | 10 | ||||
-rw-r--r-- | tests/LinkDBTest.php | 12 | ||||
-rw-r--r-- | tests/TimeZoneTest.php | 83 | ||||
-rw-r--r-- | tests/UtilsTest.php | 34 | ||||
-rw-r--r-- | tpl/picwall.html | 6 |
13 files changed, 305 insertions, 113 deletions
diff --git a/.travis.yml b/.travis.yml index bcaf682c..80db6506 100644 --- a/.travis.yml +++ b/.travis.yml | |||
@@ -1,10 +1,13 @@ | |||
1 | sudo: false | ||
1 | language: php | 2 | language: php |
2 | php: | 3 | php: |
3 | - 5.6 | 4 | - 5.6 |
4 | - 5.5 | 5 | - 5.5 |
5 | - 5.4 | 6 | - 5.4 |
7 | - 5.3 | ||
6 | install: | 8 | install: |
7 | - composer self-update | 9 | - composer self-update |
8 | - composer install | 10 | - composer install |
9 | script: | 11 | script: |
12 | - make clean | ||
10 | - make test | 13 | - make test |
@@ -106,7 +106,7 @@ mess_detector_summary: mess_title | |||
106 | # See phpunit.xml for configuration | 106 | # See phpunit.xml for configuration |
107 | # https://phpunit.de/manual/current/en/appendixes.configuration.html | 107 | # https://phpunit.de/manual/current/en/appendixes.configuration.html |
108 | ## | 108 | ## |
109 | test: clean | 109 | test: |
110 | @echo "-------" | 110 | @echo "-------" |
111 | @echo "PHPUNIT" | 111 | @echo "PHPUNIT" |
112 | @echo "-------" | 112 | @echo "-------" |
@@ -118,13 +118,13 @@ test: clean | |||
118 | 118 | ||
119 | ### remove all unversioned files | 119 | ### remove all unversioned files |
120 | clean: | 120 | clean: |
121 | @git clean -df | 121 | @git clean -df |
122 | 122 | ||
123 | ### update the local copy of the documentation | 123 | ### update the local copy of the documentation |
124 | doc: clean | 124 | doc: clean |
125 | @rm -rf doc | 125 | @rm -rf doc |
126 | @git clone https://github.com/shaarli/Shaarli.wiki.git doc | 126 | @git clone https://github.com/shaarli/Shaarli.wiki.git doc |
127 | @rm -rf doc/.git | 127 | @rm -rf doc/.git |
128 | 128 | ||
129 | ### Convert local markdown documentation to HTML | 129 | ### Convert local markdown documentation to HTML |
130 | htmldoc: | 130 | htmldoc: |
@@ -55,9 +55,11 @@ Password: `demo` | |||
55 | * [Bugs/Feature requests/Discussion](https://github.com/shaarli/Shaarli/issues/) | 55 | * [Bugs/Feature requests/Discussion](https://github.com/shaarli/Shaarli/issues/) |
56 | 56 | ||
57 | 57 | ||
58 | ## Installing | 58 | ## Requirements |
59 | |||
60 | Check the [Server requirements](https://github.com/shaarli/Shaarli/wiki/Server-requirements) wiki page. | ||
59 | 61 | ||
60 | Shaarli requires php 5.4. `php-gd` is optional and provides thumbnail resizing. | 62 | ## Installing |
61 | 63 | ||
62 | * Download the latest stable release from https://github.com/shaarli/Shaarli/releases | 64 | * Download the latest stable release from https://github.com/shaarli/Shaarli/releases |
63 | * Unpack the archive in a directory on your web server | 65 | * Unpack the archive in a directory on your web server |
diff --git a/application/Config.php b/application/Config.php index 0b01b524..ec799d7f 100755 --- a/application/Config.php +++ b/application/Config.php | |||
@@ -19,10 +19,10 @@ | |||
19 | function writeConfig($config, $isLoggedIn) | 19 | function writeConfig($config, $isLoggedIn) |
20 | { | 20 | { |
21 | // These fields are required in configuration. | 21 | // These fields are required in configuration. |
22 | $MANDATORY_FIELDS = [ | 22 | $MANDATORY_FIELDS = array( |
23 | 'login', 'hash', 'salt', 'timezone', 'title', 'titleLink', | 23 | 'login', 'hash', 'salt', 'timezone', 'title', 'titleLink', |
24 | 'redirector', 'disablesessionprotection', 'privateLinkByDefault' | 24 | 'redirector', 'disablesessionprotection', 'privateLinkByDefault' |
25 | ]; | 25 | ); |
26 | 26 | ||
27 | if (!isset($config['config']['CONFIG_FILE'])) { | 27 | if (!isset($config['config']['CONFIG_FILE'])) { |
28 | throw new MissingFieldConfigException('CONFIG_FILE'); | 28 | throw new MissingFieldConfigException('CONFIG_FILE'); |
@@ -126,4 +126,4 @@ class UnauthorizedConfigException extends Exception | |||
126 | { | 126 | { |
127 | $this->message = 'You are not authorized to alter config.'; | 127 | $this->message = 'You are not authorized to alter config.'; |
128 | } | 128 | } |
129 | } \ No newline at end of file | 129 | } |
diff --git a/application/TimeZone.php b/application/TimeZone.php new file mode 100644 index 00000000..ccbef918 --- /dev/null +++ b/application/TimeZone.php | |||
@@ -0,0 +1,110 @@ | |||
1 | <?php | ||
2 | /** | ||
3 | * Generates the timezone selection form and JavaScript. | ||
4 | * | ||
5 | * Note: 'UTC/UTC' is mapped to 'UTC' to form a valid option | ||
6 | * | ||
7 | * Example: preselect Europe/Paris | ||
8 | * list($htmlform, $js) = templateTZform('Europe/Paris'); | ||
9 | * | ||
10 | * @param string $preselected_timezone preselected timezone (optional) | ||
11 | * | ||
12 | * @return an array containing the generated HTML form and Javascript code | ||
13 | **/ | ||
14 | function generateTimeZoneForm($preselected_timezone='') | ||
15 | { | ||
16 | // Select the first available timezone if no preselected value is passed | ||
17 | if ($preselected_timezone == '') { | ||
18 | $l = timezone_identifiers_list(); | ||
19 | $preselected_timezone = $l[0]; | ||
20 | } | ||
21 | |||
22 | // Try to split the provided timezone | ||
23 | $spos = strpos($preselected_timezone, '/'); | ||
24 | $pcontinent = substr($preselected_timezone, 0, $spos); | ||
25 | $pcity = substr($preselected_timezone, $spos+1); | ||
26 | |||
27 | // Display config form: | ||
28 | $timezone_form = ''; | ||
29 | $timezone_js = ''; | ||
30 | |||
31 | // The list is in the form 'Europe/Paris', 'America/Argentina/Buenos_Aires'... | ||
32 | // We split the list in continents/cities. | ||
33 | $continents = array(); | ||
34 | $cities = array(); | ||
35 | |||
36 | // TODO: use a template to generate the HTML/Javascript form | ||
37 | |||
38 | foreach (timezone_identifiers_list() as $tz) { | ||
39 | if ($tz == 'UTC') { | ||
40 | $tz = 'UTC/UTC'; | ||
41 | } | ||
42 | $spos = strpos($tz, '/'); | ||
43 | |||
44 | if ($spos !== false) { | ||
45 | $continent = substr($tz, 0, $spos); | ||
46 | $city = substr($tz, $spos+1); | ||
47 | $continents[$continent] = 1; | ||
48 | |||
49 | if (!isset($cities[$continent])) { | ||
50 | $cities[$continent] = ''; | ||
51 | } | ||
52 | $cities[$continent] .= '<option value="'.$city.'"'; | ||
53 | if ($pcity == $city) { | ||
54 | $cities[$continent] .= ' selected="selected"'; | ||
55 | } | ||
56 | $cities[$continent] .= '>'.$city.'</option>'; | ||
57 | } | ||
58 | } | ||
59 | |||
60 | $continents_html = ''; | ||
61 | $continents = array_keys($continents); | ||
62 | |||
63 | foreach ($continents as $continent) { | ||
64 | $continents_html .= '<option value="'.$continent.'"'; | ||
65 | if ($pcontinent == $continent) { | ||
66 | $continents_html .= ' selected="selected"'; | ||
67 | } | ||
68 | $continents_html .= '>'.$continent.'</option>'; | ||
69 | } | ||
70 | |||
71 | // Timezone selection form | ||
72 | $timezone_form = 'Continent:'; | ||
73 | $timezone_form .= '<select name="continent" id="continent" onChange="onChangecontinent();">'; | ||
74 | $timezone_form .= $continents_html.'</select>'; | ||
75 | $timezone_form .= ' City:'; | ||
76 | $timezone_form .= '<select name="city" id="city">'.$cities[$pcontinent].'</select><br />'; | ||
77 | |||
78 | // Javascript handler - updates the city list when the user selects a continent | ||
79 | $timezone_js = '<script>'; | ||
80 | $timezone_js .= 'function onChangecontinent() {'; | ||
81 | $timezone_js .= 'document.getElementById("city").innerHTML ='; | ||
82 | $timezone_js .= ' citiescontinent[document.getElementById("continent").value]; }'; | ||
83 | $timezone_js .= 'var citiescontinent = '.json_encode($cities).';'; | ||
84 | $timezone_js .= '</script>'; | ||
85 | |||
86 | return array($timezone_form, $timezone_js); | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * Tells if a continent/city pair form a valid timezone | ||
91 | * | ||
92 | * Note: 'UTC/UTC' is mapped to 'UTC' | ||
93 | * | ||
94 | * @param string $continent the timezone continent | ||
95 | * @param string $city the timezone city | ||
96 | * | ||
97 | * @return whether continent/city is a valid timezone | ||
98 | */ | ||
99 | function isTimeZoneValid($continent, $city) | ||
100 | { | ||
101 | if ($continent == 'UTC' && $city == 'UTC') { | ||
102 | return true; | ||
103 | } | ||
104 | |||
105 | return in_array( | ||
106 | $continent.'/'.$city, | ||
107 | timezone_identifiers_list() | ||
108 | ); | ||
109 | } | ||
110 | ?> | ||
diff --git a/application/Utils.php b/application/Utils.php index 658b97bc..cd4724fa 100644 --- a/application/Utils.php +++ b/application/Utils.php | |||
@@ -48,7 +48,7 @@ function endsWith($haystack, $needle, $case=true) | |||
48 | */ | 48 | */ |
49 | function nl2br_escaped($html) | 49 | function nl2br_escaped($html) |
50 | { | 50 | { |
51 | return str_replace('>','>',str_replace('<','<',nl2br($html))); | 51 | return str_replace('>', '>', str_replace('<', '<', nl2br($html))); |
52 | } | 52 | } |
53 | 53 | ||
54 | /** | 54 | /** |
@@ -117,3 +117,24 @@ function generateLocation($referer, $host, $loopTerms = array()) | |||
117 | 117 | ||
118 | return $final_referer; | 118 | return $final_referer; |
119 | } | 119 | } |
120 | |||
121 | /** | ||
122 | * Checks the PHP version to ensure Shaarli can run | ||
123 | * | ||
124 | * @param string $minVersion minimum PHP required version | ||
125 | * @param string $curVersion current PHP version (use PHP_VERSION) | ||
126 | * | ||
127 | * @throws Exception the PHP version is not supported | ||
128 | */ | ||
129 | function checkPHPVersion($minVersion, $curVersion) | ||
130 | { | ||
131 | if (version_compare($curVersion, $minVersion) < 0) { | ||
132 | throw new Exception( | ||
133 | 'Your PHP version is obsolete!' | ||
134 | .' Shaarli requires at least PHP '.$minVersion.', and thus cannot run.' | ||
135 | .' Your PHP version has known security vulnerabilities and should be' | ||
136 | .' updated as soon as possible.' | ||
137 | ); | ||
138 | } | ||
139 | } | ||
140 | ?> | ||
@@ -1,9 +1,9 @@ | |||
1 | <?php | 1 | <?php |
2 | // Shaarli 0.0.45beta - Shaare your links... | 2 | // Shaarli 0.5.0 - Shaare your links... |
3 | // The personal, minimalist, super-fast, no-database Delicious clone. By sebsauvage.net | 3 | // The personal, minimalist, super-fast, no-database Delicious clone. By sebsauvage.net |
4 | // http://sebsauvage.net/wiki/doku.php?id=php:shaarli | 4 | // http://sebsauvage.net/wiki/doku.php?id=php:shaarli |
5 | // Licence: http://www.opensource.org/licenses/zlib-license.php | 5 | // Licence: http://www.opensource.org/licenses/zlib-license.php |
6 | // Requires: PHP 5.1.x (but autocomplete fields will only work if you have PHP 5.2.x) | 6 | // Requires: PHP 5.3.x |
7 | // ----------------------------------------------------------------------------------------------- | 7 | // ----------------------------------------------------------------------------------------------- |
8 | // NEVER TRUST IN PHP.INI | 8 | // NEVER TRUST IN PHP.INI |
9 | // Some hosts do not define a default timezone in php.ini, | 9 | // Some hosts do not define a default timezone in php.ini, |
@@ -37,7 +37,7 @@ $GLOBALS['config']['ARCHIVE_ORG'] = false; // For each link, add a link to an ar | |||
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']['ENABLE_RSS_PERMALINKS'] = true; // Enable RSS permalinks by default. This corresponds to the default behavior of shaarli before this was added as an option. |
38 | $GLOBALS['config']['HIDE_PUBLIC_LINKS'] = false; | 38 | $GLOBALS['config']['HIDE_PUBLIC_LINKS'] = false; |
39 | // ----------------------------------------------------------------------------------------------- | 39 | // ----------------------------------------------------------------------------------------------- |
40 | define('shaarli_version','0.0.45beta'); | 40 | define('shaarli_version','0.5.0'); |
41 | // http://server.com/x/shaarli --> /shaarli/ | 41 | // http://server.com/x/shaarli --> /shaarli/ |
42 | define('WEB_PATH', substr($_SERVER["REQUEST_URI"], 0, 1+strrpos($_SERVER["REQUEST_URI"], '/', 0))); | 42 | define('WEB_PATH', substr($_SERVER["REQUEST_URI"], 0, 1+strrpos($_SERVER["REQUEST_URI"], '/', 0))); |
43 | 43 | ||
@@ -59,7 +59,6 @@ ini_set('max_input_time','60'); // High execution time in case of problematic i | |||
59 | ini_set('memory_limit', '128M'); // Try to set max upload file size and read (May not work on some hosts). | 59 | ini_set('memory_limit', '128M'); // Try to set max upload file size and read (May not work on some hosts). |
60 | ini_set('post_max_size', '16M'); | 60 | ini_set('post_max_size', '16M'); |
61 | ini_set('upload_max_filesize', '16M'); | 61 | ini_set('upload_max_filesize', '16M'); |
62 | checkphpversion(); | ||
63 | error_reporting(E_ALL^E_WARNING); // See all error except warnings. | 62 | error_reporting(E_ALL^E_WARNING); // See all error except warnings. |
64 | //error_reporting(-1); // See all errors (for debugging only) | 63 | //error_reporting(-1); // See all errors (for debugging only) |
65 | 64 | ||
@@ -70,9 +69,19 @@ if (is_file($GLOBALS['config']['CONFIG_FILE'])) { | |||
70 | 69 | ||
71 | // Shaarli library | 70 | // Shaarli library |
72 | require_once 'application/LinkDB.php'; | 71 | require_once 'application/LinkDB.php'; |
72 | require_once 'application/TimeZone.php'; | ||
73 | require_once 'application/Utils.php'; | 73 | require_once 'application/Utils.php'; |
74 | require_once 'application/Config.php'; | 74 | require_once 'application/Config.php'; |
75 | 75 | ||
76 | // Ensure the PHP version is supported | ||
77 | try { | ||
78 | checkPHPVersion('5.3', PHP_VERSION); | ||
79 | } catch(Exception $e) { | ||
80 | header('Content-Type: text/plain; charset=utf-8'); | ||
81 | echo $e->getMessage(); | ||
82 | exit; | ||
83 | } | ||
84 | |||
76 | include "inc/rain.tpl.class.php"; //include Rain TPL | 85 | include "inc/rain.tpl.class.php"; //include Rain TPL |
77 | raintpl::$tpl_dir = $GLOBALS['config']['RAINTPL_TPL']; // template directory | 86 | raintpl::$tpl_dir = $GLOBALS['config']['RAINTPL_TPL']; // template directory |
78 | raintpl::$cache_dir = $GLOBALS['config']['RAINTPL_TMP']; // cache directory | 87 | raintpl::$cache_dir = $GLOBALS['config']['RAINTPL_TMP']; // cache directory |
@@ -164,21 +173,7 @@ function setup_login_state() { | |||
164 | 173 | ||
165 | return $userIsLoggedIn; | 174 | return $userIsLoggedIn; |
166 | } | 175 | } |
167 | //================================================================================================== | ||
168 | $userIsLoggedIn = setup_login_state(); | 176 | $userIsLoggedIn = setup_login_state(); |
169 | //================================================================================================== | ||
170 | //================================================================================================== | ||
171 | |||
172 | // Check PHP version | ||
173 | function checkphpversion() | ||
174 | { | ||
175 | if (version_compare(PHP_VERSION, '5.1.0') < 0) | ||
176 | { | ||
177 | header('Content-Type: text/plain; charset=utf-8'); | ||
178 | echo 'Your PHP version is obsolete! Shaarli requires at least php 5.1.0, and thus cannot run. Sorry. Your PHP version has known security vulnerabilities and should be updated as soon as possible.'; | ||
179 | exit; | ||
180 | } | ||
181 | } | ||
182 | 177 | ||
183 | // Checks if an update is available for Shaarli. | 178 | // Checks if an update is available for Shaarli. |
184 | // (at most once a day, and only for registered user.) | 179 | // (at most once a day, and only for registered user.) |
@@ -982,7 +977,7 @@ function showDaily() | |||
982 | $linksToDisplay = $LINKSDB->filterDay($day); | 977 | $linksToDisplay = $LINKSDB->filterDay($day); |
983 | } catch (Exception $exc) { | 978 | } catch (Exception $exc) { |
984 | error_log($exc); | 979 | error_log($exc); |
985 | $linksToDisplay = []; | 980 | $linksToDisplay = array(); |
986 | } | 981 | } |
987 | 982 | ||
988 | // We pre-format some fields for proper output. | 983 | // We pre-format some fields for proper output. |
@@ -1288,7 +1283,7 @@ function renderPage() | |||
1288 | if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away! | 1283 | if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away! |
1289 | $tz = 'UTC'; | 1284 | $tz = 'UTC'; |
1290 | if (!empty($_POST['continent']) && !empty($_POST['city'])) | 1285 | if (!empty($_POST['continent']) && !empty($_POST['city'])) |
1291 | if (isTZvalid($_POST['continent'],$_POST['city'])) | 1286 | if (isTimeZoneValid($_POST['continent'],$_POST['city'])) |
1292 | $tz = $_POST['continent'].'/'.$_POST['city']; | 1287 | $tz = $_POST['continent'].'/'.$_POST['city']; |
1293 | $GLOBALS['timezone'] = $tz; | 1288 | $GLOBALS['timezone'] = $tz; |
1294 | $GLOBALS['title']=$_POST['title']; | 1289 | $GLOBALS['title']=$_POST['title']; |
@@ -1322,8 +1317,8 @@ function renderPage() | |||
1322 | $PAGE->assign('token',getToken()); | 1317 | $PAGE->assign('token',getToken()); |
1323 | $PAGE->assign('title', empty($GLOBALS['title']) ? '' : $GLOBALS['title'] ); | 1318 | $PAGE->assign('title', empty($GLOBALS['title']) ? '' : $GLOBALS['title'] ); |
1324 | $PAGE->assign('redirector', empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector'] ); | 1319 | $PAGE->assign('redirector', empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector'] ); |
1325 | list($timezone_form,$timezone_js) = templateTZform($GLOBALS['timezone']); | 1320 | list($timezone_form, $timezone_js) = generateTimeZoneForm($GLOBALS['timezone']); |
1326 | $PAGE->assign('timezone_form',$timezone_form); // FIXME: Put entire tz form generation in template? | 1321 | $PAGE->assign('timezone_form', $timezone_form); |
1327 | $PAGE->assign('timezone_js',$timezone_js); | 1322 | $PAGE->assign('timezone_js',$timezone_js); |
1328 | $PAGE->renderPage('configure'); | 1323 | $PAGE->renderPage('configure'); |
1329 | exit; | 1324 | exit; |
@@ -2059,9 +2054,11 @@ function install() | |||
2059 | if (!empty($_POST['setlogin']) && !empty($_POST['setpassword'])) | 2054 | if (!empty($_POST['setlogin']) && !empty($_POST['setpassword'])) |
2060 | { | 2055 | { |
2061 | $tz = 'UTC'; | 2056 | $tz = 'UTC'; |
2062 | if (!empty($_POST['continent']) && !empty($_POST['city'])) | 2057 | if (!empty($_POST['continent']) && !empty($_POST['city'])) { |
2063 | if (isTZvalid($_POST['continent'],$_POST['city'])) | 2058 | if (isTimeZoneValid($_POST['continent'], $_POST['city'])) { |
2064 | $tz = $_POST['continent'].'/'.$_POST['city']; | 2059 | $tz = $_POST['continent'].'/'.$_POST['city']; |
2060 | } | ||
2061 | } | ||
2065 | $GLOBALS['timezone'] = $tz; | 2062 | $GLOBALS['timezone'] = $tz; |
2066 | // Everything is ok, let's create config file. | 2063 | // Everything is ok, let's create config file. |
2067 | $GLOBALS['login'] = $_POST['setlogin']; | 2064 | $GLOBALS['login'] = $_POST['setlogin']; |
@@ -2087,8 +2084,11 @@ function install() | |||
2087 | } | 2084 | } |
2088 | 2085 | ||
2089 | // Display config form: | 2086 | // Display config form: |
2090 | list($timezone_form,$timezone_js) = templateTZform(); | 2087 | list($timezone_form, $timezone_js) = generateTimeZoneForm(); |
2091 | $timezone_html=''; if ($timezone_form!='') $timezone_html='<tr><td><b>Timezone:</b></td><td>'.$timezone_form.'</td></tr>'; | 2088 | $timezone_html = ''; |
2089 | if ($timezone_form != '') { | ||
2090 | $timezone_html = '<tr><td><b>Timezone:</b></td><td>'.$timezone_form.'</td></tr>'; | ||
2091 | } | ||
2092 | 2092 | ||
2093 | $PAGE = new pageBuilder; | 2093 | $PAGE = new pageBuilder; |
2094 | $PAGE->assign('timezone_html',$timezone_html); | 2094 | $PAGE->assign('timezone_html',$timezone_html); |
@@ -2097,67 +2097,6 @@ function install() | |||
2097 | exit; | 2097 | exit; |
2098 | } | 2098 | } |
2099 | 2099 | ||
2100 | // Generates the timezone selection form and JavaScript. | ||
2101 | // Input: (optional) current timezone (can be 'UTC/UTC'). It will be pre-selected. | ||
2102 | // Output: array(html,js) | ||
2103 | // Example: list($htmlform,$js) = templateTZform('Europe/Paris'); // Europe/Paris pre-selected. | ||
2104 | // Returns array('','') if server does not support timezones list. (e.g. PHP 5.1 on free.fr) | ||
2105 | function templateTZform($ptz=false) | ||
2106 | { | ||
2107 | if (function_exists('timezone_identifiers_list')) // because of old PHP version (5.1) which can be found on free.fr | ||
2108 | { | ||
2109 | // Try to split the provided timezone. | ||
2110 | if ($ptz==false) { $l=timezone_identifiers_list(); $ptz=$l[0]; } | ||
2111 | $spos=strpos($ptz,'/'); $pcontinent=substr($ptz,0,$spos); $pcity=substr($ptz,$spos+1); | ||
2112 | |||
2113 | // Display config form: | ||
2114 | $timezone_form = ''; | ||
2115 | $timezone_js = ''; | ||
2116 | // The list is in the form "Europe/Paris", "America/Argentina/Buenos_Aires"... | ||
2117 | // We split the list in continents/cities. | ||
2118 | $continents = array(); | ||
2119 | $cities = array(); | ||
2120 | foreach(timezone_identifiers_list() as $tz) | ||
2121 | { | ||
2122 | if ($tz=='UTC') $tz='UTC/UTC'; | ||
2123 | $spos = strpos($tz,'/'); | ||
2124 | if ($spos!==false) | ||
2125 | { | ||
2126 | $continent=substr($tz,0,$spos); $city=substr($tz,$spos+1); | ||
2127 | $continents[$continent]=1; | ||
2128 | if (!isset($cities[$continent])) $cities[$continent]=''; | ||
2129 | $cities[$continent].='<option value="'.$city.'"'.($pcity==$city?' selected':'').'>'.$city.'</option>'; | ||
2130 | } | ||
2131 | } | ||
2132 | $continents_html = ''; | ||
2133 | $continents = array_keys($continents); | ||
2134 | foreach($continents as $continent) | ||
2135 | $continents_html.='<option value="'.$continent.'"'.($pcontinent==$continent?' selected':'').'>'.$continent.'</option>'; | ||
2136 | $cities_html = $cities[$pcontinent]; | ||
2137 | $timezone_form = "Continent: <select name=\"continent\" id=\"continent\" onChange=\"onChangecontinent();\">${continents_html}</select>"; | ||
2138 | $timezone_form .= " City: <select name=\"city\" id=\"city\">${cities[$pcontinent]}</select><br />"; | ||
2139 | $timezone_js = "<script>"; | ||
2140 | $timezone_js .= "function onChangecontinent(){document.getElementById(\"city\").innerHTML = citiescontinent[document.getElementById(\"continent\").value];}"; | ||
2141 | $timezone_js .= "var citiescontinent = ".json_encode($cities).";" ; | ||
2142 | $timezone_js .= "</script>" ; | ||
2143 | return array($timezone_form,$timezone_js); | ||
2144 | } | ||
2145 | return array('',''); | ||
2146 | } | ||
2147 | |||
2148 | // Tells if a timezone is valid or not. | ||
2149 | // If not valid, returns false. | ||
2150 | // If system does not support timezone list, returns false. | ||
2151 | function isTZvalid($continent,$city) | ||
2152 | { | ||
2153 | $tz = $continent.'/'.$city; | ||
2154 | if (function_exists('timezone_identifiers_list')) // because of old PHP version (5.1) which can be found on free.fr | ||
2155 | { | ||
2156 | if (in_array($tz, timezone_identifiers_list())) // it's a valid timezone? | ||
2157 | return true; | ||
2158 | } | ||
2159 | return false; | ||
2160 | } | ||
2161 | if (!function_exists('json_encode')) { | 2100 | if (!function_exists('json_encode')) { |
2162 | function json_encode($data) { | 2101 | function json_encode($data) { |
2163 | switch ($type = gettype($data)) { | 2102 | switch ($type = gettype($data)) { |
diff --git a/shaarli_version.php b/shaarli_version.php index d2254870..a2045a7b 100644 --- a/shaarli_version.php +++ b/shaarli_version.php | |||
@@ -1 +1 @@ | |||
<?php /* 0.0.45beta */ ?> | <?php /* 0.5.0 */ ?> | ||
diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php index 4279c57e..a239d8b7 100755 --- a/tests/ConfigTest.php +++ b/tests/ConfigTest.php | |||
@@ -18,7 +18,7 @@ class ConfigTest extends PHPUnit_Framework_TestCase | |||
18 | */ | 18 | */ |
19 | public function setUp() | 19 | public function setUp() |
20 | { | 20 | { |
21 | self::$_configFields = [ | 21 | self::$_configFields = array( |
22 | 'login' => 'login', | 22 | 'login' => 'login', |
23 | 'hash' => 'hash', | 23 | 'hash' => 'hash', |
24 | 'salt' => 'salt', | 24 | 'salt' => 'salt', |
@@ -28,13 +28,13 @@ class ConfigTest extends PHPUnit_Framework_TestCase | |||
28 | 'redirector' => '', | 28 | 'redirector' => '', |
29 | 'disablesessionprotection' => false, | 29 | 'disablesessionprotection' => false, |
30 | 'privateLinkByDefault' => false, | 30 | 'privateLinkByDefault' => false, |
31 | 'config' => [ | 31 | 'config' => array( |
32 | 'CONFIG_FILE' => 'tests/config.php', | 32 | 'CONFIG_FILE' => 'tests/config.php', |
33 | 'DATADIR' => 'tests', | 33 | 'DATADIR' => 'tests', |
34 | 'config1' => 'config1data', | 34 | 'config1' => 'config1data', |
35 | 'config2' => 'config2data', | 35 | 'config2' => 'config2data', |
36 | ] | 36 | ) |
37 | ]; | 37 | ); |
38 | } | 38 | } |
39 | 39 | ||
40 | /** | 40 | /** |
@@ -174,4 +174,4 @@ class ConfigTest extends PHPUnit_Framework_TestCase | |||
174 | include self::$_configFields['config']['CONFIG_FILE']; | 174 | include self::$_configFields['config']['CONFIG_FILE']; |
175 | $this->assertEquals(self::$_configFields['login'], $GLOBALS['login']); | 175 | $this->assertEquals(self::$_configFields['login'], $GLOBALS['login']); |
176 | } | 176 | } |
177 | } \ No newline at end of file | 177 | } |
diff --git a/tests/LinkDBTest.php b/tests/LinkDBTest.php index d34ea4f5..504c8190 100644 --- a/tests/LinkDBTest.php +++ b/tests/LinkDBTest.php | |||
@@ -228,12 +228,12 @@ class LinkDBTest extends PHPUnit_Framework_TestCase | |||
228 | public function testDays() | 228 | public function testDays() |
229 | { | 229 | { |
230 | $this->assertEquals( | 230 | $this->assertEquals( |
231 | ['20121206', '20130614', '20150310'], | 231 | array('20121206', '20130614', '20150310'), |
232 | self::$publicLinkDB->days() | 232 | self::$publicLinkDB->days() |
233 | ); | 233 | ); |
234 | 234 | ||
235 | $this->assertEquals( | 235 | $this->assertEquals( |
236 | ['20121206', '20130614', '20141125', '20150310'], | 236 | array('20121206', '20130614', '20141125', '20150310'), |
237 | self::$privateLinkDB->days() | 237 | self::$privateLinkDB->days() |
238 | ); | 238 | ); |
239 | } | 239 | } |
@@ -269,7 +269,7 @@ class LinkDBTest extends PHPUnit_Framework_TestCase | |||
269 | public function testAllTags() | 269 | public function testAllTags() |
270 | { | 270 | { |
271 | $this->assertEquals( | 271 | $this->assertEquals( |
272 | [ | 272 | array( |
273 | 'web' => 3, | 273 | 'web' => 3, |
274 | 'cartoon' => 2, | 274 | 'cartoon' => 2, |
275 | 'gnu' => 2, | 275 | 'gnu' => 2, |
@@ -279,12 +279,12 @@ class LinkDBTest extends PHPUnit_Framework_TestCase | |||
279 | 'software' => 1, | 279 | 'software' => 1, |
280 | 'stallman' => 1, | 280 | 'stallman' => 1, |
281 | 'free' => 1 | 281 | 'free' => 1 |
282 | ], | 282 | ), |
283 | self::$publicLinkDB->allTags() | 283 | self::$publicLinkDB->allTags() |
284 | ); | 284 | ); |
285 | 285 | ||
286 | $this->assertEquals( | 286 | $this->assertEquals( |
287 | [ | 287 | array( |
288 | 'web' => 4, | 288 | 'web' => 4, |
289 | 'cartoon' => 3, | 289 | 'cartoon' => 3, |
290 | 'gnu' => 2, | 290 | 'gnu' => 2, |
@@ -298,7 +298,7 @@ class LinkDBTest extends PHPUnit_Framework_TestCase | |||
298 | 'w3c' => 1, | 298 | 'w3c' => 1, |
299 | 'css' => 1, | 299 | 'css' => 1, |
300 | 'Mercurial' => 1 | 300 | 'Mercurial' => 1 |
301 | ], | 301 | ), |
302 | self::$privateLinkDB->allTags() | 302 | self::$privateLinkDB->allTags() |
303 | ); | 303 | ); |
304 | } | 304 | } |
diff --git a/tests/TimeZoneTest.php b/tests/TimeZoneTest.php new file mode 100644 index 00000000..f3de3913 --- /dev/null +++ b/tests/TimeZoneTest.php | |||
@@ -0,0 +1,83 @@ | |||
1 | <?php | ||
2 | /** | ||
3 | * TimeZone's tests | ||
4 | */ | ||
5 | |||
6 | require_once 'application/TimeZone.php'; | ||
7 | |||
8 | /** | ||
9 | * Unitary tests for timezone utilities | ||
10 | */ | ||
11 | class TimeZoneTest extends PHPUnit_Framework_TestCase | ||
12 | { | ||
13 | /** | ||
14 | * Generate a timezone selection form | ||
15 | */ | ||
16 | public function testGenerateTimeZoneForm() | ||
17 | { | ||
18 | $generated = generateTimeZoneForm(); | ||
19 | |||
20 | // HTML form | ||
21 | $this->assertStringStartsWith('Continent:<select', $generated[0]); | ||
22 | $this->assertContains('selected="selected"', $generated[0]); | ||
23 | $this->assertStringEndsWith('</select><br />', $generated[0]); | ||
24 | |||
25 | // Javascript handler | ||
26 | $this->assertStringStartsWith('<script>', $generated[1]); | ||
27 | $this->assertContains( | ||
28 | '<option value=\"Bermuda\">Bermuda<\/option>', | ||
29 | $generated[1] | ||
30 | ); | ||
31 | $this->assertStringEndsWith('</script>', $generated[1]); | ||
32 | } | ||
33 | |||
34 | /** | ||
35 | * Generate a timezone selection form, with a preselected timezone | ||
36 | */ | ||
37 | public function testGenerateTimeZoneFormPreselected() | ||
38 | { | ||
39 | $generated = generateTimeZoneForm('Antarctica/Syowa'); | ||
40 | |||
41 | // HTML form | ||
42 | $this->assertStringStartsWith('Continent:<select', $generated[0]); | ||
43 | $this->assertContains( | ||
44 | 'value="Antarctica" selected="selected"', | ||
45 | $generated[0] | ||
46 | ); | ||
47 | $this->assertContains( | ||
48 | 'value="Syowa" selected="selected"', | ||
49 | $generated[0] | ||
50 | ); | ||
51 | $this->assertStringEndsWith('</select><br />', $generated[0]); | ||
52 | |||
53 | |||
54 | // Javascript handler | ||
55 | $this->assertStringStartsWith('<script>', $generated[1]); | ||
56 | $this->assertContains( | ||
57 | '<option value=\"Bermuda\">Bermuda<\/option>', | ||
58 | $generated[1] | ||
59 | ); | ||
60 | $this->assertStringEndsWith('</script>', $generated[1]); | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * Check valid timezones | ||
65 | */ | ||
66 | public function testValidTimeZone() | ||
67 | { | ||
68 | $this->assertTrue(isTimeZoneValid('America', 'Argentina/Ushuaia')); | ||
69 | $this->assertTrue(isTimeZoneValid('Europe', 'Oslo')); | ||
70 | $this->assertTrue(isTimeZoneValid('UTC', 'UTC')); | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * Check invalid timezones | ||
75 | */ | ||
76 | public function testInvalidTimeZone() | ||
77 | { | ||
78 | $this->assertFalse(isTimeZoneValid('CEST', 'CEST')); | ||
79 | $this->assertFalse(isTimeZoneValid('Europe', 'Atlantis')); | ||
80 | $this->assertFalse(isTimeZoneValid('Middle_Earth', 'Moria')); | ||
81 | } | ||
82 | } | ||
83 | ?> | ||
diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php index 8355c7f8..28e15f5a 100644 --- a/tests/UtilsTest.php +++ b/tests/UtilsTest.php | |||
@@ -109,7 +109,7 @@ class UtilsTest extends PHPUnit_Framework_TestCase | |||
109 | */ | 109 | */ |
110 | public function testGenerateLocationLoop() { | 110 | public function testGenerateLocationLoop() { |
111 | $ref = 'http://localhost/?test'; | 111 | $ref = 'http://localhost/?test'; |
112 | $this->assertEquals('?', generateLocation($ref, 'localhost', ['test'])); | 112 | $this->assertEquals('?', generateLocation($ref, 'localhost', array('test'))); |
113 | } | 113 | } |
114 | 114 | ||
115 | /** | 115 | /** |
@@ -119,4 +119,36 @@ class UtilsTest extends PHPUnit_Framework_TestCase | |||
119 | $ref = 'http://somewebsite.com/?test'; | 119 | $ref = 'http://somewebsite.com/?test'; |
120 | $this->assertEquals('?', generateLocation($ref, 'localhost')); | 120 | $this->assertEquals('?', generateLocation($ref, 'localhost')); |
121 | } | 121 | } |
122 | |||
123 | /** | ||
124 | * Check supported PHP versions | ||
125 | */ | ||
126 | public function testCheckSupportedPHPVersion() | ||
127 | { | ||
128 | $minVersion = '5.3'; | ||
129 | checkPHPVersion($minVersion, '5.4.32'); | ||
130 | checkPHPVersion($minVersion, '5.5'); | ||
131 | checkPHPVersion($minVersion, '5.6.10'); | ||
132 | } | ||
133 | |||
134 | /** | ||
135 | * Check a unsupported PHP version | ||
136 | * @expectedException Exception | ||
137 | * @expectedExceptionMessageRegExp /Your PHP version is obsolete/ | ||
138 | */ | ||
139 | public function testCheckSupportedPHPVersion51() | ||
140 | { | ||
141 | checkPHPVersion('5.3', '5.1.0'); | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * Check another unsupported PHP version | ||
146 | * @expectedException Exception | ||
147 | * @expectedExceptionMessageRegExp /Your PHP version is obsolete/ | ||
148 | */ | ||
149 | public function testCheckSupportedPHPVersion52() | ||
150 | { | ||
151 | checkPHPVersion('5.3', '5.2'); | ||
152 | } | ||
122 | } | 153 | } |
154 | ?> | ||
diff --git a/tpl/picwall.html b/tpl/picwall.html index 9a2a4715..f59685cf 100644 --- a/tpl/picwall.html +++ b/tpl/picwall.html | |||
@@ -17,7 +17,9 @@ | |||
17 | {include="page.footer"} | 17 | {include="page.footer"} |
18 | 18 | ||
19 | <script> | 19 | <script> |
20 | var bLazy = new Blazy(); | 20 | window.onload = function() { |
21 | var bLazy = new Blazy(); | ||
22 | } | ||
21 | </script> | 23 | </script> |
22 | </body> | 24 | </body> |
23 | </html> \ No newline at end of file | 25 | </html> |