Skip to content

Commit

Permalink
PHP: ensure 5.3 compatibility
Browse files Browse the repository at this point in the history
Relates to shaarli#250

Modifications
 - add PHP 5.3 to Travis environments
 - rewrite array declarations: explicitely use array() instead of []
 - move checkPHPVersion to application/Utils.php
 - move timezone functions to application/TimeZone.php
 - improve test coverage
 - bump required version from 5.1.0 to 5.3.x

Signed-off-by: VirtualTam <virtualtam@flibidi.net>
  • Loading branch information
virtualtam committed Jul 11, 2015
1 parent 1b73f35 commit e3b48b3
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 100 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ php:
- 5.6
- 5.5
- 5.4
- 5.3
install:
- composer self-update
- composer install
Expand Down
6 changes: 3 additions & 3 deletions application/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
function writeConfig($config, $isLoggedIn)
{
// These fields are required in configuration.
$MANDATORY_FIELDS = [
$MANDATORY_FIELDS = array(
'login', 'hash', 'salt', 'timezone', 'title', 'titleLink',
'redirector', 'disablesessionprotection', 'privateLinkByDefault'
];
);

if (!isset($config['config']['CONFIG_FILE'])) {
throw new MissingFieldConfigException('CONFIG_FILE');
Expand Down Expand Up @@ -126,4 +126,4 @@ public function __construct()
{
$this->message = 'You are not authorized to alter config.';
}
}
}
91 changes: 91 additions & 0 deletions application/TimeZone.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php
/**
* Generates the timezone selection form and JavaScript.
*
* Note: 'UTC/UTC' is mapped to 'UTC'
*
* Example: preselect Europe/Paris
* list($htmlform, $js) = templateTZform('Europe/Paris');
*
* @param $preselected_timezone preselected timezone (can be 'UTC/UTC') (optional)
* @return array(html, js)
**/
function generateTimeZoneForm($preseleced_timezone=false)
{
// Try to split the provided timezone.
if ($preseleced_timezone == false) {
$l = timezone_identifiers_list();
$preseleced_timezone = $l[0];
}
$spos = strpos($preseleced_timezone, '/');
$pcontinent = substr($preseleced_timezone, 0, $spos);
$pcity = substr($preseleced_timezone, $spos+1);

// Display config form:
$timezone_form = '';
$timezone_js = '';

// The list is in the form "Europe/Paris", "America/Argentina/Buenos_Aires"...
// We split the list in continents/cities.
$continents = array();
$cities = array();

foreach (timezone_identifiers_list() as $tz) {
if ($tz == 'UTC') {
$tz = 'UTC/UTC';
}
$spos = strpos($tz, '/');
if ($spos !== false) {
$continent = substr($tz, 0, $spos);
$city = substr($tz, $spos+1);
$continents[$continent] = 1;

if (!isset($cities[$continent])) {
$cities[$continent] = '';
}
$cities[$continent].='<option value="'.$city.'"'.($pcity==$city?' selected':'').'>'.$city.'</option>';
}
}

$continents_html = '';
$continents = array_keys($continents);

// TODO: use a template to generate the HTML/Javascript form

foreach ($continents as $continent) {
$continents_html.='<option value="'.$continent.'"'.($pcontinent==$continent?' selected':'').'>'.$continent.'</option>';
}

$cities_html = $cities[$pcontinent];

$timezone_form = "Continent: <select name=\"continent\" id=\"continent\" onChange=\"onChangecontinent();\">${continents_html}</select>";
$timezone_form .= "&nbsp;&nbsp;&nbsp;&nbsp;City: <select name=\"city\" id=\"city\">${cities[$pcontinent]}</select><br />";
$timezone_js = "<script>";
$timezone_js .= "function onChangecontinent(){document.getElementById(\"city\").innerHTML = citiescontinent[document.getElementById(\"continent\").value];}";
$timezone_js .= "var citiescontinent = ".json_encode($cities).";";
$timezone_js .= "</script>";
return array($timezone_form, $timezone_js);
}

/**
* Tells if a continent/city pair form a valid timezone
*
* Note: 'UTC/UTC' is mapped to 'UTC'
*
* @param $continent the timezone continent
* @param $city the timezone city
* @return whether continent/city is a valid timezone
*/
function isTimeZoneValid($continent, $city)
{
if ($continent == 'UTC' && $city == 'UTC') {
return true;
}

$tz = $continent.'/'.$city;
if (in_array($tz, timezone_identifiers_list())) {
return true;
}
return false;
}
?>
21 changes: 20 additions & 1 deletion application/Utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ function endsWith($haystack, $needle, $case=true)
*/
function nl2br_escaped($html)
{
return str_replace('>','&gt;',str_replace('<','&lt;',nl2br($html)));
return str_replace('>', '&gt;', str_replace('<', '&lt;', nl2br($html)));
}

/**
Expand Down Expand Up @@ -84,4 +84,23 @@ function checkDateFormat($format, $string)
$date = DateTime::createFromFormat($format, $string);
return $date && $date->format($string) == $string;
}

/**
* Checks the PHP version to ensure Shaarli can run
*
* @param $minVersion minimum PHP required version
* @param $curVersion current PHP version (use PHP_VERSION)
* @throws Exception the PHP version is not supported
*/
function checkPHPVersion($minVersion, $curVersion)
{
if (version_compare($curVersion, $minVersion) < 0) {
throw new Exception(
'Your PHP version is obsolete!'
.' Shaarli requires at least PHP '.$minVersion.', and thus cannot run.'
.' Your PHP version has known security vulnerabilities and should be'
.' updated as soon as possible.'
);
}
}
?>
109 changes: 24 additions & 85 deletions index.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// The personal, minimalist, super-fast, no-database Delicious clone. By sebsauvage.net
// http://sebsauvage.net/wiki/doku.php?id=php:shaarli
// Licence: http://www.opensource.org/licenses/zlib-license.php
// Requires: PHP 5.1.x (but autocomplete fields will only work if you have PHP 5.2.x)
// Requires: PHP 5.3.x
// -----------------------------------------------------------------------------------------------
// NEVER TRUST IN PHP.INI
// Some hosts do not define a default timezone in php.ini,
Expand Down Expand Up @@ -59,7 +59,6 @@
ini_set('memory_limit', '128M'); // Try to set max upload file size and read (May not work on some hosts).
ini_set('post_max_size', '16M');
ini_set('upload_max_filesize', '16M');
checkphpversion();
error_reporting(E_ALL^E_WARNING); // See all error except warnings.
//error_reporting(-1); // See all errors (for debugging only)

Expand All @@ -70,9 +69,19 @@

// Shaarli library
require_once 'application/LinkDB.php';
require_once 'application/TimeZone.php';
require_once 'application/Utils.php';
require_once 'application/Config.php';

// Ensure the PHP version is supported
try {
checkPHPVersion('5.3', PHP_VERSION);
} catch(Exception $e) {
header('Content-Type: text/plain; charset=utf-8');
echo $e->getMessage();
exit;
}

include "inc/rain.tpl.class.php"; //include Rain TPL
raintpl::$tpl_dir = $GLOBALS['config']['RAINTPL_TPL']; // template directory
raintpl::$cache_dir = $GLOBALS['config']['RAINTPL_TMP']; // cache directory
Expand Down Expand Up @@ -164,21 +173,7 @@ function setup_login_state() {

return $userIsLoggedIn;
}
//==================================================================================================
$userIsLoggedIn = setup_login_state();
//==================================================================================================
//==================================================================================================

// Check PHP version
function checkphpversion()
{
if (version_compare(PHP_VERSION, '5.1.0') < 0)
{
header('Content-Type: text/plain; charset=utf-8');
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.';
exit;
}
}

// Checks if an update is available for Shaarli.
// (at most once a day, and only for registered user.)
Expand Down Expand Up @@ -964,7 +959,7 @@ function showDaily()
$linksToDisplay = $LINKSDB->filterDay($day);
} catch (Exception $exc) {
error_log($exc);
$linksToDisplay = [];
$linksToDisplay = array();
}

// We pre-format some fields for proper output.
Expand Down Expand Up @@ -1257,7 +1252,7 @@ function renderPage()
if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away!
$tz = 'UTC';
if (!empty($_POST['continent']) && !empty($_POST['city']))
if (isTZvalid($_POST['continent'],$_POST['city']))
if (isTimeZoneValid($_POST['continent'],$_POST['city']))
$tz = $_POST['continent'].'/'.$_POST['city'];
$GLOBALS['timezone'] = $tz;
$GLOBALS['title']=$_POST['title'];
Expand Down Expand Up @@ -1291,8 +1286,8 @@ function renderPage()
$PAGE->assign('token',getToken());
$PAGE->assign('title', empty($GLOBALS['title']) ? '' : $GLOBALS['title'] );
$PAGE->assign('redirector', empty($GLOBALS['redirector']) ? '' : $GLOBALS['redirector'] );
list($timezone_form,$timezone_js) = templateTZform($GLOBALS['timezone']);
$PAGE->assign('timezone_form',$timezone_form); // FIXME: Put entire tz form generation in template?
list($timezone_form, $timezone_js) = generateTimeZoneForm($GLOBALS['timezone']);
$PAGE->assign('timezone_form', $timezone_form);
$PAGE->assign('timezone_js',$timezone_js);
$PAGE->renderPage('configure');
exit;
Expand Down Expand Up @@ -2029,9 +2024,11 @@ function install()
if (!empty($_POST['setlogin']) && !empty($_POST['setpassword']))
{
$tz = 'UTC';
if (!empty($_POST['continent']) && !empty($_POST['city']))
if (isTZvalid($_POST['continent'],$_POST['city']))
if (!empty($_POST['continent']) && !empty($_POST['city'])) {
if (isTimeZoneValid($_POST['continent'], $_POST['city'])) {
$tz = $_POST['continent'].'/'.$_POST['city'];
}
}
$GLOBALS['timezone'] = $tz;
// Everything is ok, let's create config file.
$GLOBALS['login'] = $_POST['setlogin'];
Expand All @@ -2057,8 +2054,11 @@ function install()
}

// Display config form:
list($timezone_form,$timezone_js) = templateTZform();
$timezone_html=''; if ($timezone_form!='') $timezone_html='<tr><td><b>Timezone:</b></td><td>'.$timezone_form.'</td></tr>';
list($timezone_form, $timezone_js) = generateTimeZoneForm();
$timezone_html = '';
if ($timezone_form != '') {
$timezone_html = '<tr><td><b>Timezone:</b></td><td>'.$timezone_form.'</td></tr>';
}

$PAGE = new pageBuilder;
$PAGE->assign('timezone_html',$timezone_html);
Expand All @@ -2067,67 +2067,6 @@ function install()
exit;
}

// Generates the timezone selection form and JavaScript.
// Input: (optional) current timezone (can be 'UTC/UTC'). It will be pre-selected.
// Output: array(html,js)
// Example: list($htmlform,$js) = templateTZform('Europe/Paris'); // Europe/Paris pre-selected.
// Returns array('','') if server does not support timezones list. (e.g. PHP 5.1 on free.fr)
function templateTZform($ptz=false)
{
if (function_exists('timezone_identifiers_list')) // because of old PHP version (5.1) which can be found on free.fr
{
// Try to split the provided timezone.
if ($ptz==false) { $l=timezone_identifiers_list(); $ptz=$l[0]; }
$spos=strpos($ptz,'/'); $pcontinent=substr($ptz,0,$spos); $pcity=substr($ptz,$spos+1);

// Display config form:
$timezone_form = '';
$timezone_js = '';
// The list is in the form "Europe/Paris", "America/Argentina/Buenos_Aires"...
// We split the list in continents/cities.
$continents = array();
$cities = array();
foreach(timezone_identifiers_list() as $tz)
{
if ($tz=='UTC') $tz='UTC/UTC';
$spos = strpos($tz,'/');
if ($spos!==false)
{
$continent=substr($tz,0,$spos); $city=substr($tz,$spos+1);
$continents[$continent]=1;
if (!isset($cities[$continent])) $cities[$continent]='';
$cities[$continent].='<option value="'.$city.'"'.($pcity==$city?' selected':'').'>'.$city.'</option>';
}
}
$continents_html = '';
$continents = array_keys($continents);
foreach($continents as $continent)
$continents_html.='<option value="'.$continent.'"'.($pcontinent==$continent?' selected':'').'>'.$continent.'</option>';
$cities_html = $cities[$pcontinent];
$timezone_form = "Continent: <select name=\"continent\" id=\"continent\" onChange=\"onChangecontinent();\">${continents_html}</select>";
$timezone_form .= "&nbsp;&nbsp;&nbsp;&nbsp;City: <select name=\"city\" id=\"city\">${cities[$pcontinent]}</select><br />";
$timezone_js = "<script>";
$timezone_js .= "function onChangecontinent(){document.getElementById(\"city\").innerHTML = citiescontinent[document.getElementById(\"continent\").value];}";
$timezone_js .= "var citiescontinent = ".json_encode($cities).";" ;
$timezone_js .= "</script>" ;
return array($timezone_form,$timezone_js);
}
return array('','');
}

// Tells if a timezone is valid or not.
// If not valid, returns false.
// If system does not support timezone list, returns false.
function isTZvalid($continent,$city)
{
$tz = $continent.'/'.$city;
if (function_exists('timezone_identifiers_list')) // because of old PHP version (5.1) which can be found on free.fr
{
if (in_array($tz, timezone_identifiers_list())) // it's a valid timezone?
return true;
}
return false;
}
if (!function_exists('json_encode')) {
function json_encode($data) {
switch ($type = gettype($data)) {
Expand Down
10 changes: 5 additions & 5 deletions tests/ConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class ConfigTest extends PHPUnit_Framework_TestCase
*/
public function setUp()
{
self::$_configFields = [
self::$_configFields = array(
'login' => 'login',
'hash' => 'hash',
'salt' => 'salt',
Expand All @@ -28,13 +28,13 @@ public function setUp()
'redirector' => '',
'disablesessionprotection' => false,
'privateLinkByDefault' => false,
'config' => [
'config' => array(
'CONFIG_FILE' => 'tests/config.php',
'DATADIR' => 'tests',
'config1' => 'config1data',
'config2' => 'config2data',
]
];
)
);
}

/**
Expand Down Expand Up @@ -174,4 +174,4 @@ public function testMergeDeprecatedConfigNoFile()
include self::$_configFields['config']['CONFIG_FILE'];
$this->assertEquals(self::$_configFields['login'], $GLOBALS['login']);
}
}
}
Loading

0 comments on commit e3b48b3

Please sign in to comment.