Update to pre-release version. Removed logging that was used for debugging. Added typing of files that the user sends with size restrictions.
This commit is contained in:
@@ -254,7 +254,7 @@ open http://localhost:8000
|
|||||||
|
|
||||||
## 🗺️ Development Roadmap
|
## 🗺️ Development Roadmap
|
||||||
|
|
||||||
**Current:** v4.01.222 — PWA & File Transfer Edition ✅
|
**Current:** v4.01.412 — PWA & File Transfer Edition ✅
|
||||||
|
|
||||||
* Progressive Web App installation
|
* Progressive Web App installation
|
||||||
* Secure P2P file transfer system
|
* Secure P2P file transfer system
|
||||||
@@ -551,6 +551,6 @@ SecureBit.chat:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Latest Release: v4.01.222** — PWA & Secure File Transfer
|
**Latest Release: v4.01.412** — PWA & Secure File Transfer
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Security Disclaimer and Terms of Use
|
# Security Disclaimer and Terms of Use
|
||||||
|
|
||||||
## 🔒 SecureBit.chat Enhanced Security Edition v4.01.222
|
## 🔒 SecureBit.chat Enhanced Security Edition v4.01.412
|
||||||
|
|
||||||
### Important Legal Notice
|
### Important Legal Notice
|
||||||
|
|
||||||
@@ -203,6 +203,6 @@ This software is created to:
|
|||||||
---
|
---
|
||||||
|
|
||||||
*Last Updated: 08.07.2025*
|
*Last Updated: 08.07.2025*
|
||||||
*Version: Enhanced Security Edition v4.01.222*
|
*Version: Enhanced Security Edition v4.01.412*
|
||||||
|
|
||||||
**USE AT YOUR OWN RISK AND RESPONSIBILITY**
|
**USE AT YOUR OWN RISK AND RESPONSIBILITY**
|
||||||
17
index.html
17
index.html
@@ -161,7 +161,7 @@
|
|||||||
icon: "fas fa-shield-halved",
|
icon: "fas fa-shield-halved",
|
||||||
color: "orange",
|
color: "orange",
|
||||||
title: "12-Layer Military Security",
|
title: "12-Layer Military Security",
|
||||||
description: "Revolutionary defense system with ECDH P-384 + AES-GCM 256 + ECDSA. Enhanced Security Edition v4.01.222 provides military-grade protection exceeding government standards."
|
description: "Revolutionary defense system with ECDH P-384 + AES-GCM 256 + ECDSA. Enhanced Security Edition v4.01.412 provides military-grade protection exceeding government standards."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "fas fa-bolt",
|
icon: "fas fa-bolt",
|
||||||
@@ -511,7 +511,7 @@
|
|||||||
Enhanced Security Edition Comparison
|
Enhanced Security Edition Comparison
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-secondary max-w-2xl mx-auto mb-4">
|
<p className="text-secondary max-w-2xl mx-auto mb-4">
|
||||||
SecureBit.chat v4.01.222 Enhanced Security Edition vs leading secure messengers
|
SecureBit.chat v4.01.412 Enhanced Security Edition vs leading secure messengers
|
||||||
</p>
|
</p>
|
||||||
<div className="inline-flex items-center px-4 py-2 bg-yellow-500/10 border border-yellow-500/20 rounded-lg">
|
<div className="inline-flex items-center px-4 py-2 bg-yellow-500/10 border border-yellow-500/20 rounded-lg">
|
||||||
<span className="text-yellow-400 mr-2">🏆</span>
|
<span className="text-yellow-400 mr-2">🏆</span>
|
||||||
@@ -657,7 +657,7 @@
|
|||||||
<div className="p-6 bg-gradient-to-r from-orange-500/10 to-yellow-500/10 border border-orange-500/20 rounded-xl">
|
<div className="p-6 bg-gradient-to-r from-orange-500/10 to-yellow-500/10 border border-orange-500/20 rounded-xl">
|
||||||
<h4 className="text-xl font-bold text-orange-400 mb-4 flex items-center">
|
<h4 className="text-xl font-bold text-orange-400 mb-4 flex items-center">
|
||||||
<i className="fas fa-trophy mr-3" />
|
<i className="fas fa-trophy mr-3" />
|
||||||
SecureBit.chat v4.01.222 Enhanced Security Edition Summary
|
SecureBit.chat v4.01.412 Enhanced Security Edition Summary
|
||||||
</h4>
|
</h4>
|
||||||
<p className="text-secondary leading-relaxed text-lg mb-4">
|
<p className="text-secondary leading-relaxed text-lg mb-4">
|
||||||
SecureBit.chat dominates in 11 out of 15 security categories, establishing itself as the most secure P2P messenger available.
|
SecureBit.chat dominates in 11 out of 15 security categories, establishing itself as the most secure P2P messenger available.
|
||||||
@@ -3195,7 +3195,7 @@
|
|||||||
const downloadMessage = React.createElement('div', {
|
const downloadMessage = React.createElement('div', {
|
||||||
className: 'flex items-center space-x-2'
|
className: 'flex items-center space-x-2'
|
||||||
}, [
|
}, [
|
||||||
React.createElement('span', { key: 'label' }, `📥 Файл получен: ${fileData.fileName} (${sizeMb} MB)`),
|
React.createElement('span', { key: 'label' }, `📥 File received: ${fileData.fileName} (${sizeMb} MB)`),
|
||||||
React.createElement('button', {
|
React.createElement('button', {
|
||||||
key: 'btn',
|
key: 'btn',
|
||||||
className: 'px-3 py-1 rounded bg-blue-600 hover:bg-blue-700 text-white text-xs',
|
className: 'px-3 py-1 rounded bg-blue-600 hover:bg-blue-700 text-white text-xs',
|
||||||
@@ -3210,7 +3210,7 @@
|
|||||||
setTimeout(() => fileData.revokeObjectURL(url), 15000);
|
setTimeout(() => fileData.revokeObjectURL(url), 15000);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Download failed:', e);
|
console.error('Download failed:', e);
|
||||||
addMessageWithAutoScroll(`❌ Ошибка загрузки файла: ${String(e?.message || e)}`, 'system');
|
addMessageWithAutoScroll(`❌ File upload error: ${String(e?.message || e)}`, 'system');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 'Скачать')
|
}, 'Скачать')
|
||||||
@@ -3221,15 +3221,14 @@
|
|||||||
|
|
||||||
// Error callback
|
// Error callback
|
||||||
(error) => {
|
(error) => {
|
||||||
// Более мягкая обработка ошибок файлового трансфера - не закрываем сессию
|
|
||||||
console.error('File transfer error:', error);
|
console.error('File transfer error:', error);
|
||||||
|
|
||||||
if (error.includes('Connection not ready')) {
|
if (error.includes('Connection not ready')) {
|
||||||
addMessageWithAutoScroll(`⚠️ Ошибка передачи файла: соединение не готово. Попробуйте позже.`, 'system');
|
addMessageWithAutoScroll(`⚠️ File transfer error: connection not ready. Try again later.`, 'system');
|
||||||
} else if (error.includes('File too large')) {
|
} else if (error.includes('File too large')) {
|
||||||
addMessageWithAutoScroll(`⚠️ Файл слишком большой. Максимальный размер: 100 МБ`, 'system');
|
addMessageWithAutoScroll(`⚠️ File is too big. Maximum size: 100 MB`, 'system');
|
||||||
} else {
|
} else {
|
||||||
addMessageWithAutoScroll(`❌ Ошибка передачи файла: ${error}`, 'system');
|
addMessageWithAutoScroll(`❌ File transfer error: ${error}`, 'system');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ const FileTransferComponent = ({ webrtcManager, isConnected }) => {
|
|||||||
webrtcManager.setFileTransferCallbacks(
|
webrtcManager.setFileTransferCallbacks(
|
||||||
// Progress callback - ТОЛЬКО обновляем UI, НЕ отправляем в чат
|
// Progress callback - ТОЛЬКО обновляем UI, НЕ отправляем в чат
|
||||||
(progress) => {
|
(progress) => {
|
||||||
console.log(`📁 UI Progress: ${progress.fileName}: ${progress.progress.toFixed(1)}% (${progress.status})`);
|
|
||||||
|
|
||||||
// Обновляем только локальное состояние
|
// Обновляем только локальное состояние
|
||||||
const currentTransfers = webrtcManager.getFileTransfers();
|
const currentTransfers = webrtcManager.getFileTransfers();
|
||||||
setTransfers(currentTransfers);
|
setTransfers(currentTransfers);
|
||||||
@@ -36,7 +34,6 @@ const FileTransferComponent = ({ webrtcManager, isConnected }) => {
|
|||||||
|
|
||||||
// File received callback - добавляем кнопку скачивания в UI
|
// File received callback - добавляем кнопку скачивания в UI
|
||||||
(fileData) => {
|
(fileData) => {
|
||||||
console.log(`📥 File received in UI: ${fileData.fileName}`);
|
|
||||||
// Добавляем в список готовых к скачиванию
|
// Добавляем в список готовых к скачиванию
|
||||||
setReadyFiles(prev => {
|
setReadyFiles(prev => {
|
||||||
// избегаем дублей по fileId
|
// избегаем дублей по fileId
|
||||||
@@ -59,7 +56,6 @@ const FileTransferComponent = ({ webrtcManager, isConnected }) => {
|
|||||||
|
|
||||||
// Error callback
|
// Error callback
|
||||||
(error) => {
|
(error) => {
|
||||||
console.error('File transfer error in UI:', error);
|
|
||||||
const currentTransfers = webrtcManager.getFileTransfers();
|
const currentTransfers = webrtcManager.getFileTransfers();
|
||||||
setTransfers(currentTransfers);
|
setTransfers(currentTransfers);
|
||||||
|
|
||||||
@@ -83,19 +79,27 @@ const FileTransferComponent = ({ webrtcManager, isConnected }) => {
|
|||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
try {
|
try {
|
||||||
console.log(`🚀 Starting file upload from UI: ${file.name}`);
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Валидация файла перед отправкой
|
||||||
|
const validation = webrtcManager.validateFile(file);
|
||||||
|
if (!validation.isValid) {
|
||||||
|
const errorMessage = validation.errors.join('. ');
|
||||||
|
alert(`Файл ${file.name} не может быть отправлен: ${errorMessage}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
await webrtcManager.sendFile(file);
|
await webrtcManager.sendFile(file);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Более мягкая обработка ошибок - не закрываем сессию
|
// Более мягкая обработка ошибок - не закрываем сессию
|
||||||
console.error(`Failed to send ${file.name}:`, error);
|
|
||||||
|
|
||||||
// Показываем пользователю ошибку, но не закрываем соединение
|
// Показываем пользователю ошибку, но не закрываем соединение
|
||||||
if (error.message.includes('Connection not ready')) {
|
if (error.message.includes('Connection not ready')) {
|
||||||
alert(`Файл ${file.name} не может быть отправлен сейчас. Проверьте соединение и попробуйте снова.`);
|
alert(`Файл ${file.name} не может быть отправлен сейчас. Проверьте соединение и попробуйте снова.`);
|
||||||
} else if (error.message.includes('File too large')) {
|
} else if (error.message.includes('File too large') || error.message.includes('exceeds maximum')) {
|
||||||
alert(`Файл ${file.name} слишком большой. Максимальный размер: 100 MB`);
|
alert(`Файл ${file.name} слишком большой: ${error.message}`);
|
||||||
} else if (error.message.includes('Maximum concurrent transfers')) {
|
} else if (error.message.includes('Maximum concurrent transfers')) {
|
||||||
alert(`Достигнут лимит одновременных передач. Дождитесь завершения текущих передач.`);
|
alert(`Достигнут лимит одновременных передач. Дождитесь завершения текущих передач.`);
|
||||||
|
} else if (error.message.includes('File type not allowed')) {
|
||||||
|
alert(`Тип файла ${file.name} не поддерживается: ${error.message}`);
|
||||||
} else {
|
} else {
|
||||||
alert(`Ошибка отправки файла ${file.name}: ${error.message}`);
|
alert(`Ошибка отправки файла ${file.name}: ${error.message}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -497,7 +497,7 @@ const EnhancedMinimalHeader = ({
|
|||||||
React.createElement('p', {
|
React.createElement('p', {
|
||||||
key: 'subtitle',
|
key: 'subtitle',
|
||||||
className: 'text-xs sm:text-sm text-muted hidden sm:block'
|
className: 'text-xs sm:text-sm text-muted hidden sm:block'
|
||||||
}, 'End-to-end freedom. v4.01.222')
|
}, 'End-to-end freedom. v4.01.412')
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
|
|
||||||
|
|||||||
@@ -449,9 +449,20 @@ _initializeMutexSystem() {
|
|||||||
}
|
}
|
||||||
// Initialization
|
// Initialization
|
||||||
this.initializeFileTransfer();
|
this.initializeFileTransfer();
|
||||||
// Small delay for initialization
|
|
||||||
await new Promise(r => setTimeout(r, 300));
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Ждем инициализации с таймаутом
|
||||||
return !!this.fileTransferSystem;
|
let attempts = 0;
|
||||||
|
const maxAttempts = 50; // 5 секунд максимум
|
||||||
|
while (!this.fileTransferSystem && attempts < maxAttempts) {
|
||||||
|
await new Promise(r => setTimeout(r, 100));
|
||||||
|
attempts++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.fileTransferSystem) {
|
||||||
|
throw new Error('File transfer system initialization timeout');
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('❌ _ensureFileTransferReady failed:', e?.message || e);
|
console.error('❌ _ensureFileTransferReady failed:', e?.message || e);
|
||||||
return false;
|
return false;
|
||||||
@@ -1510,6 +1521,12 @@ _initializeMutexSystem() {
|
|||||||
try {
|
try {
|
||||||
console.log('🔧 Initializing Enhanced Secure File Transfer system...');
|
console.log('🔧 Initializing Enhanced Secure File Transfer system...');
|
||||||
|
|
||||||
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Проверяем, не инициализирована ли уже система
|
||||||
|
if (this.fileTransferSystem) {
|
||||||
|
console.log('✅ File transfer system already initialized');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// CRITICAL FIX: Step-by-step readiness check
|
// CRITICAL FIX: Step-by-step readiness check
|
||||||
const channelReady = !!(this.dataChannel && this.dataChannel.readyState === 'open');
|
const channelReady = !!(this.dataChannel && this.dataChannel.readyState === 'open');
|
||||||
if (!channelReady) {
|
if (!channelReady) {
|
||||||
@@ -3274,17 +3291,43 @@ async processMessage(data) {
|
|||||||
await this.fileTransferSystem.handleFileMessage(parsed);
|
await this.fileTransferSystem.handleFileMessage(parsed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Attempt lazy initialization on the receiver side
|
|
||||||
console.warn('⚠️ File transfer system not available, attempting lazy init...');
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Автоматическая инициализация файловой системы
|
||||||
|
console.warn('⚠️ File transfer system not available, attempting automatic initialization...');
|
||||||
try {
|
try {
|
||||||
await this._ensureFileTransferReady();
|
// Проверяем готовность соединения
|
||||||
if (this.fileTransferSystem && typeof this.fileTransferSystem.handleFileMessage === 'function') {
|
if (!this.isVerified) {
|
||||||
await this.fileTransferSystem.handleFileMessage(parsed);
|
console.warn('⚠️ Connection not verified, cannot initialize file transfer');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.dataChannel || this.dataChannel.readyState !== 'open') {
|
||||||
|
console.warn('⚠️ Data channel not open, cannot initialize file transfer');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализируем файловую систему
|
||||||
|
this.initializeFileTransfer();
|
||||||
|
|
||||||
|
// Ждем инициализации
|
||||||
|
let attempts = 0;
|
||||||
|
const maxAttempts = 30; // 3 секунды максимум
|
||||||
|
while (!this.fileTransferSystem && attempts < maxAttempts) {
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 100));
|
||||||
|
attempts++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.fileTransferSystem && typeof this.fileTransferSystem.handleFileMessage === 'function') {
|
||||||
|
console.log('✅ File transfer system initialized, processing message:', parsed.type);
|
||||||
|
await this.fileTransferSystem.handleFileMessage(parsed);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
console.error('❌ File transfer system initialization failed');
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('❌ Lazy init of file transfer failed:', e?.message || e);
|
console.error('❌ Automatic file transfer initialization failed:', e?.message || e);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error('❌ File transfer system not available for:', parsed.type);
|
console.error('❌ File transfer system not available for:', parsed.type);
|
||||||
return; // IMPORTANT: Exit after handling
|
return; // IMPORTANT: Exit after handling
|
||||||
}
|
}
|
||||||
@@ -4134,8 +4177,8 @@ handleSystemMessage(message) {
|
|||||||
try {
|
try {
|
||||||
await this.establishConnection();
|
await this.establishConnection();
|
||||||
|
|
||||||
// CRITICAL: Initialize file transfer immediately
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Инициализируем файловую систему для обеих сторон
|
||||||
this.initializeFileTransfer();
|
this.initializeFileTransfer();
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Error in establishConnection:', error);
|
console.error('❌ Error in establishConnection:', error);
|
||||||
@@ -4214,6 +4257,26 @@ handleSystemMessage(message) {
|
|||||||
if (parsed.type && fileMessageTypes.includes(parsed.type)) {
|
if (parsed.type && fileMessageTypes.includes(parsed.type)) {
|
||||||
console.log('📁 File message intercepted at WebRTC level:', parsed.type);
|
console.log('📁 File message intercepted at WebRTC level:', parsed.type);
|
||||||
|
|
||||||
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Инициализируем файловую систему при получении файловых сообщений
|
||||||
|
if (!this.fileTransferSystem) {
|
||||||
|
try {
|
||||||
|
// Проверяем готовность соединения
|
||||||
|
if (this.isVerified && this.dataChannel && this.dataChannel.readyState === 'open') {
|
||||||
|
this.initializeFileTransfer();
|
||||||
|
|
||||||
|
// Ждем инициализации
|
||||||
|
let attempts = 0;
|
||||||
|
const maxAttempts = 30;
|
||||||
|
while (!this.fileTransferSystem && attempts < maxAttempts) {
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 100));
|
||||||
|
attempts++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (initError) {
|
||||||
|
console.error('❌ Failed to initialize file transfer system for receiver:', initError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handle directly WITHOUT extra checks
|
// Handle directly WITHOUT extra checks
|
||||||
if (window.fileTransferSystem) {
|
if (window.fileTransferSystem) {
|
||||||
console.log('📁 Forwarding to global file transfer system:', parsed.type);
|
console.log('📁 Forwarding to global file transfer system:', parsed.type);
|
||||||
@@ -6930,14 +6993,14 @@ _getMutexSystemDiagnostics() {
|
|||||||
console.log('✅ Session verified - setting isVerified to true');
|
console.log('✅ Session verified - setting isVerified to true');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize file transfer system with a delay
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Инициализируем файловую систему для обеих сторон
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
try {
|
try {
|
||||||
this.initializeFileTransfer();
|
this.initializeFileTransfer();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('⚠️ File transfer initialization failed during session activation:', error.message);
|
console.warn('⚠️ File transfer initialization failed during session activation:', error.message);
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
console.log('✅ Session activation handled successfully');
|
console.log('✅ Session activation handled successfully');
|
||||||
|
|
||||||
@@ -7011,11 +7074,20 @@ checkFileTransferReadiness() {
|
|||||||
dataChannelState: this.dataChannel?.readyState,
|
dataChannelState: this.dataChannel?.readyState,
|
||||||
isConnected: this.isConnected(),
|
isConnected: this.isConnected(),
|
||||||
isVerified: this.isVerified,
|
isVerified: this.isVerified,
|
||||||
|
isInitiator: this.isInitiator,
|
||||||
hasEncryptionKey: !!this.encryptionKey,
|
hasEncryptionKey: !!this.encryptionKey,
|
||||||
hasMacKey: !!this.macKey,
|
hasMacKey: !!this.macKey,
|
||||||
hasMetadataKey: !!this.metadataKey
|
hasMetadataKey: !!this.metadataKey,
|
||||||
|
hasKeyFingerprint: !!this.keyFingerprint,
|
||||||
|
hasSessionSalt: !!this.sessionSalt
|
||||||
},
|
},
|
||||||
fileTransferSystem: null
|
fileTransferSystem: null,
|
||||||
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Дополнительная диагностика
|
||||||
|
globalState: {
|
||||||
|
fileTransferActive: window.FILE_TRANSFER_ACTIVE,
|
||||||
|
hasGlobalFileTransferSystem: !!window.fileTransferSystem,
|
||||||
|
globalFileTransferSystemType: window.fileTransferSystem?.constructor?.name
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.fileTransferSystem) {
|
if (this.fileTransferSystem) {
|
||||||
@@ -7028,6 +7100,103 @@ checkFileTransferReadiness() {
|
|||||||
|
|
||||||
return diagnostics;
|
return diagnostics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getSupportedFileTypes() {
|
||||||
|
if (!this.fileTransferSystem) {
|
||||||
|
return { error: 'File transfer system not initialized' };
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return this.fileTransferSystem.getSupportedFileTypes();
|
||||||
|
} catch (error) {
|
||||||
|
return { error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
validateFile(file) {
|
||||||
|
if (!this.fileTransferSystem) {
|
||||||
|
return {
|
||||||
|
isValid: false,
|
||||||
|
errors: ['File transfer system not initialized'],
|
||||||
|
fileType: null,
|
||||||
|
fileSize: file?.size || 0,
|
||||||
|
formattedSize: '0 B'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return this.fileTransferSystem.validateFile(file);
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
isValid: false,
|
||||||
|
errors: [error.message],
|
||||||
|
fileType: null,
|
||||||
|
fileSize: file?.size || 0,
|
||||||
|
formattedSize: '0 B'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getFileTypeInfo() {
|
||||||
|
if (!this.fileTransferSystem) {
|
||||||
|
return { error: 'File transfer system not initialized' };
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return this.fileTransferSystem.getFileTypeInfo();
|
||||||
|
} catch (error) {
|
||||||
|
return { error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Метод для принудительной инициализации файловой системы
|
||||||
|
forceInitializeFileTransfer() {
|
||||||
|
try {
|
||||||
|
// Проверяем готовность соединения
|
||||||
|
if (!this.isVerified) {
|
||||||
|
throw new Error('Connection not verified');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.dataChannel || this.dataChannel.readyState !== 'open') {
|
||||||
|
throw new Error('Data channel not open');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.encryptionKey || !this.macKey) {
|
||||||
|
throw new Error('Encryption keys not ready');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Очищаем существующую систему
|
||||||
|
if (this.fileTransferSystem) {
|
||||||
|
this.fileTransferSystem.cleanup();
|
||||||
|
this.fileTransferSystem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Инициализируем новую систему
|
||||||
|
this.initializeFileTransfer();
|
||||||
|
|
||||||
|
// Ждем инициализации
|
||||||
|
let attempts = 0;
|
||||||
|
const maxAttempts = 50;
|
||||||
|
while (!this.fileTransferSystem && attempts < maxAttempts) {
|
||||||
|
// Синхронное ожидание
|
||||||
|
const start = Date.now();
|
||||||
|
while (Date.now() - start < 100) {
|
||||||
|
// busy wait
|
||||||
|
}
|
||||||
|
attempts++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.fileTransferSystem) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
throw new Error('Force initialization timeout');
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Force file transfer initialization failed:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { EnhancedSecureWebRTCManager };
|
export { EnhancedSecureWebRTCManager };
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// PWA Offline Manager for SecureBit.chat
|
// PWA Offline Manager for SecureBit.chat
|
||||||
// Enhanced Security Edition v4.01.222
|
// Enhanced Security Edition v4.01.412
|
||||||
// Handles offline functionality, data synchronization, and user experience
|
// Handles offline functionality, data synchronization, and user experience
|
||||||
|
|
||||||
class PWAOfflineManager {
|
class PWAOfflineManager {
|
||||||
|
|||||||
@@ -15,13 +15,7 @@ class EnhancedSecureFileTransfer {
|
|||||||
window.FILE_TRANSFER_ACTIVE = true;
|
window.FILE_TRANSFER_ACTIVE = true;
|
||||||
window.fileTransferSystem = this;
|
window.fileTransferSystem = this;
|
||||||
|
|
||||||
console.log('🔍 Debug: webrtcManager in constructor:', {
|
|
||||||
hasWebrtcManager: !!webrtcManager,
|
|
||||||
webrtcManagerType: webrtcManager.constructor?.name,
|
|
||||||
hasEncryptionKey: !!webrtcManager.encryptionKey,
|
|
||||||
hasMacKey: !!webrtcManager.macKey,
|
|
||||||
hasEcdhKeyPair: !!webrtcManager.ecdhKeyPair
|
|
||||||
});
|
|
||||||
|
|
||||||
// Transfer settings
|
// Transfer settings
|
||||||
// Размер чанка по умолчанию (баланс нагрузки и стабильности очереди)
|
// Размер чанка по умолчанию (баланс нагрузки и стабильности очереди)
|
||||||
@@ -31,6 +25,89 @@ class EnhancedSecureFileTransfer {
|
|||||||
this.CHUNK_TIMEOUT = 30000; // 30 seconds per chunk
|
this.CHUNK_TIMEOUT = 30000; // 30 seconds per chunk
|
||||||
this.RETRY_ATTEMPTS = 3;
|
this.RETRY_ATTEMPTS = 3;
|
||||||
|
|
||||||
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Система ограничений по типам файлов
|
||||||
|
this.FILE_TYPE_RESTRICTIONS = {
|
||||||
|
// Документы
|
||||||
|
documents: {
|
||||||
|
extensions: ['.pdf', '.doc', '.docx', '.txt', '.md', '.rtf', '.odt'],
|
||||||
|
mimeTypes: [
|
||||||
|
'application/pdf',
|
||||||
|
'application/msword',
|
||||||
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||||
|
'text/plain',
|
||||||
|
'text/markdown',
|
||||||
|
'application/rtf',
|
||||||
|
'application/vnd.oasis.opendocument.text'
|
||||||
|
],
|
||||||
|
maxSize: 50 * 1024 * 1024, // 50 MB
|
||||||
|
category: 'Documents',
|
||||||
|
description: 'PDF, DOC, TXT, MD, RTF, ODT'
|
||||||
|
},
|
||||||
|
|
||||||
|
// Изображения
|
||||||
|
images: {
|
||||||
|
extensions: ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp', '.svg', '.ico'],
|
||||||
|
mimeTypes: [
|
||||||
|
'image/jpeg',
|
||||||
|
'image/png',
|
||||||
|
'image/gif',
|
||||||
|
'image/webp',
|
||||||
|
'image/bmp',
|
||||||
|
'image/svg+xml',
|
||||||
|
'image/x-icon'
|
||||||
|
],
|
||||||
|
maxSize: 25 * 1024 * 1024, // 25 MB
|
||||||
|
category: 'Images',
|
||||||
|
description: 'JPG, PNG, GIF, WEBP, BMP, SVG, ICO'
|
||||||
|
},
|
||||||
|
|
||||||
|
// Архивы
|
||||||
|
archives: {
|
||||||
|
extensions: ['.zip', '.rar', '.7z', '.tar', '.gz', '.bz2', '.xz'],
|
||||||
|
mimeTypes: [
|
||||||
|
'application/zip',
|
||||||
|
'application/x-rar-compressed',
|
||||||
|
'application/x-7z-compressed',
|
||||||
|
'application/x-tar',
|
||||||
|
'application/gzip',
|
||||||
|
'application/x-bzip2',
|
||||||
|
'application/x-xz'
|
||||||
|
],
|
||||||
|
maxSize: 100 * 1024 * 1024, // 100 MB
|
||||||
|
category: 'Archives',
|
||||||
|
description: 'ZIP, RAR, 7Z, TAR, GZ, BZ2, XZ'
|
||||||
|
},
|
||||||
|
|
||||||
|
// Медиа файлы
|
||||||
|
media: {
|
||||||
|
extensions: ['.mp3', '.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.webm', '.ogg', '.wav'],
|
||||||
|
mimeTypes: [
|
||||||
|
'audio/mpeg',
|
||||||
|
'video/mp4',
|
||||||
|
'video/x-msvideo',
|
||||||
|
'video/x-matroska',
|
||||||
|
'video/quicktime',
|
||||||
|
'video/x-ms-wmv',
|
||||||
|
'video/x-flv',
|
||||||
|
'video/webm',
|
||||||
|
'audio/ogg',
|
||||||
|
'audio/wav'
|
||||||
|
],
|
||||||
|
maxSize: 100 * 1024 * 1024, // 100 MB
|
||||||
|
category: 'Media',
|
||||||
|
description: 'MP3, MP4, AVI, MKV, MOV, WMV, FLV, WEBM, OGG, WAV'
|
||||||
|
},
|
||||||
|
|
||||||
|
// Общие файлы (любые другие типы)
|
||||||
|
general: {
|
||||||
|
extensions: [], // Пустой массив означает "все остальные"
|
||||||
|
mimeTypes: [], // Пустой массив означает "все остальные"
|
||||||
|
maxSize: 50 * 1024 * 1024, // 50 MB
|
||||||
|
category: 'General',
|
||||||
|
description: 'Any file type up to size limits'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Active transfers tracking
|
// Active transfers tracking
|
||||||
this.activeTransfers = new Map(); // fileId -> transfer state
|
this.activeTransfers = new Map(); // fileId -> transfer state
|
||||||
this.receivingTransfers = new Map(); // fileId -> receiving state
|
this.receivingTransfers = new Map(); // fileId -> receiving state
|
||||||
@@ -48,7 +125,125 @@ class EnhancedSecureFileTransfer {
|
|||||||
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Регистрируем обработчик сообщений
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Регистрируем обработчик сообщений
|
||||||
this.setupFileMessageHandlers();
|
this.setupFileMessageHandlers();
|
||||||
|
|
||||||
console.log('🔒 Enhanced Secure File Transfer initialized');
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Устанавливаем ссылку в WebRTC менеджере
|
||||||
|
if (this.webrtcManager) {
|
||||||
|
this.webrtcManager.fileTransferSystem = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// FILE TYPE VALIDATION SYSTEM
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
// Определяем тип файла по расширению и MIME типу
|
||||||
|
getFileType(file) {
|
||||||
|
const fileName = file.name.toLowerCase();
|
||||||
|
const fileExtension = fileName.substring(fileName.lastIndexOf('.'));
|
||||||
|
const mimeType = file.type.toLowerCase();
|
||||||
|
|
||||||
|
// Проверяем каждый тип файла
|
||||||
|
for (const [typeKey, typeConfig] of Object.entries(this.FILE_TYPE_RESTRICTIONS)) {
|
||||||
|
if (typeKey === 'general') continue; // Пропускаем общий тип
|
||||||
|
|
||||||
|
// Проверяем расширение
|
||||||
|
if (typeConfig.extensions.includes(fileExtension)) {
|
||||||
|
return {
|
||||||
|
type: typeKey,
|
||||||
|
category: typeConfig.category,
|
||||||
|
description: typeConfig.description,
|
||||||
|
maxSize: typeConfig.maxSize,
|
||||||
|
allowed: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем MIME тип
|
||||||
|
if (typeConfig.mimeTypes.includes(mimeType)) {
|
||||||
|
return {
|
||||||
|
type: typeKey,
|
||||||
|
category: typeConfig.category,
|
||||||
|
description: typeConfig.description,
|
||||||
|
maxSize: typeConfig.maxSize,
|
||||||
|
allowed: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если не найден в специфических типах, используем общий
|
||||||
|
const generalConfig = this.FILE_TYPE_RESTRICTIONS.general;
|
||||||
|
return {
|
||||||
|
type: 'general',
|
||||||
|
category: generalConfig.category,
|
||||||
|
description: generalConfig.description,
|
||||||
|
maxSize: generalConfig.maxSize,
|
||||||
|
allowed: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем, разрешен ли файл для передачи
|
||||||
|
validateFile(file) {
|
||||||
|
const fileType = this.getFileType(file);
|
||||||
|
const errors = [];
|
||||||
|
|
||||||
|
// Проверяем размер файла
|
||||||
|
if (file.size > fileType.maxSize) {
|
||||||
|
errors.push(`File size (${this.formatFileSize(file.size)}) exceeds maximum allowed for ${fileType.category} (${this.formatFileSize(fileType.maxSize)})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем, разрешен ли тип файла
|
||||||
|
if (!fileType.allowed) {
|
||||||
|
errors.push(`File type not allowed. Supported types: ${fileType.description}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем общий лимит размера
|
||||||
|
if (file.size > this.MAX_FILE_SIZE) {
|
||||||
|
errors.push(`File size (${this.formatFileSize(file.size)}) exceeds general limit (${this.formatFileSize(this.MAX_FILE_SIZE)})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
isValid: errors.length === 0,
|
||||||
|
errors: errors,
|
||||||
|
fileType: fileType,
|
||||||
|
fileSize: file.size,
|
||||||
|
formattedSize: this.formatFileSize(file.size)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Форматируем размер файла для отображения
|
||||||
|
formatFileSize(bytes) {
|
||||||
|
if (bytes === 0) return '0 B';
|
||||||
|
const k = 1024;
|
||||||
|
const sizes = ['B', 'KB', 'MB', 'GB'];
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получаем список поддерживаемых типов файлов
|
||||||
|
getSupportedFileTypes() {
|
||||||
|
const supportedTypes = {};
|
||||||
|
|
||||||
|
for (const [typeKey, typeConfig] of Object.entries(this.FILE_TYPE_RESTRICTIONS)) {
|
||||||
|
if (typeKey === 'general') continue;
|
||||||
|
|
||||||
|
supportedTypes[typeKey] = {
|
||||||
|
category: typeConfig.category,
|
||||||
|
description: typeConfig.description,
|
||||||
|
extensions: typeConfig.extensions,
|
||||||
|
maxSize: this.formatFileSize(typeConfig.maxSize),
|
||||||
|
maxSizeBytes: typeConfig.maxSize
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return supportedTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получаем общую информацию о поддерживаемых типах
|
||||||
|
getFileTypeInfo() {
|
||||||
|
return {
|
||||||
|
supportedTypes: this.getSupportedFileTypes(),
|
||||||
|
generalMaxSize: this.formatFileSize(this.MAX_FILE_SIZE),
|
||||||
|
generalMaxSizeBytes: this.MAX_FILE_SIZE,
|
||||||
|
restrictions: this.FILE_TYPE_RESTRICTIONS
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
@@ -104,16 +299,12 @@ class EnhancedSecureFileTransfer {
|
|||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
setupFileMessageHandlers() {
|
setupFileMessageHandlers() {
|
||||||
console.log('🔧 Setting up file message handlers');
|
|
||||||
|
|
||||||
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Ждем готовности dataChannel
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Ждем готовности dataChannel
|
||||||
if (!this.webrtcManager.dataChannel) {
|
if (!this.webrtcManager.dataChannel) {
|
||||||
console.log('⏰ DataChannel not ready, deferring setup...');
|
|
||||||
// Попытаемся настроить через небольшой интервал
|
// Попытаемся настроить через небольшой интервал
|
||||||
const setupRetry = setInterval(() => {
|
const setupRetry = setInterval(() => {
|
||||||
if (this.webrtcManager.dataChannel) {
|
if (this.webrtcManager.dataChannel) {
|
||||||
clearInterval(setupRetry);
|
clearInterval(setupRetry);
|
||||||
console.log('🔄 DataChannel ready, setting up handlers...');
|
|
||||||
this.setupMessageInterception();
|
this.setupMessageInterception();
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
@@ -121,7 +312,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
// Timeout для предотвращения бесконечного ожидания
|
// Timeout для предотвращения бесконечного ожидания
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
clearInterval(setupRetry);
|
clearInterval(setupRetry);
|
||||||
console.warn('⚠️ DataChannel setup timeout');
|
|
||||||
}, 5000);
|
}, 5000);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -129,15 +319,12 @@ class EnhancedSecureFileTransfer {
|
|||||||
|
|
||||||
// Если dataChannel уже готов, сразу настраиваем
|
// Если dataChannel уже готов, сразу настраиваем
|
||||||
this.setupMessageInterception();
|
this.setupMessageInterception();
|
||||||
|
|
||||||
console.log('✅ File message handlers configured');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// В методе setupMessageInterception(), замените весь метод на:
|
// В методе setupMessageInterception(), замените весь метод на:
|
||||||
setupMessageInterception() {
|
setupMessageInterception() {
|
||||||
try {
|
try {
|
||||||
if (!this.webrtcManager.dataChannel) {
|
if (!this.webrtcManager.dataChannel) {
|
||||||
console.warn('⚠️ WebRTC manager data channel not available yet');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,10 +332,14 @@ class EnhancedSecureFileTransfer {
|
|||||||
window.FILE_TRANSFER_ACTIVE = true;
|
window.FILE_TRANSFER_ACTIVE = true;
|
||||||
window.fileTransferSystem = this;
|
window.fileTransferSystem = this;
|
||||||
|
|
||||||
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Устанавливаем ссылку в WebRTC менеджере
|
||||||
|
if (this.webrtcManager) {
|
||||||
|
this.webrtcManager.fileTransferSystem = this;
|
||||||
|
}
|
||||||
|
|
||||||
// 1. ПЕРЕХВАТ НА УРОВНЕ dataChannel.onmessage
|
// 1. ПЕРЕХВАТ НА УРОВНЕ dataChannel.onmessage
|
||||||
if (this.webrtcManager.dataChannel.onmessage) {
|
if (this.webrtcManager.dataChannel.onmessage) {
|
||||||
this.originalOnMessage = this.webrtcManager.dataChannel.onmessage;
|
this.originalOnMessage = this.webrtcManager.dataChannel.onmessage;
|
||||||
console.log('💾 Original onmessage handler saved');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.webrtcManager.dataChannel.onmessage = async (event) => {
|
this.webrtcManager.dataChannel.onmessage = async (event) => {
|
||||||
@@ -159,7 +350,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
const parsed = JSON.parse(event.data);
|
const parsed = JSON.parse(event.data);
|
||||||
|
|
||||||
if (this.isFileTransferMessage(parsed)) {
|
if (this.isFileTransferMessage(parsed)) {
|
||||||
console.log('🛑 FILE MESSAGE BLOCKED FROM CHAT:', parsed.type);
|
|
||||||
await this.handleFileMessage(parsed);
|
await this.handleFileMessage(parsed);
|
||||||
return; // КРИТИЧЕСКИ ВАЖНО: НЕ передаем дальше
|
return; // КРИТИЧЕСКИ ВАЖНО: НЕ передаем дальше
|
||||||
}
|
}
|
||||||
@@ -179,8 +369,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('✅ Message interception set up successfully');
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Failed to set up message interception:', error);
|
console.error('❌ Failed to set up message interception:', error);
|
||||||
}
|
}
|
||||||
@@ -201,22 +389,48 @@ class EnhancedSecureFileTransfer {
|
|||||||
'file_transfer_error'
|
'file_transfer_error'
|
||||||
];
|
];
|
||||||
|
|
||||||
const isFileMessage = fileMessageTypes.includes(message.type);
|
return fileMessageTypes.includes(message.type);
|
||||||
|
|
||||||
if (isFileMessage) {
|
|
||||||
console.log(`🎯 CONFIRMED FILE MESSAGE: ${message.type} - WILL BE BLOCKED FROM CHAT`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return isFileMessage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обрабатываем файловые сообщения
|
// Обрабатываем файловые сообщения
|
||||||
async handleFileMessage(message) {
|
async handleFileMessage(message) {
|
||||||
try {
|
try {
|
||||||
console.log(`🔄 Handling file message: ${message.type}`, {
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Проверяем готовность файловой системы
|
||||||
fileId: message.fileId,
|
if (!this.webrtcManager.fileTransferSystem) {
|
||||||
type: message.type
|
try {
|
||||||
});
|
// Попытка инициализации файловой системы
|
||||||
|
if (typeof this.webrtcManager.initializeFileTransfer === 'function') {
|
||||||
|
this.webrtcManager.initializeFileTransfer();
|
||||||
|
|
||||||
|
// Ждем инициализации
|
||||||
|
let attempts = 0;
|
||||||
|
const maxAttempts = 50; // 5 секунд максимум
|
||||||
|
while (!this.webrtcManager.fileTransferSystem && attempts < maxAttempts) {
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 100));
|
||||||
|
attempts++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.webrtcManager.fileTransferSystem) {
|
||||||
|
throw new Error('File transfer system initialization timeout');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error('initializeFileTransfer method not available');
|
||||||
|
}
|
||||||
|
} catch (initError) {
|
||||||
|
console.error('❌ Failed to initialize file transfer system:', initError);
|
||||||
|
// Отправляем ошибку отправителю
|
||||||
|
if (message.fileId) {
|
||||||
|
const errorMessage = {
|
||||||
|
type: 'file_transfer_error',
|
||||||
|
fileId: message.fileId,
|
||||||
|
error: 'File transfer system not available',
|
||||||
|
timestamp: Date.now()
|
||||||
|
};
|
||||||
|
await this.sendSecureMessage(errorMessage);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case 'file_transfer_start':
|
case 'file_transfer_start':
|
||||||
@@ -269,8 +483,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
|
|
||||||
async deriveFileSessionKey(fileId) {
|
async deriveFileSessionKey(fileId) {
|
||||||
try {
|
try {
|
||||||
console.log('🔑 Deriving file session key for:', fileId);
|
|
||||||
|
|
||||||
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Используем keyFingerprint и sessionSalt
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Используем keyFingerprint и sessionSalt
|
||||||
// которые уже согласованы между пирами
|
// которые уже согласованы между пирами
|
||||||
|
|
||||||
@@ -323,7 +535,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
created: Date.now()
|
created: Date.now()
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('✅ File session key derived successfully for:', fileId);
|
|
||||||
return { key: fileSessionKey, salt: Array.from(fileSalt) };
|
return { key: fileSessionKey, salt: Array.from(fileSalt) };
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -334,8 +545,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
|
|
||||||
async deriveFileSessionKeyFromSalt(fileId, saltArray) {
|
async deriveFileSessionKeyFromSalt(fileId, saltArray) {
|
||||||
try {
|
try {
|
||||||
console.log('🔑 Deriving session key from salt for receiver:', fileId);
|
|
||||||
|
|
||||||
// Проверка соли
|
// Проверка соли
|
||||||
if (!saltArray || !Array.isArray(saltArray) || saltArray.length !== 32) {
|
if (!saltArray || !Array.isArray(saltArray) || saltArray.length !== 32) {
|
||||||
throw new Error(`Invalid salt: ${saltArray?.length || 0} bytes`);
|
throw new Error(`Invalid salt: ${saltArray?.length || 0} bytes`);
|
||||||
@@ -389,7 +598,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
created: Date.now()
|
created: Date.now()
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('✅ Session key derived successfully for receiver:', fileId);
|
|
||||||
return fileSessionKey;
|
return fileSessionKey;
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -409,22 +617,16 @@ class EnhancedSecureFileTransfer {
|
|||||||
throw new Error('WebRTC Manager not initialized');
|
throw new Error('WebRTC Manager not initialized');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔍 Debug: webrtcManager in sendFile:', {
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Валидация файла с новой системой типов
|
||||||
hasWebrtcManager: !!this.webrtcManager,
|
|
||||||
webrtcManagerType: this.webrtcManager.constructor?.name,
|
|
||||||
hasEncryptionKey: !!this.webrtcManager.encryptionKey,
|
|
||||||
hasMacKey: !!this.webrtcManager.macKey,
|
|
||||||
isConnected: this.webrtcManager.isConnected?.(),
|
|
||||||
isVerified: this.webrtcManager.isVerified
|
|
||||||
});
|
|
||||||
|
|
||||||
// Validate file
|
|
||||||
if (!file || !file.size) {
|
if (!file || !file.size) {
|
||||||
throw new Error('Invalid file object');
|
throw new Error('Invalid file object');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file.size > this.MAX_FILE_SIZE) {
|
// Проверяем тип и размер файла
|
||||||
throw new Error(`File too large. Maximum size: ${this.MAX_FILE_SIZE / 1024 / 1024} MB`);
|
const validation = this.validateFile(file);
|
||||||
|
if (!validation.isValid) {
|
||||||
|
const errorMessage = validation.errors.join('. ');
|
||||||
|
throw new Error(errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.activeTransfers.size >= this.MAX_CONCURRENT_TRANSFERS) {
|
if (this.activeTransfers.size >= this.MAX_CONCURRENT_TRANSFERS) {
|
||||||
@@ -492,16 +694,10 @@ class EnhancedSecureFileTransfer {
|
|||||||
version: '2.0'
|
version: '2.0'
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('📁 Sending file metadata for:', transferState.file.name);
|
|
||||||
|
|
||||||
// Send metadata through secure channel
|
// Send metadata through secure channel
|
||||||
await this.sendSecureMessage(metadata);
|
await this.sendSecureMessage(metadata);
|
||||||
|
|
||||||
transferState.status = 'metadata_sent';
|
transferState.status = 'metadata_sent';
|
||||||
|
|
||||||
// ИСПРАВЛЕНИЕ: НЕ отправляем системные сообщения в чат
|
|
||||||
// Только логируем
|
|
||||||
console.log(`📁 File metadata sent: ${transferState.file.name} (5% progress)`);
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Failed to send file metadata:', error);
|
console.error('❌ Failed to send file metadata:', error);
|
||||||
@@ -531,23 +727,17 @@ class EnhancedSecureFileTransfer {
|
|||||||
transferState.sentChunks++;
|
transferState.sentChunks++;
|
||||||
const progress = Math.round((transferState.sentChunks / totalChunks) * 95) + 5; // 5-100%
|
const progress = Math.round((transferState.sentChunks / totalChunks) * 95) + 5; // 5-100%
|
||||||
|
|
||||||
// ИСПРАВЛЕНИЕ: НЕ отправляем каждый чанк в чат
|
|
||||||
// Только логируем
|
|
||||||
console.log(`📤 Chunk sent ${transferState.sentChunks}/${totalChunks} (${progress}%)`);
|
|
||||||
|
|
||||||
// Backpressure: ждём разгрузки очереди перед следующим чанком
|
// Backpressure: ждём разгрузки очереди перед следующим чанком
|
||||||
await this.waitForBackpressure();
|
await this.waitForBackpressure();
|
||||||
}
|
}
|
||||||
|
|
||||||
transferState.status = 'waiting_confirmation';
|
transferState.status = 'waiting_confirmation';
|
||||||
console.log('✅ All chunks sent, waiting for completion confirmation');
|
|
||||||
|
|
||||||
// Timeout for completion confirmation
|
// Timeout for completion confirmation
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (this.activeTransfers.has(transferState.fileId)) {
|
if (this.activeTransfers.has(transferState.fileId)) {
|
||||||
const state = this.activeTransfers.get(transferState.fileId);
|
const state = this.activeTransfers.get(transferState.fileId);
|
||||||
if (state.status === 'waiting_confirmation') {
|
if (state.status === 'waiting_confirmation') {
|
||||||
console.log('⏰ Transfer completion timeout, cleaning up');
|
|
||||||
this.cleanupTransfer(transferState.fileId);
|
this.cleanupTransfer(transferState.fileId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -689,8 +879,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
|
|
||||||
async handleFileTransferStart(metadata) {
|
async handleFileTransferStart(metadata) {
|
||||||
try {
|
try {
|
||||||
console.log('📥 Receiving file transfer:', metadata.fileName);
|
|
||||||
|
|
||||||
// Validate metadata
|
// Validate metadata
|
||||||
if (!metadata.fileId || !metadata.fileName || !metadata.fileSize) {
|
if (!metadata.fileId || !metadata.fileName || !metadata.fileSize) {
|
||||||
throw new Error('Invalid file transfer metadata');
|
throw new Error('Invalid file transfer metadata');
|
||||||
@@ -698,7 +886,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
|
|
||||||
// Check if we already have this transfer
|
// Check if we already have this transfer
|
||||||
if (this.receivingTransfers.has(metadata.fileId)) {
|
if (this.receivingTransfers.has(metadata.fileId)) {
|
||||||
console.warn('⚠️ File transfer already in progress:', metadata.fileId);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -737,18 +924,12 @@ class EnhancedSecureFileTransfer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
await this.sendSecureMessage(response);
|
await this.sendSecureMessage(response);
|
||||||
|
|
||||||
// ИСПРАВЛЕНИЕ: НЕ отправляем уведомления в чат
|
|
||||||
// Только логируем
|
|
||||||
console.log(`📥 Started receiving file: ${receivingState.fileName} (${(receivingState.fileSize / 1024 / 1024).toFixed(2)} MB)`);
|
|
||||||
|
|
||||||
// Process buffered chunks if any
|
// Process buffered chunks if any
|
||||||
if (this.pendingChunks.has(metadata.fileId)) {
|
if (this.pendingChunks.has(metadata.fileId)) {
|
||||||
console.log('🔄 Processing buffered chunks for:', metadata.fileId);
|
|
||||||
const bufferedChunks = this.pendingChunks.get(metadata.fileId);
|
const bufferedChunks = this.pendingChunks.get(metadata.fileId);
|
||||||
|
|
||||||
for (const [chunkIndex, chunkMessage] of bufferedChunks.entries()) {
|
for (const [chunkIndex, chunkMessage] of bufferedChunks.entries()) {
|
||||||
console.log('📦 Processing buffered chunk:', chunkIndex);
|
|
||||||
await this.handleFileChunk(chunkMessage);
|
await this.handleFileChunk(chunkMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -776,8 +957,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
|
|
||||||
// Buffer early chunks if transfer not yet initialized
|
// Buffer early chunks if transfer not yet initialized
|
||||||
if (!receivingState) {
|
if (!receivingState) {
|
||||||
console.log('📦 Buffering early chunk for:', chunkMessage.fileId, 'chunk:', chunkMessage.chunkIndex);
|
|
||||||
|
|
||||||
if (!this.pendingChunks.has(chunkMessage.fileId)) {
|
if (!this.pendingChunks.has(chunkMessage.fileId)) {
|
||||||
this.pendingChunks.set(chunkMessage.fileId, new Map());
|
this.pendingChunks.set(chunkMessage.fileId, new Map());
|
||||||
}
|
}
|
||||||
@@ -791,7 +970,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
|
|
||||||
// Check if chunk already received
|
// Check if chunk already received
|
||||||
if (receivingState.receivedChunks.has(chunkMessage.chunkIndex)) {
|
if (receivingState.receivedChunks.has(chunkMessage.chunkIndex)) {
|
||||||
console.log('⚠️ Duplicate chunk received:', chunkMessage.chunkIndex);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -812,8 +990,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
throw new Error('Missing encrypted data');
|
throw new Error('Missing encrypted data');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔓 Decrypting chunk:', chunkMessage.chunkIndex);
|
|
||||||
|
|
||||||
const decryptedChunk = await crypto.subtle.decrypt(
|
const decryptedChunk = await crypto.subtle.decrypt(
|
||||||
{
|
{
|
||||||
name: 'AES-GCM',
|
name: 'AES-GCM',
|
||||||
@@ -832,14 +1008,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
receivingState.receivedChunks.set(chunkMessage.chunkIndex, decryptedChunk);
|
receivingState.receivedChunks.set(chunkMessage.chunkIndex, decryptedChunk);
|
||||||
receivingState.receivedCount++;
|
receivingState.receivedCount++;
|
||||||
|
|
||||||
// Update progress
|
|
||||||
const progress = Math.round((receivingState.receivedCount / receivingState.totalChunks) * 100);
|
|
||||||
|
|
||||||
console.log(`📥 Received chunk ${chunkMessage.chunkIndex + 1}/${receivingState.totalChunks} (${progress}%)`);
|
|
||||||
|
|
||||||
// ИСПРАВЛЕНИЕ: НЕ отправляем уведомления о прогрессе в чат
|
|
||||||
// Только логируем
|
|
||||||
|
|
||||||
// Send chunk confirmation
|
// Send chunk confirmation
|
||||||
const confirmation = {
|
const confirmation = {
|
||||||
type: 'chunk_confirmation',
|
type: 'chunk_confirmation',
|
||||||
@@ -881,8 +1049,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
|
|
||||||
async assembleFile(receivingState) {
|
async assembleFile(receivingState) {
|
||||||
try {
|
try {
|
||||||
console.log('🔄 Assembling file:', receivingState.fileName);
|
|
||||||
|
|
||||||
receivingState.status = 'assembling';
|
receivingState.status = 'assembling';
|
||||||
|
|
||||||
// Verify we have all chunks
|
// Verify we have all chunks
|
||||||
@@ -979,8 +1145,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
}
|
}
|
||||||
this.receivingTransfers.delete(receivingState.fileId);
|
this.receivingTransfers.delete(receivingState.fileId);
|
||||||
|
|
||||||
console.log('✅ File assembly completed:', receivingState.fileName);
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ File assembly failed:', error);
|
console.error('❌ File assembly failed:', error);
|
||||||
receivingState.status = 'failed';
|
receivingState.status = 'failed';
|
||||||
@@ -1017,20 +1181,15 @@ class EnhancedSecureFileTransfer {
|
|||||||
|
|
||||||
handleTransferResponse(response) {
|
handleTransferResponse(response) {
|
||||||
try {
|
try {
|
||||||
console.log('📨 File transfer response:', response);
|
|
||||||
|
|
||||||
const transferState = this.activeTransfers.get(response.fileId);
|
const transferState = this.activeTransfers.get(response.fileId);
|
||||||
|
|
||||||
if (!transferState) {
|
if (!transferState) {
|
||||||
console.warn('⚠️ Received response for unknown transfer:', response.fileId);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.accepted) {
|
if (response.accepted) {
|
||||||
console.log('✅ File transfer accepted by peer');
|
|
||||||
transferState.status = 'accepted';
|
transferState.status = 'accepted';
|
||||||
} else {
|
} else {
|
||||||
console.log('❌ File transfer rejected by peer:', response.error);
|
|
||||||
transferState.status = 'rejected';
|
transferState.status = 'rejected';
|
||||||
|
|
||||||
if (this.onError) {
|
if (this.onError) {
|
||||||
@@ -1048,14 +1207,11 @@ class EnhancedSecureFileTransfer {
|
|||||||
try {
|
try {
|
||||||
const transferState = this.activeTransfers.get(confirmation.fileId);
|
const transferState = this.activeTransfers.get(confirmation.fileId);
|
||||||
if (!transferState) {
|
if (!transferState) {
|
||||||
console.warn('⚠️ Received chunk confirmation for unknown transfer:', confirmation.fileId);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
transferState.confirmedChunks++;
|
transferState.confirmedChunks++;
|
||||||
transferState.lastChunkTime = Date.now();
|
transferState.lastChunkTime = Date.now();
|
||||||
|
|
||||||
console.log(`✅ Chunk ${confirmation.chunkIndex} confirmed for ${confirmation.fileId}`);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Failed to handle chunk confirmation:', error);
|
console.error('❌ Failed to handle chunk confirmation:', error);
|
||||||
}
|
}
|
||||||
@@ -1063,16 +1219,12 @@ class EnhancedSecureFileTransfer {
|
|||||||
|
|
||||||
handleTransferComplete(completion) {
|
handleTransferComplete(completion) {
|
||||||
try {
|
try {
|
||||||
console.log('🏁 Transfer completion:', completion);
|
|
||||||
|
|
||||||
const transferState = this.activeTransfers.get(completion.fileId);
|
const transferState = this.activeTransfers.get(completion.fileId);
|
||||||
if (!transferState) {
|
if (!transferState) {
|
||||||
console.warn('⚠️ Received completion for unknown transfer:', completion.fileId);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (completion.success) {
|
if (completion.success) {
|
||||||
console.log('✅ File transfer completed successfully');
|
|
||||||
transferState.status = 'completed';
|
transferState.status = 'completed';
|
||||||
transferState.endTime = Date.now();
|
transferState.endTime = Date.now();
|
||||||
|
|
||||||
@@ -1086,7 +1238,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('❌ File transfer failed:', completion.error);
|
|
||||||
transferState.status = 'failed';
|
transferState.status = 'failed';
|
||||||
|
|
||||||
if (this.onError) {
|
if (this.onError) {
|
||||||
@@ -1103,8 +1254,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
|
|
||||||
handleTransferError(errorMessage) {
|
handleTransferError(errorMessage) {
|
||||||
try {
|
try {
|
||||||
console.error('❌ Transfer error received:', errorMessage);
|
|
||||||
|
|
||||||
const transferState = this.activeTransfers.get(errorMessage.fileId);
|
const transferState = this.activeTransfers.get(errorMessage.fileId);
|
||||||
if (transferState) {
|
if (transferState) {
|
||||||
transferState.status = 'failed';
|
transferState.status = 'failed';
|
||||||
@@ -1241,32 +1390,37 @@ class EnhancedSecureFileTransfer {
|
|||||||
maxFileSize: this.MAX_FILE_SIZE,
|
maxFileSize: this.MAX_FILE_SIZE,
|
||||||
chunkSize: this.CHUNK_SIZE,
|
chunkSize: this.CHUNK_SIZE,
|
||||||
hasWebrtcManager: !!this.webrtcManager,
|
hasWebrtcManager: !!this.webrtcManager,
|
||||||
isConnected: this.webrtcManager?.isConnected?.() || false
|
isConnected: this.webrtcManager?.isConnected?.() || false,
|
||||||
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Дополнительная диагностика
|
||||||
|
hasDataChannel: !!this.webrtcManager?.dataChannel,
|
||||||
|
dataChannelState: this.webrtcManager?.dataChannel?.readyState,
|
||||||
|
isVerified: this.webrtcManager?.isVerified,
|
||||||
|
hasEncryptionKey: !!this.webrtcManager?.encryptionKey,
|
||||||
|
hasMacKey: !!this.webrtcManager?.macKey,
|
||||||
|
linkedToWebRTCManager: this.webrtcManager?.fileTransferSystem === this,
|
||||||
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Информация о поддерживаемых типах файлов
|
||||||
|
supportedFileTypes: this.getSupportedFileTypes(),
|
||||||
|
fileTypeInfo: this.getFileTypeInfo()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
console.log('🧹 Cleaning up file transfer system');
|
|
||||||
|
|
||||||
// ИСПРАВЛЕНИЕ: Очищаем глобальные флаги
|
// ИСПРАВЛЕНИЕ: Очищаем глобальные флаги
|
||||||
window.FILE_TRANSFER_ACTIVE = false;
|
window.FILE_TRANSFER_ACTIVE = false;
|
||||||
window.fileTransferSystem = null;
|
window.fileTransferSystem = null;
|
||||||
|
|
||||||
// ИСПРАВЛЕНИЕ: Восстанавливаем ВСЕ перехваченные методы
|
// ИСПРАВЛЕНИЕ: Восстанавливаем ВСЕ перехваченные методы
|
||||||
if (this.webrtcManager && this.webrtcManager.dataChannel && this.originalOnMessage) {
|
if (this.webrtcManager && this.webrtcManager.dataChannel && this.originalOnMessage) {
|
||||||
console.log('🔄 Restoring original onmessage handler');
|
|
||||||
this.webrtcManager.dataChannel.onmessage = this.originalOnMessage;
|
this.webrtcManager.dataChannel.onmessage = this.originalOnMessage;
|
||||||
this.originalOnMessage = null;
|
this.originalOnMessage = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.webrtcManager && this.originalProcessMessage) {
|
if (this.webrtcManager && this.originalProcessMessage) {
|
||||||
console.log('🔄 Restoring original processMessage handler');
|
|
||||||
this.webrtcManager.processMessage = this.originalProcessMessage;
|
this.webrtcManager.processMessage = this.originalProcessMessage;
|
||||||
this.originalProcessMessage = null;
|
this.originalProcessMessage = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.webrtcManager && this.originalRemoveSecurityLayers) {
|
if (this.webrtcManager && this.originalRemoveSecurityLayers) {
|
||||||
console.log('🔄 Restoring original removeSecurityLayers handler');
|
|
||||||
this.webrtcManager.removeSecurityLayers = this.originalRemoveSecurityLayers;
|
this.webrtcManager.removeSecurityLayers = this.originalRemoveSecurityLayers;
|
||||||
this.originalRemoveSecurityLayers = null;
|
this.originalRemoveSecurityLayers = null;
|
||||||
}
|
}
|
||||||
@@ -1288,8 +1442,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
this.sessionKeys.clear();
|
this.sessionKeys.clear();
|
||||||
this.transferNonces.clear();
|
this.transferNonces.clear();
|
||||||
this.processedChunks.clear();
|
this.processedChunks.clear();
|
||||||
|
|
||||||
console.log('✅ File transfer system cleaned up');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
@@ -1297,38 +1449,67 @@ class EnhancedSecureFileTransfer {
|
|||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
onSessionUpdate(sessionData) {
|
onSessionUpdate(sessionData) {
|
||||||
console.log('🔄 File transfer system: session updated', sessionData);
|
|
||||||
|
|
||||||
// Clear session keys cache for resync
|
// Clear session keys cache for resync
|
||||||
this.sessionKeys.clear();
|
this.sessionKeys.clear();
|
||||||
|
|
||||||
console.log('✅ File transfer keys cache cleared for resync');
|
|
||||||
|
|
||||||
// If there are active transfers, log warning
|
|
||||||
if (this.activeTransfers.size > 0 || this.receivingTransfers.size > 0) {
|
|
||||||
console.warn('⚠️ Session updated during active file transfers - may cause issues');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// DEBUGGING AND DIAGNOSTICS
|
// DEBUGGING AND DIAGNOSTICS
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Метод для диагностики проблем с передачей файлов
|
||||||
|
diagnoseFileTransferIssue() {
|
||||||
|
const diagnosis = {
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
fileTransferSystem: {
|
||||||
|
initialized: !!this,
|
||||||
|
hasWebrtcManager: !!this.webrtcManager,
|
||||||
|
webrtcManagerType: this.webrtcManager?.constructor?.name,
|
||||||
|
linkedToWebRTCManager: this.webrtcManager?.fileTransferSystem === this
|
||||||
|
},
|
||||||
|
webrtcManager: {
|
||||||
|
hasDataChannel: !!this.webrtcManager?.dataChannel,
|
||||||
|
dataChannelState: this.webrtcManager?.dataChannel?.readyState,
|
||||||
|
isConnected: this.webrtcManager?.isConnected?.() || false,
|
||||||
|
isVerified: this.webrtcManager?.isVerified,
|
||||||
|
hasEncryptionKey: !!this.webrtcManager?.encryptionKey,
|
||||||
|
hasMacKey: !!this.webrtcManager?.macKey,
|
||||||
|
hasKeyFingerprint: !!this.webrtcManager?.keyFingerprint,
|
||||||
|
hasSessionSalt: !!this.webrtcManager?.sessionSalt
|
||||||
|
},
|
||||||
|
globalState: {
|
||||||
|
fileTransferActive: window.FILE_TRANSFER_ACTIVE,
|
||||||
|
hasGlobalFileTransferSystem: !!window.fileTransferSystem,
|
||||||
|
globalFileTransferSystemType: window.fileTransferSystem?.constructor?.name
|
||||||
|
},
|
||||||
|
transfers: {
|
||||||
|
activeTransfers: this.activeTransfers.size,
|
||||||
|
receivingTransfers: this.receivingTransfers.size,
|
||||||
|
pendingChunks: this.pendingChunks.size,
|
||||||
|
sessionKeys: this.sessionKeys.size
|
||||||
|
},
|
||||||
|
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Информация о поддерживаемых типах файлов
|
||||||
|
fileTypeSupport: {
|
||||||
|
supportedTypes: this.getSupportedFileTypes(),
|
||||||
|
generalMaxSize: this.formatFileSize(this.MAX_FILE_SIZE),
|
||||||
|
restrictions: Object.keys(this.FILE_TYPE_RESTRICTIONS)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return diagnosis;
|
||||||
|
}
|
||||||
|
|
||||||
async debugKeyDerivation(fileId) {
|
async debugKeyDerivation(fileId) {
|
||||||
try {
|
try {
|
||||||
console.log('🔍 Debug: Testing key derivation for:', fileId);
|
|
||||||
|
|
||||||
if (!this.webrtcManager.keyFingerprint || !this.webrtcManager.sessionSalt) {
|
if (!this.webrtcManager.keyFingerprint || !this.webrtcManager.sessionSalt) {
|
||||||
throw new Error('Session data not available');
|
throw new Error('Session data not available');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test sender derivation
|
// Test sender derivation
|
||||||
const senderResult = await this.deriveFileSessionKey(fileId);
|
const senderResult = await this.deriveFileSessionKey(fileId);
|
||||||
console.log('✅ Sender key derived successfully');
|
|
||||||
|
|
||||||
// Test receiver derivation with same salt
|
// Test receiver derivation with same salt
|
||||||
const receiverKey = await this.deriveFileSessionKeyFromSalt(fileId, senderResult.salt);
|
const receiverKey = await this.deriveFileSessionKeyFromSalt(fileId, senderResult.salt);
|
||||||
console.log('✅ Receiver key derived successfully');
|
|
||||||
|
|
||||||
// Test encryption/decryption
|
// Test encryption/decryption
|
||||||
const testData = new TextEncoder().encode('test data');
|
const testData = new TextEncoder().encode('test data');
|
||||||
@@ -1349,7 +1530,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
const decryptedText = new TextDecoder().decode(decrypted);
|
const decryptedText = new TextDecoder().decode(decrypted);
|
||||||
|
|
||||||
if (decryptedText === 'test data') {
|
if (decryptedText === 'test data') {
|
||||||
console.log('✅ Cross-key encryption/decryption test successful');
|
|
||||||
return { success: true, message: 'All tests passed' };
|
return { success: true, message: 'All tests passed' };
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Decryption verification failed');
|
throw new Error('Decryption verification failed');
|
||||||
@@ -1368,8 +1548,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
// Если переопределение processMessage не работает,
|
// Если переопределение processMessage не работает,
|
||||||
// используйте этот метод для явной регистрации обработчика
|
// используйте этот метод для явной регистрации обработчика
|
||||||
registerWithWebRTCManager() {
|
registerWithWebRTCManager() {
|
||||||
console.log('🔧 Registering file transfer handler with WebRTC manager');
|
|
||||||
|
|
||||||
if (!this.webrtcManager) {
|
if (!this.webrtcManager) {
|
||||||
throw new Error('WebRTC manager not available');
|
throw new Error('WebRTC manager not available');
|
||||||
}
|
}
|
||||||
@@ -1380,16 +1558,12 @@ class EnhancedSecureFileTransfer {
|
|||||||
// КРИТИЧЕСКИ ВАЖНО: Устанавливаем обработчик файловых сообщений
|
// КРИТИЧЕСКИ ВАЖНО: Устанавливаем обработчик файловых сообщений
|
||||||
this.webrtcManager.setFileMessageHandler = (handler) => {
|
this.webrtcManager.setFileMessageHandler = (handler) => {
|
||||||
this.webrtcManager._fileMessageHandler = handler;
|
this.webrtcManager._fileMessageHandler = handler;
|
||||||
console.log('✅ File message handler registered in WebRTC manager');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Регистрируем наш обработчик
|
// Регистрируем наш обработчик
|
||||||
this.webrtcManager.setFileMessageHandler((message) => {
|
this.webrtcManager.setFileMessageHandler((message) => {
|
||||||
console.log('📁 File message via registered handler:', message.type);
|
|
||||||
return this.handleFileMessage(message);
|
return this.handleFileMessage(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('✅ File transfer handler registered');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Метод для прямого вызова из WebRTC менеджера
|
// Метод для прямого вызова из WebRTC менеджера
|
||||||
@@ -1400,7 +1574,6 @@ class EnhancedSecureFileTransfer {
|
|||||||
const parsed = JSON.parse(event.data);
|
const parsed = JSON.parse(event.data);
|
||||||
|
|
||||||
if (fileTransferSystem.isFileTransferMessage(parsed)) {
|
if (fileTransferSystem.isFileTransferMessage(parsed)) {
|
||||||
console.log('📁 File message filtered by static method:', parsed.type);
|
|
||||||
await fileTransferSystem.handleFileMessage(parsed);
|
await fileTransferSystem.handleFileMessage(parsed);
|
||||||
return true; // Сообщение обработано
|
return true; // Сообщение обработано
|
||||||
}
|
}
|
||||||
|
|||||||
4
sw.js
4
sw.js
@@ -1,5 +1,5 @@
|
|||||||
// SecureBit.chat Service Worker
|
// SecureBit.chat Service Worker
|
||||||
// Enhanced Security Edition v4.01.222
|
// Enhanced Security Edition v4.01.412
|
||||||
|
|
||||||
const CACHE_NAME = 'securebit-v4.0.3';
|
const CACHE_NAME = 'securebit-v4.0.3';
|
||||||
const STATIC_CACHE = 'securebit-static-v4.0.3';
|
const STATIC_CACHE = 'securebit-static-v4.0.3';
|
||||||
@@ -352,4 +352,4 @@ self.addEventListener('unhandledrejection', (event) => {
|
|||||||
console.error('❌ Service Worker unhandled rejection:', event.reason);
|
console.error('❌ Service Worker unhandled rejection:', event.reason);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('🔧 SecureBit.chat Service Worker loaded - Enhanced Security Edition v4.01.222');
|
console.log('🔧 SecureBit.chat Service Worker loaded - Enhanced Security Edition v4.01.412');
|
||||||
Reference in New Issue
Block a user