mirror of
https://github.com/icecoder/ICEcoder.git
synced 2026-02-20 01:51:18 +01:00
313 lines
12 KiB
PHP
313 lines
12 KiB
PHP
<?php
|
|
require_once dirname(__FILE__) . "/../classes/_ExtraProcesses.php";
|
|
require_once dirname(__FILE__) . "/../classes/System.php";
|
|
|
|
use ICEcoder\ExtraProcesses;
|
|
use ICEcoder\System;
|
|
|
|
$systemClass = new System;
|
|
$systemClass->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, "<?php") !== false) {
|
|
$prevIndexData = $settingsClass->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
|
|
);
|
|
}
|