Files
assetmgt/logfile.php
“VeLiTi” 653e33d7e9 Add software tool functionality with device connection and upgrade options
- Implemented the software tool page with user interface for connecting devices.
- Added functionality to display connection status and software upgrade options.
- Included a help modal with step-by-step instructions for users.
- Integrated error handling and user permission checks.
- Enhanced user experience with dynamic content updates and visual feedback.
2025-12-21 14:16:55 +01:00

244 lines
8.8 KiB
PHP

<?php
defined(page_security_key) or exit;
//Check if allowed
if (isAllowed('logfile',$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
header('location: index.php');
exit;
}
// Define logs directory path
$logs_dir = __DIR__ . '/log/';
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// POST HANDLER - Delete all logs
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
$delete_message = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_all_logs'])) {
$deleted_count = 0;
if (is_dir($logs_dir)) {
$files = scandir($logs_dir);
foreach ($files as $file) {
if (preg_match('/\.(txt|log)$/', $file)) {
if (unlink($logs_dir . $file)) {
$deleted_count++;
}
}
}
}
$delete_message = "Successfully deleted $deleted_count log file(s).";
// Redirect to index page
header("Location: index.php?page=logfile&deleted=$deleted_count");
exit;
}
// Show delete confirmation message
if (isset($_GET['deleted'])) {
$delete_message = "Successfully deleted " . intval($_GET['deleted']) . " log file(s).";
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// DOWNLOAD HANDLER
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if (isset($_GET['download']) && $_GET['download']) {
$filename = $_GET['download'];
$filepath = $logs_dir . $filename;
// Security check: ensure file exists and is within logs directory
if (file_exists($filepath) && strpos(realpath($filepath), realpath($logs_dir)) === 0) {
// Set headers for file download
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Length: ' . filesize($filepath));
header('Cache-Control: must-revalidate');
header('Pragma: public');
// Output file content
readfile($filepath);
exit;
}
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// GET HANDLER
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Get selected log file from query parameter
$selected_log = $_GET['log'] ?? '';
// Scan logs directory for all log files
$log_files = [];
if (is_dir($logs_dir)) {
$files = scandir($logs_dir);
foreach ($files as $file) {
if (preg_match('/\.(txt|log)$/', $file) && is_file($logs_dir . $file)) {
$log_files[] = [
'filename' => $file,
'path' => $logs_dir . $file,
'size' => filesize($logs_dir . $file),
'mtime' => filemtime($logs_dir . $file) // creation/modification time
];
}
}
}
// Sort by creation date descending (newest first)
usort($log_files, function($a, $b) {
return $b['mtime'] <=> $a['mtime'];
});
// Load selected log content
$contents = '';
if ($selected_log && file_exists($logs_dir . $selected_log)) {
$contents = file_get_contents($logs_dir . $selected_log);
} elseif (!empty($log_files)) {
// Default to most recent log
$contents = file_get_contents($log_files[0]['path']);
$selected_log = $log_files[0]['filename'];
} else {
$contents = 'No application log files found.';
}
$filelocation_webserver = '/var/www/vhosts/veliti.nl/logs/'.$_SERVER['HTTP_HOST'].'/access_ssl_log';
if (file_exists($filelocation_webserver)){
$contents_webserver = file_get_contents($filelocation_webserver);
} else {$contents_webserver = 'No webserver log file found.';}
?>
<?=template_header('Log', 'log','view')?>
<?php if ($delete_message): ?>
<div class="msg success" id="delete-notification">
<i class="fas fa-check-circle"></i>
<p><?=$delete_message?></p>
<i class="fas fa-times"></i>
</div>
<?php endif; ?>
<form action="" method="post">
<div class="content-title responsive-flex-wrap responsive-pad-bot-3">
<h2 class="responsive-width-100">Debuglog</h2>
<div style="display: flex; gap: 10px; align-items: center;">
<select id="log-file-selector" onchange="loadLogFile(this.value)" style="padding: 5px 10px; border: 1px solid #ddd; border-radius: 4px;">
<?php foreach ($log_files as $log): ?>
<?php $selected = ($log['filename'] === $selected_log) ? 'selected' : ''; ?>
<?php $size_kb = round($log['size'] / 1024, 2); ?>
<?php $date_str = date('Y-m-d H:i', $log['mtime']); ?>
<option value="<?=htmlspecialchars($log['filename'])?>" <?=$selected?>>
<?=htmlspecialchars($log['filename'])?> (<?=$size_kb?> KB) - <?=$date_str?>
</option>
<?php endforeach; ?>
</select>
<button type="button" onclick="refreshLog()" class="btn" >
<i class="fas fa-sync-alt"></i>
</button>
<button type="button" onclick="downloadLogFile()" class="btn" style="background: #3498db; color: white; border: none; padding: 8px 12px; border-radius: 4px; cursor: pointer;">
<i class="fas fa-download"></i>
</button>
<button type="submit" name="delete_all_logs" onclick="return confirmDeleteAll()" class="btn" style="background: #e74c3c; color: white; border: none; padding: 8px 12px; border-radius: 4px; cursor: pointer;">
<i class="fas fa-trash-alt"></i>
</button>
</div>
</div>
<div class="tabs">
<a href="#" class="active">Application</a>
</div>
<div class="content-block">
<div class="form responsive-width-100">
<div class="tab-content active">
<label for="Logfile">Application Log</label>
<textarea name="logfile" id="logfile" style="min-height: 70vh; font-family: 'Courier New', monospace; font-size: 12px; background: #1e1e1e; color: #f8f8f2; border: 1px solid #333; padding: 15px;"><?=$contents?></textarea>
</div>
<div class="tabs">
<a href="#" class="">Webserver</a>
</div>
<div class="tab-content">
<label for="WebserverLog">Webserver Log</label>
<textarea name="" id="webserver-log" style="min-height: 70vh; font-family: 'Courier New', monospace; font-size: 12px; background: #1e1e1e; color: #f8f8f2; border: 1px solid #333; padding: 15px;"><?=$contents_webserver?></textarea>
</div>
</div>
</div>
</form>
<script>
// Confirm delete all logs
function confirmDeleteAll() {
return confirm('⚠️ WARNING: This will permanently delete ALL log files in the logs directory.\n\nAre you absolutely sure you want to continue?');
}
// Auto-hide delete notification
document.addEventListener('DOMContentLoaded', function() {
const notification = document.getElementById('delete-notification');
if (notification) {
setTimeout(() => {
notification.style.opacity = '0';
notification.style.transition = 'opacity 0.5s ease';
setTimeout(() => notification.remove(), 500);
}, 3000);
}
});
// Load selected log file
function loadLogFile(filename) {
if (filename) {
const url = new URL(window.location.href);
url.searchParams.set('log', filename);
window.location.href = url.toString();
}
}
// Download current log file
function downloadLogFile() {
const selector = document.getElementById('log-file-selector');
const selectedFile = selector.value;
if (selectedFile) {
const url = new URL(window.location.href);
url.searchParams.set('download', selectedFile);
window.location.href = url.toString();
} else {
alert('No log file selected to download.');
}
}
// Refresh log functionality
function refreshLog() {
const button = event.target.closest('button');
const originalHTML = button.innerHTML;
// Show loading state
button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Refreshing...';
button.disabled = true;
// Reload the page to get fresh content
setTimeout(() => {
window.location.reload();
}, 500);
}
// Clear log content from view
function clearLogContent() {
const textarea = document.getElementById('logfile');
if (textarea) {
if (confirm('Clear the log content from view? (This won\'t delete the actual log file)')) {
textarea.value = '';
}
}
}
// Auto-scroll to bottom of logs when page loads
document.addEventListener('DOMContentLoaded', function() {
const activeTextarea = document.querySelector('.tab-content.active textarea');
if (activeTextarea && activeTextarea.value.trim()) {
activeTextarea.scrollTop = activeTextarea.scrollHeight;
}
});
</script>
<?=template_footer()?>