* @copyrights (c) 2016, 2024, 5 Mode
* @license https://opensource.org/licenses/BSD-3-Clause
*/
require "HC_init.inc";
$cmdHistory = [];
$cmd = HC_STR;
$opt = HC_STR;
$param1 = HC_STR;
$param2 = HC_STR;
$param3 = HC_STR;
$cmdRecallHistory = [];
function showHistory() {
global $cmdHistory;
$i = 1;
foreach($cmdHistory as $val) {
echo(str_replace("\n", "
", $val));
$i++;
}
}
function updateHistory(&$update, $maxItems) {
global $cmdHistory;
// Making enough space in $cmdHistory for the update..
$shift = (count($cmdHistory) + count($update)) - $maxItems;
if ($shift > 0) {
$cmdHistory = array_slice($cmdHistory, $shift, $maxItems);
}
// Adding $cmdHistory update..
if (count($update) > $maxItems) {
$beginUpd = count($update) - ($maxItems-1);
} else {
$beginUpd = 0;
}
$update = array_slice($update, $beginUpd, $maxItems);
foreach($update as $val) {
$cmdHistory[] = $val;
}
// Writing out $cmdHistory on disk..
$filepath = HC_APP_PATH . HC_SLASH . ".HC_history";
file_put_contents($filepath, implode('', $cmdHistory));
}
function loadRecallHistory() {
global $cmdRecallHistory;
$tmpcmdRecallHistory = file(HC_APP_PATH . HC_SLASH . ".HC_Recallhistory");
foreach($tmpcmdRecallHistory as $val) {
$cmdRecallHistory[left($val, strlen($val)-1)]=$val;
}
}
function updateRecallHistory($update, $maxItems) {
global $cmdRecallHistory;
if (!array_key_exists($update, $cmdRecallHistory)) {
// Making enough space in $cmdHistory for the update..
$shift = (count($cmdRecallHistory) + 1) - $maxItems;
if ($shift > 0) {
$cmdRecallHistory = array_slice($cmdRecallHistory, $shift, $maxItems);
}
$cmdRecallHistory[$update] = $update . "\n";
}
// Writing out $cmdRecallHistory on disk..
$filepath = HC_APP_PATH . HC_SLASH . ".HC_Recallhistory";
file_put_contents($filepath, implode('', $cmdRecallHistory));
}
function updateHistoryWithErr(string $err, bool $withCommand = true)
{
global $prompt;
global $command;
$output = [];
if ($withCommand) {
$output[] = $prompt . " " . $command . "\n";
}
$output[] = "$err\n";
updateHistory($output, HC_HISTORY_MAX_ITEMS);
}
function myExecCommand() {
global $prompt;
global $command;
// Exec command..
$output = [];
$output[] = $prompt . " " . $command . "\n";
exec($command, $output);
// Update history..
foreach ($output as &$val) {
if (right($val,1)!="\n") {
$val = $val . "\n";
}
}
updateRecallHistory($command, HC_RECALL_HISTORY_MAX_ITEMS);
updateHistory($output, HC_HISTORY_MAX_ITEMS);
}
function myExecCopy() {
global $prompt;
global $command;
global $param1;
global $param2;
// Exec command..
$output = [];
$output[] = $prompt . " " . $command . "\n";
copy($param1, $param2);
// Update history..
foreach ($output as &$val) {
if (right($val,1)!="\n") {
$val = $val . "\n";
}
}
updateRecallHistory($command, HC_RECALL_HISTORY_MAX_ITEMS);
updateHistory($output, HC_HISTORY_MAX_ITEMS);
}
function myExecCDFolderCommand() {
global $prompt;
global $command;
global $param1;
global $curPath;
// Exec command..
$output = [];
$output[] = $prompt . " " . $command . "\n";
//exec($command, $output);
$newPath = $curPath . HC_SLASH . $param1;
chdir($newPath);
$curPath = $newPath;
$curDir = $param1;
// Creating the Download folder if doesn't exist..
$downloadPath = $curPath . HC_SLASH . ".HCdownloads";
if (!file_exists($downloadPath)) {
//copy(HC_APP_STAGE_PATH . HC_SLASH . ".HCsampledir", $downloadPath);
$mycmd = "cp -Rp " . HC_APP_STAGE_PATH . HC_SLASH . ".HCsampledir" . " " . $downloadPath;
$myret = exec($mycmd);
}
$prompt = str_replace("$1", $curDir, HC_APP_PROMPT);
// Update history..
foreach ($output as &$val) {
if (right($val,1)!="\n") {
$val = $val . "\n";
}
}
updateRecallHistory($command, HC_RECALL_HISTORY_MAX_ITEMS);
updateHistory($output, HC_HISTORY_MAX_ITEMS);
}
function myExecCDBackwCommand() {
global $prompt;
global $command;
global $curPath;
// Exec command..
$output = [];
$output[] = $prompt . " " . $command . "\n";
//exec($command, $output);
$ipos = strripos($curPath, HC_SLASH);
$newPath = substr($curPath, 0, $ipos);
chdir($newPath);
$curPath = getcwd();
$ipos = strripos($curPath, HC_SLASH);
$curDir = substr($curPath, $ipos);
$prompt = str_replace("$1", $curDir, HC_APP_PROMPT);
// Update history..
foreach ($output as &$val) {
if (right($val,1)!="\n") {
$val = $val . "\n";
}
}
updateRecallHistory($command, HC_RECALL_HISTORY_MAX_ITEMS);
updateHistory($output, HC_HISTORY_MAX_ITEMS);
}
function myExecLSCommand() {
global $prompt;
global $command;
global $curPath;
$downloadPath = $curPath . HC_SLASH . ".HCdownloads";
// Exec command..
$output = [];
$output[] = $prompt . " " . $command . "\n";
exec($command, $output);
// Creating the Download path for the current folder..
if (!file_exists($downloadPath)) {
//copy(HC_APP_STAGE_PATH . HC_SLASH . ".HCsampledir", $downloadPath);
$mycmd = "cp -Rp " . HC_APP_STAGE_PATH . HC_SLASH . ".HCsampledir" . " " . $downloadPath;
$myret=exec($mycmd);
}
// Cleaning the Download folder..
if (file_exists($downloadPath)) {
$files1 = scandir($downloadPath);
foreach($files1 as $file) {
if (!is_dir($downloadPath . HC_SLASH . $file) && $file !== "." && $file !== "..") {
unlink($downloadPath . HC_SLASH . $file);
}
}
}
// Update history..
foreach ($output as &$val) {
if ($val === $prompt . " " . $command . "\n") {
} else {
if (right($val,1)==="\n") {
$val = left($val, strlen($val)-1);
}
// Creating the tmp download for the file entry and generating the virtual path..
$virtualPath = HC_STR;
if (file_exists($downloadPath)) {
if (!is_dir($curPath . HC_SLASH . $val) && filesize($curPath . HC_SLASH . $val)<=651000) {
copy($curPath . HC_SLASH . $val, $downloadPath . HC_SLASH . $val . ".hcd");
$virtualPath = getVirtualPath($downloadPath . HC_SLASH . $val . ".hcd");
}
} else {
$virtualPath=HC_STR;
}
if ($virtualPath!==HC_STR) {
$val = "" . $val . "\n";
} else {
$val = $val . "\n";
}
}
}
updateRecallHistory($command, HC_RECALL_HISTORY_MAX_ITEMS);
updateHistory($output, HC_HISTORY_MAX_ITEMS);
}
function parseCommand() {
global $command;
global $cmd;
global $opt;
global $param1;
global $param2;
global $param3;
$str = trim($command);
$ipos = stripos($str, HC_SPACE);
if ($ipos > 0) {
$cmd = left($str, $ipos);
$str = substr($str, $ipos+1);
} else {
$cmd = $str;
return;
}
if (left($str, 1) === "-") {
$ipos = stripos($str, HC_SPACE);
if ($ipos > 0) {
$opt = left($str, $ipos);
$str = substr($str, $ipos+1);
} else {
$opt = $str;
return;
}
}
$ipos = stripos($str, HC_SPACE);
if ($ipos > 0) {
$param1 = left($str, $ipos);
$str = substr($str, $ipos+1);
} else {
$param1 = $str;
return;
}
$ipos = stripos($str, HC_SPACE);
if ($ipos > 0) {
$param2 = left($str, $ipos);
$str = substr($str, $ipos+1);
} else {
$param2 = $str;
return;
}
$ipos = stripos($str, HC_SPACE);
if ($ipos > 0) {
$param3 = left($str, $ipos);
$str = substr($str, $ipos+1);
} else {
$param3 = $str;
return;
}
}
function cdparamValidation() {
global $curPath;
global $opt;
global $param1;
global $param2;
global $param3;
//opt==""
if ($opt!=HC_STR) {
updateHistoryWithErr("invalid options");
return false;
}
//param1!="" and isword
if (($param1===HC_STR) && !is_word($param1)) {
updateHistoryWithErr("invalid dir");
return false;
}
//param2==""
if ($param2!==HC_STR) {
updateHistoryWithErr("invalid parameters");
return false;
}
//param3==""
if ($param3!=HC_STR) {
updateHistoryWithErr("invalid parameters");
return false;
}
//param1 exist and is_dir
$path = $curPath . HC_SLASH . $param1;
if (!file_exists($path) || !is_dir($path)) {
updateHistoryWithErr("dir doesn't exist");
return false;
}
return true;
}
function is_subfolderdest(string $path): bool
{
global $curPath;
$ret=false;
if ($path!=HC_STR) {
$folderName = left($path, strlen($path)-1);
if (is_dir($curPath . HC_SLASH . $folderName) && (right($path,1)==="/")) {
$ret=true;
}
}
return $ret;
}
function cpparamValidation() {
global $curPath;
global $opt;
global $param1;
global $param2;
global $param3;
//opt!="" and opt!="-R" and opt!="-Rp"
if (($opt!==HC_STR) && ($opt!=="-R") && ($opt!=="-Rp") && ($opt!=="-p")) {
updateHistoryWithErr("invalid options");
return false;
}
//param1!="" and isword
if (($param1===HC_STR) || !is_word($param1)) {
updateHistoryWithErr("invalid source path");
return false;
}
//param2!="" and (isword or param2=="../" or is_subfolderdest)
if (($param2===HC_STR) || (!is_word($param2) && ($param2!="../") && !is_subfolderdest($param2))) {
updateHistoryWithErr("invalid destination path");
return false;
}
//param3==""
if ($param3!=HC_STR) {
updateHistoryWithErr("invalid parameters");
return false;
}
//param1 exist
$path = $curPath . HC_SLASH . $param1;
if (!file_exists($path)) {
updateHistoryWithErr("source must exists");
return false;
}
//isword(param2) && doesn't exist
if (is_word($param2)) {
$path = $curPath . HC_SLASH . $param2;
if (file_exists($path)) {
updateHistoryWithErr("destination already exists");
return false;
}
}
return true;
}
function mvparamValidation() {
global $curPath;
global $opt;
global $param1;
global $param2;
global $param3;
//opt!="" and opt!="-R"
if ($opt!=HC_STR) {
updateHistoryWithErr("invalid options");
return false;
}
//param1!="" and isword
if (($param1===HC_STR) || !is_word($param1)) {
updateHistoryWithErr("invalid source path");
return false;
}
//param2!="" and (isword or param2=="../" or is_subfolderdest)
if (($param2===HC_STR) || (!is_word($param2) && ($param2!="../") && !is_subfolderdest($param2))) {
updateHistoryWithErr("invalid destination path");
return false;
}
//param3!=""
if ($param3!=HC_STR) {
updateHistoryWithErr("invalid parameters");
return false;
}
//param1 exist
$path = $curPath . HC_SLASH . $param1;
if (!file_exists($path)) {
updateHistoryWithErr("source must exists");
return false;
}
//isword(param2) && doesn't exist
if (is_word($param2)) {
$path = $curPath . HC_SLASH . $param2;
if (file_exists($path)) {
updateHistoryWithErr("destination already exists");
return false;
}
}
return true;
}
function upload() {
global $curPath;
global $prompt;
//if (!empty($_FILES['files'])) {
if (!empty($_FILES['files']['tmp_name'][0])) {
// Updating history..
$output = [];
$output[] = $prompt . " " . "File upload" . "\n";
updateHistory($output, HC_HISTORY_MAX_ITEMS);
$uploads = (array)fixMultipleFileUpload($_FILES['files']);
//no file uploaded
if ($uploads[0]['error'] === HC_UPLOAD_ERR_NO_FILE) {
updateHistoryWithErr("No file uploaded.", false);
return;
}
foreach($uploads as &$upload) {
switch ($upload['error']) {
case HC_UPLOAD_ERR_OK:
break;
case HC_UPLOAD_ERR_NO_FILE:
updateHistoryWithErr("One or more uploaded files are missing.", false);
return;
case HC_UPLOAD_ERR_INI_SIZE:
updateHistoryWithErr("File exceeded INI size limit.", false);
return;
case HC_UPLOAD_ERR_FORM_SIZE:
updateHistoryWithErr("File exceeded form size limit.", false);
return;
case HC_UPLOAD_ERR_PARTIAL:
updateHistoryWithErr("File only partially uploaded.", false);
return;
case HC_UPLOAD_ERR_NO_TMP_DIR:
updateHistoryWithErr("TMP dir doesn't exist.", false);
return;
case HC_UPLOAD_ERR_CANT_WRITE:
updateHistoryWithErr("Failed to write to the disk.", false);
return;
case HC_UPLOAD_ERR_EXTENSION:
updateHistoryWithErr("A PHP extension stopped the file upload.", false);
return;
default:
updateHistoryWithErr("Unexpected error happened.", false);
return;
}
if (!is_uploaded_file($upload['tmp_name'])) {
updateHistoryWithErr("One or more file have not been uploaded.", false);
return;
}
// name
$name = (string)substr((string)filter_var($upload['name']), 0, 255);
if ($name == HC_STR) {
updateHistoryWithErr("Invalid file name: " . $name, false);
return;
}
$upload['name'] = $name;
// fileType
$fileType = substr((string)filter_var($upload['type']), 0, 30);
$upload['type'] = $fileType;
// tmp_name
$tmp_name = substr((string)filter_var($upload['tmp_name']), 0, 300);
if ($tmp_name == HC_STR || !file_exists($tmp_name)) {
updateHistoryWithErr("Invalid file temp path: " . $tmp_name, false);
return;
}
$upload['tmp_name'] = $tmp_name;
//size
$size = substr((string)filter_var($upload['size'], FILTER_SANITIZE_NUMBER_INT), 0, 12);
if ($size == "") {
updateHistoryWithErr("Invalid file size.", false);
return;
}
$upload["size"] = $size;
$tmpFullPath = $upload["tmp_name"];
$originalFilename = pathinfo($name, PATHINFO_FILENAME);
$originalFileExt = pathinfo($name, PATHINFO_EXTENSION);
$FileExt = strtolower(pathinfo($name, PATHINFO_EXTENSION));
if ($originalFileExt!==HC_STR) {
$destFileName = $originalFilename . "." . $originalFileExt;
} else {
$destFileName = $originalFilename;
}
$destFullPath = $curPath . PHP_SLASH . $destFileName;
if (file_exists($destFullPath)) {
updateHistoryWithErr("destination already exists", false);
return;
}
copy($tmpFullPath, $destFullPath);
// Updating history..
$output = [];
$output[] = $destFileName . " " . "uploaded" . "\n";
updateHistory($output, HC_HISTORY_MAX_ITEMS);
// Cleaning up..
// Delete the tmp file..
unlink($tmpFullPath);
}
}
}
$password = filter_input(INPUT_POST, "Password");
$command = filter_input(INPUT_POST, "CommandLine");
$pwd = filter_input(INPUT_POST, "pwd");
$hideFB = filter_input(INPUT_POST, "hideFB");
if ($password !== HC_STR) {
$hash = hash("sha256", $password . HC_APP_SALT, false);
if ($hash !== HC_APP_HASH) {
$password=HC_STR;
}
}
$curPath = HC_APP_STAGE_PATH;
if ($pwd!==HC_STR) {
if (left($pwd, strlen(HC_APP_STAGE_PATH)) === HC_APP_STAGE_PATH) {
$curPath = $pwd;
chdir($curPath);
}
}
$ipos = strripos($curPath, HC_SLASH);
$curDir = substr($curPath, $ipos);
$prompt = str_replace("$1", $curDir, HC_APP_PROMPT);
if ($password !== HC_STR) {
loadRecallHistory();
$cmdHistory = file(HC_APP_PATH . HC_SLASH . ".HC_history");
parseCommand($command);
//echo("cmd=" . $cmd . "
");
//echo("opt=" . $opt . "
");
//echo("param1=" . $param1 . "
");
//echo("param2=" . $param2 . "
");
upload();
if (mb_stripos(HC_CMDLINE_VALIDCMDS, "|" . $command . "|")) {
if ($command === "cd ..") {
$ipos = strripos($curPath, HC_SLASH);
$nextPath = substr($curPath, 0, $ipos);
if (strlen(HC_APP_STAGE_PATH) > strlen($nextPath)) {
updateHistoryWithErr("out of root boundary");
} else {
myExecCDBackwCommand();
}
} else if ($command === "ls") {
myExecLSCommand();
} else {
myExecCommand();
}
} else if (mb_stripos(HC_CMDLINE_VALIDCMDS, "|" . $cmd . "|")) {
if ($cmd === "cd") {
if (cdparamValidation()) {
myExecCDFolderCommand();
}
} else if ($cmd === "cp") {
if (cpparamValidation()) {
myExecCommand();
}
} else if ($cmd === "mv") {
if (mvparamValidation()) {
myExecCommand();
}
}
} else {
if (empty($_FILES['files']['tmp_name'][0])) {
updateHistoryWithErr("invalid command");
}
}
} else {
$cmdHistory = [];
}
?>