v0.0.66: блокировка выбора/удаления файлов на время загрузки и обработки, заморозка сессии после результата + кнопка Новая сессия
Deploy drhider / validate (push) Canceled after 0s

This commit is contained in:
“Naeel”
2026-08-24 15:42:37 +03:00
parent dd9785747d
commit c346be5add
2 changed files with 36 additions and 4 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ if _sys_path_root not in sys.path:
sys.path.insert(0, _sys_path_root)
# Версия приложения (меняется при изменениях)
VERSION = "0.0.65"
VERSION = "0.0.66"
def setup_logging():
+35 -3
View File
@@ -73,6 +73,7 @@
padding: 2px 4px; font-size: 14px; line-height: 1;
}
.remove-btn:hover { color: var(--red); }
body.busy .remove-btn { display: none; }
.footer-bar {
margin-top: 10px; display: flex; justify-content: space-between; align-items: center;
font-size: 12px; color: var(--muted);
@@ -162,6 +163,7 @@
<div class="footer-bar">
<span id="fileCount">0 файлов</span>
<button class="btn" id="cancelBtn" style="display:none" onclick="confirmCancel()">⏹ Прервать</button>
<button class="btn" id="newSessionBtn" style="display:none" onclick="resetAll()">🔄 Новая сессия</button>
<button class="btn btn-primary" id="uploadBtn" disabled onclick="uploadFiles()">🛡️ Обфусцировать</button>
</div>
<div class="status" id="status"></div>
@@ -214,6 +216,8 @@ let procExtractDone = false; // true после extract_done (далее done
let procExtractRate = null; // измеренная скорость извлечения (сек/МБ) для оценок ожидающих
let procRefresh = null; // setInterval перерисовки таблицы
let ptimer = null, liveRefresh = null; // таймеры статуса и live-блока
let busy = false; // идёт загрузка/обработка — список файлов заблокирован
let sessionDone = false; // результат готов — сессия заморожена до «Новая сессия»
const MAX_FILE_BYTES = 50 * 1024 * 1024; // 50 МБ на один файл
const MAX_SESSION_BYTES = 500 * 1024 * 1024; // 500 МБ суммарно на сессию
const VM_UPLOAD_URL = 'https://contracts.kube5s.ru/drhider-upload/'; // ВМ-буфер: PUT больших файлов (шлюз кластера их рвёт)
@@ -238,6 +242,9 @@ function resetAll() {
procNameIdx = {};
procExtractDone = false;
procExtractRate = null;
sessionDone = false;
setBusy(false);
document.getElementById('newSessionBtn').style.display = 'none';
document.getElementById('cancelBtn').style.display = 'none';
fi.value = '';
rr();
@@ -375,7 +382,13 @@ function finishProcUI() {
rr();
}
function rm(i) { const nm = sf[i].name; overNames.delete(nm); fileMeta.delete(nm); sf.splice(i, 1); const d = new DataTransfer(); sf.forEach(f => d.items.add(f)); fi.files = d.files; rr(); }
function setBusy(b) {
busy = b;
fi.disabled = b; // «Выбрать файлы» — блокируется на время загрузки/обработки и в замороженной сессии
document.body.classList.toggle('busy', b); // скрывает кнопки «✕» в таблице
}
function rm(i) { if (busy) return; const nm = sf[i].name; overNames.delete(nm); fileMeta.delete(nm); sf.splice(i, 1); const d = new DataTransfer(); sf.forEach(f => d.items.add(f)); fi.files = d.files; rr(); }
window.addEventListener('load', () => { sf = []; fileMeta = new Map(); fi.value = ''; rr(); /* прогрев upstream-соединения */ fetch('/health').catch(() => {}); });
// ═══════════ Нативная распаковка ZIP (без внешних библиотек) ═══════════
@@ -516,6 +529,7 @@ function addFileWithDedup(file) {
}
fi.addEventListener('change', async () => {
if (busy) return; // во время загрузки/обработки менять список нельзя
const incoming = Array.from(fi.files);
const hasZip = incoming.some(f => f.name.toLowerCase().endsWith('.zip'));
if (hasZip) {
@@ -553,7 +567,11 @@ fi.addEventListener('change', async () => {
function ss(idx, h) { const e = document.getElementById('st-' + idx); if (e) e.innerHTML = h; }
async function uploadFiles() {
if (busy) return; // уже идёт загрузка/обработка
if (sf.length === 0) return;
setBusy(true);
sessionDone = false;
document.getElementById('newSessionBtn').style.display = 'none';
// Сохранить список до очистки
const files = sf.slice();
// Только учитываемые файлы идут на загрузку/обфускацию (переборные пропускаем)
@@ -574,7 +592,7 @@ async function uploadFiles() {
document.getElementById('liveBlock').classList.remove('show');
ub.disabled = true;
const total = toSend.length;
if (total === 0) { st.className = 'status error'; st.textContent = 'Нет файлов для обфускации (все превышают лимит).'; ub.disabled = false; return; }
if (total === 0) { st.className = 'status error'; st.textContent = 'Нет файлов для обфускации (все превышают лимит).'; setBusy(false); ub.disabled = false; return; }
// Фаза 1: загрузка на ВМ-буфер (PUT напрямую на nginx ВМ, минуя шлюз кластера)
const token = crypto.randomUUID();
@@ -619,6 +637,7 @@ async function uploadFiles() {
ss(i, '<span style="color:#ef4444">✗</span>');
st.className = 'status error';
st.textContent = 'Ошибка загрузки на ВМ: ' + err.message;
setBusy(false);
ub.disabled = false;
return;
}
@@ -640,6 +659,7 @@ async function uploadFiles() {
} catch (err) {
st.className = 'status error';
st.textContent = 'Ошибка передачи ссылок: ' + err.message;
setBusy(false);
ub.disabled = false;
return;
}
@@ -648,6 +668,7 @@ async function uploadFiles() {
if (TEST_UPLOAD_ONLY) {
st.className = 'status done';
st.textContent = '✅ Загружено ' + uploadedCount + ' файлов (тест: обработка пропущена). Сессия: ' + currentSid;
setBusy(false);
ub.disabled = false;
return;
}
@@ -806,6 +827,11 @@ async function uploadFiles() {
}
sb.classList.add('show');
db.classList.add('show');
// Заморозка сессии: результат готов (частичный), список файлов больше не меняем
sessionDone = true;
ub.disabled = true;
fi.disabled = true;
document.getElementById('newSessionBtn').style.display = 'inline-block';
resolve();
});
activeES.addEventListener('complete', function(e) {
@@ -826,6 +852,11 @@ async function uploadFiles() {
}
sb.classList.add('show');
db.classList.add('show');
// Заморозка сессии: результат готов, список файлов больше не меняем
sessionDone = true;
ub.disabled = true;
fi.disabled = true;
document.getElementById('newSessionBtn').style.display = 'inline-block';
resolve();
});
activeES.onerror = function() {
@@ -835,10 +866,11 @@ async function uploadFiles() {
});
} catch (err) {
finishProcUI();
setBusy(false);
st.className = 'status error';
st.textContent = 'Ошибка: ' + err.message;
}
ub.disabled = false;
if (!sessionDone) ub.disabled = false;
}
function downloadZip() {