$long_execution_threshold || $totaltime > $long_execution_notify_secs) { $flag = 1; // flag will be used to bold one line item, and then it'll be reset. $show_report = 1; // this will make the report show. won't be reset. } $timereport .= $totaltime.' '.$location.'
'; // 11/2/16: We really only want to start building this at the point of the first long-execution issue. but for temporary deep bug checking, we are always building this report, for everybody. if ($flag || $force) { $thetime = ''.number_format($time_since_last_invokation, 3).' ('.number_format($totaltime, 3).'s)   '; if ($time_since_last_invokation > 1) { $thetime = ''.$thetime.''; $location = ''.$location.''; } elseif ($time_since_last_invokation > .1) { $thetime = ''.$thetime.''; $location = ''.$location.''; } $thereport[] = $thetime; $thereport[] = $location; } $last_mtime = $mtime; // so we can remembr how long between trips to this function, through global() if ($show_report && $thereport) { $report = ''; for ($timecheck_i = 0; $timecheck_i < count($thereport); $timecheck_i += 2) $report .= ''; $report .= '
'.$thereport[$timecheck_i].''.$thereport[$timecheck_i + 1].'
'; if ($force == 2) return $timereport; else return $report; } return ''; } function addslashes_recursive($array) { // Figure out funky quotes by their Unicode Decimal Code, using chr() and replace them with regurlur ass apostrophes. foreach ($array as $key => $val) { if (is_array($val)) $array[$key] = addslashes_recursive($val); else { if (is_string($val) && $val !== '') { $t = preg_replace( '/[\x{2018}\x{2019}\x{201A}\x{201B}\x{2032}\x{2035}\x{02BC}\x{02B9}\x{FF07}\x{00B4}`]/u', "'", $val ); $val = ($t === null) ? $val : $t; $val = str_replace(array(chr(145), chr(146), chr(180)), "'", $val); } $val = str_replace('\\\\', '\\', $val); $val = stripslashes($val); // Get rid of any ways they could be trying to add a backslash for sql injection. $array[$key] = addcslashes($val, "'"); // urldecode($val) // 1/18/16: Took out the decoding because it was messing with the propagation of our url variables that were not supposed to be decoded! } } unset($val); return $array; } // if (!get_magic_quotes_gpc()) { if (is_array($_POST)) { $_POST = addslashes_recursive($_POST); extract($_POST); } if (is_array($_GET)) { $_GET = addslashes_recursive($_GET); extract($_GET); } if (is_array($_FILES)) { $_FILES = addslashes_recursive($_FILES); extract($_FILES); } if (is_array($_COOKIE)) { $_COOKIE = addslashes_recursive($_COOKIE); extract($_COOKIE); } // } timecheck('handler after extract', 1); if (!defined('ROOT_DIR')) { require_once("ready.html"); require_once(ACCOUNT_DIR.'config.html'); } timecheck('handler after ready/config'); function is_stealth_domain() { return (STEALTH_DOMAINS && in_array($_SERVER["HTTP_HOST"], STEALTH_DOMAINS)); } if ($staging_mode) { // temporarily allow for any IP because my IP is hopping around. ini_set("include_path", ROOT_DIR.'staging/'); ini_set("display_errors",1); // error_reporting(E_ALL & ~E_NOTICE); error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING & ~E_DEPRECATED & ~E_USER_DEPRECATED); } else { if (isset(OWNER_IPS[$_SERVER['REMOTE_ADDR']])) { ini_set("display_errors", 1); // error_reporting(E_ALL & ~E_NOTICE); error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING & ~E_DEPRECATED & ~E_USER_DEPRECATED); if ($staging_mode) { ini_set("include_path", ROOT_DIR.'staging/'); $staging_mode = 1; } else { ini_set("include_path", ROOT_DIR); $staging_mode = 0; } } else { error_reporting(E_ERROR | E_PARSE); ini_set("display_errors", 0); $staging_mode = 0; ini_set("include_path", ROOT_DIR); } } timecheck('handler before functions_essential.html'); require_once("functions_essential.html"); timecheck('handler after functions_essential.html'); function myErrorHandler($severity, $message, $file, $line) { if (error_reporting() & $severity) { $backtrace = debug_backtrace(); error_log("Fatal error occurred yall: $message in $file on line $line\n\n{$backtrace[2]['file']} line {$backtrace[2]['line']} ..... {$backtrace[1]['file']} line {$backtrace[1]['line']} ..... {$backtrace[0]['file']} {$backtrace[0]['line']}"); } return false; } // Set the custom error handler for fatal errors set_error_handler('myErrorHandler', E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR); // Still won't catch syntax errors because this only catches errors that happened once script started running. timecheck("about to extract globals"); chdir(ROOT_DIR); // this is where the site will assume all the includes and everything will come from! // Why do this... we already did at the top. extract($GLOBALS); extract($_SERVER); extract($_REQUEST); extract($_FILES); extract($_POST); timecheck('extracted globalz'); // private allows the users' browser to cache pages. nocache means they'll be forced to reload e.g. when they hit back button (bad for speed and bandwidth!) session_cache_limiter('private'); session_cache_expire(0); // php tacks session.cache_expire onto the private limiter, and its default of 180 minutes was telling browsers our pages were good for 3 hours without asking us again. 0 gives max-age=0 instead, so they revalidate. Back button stays fast either way, since only the no-store that nocache sends would kill the bfcache in chrome. if (preg_match("/^www\./",$_SERVER["HTTP_HOST"])) { $destination = 'http'.(isset($_SERVER["HTTPS"]) ? 's':'').'://'.str_replace('www.','',$_SERVER["HTTP_HOST"]).$_SERVER["REQUEST_URI"]; header("location: $destination"); exit; } IF (SITE_TEMPORARILY_DOWN) { require_once("functions_utilities.html"); sucky_error(); } require_once("db_connect.html"); // we just always connect, cuz we'll always need a DB connection on every page anyway. timecheck('handler after db_connect'); $host_array = explode('.', $_SERVER["HTTP_HOST"]); $subnumber = ((is_array($host_array)) ? count($host_array) : 0); // we go by how many dots between the words. if (strstr($_SERVER["HTTP_HOST"], '.co.uk')) { // for certain domains, we have two dots, so we have to conflate the top-level domain into a single array element. Ex: site.co.uk or test.co.uk $top_level_position = $subnumber - 2; // this is where the .com would normally be. the next slot over (-1) is where our .uk will be.... $secondary_top_level_position = $subnumber - 1; $host_array[$top_level_position] = $host_array[$top_level_position] .'.'. $host_array[$secondary_top_level_position]; // take the "co" and add the 'uk' into its array position. unset($host_array[$secondary_top_level_position]); // kill the last element. $subnumber--; // we really have fewer segments than first counted. } if ($subnumber > 1 && !is_stealth_domain()) { // If we are on a subdomain name, check that it's not one of our hardcoded ones from another site. if ($subnumber > 2) { // if two dots in domain name, we are in a subdomain!! Yay! But our variables have to still look like we are not in one. if ($host_array[0] == 'fetish') { // && isset(OWNER_IPS[$_SERVER['REMOTE_ADDR']]) $_SERVER["HTTP_HOST"] = $host_array[0].'.'.$host_array[1].'.'.$host_array[2]; $_SERVER["HTTP_SUBDOMAIN"] = ''; } else { // Make our test_blahblah url's look like test.blahblah, since our wildcard domain wont' work for subsubdomains. if (preg_match("/^test_/", $host_array[0])) { $host_array[0] = str_replace("test_", "", $host_array[0]); // Take off our test_ so that the domain itself can be processed normally. $_SERVER["HTTP_SUBSUBDOMAIN"] = 'test'; // So that we can treat this as if it had a "test" sub-subdomain! array_unshift($host_array, 'test'); // add "test" onto our host array, just as if we had added "test." onto the beginning of our URL like a sub-subdomain. $subnumber++; } if ($subnumber == 3) { $_SERVER["HTTP_HOST"] = $host_array[1].'.'.$host_array[2]; $_SERVER["HTTP_SUBDOMAIN"] = $host_array[0]; } else { // we have 4. sub-sub domains! $_SERVER["HTTP_HOST"] = $host_array[2].'.'.$host_array[3]; $_SERVER["HTTP_SUBDOMAIN"] = $host_array[1]; $_SERVER["HTTP_SUBSUBDOMAIN"] = $host_array[0]; // logthis('SUBSUBDOMAIN!!! '. ' '.$host_array[0].'.'.$host_array[1].'.'.$host_array[2].'.'.$host_array[3].' HTTP_REFERER '.$HTTP_REFERER.' '.$REMOTE_ADDR, '', 1); } if ($_SERVER["HTTP_SUBDOMAIN"] != 'test') $we_are_external = 1; } } // See which system site this subdomain is associated with and make that the new $_SERVER["HTTP_HOST"]. If none to use as replacement, let $_SERVER["HTTP_HOST"] remain at the current one. if (@include('media/cache/sub_list.txt')) { if ($_SERVER["HTTP_SUBDOMAIN"] && !empty($sub_list[$_SERVER["HTTP_SUBDOMAIN"]])) { // logthis('HTTP_SUBDOMAIN '. $_SERVER["HTTP_SUBDOMAIN"], '', 1); $_SERVER["HTTP_HOST"] = $sub_list[$_SERVER["HTTP_SUBDOMAIN"]]; // // It's how we identify our system site throughout our scripts. } unset($sub_list); // else logthis('not on sub_list: '. $_SERVER["HTTP_SUBDOMAIN"], '', 1); } } if ($_SERVER["HTTP_HOST"] == 'dirtiestsiteintheworld.com' || $_SERVER["HTTP_HOST"] == 'thedirtiestsiteintheworld.com' || $_SERVER["HTTP_HOST"] == 'pornreality.com') { // now that we have a host, bounce them if it's a bounceable one. // 2/5/23: Took this off. Just make it redirect to umd.net. if (0 && isset(OWNER_IPS[$_SERVER['REMOTE_ADDR']])) { $_SERVER["REAL_HTTP_HOST"] = $_SERVER["HTTP_HOST"]; // Still need to remember this, for cookie purposes only. Cookies have to match the domainname. $_SERVER["HTTP_HOST"] = 'umd.net'; $_SERVER["SERVER_NAME"] = 'umd.net'; } else { // logthis("bouncing back to umd.net! $_SERVER[HTTP_HOST]", '', 1, '', 1); header("location: //umd.net"); exit; } } else $_SERVER["REAL_HTTP_HOST"] = ''; if (!is_stealth_domain() && $_SERVER["HTTP_HOST"] != 'umd.net' && $_SERVER["HTTP_HOST"] != 'content.umd.net' && $_SERVER["HTTP_HOST"] != 'mucky.umd.net' && $_SERVER["HTTP_HOST"] != 'fetish.umd.net' && $_SERVER["HTTP_HOST"] != 'dirtiestsiteintheworld.com' && $_SERVER["HTTP_HOST"] != 'pornreality.com') { // if we are getting a hit from a "sister site" then we will redirect them to their subdomain. // we have to join on the virtual site matrix, and then the system sites db, in order to figure out which top-level domain name this store is supposed to belong to! if ($_SERVER["HTTP_HOST"] == 'umdfetish.com' || $_SERVER["HTTP_HOST"] == 'umdfetish.net') { if ($_SERVER["HTTP_HOST"] == 'loverbuns.com') header("HTTP/1.1 301 Moved Permanently"); // loverbuns is moved permanently. else header("HTTP/1.1 303 See Other"); // means this is valid, but see other (and it would send any post data from a form to that url, as well.) // logthis("Sending to the fetish side! $_SERVER[HTTP_HOST]", '', 1, '', 1); header("location: //fetish.umd.net"); exit; } else { if (is_numeric(str_replace('.', '', $_SERVER['HTTP_HOST']))) { // Hitting from raw IP instead of domain. Probably at our server. Stop them there. header("HTTP/1.1 404 Not Found"); echo 'Not found'; exit; } $query = "select idtitle, system_sites.domainname, system_sites.cookie_domain from download_stores left join system_sites on download_stores.system_site_1 = system_sites.id where download_stores.domainname = '{$_SERVER['HTTP_HOST']}' and download_stores.store_deleted = 0"; $data = coolquery($query, 1); if ($data['idtitle'] || ($_SERVER["HTTP_HOST"] == 'loverbuns.com' || $_SERVER["HTTP_HOST"] == 'fluffybodies.com' || $_SERVER["HTTP_HOST"] == 'fluffybody.com')) { header("HTTP/1.1 303 See Other"); // means this is valid, but see other (and it would send any post data from a form to that url, as well.) // logthis("Sending to the fetish side. $_SERVER[HTTP_HOST]", '', 1, '', 1); if ($data['idtitle']) header("location: //{$data['idtitle']}.{$data['cookie_domain']}"); else header("location: //fetish.umd.net"); exit; } else { // Generic fallback which will catch all traffic here, to a domain name that is not in the system. Well they're here, so let's redirect them to a generic spot. if (!strstr($_SERVER['HTTP_HOST'], ':443') && !strstr($_SERVER['HTTP_HOST'], ':80') && $_SERVER['HTTP_HOST'] != 'net.' && $_SERVER['HTTP_HOST'] != 'example.com' && !is_bot()) logthis("Hit to invalid domain \"{$_SERVER['HTTP_HOST']}\"", '', '', '', 1); // && $_SERVER[HTTP_REFERER] // 12/19/20: Commented out referrer requirement because we want to be alerted even if this happens with direct hits. // logthis("Domain not in the system. $_SERVER[HTTP_HOST]", '', 1, '', 1); header("HTTP/1.0 404 Not Found"); header("location: //umd.net"); exit; } } } if (is_stealth_domain()) $host_lookup = 'umd.net'; // Treat just like normal site elseif (!empty($_GET['host']) && ($_GET['host'] == 'umd.net' || $_GET['host'] == 'fetish.umd.net')) $host_lookup = $_GET['host']; // (Only these 2 hardcoded for now.) They can pass alternate host so we can be like we're on that site. Really so we can use content server and still authenticate user correctly by specifying real domain thru url. else $host_lookup = $_SERVER["HTTP_HOST"]; if (!showcache('sitedata_'.$host_lookup, '', 1)) { // we cache the sitedata for each domain. // (isset(OWNER_IPS[$_SERVER['REMOTE_ADDR']])) || $sitedata = getsitedata($domain_site_id, $host_lookup, '', ''); // gets and caches info from system_sites database. $site_id is taken as priority, but we only ever send it if manually setting site ID based on something else. timecheck("cached up new sitedata on handler $domain_site_id, $host_lookup"); $output = str_replace("'", "\'", serialize($sitedata)); $output = ''; // once in the included file, will regenerate our array into this function. showcache('sitedata_'.$host_lookup, $output, 1); // the 1 makes it universal, so it pulls up and stores NOT based on the currently-viewed virtual site id, which we wouldn't even have here now anyway, which was the point. /* if (isset(OWNER_IPS[$_SERVER['REMOTE_ADDR']])) { echo 'sitedata_'.$host_lookup; echo $sitedata[config][useroftheday]; } */ $output = ''; } // else timecheck("got sitedata from cache on handler domain_site_id: $domain_site_id, host_lookup: $host_lookup"); global $sitedata; $userdata = array(); $sitedata['now'] = time(); $sitedata['start_time'] = $starttime; if (is_stealth_domain()) { $sitedata['cookie_domain'] = $_SERVER["HTTP_HOST"]; $sitedata['stealth_domain'] = 1; $sitedata['domain_wildcard'] = '.'; // We don't use wildcard with IP. } else $sitedata['domain_wildcard'] = '.'; if (!$sitedata['id']) { logthis("No site ID. Bouncing to UMD. host_lookup: $host_lookup Sent thru get? {$_GET['host']}. HTTP_HOST: {$_SERVER['HTTP_HOST']} domain_site_id: $domain_site_id", 1, '', '', 1, '', '', 2); if (isset(OWNER_IPS[$_SERVER['REMOTE_ADDR']])) { echo "No site ID."; mup('host lookup: '.$host_lookup); mup('domain_site_id: '.$domain_site_id); mup(getsitedata($domain_site_id, $host_lookup)); mup($host_lookup); mup($sitedata); exit; } header("location: https://umd.net"); exit; } if ($_SERVER["REAL_HTTP_HOST"]) { // Add / substitute some values in our $sitedata array... just the items that make it possible to actually use the site on a different domain $sitedata['realdomainname'] = $_SERVER["REAL_HTTP_HOST"]; // Add this for our base href $sitedata['cookie_domain'] = $_SERVER["REAL_HTTP_HOST"]; // When using an aliased domain name, this is the only thing we're taking into the scripts that shows any connection to the real actual domain name we're using.. } else $sitedata['realdomainname'] = $_SERVER["HTTP_HOST"]; // Just fill so it's there. if ($cookie_preferences) { $cookie_preferences = unserialize(stripslashes($cookie_preferences)); $userdata['preferences'] = $cookie_preferences; // in case user had prefs set in cookie but isn't logged in, this'll be our userdata. Otherwise it'll get replaced later. } // $sitedata[color_css] = $sitedata[protocol].'://'.$sitedata[domainname].'/css.html/'.($sitedata[subdomain] ? 's/'.$sitedata[subdomain].'/' : '').'d/'.$sitedata[domainname].($cookie_preferences[cs] ? '/cs/'.$cookie_preferences[cs]:''); if ($_SERVER["HTTP_SUBDOMAIN"] == 'content') { // $sitedata["content_server"] = 'vegas'; // $sitedata["subdomain"] = ''; // Unnecessary; Just showing that we're not populating subdomain. $sitedata["subdomain"] = $_SERVER["HTTP_SUBDOMAIN"]; } else $sitedata["subdomain"] = $_SERVER["HTTP_SUBDOMAIN"]; // Give $sitedata array the subdomain that we're on, unless it's "content." that is special and the site should see it normally so it can process it. if (empty($_SERVER["HTTP_SUBDOMAIN"]) && !empty($_GET['wamshop'])) { // legacy poplock URLs; always use store subdomain now $store_slug = preg_replace('/[^a-z0-9_-]/i', '', $_GET['wamshop']); if ($store_slug) { $redirect_path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); $redirect_query = $_GET; unset($redirect_query['wamshop']); $redirect_url = $sitedata['protocol'].'://'.$store_slug.'.'.$sitedata['cookie_domain'].$redirect_path.($redirect_query ? '?'.http_build_query($redirect_query) : ''); header('Location: '.$redirect_url); exit; } } $sitedata["subsubdomain"] = $_SERVER["HTTP_SUBSUBDOMAIN"]; // use the old host array. date_default_timezone_set('America/New_York'); /* if (!$cookie_preferences || !$cookie_preferences['cs']) { $ampm = date("G") + 5; // +5 because the server is on EST. This puts the result at 0 / GMT. if ($cookie_preferences['zone']) $ampm += $cookie_preferences['zone']; // Subtract / add the user's own time zone. if ($ampm >= 18 || $ampm < 6) $cs = 1; else $cs = ''; } else $cs = $cookie_preferences['cs']; */ if (!$cookie_preferences || !$cookie_preferences['cs']) { if (!isset($auto_day_night)) { $timezone_offset = isset($cookie_preferences['zone']) ? $cookie_preferences['zone'] : -5; $user_time = time() + (($timezone_offset + 5) * 3600); // Must add 5 because server time is EST $current_time = $user_time; // Use full timestamp for precise calculations $day_of_year = date("z", $user_time); // 0-364 // Simple seasonal nudging: longest day around day 172 (June 21), shortest around day 355 (Dec 21) // Varies sunrise ±2 hours, sunset ±2 hours from base 7AM/7PM $seasonal_factor = cos(($day_of_year - 172) * 2 * 3.14159 / 365); // -1 to +1 $sunrise_hour = 7 + ($seasonal_factor * -2); // Varies 5AM to 9AM (earlier in summer, later in winter) $sunset_hour = 19 + ($seasonal_factor * 2); // Varies 5PM to 9PM (later in summer, earlier in winter) // Convert sunrise/sunset hours to precise timestamps for today $today_start = mktime(0, 0, 0, date("n", $user_time), date("j", $user_time), date("Y", $user_time)); $sunrise_time = $today_start + ($sunrise_hour * 3600); $sunset_time = $today_start + ($sunset_hour * 3600); // Use night mode between sunset and sunrise with precise time comparison if ($current_time >= $sunset_time || $current_time < $sunrise_time) { $cs = 1; } else { $cs = 0; } setbrownie("auto_day_night", $cs, time()+1800, '/'); // expire after half hour set_cookie_session(); } else $cs = $auto_day_night; } else $cs = $cookie_preferences['cs']; $templates_directory = 'templates/'.($sitedata['domainname'] == 'umd.net' ? $sitedata['domainname'] : 'generic').($cs && $cs == '1' ? '2':'').'/'; // $sitedata['we_are_external'] = $we_are_external; if ($we_are_external) $sitedata['site_dir'] = 'templates/generic/'; // for our independent sites that we have. Plus new sister sites. else { $sitedata['site_dir'] = $templates_directory; } // figure out our protocol (http or https) since we will be doing secure transactions sometimes if (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on' ) $sitedata['protocol'] = 'https'; else $sitedata['protocol'] = 'http'; // 1/18/17: Might wanna use cookie domain here... $our_url = $sitedata['protocol'].'://'.$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"]; $yeah = parse_url(str_replace('%2F','%3F',$our_url)); // 10/24/18: Not needed $query_string = substr(strrchr($our_url, '?'),1); // get the traditional query string from the url if it exists. $our_url = str_replace('?'.$query_string, '',$our_url); // Take that traditional query string off of the url so we can parse what's left. $our_url = str_replace($sitedata['protocol'].'://', '' , $our_url); // Take the http:// off of the url since we don't need that. $slash_position = strstr($our_url,'/'); // Find out where first slash is so we can delete what's after it to derive our domain name. if ($staging_mode) { $views_directory = ROOT_DIR.'staging/'; } else $views_directory = ROOT_DIR; $pattern = "/^{$_SERVER['HTTP_HOST']}\//"; $file_name = preg_replace($pattern, '', $our_url); // Removing the domain name and trailing slash leaves us with the file name (and any custom query string). if (strpos($file_name, '..') !== false || (isset($file_name[0]) && $file_name[0] === '/')) { header("HTTP/1.0 404 Not Found"); header("location: {$sitedata['protocol']}://{$_SERVER['HTTP_HOST']}"); exit; } if (!$test = @parse_url($_SERVER['REQUEST_URI'])) { header("location: /"); exit; } $test['path'] = substr($test['path'], 1); // kill the beginning slash that php likes to leave on there if (strpos($test['path'], '..') !== false || (isset($test['path'][0]) && $test['path'][0] === '/')) { header("HTTP/1.0 404 Not Found"); header("location: {$sitedata['protocol']}://{$_SERVER['HTTP_HOST']}"); exit; } if (file_exists($views_directory . $test['path']) && $file_name) { // if the file exists right in the root directory, set our paths n stuff to that. can't give to them. must include later. $views_directory = $views_directory . substr(str_replace($file_name,'',$test['path']).'/',1); } // Before sending any content, allow their browser to cache our pages. header("Cache-Control: private, no-cache, must-revalidate, max-age=0"); // no-cache + max-age=0 means revalidate every load. must-revalidate blocks serving stale after that. private keeps back-button cache eligible unlike no-store. header_remove('ETag'); // Apache may add these from the .html file on disk after this runs; footer.html strips them again right before output. header_remove('Last-Modified'); if (!preg_match("/.html$/", $file_name) && !preg_match("/.php$/", $file_name)) { // html files must be included. otherwise, give it straight to them. // we STILL must check that the file exists, because we are also given filenames sans extension. And we don't want to be trying to give them that. if (is_file($views_directory.$file_name) && $file_name) { // if it's in main directory... // if the stuff is located in a "virtual" directory, we stack the requested file on top of the templates directory and saw if it existed. // if the file exists in our template directory, give it to them. But don't do it for html files, etc. cuz they must be included and parsed below. $forbidden_url_beginnings = array('protected', 'media/cache', 'media/uploads', 'media/webmaster_uploads', 'media/webmaster_uploads_browser', 'media/temp/photocount', 'media/temp/zips'); // No preceding slash needed. foreach($forbidden_url_beginnings as $check) { if (strrpos($file_name, $check, -strlen($file_name)) !== FALSE) { logthis("Forbidden file request:\n$file_name", 1, 1, $userdata, 1); header("HTTP/1.0 404 Not Found"); header("location: /downloads"); exit; } } header("HTTP/1.1 200 OK"); give_them($views_directory.$file_name); // substr gets rid of extra slash. give_them function spits out file directly. } if (is_file(ROOT_DIR . $templates_directory.$file_name) && $file_name) { // fall back on the media in root directory. header("HTTP/1.1 200 OK"); give_them(ROOT_DIR . $templates_directory.$file_name); // substr gets rid of extra slash. give_them function spits out file directly. } /* elseif (is_file($file_name) && $file_name) { // otherwise we look in our special directory. header("HTTP/1.1 200 Ok"); give_them($file_name); // substr gets rid of extra slash. give_them function spits out file directly. } */ elseif (is_file(ROOT_DIR.$file_name) && $file_name) { // otherwise we look in our special directory. header("HTTP/1.1 200 OK"); give_them(ROOT_DIR.$file_name); // substr gets rid of extra slash. give_them function spits out file directly. } } $custom_query_string = strstr($file_name,'/'); // Obtain our neat, slash-separated query string. Variables should be odd; values should be even. $file_name = str_replace($custom_query_string,'',$file_name); // we remove any custom query string so we're just left with the file name. // now we have to get our evens and odds! $custom_query_string = substr($custom_query_string,1); $query_string2 = ''; if ($custom_query_string) { if (strstr($custom_query_string, '/')) { $custom_query_string = explode('/',$custom_query_string); $count = 0; foreach($custom_query_string as $segment) { if (!$count && $segment == 'this') { logthis("Possible hack attempt: String named 'this' in query string.\n\nBan IP", '', 1, $userdata, 1); continue; } $query_string2 .= addslashes($segment); $query_string2 .= ($count ? '&' : '='); if ($count == 1) $count = 0; else $count = 1; } } else { $query_string2 .= 'idtitle='.$custom_query_string.'&i='.$custom_query_string; // We are going to start using the $i variable, intead of ugly idtitle. } } if ($query_string) { parse_str($query_string, $handler_parsed_query); extract($handler_parsed_query); } if ($query_string2) { parse_str($query_string2, $handler_parsed_query); extract($handler_parsed_query); } if ((!$file_name || $file_name == 'index' || $file_name == 'index.html' || $file_name == '?')) { // if there was no slash, then we don't even have a file name, so default.... if ($_SERVER["HTTP_SUBDOMAIN"] && $_SERVER["HTTP_SUBDOMAIN"] != 'test' && !$set_splash) $file_name = 'downloads'; else $file_name = 'index.html'; // if there was no slash, then we don't even have a file name, so default to index.php. } if ($file_name == 'handler.html') { // this is the only file we specifically deny here. header("location: /"); exit; } $sitedata['script_name'] = str_replace('.html', '', $file_name); // interim for early p.html exits; finalized again before include require_once("functions.html"); // Static assets above this point only needed functions_essential. Everything from here on is an html page route (including p.html 404s). // HERE IS WHERE WE REALLY ALLOW THE USER TO USE CLEAN URL'S WITH NO .HTML ON THEM. if (strstr($file_name, '.')) { // if the file name has a dot in it, then it'll have an extension, too. So we're done. much faster than sending thru that function every time. $file_info['directory'] = $views_directory; $file_info['file_name'] = $file_name; } elseif (is_file($views_directory.$file_name .".html")) { // if no dot, then try with .html in our main directory and see if that exists. If so, run with that. $file_name = $file_name .=".html"; $file_info['directory'] = $views_directory; $file_info['file_name'] = $file_name.'.html'; } // do we really need this hierarchy to find html files up in the templates folder? can't just just always address that file directly? elseif (is_file($templates_directory.$file_name .".html")) { // if it didn't exist there, then try in templates directory with .html. $file_name = $file_name .= ".html"; $file_info['directory'] = $templates_directory; $file_info['file_name'] = $file_name.'.html'; } else { // if still not found, then perhaps there is a user with this name that we can bounce to. if (preg_match("/.*jpe?g$/", $_SERVER["REQUEST_URI"])) { // logthis("Image not found: $_SERVER[REQUEST_URI]; sending to no_user_icon"); header("location: /{$templates_directory}images/no_image.png"); exit; } else { // if this is not an image that we're looking for, then try to find a user, or ulimately, redirect to homepage. $user_exists = ''; /* if (strstr($REQUEST_URI, 'wp-admin') || strstr($REQUEST_URI, 'wordpress') || strstr($REQUEST_URI, 'php') || strstr($REQUEST_URI, 'jquery') || strstr($REQUEST_URI, 'application') || strstr($REQUEST_URI, 'include') || strstr($REQUEST_URI, '.cgi') || strstr($REQUEST_URI, '%20') || strstr($REQUEST_URI, '.js') || strstr($REQUEST_URI, 'script') || strstr($REQUEST_URI, 'splash_url_leave')) { // Don't want notifications about these routeine hacks // logthis("will quietly give 404: $REQUEST_URI", '', 1, '', 1); header("HTTP/1.1 404 Not Found"); $page = '404'; $sitedata[skip_valid_page_check] = 1; include("p.html"); // simple page just echoes out the contents of our page. exit; } */ $file_name = addslashes($file_name); $check = preg_replace("/[^a-z0-9_-]/", "", strtolower(str_replace('/', '', $file_name))); // We will check it against its filtered, pure name // If it's not a pure name, block it. if (($check != strtolower($file_name) || strlen($file_name) > 50)) { // && (!strstr($REQUEST_URI, 'media/') && !strstr($REQUEST_URI, 'images/')) header("HTTP/1.1 400 Bad Request"); $page = '404'; $sitedata['skip_valid_page_check'] = 1; include("p.html"); // simple page just echoes out the contents of our page. exit; } if (!strstr($REQUEST_URI, 'media/') && !strstr($REQUEST_URI, 'images/')) { $user_exists = querycount("select 1 from users where idtitle = '$file_name'"); $uri_lower = strtolower($REQUEST_URI); $hack_signals = array('wp-content', 'wp-admin', 'wp-includes', 'wp-login', 'wp-config', 'wordpress', 'xmlrpc.php', 'phpmyadmin', 'pma/', 'adminer', 'phpinfo', '.php', '.js', 'cgi-bin', '.cgi', '.env', '/.git', '.git/', 'joomla', 'administrator/index.php', 'drupal', 'vendor/phpunit', 'phpunit/', 'etc/passwd', 'backup.sql', 'dump.sql', 'backup.zip', '.sql.gz', 'setup-config', 'shell.php', 'c99.php', 'r57', 'alfashell', 'wso.php', 'bypass.php', 'eval-stdin.php', 'solr/admin', 'aws.yml', '.aws/', 'laravel', 'vendor/laravel', 'actuator/', 'console/login', 'boaform/admin', 'goform/', 'hudson', 'jenkins', 'struts', 'web-inf', 'meta-inf', '.htpasswd', 'license.txt', 'readme.html'); $looks_like_hack = 0; foreach ($hack_signals as $hack_signal) { if (strstr($uri_lower, $hack_signal)) { $looks_like_hack = 1; break; } } if (!$user_exists && $looks_like_hack && !is_file(ROOT_DIR.$test['path'])) { // Real files on disk (e.g. cometchat/cometchat_receive.php) hit this branch after path parsing to idtitle "cometchat"; do not treat .php in REQUEST_URI as a hack for those. $is_bot = is_bot(); logthis("Invalid file, and failed checked for user with file_name, so banning IP\nREQUEST_URI: $REQUEST_URI\n$REMOTE_ADDR\n".($is_bot ? "Was a bot: $is_bot" : ""), '', ''); require_once("functions_user.html"); // ban_ip() if (!$is_bot && !mu()) ban_ip($REMOTE_ADDR, "Invalid file requested that looks like a hack attempt\n$REQUEST_URI ", 1); } } if ($user_exists) { // we found a user with this idtitle! we will just include profile.html instead of including it so it looks like the user's custom url. $idtitle = $file_name; $file_info['directory'] = $views_directory; $file_name = 'profile.html'; $file_info['file_name'] = 'profile.html'; $sitedata['script_name'] = 'profile'; } else { // if still no dice, then show our 404 message. This will also happen if they try to access a not-found image in a nonexistent templates folder, or any other folder. // set up redirection for certain scripts. $redirection_array = array('forum' => 'forums', 'my_downloads' => 'purchases', 'mycart' => 'cart', 'manage_users' => 'preferences'); if (array_key_exists($file_name, $redirection_array)) { // only really works for non-.html filenames. // logthis('Invalid file on handler but found redirection: '.$file_name, 1, 1, $userdata, 1, '', '', 2); $destination = str_replace($file_name, $redirection_array[$file_name], $REQUEST_URI); header("location: $destination"); exit; } else { header("HTTP/1.1 404 Not Found"); $page = '404'; $sitedata['skip_valid_page_check'] = 1; // logthis('Invalid file on handler: '.$file_name, 1, 1, $userdata, 1, '', '', 2); include("p.html"); // simple page just echoes out the contents of our page. exit; } } } } if (empty($idtitle) && !empty($i)) $idtitle = $i; // We like this va better in the URL, so we make it optional for use as our unique id name instead of the ugly "idtitle"! if (!empty($idtitle)) $idtitle = substr(preg_replace("/[^a-zA-Z0-9_\- ]/", "", $idtitle), 0, 100); // Clean it up and limit to reasonable length. $sitedata['script_name'] = str_replace('.html', '', $file_name); $sitedata['file_name'] = $file_name; // Now we have our final filename. Simply include it. if (is_file($views_directory.$file_name)) { if (preg_match("/.php$/", $file_name)) { // If this is a php file, make sure it's on the approved list. // $allowed_php_pages = array('umdringimage.php'); // 'sucuri-55a58e2e83580c1b0bff5610bf18c3e7.php', , 'phpvideotoolkit.php5.php' // if (!in_array($file_name, $allowed_php_pages)) { $comment = "Possible hack, trying to run $file_name"; require_once("functions_user.html"); // ban_ip() ban_ip($REMOTE_ADDR, $comment, 7); logthis('Request for invalid script. Banned '.$REMOTE_ADDR, '', !$sitedata['config']['do_not_disturb'], '', 1, '/system_log/ip/'.$REMOTE_ADDR, 'View IP Log', 3, '', '', '', '', '', 'hack'); // '.$file_name.' REQUEST_URI header("HTTP/1.0 404 Not Found"); header("location: {$sitedata['protocol']}://{$_SERVER['HTTP_HOST']}"); // home exit; // } } // Protect against directory traversal attacks if (strpos($file_name, '../') !== false) { $comment = "Directory traversal attempt with file: $file_name"; require_once("functions_user.html"); // ban_ip() ban_ip($REMOTE_ADDR, $comment, 7); logthis('Directory traversal attempt. Banned '.$REMOTE_ADDR, '', !$sitedata['config']['do_not_disturb'], '', 1, '/system_log/ip/'.$REMOTE_ADDR, 'View IP Log', 3, '', '', '', '', '', 'hack'); header("HTTP/1.0 404 Not Found"); header("location: {$sitedata['protocol']}://{$_SERVER['HTTP_HOST']}"); // home exit; } include($views_directory.$file_name); } else { header("location: {$sitedata['protocol']}://{$_SERVER['HTTP_HOST']}"); // home // include($views_directory.'index.html'); exit; } function give_them($file, $disposition = 'inline', $log_done = '', $final_queries = '') { // Handles the output of all files that are not .php. global $userdata, $database_connection, $api_contacting, $direct_download, $REMOTE_ADDR, $REQUEST_URI; // so that it doesn't have to be open the whole time this person is downloading the file!; if (strpos($file, '..') !== false) { header("HTTP/1.1 404 Not Found"); logthis('handler: blocked path traversal: '.$file, 1, 2, $userdata, 1, '', '', 3, '', '', '', '', '', '', 'hack'); echo 'Not found.'; exit; } //Gather relevent info about file $length = @filesize($file); if ($length) { $filename = basename($file); $file_extension = strtolower(substr(strrchr($filename,"."),1)); $now = time(); //This will set the Content-Type to the appropriate setting for the file switch( $file_extension ) { case "csv": $content_type="text/csv"; break; case "pdf": $content_type="application/pdf"; break; case "exe": $content_type="application/octet-stream"; break; case "zip": $content_type="application/zip"; break; case "doc": $content_type="application/msword"; break; case "xls": $content_type="application/vnd.ms-excel"; break; case "ppt": $content_type="application/vnd.ms-powerpoint"; break; case "gif": $content_type="image/gif"; break; case "png": $content_type="image/png"; break; case "jpeg": case "jpg": $content_type="image/jpeg"; break; // image/jpg causes it to try to download it instead of just displaying it in-window! case "tiff": $content_type="image/tiff"; break; case "mp3": $content_type="audio/mpeg"; break; case "wav": $content_type="audio/wav"; break; case "mpeg": case "mpg": case "m4v": case "m4b": case "mpe": $content_type="video/mpeg"; break; case "mp4": $content_type="video/mp4"; break; case "mov": $content_type="video/quicktime"; break; case "avi": $content_type="video/x-msvideo"; break; case "wma": $content_type="audio/x-ms-wma"; break; case "wmv": $content_type="video/x-ms-wmv"; break; case "divx": $content_type="video/divx"; break; case "css": $content_type="text/css;"; break; case "html": $content_type="text/html;"; break; case "txt": $content_type="text/plain;"; break; case "flv": $content_type="video/x-flv;"; break; case "js": $content_type="text/javascript;"; break; case "xml": $content_type="application/xml"; break; default: $content_type="text/plain;charset=UTF-8;"; } // Write da headers... http_response_code(200); header ("Expires: ".gmdate('D, d M Y H:i:s', $now + (86400 * 7)) .' EST'); // one week header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " EST"); // always modified header ("Content-Type: $content_type"); // Give 'em da file! Always force these as attachments unless told specifically to put them inline. if ($disposition != 'inline' && ($file_extension == 'mp4' || $file_extension == 'wmv' || $file_extension == 'mpg' || $file_extension == 'mpeg' || $file_extension == 'm4v' || $file_extension == 'avi' || $file_extension == 'mov' || $file_extension == 'zip' || $file_extension == 'flv' || $file_extension == 'mp3' || $file_extension == 'wav' || $file_extension == 'txt' || $file_extension == 'divx' || $file_extension == 'csv' || $file_extension == 'jpg' || $file_extension == 'jpeg' || $file_extension == 'png' || $file_extension == 'm4b')) { header("Content-Disposition: attachment; filename=$filename;"); } elseif ($disposition == 'attachment' && ($file_extension == 'pdf')) { // We only force these as attachments if told to. We do this separately from above because we don't want to FORCE PDF's as attachment if no disposition specified. header("Content-Disposition: attachment; filename=$filename;"); } else { // We only force these as attachments if told to; Otherwise we default to inline. header("Content-Disposition: inline; filename=$filename;"); } header("Content-Transfer-Encoding: binary"); header("X-Powered-By: Love"); while (ob_get_level()) ob_end_clean(); if (session_status() === PHP_SESSION_ACTIVE) session_write_close(); if ($database_connection) @mysqli_close($database_connection); if (isset($_SERVER['HTTP_RANGE'])) { rangeDownload($file); } else { header("Content-Length: ".$length); http_response_code(200); readfile_chunked($file); } if ($log_done || $final_queries) { // if they want us to log this file as being done, then we have to reconnect to the database and log it (we disconnect from DB before sending long files and tying up the open database connection for that long) db_connect(); if ($log_done) logthis("Downloaded $filename", 4, '', $userdata, '', '', '', 1, '', '', '', '', '', '', 'dld', $filename); // the 1 is "permanent" if (is_array($final_queries)) { foreach ($final_queries as $query) { hotquery($query); } } } } else { header("HTTP/1.1 404 Not Found"); $restore_fetch = ($api_contacting && $direct_download && ip_legit()); if ($restore_fetch) { db_connect(); if (is_file($file)) logthis("Backup restore rejected: zero-byte file on main\n$file", '', 1, '', '', '', '', 2, '', '', '', '', '', '', 'backup', SERVER_NICKNAME); else logthis("Backup restore rejected: not on main\n$file", '', 1, '', '', '', '', 2, '', '', '', '', '', '', 'backup', SERVER_NICKNAME); } elseif (is_file($file)) { db_connect(); /* // 3/25/25: Did this at one point when we thought it was a signal of a hacker trying to upload and execute weird files, but that never panned out, and this is banning people whenever a file is corrupted. if (!mu()) { require_once("functions_user.html"); // ban_ip() ban_ip($REMOTE_ADDR, 'Potential hack attempt by adding file', 7); } */ logthis('handler: File exists but has no length: '.$file, 1, 1, $userdata, 1, '', '', 3, '', '', '', '', '', '', 'notfound'); } else { db_connect(); logthis('File not found on handler: '.$file, 1, ($REQUEST_URI && $HTTP_REFERER && !$sitedata['config']['do_not_disturb'] ? 1 : ''), $userdata, 1, 2, '', '', '', '', '', '', '', '', 'notfound'); } echo 'Not found.'; if (mu()) echo '.'; } exit; } function readfile_chunked($filename) { while (ob_get_level()) ob_end_clean(); // give_them already clears; belt-and-suspenders for php83 $chunksize = 1*(1024*1024); // how many bytes per chunk $buffer = ''; $read_overall = 0; $handle = fopen($filename, 'rb'); if ($handle === false) { return false; } stream_set_timeout($handle, 5); // Changes the socket timeout. stream_set_blocking($handle, 1); // try uncommenting this... see if it helps. then try downloading file that i uploaded to media/forum_uploads via http. then try to pull the same file using give_them and test.html. remember to remove stream_set_timeout after all this shit is done? while (!feof($handle)) { // $buffer = fread($handle, $chunksize); // 3/1/15: Trying this to alleviate drop-outs. It retries delivering the chunk if it's not fully sent the first time. $read = 0; while ($read < $chunksize && ($buffer = fread($handle, $chunksize - $read))) { // We check for aborted connection BEFORE actually sending each chunk, cuz browsers seem to disconnect the instant they've gotten the final chunk, according to the file size that we told them to expect. If we check for aborted connection after last chunk, it WILL likely be aborted. if (!connection_aborted()) { $buffer_size = strlen($buffer); $read_overall += $buffer_size; $read += $buffer_size; } else return $read_overall; // if (!connection_aborted()) $total += strlen($buffer); echo $buffer; flush(); // 6/20/24: Added here instead of outside the while loop to ensure immediate delivery. } } fclose($handle); return $read_overall; } function rangeDownload($file) { while (ob_get_level()) ob_end_clean(); // http://mobiforge.com/design-development/content-delivery-mobile-devices#byte-ranges $fp = @fopen($file, 'rb'); $size = filesize($file); // File size $length = $size; // Content length $start = 0; // Start byte $end = $size - 1; // End byte // Now that we've gotten so far without errors we send the accept range header /* At the moment we only support single ranges. * Multiple ranges requires some more work to ensure it works correctly * and comply with the spesifications: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2 * * Multirange support annouces itself with: * header('Accept-Ranges: bytes'); * * Multirange content must be sent with multipart/byteranges mediatype, * (mediatype = mimetype) * as well as a boundry header to indicate the various chunks of data. */ header("Accept-Ranges: 0-$length"); // header('Accept-Ranges: bytes'); // multipart/byteranges // http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2 if (isset($_SERVER['HTTP_RANGE'])) { $c_start = $start; $c_end = $end; // Extract the range string list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2); // Make sure the client hasn't sent us a multibyte range if (strpos($range, ',') !== false) { // (?) Shoud this be issued here, or should the first // range be used? Or should the header be ignored and // we output the whole content? header('HTTP/1.1 416 Requested Range Not Satisfiable'); header("Content-Range: bytes $start-$end/$size"); db_connect(); logthis("Failed file send. No server range. File: $file"); exit; } // If the range starts with an '-' we start from the beginning // If not, we forward the file pointer // And make sure to get the end byte if spesified if ($range0 == '-') { // The n-number of the last bytes is requested $c_start = $size - substr($range, 1); } else { $range = explode('-', $range); $c_start = $range[0]; $c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $size; } /* Check the range and make sure it's treated according to the specs. * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html */ // End bytes can not be larger than $end. $c_end = ($c_end > $end) ? $end : $c_end; // Validate the requested range and return an error if it's not correct. if ($c_start > $c_end || $c_start > $size - 1 || $c_end >= $size) { header('HTTP/1.1 416 Requested Range Not Satisfiable'); header("Content-Range: bytes $start-$end/$size"); db_connect(); logthis("Failed file send. Bad requested range c_start $c_start c_end $c_end size $size. File: $file"); exit; } $start = $c_start; $end = $c_end; $length = $end - $start + 1; // Calculate new content length fseek($fp, $start); header('HTTP/1.1 206 Partial Content'); } // Notify the client the byte range we'll be outputting header("Content-Range: bytes $start-$end/$size"); header("Content-Length: $length"); error_reporting(0); // Suppresses any errors resulting from warnings, which would be logged as "PHP Warning: Cannot modify header information - headers already sent in Unknown on line 0" // Start buffered download $buffer = 1024 * 8; while(!feof($fp) && ($p = ftell($fp)) <= $end) { if ($p + $buffer > $end) { // In case we're only outputtin a chunk, make sure we don't // read past the length $buffer = $end - $p + 1; } set_time_limit(0); // Reset time limit for big files echo fread($fp, $buffer); flush(); // Free up memory. Otherwise large files will trigger PHP's memory limit. } fclose($fp); } ?>