* @copyright 2012-2020 phpMyFAQ Team
* @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
* @link https://www.phpmyfaq.de
* @since 2012-03-07
*/
use Composer\Autoload\ClassLoader;
use Elasticsearch\ClientBuilder;
use phpMyFAQ\Configuration;
use phpMyFAQ\Database;
use phpMyFAQ\Exception;
use phpMyFAQ\Init;
//
// Debug mode:
// - false debug mode disabled
// - true debug mode enabled
//
define('DEBUG', false);
if (DEBUG) {
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL | E_STRICT);
} else {
error_reporting(0);
}
//
// Fix the PHP include path if PMF is running under a "strange" PHP configuration
//
$foundCurrPath = false;
$includePaths = explode(PATH_SEPARATOR, ini_get('include_path'));
$i = 0;
while ((!$foundCurrPath) && ($i < count($includePaths))) {
if ('.' == $includePaths[$i]) {
$foundCurrPath = true;
}
++$i;
}
if (!$foundCurrPath) {
ini_set('include_path', '.' . PATH_SEPARATOR . ini_get('include_path'));
}
//
// Tweak some PHP configuration values
// Warning: be sure the server has enough memory and stack for PHP
//
ini_set('pcre.backtrack_limit', 100000000);
ini_set('pcre.recursion_limit', 100000000);
//
// The root directory
//
if (!defined('PMF_ROOT_DIR')) {
define('PMF_ROOT_DIR', dirname(__DIR__));
}
//
// Check if multisite/multisite.php exist for Multisite support
//
if (file_exists(PMF_ROOT_DIR . '/multisite/multisite.php') && 'cli' !== PHP_SAPI) {
require PMF_ROOT_DIR . '/multisite/multisite.php';
}
//
// Read configuration and constants
//
if (!defined('PMF_MULTI_INSTANCE_CONFIG_DIR')) {
define('PMF_CONFIG_DIR', PMF_ROOT_DIR . '/config'); // Single instance configuration
} else {
define('PMF_CONFIG_DIR', PMF_MULTI_INSTANCE_CONFIG_DIR); // Multi instance configuration
}
//
// Check if config/database.php exist -> if not, redirect to installer
//
if (!file_exists(PMF_CONFIG_DIR . '/database.php')) {
header('Location: ./setup/index.php');
exit();
}
require PMF_CONFIG_DIR . '/database.php';
require PMF_CONFIG_DIR . '/constants.php';
/*
* The /src directory
*/
define('PMF_SRC_DIR', __DIR__);
/*
* The directory where the translations reside
*/
define('PMF_LANGUAGE_DIR', dirname(__DIR__) . '/lang');
//
// Setting up autoloader
//
require PMF_SRC_DIR . '/libs/autoload.php';
$loader = new ClassLoader();
$loader->add('phpMyFAQ', PMF_SRC_DIR);
$loader->addPsr4('Abraham\\TwitterOAuth\\', PMF_SRC_DIR . '/libs/abraham/twitteroauth/src');
$loader->register();
require PMF_SRC_DIR . '/libs/parsedown/Parsedown.php';
require PMF_SRC_DIR . '/libs/parsedown/ParsedownExtra.php';
//
// Set the error handler to our phpMyFAQErrorHandler() function
//
set_error_handler('phpMyFAQErrorHandler');
//
// Create a database connection
//
try {
Database::setTablePrefix($DB['prefix']);
$db = Database::factory($DB['type']);
$db->connect($DB['server'], $DB['user'], $DB['password'], $DB['db'], isset($DB['port']) ? $DB['port'] : null);
} catch (Exception $e) {
Database::errorPage($e->getMessage());
exit(-1);
}
//
// Fetch the configuration and add the database connection
//
$faqConfig = new Configuration($db);
$faqConfig->getAll();
//
// We always need a valid session!
//
ini_set('session.use_only_cookies', 1); // Avoid any PHP version to move sessions on URLs
ini_set('session.auto_start', 0); // Prevent error to use session_start() if it's active in php.ini
ini_set('session.use_trans_sid', 0);
ini_set('session.cookie_samesite', 'Strict');
ini_set('session.cookie_httponly', true);
ini_set('url_rewriter.tags', '');
//
// Start the PHP session
//
Init::cleanRequest();
if (defined('PMF_SESSION_SAVE_PATH') && !empty(PMF_SESSION_SAVE_PATH)) {
session_save_path(PMF_SESSION_SAVE_PATH);
}
session_start();
//
// Connect to LDAP server, when LDAP support is enabled
//
if ($faqConfig->get('ldap.ldapSupport') && file_exists(PMF_CONFIG_DIR . '/ldap.php') && extension_loaded('ldap')) {
require PMF_CONFIG_DIR . '/ldap.php';
$faqConfig->setLdapConfig($PMF_LDAP);
} else {
$ldap = null;
}
//
// Connect to Elasticsearch if enabled
//
if ($faqConfig->get('search.enableElasticsearch') && file_exists(PMF_CONFIG_DIR . '/elasticsearch.php')) {
require PMF_CONFIG_DIR . '/elasticsearch.php';
require PMF_CONFIG_DIR . '/constants_elasticsearch.php';
$psr4Loader = new ClassLoader();
$psr4Loader->addPsr4('Elasticsearch\\', PMF_SRC_DIR . '/libs/elasticsearch/src/Elasticsearch');
$psr4Loader->addPsr4('GuzzleHttp\\Ring\\', PMF_SRC_DIR . '/libs/guzzlehttp/ringphp/src');
$psr4Loader->addPsr4('Monolog\\', PMF_SRC_DIR . '/libs/monolog/src/Monolog');
$psr4Loader->addPsr4('Psr\\', PMF_SRC_DIR . '/libs/psr/log/Psr');
$psr4Loader->addPsr4('React\\Promise\\', PMF_SRC_DIR . '/libs/react/promise/src');
$psr4Loader->register();
$esClient = ClientBuilder::create()
->setHosts($PMF_ES['hosts'])
->build();
$faqConfig->setElasticsearch($esClient);
$faqConfig->setElasticsearchConfig($PMF_ES);
}
//
// Build attachments path
//
$confAttachmentsPath = trim($faqConfig->get('records.attachmentsPath'));
if ('/' == $confAttachmentsPath[0] || preg_match('%^[a-z]:(\\\\|/)%i', $confAttachmentsPath)) {
// If we're here, some windows or unix style absolute path was detected.
define('PMF_ATTACHMENTS_DIR', $confAttachmentsPath);
} else {
// otherwise build the absolute path
$tmp = dirname(__DIR__) . DIRECTORY_SEPARATOR . $confAttachmentsPath;
// Check that nobody is traversing
if (0 === strpos((string)$tmp, dirname(__DIR__))) {
define('PMF_ATTACHMENTS_DIR', $tmp);
} else {
define('PMF_ATTACHMENTS_DIR', false);
}
}
//
// Fix if phpMyFAQ is running behind a proxy server
//
if (!isset($_SERVER['HTTP_HOST'])) {
if (isset($_SERVER['HTTP_X_FORWARDED_SERVER'])) {
$_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_SERVER'];
} else {
$_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
}
}
//
// Fix undefined server variables in Windows IIS & CGI mode
//
if (!isset($_SERVER['SCRIPT_NAME'])) {
if (isset($_SERVER['SCRIPT_FILENAME'])) {
$_SERVER['SCRIPT_NAME'] = $_SERVER['SCRIPT_FILENAME'];
} elseif (isset($_SERVER['PATH_TRANSLATED'])) {
$_SERVER['SCRIPT_NAME'] = $_SERVER['PATH_TRANSLATED'];
} elseif (isset($_SERVER['PATH_INFO'])) {
$_SERVER['SCRIPT_NAME'] = $_SERVER['PATH_INFO'];
} elseif (isset($_SERVER['SCRIPT_URL'])) {
$_SERVER['SCRIPT_NAME'] = $_SERVER['SCRIPT_URL'];
}
}
//
// phpMyFAQ exception log
//
$pmfExceptions = [];
/**
* phpMyFAQ custom error handler function, also to prevent the disclosure of
* potential sensitive data.
*
* @param int $level The level of the error raised.
* @param string $message The error message.
* @param string $filename The filename that the error was raised in.
* @param int $line The line number the error was raised at.
* @return bool|null
*/
function phpMyFAQErrorHandler($level, $message, $filename, $line)
{
// Sanity check
// Note: when DEBUG mode is true we want to track any error!
if (
// 1. the @ operator sets the PHP's error_reporting() value to 0
(!DEBUG && (0 == error_reporting()))
// 2. Honor the value of PHP's error_reporting() function
|| (!DEBUG && (0 == ($level & error_reporting())))
) {
// Do nothing
return true;
}
// Cleanup potential sensitive data
$filename = (DEBUG ? $filename : basename($filename));
$errorTypes = [
E_ERROR => 'error',
E_WARNING => 'warning',
E_PARSE => 'parse error',
E_NOTICE => 'notice',
E_CORE_ERROR => 'code error',
E_CORE_WARNING => 'core warning',
E_COMPILE_ERROR => 'compile error',
E_COMPILE_WARNING => 'compile warning',
E_USER_ERROR => 'user error',
E_USER_WARNING => 'user warning',
E_USER_NOTICE => 'user notice',
E_STRICT => 'strict warning',
E_RECOVERABLE_ERROR => 'recoverable error',
E_DEPRECATED => 'deprecated warning',
E_USER_DEPRECATED => 'user deprecated warning',
];
$errorType = 'unknown error';
if (isset($errorTypes[$level])) {
$errorType = $errorTypes[$level];
}
// Custom error message
$errorMessage = sprintf(
'
phpMyFAQ %s [%s]: %s in %s on line %d
',
$errorType,
$level,
$message,
$filename,
$line
);
if (ini_get('display_errors')) {
echo $errorMessage;
}
if (ini_get('log_errors')) {
error_log(sprintf('phpMyFAQ %s: %s in %s on line %d',
$errorType,
$message,
$filename,
$line)
);
}
switch ($level) {
// Blocking errors
case E_ERROR:
case E_PARSE:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
// Prevent processing any more PHP scripts
exit();
break;
// Not blocking errors
default:
break;
}
return true;
}