mirror of
https://github.com/icecoder/ICEcoder.git
synced 2026-02-20 01:51:18 +01:00
767 lines
38 KiB
PHP
767 lines
38 KiB
PHP
<?php declare(strict_types=1);
|
|
|
|
namespace ICEcoder;
|
|
|
|
use RecursiveDirectoryIterator;
|
|
use RecursiveIteratorIterator;
|
|
use ICEcoder\FTP;
|
|
use ICEcoder\System;
|
|
use scssc;
|
|
use lessc;
|
|
|
|
class File
|
|
{
|
|
private $ftpClass;
|
|
private $systemClass;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->ftpClass = new FTP();
|
|
$this->systemClass = new System();
|
|
}
|
|
|
|
public function check() {
|
|
global $file, $fileOrig, $docRoot, $iceRoot, $fileLoc, $fileName, $error, $errorStr, $errorMsg;
|
|
// Replace pipes with slashes, then establish the actual name as we may have HTML entities in filename
|
|
$file = html_entity_decode(str_replace("|", "/", $file));
|
|
|
|
// Put the original $file var aside for use
|
|
$fileOrig = $file;
|
|
|
|
// Trim any +'s or spaces from the end of file
|
|
$file = rtrim(rtrim($file, '+'), ' ');
|
|
|
|
// Also remove [NEW] from $file, we can consider $_GET['action'] or $fileOrig to pick that up
|
|
$file = preg_replace('/\[NEW\]$/', '', $file);
|
|
|
|
// Make each path in $file a full path (; separated list)
|
|
$allFiles = explode(";", $file);
|
|
for ($i = 0; $i < count($allFiles); $i++) {
|
|
if (false === strpos($allFiles[$i],$docRoot) && "getRemoteFile" !== $_GET['action']) {
|
|
$allFiles[$i] = str_replace("|", "/", $docRoot . $iceRoot . $allFiles[$i]);
|
|
}
|
|
};
|
|
$file = implode(";", $allFiles);
|
|
|
|
// Establish the $fileLoc and $fileName (used in single file cases, eg opening. Multiple file cases, eg deleting, is worked out in that loop)
|
|
$fileLoc = substr(str_replace($docRoot, "", $file), 0, strrpos(str_replace($docRoot, "", $file), "/"));
|
|
$fileName = basename($file);
|
|
|
|
// Check through all files to make sure they're valid/safe
|
|
$allFiles = explode(";", $file);
|
|
for ($i = 0; $i < count($allFiles); $i++) {
|
|
|
|
// Uncomment to alert and console.log the action and file, useful for debugging
|
|
// echo ";alert('" . xssClean($_GET['action'], "html") . " : " . $allFiles[$i] . "');console.log('" . xssClean($_GET['action'], "html") . " : " . $allFiles[$i] . "');";
|
|
|
|
$bannedFileFound = false;
|
|
for ($j = 0; $j < count($_SESSION['bannedFiles']); $j++) {
|
|
$thisFile = str_replace("*", "", $_SESSION['bannedFiles'][$j]);
|
|
if ("" != $thisFile && false !== strpos($allFiles[$i], $thisFile)) {
|
|
$bannedFileFound = true;
|
|
}
|
|
}
|
|
|
|
// Die if the file requested isn't something we expect
|
|
if (
|
|
// On the banned file/dir list
|
|
($bannedFileFound) ||
|
|
// A local folder that isn't the doc root or starts with the doc root
|
|
("getRemoteFile" !== $_GET['action'] && !isset($ftpSite) &&
|
|
rtrim($allFiles[$i], "/") !== rtrim($docRoot, "/") &&
|
|
0 !== strpos(realpath(rtrim(dirname($allFiles[$i]), "/")), realpath(rtrim($docRoot, "/")))
|
|
) ||
|
|
// Or a remote URL that doesn't start http
|
|
("getRemoteFile" === $_GET['action'] && 0 !== strpos($allFiles[$i], "http"))
|
|
) {
|
|
$error = true;
|
|
$errorStr = "true";
|
|
$errorMsg = "Sorry! - problem with file requested";
|
|
};
|
|
}
|
|
}
|
|
|
|
public function updateUI() {
|
|
global $fileLoc, $fileName;
|
|
|
|
$doNext = "";
|
|
// Reload file manager, rename tab & remove old file highlighting if it was a new file
|
|
if (isset($_POST['newFileName']) && "" != $_POST['newFileName']) {
|
|
$doNext .= 'ICEcoder.selectedFiles=[]; ICEcoder.updateFileManagerList(\'add\', \'' . $fileLoc . '\', \'' . $fileName . '\', false, false, false, \'file\');';
|
|
$doNext .= 'ICEcoder.renameTab(ICEcoder.selectedTab, \'' . $fileLoc . "/" . $fileName . '\');';
|
|
if (!strpos($_REQUEST['file'], "[NEW]")) {
|
|
// We're saving as a new file, so unhighlight the old name in the file manager if visible
|
|
$doNext .= "fileLink = ICEcoder.filesFrame.contentWindow.document.getElementById('" . str_replace("/", "|", $fileLoc) . "|". basename($_REQUEST['file']). "');";
|
|
$doNext .= "if (fileLink) {fileLink.style.backgroundColor = ICEcoder.tabBGnormal; fileLink.style.color = ICEcoder.tabFGnormalFile};";
|
|
}
|
|
}
|
|
|
|
return $doNext;
|
|
}
|
|
|
|
public function updateFileManager($action, $fileLoc, $fileName, $perms, $oldFile, $uploaded, $fileOrFolder) {
|
|
global $doNext;
|
|
$doNext .= "ICEcoder.updateFileManagerList('" .
|
|
$action . "', '" .
|
|
$fileLoc . "', '" .
|
|
$fileName . "', '" .
|
|
$perms . "', '" .
|
|
$oldFile . "', '" .
|
|
$uploaded . "', '" .
|
|
$fileOrFolder . "');";
|
|
|
|
return $doNext;
|
|
}
|
|
|
|
public function load() {
|
|
global $file, $fileLoc, $fileName, $t, $ftpConn, $ftpHost, $ftpLogin, $ftpRoot, $ftpUser, $ftpMode;
|
|
echo 'action="load";';
|
|
$lineNumber = max(isset($_REQUEST['lineNumber']) ? intval($_REQUEST['lineNumber']) : 1, 1);
|
|
// Check this file isn't on the banned list at all
|
|
$canOpen = true;
|
|
for ($i = 0; $i < count($_SESSION['bannedFiles']); $i++) {
|
|
if ("" !== str_replace("*", "", $_SESSION['bannedFiles'][$i]) && false !== strpos($file, str_replace("*", "", $_SESSION['bannedFiles'][$i]))) {
|
|
$canOpen = false;
|
|
}
|
|
}
|
|
|
|
if (false === $canOpen) {
|
|
echo 'fileType="nothing"; parent.parent.ICEcoder.message(\'' . $t['Sorry, could not...'] . ' ' . $fileLoc . "/" . $fileName . '\');';
|
|
} elseif (isset($ftpSite) || file_exists($file)) {
|
|
$finfo = "text";
|
|
// Determine what to do based on mime type
|
|
if (!isset($ftpSite) && function_exists('finfo_open')) {
|
|
$finfoMIME = finfo_open(FILEINFO_MIME);
|
|
$finfo = finfo_file($finfoMIME, $file);
|
|
finfo_close($finfoMIME);
|
|
} else {
|
|
$fileExt = explode(" ", pathinfo($file, PATHINFO_EXTENSION));
|
|
$fileExt = $fileExt[0];
|
|
if (false !== array_search($fileExt, ["gif", "jpg", "jpeg", "png"])) {
|
|
$finfo = "image";
|
|
};
|
|
if (false !== array_search($fileExt, ["doc", "docx", "ppt", "rtf", "pdf", "zip", "tar", "gz", "swf", "asx", "asf", "midi", "mp3", "wav", "aiff", "mov", "qt", "wmv", "mp4", "odt", "odg", "odp"])) {
|
|
$finfo = "other";
|
|
};
|
|
}
|
|
if (0 === strpos($finfo, "text") || 0 === strpos($finfo, "application/xml") || false !== strpos($finfo, "empty")) {
|
|
echo 'fileType="text";';
|
|
echo 'parent.parent.ICEcoder.shortURL = parent.parent.ICEcoder.thisFileFolderLink = "' . $fileLoc . "/" . $fileName . '";';
|
|
|
|
// Get file over FTP?
|
|
if (isset($ftpSite)) {
|
|
$this->ftpClass->ftpStart();
|
|
// Show user warning if no good connection
|
|
if (!$ftpConn || !$ftpLogin) {
|
|
die('parent.parent.ICEcoder.message("Sorry, no FTP connection to ' . $ftpHost . ' for user ' . $ftpUser . '");parent.parent.ICEcoder.serverMessage();parent.parent.ICEcoder.serverQueue("del",0);</script>');
|
|
}
|
|
// Get our file contents and close the FTP connection
|
|
$loadedFile = toUTF8noBOM($this->ftpClass->ftpGetContents($ftpConn, $ftpRoot . $fileLoc . "/" . $fileName, $ftpMode), false);
|
|
$this->ftpClass->ftpEnd();
|
|
// Get local file
|
|
} else {
|
|
$loadedFile = toUTF8noBOM(getData($file), true);
|
|
}
|
|
$encoding = ini_get("default_charset");
|
|
if ("" == $encoding) {
|
|
$encoding = "UTF-8";
|
|
}
|
|
// Get content and set HTML entities on it according to encoding
|
|
$loadedFile = htmlentities($loadedFile, ENT_COMPAT, $encoding);
|
|
// Remove \r chars and replace \n with carriage return HTML entity char
|
|
$loadedFile = preg_replace('/\\r/', '', $loadedFile);
|
|
$loadedFile = preg_replace('/\\n/', ' ', $loadedFile);
|
|
echo '</script><textarea name="loadedFile" id="loadedFile">' . $loadedFile . '</textarea><script>';
|
|
// Run our custom processes
|
|
$extraProcessesClass = new ExtraProcesses($fileLoc, $fileName);
|
|
$extraProcessesClass->onFileLoad();
|
|
} else if (0 === strpos($finfo, "image")) {
|
|
echo 'fileType="image";fileName=\'' . $fileLoc . "/" . $fileName . '\';';
|
|
} else {
|
|
echo 'fileType="other";window.open(\'http://' . $_SERVER['SERVER_NAME'] . $fileLoc . "/" . $fileName . '\');';
|
|
};
|
|
} else {
|
|
echo 'fileType="nothing"; parent.parent.ICEcoder.message(\'' . $t['Sorry'] . ', ' . $fileLoc . "/" . $fileName . ' ' . $t['does not seem...'] . '\');';
|
|
}
|
|
}
|
|
|
|
public function returnLoadTextScript() {
|
|
global $t, $file, $fileLoc, $fileName, $lineNumber, $serverType;
|
|
|
|
$script = 'if ("text" === fileType) {';
|
|
|
|
if (isset($ftpSite) || file_exists($file)) {
|
|
$script .= '
|
|
setTimeout(function() {
|
|
if (!parent.parent.ICEcoder.content.contentWindow.createNewCMInstance) {
|
|
console.log(\'' .$t['There was a...'] . '\');
|
|
window.location.reload(true);
|
|
} else {
|
|
parent.parent.ICEcoder.loadingFile = true;
|
|
// Reset the various states back to their initial setting
|
|
selectedTab = parent.parent.ICEcoder.openFiles.length; // The tab that\'s currently selected
|
|
|
|
// Finally, store all data, show tabs etc
|
|
parent.parent.ICEcoder.createNewTab(false);
|
|
parent.parent.ICEcoder.cMInstances.push(parent.parent.ICEcoder.nextcMInstance);
|
|
parent.parent.ICEcoder.setLayout();
|
|
parent.parent.ICEcoder.content.contentWindow.createNewCMInstance(parent.parent.ICEcoder.nextcMInstance);
|
|
|
|
// Set the value & innerHTML of the code textarea to that of our loaded file plus make it visible (it\'s hidden on ICEcoder\'s load)
|
|
parent.parent.ICEcoder.switchMode();
|
|
cM = parent.parent.ICEcoder.getcMInstance();
|
|
cM.setValue(document.getElementById(\'loadedFile\').value);
|
|
parent.parent.ICEcoder.savedPoints[parent.parent.ICEcoder.selectedTab - 1] = cM.changeGeneration();
|
|
parent.parent.ICEcoder.savedContents[parent.parent.ICEcoder.selectedTab - 1] = cM.getValue();
|
|
parent.parent.document.getElementById(\'content\').style.visibility = \'visible\';
|
|
parent.parent.ICEcoder.switchTab(parent.parent.ICEcoder.selectedTab, \'noFocus\');
|
|
setTimeout(function(){parent.parent.ICEcoder.filesFrame.contentWindow.focus();}, 0);
|
|
|
|
// Then clean it up, set the text cursor, update the display and get the character data
|
|
parent.parent.ICEcoder.contentCleanUp();
|
|
parent.parent.ICEcoder.content.contentWindow[\'cM\' + parent.parent.ICEcoder.cMInstances[parent.parent.ICEcoder.selectedTab - 1]].removeLineClass(parent.parent.ICEcoder[\'cMActiveLinecM\' + parent.parent.ICEcoder.cMInstances[parent.parent.ICEcoder.selectedTab - 1]], "background");
|
|
parent.parent.ICEcoder[\'cMActiveLinecM\'+parent.parent.ICEcoder.selectedTab] = parent.parent.ICEcoder.content.contentWindow[\'cM\' + parent.parent.ICEcoder.cMInstances[parent.parent.ICEcoder.selectedTab - 1]].addLineClass(0, "background", "cm-s-activeLine");
|
|
parent.parent.ICEcoder.nextcMInstance++;
|
|
parent.parent.ICEcoder.openFileMDTs.push(\'' . ("Windows" !== $serverType ? filemtime($file) : "1000000") . '\');
|
|
parent.parent.ICEcoder.openFileVersions.push(' . getVersionsCount($fileLoc, $fileName)['count'] .');
|
|
parent.parent.ICEcoder.updateVersionsDisplay();
|
|
|
|
parent.parent.ICEcoder.goToLine(' . $lineNumber . ');
|
|
parent.parent.ICEcoder.loadingFile = false;
|
|
}
|
|
}, 4);';
|
|
} else {
|
|
$script .= '
|
|
setTimeout(function() {
|
|
if (!parent.parent.ICEcoder.content.contentWindow.createNewCMInstance) {
|
|
console.log(\'' .$t['There was a...'] . '\');
|
|
window.location.reload(true);
|
|
}
|
|
}, 4);';
|
|
}
|
|
|
|
$script .= "}";
|
|
|
|
return $script;
|
|
}
|
|
|
|
public function returnLoadImageScript() {
|
|
global $fileLoc, $fileName, $t;
|
|
$script = '
|
|
if ("image" === fileType) {
|
|
parent.parent.document.getElementById(\'blackMask\').style.visibility = "visible";
|
|
parent.parent.document.getElementById(\'mediaContainer\').innerHTML =
|
|
"<canvas id=\"canvasPicker\" width=\"1\" height=\"1\" style=\"position: absolute; margin: 10px 0 0 10px; cursor: crosshair\" onmouseover=\"parent.parent.ICEcoder.overPopup=true\" onmouseout=\"parent.parent.ICEcoder.overPopup=false\"></canvas>" +
|
|
"<img src=\"' . ((isset($ftpSite) ? $ftpSite : "") . $fileLoc . "/" . $fileName . "?unique=" . microtime(true)) .'\" class=\"whiteGlow\" style=\"border: solid 10px #fff; max-width: 700px; max-height: 500px; background-color: #000; background-image: url(\'assets/images/checkerboard.png\')\" onLoad=\"reducedImgMsg = (this.naturalWidth > 700 || this.naturalHeight > 500) ? \', ' .$t['displayed at'] . '\' + this.width + \' x \' + this.height : \'\'; document.getElementById(\'imgInfo\').innerHTML += \' (\' + this.naturalWidth + \' x \' + this.naturalHeight + reducedImgMsg + \')\'; ICEcoder.initCanvasImage(this); ICEcoder.interactCanvasImage(this)\"><br>" +
|
|
"<div class=\"whiteGlow\" style=\"display: inline-block; margin-top: -10px; border: solid 10px #fff; color: #000; background-color: #fff\" id=\"imgInfo\" onmouseover=\"parent.parent.ICEcoder.overPopup=true\" onmouseout=\"parent.parent.ICEcoder.overPopup=false\">" +
|
|
"<b>' . $fileLoc . "/" . $fileName . '</b>" +
|
|
"</div><br>" +
|
|
"<div id=\"canvasPickerColorInfo\">"+
|
|
"<input type=\"text\" id=\"hexMouseXY\" style=\"border: 1px solid #888; border-right: 0; width: 70px\" onmouseover=\"parent.parent.ICEcoder.overPopup=true\" onmouseout=\"parent.parent.ICEcoder.overPopup=false\"></input>" +
|
|
"<input type=\"text\" id=\"rgbMouseXY\" style=\"border: 1px solid #888; margin-right: 10px; width: 70px\" onmouseover=\"parent.parent.ICEcoder.overPopup=true\" onmouseout=\"parent.parent.ICEcoder.overPopup=false\"></input>" +
|
|
"<input type=\"text\" id=\"hex\" style=\"border: 1px solid #888; border-right: 0; width: 70px\" onmouseover=\"parent.parent.ICEcoder.overPopup=true\" onmouseout=\"parent.parent.ICEcoder.overPopup=false\"></input>" +
|
|
"<input type=\"text\" id=\"rgb\" style=\"border: 1px solid #888; width: 70px\" onmouseover=\"parent.parent.ICEcoder.overPopup=true\" onmouseout=\"parent.parent.ICEcoder.overPopup=false\"></input>"+
|
|
"</div>"+
|
|
"<div id=\"canvasPickerCORSInfo\" style=\"display: none; padding-top: 4px\">CORS not enabled on resource site</div>";
|
|
parent.parent.document.getElementById(\'floatingContainer\').style.background = "#fff url(\'' .($fileLoc . "/" . $fileName . "?unique=" . microtime(true)) .'\') no-repeat 0 0";
|
|
}';
|
|
|
|
return $script;
|
|
}
|
|
|
|
public function handleSaveLooparound($fileDetails, $finalAction, $t) {
|
|
global $newFileAutoSave, $tabNum;
|
|
|
|
$docRoot = $fileDetails['docRoot'];
|
|
$fileLoc = $fileDetails['fileLoc'];
|
|
$fileURL = $fileDetails['fileURL'];
|
|
$fileName = $fileDetails['fileName'];
|
|
$fileMDTURLPart = $fileDetails['fileMDTURLPart'];
|
|
$fileVersionURLPart = $fileDetails['fileVersionURLPart'];
|
|
$ftpSite = $fileDetails['ftpSite'];
|
|
|
|
$doNext = '
|
|
ICEcoder.serverMessage();
|
|
fileLoc = "' . $fileLoc . '";
|
|
overwriteOK = false;
|
|
noConflictSave = false;
|
|
newFileName = ICEcoder.getInput("' . $t['Enter filename to...'] . ' " + (fileLoc!="" ? fileLoc : "/"), "");
|
|
if (newFileName) {
|
|
if ("/" !== newFileName.substr(0,1)) {newFileName = "/" + newFileName};
|
|
newFileName = fileLoc + newFileName;
|
|
|
|
/* Check if file/dir exists */
|
|
ICEcoder.lastFileDirCheckStatusObj = false;
|
|
ICEcoder.checkExists(newFileName);
|
|
var thisInt = setInterval(function() {
|
|
if (false != ICEcoder.lastFileDirCheckStatusObj) {
|
|
clearInterval(thisInt);
|
|
|
|
if (ICEcoder.lastFileDirCheckStatusObj.file && ICEcoder.lastFileDirCheckStatusObj.file.exists) {
|
|
overwriteOK = ICEcoder.ask("' . $t['That file exists...'] . '");
|
|
} else {
|
|
noConflictSave = true;
|
|
};
|
|
|
|
/* Saving under conditions: Confirmation of overwrite or there is no filename conflict, it is a new file, in either case we can save */
|
|
if (overwriteOK || noConflictSave) {
|
|
newFileName = "' . (true === $ftpSite ? "" : $docRoot) . '" + newFileName;
|
|
saveURL = "lib/file-control.php?action=save' . $fileMDTURLPart . $fileVersionURLPart . '&csrf=' . $_GET["csrf"] . '";
|
|
|
|
var xhr = ICEcoder.xhrObj();
|
|
|
|
xhr.onreadystatechange=function() {
|
|
if (4 === xhr.readyState && 200 === xhr.status) {
|
|
/* console.log(xhr.responseText); */
|
|
var statusObj = JSON.parse(xhr.responseText);
|
|
/* Set the actions end time and time taken in JSON object */
|
|
statusObj.action.timeEnd = new Date().getTime();
|
|
statusObj.action.timeTaken = statusObj.action.timeEnd - statusObj.action.timeStart;
|
|
/* console.log(statusObj); */
|
|
|
|
if (statusObj.status.error) {
|
|
ICEcoder.message(statusObj.status.errorMsg);
|
|
} else {
|
|
eval(statusObj.action.doNext);
|
|
}
|
|
}
|
|
};
|
|
|
|
/* console.log(\'Calling \' + saveURL + \' via XHR\'); */
|
|
xhr.open("POST",saveURL,true);
|
|
xhr.setRequestHeader(\'Content-type\', \'application/x-www-form-urlencoded\');
|
|
xhr.send(\'timeStart=' . numClean($_POST["timeStart"]) . '&file=' . $fileURL . '&newFileName=\' + newFileName.replace(/\\\+/g, "%2B") + \'&contents=\' + encodeURIComponent(ICEcoder.saveAsContent));
|
|
ICEcoder.serverMessage("<b>' . $t['Saving'] . '</b><br>" + "'.("Save" === $finalAction ? "newFileName" : "'" . $fileName . "'") . '");
|
|
}
|
|
}
|
|
}, 10);' .
|
|
($newFileAutoSave
|
|
? '} else {ICEcoder.closeTab(' . ($tabNum ?? 'ICEcoder.selectedTab') . ', "dontSetPV", "dontAsk");'
|
|
: ''
|
|
) .
|
|
'};
|
|
|
|
/* UI dialog cancelling and saving contents for save as looparound */
|
|
if (!newFileName || newFileName && !overwriteOK) {
|
|
ICEcoder.saveAsContent = document.getElementById(\'saveTemp1\').value;
|
|
ICEcoder.serverMessage();ICEcoder.serverQueue("del", 0);
|
|
}
|
|
';
|
|
|
|
return $doNext;
|
|
}
|
|
|
|
public function writeFile() {
|
|
global $file, $t, $ICEcoder, $serverType, $doNext, $contents, $systemClass, $tabNum;
|
|
if (isset($_POST['changes'])) {
|
|
// Get existing file contents as lines and stitch changes onto it
|
|
$fileLines = file($file);
|
|
$contents = $this->systemClass->stitchChanges($fileLines, $_POST['changes']);
|
|
|
|
// get old file contents, and count stats on usage \n and \r there
|
|
// in this case we can keep line endings, which file had before, without
|
|
// making code version control systems going crazy about line endings change in whole file.
|
|
$oldContents = file_exists($file) ? getData($file) : '';
|
|
$unixNewLines = preg_match_all('/[^\r][\n]/u', $oldContents);
|
|
$windowsNewLines = preg_match_all('/[\r][\n]/u', $oldContents);
|
|
} else {
|
|
$contents = $_POST['contents'];
|
|
}
|
|
|
|
// Newly created files have the perms set too
|
|
$setPerms = (!file_exists($file)) ? true : false;
|
|
$systemClass->invalidateOPCache($file);
|
|
$fh = fopen($file, 'w') or die($t['Sorry, cannot save']);
|
|
|
|
// replace \r\n (Windows), \r (old Mac) and \n (Linux) line endings with whatever we chose to be lineEnding
|
|
$contents = str_replace("\r\n", $ICEcoder["lineEnding"], $contents);
|
|
$contents = str_replace("\r", $ICEcoder["lineEnding"], $contents);
|
|
$contents = str_replace("\n", $ICEcoder["lineEnding"], $contents);
|
|
if (isset($_POST['changes']) && (0 < $unixNewLines) || (0 < $windowsNewLines)) {
|
|
if ($unixNewLines > $windowsNewLines){
|
|
$contents = str_replace($ICEcoder["lineEnding"], "\n", $contents);
|
|
} elseif ($windowsNewLines > $unixNewLines){
|
|
$contents = str_replace($ICEcoder["lineEnding"], "\r\n", $contents);
|
|
}
|
|
}
|
|
// Now write that content, close the file and clear the statcache
|
|
fwrite($fh, $contents);
|
|
fclose($fh);
|
|
|
|
if ($setPerms) {
|
|
chmod($file, octdec($ICEcoder['newFilePerms']));
|
|
}
|
|
clearstatcache();
|
|
$filemtime = "Windows" !== $serverType ? filemtime($file) : "1000000";
|
|
$doNext .= 'ICEcoder.openFileMDTs[' . ($tabNum ?? 'ICEcoder.selectedTab') .' - 1] = "' . $filemtime . '";';
|
|
$doNext .= '(function() {var x = ICEcoder.openFileVersions; var y = ' . ($tabNum ?? 'ICEcoder.selectedTab') .' - 1; x[y] = "undefined" != typeof x[y] ? x[y] + 1 : 1})(); ICEcoder.updateVersionsDisplay();';
|
|
}
|
|
|
|
/**
|
|
* @param $filePath
|
|
*/
|
|
public function download($filePath)
|
|
{
|
|
header("Pragma: public");
|
|
header("Expires: 0");
|
|
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
|
|
header("Cache-Control: public");
|
|
header('Content-Description: File Transfer');
|
|
header("Content-Type: application/octet-stream");
|
|
header('Content-Disposition: attachment; filename=' . basename($filePath));
|
|
// header("Content-Transfer-Encoding: binary");
|
|
header('Content-Length: ' . filesize($filePath));
|
|
ob_clean();
|
|
flush();
|
|
readfile($filePath);
|
|
}
|
|
|
|
public function delete() {
|
|
global $filesArray, $docRoot, $iceRoot, $doNext, $t, $demoMode, $ICEcoder, $finalAction;
|
|
|
|
for ($i = 0;$i < count($filesArray); $i++) {
|
|
$fullPath = str_replace($docRoot, "", $filesArray[$i]);
|
|
$fullPath = str_replace($iceRoot, "", $fullPath);
|
|
$fullPath = $docRoot . $iceRoot . $fullPath;
|
|
|
|
if (rtrim($fullPath, "/") === rtrim($docRoot, "/")) {
|
|
$doNext .= "ICEcoder.message('" . $t['Sorry, cannot delete...'] . "');";
|
|
} else if (!$demoMode && is_writable($fullPath)) {
|
|
if (is_dir($fullPath)) {
|
|
$this->rrmdir($fullPath);
|
|
} else {
|
|
// Delete file to tmp dir or full delete
|
|
$ICEcoder['deleteToTmp']
|
|
? rename($fullPath, str_replace("\\", "/", dirname(__FILE__)) . "/../tmp/." . str_replace(":", "_", str_replace("/", "_", $fullPath)))
|
|
: unlink($fullPath);
|
|
}
|
|
$fileName = basename($fullPath);
|
|
$fileLoc = dirname(str_replace($docRoot, "", $fullPath));
|
|
if ($fileLoc=="" || "\\" === $fileLoc) {
|
|
$fileLoc="/";
|
|
};
|
|
|
|
// Reload file manager
|
|
$doNext .= 'ICEcoder.selectedFiles = []; ICEcoder.updateFileManagerList(\'delete\', \'' . $fileLoc . '\', \'' . $fileName . '\');';
|
|
$finalAction = "delete";
|
|
|
|
// Run any extra processes
|
|
$extraProcessesClass = new ExtraProcesses($fileLoc, $fileName);
|
|
$doNext = $extraProcessesClass->onFileDirDelete($doNext);
|
|
} else {
|
|
$doNext .= "ICEcoder.message('" . $t['Sorry, cannot delete'] . "\\\\n" . str_replace($docRoot, "", $fullPath) . "');";
|
|
$finalAction = "nothing";
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $dir
|
|
*/
|
|
public function rrmdir($dir) {
|
|
global $ICEcoder;
|
|
|
|
if (is_dir($dir)) {
|
|
$objects = scandir($dir);
|
|
foreach ($objects as $object) {
|
|
if ("." !== $object && ".." !== $object) {
|
|
if ("dir" === filetype($dir . "/" . $object)) {
|
|
$this->rrmdir($dir . "/" . $object);
|
|
} else {
|
|
$ICEcoder['deleteToTmp']
|
|
? rename($dir . "/" . $object, str_replace("\\", "/", dirname(__FILE__)) . "/../tmp/." . str_replace(":", "_", str_replace("/", "_", $dir)) . "/" . $object)
|
|
: unlink($dir . "/" . $object);
|
|
}
|
|
}
|
|
}
|
|
reset($objects);
|
|
$ICEcoder['deleteToTmp']
|
|
? rename($dir, str_replace("\\", "/", dirname(__FILE__)) . "/../tmp/." . str_replace(":", "_", str_replace("/", "_", $dir)))
|
|
: rmdir($dir);
|
|
}
|
|
}
|
|
|
|
public function paste() {
|
|
global $source, $dest, $ICEcoder;
|
|
|
|
if (is_dir($source)) {
|
|
$fileOrFolder = "folder";
|
|
if (!is_dir($dest)) {
|
|
mkdir($dest, octdec($ICEcoder['newDirPerms']));
|
|
} else {
|
|
for ($i = 2; $i < 1000000000; $i++) {
|
|
if (!is_dir($dest . " (" . $i . ")")) {
|
|
$dest = $dest." (" . $i . ")";
|
|
mkdir($dest, octdec($ICEcoder['newDirPerms']));
|
|
$i = 1000000000;
|
|
}
|
|
}
|
|
}
|
|
foreach ($iterator = new RecursiveIteratorIterator(
|
|
new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS),
|
|
RecursiveIteratorIterator::SELF_FIRST) as $item
|
|
) {
|
|
if ($item->isDir()) {
|
|
mkdir($dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName(), octdec($ICEcoder['newDirPerms']));
|
|
} else {
|
|
copy($item, $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName());
|
|
}
|
|
}
|
|
} else {
|
|
$fileOrFolder = "file";
|
|
if (!file_exists($dest)) {
|
|
copy($source, $dest);
|
|
} else {
|
|
for ($i = 2; $i < 1000000000; $i++) {
|
|
if (!file_exists($dest . " (" . $i . ")")) {
|
|
$dest = $dest . " (" . $i . ")";
|
|
copy($source, $dest);
|
|
$i = 1000000000;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $fileOrFolder;
|
|
}
|
|
|
|
public function loadAndShowDiff() {
|
|
global $file, $fileLoc, $fileName, $doNext, $filemtime, $finalAction, $t;
|
|
// Only applicable for local files
|
|
$loadedFile = toUTF8noBOM(getData($file), true);
|
|
$fileCountInfo = getVersionsCount($fileLoc, $fileName);
|
|
$doNext .= '
|
|
var loadedFile = document.createElement("textarea");
|
|
loadedFile.value = "' . str_replace('"', '\\\"', str_replace("\r", "\\\\r", str_replace("\n", "\\\\n", str_replace("</textarea>", "<ICEcoder:/:textarea>", $loadedFile)))).'";
|
|
var refreshFile = ICEcoder.ask("' . $t['Sorry, this file...'] . '\\\n' . $file . '\\\n\\\n' . $t['Reload this file...'] . '");
|
|
if (refreshFile) {
|
|
var cM = ICEcoder.getcMInstance();
|
|
var thisTab = ICEcoder.selectedTab;
|
|
var userVersionFile = cM.getValue();
|
|
/* Revert back to original */
|
|
cM.setValue(loadedFile.value);
|
|
ICEcoder.savedPoints[thisTab - 1] = cM.changeGeneration();
|
|
ICEcoder.savedContents[thisTab - 1] = cM.getValue();
|
|
ICEcoder.openFileMDTs[ICEcoder.selectedTab - 1] = "' . $filemtime . '";
|
|
ICEcoder.openFileVersions[ICEcoder.selectedTab - 1] = "' . $fileCountInfo['count'] . '";
|
|
cM.clearHistory();
|
|
/* Now for the new version in the diff pane */
|
|
ICEcoder.setSplitPane(\'on\');
|
|
var cMdiff = ICEcoder.getcMdiffInstance();
|
|
cMdiff.setValue(userVersionFile);
|
|
};';
|
|
$finalAction = "nothing";
|
|
}
|
|
|
|
public function upload($uploads) {
|
|
global $docRoot, $iceRoot, $ICEcoder, $doNext, $t;
|
|
|
|
$uploadDir = $docRoot . $iceRoot . str_replace("..", "", str_replace("|", "/", $_POST['folder'] . "/"));
|
|
foreach($uploads as $current) {
|
|
$uploadedFile = $uploadDir . $current->name;
|
|
$fileName = $current->name;
|
|
// Get & set existing perms for existing files, or set to newFilePerms setting for new files
|
|
if (file_exists($uploadedFile)) {
|
|
$chmodInfo = substr(sprintf('%o', fileperms($uploadedFile)), -4);
|
|
$setPerms = substr($chmodInfo, 1, 3); // reduces 0755 down to 755
|
|
} else {
|
|
$setPerms = $ICEcoder['newFilePerms'];
|
|
}
|
|
if ($this->uploadThisFile($current, $uploadedFile, $setPerms)) {
|
|
$doNext .= 'parent.parent.ICEcoder.updateFileManagerList(\'add\', parent.parent.ICEcoder.selectedFiles[parent.parent.ICEcoder.selectedFiles.length - 1].replace(/\|/g, \'/\'), \'' . str_replace("'", "\'", $fileName) . '\', false, false, true, \'file\'); parent.parent.ICEcoder.serverMessage("' . $t['Uploaded file(s) OK'] . '");setTimeout(function(){parent.parent.ICEcoder.serverMessage();}, 2000);';
|
|
$finalAction = "upload";
|
|
} else {
|
|
$doNext .= "parent.parent.ICEcoder.message('" . $t['Sorry, cannot upload'] . " \\\\n" . $fileName . "\\\\n " . $t['into'] . " \\\\n' + parent.parent.ICEcoder.selectedFiles[parent.parent.ICEcoder.selectedFiles.length - 1].replace(/\|/g, '/'));";
|
|
$finalAction = "nothing";
|
|
}
|
|
}
|
|
|
|
return $finalAction;
|
|
}
|
|
|
|
private function uploadThisFile($current, $uploadFile, $setPerms){
|
|
if (move_uploaded_file($current->tmp_name, $uploadFile)){
|
|
chmod($uploadFile, octdec($setPerms));
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
public function getUploadedDetails($fileArr) {
|
|
$uploads = [];
|
|
foreach($fileArr['name'] as $keyee => $info) {
|
|
$uploads[$keyee]->name = xssClean($fileArr['name'][$keyee], "html");
|
|
$uploads[$keyee]->type = $fileArr['type'][$keyee];
|
|
$uploads[$keyee]->tmp_name = $fileArr['tmp_name'][$keyee];
|
|
$uploads[$keyee]->error = $fileArr['error'][$keyee];
|
|
}
|
|
return $uploads;
|
|
}
|
|
|
|
public function handleMarkdown() {
|
|
// Reload previewWindow window if not a Markdown file
|
|
// In doing this, we check on an interval for the page to be complete and if we last saw it loading
|
|
// When we are done loading, so set the loading status to false and load plugins on..
|
|
$doNext = 'if (ICEcoder.previewWindow.location && ICEcoder.previewWindow.location.pathname && -1 === ICEcoder.previewWindow.location.pathname.indexOf(".md")) {
|
|
ICEcoder.previewWindowLoading = false;
|
|
ICEcoder.previewWindow.location.reload(true);
|
|
|
|
ICEcoder.checkPreviewWindowLoadingInt = setInterval(function() {
|
|
if ("loading" !== ICEcoder.previewWindow.document.readyState && ICEcoder.previewWindowLoading) {
|
|
ICEcoder.previewWindowLoading = false;
|
|
try {ICEcoder.doPesticide();} catch(err) {};
|
|
try {ICEcoder.doStatsJS(\'save\');} catch(err) {};
|
|
try {ICEcoder.doResponsive();} catch(err) {};
|
|
clearInterval(ICEcoder.checkPreviewWindowLoadingInt);
|
|
} else {
|
|
ICEcoder.previewWindowLoading = "loading" === ICEcoder.previewWindow.document.readyState ? true : false;
|
|
}
|
|
}, 4);
|
|
|
|
};';
|
|
|
|
return $doNext;
|
|
}
|
|
|
|
public function handleDiffPane() {
|
|
global $tabNum;
|
|
// Copy over content to diff pane if we have that setting on
|
|
$doNext = '
|
|
cM = ICEcoder.getcMInstance('. ($tabNum ?? 'ICEcoder.selectedTab') .');
|
|
cMdiff = ICEcoder.getcMdiffInstance('. ($tabNum ?? 'ICEcoder.selectedTab') .');
|
|
if (ICEcoder.updateDiffOnSave) {
|
|
cMdiff.setValue(cM.getValue());
|
|
};
|
|
';
|
|
|
|
return $doNext;
|
|
}
|
|
|
|
public function finaliseSave() {
|
|
global $tabNum;
|
|
|
|
// Finally, set previous files, indicate changes, set saved points and redo tabs
|
|
$doNext = '
|
|
ICEcoder.setPreviousFiles();
|
|
setTimeout(function(){ICEcoder.indicateChanges()}, 4);
|
|
ICEcoder.savedPoints[' . ($tabNum ?? 'ICEcoder.selectedTab') .' - 1] = cM.changeGeneration();
|
|
ICEcoder.savedContents[' . ($tabNum ?? 'ICEcoder.selectedTab') .' - 1] = cM.getValue();
|
|
ICEcoder.redoTabHighlight(' . ($tabNum ?? 'ICEcoder.selectedTab') .');
|
|
ICEcoder.switchTab(ICEcoder.selectedTab);';
|
|
|
|
return $doNext;
|
|
}
|
|
|
|
public function compileSass() {
|
|
global $docRoot, $fileLoc, $fileName, $systemClass;
|
|
|
|
$doNext = "";
|
|
|
|
// Compiling Sass files (.scss to .css, with same name, in same dir)
|
|
$filePieces = explode(".", $fileName);
|
|
$fileExt = $filePieces[count($filePieces) - 1];
|
|
|
|
// SCSS Compiling if we have SCSSPHP plugin installed
|
|
if (strtolower($fileExt) == "scss" && file_exists(dirname(__FILE__) . "/../plugins/scssphp/scss.inc.php")) {
|
|
// Load the SCSSPHP lib and start a new instance
|
|
require dirname(__FILE__) . "/../plugins/scssphp/scss.inc.php";
|
|
$scss = new scssc();
|
|
|
|
// Set the import path and formatting type
|
|
$scss->setImportPaths($docRoot . $fileLoc . "/");
|
|
$scss->setFormatter('scss_formatter_compressed'); // scss_formatter, scss_formatter_nested, scss_formatter_compressed
|
|
|
|
if (true === is_writable($docRoot . $fileLoc)) {
|
|
$scssContent = $scss->compile('@import "' . $fileName . '"');
|
|
$systemClass->invalidateOPCache($docRoot . $fileLoc . "/" . substr($fileName, 0, -4) . "css");
|
|
$fh = fopen($docRoot . $fileLoc . "/" . substr($fileName, 0, -4) . "css", 'w');
|
|
fwrite($fh, $scssContent);
|
|
fclose($fh);
|
|
} else {
|
|
$doNext .= ";ICEcoder.message('Could not compile your Sass, dir not writable.');";
|
|
}
|
|
}
|
|
|
|
return $doNext;
|
|
}
|
|
|
|
public function compileLess() {
|
|
global $docRoot, $fileLoc, $fileName;
|
|
|
|
$doNext = "";
|
|
|
|
// Compiling LESS files (.less to .css, with same name, in same dir)
|
|
$filePieces = explode(".", $fileName);
|
|
$fileExt = $filePieces[count($filePieces) - 1];
|
|
|
|
// Less Compiling if we have LESSPHP plugin installed
|
|
if (strtolower($fileExt) == "less" && file_exists(dirname(__FILE__) . "/../plugins/lessphp/lessc.inc.php")) {
|
|
// Load the LESSPHP lib and start a new instance
|
|
require dirname(__FILE__) . "/../plugins/lessphp/lessc.inc.php";
|
|
$less = new lessc();
|
|
|
|
// Set the formatting type and if we want to preserve comments
|
|
$less->setFormatter('lessjs'); // lessjs (same style used in LESS for JS), compressed (no whitespace) or classic (LESSPHP's original formatting)
|
|
$less->setPreserveComments(false); // true or false
|
|
|
|
if (true === is_writable($docRoot . $fileLoc)) {
|
|
$less->checkedCompile($docRoot . $fileLoc . "/" . $fileName, $docRoot . $fileLoc . "/" . substr($fileName, 0, -4) . "css"); // Note: Only recompiles if changed
|
|
} else {
|
|
$doNext .= ";ICEcoder.message('Could not compile your LESS, dir not writable.');";
|
|
}
|
|
}
|
|
|
|
return $doNext;
|
|
}
|
|
|
|
public function returnJSON() {
|
|
global $ftpSite, $ftpConn, $fileLoc, $fileName, $ftpRoot, $file, $filemtime, $finalAction, $timeStart, $error, $errorStr, $errorMsg, $doNext;
|
|
|
|
if (isset($ftpSite)) {
|
|
// Get info on dir/file now
|
|
$ftpFileDirInfo = $this->ftpClass->ftpGetFileInfo($ftpConn, ltrim($fileLoc, "/"), $fileName);
|
|
// End the connection
|
|
$this->ftpClass->ftpEnd();
|
|
// Then set info
|
|
$itemAbsPath = $ftpRoot . $fileLoc . '/' . $fileName;
|
|
$itemPath = dirname($ftpRoot.$fileLoc . '/' . $fileName);
|
|
$itemBytes = $ftpFileDirInfo['size'];
|
|
$itemType = (isset($ftpFileDirInfo['type']) ? ("directory" === $ftpFileDirInfo['type'] ? "dir" : "file") : "unknown");
|
|
$itemExists = (isset($ftpFileDirInfo['type']) ? "true" : "false");
|
|
} else {
|
|
$itemAbsPath = $file;
|
|
$itemPath = dirname($file);
|
|
$itemBytes = is_dir($file) ? null : filesize($file);
|
|
$itemType = (file_exists($file) ? (is_dir($file) ? "dir" : "file") : "unknown");
|
|
$itemExists = (file_exists($file) ? "true" : "false");
|
|
}
|
|
|
|
return '{
|
|
"file": {
|
|
"absPath": "' . $itemAbsPath . '",
|
|
"relPath": "' . $fileLoc . '/' . $fileName . '",
|
|
"name": "' . $fileName . '",
|
|
"path": "' . $itemPath . '",
|
|
"bytes": "' . $itemBytes . '",
|
|
"modifiedDT": "' . $filemtime . '",
|
|
"type": "' . $itemType . '",
|
|
"exists": ' . $itemExists . '
|
|
},
|
|
"action": {
|
|
"initial" : "' . xssClean($_GET['action'], "html") . '",
|
|
"final" : "' . $finalAction . '",
|
|
"timeStart": ' . $timeStart . ',
|
|
"timeEnd": 0,
|
|
"timeTaken": 0,
|
|
"csrf": "' . xssClean($_GET['csrf'], "html") . '",
|
|
"doNext" : "' . preg_replace('/\r|\n/', '', str_replace(' ', '', str_replace('"', '\"', $doNext))) . 'ICEcoder.switchMode();"
|
|
},
|
|
"status": {
|
|
"error" : ' . ($error ? 'true' : 'false') . ',
|
|
"errorStr" : "' . $errorStr . '",
|
|
"errorMsg" : "' . $errorMsg . '"
|
|
}
|
|
}';
|
|
}
|
|
}
|