Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

2154 lines (1941 sloc) 78.564 kb
<?php /*
ocPortal
Copyright (c) ocProducts, 2004-2012
See text/EN/licence.txt for full licencing information.
NOTE TO PROGRAMMERS:
Do not edit this file. If you need to make changes, save your changed file to the appropriate *_custom folder
**** If you ignore this advice, then your website upgrades (e.g. for bug fixes) will likely kill your changes ****
*/
/**
* @license http://opensource.org/licenses/cpal_1.0 Common Public Attribution License
* @copyright ocProducts Ltd
* @package core
*/
/**
* Standard code module initialisation function.
*/
function init__global2()
{
global $BOOTSTRAPPING,$CHECKING_SAFEMODE,$BAD_WORD_CHARS,$FIXED_WORD_CHARS,$FIXED_WORD_CHARS_HTML,$BROWSER_DECACHEING,$CHARSET,$TEMP_CHARSET,$RELATIVE_PATH,$CURRENTLY_HTTPS,$RUNNING_SCRIPT_CACHE,$SERVER_TIMEZONE,$HAS_SET_ERROR_HANDLER,$DYING_BADLY,$XSS_DETECT,$SITE_INFO,$JAVASCRIPTS,$JAVASCRIPT,$CSSS,$IN_MINIKERNEL_VERSION,$EXITING,$FILE_BASE,$MOBILE,$CACHE_TEMPLATES,$BASE_URL_HTTP,$BASE_URL_HTTPS,$WORDS_TO_FILTER,$FIELD_RESTRICTIONS,$VALID_ENCODING,$CONVERTED_ENCODING,$MICRO_BOOTUP,$MICRO_AJAX_BOOTUP,$QUERY_LOG,$_CREATED_FILES,$CURRENT_SHARE_USER,$CACHE_FIND_SCRIPT;
if (ini_get('output_buffering')=='1') @ob_end_clean();
if (array_key_exists('HTTP_X_REWRITE_URL',$_SERVER))
{
foreach ($_GET as $key=>$val)
{
if ($key[0]=='?')
{
unset($_GET[$key]);
$_GET[substr($key,1)]=$val;
}
}
$_SERVER['REQUEST_URI']=$_SERVER['HTTP_X_REWRITE_URL'];
} elseif ((!array_key_exists('REQUEST_URI',$_SERVER)) && (!array_key_exists('REQUEST_URI',$_ENV)))
{
$_SERVER['REQUEST_URI']=$_SERVER['PHP_SELF'];
$first=true;
foreach ($_GET as $key=>$val)
{
$_SERVER['REQUEST_URI'].=$first?'?':'&';
$_SERVER['REQUEST_URI'].=urlencode($key).'='.urlencode($val);
$first=false;
}
}
if ((array_key_exists('SCRIPT_FILENAME',$_SERVER)) && (!array_key_exists('PHP_SELF',$_SERVER))) $_SERVER['PHP_SELF']=$_SERVER['SCRIPT_FILENAME'];
elseif ((array_key_exists('SCRIPT_NAME',$_SERVER)) && (defined('HIPHOP_PHP'))) $_SERVER['PHP_SELF']=$_SERVER['SCRIPT_NAME'];
@header('Expires: Mon, 20 Dec 1998 01:00:00 GMT');
@header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
//@header('Cache-Control: no-cache, must-revalidate'); // DISABLED AS MAKES IE RELOAD ON 'BACK' AND LOSE FORM CONTENTS
@header('Pragma: no-cache'); // for proxies, and also IE
if ((strpos($_SERVER['PHP_SELF'],'upgrader.php')===false) && ((!isset($SITE_INFO['no_extra_closed_file'])) || ($SITE_INFO['no_extra_closed_file']=='0')))
{
if (is_file('closed.html'))
{
if ((@strpos($_SERVER['SERVER_SOFTWARE'],'IIS')===false)) header('HTTP/1.0 503 Service Temporarily Unavailable');
header('Location: closed.html');
exit();
}
if (@is_file('../closed.html'))
{
if ((@strpos($_SERVER['SERVER_SOFTWARE'],'IIS')===false)) header('HTTP/1.0 503 Service Temporarily Unavailable');
header('Location: ../closed.html');
exit();
}
}
// Cover up holes in old PHP versions functionality
if (!function_exists('str_word_count'))
{
/**
* Isolate the words in the input string.
*
* @param string String to count words in
* @param integer The format
* @set 0 1 2
* @return mixed Typically a list - the words of the input string
*/
function str_word_count($input,$format=0)
{
//count words
$pattern="/[^(\w|\d|\'|\"|\.|\!|\?|;|,|\\|\/|\-\-|:|\&|@)]+/";
$all_words=trim(preg_replace($pattern,' ',$input));
$a=array();
$pos=0;
while (true)
{
$old_pos=$pos;
$pos=strpos($all_words,' ',$pos);
if ($pos===false)
{
$a[$old_pos]=substr($all_words,$old_pos);
break;
}
$a[$old_pos]=substr($all_words,$old_pos,$pos-$old_pos);
}
if ($format==0) return count($a);
return $a;
}
}
if (!function_exists('html_entity_decode'))
{
/**
* Decode the HTML entitity encoded input string.
*
* @param string The text to decode
* @param integer The quote style code
* @param ?string Character set to decode to (NULL: default)
* @return string The decoded text
*/
function html_entity_decode($input,$quote_style,$charset=NULL)
{
unset($quote_style);
unset($charset);
/* // NB: &nbsp does not go to <space>. It's not something you use with html escaping, it's for hard-space-formatting. URL's don't contain spaces, but that's due to URL escaping (%20)
$replace_array=array(
'&amp;'=>'&',
'&gt;'=>'>',
'&lt;'=>'<',
'&#039;'=>'\'',
'&quot;'=>'"',
);
foreach ($replace_array as $from=>$to)
{
$input=str_replace($from,$to,$input);
}
return $input;*/
$trans_tbl=get_html_translation_table(HTML_ENTITIES);
$trans_tbl=array_flip($trans_tbl);
return strtr($input,$trans_tbl);
}
}
if (version_compare(phpversion(),'4.3.0')>=0)
{
if (!function_exists('unichrm_hex'))
{
/**
* Convert a unicode character number to a unicode string. Callback for preg_replace.
*
* @param array Regular expression match array.
* @return ~string Converted data (false: could not convert).
*/
function unichrm_hex($matches)
{
return unichr(hexdec($matches[1]));
}
}
if (!function_exists('unichrm'))
{
/**
* Convert a unicode character number to a unicode string. Callback for preg_replace.
*
* @param array Regular expression match array.
* @return ~string Converted data (false: could not convert).
*/
function unichrm($matches)
{
return unichr(intval($matches[1]));
}
}
if (!function_exists('unichr'))
{
/**
* Convert a unicode character number to a HTML-entity enabled string, using lower ASCII characters where possible.
*
* @param integer Character number.
* @return ~string Converted data (false: could not convert).
*/
function unichr($c)
{
if ($c<=0x7F)
{
return chr($c);
} else
{
return '#&'.strval($c).';';
}
}
}
}
$BOOTSTRAPPING=1;
$CHECKING_SAFEMODE=false;
$BAD_WORD_CHARS=array(chr(128),chr(130),chr(131),chr(132),chr(133),chr(134),chr(135),chr(136),chr(137),chr(138),chr(139),chr(140),chr(142),chr(145),chr(146),chr(147),chr(148),chr(149),chr(150),chr(151),chr(152),chr(153),chr(154),chr(155),chr(156),chr(158),chr(159));
$FIXED_WORD_CHARS=array('(EUR-)',',','{f.}','"','...','-|-','=|=','^','{%o}','{~S}','<','CE','{~Z}',"'","'",'"','"','-','-','--','~','(TM)','{~s}','>','ce','{~z}','{.Y.}'); // some of these are Comcode shortcuts. We can't use entities as we can't assume we're converting into Comcode.
$FIXED_WORD_CHARS_HTML=array('&#8364;','&#8218;','&#402;','&#8222;','&hellip;','&#8224;','&#8225;','&#710;','&#8240;','&#352;','&#8249;','&#338;','&#381;',"&lsquo;","&rsquo;",'&ldquo;','&rdquo;','&bull;','&ndash;','&mdash;','&#732;','&trade;','&#353;','&#8250;','&#339;','&#382;','&#376;');
$RUNNING_SCRIPT_CACHE=array();
$BROWSER_DECACHEING=NULL;
$CHARSET=NULL;
$TEMP_CHARSET=NULL;
$CURRENTLY_HTTPS=NULL;
$CACHE_FIND_SCRIPT=array();
error_reporting(E_ALL);
@ini_set('html_errors','1');
@ini_set('docref_root','http://www.php.net/manual/en/');
@ini_set('docref_ext','.php');
$SERVER_TIMEZONE=function_exists('date_default_timezone_get')?@date_default_timezone_get():ini_get('date.timezone');
@ini_set('date.timezone','UTC');
if (function_exists('date_default_timezone_set')) date_default_timezone_set('UTC'); // Needed for HPHP
$HAS_SET_ERROR_HANDLER=false;
$DYING_BADLY=false; // If ocPortal is bailing out uncontrollably, setting this will make sure the error hander does not try and suppress
$XSS_DETECT=function_exists('ocp_mark_as_escaped');
$GLOBALS['DEBUG_MODE']=(((!array_key_exists('debug_mode',$SITE_INFO) || ($SITE_INFO['debug_mode']=='1')) && ((is_dir(get_file_base().'/.svn')) || (is_dir(get_file_base().'/.git')) || (function_exists('ocp_mark_as_escaped')))) && ((!array_key_exists('keep_no_debug_mode',$_GET) || ($_GET['keep_no_debug_mode']=='0'))));
$GLOBALS['SEMI_DEBUG_MODE']=(((!array_key_exists('debug_mode',$SITE_INFO) || ($SITE_INFO['debug_mode']=='1')) && ((is_dir(get_file_base().'/.svn')) || (is_dir(get_file_base().'/.git')) || (function_exists('ocp_mark_as_escaped')))));
if (function_exists('set_time_limit')) @set_time_limit(60);
if ($GLOBALS['DEBUG_MODE'])
{
if (function_exists('set_time_limit')) @set_time_limit(10);
@ini_set('ocproducts.type_strictness','1');
@ini_set('ocproducts.xss_detect','1');
}
if ($GLOBALS['DEBUG_MODE'])
{
require_code('developer_tools');
}
$JAVASCRIPTS=array('javascript'=>1,'javascript_thumbnails'=>1);
if (($GLOBALS['CURRENT_SHARE_USER']!==NULL) || (get_domain()=='myocp.com')) $JAVASCRIPTS['javascript_ajax']=1;
$CSSS=array('no_cache'=>1,'global'=>1);
// Try and make the PHP environment as we need it
if (function_exists('set_magic_quotes_runtime')) @set_magic_quotes_runtime(0); // @'d because it's deprecated and PHP 5.3 may give an error
@ini_set('auto_detect_line_endings','0');
@ini_set('include_path','');
@ini_set('default_socket_timeout','60');
@ini_set('allow_url_fopen','0');
@ini_set('suhosin.executor.disable_emodifier','1'); // Extra security if suhosin is available
@ini_set('suhosin.executor.multiheader','1'); // Extra security if suhosin is available
@ini_set('suhosin.executor.disable_eval','0');
@ini_set('suhosin.executor.eval.whitelist','');
@ini_set('suhosin.executor.func.whitelist','');
// Load most basic config
$IN_MINIKERNEL_VERSION=0;
$EXITING=0;
if ((array_key_exists('use_ocf',$_GET)) && (running_script('upgrader')))
{
$SITE_INFO['forum_type']='ocf';
$SITE_INFO['ocf_table_prefix']=$SITE_INFO['table_prefix'];
}
$CACHE_TEMPLATES=true;
// The URL to our install (no trailing /)
$BASE_URL_HTTP=NULL;
$BASE_URL_HTTPS=NULL;
$WORDS_TO_FILTER=NULL;
$FIELD_RESTRICTIONS=NULL;
$VALID_ENCODING=false;
$CONVERTED_ENCODING=false;
if (!isset($MICRO_BOOTUP)) $MICRO_BOOTUP=0;
if (!isset($MICRO_AJAX_BOOTUP)) $MICRO_AJAX_BOOTUP=0;
require_code_no_override('version');
if (($MICRO_BOOTUP==0) && ($MICRO_AJAX_BOOTUP==0))
{
@header('X-Powered-By: ocPortal '.ocp_version_full().' (PHP '.phpversion().')');
$QUERY_LOG=false;
if ((isset($_REQUEST['special_page_type'])) && ($_REQUEST['special_page_type']=='query'))
{
$QUERY_LOG=true;
}
}
// Most critical things
require_code('support'); // A lot of support code is present in this
srand(make_seed());
mt_srand(make_seed());
if (($MICRO_BOOTUP==0) && ($MICRO_AJAX_BOOTUP==0)) // Fast cacheing for bots
{
if ((running_script('index')) && (count($_POST)==0))
{
$bot_type=get_bot_type();
if (($bot_type!==NULL) && (isset($SITE_INFO['fast_spider_cache'])) && ($SITE_INFO['fast_spider_cache']!='0'))
{
fast_spider_cache(true);
}
}
}
require_code('caches'); // Recently taken out of 'support' so makes sense to load it here
require_code('database'); // There's nothing without the database
if (((!isset($SITE_INFO['known_suexec'])) || ($SITE_INFO['known_suexec']=='0')) && (!is_writable_wrap(get_file_base().'/.htaccess'))) // If we have to run this in software
{
require_code('support2');
if (ip_banned(get_ip_address())) critical_error('BANNED');
}
if ((running_script('messages')) && (get_param('action','new')=='new') && (get_param_integer('routine_refresh',0)==0)) // Architecturally unsound chat message precheck (for extra efficiency)
{
require_code('chat_poller');
chat_poller();
}
if ($MICRO_BOOTUP==0)
{
load_user_stuff();
}
// For any kind of niceness we need these. The order is chosen for complex dependency reasons - don't mess with it
if ($MICRO_AJAX_BOOTUP==0)
{
require_code('themes'); // Output needs to know about themes
require_code('templates'); // So that we can do error templates
require_code('tempcode'); // Output is done with tempcode
if ($MICRO_BOOTUP==0)
{
require_code('comcode'); // Much output goes through comcode
}
}
require_code('zones'); // Zone is needed because zones are where all ocPortal pages reside
require_code('config'); // Config is needed for much active stuff
if ((get_option('collapse_user_zones',true)==='1') && ($RELATIVE_PATH=='site'))
{
get_base_url();/*force calculation first*/
$RELATIVE_PATH='';
}
require_code('users'); // Users are important due to permissions
if (($MICRO_BOOTUP==0) && ($MICRO_AJAX_BOOTUP==0)) // Fast cacheing for Guests
{
if ((running_script('index')) && (count($_POST)==0))
{
if ((isset($SITE_INFO['any_guest_cached_too'])) && ($SITE_INFO['any_guest_cached_too']=='1') && (is_guest(NULL,true)))
{
fast_spider_cache(false);
}
}
}
$CACHE_TEMPLATES=((get_option('is_on_template_cache')=='1') || (get_param_integer('keep_cache',0)==1) || (get_param_integer('cache',0)==1)) && (get_param_integer('keep_cache',NULL)!==0) && (get_param_integer('cache',NULL)!==0);
if ($MICRO_AJAX_BOOTUP==0)
{
require_code('temporal'); // Date/time functions
require_code('files'); // Contains fix_permissions, needed for 'lang'
require_code('lang'); // So that we can do language stuff (e.g. errors)
convert_data_encodings();
if ($MICRO_BOOTUP==0)
{
require_code('permissions'); // So we can check access
}
}
// At this point we can display errors nicely
$GLOBALS['SUPRESS_ERROR_DEATH']=false;
set_error_handler('ocportal_error_handler');
if (function_exists('error_get_last')) register_shutdown_function('catch_fatal_errors');
$HAS_SET_ERROR_HANDLER=true;
if ($MICRO_BOOTUP==0)
{
if (method_exists($GLOBALS['FORUM_DRIVER'],'forum_layer_initialise')) $GLOBALS['FORUM_DRIVER']->forum_layer_initialise();
}
if ($MICRO_AJAX_BOOTUP==0)
{
$JAVASCRIPT=new ocp_tempcode();
}
if ($MICRO_BOOTUP==0)
{
if (($IN_MINIKERNEL_VERSION!=1) && ($MICRO_AJAX_BOOTUP==0))
{
has_cookies(); // Will determine at early point whether we have cookie support
get_num_users_site(); // Will kill site if there are too many users
}
}
require_code('urls'); // URL building is crucial
@header('Content-type: text/html; charset='.get_charset());
if (($MICRO_AJAX_BOOTUP==0) && ($MICRO_BOOTUP==0))
{
// Before anything gets outputted
handle_logins();
require_code('site'); // This powers the site (top level page generation)
// Are we installed?
get_option('site_name');
}
// Our logging (change false to true for temporarily changing it so staff get logging)
if (get_option('log_php_errors')=='1')
{
@ini_set('log_errors','1');
if (addon_installed('errorlog'))
@ini_set('error_log',get_custom_file_base().'/data_custom/errorlog.php');
}
if (($MICRO_BOOTUP==0) && ($MICRO_AJAX_BOOTUP==0) && ((get_option('display_php_errors')=='1') || (running_script('upgrader')) || (has_specific_permission(get_member(),'see_php_errors'))))
{
@ini_set('display_errors','1');
} elseif (!$GLOBALS['DEBUG_MODE']) @ini_set('display_errors','0');
// G-zip?
@ini_set('zlib.output_compression',(get_option('gzip_output')=='1')?'On':'Off');
if ((function_exists('setlocale')) && ($MICRO_AJAX_BOOTUP==0))
{
$locales=explode(',',do_lang('locale'));
setlocale(LC_ALL,$locales[0]);
@setlocale(LC_ALL,$locales);
unset($locales);
}
if (($MICRO_AJAX_BOOTUP==0) && ($MICRO_BOOTUP==0) && ((!isset($SITE_INFO['no_installer_checks'])) || ($SITE_INFO['no_installer_checks']=='0')))
{
if ((is_file(get_file_base().'/install.php')) && (!is_file(get_file_base().'/install_ok')) && (running_script('index')))
warn_exit(do_lang_tempcode('MUST_DELETE_INSTALLER'));
}
if (($MICRO_AJAX_BOOTUP==0) && ($MICRO_BOOTUP==0))
{
$changed_base_url=!array_key_exists('base_url',$SITE_INFO) && get_long_value('last_base_url')!==get_base_url(false);
if ((running_script('index')) && ((is_browser_decacheing()) || ($changed_base_url)))
{
require_code('view_modes');
erase_tempcode_cache();
erase_cached_templates(!$changed_base_url);
erase_cached_language();
persistant_cache_empty();
if ($changed_base_url)
{
require_lang('zones');
require_code('zones3');
erase_comcode_page_cache();
set_long_value('last_base_url',get_base_url(false));
}
}
if (has_zone_access(get_member(),'adminzone'))
{
$JAVASCRIPTS['javascript_staff']=1;
$JAVASCRIPTS['javascript_ajax']=1;
if (addon_installed('occle')) $JAVASCRIPTS['javascript_button_occle']=1;
}
if ((addon_installed('realtime_rain')) && (get_option('bottom_show_realtime_rain_button',true)==='1')) $JAVASCRIPTS['javascript_button_realtime_rain']=1;
}
/*ocp_memory_profile('startup');
$func=get_defined_functions();
print_r($func['user']);*/
if (((ocp_srv('HTTPS')!='') && (ocp_srv('HTTPS')!='off')) && (((!defined('HIPHOP_PHP')) || (tacit_https()) || (is_page_https(get_zone_name(),get_page_name()))))) // Fix IE bug
{
@header('Cache-Control: private');
@header('Pragma: private');
}
$BOOTSTRAPPING=0;
if (($GLOBALS['SEMI_DEBUG_MODE']) && ($MICRO_AJAX_BOOTUP==0)) // Lots of code that only runs if you're a programmer. It tries to make sure coding standards are met.
{
if ($GLOBALS['SEMI_DEBUG_MODE'])
{
/*if ((mt_rand(0,2)==1) && ($GLOBALS['DEBUG_MODE']) && (running_script('index'))) We know this works now, so let's stop messing up our development speed
{
require_code('view_modes');
erase_cached_templates(true); // Stop anything trying to read a template cache item (E.g. CSS, JS) that might not exist!
}*/
if ((strpos(ocp_srv('HTTP_REFERER'),ocp_srv('HTTP_HOST'))!==false) && (strpos(ocp_srv('HTTP_REFERER'),'keep_devtest')!==false) && (!running_script('attachment')) && (!running_script('upgrader')) && (strpos(ocp_srv('HTTP_REFERER'),'login')===false) && (is_null(get_param('keep_devtest',NULL))))
{
$_GET['keep_devtest']='1';
fatal_exit('URL not constructed properly: development mode in use but keep_devtest was not specified. This indicates that links have been made without build_url (in PHP) or keep_stub (in Javascript). Whilst not fatal this time, failure to use these functions can cause problems when your site goes live. See the ocPortal codebook for more details.');
} else $_GET['keep_devtest']='1';
}
if ((browser_matches('true_xhtml')) && (get_value('html5')!=='1') && (get_value('html5')!=='_true'/*TODO: deprecate old _true check*/) && (get_param_integer('keep_no_xhtml',0)==0) && (!running_script('upgrader'))) // In theory this is supported (and mostly does work), but a lot of necessary Javascript is not standardised, and the browser's that support XHTML properly do not agree on how to implement this Javascript in a usable way when it is enabled. This leads to a lot of corner-cases. If you're seeing this code enabled, it was possible for us to resolve them, otherwise not yet.
{
@header('Content-type: application/xhtml+xml; charset='.get_charset());
}
if (isset($_CREATED_FILES)) // Comes from ocProducts custom PHP version
{
/**
* Run after-tests for debug mode, to make sure coding standards are met.
*/
function debug_mode_aftertests()
{
global $_CREATED_FILES,$_MODIFIED_FILES;
// Use the info from ocProduct's custom PHP version to make sure that all files that were created/modified got synched as they should have been.
foreach ($_CREATED_FILES as $file)
{
if ((substr($file,0,strlen(get_file_base()))==get_file_base()) && (substr($file,-4)!='.log') && (basename($file)!='permissioncheckslog.php'))
@exit(escape_html('File not permission-synched: '.$file));
}
foreach ($_MODIFIED_FILES as $file)
{
if ((strpos($file,'_cache')===false) && (substr($file,0,strlen(get_file_base()))==get_file_base()) && (substr($file,-4)!='.log') && (basename($file)!='permissioncheckslog.php'))
@exit(escape_html('File not change-synched: '.$file));
}
global $TITLE_CALLED,$SCREEN_TEMPLATE_CALLED,$EXITING;
if ((is_null($SCREEN_TEMPLATE_CALLED)) && ($EXITING==0) && (strpos(ocp_srv('PHP_SELF'),'index.php')!==false)) @exit(escape_html('No screen template called.'));
if ((!$TITLE_CALLED) && ((is_null($SCREEN_TEMPLATE_CALLED)) || ($SCREEN_TEMPLATE_CALLED!='')) && ($EXITING==0) && (strpos(ocp_srv('PHP_SELF'),'index.php')!==false)) @exit(escape_html('No title used on screen.'));
}
register_shutdown_function('debug_mode_aftertests');
}
if ((ocp_srv('SCRIPT_FILENAME')!='') && ($GLOBALS['DEBUG_MODE']) && (strpos(ocp_srv('SCRIPT_FILENAME'),'data_custom')===false))
{
if (@strlen(file_get_contents(ocp_srv('SCRIPT_FILENAME'),FILE_TEXT))>4500)
{
fatal_exit('Entry scripts (front controllers) should not be shoved full of code.');
}
}
}
// FirePHP console support, only for administrators
if (((get_param_integer('keep_firephp',0)==1) || (get_param_integer('keep_queries',0)==1)) && (($GLOBALS['FORUM_DRIVER']->is_super_admin(get_member())) || ($GLOBALS['IS_ACTUALLY_ADMIN'])))
{
require_code('firephp');
}
$default_memory_limit=get_value('memory_limit');
if ((is_null($default_memory_limit)) || ($default_memory_limit=='') || ($default_memory_limit=='0') || ($default_memory_limit=='-1'))
$default_memory_limit='64M';
@ini_set('memory_limit',$default_memory_limit);
if ((isset($GLOBALS['FORUM_DRIVER'])) && ($GLOBALS['FORUM_DRIVER']->is_super_admin(get_member())))
{
if (get_param_integer('keep_avoid_memory_limit',0)==1)
{
disable_php_memory_limit();
}
$memory_test=get_param_integer('keep_memory_limit_test',0);
if (($memory_test!=0) && ($memory_test<=32))
{
@ini_set('memory_limit',strval($memory_test).'M');
}
}
if ((get_option('sitewide_im',true)==='1') && (running_script('index')) /* i.e. not running script */ && (get_param('type','misc',true)!='room'))
{
require_code('chat');
enter_chat_lobby();
}
// Startup hooks
if (!running_script('upgrader'))
{
$startup_hooks=find_all_hooks('systems','startup');
foreach (array_keys($startup_hooks) as $hook)
{
require_code('hooks/systems/startup/'.filter_naughty_harsh($hook));
$ob=object_factory('Hook_startup_'.filter_naughty_harsh($hook),true);
if ($ob===NULL) continue;
$ob->run($MICRO_BOOTUP,$MICRO_AJAX_BOOTUP,0);
}
if (($CURRENT_SHARE_USER!==NULL) && (float_to_raw_string(ocp_version_number())!=get_value('version')))
{
require_code('upgrade');
clear_caches_2();
version_specific();
upgrade_modules();
ocf_upgrade();
}
}
}
/**
* Find if we can use the fast spider cache.
*
* @return boolean Whether we can
*/
function can_fast_spider_cache()
{
if (isset($_GET['keep_session'])) return false;
if (isset($_GET['redirect'])) return false;
if (isset($_GET['zone'])) return false;
if (isset($_GET['date'])) return false;
$url_easy=get_self_url_easy();
if (strpos($url_easy,'sort=')!==false) return false;
if (strpos($url_easy,'start=')!==false) return false;
if (strpos($url_easy,'max=')!==false) return false;
return true;
}
/**
* If possible dump the user to 100% static caching.
*
* @param boolean Whether to cache as a bot
*/
function fast_spider_cache($bot=true)
{
global $SITE_INFO;
require_code('urls');
if (!can_fast_spider_cache()) return;
$fast_cache_path=get_custom_file_base().'/persistant_cache/'.md5(serialize(get_self_url_easy()));
if (!$bot) $fast_cache_path.='__non-bot';
if (!array_key_exists('js_on',$_COOKIE)) $fast_cache_path.='__no-js';
$fast_cache_path.='.gcd';
if (is_file($fast_cache_path))
{
$expires=60*60*intval($SITE_INFO['fast_spider_cache']);
$mtime=filemtime($fast_cache_path);
if ($mtime>time()-$expires)
{
if ($bot) // Only bots can do this, as they won't try to login and end up reaching a previously cached page
{
header("Pragma: public");
header("Cache-Control: maxage=".strval($expires));
header('Expires: '.gmdate('D, d M Y H:i:s',time()+$expires).' GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s',$mtime).' GMT');
$since=ocp_srv('HTTP_IF_MODIFIED_SINCE');
if ($since!='')
{
if (strtotime($since)<$mtime)
{
header('HTTP/1.0 304 Not Modified');
exit();
}
}
}
if (function_exists('gzencode'))
{
ini_set('zlib.output_compression','Off');
header('Content-Encoding: gzip');
}
exit(file_get_contents($fast_cache_path));
} else
{
@unlink($fast_cache_path);
sync_file($fast_cache_path);
}
}
}
/**
* Disable the PHP memory limit. Do not use this carelessly, use it if a screen is a bit fat or in an importer, don't use it assuming memory is infinite.
*/
function disable_php_memory_limit()
{
$shl=@ini_get('suhosin.memory_limit');
if (($shl===false) || ($shl=='') || ($shl=='0'))
{
@ini_set('memory_limit','64M');
@ini_set('memory_limit','-1');
} else
{
@ini_set('memory_limit',$shl);
}
}
/**
* Get the character set to use. We try and be clever to allow AJAX scripts to avoid loading up language
*
* @return string The character set
*/
function get_charset()
{
global $CHARSET,$XSS_DETECT;
if (isset($CHARSET)) return $CHARSET;
global $SITE_INFO;
if (isset($SITE_INFO['charset'])) // An optimisation, if you want to put it in here
{
$CHARSET=$SITE_INFO['charset'];
if ($XSS_DETECT) ocp_mark_as_escaped($CHARSET);
return $CHARSET;
}
global $LANG_LOADED_LANG;
if ((function_exists('do_lang')) && (function_exists('user_lang')) && (isset($LANG_LOADED_LANG[user_lang()]['critical_error'])) && (!in_safe_mode()))
{
$attempt=do_lang('charset',NULL,NULL,NULL,NULL,false);
if ($attempt!==NULL)
{
$CHARSET=$attempt;
return $attempt;
}
}
global $TEMP_CHARSET;
if (isset($TEMP_CHARSET)) return $TEMP_CHARSET;
global $SITE_INFO;
$lang=array_key_exists('default_lang',$SITE_INFO)?$SITE_INFO['default_lang']:'EN';
$path=get_file_base().'/lang_custom/'.$lang.'/global.ini';
if (!is_file($path)) $path=get_file_base().'/lang/'.$lang.'/global.ini';
if (!is_file($path))
{
$path=get_file_base().'/lang_custom/'.$lang.'/global.po';
if (is_file($path))
{
$TEMP_CHARSET='utf-8';
return $TEMP_CHARSET;
}
}
if (!is_file($path))
{
$path=get_file_base().'/lang_custom/'.$lang.'/global-'.strtolower($lang).'.po';
if (is_file($path))
{
$TEMP_CHARSET='utf-8';
return $TEMP_CHARSET;
}
}
if (!is_file($path)) $path=get_file_base().'/lang/EN/global.ini';
$file=fopen($path,'rt');
$contents=str_replace(chr(13),chr(10),fread($file,3000));
fclose($file);
$matches=array();
if (preg_match('#\[strings\].*charset=([\w\-]+)\n#s',$contents,$matches)!=0)
{
$TEMP_CHARSET=$matches[1];
if ($XSS_DETECT) ocp_mark_as_escaped($TEMP_CHARSET);
return $TEMP_CHARSET;
}
$TEMP_CHARSET='iso-8859-1';
return $TEMP_CHARSET;
}
/**
* Load stuff that allows user code to work.
*/
function load_user_stuff()
{
if ((!array_key_exists('FORUM_DRIVER',$GLOBALS)) || ($GLOBALS['FORUM_DRIVER']===NULL)) // Second clause is for Quercus, as it pre-NULLs referenced variables
{
global $SITE_INFO;
require_code('forum_stub');
if (!array_key_exists('forum_type',$SITE_INFO)) $SITE_INFO['forum_type']='ocf';
require_code('forum/'.$SITE_INFO['forum_type']); // So we can at least get user details
$GLOBALS['FORUM_DRIVER']=object_factory('forum_driver_'.filter_naughty_harsh($SITE_INFO['forum_type']));
if (($SITE_INFO['forum_type']=='ocf') && (get_db_forums()==get_db_site()) && ($GLOBALS['FORUM_DRIVER']->get_drivered_table_prefix()==get_table_prefix()) && (!$GLOBALS['DEBUG_MODE'])) // NB: In debug mode needs separating so we can properly test our boundaries
{
$GLOBALS['FORUM_DRIVER']->connection=$GLOBALS['SITE_DB'];
}
elseif ($SITE_INFO['forum_type']!='none')
{
$GLOBALS['FORUM_DRIVER']->connection=new database_driver(get_db_forums(),get_db_forums_host(),get_db_forums_user(),get_db_forums_password(),$GLOBALS['FORUM_DRIVER']->get_drivered_table_prefix());
}
$GLOBALS['FORUM_DRIVER']->MEMBER_ROWS_CACHED=array();
$GLOBALS['FORUM_DB']=&$GLOBALS['FORUM_DRIVER']->connection;
}
}
/**
* ocPortal error catcher for fatal versions. This is hooked in only on PHP5.2 as error_get_last() only works on these versions.
*/
function catch_fatal_errors()
{
if (!function_exists('error_get_last')) return;
$error=error_get_last();
if (!is_null($error))
{
if (!array_key_exists('message',$error)) return; // Needed for HipHop PHP
if (substr($error['message'],0,26)=='Maximum execution time of ')
{
if (function_exists('i_force_refresh'))
{
i_force_refresh();
}
}
//$tmp=$GLOBALS;unset($tmp['GLOBALS']);@var_dump($tmp);@exit();
//@var_dump(get_defined_functions()); exit(); // Useful for debugging memory problems, finding unneeded stuff that is loaded
switch($error['type'])
{
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
$GLOBALS['SUPRESS_ERROR_DEATH']=false; // We can't recover as we've lost our execution track. Force a nice death rather than trying to display a recoverable error.
$GLOBALS['DYING_BADLY']=true; // Does not actually work unfortunately. @'d calls never get here at all.
ocportal_error_handler($error['type'],$error['message'],$error['file'],$error['line']);
}
}
}
/**
* ocPortal error handler (hooked into PHP error system).
*
* @param integer The error code-number
* @param PATH The error message
* @param string The file the error occurred in
* @param integer The line the error occurred on
* @return boolean Always false
*/
function ocportal_error_handler($errno,$errstr,$errfile,$errline)
{
if ((error_reporting()==0) && (!$GLOBALS['DYING_BADLY'])) return false; // This actually tells if @ was used oddly enough. You wouldn't figure from the PHP docs.
if ((error_reporting() & $errno) || ($GLOBALS['DYING_BADLY']))
{
// Strip down path for security
if (substr(str_replace(DIRECTORY_SEPARATOR,'/',$errfile),0,strlen(get_file_base().'/'))==str_replace(DIRECTORY_SEPARATOR,'/',get_file_base().'/'))
$errfile=substr($errfile,strlen(get_file_base().'/'));
// Work out the error type
if (!defined('E_RECOVERABLE_ERROR')) define('E_RECOVERABLE_ERROR',4096);
switch ($errno)
{
case E_RECOVERABLE_ERROR: // constant not defined in all php versions but we defined it
case E_USER_ERROR:
case E_PARSE:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_ERROR:
$type='error';
break;
case -123: // Hacked in for the memtrack extension, which was buggy
case E_CORE_WARNING:
case E_COMPILE_WARNING:
case E_USER_WARNING:
case E_WARNING:
$type='warning';
break;
//case E_STRICT: (constant not defined in all php versions)
//case E_DEPRECATED: (constant not defined in all php versions)
//case E_USER_DEPRECATED: (constant not defined in all php versions)
case E_USER_NOTICE:
case E_NOTICE:
$type='notice';
break;
default: // We don't know the error type so it's probably best to continue (could be a problem with something getting deprecated)
return false;
}
$GLOBALS['DYING_BADLY']=false; // So error suppress works again
if (strpos($errstr,'Allowed memory')!==false)
{
global $_REQUIRED_CODE;
if (!array_key_exists('failure',$_REQUIRED_CODE))
{
critical_error('EMERGENCY',$errstr.' ['.$errfile.' at '.strval($errline).']');
}
}
require_code('failure');
_ocportal_error_handler($type,$errno,$errstr,$errfile,$errline);
}
return false;
}
/*function ocp_memory_profile($id)
{
if (!function_exists('memory_get_usage')) return;
echo memory_get_usage().' ('.$id.')<br />';
}
function ocp_memory_profile_2($id,&$struct)
{
if (!function_exists('memory_get_usage')) return;
if (!function_exists('var_export')) return;
@ob_end_clean();
echo memory_get_usage().' ('.$id.')'.(is_null($struct)?'':(' ['.strlen(var_export($struct,true)).']')).'<br />';
}*/
/**
* Find whether the browser session is set to be doing a hard cache-empty refresh.
*
* @return boolean Whether the browser session is set to be doing a hard cache-empty refresh
*/
function is_browser_decacheing()
{
global $BROWSER_DECACHEING;
if ($BROWSER_DECACHEING!==NULL) return $BROWSER_DECACHEING;
if (is_null(get_value('ran_once')))
{
set_value('ran_once','1');
return true;
}
$header_method=(array_key_exists('HTTP_CACHE_CONTROL',$_SERVER)) && ($_SERVER['HTTP_CACHE_CONTROL']=='no-cache') && (ocp_srv('REQUEST_METHOD')!='POST') && ((!function_exists('browser_matches')) || (!browser_matches('opera')));
$BROWSER_DECACHEING=(($header_method) && ((array_key_exists('FORUM_DRIVER',$GLOBALS)) && (has_actual_page_access(get_member(),'admin_cleanup')) || ($GLOBALS['IS_ACTUALLY_ADMIN'])));
return $BROWSER_DECACHEING;
}
/**
* Find whether a certain script is being run to get here.
*
* @param string Script filename (canonically we want NO .php file type suffix)
* @return boolean Whether the script is running
*/
function running_script($is_this_running)
{
// First check cache
global $RUNNING_SCRIPT_CACHE;
if (isset($RUNNING_SCRIPT_CACHE[$is_this_running.'.php'])) return $RUNNING_SCRIPT_CACHE[$is_this_running.'.php'];
if (isset($RUNNING_SCRIPT_CACHE[$is_this_running])) return $RUNNING_SCRIPT_CACHE[$is_this_running];
// Make $is_this_running fully-qualified, to stop common filename prefixes matching with a stem compare
if (substr($is_this_running,-4)!='.php') $is_this_running.='.php';
// Strip down current URL so we can do a simple stem compare
$stripped_current_url=preg_replace('#^.*/#','',function_exists('ocp_srv')?ocp_srv('PHP_SELF'):$_SERVER['PHP_SELF']);
// Do the stem compare
$answer=(substr($stripped_current_url,0,strlen($is_this_running))==$is_this_running);
// Cache and return result
$RUNNING_SCRIPT_CACHE[$is_this_running]=$answer;
return $answer;
}
/**
* This is a intended to output an informational exit at the same time as terminating execution
*
* @param mixed The error message (string or tempcode)
*/
function inform_exit($text)
{
require_code('failure'); // It's in failure.php although this isn't REALLY failure. Still it's an exceptional event so we can't justify loading the code as global.
_generic_exit($text,'INFORM_SCREEN');
}
/**
* This is a less-revealing alternative to fatal_exit, that is used for user-errors/common-corruption-scenarios
*
* @param mixed The error message (string or tempcode)
*/
function warn_exit($text)
{
require_code('failure');
suggest_fatalistic();
_generic_exit($text,'WARN_SCREEN');
if (running_script('cron_bridge'))
relay_error_notification(is_object($text)?$text->evaluate():escape_html($text),false,'error_occurred_cron');
}
/**
* Give the user an option to see a stack trace by adding in a link, but only if they have permission
*/
function suggest_fatalistic()
{
if ((may_see_stack_dumps()) && (get_param_integer('keep_fatalistic',0)==0) && (running_script('index')))
{
if (count($_POST)==0)
{
$stack_trace_url=build_url(array('page'=>'_SELF','keep_fatalistic'=>1),'_SELF',NULL,true);
$st=do_lang_tempcode('WARN_TO_STACK_TRACE',escape_html($stack_trace_url->evaluate()));
} elseif (count($_FILES)==0)
{
$stack_trace_url=build_url(array('page'=>'_SELF','keep_fatalistic'=>1),'_SELF',NULL,true);
$p=build_keep_post_fields();
$st=do_lang_tempcode('WARN_TO_STACK_TRACE_2',escape_html($stack_trace_url->evaluate()),$p->evaluate());
} else
{
$stack_trace_url=build_url(array('page'=>'','keep_fatalistic'=>1),'');
$st=do_lang_tempcode('WARN_TO_STACK_TRACE_3',escape_html($stack_trace_url->evaluate()));
}
require_code('site');
attach_message($st,'inform');
}
}
/**
* Do a fatal exit, echo the header (if possible) and an error message, followed by a debugging back-trace.
* It also adds an entry to the error log, for reference.
*
* @param mixed The error message (string or tempcode)
*/
function fatal_exit($text)
{
require_code('failure');
_fatal_exit($text);
}
/**
* Log a hackattack, then displays an error message. It also attempts to send an e-mail to the staff alerting them of the hackattack.
*
* @param ID_TEXT The reason for the hack attack. This has to be a language string codename
* @param SHORT_TEXT A parameter for the hack attack language string (this should be based on a unique ID, preferably)
* @param SHORT_TEXT A more illustrative parameter, which may be anything (e.g. a title)
*/
function log_hack_attack_and_exit($reason,$reason_param_a='',$reason_param_b='')
{
require_code('failure');
_log_hack_attack_and_exit($reason,$reason_param_a,$reason_param_b);
}
/**
* Use the url_title_cache table (a bit of a hack but saved changed the DB structure) to see if a check-op was performed has been performed within the last 30 days.
*
* @param ID_TEXT Special check code (often a URL but does not need to be).
* @return boolean Whether the check has happened recently.
*/
function handle_has_checked_recently($id_code)
{
$last_check_test=$GLOBALS['SITE_DB']->query_value_null_ok('url_title_cache','t_title',array('t_url'=>'!'.$id_code));
if ((is_null($last_check_test)) || (substr($last_check_test,0,1)!='!') || (intval(substr($last_check_test,1))+60*60*24*30<time())) // only re-checks every 30 days
{
// Show when it was last tested
$GLOBALS['SITE_DB']->query_delete('url_title_cache',array('t_url'=>'!'.$id_code),'',1); // To make sure it can insert below
$GLOBALS['SITE_DB']->query_insert('url_title_cache',array('t_title'=>'!'.strval(time()),'t_url'=>'!'.$id_code),false,true); // To stop weird race-like conditions
return false;
}
return true;
}
/**
* A custom random number seed generator. It returns a random number seed.
*
* @return integer A random seed
*/
function make_seed()
{
list($usec,$sec)=explode(' ', microtime(false));
$u=produce_salt();
return intval(floatval($sec)*floatval($usec))+ord(substr($u,0,1))+(ord(substr($u,1,2))<<8);
}
/**
* Get the full string version of ocPortal that you are running.
*
* @return string The string saying the full ocPortal version number
*/
function ocp_version_full()
{
$minor=ocp_version_minor();
return strval(ocp_version()).(($minor=='')?'':(is_numeric($minor[0])?'.':'-').$minor);
}
/**
* Get the domain the website is installed on (preferably, without any www). The domain is used for e-mail defaults amongst other things.
*
* @return string The domain of the website
*/
function get_domain()
{
global $SITE_INFO;
$ret=array_key_exists('domain',$SITE_INFO)?$SITE_INFO['domain']:'';
if ($ret=='')
{
if ((!array_key_exists('base_url',$SITE_INFO)) || ($SITE_INFO['base_url']=='')) return array_key_exists('HTTP_HOST',$_SERVER)?preg_replace('#^www\.#','',$_SERVER['HTTP_HOST']):'localhost'; // Can't be ocp_srv due to bootstrap order
$matches=array();
preg_match('#://([^/\#]+)#',$SITE_INFO['base_url'],$matches);
$ret=preg_replace('#^www\.#','',$matches[1]);
}
return $ret;
}
/**
* Get the type of forums installed.
*
* @return string The type of forum installed
*/
function get_forum_type()
{
global $SITE_INFO;
if (!isset($SITE_INFO['forum_type'])) $SITE_INFO['forum_type']='ocf';
return $SITE_INFO['forum_type'];
}
/**
* Get the installed forum base URL.
*
* @param boolean Whether to get the base directory of the forum. Unless running OCF, this makes no difference - if possibly running OCF, you need to think about this parameter: are you trying to reach the MSN-central-site or just a link to the forums?
* @return URLPATH The installed forum base URL
*/
function get_forum_base_url($forum_base=false)
{
global $SITE_INFO;
if (!array_key_exists('board_prefix',$SITE_INFO)) $SITE_INFO['board_prefix']=get_base_url();
$forum_type=get_forum_type();
if ($forum_type=='none') return '';
$needs_forum_strip=(substr($SITE_INFO['board_prefix'],-6)=='/forum') && (substr(get_base_url(),-6)!='/forum');
if (($forum_type=='ocf') && (!$forum_base) && ($needs_forum_strip)) return substr($SITE_INFO['board_prefix'],0,strlen($SITE_INFO['board_prefix'])-6);
if (($forum_type=='ocf') && ($forum_base) && ($needs_forum_strip)) return $SITE_INFO['board_prefix'].'/forum';
return $SITE_INFO['board_prefix'];
}
/**
* Get the ocPortal cookie path.
*
* @return ?string The ocPortal cookie path (NULL: no special path, global)
*/
function get_cookie_path()
{
global $SITE_INFO;
$ret=array_key_exists('cookie_path',$SITE_INFO)?$SITE_INFO['cookie_path']:'/';
return ($ret=='')?NULL:$ret;
}
/**
* Get the ocPortal cookie domain.
*
* @return ?string The ocPortal cookie domain (NULL: current domain)
*/
function get_cookie_domain()
{
global $SITE_INFO;
$ret=array_key_exists('cookie_domain',$SITE_INFO)?$SITE_INFO['cookie_domain']:NULL;
return ($ret=='')?NULL:$ret;
}
/**
* Get the number of days to store our cookies.
*
* @return integer The number of days to store our cookies
*/
function get_cookie_days()
{
global $SITE_INFO;
return array_key_exists('cookie_domain',$SITE_INFO)?intval($SITE_INFO['cookie_days']):120;
}
/**
* Get the site name.
*
* @return string The name of the site
*/
function get_site_name()
{
return get_option('site_name');
}
/**
* Find whether we are running in safe mode.
*
* @return boolean Whether we are in safe mode
*/
function in_safe_mode()
{
global $SITE_INFO;
if ((isset($SITE_INFO['safe_mode'])) && ($SITE_INFO['safe_mode']=='1')) return true; // Useful for testing HPHP support
global $CHECKING_SAFEMODE;
if ($CHECKING_SAFEMODE) return false; // Stops infinite loops (e.g. Check safe mode > Check access > Check usergroups > Check implicit usergroup hooks > Check whether to look at custom implicit usergroup hooks [i.e. if not in safe mode])
$CHECKING_SAFEMODE=true;
$ret=((get_param_integer('keep_safe_mode',0)==1) && ((isset($GLOBALS['IS_ACTUALLY_ADMIN']) && ($GLOBALS['IS_ACTUALLY_ADMIN'])) || (!array_key_exists('FORUM_DRIVER',$GLOBALS)) || ($GLOBALS['FORUM_DRIVER']===NULL) || (!function_exists('get_member')) || ($GLOBALS['FORUM_DRIVER']->is_super_admin(get_member()))));
$CHECKING_SAFEMODE=false;
return $ret;
}
/**
* Find the URL to a certain external handler script (ocPortal allows these to be moved around between zones, to suit site .htaccess requirements).
*
* @param string The codename of the needed script
* @param boolean Whether to append keep variables
* @param integer Code representing what base URL type to use (0=guess, 1=http, 2=https)
* @set 0 1 2
* @return URLPATH The URL to the script
*/
function find_script($name,$append_keep=false,$base_url_code=0)
{
$append='';
if ($append_keep)
{
$keep=symbol_tempcode('KEEP',array('1'));
$append.=$keep->evaluate();
}
global $CACHE_FIND_SCRIPT;
if ($CACHE_FIND_SCRIPT===array())
{
if (function_exists('persistant_cache_get')) $CACHE_FIND_SCRIPT=persistant_cache_get('SCRIPT_PLACES');
if ($CACHE_FIND_SCRIPT===NULL) $CACHE_FIND_SCRIPT=array();
}
if (isset($CACHE_FIND_SCRIPT[$name][$append_keep][$base_url_code])) return $CACHE_FIND_SCRIPT[$name][$append_keep][$base_url_code].$append;
$zones=array(get_zone_name());
if (!in_safe_mode())
{
$zones[]='data_custom';
}
$zones[]='data';
$zones=array_merge($zones,find_all_zones());
foreach ($zones as $zone)
{
if ($zone!='site') // If not found, we assume in here
{
if (is_file(get_file_base().'/'.$zone.'/'.$name.'.php'))
{
$ret=get_base_url().'/'.$zone.(($zone!='')?'/':'').$name.'.php';
$CACHE_FIND_SCRIPT[$name][$append_keep][$base_url_code]=$ret;
if (function_exists('persistant_cache_set')) persistant_cache_set('SCRIPT_PLACES',$CACHE_FIND_SCRIPT,true);
return $ret.$append;
}
}
}
$ret=get_base_url(($base_url_code==0)?NULL:($base_url_code==2)).'/site/'.$name.'.php';
$CACHE_FIND_SCRIPT[$name][$append_keep][$base_url_code]=$ret;
if (function_exists('persistant_cache_set')) persistant_cache_set('SCRIPT_PLACES',$CACHE_FIND_SCRIPT,true);
return $ret.$append;
}
/**
* Get the base url (the minimum fully qualified URL to our installation).
*
* @param ?boolean Whether to get the HTTPS base URL (NULL: do so only if the current page uses the HTTPS base URL)
* @param ?ID_TEXT The zone the link is for (NULL: root zone)
* @return URLPATH The base-url
*/
function get_base_url($https=NULL,$zone_for=NULL)
{
if ($https===NULL) // If we don't know, we go by what the current page is
{
global $CURRENTLY_HTTPS;
$https=$CURRENTLY_HTTPS;
if ($https===NULL)
{
if ((get_option('enable_https',true)=='0') || (!running_script('index')))
{
$https=false;
} else
{
$https=function_exists('is_page_https') && function_exists('get_zone_name') && ((tacit_https()) || is_page_https(get_zone_name(),get_page_name()));
}
$CURRENTLY_HTTPS=$https;
}
}
global $BASE_URL_HTTP,$BASE_URL_HTTPS,$VIRTUALISED_ZONES;
if ($VIRTUALISED_ZONES===NULL)
{
require_code('zones');
get_zone_name();
}
if (($BASE_URL_HTTP!==NULL) && (!$https) && ((!$VIRTUALISED_ZONES) || ($zone_for===NULL))) return $BASE_URL_HTTP.(($zone_for=='')?'':('/'.$zone_for));
if (($BASE_URL_HTTPS!==NULL) && ($https) && ((!$VIRTUALISED_ZONES) || ($zone_for===NULL))) return $BASE_URL_HTTPS.(($zone_for=='')?'':('/'.$zone_for));
global $SITE_INFO;
if ((!isset($SITE_INFO)) || (!array_key_exists('base_url',$SITE_INFO)) || ($SITE_INFO['base_url']=='')) // Try and autodetect the base URL if it's not configured
{
$domain=ocp_srv('HTTP_HOST');
$colon_pos=strpos($domain,':');
if ($colon_pos!==false) $domain=substr($domain,0,$colon_pos);
$port=ocp_srv('SERVER_PORT');
if (($port=='') || ($port=='80') || ($port=='443')) $port=''; else $port=':'.$port;
$SITE_INFO['base_url']='http://'.$domain.$port.str_replace('%2F','/',rawurlencode(preg_replace('#/'.str_replace('#','\#',preg_quote($GLOBALS['RELATIVE_PATH'])).'$#','',str_replace('\\','/',dirname(ocp_srv('PHP_SELF'))))));
}
$base_url=$SITE_INFO['base_url'];
global $CURRENT_SHARE_USER;
if ($CURRENT_SHARE_USER!==NULL)
{
$base_url=preg_replace('#^http://([\w]+\.)?'.str_replace('#','\#',preg_quote($SITE_INFO['custom_share_domain'])).'#','http://'.ocp_srv('HTTP_HOST'),$base_url);
}
$found_mapping=false;
if ($VIRTUALISED_ZONES)
{
$zone_doing=($zone_for===NULL)?'':str_replace('/','',$zone_for);
if (array_key_exists('ZONE_MAPPING_'.$zone_doing,$SITE_INFO))
{
$domain=$SITE_INFO['ZONE_MAPPING_'.$zone_doing][0];
$path=$SITE_INFO['ZONE_MAPPING_'.$zone_doing][1];
$base_url='http://'.$domain;
if ($path!='') $base_url.='/'.$path;
$found_mapping=true;
}
}
if ($https)
{
$base_url='https://'.preg_replace('#^\w*://#','',$base_url);
if ((!$VIRTUALISED_ZONES) || ($zone_for===NULL)) $BASE_URL_HTTPS=$base_url;
} elseif ((!$VIRTUALISED_ZONES) || ($zone_for===NULL)) $BASE_URL_HTTP=$base_url;
if (!$found_mapping)
{
$base_url.=(($zone_for=='')?'':('/'.$zone_for));
}
return $base_url;
}
/**
* Get the base url (the minimum fully qualified URL to our personal data installation). For a shared install only, this is different to the base-url.
*
* @param ?boolean Whether to get the HTTPS base URL (NULL: do so only if the current page uses the HTTPS base URL)
* @return URLPATH The base-url
*/
function get_custom_base_url($https=NULL)
{
global $SITE_INFO;
if (!isset($SITE_INFO['custom_base_url_stub'])) return get_base_url($https);
// Note that HTTPS is not supported for shared installs
$u=current_share_user();
if ($u===NULL) return get_base_url($https);
return $SITE_INFO['custom_base_url_stub'].'/'.$u;
}
/**
* Function to get a base URL for an OCF relative-URL. The situation is complex as it needs to take into account OCF multi-site-network's, locally defined theme images, and shared-installs (myocp style).
*
* @param URLPATH Short base URL we need to probe
* @return URLPATH The appropriate base-url
*/
function get_complex_base_url($at)
{
return ((get_forum_base_url()!=get_base_url())?get_forum_base_url():((substr($at,0,22)=='themes/default/images/')?get_base_url():get_custom_base_url()));
}
/**
* Get a value (either POST [u]or[/u] GET), or the default if neither can be found.
*
* @param ID_TEXT The name of the parameter to get
* @param ?mixed The default value to give the parameter if the parameter value is not defined (NULL: allow missing parameter) (false: give error on missing parameter)
* @return ?string The parameter value (NULL: missing)
*/
function either_param($name,$default=false)
{
$a=__param(array_merge($_POST,$_GET),$name,$default,false,NULL);
if ($a===NULL) return NULL;
if ($a!==$default) // Check input field security
{
require_code('input_filter');
check_input_field($name,$a);
}
return function_exists('ocp_url_decode_post_process')?ocp_url_decode_post_process($a):$a;
}
/**
* Get the value of the specified POST key, if it is found, or the default otherwise.
*
* @param ID_TEXT The name of the parameter to get
* @param ?mixed The default value to give the parameter if the parameter value is not defined (NULL: allow missing parameter) (false: give error on missing parameter)
* @param boolean Whether we are cleaning for HTML rather than Comcode/plain-text
* @param boolean Whether to convert WYSIWYG contents to Comcode automatically
* @return ?string The parameter value (NULL: missing)
*/
function post_param($name,$default=false,$html=false,$conv_from_wysiwyg=true)
{
$a=__param($_POST,$name,$default,false,true);
if ($a===NULL) return NULL;
if ((trim($a)=='') && ($default!=='') && (array_key_exists('require__'.$name,$_POST)) && ($_POST['require__'.$name]!='0'))
{
require_code('failure');
improperly_filled_in_post($name);
}
if (($a!='') && (addon_installed('wordfilter')))
{
if ($name!='password')
{
require_code('word_filter');
$a=check_word_filter($a,$name);
}
}
if ($a!==NULL) $a=unixify_line_format($a,NULL,$html);
if ((isset($_POST[$name.'__is_wysiwyg'])) && ($_POST[$name.'__is_wysiwyg']=='1') && ($conv_from_wysiwyg))
{
if (trim($a)=='')
{
$a='';
} else
{
require_code('comcode_from_html');
$a=trim(semihtml_to_comcode($a));
}
} else
{
if ((substr($a,0,10)=='[semihtml]') && (substr(trim($a),-11)=='[/semihtml]'))
{
$_a=trim($a);
$_a=substr($_a,10,strlen($_a)-11-10);
if (strpos($_a,'[semihtml')===false)
{
require_code('comcode_from_html');
$a=trim(semihtml_to_comcode($_a));
}
}
}
return function_exists('ocp_url_decode_post_process')?ocp_url_decode_post_process($a):$a;
}
/**
* Get the value of the specified GET key, if it is found, or the default otherwise.
*
* @param ID_TEXT The name of the parameter to get
* @param ?mixed The default value to give the parameter if the parameter value is not defined (NULL: allow missing parameter) (false: give error on missing parameter)
* @param boolean Whether to skip the security check
* @return ?string The parameter value (NULL: missing)
*/
function get_param($name,$default=false,$no_security=false)
{
$a=__param($_GET,$name,$default);
if (($a=='') && (isset($_GET['require__'.$name])) && ($default!==$a) && ($_GET['require__'.$name]!='0'))
{
// We didn't give some required input
$GLOBALS['HTTP_STATUS_CODE']='400';
if (!headers_sent())
{
if ((!browser_matches('ie')) && (strpos(ocp_srv('SERVER_SOFTWARE'),'IIS')===false)) header('HTTP/1.0 400 Bad Request');
}
warn_exit(do_lang_tempcode('IMPROPERLY_FILLED_IN'));
}
if ($a===$default) return $a;
if (strpos($a,':')!==false)
$a=function_exists('ocp_url_decode_post_process')?ocp_url_decode_post_process($a):$a;
// Security check
$is_url=($name=='from') || ($name=='preview_url') || ($name=='redirect') || ($name=='redirect_passon') || ($name=='url');
if (($name!='s_message') && (!$is_url) && (!$no_security))
{
if (((isset($a[100])) && (strpos(substr($a,10),'::slash::slash:')===false) && (strpos(substr($a,10),'://')===false) && (strpos(substr($a,10),'::slash::slash:')===false)) || (preg_match('#\n|\000|<|(".*[=<>])|\.\./|^\s*((((j\s*a\s*v\s*a\s*)|(v\s*b\s*))?s\s*c\s*r\s*i\s*p\s*t)|(d\s*a\s*t\s*a\s*))\s*:#mi',$a)!=0))
{
log_hack_attack_and_exit('DODGY_GET_HACK',$name,$a);
}
} else
{
if ($is_url)
{
if (preg_match('#\n|\000|<|(".*[=<>])|^\s*((((j\s*a\s*v\s*a\s*)|(v\s*b\s*))?s\s*c\s*r\s*i\s*p\s*t)|(d\s*a\s*t\s*a\s*))\s*:#mi',$a)!=0)
{
log_hack_attack_and_exit('DODGY_GET_HACK',$name,$a);
}
$bu=get_base_url();
if ((looks_like_url($a)) && (substr($a,0,strlen($bu))!=$bu) && (substr($a,0,strlen(get_forum_base_url()))!=get_forum_base_url())) // Don't allow external redirections
{
$a=get_base_url();
}
}
}
if ($a===NULL) return NULL;
return $a;
}
/**
* Helper function to load up a GET/POST parameter.
*
* @param array The array we're extracting parameters from
* @param string The name of the parameter
* @param ?mixed The default value to give the parameter if the parameter value is not defined (NULL: allow missing parameter) (false: give error on missing parameter)
* @param boolean Whether the parameter has to be an integer
* @param ?boolean Whether the parameter is a POST parameter (NULL: undetermined)
* @return string The value of the parameter
*/
function __param($array,$name,$default,$integer=false,$posted=false)
{
if ((!isset($array[$name])) || (($integer) && ($array[$name]=='')))
{
if ($default!==false) return $default;
require_code('failure');
improperly_filled_in($name,$posted,$array);
}
$val=$array[$name];
if (is_array($val)) $val=implode(',',$val);
if (get_magic_quotes_gpc()) $val=stripslashes($val);
if (($posted) && ($GLOBALS['BOOTSTRAPPING']==0) && ($GLOBALS['MICRO_AJAX_BOOTUP']==0)) // Check against fields.xml
{
require_code('input_filter');
return check_posted_field($name,$val);
}
return $val;
}
/**
* Do a wildcard match by converting to a regular expression.
*
* @param string The haystack
* @param string The needle (a wildcard expression)
* @param boolean Whether full-coverance is required
* @return boolean Whether we have a match
*/
function simulated_wildcard_match($context,$word,$full_cover=false)
{
$rexp=str_replace('%','.*',str_replace('_','.',str_replace('\\?','.',str_replace('\\*','.*',preg_quote($word)))));
if ($full_cover) $rexp='^'.$rexp.'$';
return preg_match('#'.str_replace('#','\#',$rexp).'#i',$context)!=0;
}
/**
* This function is the integeric partner of either_param, as it returns the value as an integer.
* You should always use integer specified versions when inputting integers, for the added security that type validation allows. If the value is of the wrong type, it indicates a hack attempt and will be logged.
*
* @param ID_TEXT The name of the parameter to get
* @param ?mixed The default value to give the parameter if the parameter value is not defined or the empty string (NULL: allow missing parameter) (false: give error on missing parameter)
* @return ?integer The parameter value (NULL: not set, and NULL given as default)
*/
function either_param_integer($name,$default=false)
{
$ret=__param(array_merge($_POST,$_GET),$name,($default===false)?$default:(($default===NULL)?'':strval($default)),true,NULL); // $_REQUEST contains cookies too, so can't use
if (($default===NULL) && ($ret==='')) return NULL;
$ret=trim($ret);
if (!is_numeric($ret))
{
require_code('failure');
$ret=_param_invalid($name,$ret,true);
}
$reti=intval($ret);
if (($reti>2147483647) || ($reti<-2147483648))
{
require_code('failure');
_param_invalid($name,NULL,true);
}
return $reti;
}
/**
* This function is the integeric partner of post_param, as it returns the value as an integer.
*
* @param ID_TEXT The name of the parameter to get
* @param ?mixed The default value to give the parameter if the parameter value is not defined or the empty string (NULL: allow missing parameter) (false: give error on missing parameter)
* @return ?integer The parameter value (NULL: not set, and NULL given as default)
*/
function post_param_integer($name,$default=false)
{
$ret=__param($_POST,$name,($default===false)?$default:(($default===NULL)?'':strval($default)),true,true);
if (($default===NULL) && ($ret==='')) return NULL;
$ret=trim($ret);
if (!is_numeric($ret))
{
require_code('failure');
$ret=_param_invalid($name,$ret,true);
}
if ($ret=='0') return 0;
if ($ret=='1') return 1;
$reti=intval($ret);
$retf=floatval($reti);
if (($retf>2147483647.0) || ($retf<-2147483648.0))
{
if ($name!='security_image')
{
require_code('failure');
_param_invalid($name,NULL,true);
}
}
return $reti;
}
/**
* This function is the integeric partner of get_param, as it returns the value as an integer.
*
* @param ID_TEXT The name of the parameter to get
* @param ?mixed The default value to give the parameter if the parameter value is not defined or the empty string (NULL: allow missing parameter) (false: give error on missing parameter)
* @param boolean If a string is given, use the default parameter rather than giving an error (only use this if you are suffering from a parameter conflict situation between different parts of ocPortal)
* @return ?integer The parameter value (NULL: not set, and NULL given as default)
*/
function get_param_integer($name,$default=false,$not_string_ok=false)
{
$m_default=($default===false)?false:(isset($default)?(($default==0)?'0':strval($default)):'');
$ret=__param($_GET,$name,$m_default,true); // do not set $ret to mixed(), breaks bootstrapping
if ((!isset($default)) && ($ret==='')) return NULL;
$ret=trim($ret);
if (!is_numeric($ret))
{
if (substr($ret,-1)=='/') $ret=substr($ret,0,strlen($ret)-1);
if (!is_numeric($ret)) // Bizarre situation (bug in IIS?)
{
$matches=array();
if (preg_match('#^(\d+)\#[\w]*$#',$ret,$matches)!=0)
{
$ret=$matches[1];
} else
{
if ($not_string_ok) return $default;
require_code('failure');
$ret=_param_invalid($name,$ret,false);
}
}
}
if ($ret=='0') return 0;
if ($ret=='1') return 1;
$reti=intval($ret);
$retf=floatval($reti);
if (($retf>2147483647.0) || ($retf<-2147483648.0))
{
require_code('failure');
_param_invalid($name,NULL,false);
}
return $reti;
}
/**
* Make sure that lines are seperated by chr(10), with no chr(13)'s there at all. For Mac data, this will be a flip scenario. For Linux data this will be a null operation. For windows data this will be change from chr(13).chr(10) to just chr(10). For a realistic scenario, data could have originated on all kinds of platforms, with some editors converting, some situations being inter-platform, and general confusion. Don't make blind assumptions - use this function to clean data, then write clean code that only considers chr(10)'s.
*
* @param string The data to clean
* @param ?ID_TEXT The character set it should be in. We don't do any real conversions using this, only make sure that common problems with fed ISO-8859-1 data are resolved (NULL: output character set)
* @param boolean Whether we are cleaning for HTML rather than Comcode/plain-text
* @param boolean Whether the file is loaded from disk (less conversion needed)
* @return string The cleaned data
*/
function unixify_line_format($in,$desired_charset=NULL,$html=false,$from_disk=false)
{
if ($in=='') return $in;
if ($desired_charset===NULL) $desired_charset=get_charset();
$in=str_replace(array(chr(13).chr(10),'&#8298;',chr(13)),array(chr(10),'',chr(10)),$in); // &#8298; is very odd- seems to come from open office copy & paste
if (!$from_disk)
{
if ($desired_charset=='ISO-8859-1') // Fix up Windows ANSI characters
{
$in=str_replace($GLOBALS['BAD_WORD_CHARS'],$html?$GLOBALS['FIXED_WORD_CHARS_HTML']:$GLOBALS['FIXED_WORD_CHARS'],$in);
}
}
return $in;
}
/**
* Force a Javascript file to be cached (ordinarily we can rely on this to be automated by require_javascript/javascript_tempcode).
*
* @param string The javascript file required
* @param ?ID_TEXT The name of the theme (NULL: current theme)
* @param ?boolean Whether to minify (NULL: read from environment)
* @return string The path to the javascript file in the cache (blank: no file)
*/
function javascript_enforce($j,$theme=NULL,$minify=NULL)
{
if (get_param_integer('keep_textonly',0)==1) return '';
if ($minify===NULL)
$minify=(get_param_integer('keep_no_minify',0)==0);
global $SITE_INFO;
// Make sure the Javascript exists
if ($theme===NULL)
$theme=filter_naughty($GLOBALS['FORUM_DRIVER']->get_theme());
$dir=get_custom_file_base().'/themes/'.$theme.'/templates_cached/'.filter_naughty(user_lang());
if ((!isset($SITE_INFO['no_disk_sanity_checks'])) || ($SITE_INFO['no_disk_sanity_checks']=='0'))
{
if (!is_dir($dir))
{
if (@mkdir($dir,0777)===false)
{
warn_exit(do_lang_tempcode('WRITE_ERROR_DIRECTORY_REPAIR',escape_html($dir)));
}
fix_permissions($dir,0777);
sync_file($dir);
}
}
$js_cache_path=$dir.'/'.filter_naughty_harsh($j);
if (!$minify) $js_cache_path.='_non_minified';
if ((get_option('enable_https',true)=='1') && function_exists('is_page_https') && function_exists('get_zone_name') && ((tacit_https()) || is_page_https(get_zone_name(),get_page_name())))
$js_cache_path.='_ssl';
if (is_mobile()) $js_cache_path.='_mobile';
$js_cache_path.='.js';
global $CACHE_TEMPLATES;
$support_smart_decaching=(!isset($SITE_INFO['disable_smart_decaching'])) || ($SITE_INFO['disable_smart_decaching']=='0');
$is_cached=($CACHE_TEMPLATES || !running_script('index')/*must cache for non-index to stop getting blanked out in depended sub-script output generation and hence causing concurrency issues*/) && (@(filesize($js_cache_path)!=0)) && (!is_browser_decacheing()) && (!in_safe_mode());
if (($support_smart_decaching) || (!$is_cached))
{
$found=find_template_place(strtoupper($j),'',$theme,'.tpl','templates');
if ($found===NULL) return '';
$theme=$found[0];
$fullpath=get_custom_file_base().'/themes/'.$theme.$found[1].strtoupper($j).'.tpl';
if (!is_file($fullpath))
$fullpath=get_file_base().'/themes/'.$theme.$found[1].strtoupper($j).'.tpl';
$globals_custom=str_replace('default/templates/JAVASCRIPT.tpl',filter_naughty($GLOBALS['FORUM_DRIVER']->get_theme()).'/templates_custom/JAVASCRIPT_CUSTOM_GLOBALS.tpl',$fullpath);
}
if ((($support_smart_decaching) && ((@(filemtime($js_cache_path)<filemtime($fullpath)) && (@filemtime($fullpath)<time())) || (@filemtime(get_file_base().'/info.php')>@filemtime($js_cache_path)) || ((is_file($globals_custom)) && (@filemtime($globals_custom)>@filemtime($js_cache_path))))) || (!$is_cached))
{
require_code('css_and_js');
js_compile($j,$js_cache_path,$minify);
}
if (filesize($js_cache_path)==0) return '';
return $js_cache_path;
}
/**
* Get tempcode to tie in (to the HTML, in <head>) all the Javascript files that have been required.
*
* @param ?string Position to get Javascript for (NULL: all positions)
* @set NULL header footer
* @return tempcode The tempcode to tie in the Javascript files
*/
function javascript_tempcode($position=NULL)
{
global $JAVASCRIPTS,$JAVASCRIPT;
$js=new ocp_tempcode();
$minify=(get_param_integer('keep_no_minify',0)==0);
$https=((get_option('enable_https',true)=='1') && function_exists('is_page_https') && function_exists('get_zone_name') && ((tacit_https()) || is_page_https(get_zone_name(),get_page_name())));
$mobile=is_mobile();
// Special merge operation for staff. In truth it's to get a better score on Google Page Speed ;)
$to_merge=array('javascript_staff','javascript_button_occle','javascript_fractional_edit');
$good_to_merge=true;
foreach ($to_merge as $j)
if (!array_key_exists($j,$JAVASCRIPTS)) $good_to_merge=false;
if ($good_to_merge)
{
$j='javascript_staff___merged';
if (!$minify) $j.='_non_minified';
if ($https) $j.='_ssl';
if ($mobile) $j.='_mobile';
$theme=filter_naughty($GLOBALS['FORUM_DRIVER']->get_theme());
$dir=get_custom_file_base().'/themes/'.$theme.'/templates_cached/'.filter_naughty(user_lang());
$write_path=$dir.'/'.filter_naughty_harsh($j);
$write_path.='.js';
/*$rebuild=false; Performance hit
foreach ($to_merge as $j2)
{
$merge_from=javascript_enforce($j2);
if (filemtime($merge_from)==time()) $rebuild=true; // Hmm, just recalculated
}*/
if (!is_file($write_path)/* || $rebuild*/) // Merging algorithm
{
$data='';
foreach ($to_merge as $j2)
{
$merge_from=javascript_enforce($j2);
if (is_file($merge_from))
{
$data.=unixify_line_format(file_get_contents($merge_from,FILE_TEXT));
} else // race condition
{
$good_to_merge=false;
break;
}
}
if ($good_to_merge)
{
$myfile=@fopen($write_path,'wb') OR intelligent_write_error($write_path); // Intentionally wb to stop line ending conversions on Windows
fwrite($myfile,$data);
fclose($myfile);
fix_permissions($write_path,0777);
sync_file($write_path);
}
}
if ($good_to_merge)
{
if ($position!='header')
$js->attach(do_template('JAVASCRIPT_NEED',array('CODE'=>$j)));
}
}
// Our main loop
$bottom_ones=array('javascript_staff'=>1,'javascript_button_occle'=>1,'javascript_fractional_edit'=>1,'javascript_thumbnails'=>1,'javascript_button_realtime_rain'=>1);
foreach (array_keys($JAVASCRIPTS) as $j)
{
if (($good_to_merge) && (in_array($j,$to_merge))) continue;
if ($position!==NULL)
{
$bottom=(isset($bottom_ones[$j])); // TODO: progmattic way of saying this at point of calls
if (($position=='header') && ($bottom)) continue;
if (($position=='footer') && (!$bottom)) continue;
}
$temp=javascript_enforce($j);
if ($temp!='')
{
if (!$minify) $j.='_non_minified';
if ($https) $j.='_ssl';
if ($mobile) $j.='_mobile';
$js->attach(do_template('JAVASCRIPT_NEED',array('_GUID'=>'b5886d9dfc4d528b7e1b0cd6f0eb1670','CODE'=>$j)));
}
}
if (!is_null($JAVASCRIPT)) $js->attach($JAVASCRIPT);
return $js;
}
/**
* Make sure that the given javascript file is loaded up.
*
* @param ID_TEXT The javascript file required
*/
function require_javascript($javascript)
{
//if ((!array_key_exists('DONE_HEADER',$GLOBALS)) || (!$GLOBALS['DONE_HEADER']))
//{
if ($javascript=='javascript_forums_embed') // Has to be first
{
$GLOBALS['JAVASCRIPTS']=array_merge(array('javascript_forums_embed'=>1),$GLOBALS['JAVASCRIPTS']);
} else
{
$GLOBALS['JAVASCRIPTS'][$javascript]=1;
}
/*} else -- Won't work, as we can't sync with the output properly
{
$GLOBALS['JAVASCRIPTS'][$javascript]=1;
$file=javascript_enforce($javascript);
$temp=do_template('JAVASCRIPT_NEED_INLINE',array('_GUID'=>'a6c907e26c5a8dd8c65f1d36a1a674a9','CODE'=>file_get_contents($file,FILE_TEXT)));
$temp->evaluate_echo();
}*/
}
/**
* Force a CSS file to be cached.
*
* @param string The CSS file required
* @param ?ID_TEXT The name of the theme (NULL: current theme)
* @param ?boolean Whether to minify (NULL: read from environment)
* @return string The path to the CSS file in the cache (blank: no file)
*/
function css_enforce($c,$theme=NULL,$minify=NULL)
{
$text_only=(get_param_integer('keep_textonly',0)==1);
if ($text_only) $c.='_textonly';
if ($minify===NULL)
$minify=(get_param_integer('keep_no_minify',0)==0);
global $SITE_INFO;
// Make sure the CSS file exists
if ($theme===NULL)
$theme=@method_exists($GLOBALS['FORUM_DRIVER'],'get_theme')?$GLOBALS['FORUM_DRIVER']->get_theme():'default';
$active_theme=$theme;
$dir=get_custom_file_base().'/themes/'.$theme.'/templates_cached/'.filter_naughty(user_lang());
if ((!isset($SITE_INFO['no_disk_sanity_checks'])) || ($SITE_INFO['no_disk_sanity_checks']=='0'))
{
if (!is_dir($dir))
{
if (@mkdir($dir,0777)===false)
{
warn_exit(do_lang_tempcode('WRITE_ERROR_DIRECTORY_REPAIR',escape_html($dir)));
}
fix_permissions($dir,0777);
sync_file($dir);
}
}
$css_cache_path=$dir.'/'.filter_naughty_harsh($c);
if (!$minify) $css_cache_path.='_non_minified';
if ((get_option('enable_https',true)=='1') && function_exists('is_page_https') && function_exists('get_zone_name') && ((tacit_https()) || is_page_https(get_zone_name(),get_page_name())))
$css_cache_path.='_ssl';
if (is_mobile()) $css_cache_path.='_mobile';
$css_cache_path.='.css';
global $CACHE_TEMPLATES;
$support_smart_decaching=(!isset($SITE_INFO['disable_smart_decaching'])) || ($SITE_INFO['disable_smart_decaching']=='0');
$is_cached=($CACHE_TEMPLATES || !running_script('index')/*must cache for non-index to stop getting blanked out in depended sub-script output generation and hence causing concurrency issues*/) && (@(filesize($css_cache_path)!=0)) && (!is_browser_decacheing()) && (!in_safe_mode());
if (($support_smart_decaching) || (!$is_cached) || ($text_only))
{
$found=find_template_place($c,'',$theme,'.css','css');
if ($found===NULL) return '';
$theme=$found[0];
$fullpath=get_custom_file_base().'/themes/'.$theme.$found[1].$c.'.css';
if (!is_file($fullpath))
$fullpath=get_file_base().'/themes/'.$theme.$found[1].$c.'.css';
if (($text_only) && (!is_file($fullpath))) return '';
}
if (((!$is_cached) || (($support_smart_decaching) && (@(filemtime($css_cache_path)<filemtime($fullpath)) && (@filemtime($fullpath)<time())))))
{
require_code('css_and_js');
css_compile($active_theme,$theme,$c,$fullpath,$css_cache_path,$minify);
}
if (filesize($css_cache_path)==0) return '';
return $css_cache_path;
}
/**
* Get tempcode to tie in (to the HTML, in <head>) all the CSS files that have been required.
*
* @param boolean Force inline CSS
* @param boolean Only do global CSS
* @param ?string HTML context for which we filter (minimise) any CSS we spit out as inline (NULL: none)
* @param ?ID_TEXT The name of the theme (NULL: current theme)
* @return tempcode The tempcode to tie in the CSS files
*/
function css_tempcode($inline=false,$only_global=false,$context=NULL,$theme=NULL)
{
global $CSSS;
$seed='';
if (has_specific_permission(get_member(),'view_profiling_modes'))
{
$seed=get_param('keep_theme_seed','');
}
$text_only=(get_param_integer('keep_textonly',0)==1);
$minify=(get_param_integer('keep_no_minify',0)==0);
$https=((get_option('enable_https',true)=='1') && function_exists('is_page_https') && function_exists('get_zone_name') && ((tacit_https()) || is_page_https(get_zone_name(),get_page_name())));
$mobile=is_mobile();
$css=new ocp_tempcode();
$css_need_inline=new ocp_tempcode();
$css_to_do=$only_global?array('global','no_cache'):array_keys($CSSS);
foreach ($css_to_do as $c)
{
if ($seed!='')
{
$keep=symbol_tempcode('KEEP');
$css->attach(do_template('CSS_NEED_FULL',array('URL'=>find_script('themewizard').'?type=css&show='.$c.'.css'.$keep->evaluate()),user_lang(),false,NULL,'.tpl','templates',$theme));
}
elseif (($c=='no_cache') || ($inline))
{
if (!$text_only)
{
$_css=do_template($c,NULL,user_lang(),false,NULL,'.css','css',$theme);
$__css=$_css->evaluate();
if ($context!==NULL)
{
$__css=filter_css($__css,$context);
} else
{
$__css=str_replace('} ','}'.chr(10),preg_replace('#\s+#',' ',$__css));
}
if (trim($__css)!='')
$css_need_inline->attach(do_template('CSS_NEED_INLINE',array('_GUID'=>'f5b225e080c633ffa033ec5af5aec866','CSS'=>$__css),user_lang(),false,NULL,'.tpl','templates',$theme));
}
} else
{
$temp=css_enforce($c,$theme);
if (!$minify) $c.='_non_minified';
if ($https) $c.='_ssl';
if ($mobile) $c.='_mobile';
if ($temp!='')
$css->attach(do_template('CSS_NEED',array('_GUID'=>'ed35fac857214000f69a1551cd483096','CODE'=>$c),user_lang(),false,NULL,'.tpl','templates',$theme));
}
}
$css_need_inline->attach($css);
return $css_need_inline;
}
/**
* Make sure that the given CSS file is loaded up.
*
* @param ID_TEXT The CSS file required
*/
function require_css($css)
{
// if ((!array_key_exists('DONE_HEADER',$GLOBALS)) || (!$GLOBALS['DONE_HEADER']))
{
$GLOBALS['CSSS'][$css]=1;
}/* else -- Won't work, as we can't sync with the output properly
{
$GLOBALS['CSSS'][$css]=1;
$file=css_enforce($css);
$temp=do_template('CSS_NEED_INLINE',array('_GUID'=>'b6c907e26c5a8dd8c65f1d36a1a674a9','CSS'=>file_get_contents($file,FILE_TEXT)));
$temp->evaluate_echo();
}*/
}
/**
* Provides a hook for file synchronisation between mirrored servers. Called after any file creation, deletion or edit.
*
* @param PATH File/directory name to sync on (full path)
*/
function sync_file($filename)
{
global $FILE_BASE,$_MODIFIED_FILES,$_CREATED_FILES;
static $has_sync_script=NULL;
if (is_null($has_sync_script)) $has_sync_script=is_file($FILE_BASE.'/data_custom/sync_script.php');
if ((!$has_sync_script) && (!isset($_MODIFIED_FILES))) return;
if (substr($filename,0,strlen($FILE_BASE)+1)==$FILE_BASE.'/')
{
$filename=substr($filename,strlen($FILE_BASE)+1);
}
if ($has_sync_script)
{
require_once($FILE_BASE.'/data_custom/sync_script.php');
if (function_exists('master__sync_file')) master__sync_file($filename);
}
if (isset($_MODIFIED_FILES))
foreach ($_MODIFIED_FILES as $i=>$x)
if (($x==$FILE_BASE.'/'.$filename) || ($x==$filename)) unset($_MODIFIED_FILES[$i]);
if (isset($_CREATED_FILES))
foreach ($_CREATED_FILES as $i=>$x)
if (($x==$FILE_BASE.'/'.$filename) || ($x==$filename)) unset($_CREATED_FILES[$i]);
}
/**
* Provides a hook for file-move synchronisation between mirrored servers. Called after any rename or move action.
*
* @param PATH File/directory name to move from (may be full or relative path)
* @param PATH File/directory name to move to (may be full or relative path)
*/
function sync_file_move($old,$new)
{
require_code('files2');
_sync_file_move($old,$new);
}
/**
* Performs lots of magic to make sure data encodings are converted correctly. Input, and output too (as often stores internally in UTF or performs automatic dynamic conversions from internal to external charsets).
* Roll on PHP6 that has a true internal UTF string model. For now, anyone who uses UTF will get some (albeit minor) imperfections from PHP's manipulations of the strings.
*
* @param boolean Whether we know we are working in UTF-8. This is the case for AJAX calls.
*/
function convert_data_encodings($known_utf8=false)
{
global $VALID_ENCODING,$CONVERTED_ENCODING;
$VALID_ENCODING=true;
if ($CONVERTED_ENCODING) return; // Already done it
if ((array_key_exists('KNOWN_UTF8',$GLOBALS)) && ($GLOBALS['KNOWN_UTF8'])) $known_utf8=true;
$charset=get_charset();
$done_something=false;
// Conversion of parameters that might be in the wrong character encoding (e.g. Javascript uses UTF to make requests regardless of document encoding, so the stuff needs converting)
// If we don't have any PHP extensions (mbstring etc) that can perform the detection/conversion, our code will take this into account and use utf8_decode at points where it knows that it's being communicated with by Javascript.
if (@strlen(ini_get('unicode.runtime_encoding'))>0)
{
@ini_set('default_charset',$charset);
@ini_set('unicode.runtime_encoding',$charset);
@ini_set('unicode.output_encoding',$charset);
@ini_set('unicode.semantics','1');
$done_something=true;
}
elseif (($known_utf8) && ((version_compare(phpversion(),'4.3.0')>=0) || (strtolower($charset)=='iso-8859-1')) && /*test method works...*/(will_be_unicode_neutered(serialize($_GET).serialize($_POST))) && (in_array(strtolower($charset),array('iso-8859-1','iso-8859-15','koi8-r','big5','gb2312','big5-hkscs','shift_jis','euc-jp')))) // Preferred as it will sub entities where there's no equivalent character
{
require_code('character_sets');
do_environment_utf8_conversion($charset);
$done_something=true;
}
elseif ((function_exists('iconv_set_encoding')) && (get_value('disable_iconv')!=='1'))
{
$encoding=$known_utf8?'UTF-8':$charset;
if (@iconv_set_encoding('input_encoding',$encoding))
{
iconv_set_encoding('output_encoding',$charset);
iconv_set_encoding('internal_encoding',$charset);
} else
{
$VALID_ENCODING=false;
}
$done_something=true;
}
elseif ((function_exists('mb_convert_encoding')) && (get_value('disable_mbstring')!=='1'))
{
if (function_exists('mb_list_encodings'))
{
$VALID_ENCODING=in_array(strtolower($charset),array_map('strtolower',mb_list_encodings()));
} else $VALID_ENCODING=true;
if ($VALID_ENCODING)
{
$encoding=$known_utf8?'UTF-8':'';
if ((function_exists('mb_http_input')) && ($encoding==''))
{
if (count($_POST)!=0)
{
$encoding=mb_http_input('P');
if ((!is_string($encoding)) || ($encoding=='pass')) $encoding='';
}
}
if ((function_exists('mb_http_input')) && ($encoding==''))
{
$encoding=mb_http_input('G');
if ((!is_string($encoding)) || ($encoding=='pass')) $encoding='';
if ((function_exists('mb_detect_encoding')) && ($encoding=='') && (ocp_srv('REQUEST_URI')!=''))
{
$encoding=mb_detect_encoding(urldecode(ocp_srv('REQUEST_URI')),$charset.',UTF-8,ISO-8859-1');
if ((!is_string($encoding)) || ($encoding=='pass')) $encoding='';
}
}
if ($encoding!='')
{
foreach ($_GET as $key=>$val)
{
if (is_string($val))
{
$_GET[$key]=mb_convert_encoding($val,$charset,$encoding);
} elseif (is_array($val))
{
foreach ($val as $i=>$v)
{
$_GET[$key][$i]=mb_convert_encoding($v,$charset,$encoding);
}
}
}
foreach ($_POST as $key=>$val)
{
if (is_string($val))
{
$_POST[$key]=mb_convert_encoding($val,$charset,$encoding);
} elseif (is_array($val))
{
foreach ($val as $i=>$v)
{
$_POST[$key][$i]=mb_convert_encoding($v,$charset,$encoding);
}
}
}
}
if (function_exists('mb_http_output')) mb_http_output($charset);
}
$done_something=true;
}
elseif (($known_utf8) && (strtolower($charset)!='utf-8') && (strtolower($charset)!='utf8')) // This is super-easy, but it's imperfect as it assumes ISO-8859-1 -- hence our worst option
{
require_code('character_sets');
do_simple_environment_utf8_conversion();
$done_something=true;
}
if ($done_something) $CONVERTED_ENCODING=true;
}
/**
* Guard for entity_utf8_decode. Checks that the data can be stripped so there is no unicode left. Either the htmlentities function must convert mechanically to entity-characters or all higher ascii character codes (which are actually unicode control codes in a unicode interpretation) that are used happen to be linked to named entities.
*
* @param string Data to check.
* @return boolean Whether we are good to execute entity_utf8_decode.
*/
function will_be_unicode_neutered($data)
{
$data=@htmlentities($data,ENT_COMPAT,'UTF-8');
if ($data=='') return false; // Some servers fail at the first step
for ($i=0;$i<strlen($data);$i++)
{
if (ord($data[$i])>0x7F) return false;
}
return true;
}
Jump to Line
Something went wrong with that request. Please try again.