From e5963429508e8c80347153036229fa05cbdefc53 Mon Sep 17 00:00:00 2001 From: Hermes Date: Mon, 18 May 2026 20:12:35 +0000 Subject: [PATCH] =?UTF-8?q?Atualiza=C3=A7=C3=A3o=20autom=C3=A1tica:=202026?= =?UTF-8?q?-05-18=2020:12:35?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web-interface/public/app-new.js | 16 +---- web-interface/public/app-premium.js | 6 +- web-interface/public/app.js | 4 +- web-interface/public/storage-panel.js | 2 +- web-interface/server.js | 87 +++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 23 deletions(-) diff --git a/web-interface/public/app-new.js b/web-interface/public/app-new.js index dccf2c3..9d9c5a7 100644 --- a/web-interface/public/app-new.js +++ b/web-interface/public/app-new.js @@ -593,20 +593,8 @@ function saveSettings() { // Utility Functions function openClonedSite(directory) { - // Try to open via server endpoint - fetch('/api/health', { - method: 'GET' - }).then(response => { - if (response.ok) { - // Server is running, open the site via same origin - const siteName = directory.replace(/\\/g, '/').split('/').pop(); - window.open(`/${siteName}/index.html`, '_blank'); - } else { - showToast('Servidor não está respondendo.', 'error'); - } - }).catch(error => { - showToast('Servidor não está respondendo.', 'error'); - }); + const siteName = directory.replace(/\\/g, '/').split('/').pop(); + window.open(`/api/preview/${siteName}`, '_blank'); } function openCloneFolder(directory) { diff --git a/web-interface/public/app-premium.js b/web-interface/public/app-premium.js index 46379dc..13a8547 100644 --- a/web-interface/public/app-premium.js +++ b/web-interface/public/app-premium.js @@ -15,12 +15,8 @@ urlInput.addEventListener('keypress', (e) => { document.getElementById('btnOpenSite').addEventListener('click', () => { if (clonedData && clonedData.data && clonedData.data.path) { - // Construct local URL. Server serves //index.html - // We know server serves static files from cloned-sites directly if configured? - // Wait, server.js serves ../cloned-sites as static. - // so path is just /FolderName/index.html const dirName = clonedData.data.path.split('\\').pop().split('/').pop(); - window.open(`/${dirName}/index.html`, '_blank'); + window.open(`/api/preview/${dirName}`, '_blank'); } }); diff --git a/web-interface/public/app.js b/web-interface/public/app.js index 64bb8ea..16f52c2 100644 --- a/web-interface/public/app.js +++ b/web-interface/public/app.js @@ -437,8 +437,6 @@ function openCloneFolder(directory) { } function openClonedSite(directory) { - // Extract folder name and open site in browser via window.open const folderName = directory.split('/').pop(); - const siteUrl = window.location.protocol + '//' + window.location.host + '/' + folderName + '/index.html'; - window.open(siteUrl, '_blank'); + window.open('/api/preview/' + folderName, '_blank'); } \ No newline at end of file diff --git a/web-interface/public/storage-panel.js b/web-interface/public/storage-panel.js index 9164eed..052a0e6 100644 --- a/web-interface/public/storage-panel.js +++ b/web-interface/public/storage-panel.js @@ -373,7 +373,7 @@ function confirmDeleteClone(cloneId) { } function openClone(cloneId) { - window.open(`/${cloneId}/index.html`, '_blank'); + window.open(`/api/preview/${cloneId}`, '_blank'); } function cloneSiteAgain(baseUrl) { diff --git a/web-interface/server.js b/web-interface/server.js index 355fafc..e5c2418 100644 --- a/web-interface/server.js +++ b/web-interface/server.js @@ -25,6 +25,93 @@ app.use((req, res, next) => { app.use(cors()); app.use(express.json()); +// Helper para parsear cookies +function parseCookies(cookieHeader) { + const list = {}; + if (!cookieHeader) return list; + cookieHeader.split(';').forEach(cookie => { + let [name, ...rest] = cookie.split('='); + name = name?.trim(); + if (!name) return; + const value = rest.join('=').trim(); + if (!value) return; + list[name] = decodeURIComponent(value); + }); + return list; +} + +// Rota para ativar o Virtual Root Preview (define o cookie e redireciona para a raiz) +app.get('/api/preview/:folder', (req, res) => { + const folderName = req.params.folder; + res.setHeader('Set-Cookie', `clone_preview_target=${encodeURIComponent(folderName)}; Path=/; HttpOnly; SameSite=Lax`); + res.redirect('/'); +}); + +// Rota para sair do Virtual Root Preview (limpa o cookie e volta ao dashboard) +app.get('/api/exit-preview', (req, res) => { + res.setHeader('Set-Cookie', 'clone_preview_target=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT'); + res.redirect('/'); +}); + +// Middleware de Virtual Root Proxy (serve o site clonado diretamente na raiz / quando o cookie está ativo) +app.use((req, res, next) => { + const cookies = parseCookies(req.headers.cookie); + if (cookies.clone_preview_target && !req.path.startsWith('/api') && req.path !== '/old') { + const folderName = cookies.clone_preview_target; + const folderPath = path.join(__dirname, '..', 'cloned-sites', folderName); + + if (fs.existsSync(folderPath)) { + let targetFile = req.path; + if (targetFile === '/') targetFile = '/index.html'; + + // Se o arquivo solicitado existir dentro da pasta do clone + const fullPath = path.join(folderPath, targetFile); + + if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) { + // Se for HTML, injeta a barra de preview flutuante + if (targetFile.endsWith('.html')) { + let html = fs.readFileSync(fullPath, 'utf8'); + const previewBar = ` +
+ Live Preview: ${folderName.split('_')[0]} + Sair do Preview +
+ `; + if (html.includes('')) { + html = html.replace('', previewBar + ''); + } else { + html += previewBar; + } + res.setHeader('Content-Type', 'text/html'); + return res.send(html); + } + + // Para outros arquivos (CSS, JS, imagens), serve diretamente com o MIME type correto + if (targetFile.endsWith('.css')) res.setHeader('Content-Type', 'text/css'); + if (targetFile.endsWith('.js')) res.setHeader('Content-Type', 'application/javascript'); + return res.sendFile(fullPath); + } else { + // Fallback de SPA: se a rota virtual não existir como arquivo no disco, serve o index.html do clone!!! + const indexPath = path.join(folderPath, 'index.html'); + if (fs.existsSync(indexPath)) { + let html = fs.readFileSync(indexPath, 'utf8'); + const previewBar = ` +
+ Live Preview: ${folderName.split('_')[0]} + Sair do Preview +
+ `; + if (html.includes('')) html = html.replace('', previewBar + ''); + else html += previewBar; + res.setHeader('Content-Type', 'text/html'); + return res.send(html); + } + } + } + } + next(); +}); + // Serve static files with proper MIME types app.use(express.static(path.join(__dirname, 'public'), { setHeaders: (res, path) => {