* PHP 7.2: fix several PHP Fatal errors and warnings stalling installation and usage

This commit is contained in:
Ralf Becker 2018-04-09 16:02:00 +02:00
parent 4a3773ddcd
commit 0d984589ff
12 changed files with 91 additions and 68 deletions

View File

@ -330,7 +330,7 @@ class Customfields extends Transformer
$widget->attrs['multiple'] = $field['rows'] > 1;
// fall through
case 'radio':
if (count($field['values']) == 1 && isset($field['values']['@']))
if (!empty($field['values']) && count($field['values']) == 1 && isset($field['values']['@']))
{
$field['values'] = Api\Storage\Customfields::get_options_from_file($field['values']['@']);
}

View File

@ -73,12 +73,6 @@ class Session
*/
const EGW_SESSION_NAME = 'sessionid';
/**
* Used mcrypt algorithm and mode
*/
const MCRYPT_ALGO = MCRYPT_TRIPLEDES;
const MCRYPT_MODE = MCRYPT_MODE_ECB;
/**
* current user login (account_lid@domain)
*
@ -266,8 +260,10 @@ class Session
*/
function __wakeup()
{
ini_set('session.gc_maxlifetime', $GLOBALS['egw_info']['server']['sessions_timeout']);
if (!empty($GLOBALS['egw_info']['server']['sessions_timeout']) && session_status() === PHP_SESSION_NONE)
{
ini_set('session.gc_maxlifetime', $GLOBALS['egw_info']['server']['sessions_timeout']);
}
$this->action = null;
}
@ -399,13 +395,13 @@ class Session
/**
* Check if session encryption is configured, possible and initialise it
*
* If mcrypt extension is not available (eg. in PHP 7.2+ no longer contains it) fail gracefully.
*
* @param string $kp3 mcrypt key transported via cookie or get parameter like the session id,
* unlike the session id it's not know on the server, so only the client-request can decrypt the session!
* @param string $algo =self::MCRYPT_ALGO
* @param string $mode =self::MCRYPT_MODE
* @return boolean true if encryption is used, false otherwise
*/
static private function init_crypt($kp3,$algo=self::MCRYPT_ALGO,$mode=self::MCRYPT_MODE)
static private function init_crypt($kp3)
{
if(!$GLOBALS['egw_info']['server']['mcrypt_enabled'])
{
@ -422,9 +418,9 @@ class Session
error_log(__METHOD__."() required PHP extension mcrypt not loaded and can not be loaded, sessions get NOT encrypted!");
return false;
}
if (!(self::$mcrypt = mcrypt_module_open($algo, '', $mode, '')))
if (!(self::$mcrypt = mcrypt_module_open(MCRYPT_TRIPLEDES, '', MCRYPT_MODE_ECB, '')))
{
error_log(__METHOD__."() could not mcrypt_module_open(algo='$algo','',mode='$mode',''), sessions get NOT encrypted!");
error_log(__METHOD__."() could not mcrypt_module_open(MCRYPT_TRIPLEDES,'',MCRYPT_MODE_ECB,''), sessions get NOT encrypted!");
return false;
}
$iv_size = mcrypt_enc_get_iv_size(self::$mcrypt);
@ -927,10 +923,19 @@ class Session
return false;
}
session_name(self::EGW_SESSION_NAME);
session_id($this->sessionid);
self::cache_control();
session_start();
switch (session_status())
{
case PHP_SESSION_DISABLED:
throw new ErrorException('EGroupware requires the PHP session extension!');
case PHP_SESSION_NONE:
session_name(self::EGW_SESSION_NAME);
session_id($this->sessionid);
self::cache_control();
session_start();
break;
case PHP_SESSION_ACTIVE:
// session already started eg. by managementserver_client
}
// check if we have a eGroupware session --> return false if not (but dont destroy it!)
if (is_null($_SESSION) || !isset($_SESSION[self::EGW_SESSION_VAR]))
@ -1586,16 +1591,22 @@ class Session
*/
public static function init_handler()
{
ini_set('session.use_cookies',0); // disable the automatic use of cookies, as it uses the path / by default
session_name(self::EGW_SESSION_NAME);
if (($sessionid = self::get_sessionid()))
switch(session_status())
{
session_id($sessionid);
self::cache_control();
$ok = session_start();
self::decrypt();
if (self::ERROR_LOG_DEBUG) error_log(__METHOD__."() sessionid=$sessionid, _SESSION[".self::EGW_SESSION_VAR.']='.array2string($_SESSION[self::EGW_SESSION_VAR]));
return $ok;
case PHP_SESSION_DISABLED:
throw new \ErrorException('EGroupware requires PHP session extension!');
case PHP_SESSION_NONE:
ini_set('session.use_cookies',0); // disable the automatic use of cookies, as it uses the path / by default
session_name(self::EGW_SESSION_NAME);
if (($sessionid = self::get_sessionid()))
{
session_id($sessionid);
self::cache_control();
$ok = session_start();
self::decrypt();
if (self::ERROR_LOG_DEBUG) error_log(__METHOD__."() sessionid=$sessionid, _SESSION[".self::EGW_SESSION_VAR.']='.array2string($_SESSION[self::EGW_SESSION_VAR]));
return $ok;
}
}
if (self::ERROR_LOG_DEBUG) error_log(__METHOD__."() no active session!");

View File

@ -990,7 +990,7 @@ abstract class Merge
// Tags we can replace with the target document's version
$replace_tags = array();
// only keep tags, if we have xsl extension available
if (class_exists(XSLTProcessor) && class_exists(DOMDocument) && $this->parse_html_styles)
if (class_exists('XSLTProcessor') && class_exists('DOMDocument') && $this->parse_html_styles)
{
switch($mimetype.$mso_application_progid)
{

View File

@ -180,7 +180,7 @@ class StreamWrapper extends LinksParent
);
}
// if entry directory does not exist --> return fake directory
elseif (!($ret = parent::url_stat($url,$flags,$eacl_check)) && $eacl_check)
elseif (!($ret = parent::url_stat($url,$flags)) && $eacl_check)
{
list(,/*$apps*/,/*$app*/,$id,$rel_path) = explode('/', Vfs::parse_url($url, PHP_URL_PATH), 5);
if ($id && !isset($rel_path))

View File

@ -157,6 +157,11 @@ class StreamWrapper extends Api\Db\Pdo implements Vfs\StreamWrapperIface
*/
static public $extra_columns = ',fs_link';
/**
* @var array $overwrite_new =null if set create new file with values overwriten by the given ones
*/
protected $overwrite_new;
/**
* Clears our stat-cache
*
@ -184,10 +189,9 @@ class StreamWrapper extends Api\Db\Pdo implements Vfs\StreamWrapperIface
* - STREAM_REPORT_ERRORS If this flag is set, you are responsible for raising errors using trigger_error() during opening of the stream.
* If this flag is not set, you should not raise any errors.
* @param string &$opened_path full path of the file/resource, if the open was successfull and STREAM_USE_PATH was set
* @param array $overwrite_new =null if set create new file with values overwriten by the given ones
* @return boolean true if the ressource was opened successful, otherwise false
*/
function stream_open ( $url, $mode, $options, &$opened_path, array $overwrite_new=null )
function stream_open ($url, $mode, $options, &$opened_path)
{
if (self::LOG_LEVEL > 1) error_log(__METHOD__."($url,$mode,$options)");
@ -201,7 +205,7 @@ class StreamWrapper extends Api\Db\Pdo implements Vfs\StreamWrapperIface
parse_str(parse_url($url, PHP_URL_QUERY), $this->dir_url_params);
if (!is_null($overwrite_new) || !($stat = $this->url_stat($path,STREAM_URL_STAT_QUIET)) || $mode[0] == 'x') // file not found or file should NOT exist
if (!is_null($this->overwrite_new) || !($stat = $this->url_stat($path,STREAM_URL_STAT_QUIET)) || $mode[0] == 'x') // file not found or file should NOT exist
{
if (!$dir || $mode[0] == 'r' || // does $mode require the file to exist (r,r+)
$mode[0] == 'x' && $stat || // or file should not exist, but does
@ -239,7 +243,7 @@ class StreamWrapper extends Api\Db\Pdo implements Vfs\StreamWrapperIface
'fs_size' => 0,
'fs_active' => self::_pdo_boolean(true),
);
if ($overwrite_new) $values = array_merge($values,$overwrite_new);
if ($this->overwrite_new) $values = array_merge($values, $this->overwrite_new);
if (!$stmt->execute($values) || !($this->opened_fs_id = self::$pdo->lastInsertId('egw_sqlfs_fs_id_seq')))
{
$this->opened_stream = $this->opened_path = $this->opened_mode = null;
@ -543,18 +547,15 @@ class StreamWrapper extends Api\Db\Pdo implements Vfs\StreamWrapperIface
* @param string $url
* @return boolean TRUE on success or FALSE on failure
*/
function unlink ( $url, $parent_stat=null )
function unlink ( $url )
{
if (self::LOG_LEVEL > 1) error_log(__METHOD__."($url)");
$path = Vfs::parse_url($url,PHP_URL_PATH);
// need to get parent stat from Sqlfs, not Vfs
if (!isset($parent_stat))
{
$parent_stat = !($dir = Vfs::dirname($path)) ? false :
$this->url_stat($dir, STREAM_URL_STAT_LINK);
}
$parent_stat = !($dir = Vfs::dirname($path)) ? false :
$this->url_stat($dir, STREAM_URL_STAT_LINK);
if (!$parent_stat || !($stat = $this->url_stat($path,STREAM_URL_STAT_LINK)) ||
!$dir || !Vfs::check_access($dir, Vfs::WRITABLE, $parent_stat))
@ -1123,10 +1124,9 @@ class StreamWrapper extends Api\Db\Pdo implements Vfs\StreamWrapperIface
* - STREAM_URL_STAT_QUIET If this flag is set, your wrapper should not raise any errors. If this flag is not set,
* you are responsible for reporting errors using the trigger_error() function during stating of the path.
* stat triggers it's own warning anyway, so it makes no sense to trigger one by our stream-wrapper!
* @param boolean $eacl_access =null allows extending classes to pass the value of their check_extended_acl() method (no lsb!)
* @return array
*/
function url_stat ( $url, $flags, $eacl_access=null )
function url_stat ( $url, $flags )
{
static $max_subquery_depth=null;
if (is_null($max_subquery_depth))
@ -1134,7 +1134,7 @@ class StreamWrapper extends Api\Db\Pdo implements Vfs\StreamWrapperIface
$max_subquery_depth = $GLOBALS['egw_info']['server']['max_subquery_depth'];
if (!$max_subquery_depth) $max_subquery_depth = 7; // setting current default of 7, if nothing set
}
if (self::LOG_LEVEL > 1) error_log(__METHOD__."('$url',$flags,$eacl_access)");
if (self::LOG_LEVEL > 1) error_log(__METHOD__."('$url',$flags)");
$path = Vfs::parse_url($url,PHP_URL_PATH);
@ -1148,7 +1148,7 @@ class StreamWrapper extends Api\Db\Pdo implements Vfs\StreamWrapperIface
return false; // is invalid and gives sql error
}
// check if we already have the info from the last dir_open call, as the old vfs reads it anyway from the db
if (self::$stat_cache && isset(self::$stat_cache[$path]) && (is_null($eacl_access) || self::$stat_cache[$path] !== false))
if (self::$stat_cache && isset(self::$stat_cache[$path]) && self::$stat_cache[$path] !== false)
{
return self::$stat_cache[$path] ? self::_vfsinfo2stat(self::$stat_cache[$path]) : false;
}
@ -1162,11 +1162,9 @@ class StreamWrapper extends Api\Db\Pdo implements Vfs\StreamWrapperIface
' AND fs_name'.self::$case_sensitive_equal.'? AND fs_dir=';
$parts = explode('/',$path);
// if we have extendes acl access to the url, we dont need and can NOT include the sql for the readable check
if (is_null($eacl_access))
{
$eacl_access = self::check_extended_acl($path,Vfs::READABLE); // should be static::check_extended_acl, but no lsb!
}
// if we have extended acl access to the url, we dont need and can NOT include the sql for the readable check
// using $this->check_extended_acl instead of self::check_extended_acl to ensure we call Vfs\Links\StreamWraper::check_extended_stat()
$eacl_access = self::check_extended_acl($path,Vfs::READABLE); // should be static::check_extended_acl, but no lsb!
try {
foreach($parts as $n => $name)
@ -1211,7 +1209,7 @@ class StreamWrapper extends Api\Db\Pdo implements Vfs\StreamWrapperIface
$query = str_replace('fs_name'.self::$case_sensitive_equal.'?','fs_name'.self::$case_sensitive_equal.self::$pdo->quote($name),$base_query).'('.$query.')';
}
}
if (self::LOG_LEVEL > 2) $query = '/* '.__METHOD__."($url,$flags,$eacl_access)".' */ '.$query;
if (self::LOG_LEVEL > 2) $query = '/* '.__METHOD__."($url,$flags) eacl_access=$eacl_access".' */ '.$query;
//if (self::LOG_LEVEL > 2) $query = '/* '.__METHOD__.': '.__LINE__.' */ '.$query;
if (!($result = self::$pdo->query($query)) || !($info = $result->fetch(\PDO::FETCH_ASSOC)))
@ -1235,7 +1233,7 @@ class StreamWrapper extends Api\Db\Pdo implements Vfs\StreamWrapperIface
error_log(__METHOD__."() decremented max_subquery_depth to $max_subquery_depth");
Api\Config::save_value('max_subquery_depth', $max_subquery_depth, 'phpgwapi');
if (method_exists($GLOBALS['egw'],'invalidate_session_cache')) $GLOBALS['egw']->invalidate_session_cache();
return $this->url_stat($url, $flags, $eacl_access);
return $this->url_stat($url, $flags);
}
self::$stat_cache[$path] = $info;

View File

@ -582,8 +582,8 @@ class calendar_bo
}
}
if (!isset($params['users']) || !$params['users'] ||
count($params['users']) == 1 && isset($params['users'][0]) && !$params['users'][0]) // null or '' casted to an array
if (empty($params['users']) ||
is_array($params['users']) && count($params['users']) == 1 && empty($params['users'][0])) // null or '' casted to an array
{
// for a search use all account you have read grants from
$params['users'] = $params['query'] ? array_keys($this->grants) : $this->user;

View File

@ -127,7 +127,8 @@ class calendar_export_ical extends calendar_export_csv {
* return html for options.
*
*/
public function get_options_etpl() {
public function get_options_etpl($definition = null) {
unset($definition); // not used, but required by function signature
}
/**

View File

@ -574,7 +574,7 @@ class calendar_rrule implements Iterator
if($this->type != self::NONE)
{
$str = lang(self::$types[$this->type]);
$str_extra = array();
switch ($this->type)
{
@ -756,7 +756,7 @@ class calendar_rrule implements Iterator
self::rrule2tz($event, $time, $to_tz);
$time->setTimezone(self::$tz_cache[$to_tz]);
if ($event['recur_enddate'])
{
$enddate = is_a($event['recur_enddate'],'DateTime') ? clone $event['recur_enddate'] : new Api\DateTime($event['recur_enddate'],$timestamp_tz);
@ -863,7 +863,7 @@ class calendar_rrule implements Iterator
$enddate = new DateTime($date);
}
}
return new calendar_rrule($time,$type_id,$interval,$enddate,$weekdays,$exceptions);
}
/**
@ -897,7 +897,7 @@ class calendar_rrule implements Iterator
if (!is_array($event) ||
!isset($event['recur_type']) ||
$event['recur_type'] == self::NONE ||
empty($event['recur_data']) || $event['recur_data'] == ALLDAYS ||
empty($event['recur_data']) || $event['recur_data'] == self::ALLDAYS ||
empty($event['tzid']) || empty($to_tz) ||
$event['tzid'] == $to_tz) return;

View File

@ -571,7 +571,7 @@ class importexport_helper_functions {
foreach($definitions as $appname => $_types) {
$definitions[$appname] = array_intersect_key($definitions[$appname], array_flip($types));
}
return count($definitions[$appname]) > 0;
return !empty($definitions[$appname]);
}
// Api\Cache needs this public

View File

@ -470,13 +470,13 @@ class infolog_ui
if ($query['action_id'] && $query['csv_export'] !== 'children')
{
$parents = $query['action'] == 'sp' && $query['action_id'] ? (array)$query['action_id'] : array();
if (count($parents) == 1 && is_array($query['action_id']))
if (!empty($parents) && count($parents) == 1 && is_array($query['action_id']))
{
$query['action_id'] = array_shift($query['action_id']); // display single parent as app_header
}
}
$parent_first = count($parents) == 1;
$parent_first = !empty($parents) && count($parents) == 1;
$parent_index = 0;
// et2 nextmatch listens to total, and only displays that many rows, so add parent in or we'll lose the last row
if($parent_first || $query['action'] == 'sp' && is_array($query['action_id'])) $query['total']++;
@ -759,7 +759,7 @@ class infolog_ui
}
if (is_array($values) && !empty($values['nm']['multi_action']))
{
if (!count($values['nm']['selected']) && !$values['nm']['select_all'])
if (empty($values['nm']['selected']) && !$values['nm']['select_all'])
{
$msg = lang('You need to select some entries first');
}

View File

@ -226,6 +226,10 @@ $checks = array(
'func' => 'extension_check',
'warning' => lang('The tidy extension is need in merge-print to clean up html before inserting it in office documents.'),
),
'xsl' => array(
'func' => 'extension_check',
'warning' => lang('The xsl extension is need in merge-print for processing html and office documents.'),
),
'xmlreader' => array(
'func' => 'extension_check',
'error' => lang('The xmlreader extension is required by EGroupware in several applications.'),

View File

@ -249,15 +249,24 @@ class setup
// make sure we have session extension available, otherwise fail with exception that we need it
check_load_extension('session', true);
ini_set('session.use_cookie', true);
session_name(self::SESSIONID);
session_set_cookie_params(0, '/', self::cookiedomain(),
// if called via HTTPS, only send cookie for https and only allow cookie access via HTTP (true)
!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off', true);
switch(session_status())
{
case PHP_SESSION_DISABLED:
throw new \ErrorException('EGroupware requires PHP session extension!');
case PHP_SESSION_NONE:
ini_set('session.use_cookie', true);
session_name(self::SESSIONID);
session_set_cookie_params(0, '/', self::cookiedomain(),
// if called via HTTPS, only send cookie for https and only allow cookie access via HTTP (true)
!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off', true);
if (isset($_COOKIE[self::SESSIONID])) session_id($_COOKIE[self::SESSIONID]);
if (isset($_COOKIE[self::SESSIONID])) session_id($_COOKIE[self::SESSIONID]);
$ok = @session_start(); // suppress notice if session already started or warning in CLI
$ok = @session_start(); // suppress notice if session already started or warning in CLI
break;
case PHP_SESSION_ACTIVE:
$ok = true;
}
// need to decrypt session, in case session encryption is switched on in header.inc.php
Api\Session::decrypt();
//error_log(__METHOD__."() returning ".array2string($ok).' _SESSION='.array2string($_SESSION));