v0.9.59
- code cleanup and refactoring - implement max post size on pc services - add box account transfer system - create directory indexer for pc services - fix catchall for pc services - pc services not respects `disabled: true` if sharing the same port - new wtv-tricks:/info from WebTV Redialed - Added missing Pagebuilder themes - Fixed various PageBuilder bugs, pages should work correctly (republish your page if needed) - various security and bug fixes
This commit is contained in:
162
zefie_wtvp_minisrv/includes/ServiceVault/http_pc/indexer.js
Normal file
162
zefie_wtvp_minisrv/includes/ServiceVault/http_pc/indexer.js
Normal file
@@ -0,0 +1,162 @@
|
||||
var minisrv_service_file = true;
|
||||
try {
|
||||
var relativePath = request_headers.request_url;
|
||||
if (relativePath.indexOf('?') > -1) relativePath = relativePath.split('?')[0];
|
||||
while (relativePath.endsWith('/')) relativePath = relativePath.substring(0, relativePath.length - 1);
|
||||
|
||||
var dir = service_name + relativePath;
|
||||
var num_per_page = 25;
|
||||
var dirs = ['<tr><td>Directory</td><td><a href="' + relativePath + '/..">Parent Directory</a></td><td>-</td><td>-</td></tr > '];
|
||||
var files = [];
|
||||
vault_found = false;
|
||||
|
||||
|
||||
// Iterate through each service vault to find the first occurrence
|
||||
for (let i = 0; i < service_vaults.length; i++) {
|
||||
const vaultPath = path.join(service_vaults[i], dir || '');
|
||||
if (!fs.existsSync(vaultPath)) continue;
|
||||
|
||||
try {
|
||||
vault_found = true;
|
||||
const entries = fs.readdirSync(vaultPath);
|
||||
|
||||
entries.forEach(entry => {
|
||||
if (entry === path.basename(__filename)) return;
|
||||
|
||||
// Check if entry exists in all service vaults
|
||||
let found = false;
|
||||
var checkPath = "";
|
||||
for (let j = 0; j < service_vaults.length; j++) {
|
||||
checkPath = path.join(service_vaults[j], dir || '', entry);
|
||||
if (fs.existsSync(checkPath)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Skip if not found in all
|
||||
if (!found) return;
|
||||
|
||||
const fullPath = checkPath;
|
||||
const stats = fs.statSync(fullPath);
|
||||
const isDir = stats.isDirectory();
|
||||
const mimeType = (isDir) ? "Directory" : wtvmime.getContentType(fullPath)[1];
|
||||
var readableSize = '-';
|
||||
// Get file size with unit
|
||||
if (!isDir) {
|
||||
const fileSize = stats.size;
|
||||
const units = ['Bytes', 'KB', 'MB', 'GB'];
|
||||
const unitSize = Math.floor(Math.log(fileSize) / Math.log(1024));
|
||||
readableSize = (fileSize / Math.pow(1024, unitSize)).toFixed(2) + units[unitSize];
|
||||
}
|
||||
// Get last modified time
|
||||
const mtime = stats.mtime.toLocaleString('en-US', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit'
|
||||
});
|
||||
|
||||
// Check if modified recently
|
||||
const currentTime = Date.now();
|
||||
const tenSecondsAgo = currentTime - 10000;
|
||||
const isModifiedRecently = stats.mtime.getTime() > tenSecondsAgo;
|
||||
|
||||
// Create clickable link
|
||||
const link = isDir ?
|
||||
`<a href="${relativePath}/${entry}">${entry}</a>` :
|
||||
`<a href="${relativePath}/${path.basename(fullPath)}">${entry}</a>`;
|
||||
|
||||
// Generate icon and timestamp display
|
||||
const icon = mimeType;
|
||||
const timestampDisplay = isModifiedRecently ?
|
||||
`<span style="color: #666;">${mtime}</span>` :
|
||||
`${mtime}`;
|
||||
|
||||
if (isDir) dirs.push(`<tr><td>${icon}</td><td>${(isModifiedRecently) ? entry : link}</td><td>${readableSize}</td><td>${timestampDisplay}</td></tr>`);
|
||||
else files.push(`<tr><td>${icon}</td><td>${(isModifiedRecently) ? entry : link}</td><td>${readableSize}</td><td>${timestampDisplay}</td></tr>`);
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Error:', err);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vault_found) {
|
||||
var errpage = wtvshared.doErrorPage(404);
|
||||
headers = errpage[0];
|
||||
data = errpage[1];
|
||||
} else {
|
||||
|
||||
// Pagination logic
|
||||
const totalFiles = files.length;
|
||||
const max_pages = Math.ceil(totalFiles / num_per_page);
|
||||
let current_page = 1; // Default to first page
|
||||
if (totalFiles > 0) {
|
||||
current_page = parseInt(request_headers.query.page || 1);
|
||||
if (current_page < 1) current_page = 1;
|
||||
if (current_page > max_pages) current_page = max_pages;
|
||||
}
|
||||
|
||||
const start_index = (current_page - 1) * num_per_page;
|
||||
const end_index = current_page * num_per_page;
|
||||
const merged_files = dirs.concat(files);
|
||||
const paginatedFiles = merged_files.slice(start_index, end_index);
|
||||
|
||||
let paginationHtml = `
|
||||
<div style="text-align: center; margin-top: 20px;">
|
||||
<form action="" method="get" style="display: inline;">
|
||||
<input type=button onclick="window.location.href='?page=1'" ${(current_page === 1) ? 'disabled' : ''} value="First"></input>
|
||||
<input type=button onclick="window.location.href='?page=${Math.max(current_page - 1, 1)}'" ${(current_page === 1) ? 'disabled' : ''} value="Previous"></input>
|
||||
<span style="margin: 0 10px;">Page ${current_page} of ${max_pages}</span>
|
||||
<input type=button onclick="window.location.href='?page=${Math.min(current_page + 1, max_pages)}'" ${(current_page === max_pages) ? 'disabled' : ''} value="Next"></input>
|
||||
<input type=button onclick="window.location.href='?page=${max_pages}'" ${(current_page === max_pages) ? 'disabled' : ''} value="Last"></input>
|
||||
</form>
|
||||
</div>`;
|
||||
|
||||
data = `
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Directory Index</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #121212;
|
||||
color: #ffffff;
|
||||
}
|
||||
a, a:hover, a:active {
|
||||
color: #1e90ff;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:visited { color: #8a2be2; }
|
||||
table { width: 100%; border-collapse: collapse; }
|
||||
th, td { padding: 8px; text-align: left; border-bottom: 1px solid #333; }
|
||||
tr:hover { background-color: #2a2a2a; }
|
||||
</style>
|
||||
</head>
|
||||
<body bgcolor="#121212" text="#ffffff" link="#1e90ff" vlink="#8a2be2">
|
||||
<h2>Directory Index of ${relativePath}</h2>
|
||||
<hr>
|
||||
<table>
|
||||
<tr><th>Type</th><th>Name</th><th>Size</th><th>Last Modified</th></tr>
|
||||
${paginatedFiles.join('')}
|
||||
</table>
|
||||
${paginationHtml}
|
||||
<script>
|
||||
function toggleTheme() { ... }
|
||||
</script>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
headers = `200 OK\nContent-Type: text/html`;
|
||||
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error:', err);
|
||||
var err = wtvshared.doErrorPage(404);
|
||||
headers = err[0];
|
||||
data = err[1];
|
||||
}
|
||||
Reference in New Issue
Block a user