From 700c47277d4fae77894a752713c9e5e3e76eeec5 Mon Sep 17 00:00:00 2001 From: Hermes Date: Mon, 18 May 2026 17:10:08 +0000 Subject: [PATCH] =?UTF-8?q?Atualiza=C3=A7=C3=A3o=20autom=C3=A1tica:=202026?= =?UTF-8?q?-05-18=2017:10:08?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web-interface/public/app-new.js | 8 +- web-interface/public/app-premium.js | 7 +- web-interface/public/app.js | 18 ++-- web-interface/server.js | 156 ++++++++++++++++++++++++---- 4 files changed, 155 insertions(+), 34 deletions(-) diff --git a/web-interface/public/app-new.js b/web-interface/public/app-new.js index b6fe0c5..dccf2c3 100644 --- a/web-interface/public/app-new.js +++ b/web-interface/public/app-new.js @@ -610,14 +610,18 @@ function openClonedSite(directory) { } function openCloneFolder(directory) { - showToast('Abrindo pasta no sistema da VPS: ' + directory, 'info'); + showToast('Abrindo gerenciador de arquivos web...', 'info'); fetch('/api/open-folder', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ path: directory }) }).then(res => res.json()) .then(data => { - if (!data.success) showToast('Erro ao abrir pasta: ' + (data.error || ''), 'error'); + if (!data.success) { + showToast('Erro ao abrir pasta: ' + (data.error || ''), 'error'); + } else if (data.url) { + window.open(data.url, '_blank'); + } }) .catch(err => console.error('Erro ao chamar open-folder:', err)); } diff --git a/web-interface/public/app-premium.js b/web-interface/public/app-premium.js index 37c5f8f..46379dc 100644 --- a/web-interface/public/app-premium.js +++ b/web-interface/public/app-premium.js @@ -30,7 +30,12 @@ document.getElementById('btnOpenFolder').addEventListener('click', () => { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ path: clonedData.data.path }) - }); + }).then(res => res.json()) + .then(data => { + if (data.success && data.url) { + window.open(data.url, '_blank'); + } + }); } }); diff --git a/web-interface/public/app.js b/web-interface/public/app.js index bb0c2ff..64bb8ea 100644 --- a/web-interface/public/app.js +++ b/web-interface/public/app.js @@ -418,20 +418,22 @@ document.addEventListener('DOMContentLoaded', function() { // Funções para gerenciar sites clonados function openCloneFolder(directory) { - // Tentar abrir a pasta no explorador do Windows fetch('/api/open-folder', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ path: directory }) - }).then(response => { - if (!response.ok) { - alert('Não foi possível abrir a pasta automaticamente.\nLocalização: ' + directory); - } - }).catch(error => { - alert('Não foi possível abrir a pasta automaticamente.\nLocalização: ' + directory); - }); + }).then(response => response.json()) + .then(data => { + if (data.success && data.url) { + window.open(data.url, '_blank'); + } else { + alert('Não foi possível abrir a pasta.\nLocalização: ' + directory); + } + }).catch(error => { + alert('Não foi possível abrir a pasta.\nLocalização: ' + directory); + }); } function openClonedSite(directory) { diff --git a/web-interface/server.js b/web-interface/server.js index 21ffa26..fc6b51f 100644 --- a/web-interface/server.js +++ b/web-interface/server.js @@ -38,6 +38,11 @@ app.use(express.static(path.join(__dirname, 'public'), { app.use((req, res, next) => { if (!req.path.startsWith('/api') && req.path !== '/' && req.path !== '/old') { let urlPath = req.path; + // Remover prefixo /cloned-sites se existir para buscar corretamente no disco + if (urlPath.startsWith('/cloned-sites/')) { + urlPath = urlPath.replace('/cloned-sites/', '/'); + } + if (!urlPath.match(/\.[a-zA-Z0-9]+$/)) { if (!urlPath.endsWith('/')) urlPath += '/'; urlPath += 'index.html'; @@ -54,10 +59,12 @@ app.use((req, res, next) => { (function() { try { const originalPathname = Object.getOwnPropertyDescriptor(Location.prototype, 'pathname').get; + const originalHref = Object.getOwnPropertyDescriptor(Location.prototype, 'href').get; + Object.defineProperty(Location.prototype, 'pathname', { get: function() { const path = originalPathname.call(this); - if (path !== '/' && path !== '/index.html') { + if (path !== '/' && path !== '/index.html' && (path.includes('_202') || path.includes('/cloned-sites/'))) { return '/'; } return path; @@ -66,7 +73,29 @@ app.use((req, res, next) => { window.location.assign(val); } }); - console.log('🚀 [CloneWeb] SPA Router fix initialized. Simulating root pathname /'); + + Object.defineProperty(Location.prototype, 'href', { + get: function() { + const href = originalHref.call(this); + if (href.includes('_202') || href.includes('/cloned-sites/')) { + const url = new URL(href); + return url.protocol + '//' + url.host + '/'; + } + return href; + } + }); + + const OriginalURL = window.URL; + window.URL = function(url, base) { + if (typeof url === 'string' && (url.includes('_202') || url.includes('/cloned-sites/'))) { + url = url.replace(/\\/cloned-sites\\/[^/]+/gi, '').replace(/\\/[^/]+_202[0-9-_T:.]+(\\/index\\.html)?/gi, '/'); + } + return new OriginalURL(url, base); + }; + window.URL.prototype = OriginalURL.prototype; + Object.assign(window.URL, OriginalURL); + + console.log('🚀 [CloneWeb] Ultimate SPA Router fix initialized. Simulating root pathname /'); } catch(e) { console.error('❌ [CloneWeb] Failed to initialize router fix:', e); } @@ -257,7 +286,102 @@ app.get('/api/health', async (req, res) => { } }); -// Abrir pasta do clone +// Rota de visualização de arquivos da pasta clonada (Gerenciador de Arquivos Web Embutido) +app.get('/api/browse/:folder', (req, res) => { + try { + const folderName = req.params.folder; + const folderPath = path.join(__dirname, '..', 'cloned-sites', folderName); + + if (!fs.existsSync(folderPath)) { + return res.status(404).send('

Pasta não encontrada

A pasta solicitada não existe no servidor.

'); + } + + const items = fs.readdirSync(folderPath); + let filesHtml = ''; + + items.forEach(item => { + const itemPath = path.join(folderPath, item); + const stat = fs.statSync(itemPath); + const isDir = stat.isDirectory(); + const size = isDir ? '-' : (stat.size / 1024).toFixed(2) + ' KB'; + const date = new Date(stat.mtime).toLocaleString('pt-BR'); + const icon = isDir ? 'fa-folder' : (item.endsWith('.html') ? 'fa-file-code' : (item.endsWith('.json') ? 'fa-file-alt' : 'fa-file')); + const link = isDir ? `#` : `/${folderName}/${item}`; + + filesHtml += ` + + ${item} + ${size} + ${date} + + ${!isDir ? `Visualizar` : ''} + ${!isDir ? `Baixar` : ''} + + + `; + }); + + const html = ` + + + + + + Arquivos Clonados - ${folderName} + + + + + +
+
+

${folderName}

+ +
+ + + + + + + + + + + ${filesHtml} + +
Nome do FicheiroTamanhoModificado emAções
+
+ + + `; + + res.send(html); + } catch (error) { + console.error('Erro ao listar pasta:', error); + res.status(500).send('

Erro interno do servidor

'); + } +}); + +// Abrir pasta do clone (mantém compatibilidade legada e retorna a URL do Web Browse) app.post('/api/open-folder', (req, res) => { try { const { path: folderPath } = req.body; @@ -265,14 +389,10 @@ app.post('/api/open-folder', (req, res) => { return res.status(400).json({ error: 'Caminho da pasta é obrigatório' }); } - // Abrir pasta no gerenciador de ficheiros - exec(`xdg-open "${folderPath}"`, (error) => { - if (error) { - console.error('Erro ao abrir pasta:', error); - return res.status(500).json({ error: 'Não foi possível abrir a pasta' }); - } - res.json({ success: true, message: 'Pasta aberta com sucesso' }); - }); + const folderName = path.basename(folderPath); + const browseUrl = `/api/browse/${folderName}`; + + res.json({ success: true, message: 'Pasta acessível via Web', url: browseUrl }); } catch (error) { console.error('Erro ao abrir pasta:', error); res.status(500).json({ error: 'Erro interno do servidor' }); @@ -287,20 +407,10 @@ app.post('/api/open-site', (req, res) => { return res.status(400).json({ error: 'Caminho do site é obrigatório' }); } - // Extrair apenas o nome da pasta (último segmento do caminho) const folderName = path.basename(sitePath); - const siteUrl = `http://localhost:${PORT}/${folderName}/index.html`; + const siteUrl = `/${folderName}/index.html`; - console.log(`🌍 Opening site via HTTP: ${siteUrl}`); - - // Abrir URL no navegador padrão (Linux) - exec(`xdg-open "${siteUrl}"`, (error) => { - if (error) { - console.error('Erro ao abrir site:', error); - return res.status(500).json({ error: 'Não foi possível abrir o site via HTTP' }); - } - res.json({ success: true, message: 'Site aberto via HTTP com sucesso', url: siteUrl }); - }); + res.json({ success: true, message: 'Site aberto com sucesso', url: siteUrl }); } catch (error) { console.error('Erro ao abrir site:', error); res.status(500).json({ error: 'Erro interno do servidor' });