Fixed Make XenForo requirements script results more accurate and robust for all server setups

bzcomputers

Well-known member
As it currently sits the XenForo requirements script (https://xenforo.com/purchase/requirements-zip) does not function check all required and recommended functions. It still currently relies on what php.ini reports through ini_get('disable_functions'); to determine if many functions are available. This is not very accurate as php functions can be disabled in numerous places on the server outside of php.ini, for example through server configuration files like .htaccess, web server settings (e.g., in Apache's httpd.conf or Nginx's nginx.conf), and possibly through additional server security software/hardware. The only way to accurately determine if a required or recommended function is disabled on the server would be to check each individual function with function_exists.

It currently appears these required and recommended functions are not actually function checked: ini_set, fsockopen, exec, escapeshellarg, proc_open, popen, and set_time_out.

Currently if any of those functions are disabled outside of php.ini, the current XenForo requirements script will not report them as being disabled. This could cause XenForo admins to be unaware their server setups are incompatible with all of XenForo's features and issues could be occurring, some of which could be hard to detect and diagnose.
 
As it currently sits the XenForo requirements script (https://xenforo.com/purchase/requirements-zip) does not function check all required and recommended functions. It still currently relies on what php.ini reports through ini_get('disable_functions'); to determine if many functions are available. This is not very accurate as php functions can be disabled in numerous places on the server outside of php.ini, for example through server configuration files like .htaccess, web server settings (e.g., in Apache's httpd.conf or Nginx's nginx.conf), and possibly through additional server security software/hardware. The only way to accurately determine if a required or recommended function is disabled on the server would be to check each individual function with function_exists.
You're right about set_time_out, but can you elaborate on how these functions might be disabled external to the PHP configuration? Apache mod_php changes should be reflected via the ini_get call, and nginx connects to PHP as a separate service entirely. And functions disabled via disable_functions still existed internally prior to PHP 8, so function_exists would return true even if they were disabled.
 
ini_get will only return what is included in php.ini

In my case the server running XenForo has additional security installed with a separate ssp.ini settings file that also includes disable_functions.

Originally the contents were:
Code:
display_errors = Off
expose_php = Off
enable_dl = Off
open_basedir =
disable_functions = show_source,system,shell_exec,passthru,exec,popen,proc_open,allow_url_fopen

Even though the XenForo recommended functions of exec, popen and proc_open were disabled in this file. Your current requirements script did not indicate this during its' check.

This is what your current xenforo_requirements.php script reported:

current.webp


After modifying xenforo_requirements.php script...

Removed lines 355-376:
PHP:
try
{
    $disabled = ini_get('disable_functions');
}
catch (Exception $e)
{
    $errors['ini_get'] = 'Your server has disabled functions that make it impossible to detect server information. Other errors may occur.';
}

$required = array(
    'ini_set',
    'fpassthru',
);

$recommended = array(
    'fsockopen',
    'exec',
    'escapeshellarg',
    'proc_open',
    'popen',
    'set_time_out',
);

And added these individual function_exists checks:
(fpassthru check was already included in the existing code on line 276)
PHP:
if (!function_exists('ini_set'))
{
    $errors['ini_set'] = 'The required PHP extension ini_set could not be found. Please ask your host to install this extension.';
}

if (!function_exists('fsockopen'))
{
    $errors['fsockopen'] = 'The required PHP extension fsockopen could not be found. Please ask your host to install this extension.';
}

if (!function_exists('exec'))
{
    $errors['exec'] = 'The required PHP extension exec could not be found. Please ask your host to install this extension.';
}

if (!function_exists('escapeshellarg'))
{
    $errors['escapeshellarg'] = 'The required PHP extension escapeshellarg could not be found. Please ask your host to install this extension.';
}

if (!function_exists('proc_open'))
{
    $errors['proc_open'] = 'The required PHP extension proc_open could not be found. Please ask your host to install this extension.';
}

if (!function_exists('popen'))
{
    $errors['popen'] = 'The required PHP extension popen could not be found. Please ask your host to install this extension.';
}

if (!function_exists('set_time_limit'))
{
    $errors['set_time_limit'] = 'The required PHP extension set_time_limit could not be found. Please ask your host to install this extension.';
}

I then was able to get an accurate response to the functions being disabled on the server:

modified-script-results.webp
 
Last edited:
ini_get will only return what is included in php.ini
That's puzzling, ini_get should return whatever the runtime configuration value is regardless of how or where it was configured. That's the difference between ini_get and get_cfg_var. You can even set a value with ini_set and have it reflected via subsequent ini_get calls. Any ini files under the configuration directory should be treated the same as if they were in php.ini too.

I'm not disputing your experience though. In any case, we'd need to check both function_exists and disable_functions since the former will not work on PHP < 8.
 
Thank you for reporting this issue, it has now been resolved. We are aiming to include any changes that have been made in a future XF release (2.3.4).

Change log:
Make required and recommended function checks more robust
There may be a delay before changes are rolled out to the XenForo Community.
 
Back
Top Bottom