Typesetter-Original-gtbu/include/common.php

724 lines
18 KiB
PHP

<?php
defined('is_running') or die('Not an entry point...');
/**
* See gpconfig.php for these configuration options
*
*/
gp_defined('gpdebug', false);
if( gpdebug ){
error_reporting(E_ALL);
}
set_error_handler('showError');
require_once('tool.php');
require_once('thirdparty/time/strftime.php');
gp_defined('gp_restrict_uploads', false);
gp_defined('gpdebugjs', gpdebug);
gp_defined('gp_cookie_cmd', true);
gp_defined('gp_browser_auth', false);
gp_defined('gp_require_encrypt', false);
gp_defined('gp_nonce_algo', 'legacy'); // Since 5.0
gp_defined('gp_chmod_file', 0666);
gp_defined('gp_chmod_dir', 0755);
gp_defined('gp_index_filenames', true);
gp_defined('gp_safe_mode', false);
gp_defined('gp_backup_limit', 30);
gp_defined('gp_write_lock_time', 5);
gp_defined('gp_dir_index', true);
gp_defined('gp_remote_addons', true); // deprecated 4.0.1
gp_defined('gp_remote_plugins', gp_remote_addons);
gp_defined('gp_remote_themes', gp_remote_addons);
gp_defined('gp_remote_update', gp_remote_addons);
gp_defined('gp_unique_addons', false);
gp_defined('gp_data_type', '.php');
gp_defined('gp_default_theme', 'Bootstrap4/footer');
gp_defined('gp_allowed_fatal_errors', 10 ); // number of fatal errors to allow before disabling a component
gp_defined('gp_prefix_urls', false); // not yet implemented
gp_defined('create_css_sourcemaps', false); // Since 5.2
gp_defined('load_css_in_body', false); // Since 5.1
gp_defined('notify_deprecated', true); // Since 5.2
//gp_defined('CMS_DOMAIN', 'http://gpeasy.loc');
gp_defined('CMS_DOMAIN', 'https://www.typesettercms.com');
gp_defined('CMS_READABLE_DOMAIN', 'TypesetterCMS.com');
gp_defined('CMS_NAME', 'Typesetter');
gp_defined('CMS_NAME_FULL', 'Typesetter CMS');
gp_defined('addon_browse_path', CMS_DOMAIN . '/index.php');
gp_defined('debug_path', CMS_DOMAIN . '/index.php/Debug');
gp_defined('gpversion', '5.3-p8.3');
gp_defined('gp_random', \gp\tool::RandomString());
@ini_set('session.use_only_cookies', '1');
@ini_set('default_charset', 'utf-8');
@ini_set('html_errors', '0');
if( function_exists('mb_internal_encoding') ){
mb_internal_encoding('UTF-8');
}
//see mediawiki/languages/Names.php
$languages = [
'af' => 'Afrikaans', # Afrikaans
'ar' => 'العربية', # Arabic
'bg' => 'Български', # Bulgarian
'ca' => 'Català', # Catalan
'cs' => 'Česky', # Czech
'da' => 'Dansk', # Danish
'de' => 'Deutsch', # German
'el' => 'Ελληνικά', # Greek
'en' => 'English', # English
'es' => 'Español', # Spanish
'et' => 'eesti', # Estonian
'fi' => 'Suomi', # Finnish
'fo' => 'Føroyskt', # Faroese
'fr' => 'Français', # French
'gl' => 'Galego', # Galician
'hr' => 'hrvatski', # Croatian
'hu' => 'Magyar', # Hungarian
'is' => 'Íslenska', # Icelandic
'it' => 'Italiano', # Italian
'ja' => '日本語', # Japanese
'lt' => 'Lietuvių', # Lithuanian
'nl' => 'Nederlands', # Dutch
'no' => 'Norsk', # Norwegian
'pl' => 'Polski', # Polish
'pt' => 'Português', # Portuguese
'pt-br' => 'Português do Brasil', # Brazilian Portuguese
'ro' => 'Română', # Romanian
'ru' => 'Русский', # Russian
'sk' => 'Slovenčina', # Slovak
'sl' => 'Slovenščina', # Slovenian
'sv' => 'Svenska', # Swedish
'tr' => 'Türkçe', # Turkish
'uk' => 'Українська', # Ukrainian
'zh' => '中文', # (Zhōng Wén) - Chinese
];
$gpversion = gpversion; // @deprecated 3.5b2
$addonDataFolder = $addonCodeFolder = false; // deprecated
$addonPathData = $addonPathCode = false;
$wbErrorBuffer = $gp_not_writable = $wbMessageBuffer = [];
require_once('deprecated.php');
/* from wordpress
* wp-settings.php
* see also classes.php
*/
// Fix for IIS, which doesn't set REQUEST_URI
if( empty($_SERVER['REQUEST_URI']) ){
// IIS Mod-Rewrite
if( isset($_SERVER['HTTP_X_ORIGINAL_URL']) ){
$_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_ORIGINAL_URL'];
}else if( isset($_SERVER['HTTP_X_REWRITE_URL']) ){
// IIS Isapi_Rewrite
$_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_REWRITE_URL'];
}else{
// Use ORIG_PATH_INFO if there is no PATH_INFO
if( !isset($_SERVER['PATH_INFO']) && isset($_SERVER['ORIG_PATH_INFO']) ){
$_SERVER['PATH_INFO'] = $_SERVER['ORIG_PATH_INFO'];
}
// Some IIS + PHP configurations puts the script-name in the path-info (No need to append it twice)
if( isset($_SERVER['PATH_INFO']) ){
if( $_SERVER['PATH_INFO'] == $_SERVER['SCRIPT_NAME'] ){
$_SERVER['REQUEST_URI'] = $_SERVER['PATH_INFO'];
}else{
$_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] . $_SERVER['PATH_INFO'];
}
}
// Append the query string if it exists and isn't null
if( isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING']) ){
$_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
}
}
}
// Set default timezone in PHP 5.
if ( function_exists('date_default_timezone_set') ){
date_default_timezone_set( 'UTC' );
}
/**
* Error Handling
* Display the error and a debug_backtrace if gpdebug is not false
* If gpdebug is an email address, send the error message to the address
* @return false Always returns false so the standard PHP error handler is also used
*
*/
function showError($errno, $errmsg, $filename, $linenum, $vars=null, $backtrace=null): bool
{
global $wbErrorBuffer, $addon_current_id, $page, $addon_current_version, $config, $addonFolderName;
static $reported = [];
$errortype = array (
E_ERROR => 'Fatal Error',
E_WARNING => 'Warning',
E_PARSE => 'Parsing Error',
E_NOTICE => 'Notice',
E_CORE_ERROR => 'Core 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 Notice',
E_RECOVERABLE_ERROR => 'Recoverable Error',
E_DEPRECATED => 'Deprecated',
E_USER_DEPRECATED => 'User Deprecated',
);
// for functions prepended with @ symbol to suppress errors
$error_reporting = error_reporting();
if( $error_reporting === 0 ){
return false;
}
// since we supported older versions of php, there may be a lot of strict errors
if( $errno === E_STRICT ){
return true;
}
//get the backtrace and function where the error was thrown
if( !$backtrace ){
$backtrace = debug_backtrace();
}
//remove showError() from backtrace
if( strtolower($backtrace[0]['function']) == 'showerror' ){
$backtrace = array_slice($backtrace, 1);
}
$backtrace = array_slice($backtrace, 0 ,7);
//record one error per function and only record the error once per request
if( isset($backtrace[0]['function']) ){
$uniq = $filename.$backtrace[0]['function'];
}else{
$uniq = $filename . $linenum;
}
if( isset($reported[$uniq]) ){
return false;
}
$reported[$uniq] = true;
//disable showError after 20 errors
if( count($reported) >= 20 ){
restore_error_handler();
}
if( gpdebug === false ){
//if it's an addon error, only report if the addon was installed remotely
if( isset($addonFolderName) && $addonFolderName ){
if( !isset($config['addons'][$addonFolderName]['remote_install']) ){
return false;
}
//if it's a core error, it should be in the include folder
}elseif(!str_contains($filename, '/include/')){
return false;
}
//record the error
$i = count($wbErrorBuffer);
$args = [];
$args['en' . $i] = $errno;
$args['el' . $i] = $linenum;
$args['em' . $i] = substr($errmsg,0,255);
$args['ef' . $i] = $filename; //filename length checked later
if( isset($addon_current_id) ){
$args['ea' . $i] = $addon_current_id;
}
if( isset($addon_current_version) && $addon_current_version ){
$args['ev' . $i] = $addon_current_version;
}
if( is_object($page) && !empty($page->title) ){
$args['ep' . $i] = $page->title;
}
$wbErrorBuffer[$uniq] = $args;
return false;
}
$mess = '';
$mess .= '<fieldset style="padding:1em">';
$mess .= '<legend>' . $errortype[$errno] . ' (' . $errno . ')</legend> ' . $errmsg;
$mess .= '<br/> &nbsp; &nbsp; <b>in:</b> ' . $filename;
$mess .= '<br/> &nbsp; &nbsp; <b>on line:</b> ' . $linenum;
$mess .= '<br/> &nbsp; &nbsp; <b>time:</b> ' . date('Y-m-d H:i:s') . ' (' . time() . ')';
$server_params = ['REQUEST_URI', 'REQUEST_METHOD', 'REMOTE_ADDR', 'HTTP_X_FORWARDED_FOR'];
foreach( $server_params as $param ){
if( array_key_exists($param, $_SERVER) ){
$mess .= '<br/> &nbsp; &nbsp; <b>' . $param . ':</b> ' . $_SERVER[$param];
}
}
//attempting to include all data can result in a blank screen
foreach($backtrace as $i => $trace){
foreach($trace as $tk => $tv){
if( is_array($tv) ){
$backtrace[$i][$tk] = '[' . count($tv) . ']';
}elseif( is_object($tv) ){
$backtrace[$i][$tk] = 'object ' . get_class($tv);
}
}
}
$mess .= '<div>';
$mess .= '<a href="javascript:void(0)" ';
$mess .= 'onclick="';
$mess .= 'var st = this.nextSibling.style; ';
$mess .= 'if( st.display==\'block\' ){ ';
$mess .= 'st.display=\'none\' ';
$mess .= '}else{ ';
$mess .= 'st.display=\'block\' ';
$mess .= '}; ';
$mess .= 'return false;"';
$mess .= '>';
$mess .= 'Show Backtrace';
$mess .= '</a>';
$mess .= '<div class="nodisplay">';
$mess .= pre($backtrace);
$mess .= '</div>';
$mess .= '</div>';
$mess .= '</fieldset>';
if( gpdebug === true ){
msg($mess);
}elseif( class_exists('\\gp\tool\\Emailer') ){
$mailer = new \gp\tool\Emailer();
$subject = \gp\tool::ServerName(true) . ' Debug';
$mailer->SendEmail(gpdebug, $subject, $mess);
}
return false;
}
/**
* Define a constant if it hasn't already been set
* @param string $var The name of the constant
* @param mixed $default The value to set the constant if it hasn't been set
* @since 2.4RC2
*/
function gp_defined($var, $default){
if( defined($var) ){
return;
}
$env = getenv($var, true);
if( $env === false ){
$env = getenv($var);
}
if( $env !== false ){
define($var, $env);
}else{
define($var, $default);
}
}
/**
* Fix GPCR if magic_quotes_gpc is on
* magic_quotes_gpc is deprecated, but still on by default in many versions of php
*
*/
if( function_exists('get_magic_quotes_gpc') &&
version_compare(phpversion(), '5.4', '<=') &&
@get_magic_quotes_gpc()
){
fix_magic_quotes($_GET);
fix_magic_quotes($_POST);
fix_magic_quotes($_COOKIE);
fix_magic_quotes($_REQUEST);
}
//If Register Globals
if( \gp\tool::IniGet('register_globals') ){
foreach($_REQUEST as $key => $value){
$key = strtolower($key);
if( ($key == 'globals') || ($key == '_post') ){
die('Hack attempted.');
}
}
}
function fix_magic_quotes(&$arr){
$new = [];
foreach( $arr as $key => $val ){
$key = stripslashes($key);
if( is_array( $val ) ){
fix_magic_quotes( $val );
}else{
$val = stripslashes( $val );
}
$new[$key] = $val;
}
$arr = $new;
}
/**
* @deprecated 5.2
* Wrapper for msg()
*
*/
function message(){
// trigger_error('Deprecated function message(). Use msg() instead');
call_user_func_array('msg', func_get_args());
}
/**
* Store a user message in the buffer
* @since 4.0
*
*/
function msg(){
global $wbMessageBuffer;
$args = func_get_args();
if( empty($args[0]) ){
return;
}
if( isset($args[1]) ){
$wbMessageBuffer[] = '<li>' . call_user_func_array('sprintf', $args) . '</li>';
}elseif( is_array($args[0]) || is_object($args[0]) ){
$wbMessageBuffer[] = '<li>' . pre($args[0]) . '</li>';
}else{
$wbMessageBuffer[] = '<li>' . $args[0] . '</li>';
}
}
/**
* add message only if admin user is logged in
* @since 5.2
*
*/
function debug(){
if( \gp\tool::LoggedIn() ){
call_user_func_array('msg', func_get_args());
}
}
/**
* Output the message buffer
*
*/
function GetMessages($wrap=true){
global $wbMessageBuffer, $gp_not_writable, $langmessage;
if( \gp\tool::loggedIn() && count($gp_not_writable) > 0 ){
$files = '<ul><li>' . implode('</li><li>', $gp_not_writable) . '</li></ul>';
$message = sprintf($langmessage['not_writable'], \gp\tool::GetUrl('Admin/Status')) . $files;
msg($message);
$gp_not_writable = [];
}
$result = $wrap_end = '';
if( $wrap ){
$result = "\n" . '<!-- message_start ' . gp_random . ' -->';
$wrap_end = '<!-- message_end -->' . "\n";
}
if( !empty($wbMessageBuffer) ){
if( gpdebug === false ){
$wbMessageBuffer = array_unique($wbMessageBuffer);
}
$result .= '<div class="messages gp-fixed-adjust">';
$result .= '<div>';
$result .= '<span class="msg_controls">';
$result .= '<a href="#close-message" class="req_script close_message" data-cmd="close_message"></a>';
if( \gp\tool::LoggedIn() ){
// add copy to clipboard icon, only for admins
$result .= '<a href="#copy-message" title="' . $langmessage['Copy to Clipboard'] . '" ';
$result .= 'class="req_script copy_message" data-cmd="copy_message"></a>';
}
$result .= '</span>';
$result .= '<ul>';
$result .= implode('', $wbMessageBuffer);
$result .= '</ul>';
$result .= '</div>';
$result .= '</div>';
$result .= '<div style="display:none;"><script type="text/javascript">';
$result .= '(function(){';
$result .= 'setTimeout(function(){';
$result .= 'var elem=document.querySelectorAll(".messages>div")[0];';
$result .= 'elem.style.height=elem.offsetHeight+"px";';
$result .= 'elem.style.maxHeight="calc(100vh - 40px)";';
$result .= '},150);';
$result .= '})();';
$result .= '</script></div>';
}
return $result .= \gp\tool::ErrorBuffer() . $wrap_end;
}
/**
* Include a file relative to the include directory of the current installation
*
*/
function includeFile($file){
global $dataDir;
switch($file){
case 'tool/ajax.php':
$file = 'tool/Output/Ajax.php';
break;
case 'tool/editing.php':
$file = 'tool/Editing.php';
break;
case 'tool/email_mailer.php':
$file = 'tool/Emailer.php';
break;
case 'tool/gpOutput.php':
$file = 'tool/Output.php';
break;
case 'tool/Images.php':
$file = 'tool/Image.php';
break;
case 'tool/sessions.php';
$file = 'tool/Session.php';
break;
case 'tool/SectionContent.php':
$file = 'tool/Output/Sections.php';
break;
case 'tool/recaptcha.php':
$file = 'tool/Recaptcha.php';
break;
case 'tool/Page_Rename.php':
$file = 'Page/Rename.php';
break;
case 'special/special_contact.php':
$file = 'special/Contact.php';
break;
case 'admin/admin_browser.php':
$file = 'admin/Content/Browser.php';
break;
case 'admin/admin_preferences.php':
$file = 'admin/Settings/Preferences.php';
break;
case 'admin/admin_uploaded.php':
$file = 'admin/Content/Uploaded.php';
break;
case 'admin/admin_tools.php':
$file = 'admin/Tools.php';
break;
case 'admin/tool_thumbnails.php';
$file = 'tool/Image.php';
break;
}
require_once($dataDir . '/include/' . $file);
}
// php < 7.0 doesn't have \Throwable
if( !interface_exists('Throwable') ){
class Throwable extends Exception{}
}
/**
* Include a script, unless it has caused a fatal error.
* Using this function allows handling fatal errors that are thrown by the included php scripts
*
* @param string $file The full path of the php file to include
* @param string $include_variation Which variation or adaptation of php's include() function to use (include,include_once,include_if, include_once_if, require ...)
* @param array $globals List of global variables to set
*/
function IncludeScript($file, $include_variation = 'include_once', $globals=array()){
$exists = file_exists($file);
//check to see if it exists
$include_variation = str_replace('_if', '', $include_variation, $has_if);
if( $has_if && !$exists ){
return true;
}
//check for fatal errors
if( \gp\tool\Output::FatalNotice('include', $file) ){
return false;
}
//set global variables
foreach($globals as $global){
global $$global;
}
$return = null;
try{
switch($include_variation){
case 'include':
$return = include($file);
break;
case 'include_once':
$return = include_once($file);
break;
case 'require':
$return = require($file);
break;
case 'require_once':
$return = require_once($file);
break;
}
}catch(Throwable $e){
\showError(
E_ERROR,
'IncludeScript() Fatal Error: ' . $e->getMessage(),
$e->GetFile(),
$e->GetLine(),
[],
$e->getTrace()
);
// php < 7.0 doesn't have \Throwable
}catch(Exception $e){
\showError(
E_ERROR,
'IncludeScript() Fatal Error: ' . $e->getMessage(),
$e->GetFile(),
$e->GetLine(),
[],
$e->getTrace()
);
}
\gp\tool\Output::PopCatchable();
return $return;
}
/**
* Similar to print_r and var_dump, but it is output buffer handling function safe
* msg( pre(array(array(true))) );
* msg( pre(new tempo()) );
*/
function pre($mixed){
static $level = 0;
$output = '';
$type = gettype($mixed);
switch($type){
case 'object':
$type = get_class($mixed) . ' object';
$output = $type . '(...)' . "\n"; //recursive object references creates an infinite loop
break;
case 'array':
$output = $type . '(' . "\n";
foreach($mixed as $key => $value){
$level++;
$output .= str_repeat(' ',$level) . '[' . $key . '] => ' . pre($value) . "\n";
$level--;
}
$output .= str_repeat(' ', $level) . ')';
break;
case 'boolean':
if( $mixed ){
$mixed = 'true';
}else{
$mixed = 'false';
}
default:
$output = '(' . $type . ')' . htmlspecialchars($mixed ?? "", ENT_COMPAT, 'UTF-8', false) . '';
break;
}
if( $level == 0 ){
return '<pre>' . htmlspecialchars($output, ENT_COMPAT, 'UTF-8', false) . '</pre>';
}
return $output;
}
/**
* @deprecated 2.6
*/
function showArray($mixed){
trigger_error('Deprecated function showArray(). Use pre() instead');
}
/**
* Modified from Wordpress function win_is_writable()
* Working for users without requiring trailing slashes as noted in Wordpress
*
* Workaround for Windows bug in is_writable() function
* will work in despite of Windows ACLs bug
* NOTE: use a trailing slash for folders!!!
* see http://bugs.php.net/bug.php?id=27609
* see http://bugs.php.net/bug.php?id=30931
*
* @param string $path
* @return bool
*/
function gp_is_writable( $path ){
if( is_writable($path) ){
return true;
}
// check tmp file for read/write capabilities
if( is_dir($path) ){
$path = rtrim($path,'/') . '/' . uniqid(mt_rand()) . '.tmp';
}
$should_delete_tmp_file = !file_exists($path);
$f = @fopen($path, 'a');
if( $f === false ){
return false;
}
fclose($f);
if( $should_delete_tmp_file ){
unlink($path);
}
return true;
}