setErrorHandling(); $systemClass->setTimeZone(); $context = $systemClass->setStreamContext(); // Start a session if we haven't already if(false === isset($_SESSION)) { ini_set('session.use_cookies', '1'); // Use cookies not URL parameters ini_set('session.use_only_cookies', '1'); // Force use of cookies and nothing else ini_set('session.name', 'ICEcoder'); // Set a seperate cookie name ini_set('session.cookie_lifetime', '0'); // Until the browser restarts by default ini_set('session.cookie_domain', ''); // This domain only // ini_set('session.cookie_path', str_replace($_SERVER['DOCUMENT_ROOT'], '', dirname(dirname(__FILE__)))); // ICEcoder path only, fails ON IE ini_set('session.use_trans_sid', '0'); // Ensure this insecure feature is disabled ini_set('session.hash_function', 'sha512'); // Use Sha512 for session ini_set('session.hash_bits_per_character', '6'); // Specify hash scheme of 0-9,a-v,A-Z,-,, ini_set('session.use_strict_mode', true); // Reject any session ID that was user provided and not generated by the session ini_set('session.httponly', true); // Only allow http protocol (ie, not JS) access to the cookie ini_set('session.cookie_httponly', true); // Only allow cookie via http protocol (ie, not JS) access to the cookie // ini_set('session.save_path', dirname(__FILE__) . '/../tmp'); // Localise the session files to /tmp if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') { ini_set('session.cookie_secure', '1'); // Only allows access to session ID when protocol is HTTPS, switched on under 'if https' condition } if (false === isset($_SESSION)) { session_start(); } if (false === isset($_SESSION['csrf'])){ session_regenerate_id(true); // Create a new ID to help prevent fixation & hijacking } } // Set the language file, if now possible if (true === isset($_SESSION['text'])) { $text = $_SESSION['text']; $t = $text['settings-common']; } // Copy over backups if we've just updated to new version (TODO: can be moved to updater.php one day after 7.0 released) if (true === isset($_GET['display']) && $_GET['display'] === "updated") { // If the backups dir doesn't exist, or it does but is empty if ( false === file_exists(dirname(__FILE__) . "/../data/backups") || count(array_diff(scandir(dirname(__FILE__) . "/../data/backups"), ['.', '..'])) === 0 ) { // If the old version has some backups to move over if (count(array_diff(scandir(dirname(__FILE__) . "/../tmp/oldVersion/backups"), ['.', '..'])) > 0) { // If the data dir is writable if (is_writable(dirname(__FILE__) . "/../data")) { // Remove the backups dir if it's there and writable if (file_exists(dirname(__FILE__) . "/../data/backups") && is_writable(dirname(__FILE__) . "/../data")) { rmdir(dirname(__FILE__) . "/../data/backups"); } // Move backups dir from old version to current version rename(dirname(__FILE__) . "/../tmp/oldVersion/backups", dirname(__FILE__) . "/../data/backups"); } } } } // Check requirements meet minimum spec include dirname(__FILE__) . "/requirements.php"; // Create a backups dir in the data dir if it doesn't exist yet if (false === file_exists(dirname(__FILE__) . "/../data/backups")) { mkdir(dirname(__FILE__) . "/../data/backups"); } // Walk through possibilities in the order we'd like to determine an user IP function getUserIP() { return $_SERVER['HTTP_CLIENT_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['HTTP_X_FORWARDED'] ?? $_SERVER['HTTP_FORWARDED_FOR'] ?? $_SERVER['HTTP_FORWARDED'] ?? $_SERVER['REMOTE_ADDR'] ?? 'Unknown'; } // Get data from a fopen or CURL connection function getData($url, $type='fopen', $dieMessage = false, $timeout = 60) { global $context, $systemClass; // Request is to connect via CURL if ($type === "curl" && function_exists('curl_init')) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); curl_setopt($ch, CURLOPT_USERAGENT, 'ICEcoder'); curl_setopt($ch, CURLOPT_FAILONERROR, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_AUTOREFERER, true); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); $data = curl_exec($ch); curl_close($ch); // Otherwise, use an fopen connection } elseif (ini_get('allow_url_fopen')) { $context = stream_context_create(array('http'=> array( 'timeout' => $timeout // secs ) )); $systemClass->invalidateOPCache($url); $data = @file_get_contents($url, false, $context); if (!$data) { $data = @file_get_contents(str_replace("https:", "http:", $url), false, $context); } } elseif (file_exists($url)) { $systemClass->invalidateOPCache($url); $data = file_get_contents($url); } // Return data or die with message if ($data) { return $data; } elseif ($dieMessage) { die($dieMessage); exit; } else { return ''; } } // Require a re-index dir/file data next time we index function requireReIndexNextTime() { // If we have a data/index.php file global $docRoot, $ICEcoderDir, $settingsClass, $systemClass; if (true === file_exists($docRoot . $ICEcoderDir . "/data/index.php")) { // Get serialized array back out of PHP file inside a comment block as prevIndexData $systemClass->invalidateOPCache($docRoot . $ICEcoderDir . "/data/index.php"); $prevIndexData = file_get_contents($docRoot . $ICEcoderDir . "/data/index.php"); if (strpos($prevIndexData, "serializedFileData("get", $docRoot . $ICEcoderDir . "/data/index.php"); // Set timestamp back to epoch to force a re-index next time $prevIndexData['timestamps']['indexed'] = 0; $settingsClass->serializedFileData("set", $docRoot . $ICEcoderDir . "/data/index.php", $prevIndexData); } } } // Logout if that's the action we're taking if (true === isset($_GET['logout'])) { $extraProcessesClass = new ExtraProcesses(); $extraProcessesClass->onUserLogout($_SESSION['username']); $_SESSION['loggedIn'] = false; $_SESSION['username'] = ""; session_destroy(); header("Location: ."); die("Logging you out..."); } define('SALT_LENGTH', 12); // Generate hash function generateHash($pw) { // Generate Bcrypt hash return password_hash($pw, PASSWORD_BCRYPT, $options = ['cost' => 10]); } // Verify hash function verifyHash($pw, $orig) { // Verify Bcrypt hash if (substr($orig, 0, 4) === "$2y$") { return password_verify($pw, $orig) ? $orig : "NO MATCH"; } // Verify legacy sha1 hash $origSalt = substr($orig, 0, SALT_LENGTH); return $origSalt . sha1($origSalt . $pw); } // returns a number, whole or decimal or null function numClean($var) { return is_numeric($var) ? floatval($var) : false; } // Clean XSS attempts using different contexts function xssClean($data, $type) { // === html === if ("html" === $type) { $bad = array("<", ">"); $good = array("<", ">"); } // === style === if ("style" === $type) { $bad = array("<", ">", "\"", "'", "``", "(", ")", "&", "\\\\"); $good = array("<", ">", """, "'", "`", "(", ")", "&", "\"); } // === attribute === if ("attribute" === $type) { $bad = array("\"", "'", "``"); $good = array(""", "'", "`"); } // === script === if ("script" === $type) { $bad = array("<", ">", "\"", "'", "\\\\", "%", "&"); $good = array("<", ">", """, "'", "\", "%", "&"); } // === url === if ("url" === $type) { if(preg_match("#^(?:(?:https?|ftp):{1})\/\/[^\"\s\\\\]*.[^\"\s\\\\]*$#iu", (string)$data, $match)) { return $match[0]; } else { return 'javascript:void(0)'; } } $output = str_replace($bad, $good, $data); return $output; } // returns a UTF8 based string with any UFT8 BOM removed function toUTF8noBOM($string, $message = false) { global $text; $t = $text['settings-common']; // Attempt to detect encoding if (function_exists('mb_detect_encoding')) { $strictUTF8 = mb_detect_encoding($string, 'UTF-8', true); // Establish a BOM $bom = pack("CCC", 0xef, 0xbb, 0xbf); // If there's a BOM in the first few chars if (0 === strncmp($string, $bom, 3)) { // If there's a BOM followed by a Windows based (2 char) line ending // chop BOM off and prefix returned string with a PHP_EOL if (0 === strncmp($string, $bom . "\r\n", 3)) { $string = PHP_EOL . substr($string, 3); // Else, simply chop off the BOM } else { $string = substr($string, 3); } } // Remove any other BOMs from view $string = preg_replace('/' . $bom . '/', '', $string); // Test for any bad characters $teststring = $string; $teststringBroken = utf8_decode($teststring); $teststringConverted = mb_convert_encoding($teststringBroken, "UTF-8"); // If we have a matching length, UTF8 encode it if (!$strictUTF8 && strlen($teststringConverted) == strlen($teststringBroken)) { $string = utf8_encode($string); if ($message) { // echo "parent.parent.ICEcoder.message('".$t['Your document does...'].".');"; } } } return $string; } // Get number of versions total for a file function getVersionsCount($fileLoc, $fileName) { global $context; $count = 0; $dateCounts = []; $backupDateDirs = []; // Establish the base, host and date dirs within... $backupDirBase = str_replace("\\", "/", dirname(__FILE__)) . "/../data/backups/"; $backupDirHost = "localhost"; // check if folder exists if local before enumerating contents if (true === is_dir($backupDirBase . $backupDirHost)) { $backupDateDirs = scandir($backupDirBase . $backupDirHost, 1); } // Get rid of . and .. from date dirs array for ($i = 0; $i < count($backupDateDirs); $i++) { if ($backupDateDirs[$i] === "." || $backupDateDirs[$i] === "..") { array_splice($backupDateDirs, $i, 1); $i--; } } // Check the backup index in each dir and add up the counts from matching lines for ($i = 0; $i < count($backupDateDirs); $i++) { $backupIndex = $backupDirBase . $backupDirHost . "/" . $backupDateDirs[$i] . "/.versions-index"; // Have a .versions-index file? Get contents if (file_exists($backupIndex) && is_readable($backupIndex)) { $versionsInfo = getData($backupIndex); $versionsInfo = explode("\n", $versionsInfo); // For each line, check if it's our file and if so, add the count to our $count value and $dateCount array for ($j = 0; $j < count($versionsInfo); $j++) { // Replace any backslashes in $fileLoc $fileLoc = str_replace("\\", "/", $fileLoc); // Join $fileLock and $fileName into a path and replace double slashes $fileRef = str_replace("//", "/", $fileLoc . "/" . $fileName . " = "); // Check if we have a match if (strpos($versionsInfo[$j], $fileRef) === 0) { // We have a match, so split on the " = " and we can grab number as 2nd part $lineInfo = explode(" = ", $versionsInfo[$j]); $count += intval($lineInfo[1]); $dateCounts[$backupDateDirs[$i]] = intval($lineInfo[1]); } } } } return array( "count" => $count, "dateCounts" => $dateCounts ); }