/** * This script redraws the default lighttpd directory listing to our custom styles. * * Since the person inserting the files has physical access to the box and we serve * their static sites directly from the USB, ***THIS SCRIPT DOES NOT ATTEMPT TO PREVENT * INJECTION ATTACKS***. We just pop filenames and the like right into innerHTML. */ console.log("butter-dir-listing.js loaded!"); const supported_extensions = ["apk", "deb", "img", "pdf"]; const usbRoot = "usb-butter/"; const inferredBaseURL = window.location.pathname.split("/" + usbRoot)[0] + "/"; console.log("Inferred Base URL:", inferredBaseURL); const getFolderDivHTML = (directory_name, number_of_items, href) => { return `
directory
${directory_name}
${number_of_items} items
`; }; const getFileDivHTML = (file_name, size, date, href) => { icon = "ext-unknown.svg"; extension = file_name.split('.').pop(); console.log("Extension:", extension); if (supported_extensions.includes(extension)) { icon = "ext-" + extension + ".svg"; } return `
directory
${file_name}
${size} | ${date}
`; }; // Function to extract directory listing information function extractDirectoryListing() { // Get all rows in the table body const rows = document.querySelectorAll('tbody tr'); console.log('Rows:', rows) // Initialize arrays to hold file and folder information const files = []; const folders = []; // Iterate over each row rows.forEach(row => { const nameCell = row.querySelector('td.n a'); const modifiedCell = row.querySelector('td.m'); const sizeCell = row.querySelector('td.s'); const typeCell = row.querySelector('td.t'); const name = nameCell.textContent; const lastModified = modifiedCell.textContent.trim(); const size = sizeCell.textContent.trim(); const type = typeCell.textContent.trim(); const href = nameCell.getAttribute('href'); // Determine if it's a file or folder based on the class of the row or type if (type === 'Directory') { if (name !== '..') { folders.push({ name: name.replace('/', ''), // Remove the trailing slash lastModified: lastModified, size: size, type: type, href: href }); } } else { files.push({ name: name, lastModified: lastModified, size: size, type: type, href: href }); } }); return { files, folders }; } window.onload = function () { // Example usage const { files, folders } = extractDirectoryListing(); console.log('Files:', files); console.log('Folders:', folders); const listDiv = document.querySelector('div.list'); // Header with breadcrumbs const h2Path = document.querySelector('h2').textContent; console.log("H2 Path:", h2Path); const path = h2Path.replace('Index of ', '').replace(usbRoot, ''); console.log("Path:", path); const breadcrumbs = document.createElement("div"); breadcrumbs.classList.add('breadcrumbs'); let breadcrumbHTML = ` home Explore `; const pathSteps = path.split('/'); let thisDirsName = "Explore"; let pathToHere = usbRoot; pathSteps.forEach((step, index) => { if (step !== "") { pathToHere += step + '/'; thisDirsName = step; breadcrumbHTML += ` ${step}`; } }); breadcrumbs.innerHTML = breadcrumbHTML; listDiv.parentNode.insertBefore(breadcrumbs, listDiv); // hr const fullWithHR = document.createElement('hr'); fullWithHR.classList.add('full-width'); listDiv.parentNode.insertBefore(fullWithHR, listDiv); // Secondary header const secondaryHeader = document.createElement('div'); secondaryHeader.classList.add('folder-name'); secondaryHeader.innerHTML = ``; secondaryHeader.innerHTML += `${thisDirsName}`; listDiv.parentNode.insertBefore(secondaryHeader, listDiv); // Create a folder listing const folderListing = document.createElement("div"); folderListing.classList.add('folder-list'); folderListing.innerHTML = '

Folders

'; // for each folder, add a div to folderListing folders.forEach(folder => { const folderDiv = document.createElement('div'); folderDiv.classList.add('folder-row'); folderDiv.innerHTML = getFolderDivHTML(folder.name, 0, folder.href); folderListing.appendChild(folderDiv); }); // do the insertion listDiv.parentNode.insertBefore(folderListing, listDiv); if (folders.length > 0 && files.length > 0) { listDiv.parentNode.insertBefore(document.createElement('hr'), listDiv); } // then for files const fileListing = document.createElement("div"); fileListing.classList.add('file-list'); fileListing.innerHTML = '

Files

'; // for each file, add a div to fileListing files.forEach(file => { const fileDiv = document.createElement('div'); fileDiv.classList.add('file-row'); fileDiv.innerHTML = getFileDivHTML(file.name, file.size, file.lastModified, file.href); fileListing.appendChild(fileDiv); }); // do the insertion listDiv.parentNode.insertBefore(fileListing, listDiv); }