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:
lockbitchat
2025-08-21 17:40:17 -04:00
parent 3eab0588db
commit cef5654cf8
9 changed files with 522 additions and 177 deletions

View File

@@ -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>

View File

@@ -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**

View File

@@ -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');
} }
} }
); );

View File

@@ -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}`);
} }

View File

@@ -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')
]) ])
]), ]),

View File

@@ -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 };

View File

@@ -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 {

View File

@@ -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
View File

@@ -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');