fix: Remove scripts from html to stop redirects or other random things
All checks were successful
Build Docker / BuildImage (push) Successful in 30s

This commit is contained in:
2025-02-27 14:28:59 +11:00
parent 3998e1cafc
commit 964779136c

View File

@@ -1,40 +1,40 @@
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function () {
// Get references to elements // Get references to elements
const curlButton = document.getElementById('curl'); const curlButton = document.getElementById('curl');
const curlUrlInput = document.getElementById('curl-url'); const curlUrlInput = document.getElementById('curl-url');
const resultsContainer = document.getElementById('curl-results'); const resultsContainer = document.getElementById('curl-results');
// Add click event listener to the button // Add click event listener to the button
curlButton.addEventListener('click', function() { curlButton.addEventListener('click', function () {
// Get the URL from the input // Get the URL from the input
const url = curlUrlInput.value.trim(); const url = curlUrlInput.value.trim();
// Validate URL // Validate URL
if (!url) { if (!url) {
showMessage('Please enter a URL', 'error'); showMessage('Please enter a URL', 'error');
return; return;
} }
// Update the url // Update the url
const params = new URLSearchParams(); const params = new URLSearchParams();
params.append('url', url); params.append('url', url);
history.pushState(null, null, `?${params.toString()}`); history.pushState(null, null, `?${params.toString()}`);
// Show loading state // Show loading state
curlButton.disabled = true; curlButton.disabled = true;
curlButton.innerHTML = '<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>Loading...'; curlButton.innerHTML = '<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>Loading...';
// Clear previous results // Clear previous results
resultsContainer.innerHTML = ''; resultsContainer.innerHTML = '';
showMessage('Fetching content...', 'info'); showMessage('Fetching content...', 'info');
// Make the request // Make the request
handleCurlRequest(url); handleCurlRequest(url);
}); });
// Add enter key listener to input // Add enter key listener to input
curlUrlInput.addEventListener('keyup', function(event) { curlUrlInput.addEventListener('keyup', function (event) {
if (event.key === 'Enter') { if (event.key === 'Enter') {
curlButton.click(); curlButton.click();
} }
}); });
@@ -43,22 +43,22 @@ document.addEventListener('DOMContentLoaded', function() {
* @param {string} url - The URL to curl * @param {string} url - The URL to curl
*/ */
function handleCurlRequest(url) { function handleCurlRequest(url) {
// Encode the URL for the API endpoint // Encode the URL for the API endpoint
const encodedUrl = encodeURIComponent(url); const encodedUrl = encodeURIComponent(url);
const apiEndpoint = `/api/v1/curl/${encodedUrl}`; const apiEndpoint = `/api/v1/curl/${encodedUrl}`;
fetch(apiEndpoint) fetch(apiEndpoint)
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
// Clear loading message // Clear loading message
resultsContainer.innerHTML = ''; resultsContainer.innerHTML = '';
if (data.success === true) { if (data.success === true) {
// Create a result card with iframe // Create a result card with iframe
const resultCard = document.createElement('div'); const resultCard = document.createElement('div');
resultCard.className = 'card shadow border-0 rounded-lg mb-5'; resultCard.className = 'card shadow border-0 rounded-lg mb-5';
resultCard.innerHTML = ` resultCard.innerHTML = `
<div class="card-header bg-success text-white py-3 d-flex justify-content-between align-items-center"> <div class="card-header bg-success text-white py-3 d-flex justify-content-between align-items-center">
<h3 class="h5 mb-0">Result for ${escapeHtml(url)}</h3> <h3 class="h5 mb-0">Result for ${escapeHtml(url)}</h3>
<div> <div>
@@ -72,24 +72,26 @@ document.addEventListener('DOMContentLoaded', function() {
</div> </div>
`; `;
resultsContainer.appendChild(resultCard); resultsContainer.appendChild(resultCard);
// Get reference to the iframe and buttons // Get reference to the iframe and buttons
const iframe = document.getElementById('result-iframe'); const iframe = document.getElementById('result-iframe');
const viewSourceButton = document.getElementById('view-source'); const viewSourceButton = document.getElementById('view-source');
// Create a blob URL from the HTML content const cleanedHtml = removeScripts(data.result);
const blob = new Blob([data.result], { type: 'text/html' });
const blobUrl = URL.createObjectURL(blob);
// Set the iframe src to the blob URL // Create a blob URL from the cleaned HTML content
iframe.src = blobUrl; const blob = new Blob([cleanedHtml], { type: 'text/html' });
const blobUrl = URL.createObjectURL(blob);
// Add event listener to view source button // Set the iframe src to the blob URL
viewSourceButton.addEventListener('click', function() { iframe.src = blobUrl;
// Show source code in a modal or new window
const sourceWindow = window.open('', '_blank'); // Add event listener to view source button
sourceWindow.document.write(` viewSourceButton.addEventListener('click', function () {
// Show source code in a modal or new window
const sourceWindow = window.open('', '_blank');
sourceWindow.document.write(`
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
@@ -101,44 +103,83 @@ document.addEventListener('DOMContentLoaded', function() {
<body>${escapeHtml(data.result)}</body> <body>${escapeHtml(data.result)}</body>
</html> </html>
`); `);
sourceWindow.document.close(); sourceWindow.document.close();
}); });
// Set up cleanup when iframe is no longer needed // Set up cleanup when iframe is no longer needed
window.addEventListener('beforeunload', function() { window.addEventListener('beforeunload', function () {
URL.revokeObjectURL(blobUrl); URL.revokeObjectURL(blobUrl);
});
} else {
// Show error message
showMessage(data.error || 'Failed to get content', 'error');
}
})
.catch(error => {
showMessage(`Request failed: ${error.message}`, 'error');
})
.finally(() => {
// Reset button state
curlButton.disabled = false;
curlButton.innerHTML = '<i class="bi bi-shield-check me-2"></i>HTTP Request';
}); });
} else {
// Show error message
showMessage(data.error || 'Failed to get content', 'error');
}
})
.catch(error => {
showMessage(`Request failed: ${error.message}`, 'error');
})
.finally(() => {
// Reset button state
curlButton.disabled = false;
curlButton.innerHTML = '<i class="bi bi-shield-check me-2"></i>HTTP Request';
});
} }
/** /**
* Remove all script tags and event handlers from HTML content
* @param {string} html - The HTML content
* @returns {string} - HTML content with scripts removed
*/
function removeScripts(html) {
// Create a DOM parser to work with the HTML
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
// Remove all script elements
const scripts = doc.getElementsByTagName('script');
while (scripts.length > 0) {
scripts[0].parentNode.removeChild(scripts[0]);
}
// Remove inline event handlers from all elements
const allElements = doc.getElementsByTagName('*');
for (let i = 0; i < allElements.length; i++) {
const element = allElements[i];
const attrs = element.attributes;
const attrsToRemove = [];
// Collect all event handler attributes (on*)
for (let j = 0; j < attrs.length; j++) {
if (attrs[j].name.toLowerCase().startsWith('on')) {
attrsToRemove.push(attrs[j].name);
}
}
// Remove the collected attributes
attrsToRemove.forEach(attr => {
element.removeAttribute(attr);
});
}
// Return the cleaned HTML
return doc.documentElement.outerHTML;
}
/**
* Display a message in the results container * Display a message in the results container
* @param {string} message - The message to display * @param {string} message - The message to display
* @param {string} type - Message type (error, success, info) * @param {string} type - Message type (error, success, info)
*/ */
function showMessage(message, type) { function showMessage(message, type) {
// Clear previous content // Clear previous content
resultsContainer.innerHTML = ''; resultsContainer.innerHTML = '';
// Create alert element // Create alert element
const alert = document.createElement('div'); const alert = document.createElement('div');
alert.className = `alert alert-${getAlertClass(type)} shadow-sm`; alert.className = `alert alert-${getAlertClass(type)} shadow-sm`;
alert.innerHTML = message; alert.innerHTML = message;
// Add the alert to the results container // Add the alert to the results container
resultsContainer.appendChild(alert); resultsContainer.appendChild(alert);
} }
/** /**
@@ -147,11 +188,11 @@ document.addEventListener('DOMContentLoaded', function() {
* @returns {string} - Bootstrap alert class * @returns {string} - Bootstrap alert class
*/ */
function getAlertClass(type) { function getAlertClass(type) {
switch (type) { switch (type) {
case 'error': return 'danger'; case 'error': return 'danger';
case 'success': return 'success'; case 'success': return 'success';
case 'info': default: return 'info'; case 'info': default: return 'info';
} }
} }
/** /**
@@ -160,21 +201,21 @@ document.addEventListener('DOMContentLoaded', function() {
* @returns {string} - Escaped text * @returns {string} - Escaped text
*/ */
function escapeHtml(text) { function escapeHtml(text) {
const div = document.createElement('div'); const div = document.createElement('div');
div.textContent = text; div.textContent = text;
return div.innerHTML; return div.innerHTML;
} }
// Check if params are present // Check if params are present
if (window.location.search) { if (window.location.search) {
const params = new URLSearchParams(window.location.search); const params = new URLSearchParams(window.location.search);
const url = params.get('url'); const url = params.get('url');
if (url) { if (url) {
// Add url to input // Add url to input
curlUrlInput.value = url; curlUrlInput.value = url;
// Show loading state // Show loading state
curlButton.disabled = true; curlButton.disabled = true;
curlButton.innerHTML = '<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>Loading...'; curlButton.innerHTML = '<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>Loading...';
handleCurlRequest(url); handleCurlRequest(url);
} }
} }
}); });