"._COM_SEF_CHK_PERMS);
if (is_readable($sef_config_class)) require_once($sef_config_class);
else die(_COM_SEF_NOREAD."( $sef_config_class )
"._COM_SEF_CHK_PERMS);
// V 1.3.1 allow internal redirect for outbound links
$shtask = mosGetParam($_GET,'shtask');
$shtarget = mosGetParam($_GET, 'shtarget');
if ($shtask == 'redirect' && !empty($shtarget)) {
shRedirect($shtarget, '', '303');
}
// V 1.2.4.t include language file
shIncludeLanguageFile();
$sefConfig = new SEFConfig();
_log(str_repeat('-', 69));
_log('New request : '.(empty($_SERVER['REQUEST_URI']) ? '': $_SERVER['REQUEST_URI']));
_log(str_repeat('-', 69));
_log("\n".'$_SERVER', $_SERVER);
// do security checks
shDoSecurityChecks();
shCleanUpSecLogFiles(); // we don't really want to do this at each page load
if ($sefConfig->Enabled) {
$sef404 = sh404SEF_FRONT_ABS_PATH.'sef404.php';
if (is_readable($sef404)) {
global $sefConfig;
// V 1.2.4.r special processing for SEF without mod_rewrite
$shSaveRequestURI = $_SERVER['REQUEST_URI']; // V x
// V 1.2.4.j 2007-04-16 use own config secure url to fix ssl switch management
// V 1.2.4.t moved here from sef404.php
$http_host = explode(':', $_SERVER['HTTP_HOST'] );
if( (!empty( $_SERVER['HTTPS'] )
&& strtolower( $_SERVER['HTTPS'] ) != 'off' || isset( $http_host[1] ) && $http_host[1] == 443)) {
$shTemp = str_replace( 'http://', '', $GLOBALS['mosConfig_live_site']);
$shTemp = str_replace( 'https://', '', $shTemp); // some sites may be running https !
$shHttpsSave = empty( $sefConfig->shConfig_live_secure_site) ? 'https://'. $shTemp
: $sefConfig->shConfig_live_secure_site;
_log('Request in SSL mode'.$shHttpsSave);
} else
$shHttpsSave = null;
if (!empty($shHttpsSave))
$GLOBALS['mosConfig_live_site'] = $shHttpsSave;
if (!empty($sefConfig->shRewriteMode)
&& strpos( $_SERVER['REQUEST_URI'], $sefConfig->shRewriteStrings[$sefConfig->shRewriteMode]) !== false ) {
$bits = explode($sefConfig->shRewriteStrings[$sefConfig->shRewriteMode], $_SERVER['REQUEST_URI']);
$base = (isset($bits[0]) ? $bits[0] : '').'/';
$index = 'index.php';
$base = str_replace( '/'.$index, '', $base);
if (isset($bits[1]))
$_SERVER['REQUEST_URI'] = $base.$bits[1];
else
$_SERVER['REQUEST_URI'] = $base;
$_SERVER['PHP_SELF'] = $base.$index;
} else {
$index = str_replace($GLOBALS['mosConfig_live_site'],"",$_SERVER['PHP_SELF']);
$base = dirname($index);
if ($base =="\\") $base = "/";
$base .= (($base == "/") ? "" :"/");
$index = basename($index);
}
$URI = array();
if (isset ($_SERVER['REQUEST_URI'])) {
//strip out the base
$REQUEST = str_replace($GLOBALS['mosConfig_live_site'],'',$_SERVER['REQUEST_URI']);
if (!empty($shHttpsSave))
$REQUEST = str_replace($shHttpsSave,'',$_SERVER['REQUEST_URI']);
$REQUEST = preg_replace('/^'.preg_quote($base,'/').'/','',$REQUEST);
// V 1.2.4. preserve ? / is it a good idea ?
$URI = new sh_Net_URL((empty($shHttpsSave)?$GLOBALS['mosConfig_live_site']:$shHttpsSave).'/'.ltrim($REQUEST,'/'));
}else{
$QUERY_STRING = isset($_SERVER['QUERY_STRING']) ? '?'.$_SERVER['QUERY_STRING'] : '';
$URI = new sh_Net_URL($index.$QUERY_STRING);
}
// V 1.2.4.s
// TODO Redirect any host to $mosConfig_live_site - in case same site is accessed through synonyms domains
if ($sefConfig->shAutoRedirectWww && empty($_POST)) { // mode = false do nothing, true = auto-redirect
// Auto redirect will do a 301 from www to non-www if mosConfig_live_site does not have www
// and from non-www to www if mosConfig_live_site has www
$shTemp = explode('/', str_replace($URI->protocol.'://', '', $GLOBALS['mosConfig_live_site']) );
$shLiveSite = strtolower($shTemp[0]);
if ($shLiveSite != strtolower($_SERVER['HTTP_HOST'].(!sh404SEF_USE_NON_STANDARD_PORT || empty($URI->port) ? '' : ':'.$URI->port))) {
if (substr( $shLiveSite, 0, 4) == 'www.'
&& strtolower('www.'.$_SERVER['HTTP_HOST'].(!sh404SEF_USE_NON_STANDARD_PORT || empty($URI->port) ? '' : ':'.$URI->port)) == $shLiveSite) {
_log('Redirecting from non www to wwww');
shRedirect( $URI->protocol.'://www.'.$_SERVER['HTTP_HOST'].(!sh404SEF_USE_NON_STANDARD_PORT || empty($URI->port) ? '' : ':'.$URI->port).$shSaveRequestURI);
}
if (substr( $shLiveSite, 0, 4) != 'www.'
&& strtolower(substr( $_SERVER['HTTP_HOST'].(!sh404SEF_USE_NON_STANDARD_PORT || empty($URI->port) ? '' : ':'.$URI->port), 4)) == $shLiveSite) {
_log('Redirecting from www to non wwww');
shRedirect($URI->protocol.'://'.str_replace('www.', '', $_SERVER['HTTP_HOST'].(!sh404SEF_USE_NON_STANDARD_PORT || empty($URI->port) ? '' : ':'.$URI->port)).$shSaveRequestURI);
}
}
}
//Make sure host name matches our config, we need this later.
if (strpos($GLOBALS['mosConfig_live_site'],$URI->host) === false) {
_log('Redirecting to home : host don\'t match our config');
shRedirect($GLOBALS['mosConfig_live_site']);
} else {
$shCurrentPageURL = $URI->protocol.'://'.$URI->host.(!sh404SEF_USE_NON_STANDARD_PORT || empty($URI->port) ? '' : ':'.$URI->port).$URI->path;
_log('Current page URL : '.$shCurrentPageURL);
$shCurrentPagePath = str_replace( $GLOBALS['mosConfig_live_site'], '', $shCurrentPageURL);
_log('Current page path : '.$shCurrentPagePath);
// V 1.2.4.s PR2 : workaround for Virtuemart cookie check issue
// see second part in sef404.php
if (shIsSearchEngine()) { // simulate doing successfull cookie check
_log('Setting VMCHECK cookie for search engine');
$_COOKIE['VMCHECK'] = 'OK';
$_REQUEST['vmcchk'] = 1;
}
include_once($sef404);
}
} else
die(_COM_SEF_NOREAD."( $sef404 )
"._COM_SEF_CHK_PERMS);
} else{
$mambo_sef = sh404SEF_ABS_PATH.'includes/sef.php';
if (is_readable($mambo_sef)) include($mambo_sef);
else {
die(_COM_SEF_NOREAD."( $mambo_sef )
"._COM_SEF_CHK_PERMS);
}
}
} else{
function sefRelToAbs( $string ) {
return $string;
}
}
function shIsSearchEngine() { // return true if user agant is a search engine
static $isSearchEngine = null;
static $searchEnginesAgents = array(
'B-l-i-t-z-B-O-T'
,'Baiduspider'
,'BlitzBot'
,'btbot'
,'DiamondBot'
,'Exabot'
,'FAST Enterprise Crawler'
,'FAST-WebCrawler/'
,'g2Crawler'
,'genieBot'
,'Gigabot'
,'Girafabot'
,'Googlebot'
,'ia_archiver'
,'ichiro'
,'Mediapartners-Google'
,'Mnogosearch'
,'msnbot'
,'MSRBOT'
,'Nusearch Spider'
,'SearchSight'
,'Seekbot'
,'sogou spider'
,'Speedy Spider'
,'Ask Jeeves/Teoma'
,'VoilaBot'
,'Yahoo!'
,'Slurp'
,'YahooSeeker'
);
//return true;
if (!is_null ($isSearchEngine)) {
return $isSearchEngine;
}
else {
$isSearchEngine = false;
$useragent = empty($_SERVER['HTTP_USER_AGENT']) ? '' : strtolower($_SERVER['HTTP_USER_AGENT']);
if (!empty($useragent))
foreach ($searchEnginesAgents as $searchEnginesAgent)
if (strpos($useragent, strtolower($searchEnginesAgent)) !== false ) {
$isSearchEngine = true;
return true;
}
return $isSearchEngine;
}
}
// V x : performs various security checks before allowing to go any further
function shDoSecurityChecks( $query = '', $fullCheck = true) {
global $sefConfig;
if (!$sefConfig->shSecEnableSecurity) return '';
$shQuery = empty($query) ? urldecode( $_SERVER['QUERY_STRING'])
: urldecode($query) ;
$shQuery = str_replace('&', '&', $shQuery);
$ip = empty($_SERVER['REMOTE_ADDR']) ? '' : $_SERVER['REMOTE_ADDR'];
$uAgent = empty($_SERVER['HTTP_USER_AGENT']) ? '' : $_SERVER['HTTP_USER_AGENT'];
// ip White/Black listing
$shWhiteListedIp = shCheckIPList($ip, $sefConfig->ipWhiteList);
if (!$shWhiteListedIp)
if (shCheckIPList($ip, $sefConfig->ipBlackList)) shDoRestrictedAccess('Blacklisted IP');
if (!$shWhiteListedIp && $fullCheck)
shDoAntiFloodCheck($ip);
// bad content in query string
$c = shCheckConfigVars($shQuery);
if ($c) shDoRestrictedAccess($c.' in URL');
$c = shCheckBase64($shQuery);
if ($c) shDoRestrictedAccess($c.' in URL');
$c = shCheckScripts($shQuery);
if ($c) shDoRestrictedAccess($c.' in URL');
$c = shCheckStandardVars($_GET);
if ($c) shDoRestrictedAccess($c.' in URL');
$c = shCheckImgTxtCmd($shQuery); // V x
if ($c) shDoRestrictedAccess($c.' in URL');
// UserAgent White/Black listing
if (!shCheckUAgentList($uAgent, $sefConfig->uAgentWhiteList))
if (shCheckUAgentList($uAgent, $sefConfig->uAgentBlackList)) shDoRestrictedAccess('BlackListed user agent');
if (!$fullCheck) return; // don't check POST and/or Honey pot if second check
// check POST variables
if ($sefConfig->shSecCheckPOSTData) {
foreach($_POST as $key=>$value) {
$c = shCheckConfigVars($key.'='.$value);
if ($c) shDoRestrictedAccess($c.' in POST');
$c = shCheckBase64($key.'='.$value);
if ($c) shDoRestrictedAccess($c.' in POST');
$c = shCheckScripts($key.'='.$value);
if ($c) shDoRestrictedAccess($c.' in POST');
$c = shCheckStandardVars($_POST);
if ($c) shDoRestrictedAccess($c.' in POST');
$c = shCheckImgTxtCmd($key.'='.$value); // V x
if ($c) shDoRestrictedAccess($c.' in POST');
}
}
// do Project Honey Pot check
if (!$shWhiteListedIp && $sefConfig->shSecCheckHoneyPot)
shDoHoneyPotCheck($ip);
}
function shSendEmailToAdmin($logData) {
if (!sh404SEF_SEC_MAIL_ATTACKS_TO_ADMIN) return;
global $mosConfig_sitename, $mosConfig_live_site, $mosConfig_mailfrom, $mosConfig_fromname;
$subject = str_replace( '%sh404SEF_404_SITE_NAME%', $mosConfig_sitename, sh404SEF_SEC_EMAIL_TO_ADMIN_SUBJECT);
$details = array(
' Date',
"\n".' Time',
"\n".' Cause',
"\n".' IP',
"\n".' Name',
"\n".' User agent',
"\n"."\n".' Request method',
"\n".' Request URI',
"\n".' Comment');
$items = explode("\t", $logData);
$count = 0;
$detailText = '';
foreach ($details as $detail) {
$detailText .= $detail . ' :: ' . trim($items[$count++]);
}
$body = str_replace( '%sh404SEF_404_SITE_URL%',$mosConfig_live_site , sh404SEF_SEC_EMAIL_TO_ADMIN_BODY);
$body = str_replace( '%sh404SEF_404_ATTACK_DETAILS%', $detailText, $body);
if (!defined('_ISO')) define('_ISO', 'charset=iso-8859-1');
mosMail( $mosConfig_mailfrom, $mosConfig_fromname, $mosConfig_mailfrom, $subject, $body);
}
function shLogToSecFile($logData) {
$shNum = 12*(intval(date('Y')) - 2000)+intval(date('m')); // number current month
$shFileName = sh404SEF_ADMIN_ABS_PATH.'logs/'.date('Y').'-'.date('m').'-'.'sh404SEF_security_log.'.$shNum.'.txt';
$fileIsThere = file_exists($shFileName);
if (!$fileIsThere) { // create file
$fileHeader = "Date\tTime\tCause\tIP\tName\tUser agent\tRequest method\tRequest URI\tComment\n";
} else $fileHeader = '';
if (!$fileIsThere || ($fileIsThere && is_writable($shFileName))) {
$logFile=fopen( $shFileName,'ab');
if ($logFile) {
if (!empty($fileHeader))
fWrite( $logFile, $fileHeader);
fWrite( $logFile, $logData);
fClose( $logFile);
}
}
}
function shCleanUpSecLogFiles(){ // delete security log files older than param
global $sefConfig;
if (mt_rand(1, SH404SEF_PAGES_TO_CLEAN_LOGS) != 1) return; // probability = 1/SH404SEF_PAGES_TO_CLEAN_LOGS
$curMonth = 12*(intval(date('Y')) - 2000)+intval(date('m'));
if ($sefConfig->shSecLogAttacks) {
if ($handle = opendir(sh404SEF_ADMIN_ABS_PATH.'logs/')) {
while (false !== ($file = readdir($handle))) {
$matches = array();
if ($file != '.' && $file != '..' &&preg_match('/\.[0-9]*\./', $file, $matches)) {
$fileNum = trim($matches[0], '.');
if ($curMonth-$fileNum > $sefConfig->monthsToKeepLogs) {
@unlink(sh404SEF_ADMIN_ABS_PATH.'logs/'.$file);
_log('Erasing security log file : '.$file);
}
}
}
closedir($handle);
}
}
}
function shDoRestrictedAccess( $causeText, $comment = '', $displayEntrance = false) {
global $sefConfig;
if ($sefConfig->shSecLogAttacks) { // log what's happening
$sep = "\t";
$logData = date('Y-m-d').$sep.date('H:i:s').$sep.$causeText.$sep.$_SERVER['REMOTE_ADDR'].$sep;
$logData .= getHostByAddr( $_SERVER['REMOTE_ADDR']).$sep;
$logData .= $_SERVER['HTTP_USER_AGENT'].$sep.$_SERVER['REQUEST_METHOD'].$sep.$_SERVER['REQUEST_URI'].$sep.$comment;
$logData .="\n";
shLogToSecFile ($logData);
}
// V x : we can possibly send email to site admin, but not log
shSendEmailToAdmin($logData);
// actually restrict access
if (!headers_sent()) {
header('HTTP/1.0 403 FORBIDDEN');
}
echo '
shSecSmellyPotText; ?>>>
('.$causeText.')'; } die(); } function shCheckConfigVars( $query) { if (empty($query)) return ''; if (preg_match( '/mosConfig_[a-zA-Z_]{1,21}=/i', $query)) return 'mosConfig_var'; else return ''; } function shCheckBase64( $query) { if (empty($query)) return ''; if (preg_match( '/base64_encode.*\(.*\)/i', $query)) return 'Base 64 encoded data'; else return ''; } function shCheckScripts( $query) { if (empty($query)) return ''; if (preg_match( '/(\<).*script.*(\>)/i', $query)) return '