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:
@@ -25,8 +25,6 @@ const FileTransferComponent = ({ webrtcManager, isConnected }) => {
|
||||
webrtcManager.setFileTransferCallbacks(
|
||||
// Progress callback - ТОЛЬКО обновляем UI, НЕ отправляем в чат
|
||||
(progress) => {
|
||||
console.log(`📁 UI Progress: ${progress.fileName}: ${progress.progress.toFixed(1)}% (${progress.status})`);
|
||||
|
||||
// Обновляем только локальное состояние
|
||||
const currentTransfers = webrtcManager.getFileTransfers();
|
||||
setTransfers(currentTransfers);
|
||||
@@ -36,7 +34,6 @@ const FileTransferComponent = ({ webrtcManager, isConnected }) => {
|
||||
|
||||
// File received callback - добавляем кнопку скачивания в UI
|
||||
(fileData) => {
|
||||
console.log(`📥 File received in UI: ${fileData.fileName}`);
|
||||
// Добавляем в список готовых к скачиванию
|
||||
setReadyFiles(prev => {
|
||||
// избегаем дублей по fileId
|
||||
@@ -59,7 +56,6 @@ const FileTransferComponent = ({ webrtcManager, isConnected }) => {
|
||||
|
||||
// Error callback
|
||||
(error) => {
|
||||
console.error('File transfer error in UI:', error);
|
||||
const currentTransfers = webrtcManager.getFileTransfers();
|
||||
setTransfers(currentTransfers);
|
||||
|
||||
@@ -83,19 +79,27 @@ const FileTransferComponent = ({ webrtcManager, isConnected }) => {
|
||||
|
||||
for (const file of files) {
|
||||
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);
|
||||
} catch (error) {
|
||||
// Более мягкая обработка ошибок - не закрываем сессию
|
||||
console.error(`Failed to send ${file.name}:`, error);
|
||||
|
||||
// Показываем пользователю ошибку, но не закрываем соединение
|
||||
if (error.message.includes('Connection not ready')) {
|
||||
alert(`Файл ${file.name} не может быть отправлен сейчас. Проверьте соединение и попробуйте снова.`);
|
||||
} else if (error.message.includes('File too large')) {
|
||||
alert(`Файл ${file.name} слишком большой. Максимальный размер: 100 MB`);
|
||||
} else if (error.message.includes('File too large') || error.message.includes('exceeds maximum')) {
|
||||
alert(`Файл ${file.name} слишком большой: ${error.message}`);
|
||||
} else if (error.message.includes('Maximum concurrent transfers')) {
|
||||
alert(`Достигнут лимит одновременных передач. Дождитесь завершения текущих передач.`);
|
||||
} else if (error.message.includes('File type not allowed')) {
|
||||
alert(`Тип файла ${file.name} не поддерживается: ${error.message}`);
|
||||
} else {
|
||||
alert(`Ошибка отправки файла ${file.name}: ${error.message}`);
|
||||
}
|
||||
|
||||
@@ -497,7 +497,7 @@ const EnhancedMinimalHeader = ({
|
||||
React.createElement('p', {
|
||||
key: 'subtitle',
|
||||
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
|
||||
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) {
|
||||
console.error('❌ _ensureFileTransferReady failed:', e?.message || e);
|
||||
return false;
|
||||
@@ -1510,6 +1521,12 @@ _initializeMutexSystem() {
|
||||
try {
|
||||
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
|
||||
const channelReady = !!(this.dataChannel && this.dataChannel.readyState === 'open');
|
||||
if (!channelReady) {
|
||||
@@ -3274,17 +3291,43 @@ async processMessage(data) {
|
||||
await this.fileTransferSystem.handleFileMessage(parsed);
|
||||
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 {
|
||||
await this._ensureFileTransferReady();
|
||||
if (this.fileTransferSystem && typeof this.fileTransferSystem.handleFileMessage === 'function') {
|
||||
await this.fileTransferSystem.handleFileMessage(parsed);
|
||||
// Проверяем готовность соединения
|
||||
if (!this.isVerified) {
|
||||
console.warn('⚠️ Connection not verified, cannot initialize file transfer');
|
||||
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) {
|
||||
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);
|
||||
return; // IMPORTANT: Exit after handling
|
||||
}
|
||||
@@ -4134,8 +4177,8 @@ handleSystemMessage(message) {
|
||||
try {
|
||||
await this.establishConnection();
|
||||
|
||||
// CRITICAL: Initialize file transfer immediately
|
||||
this.initializeFileTransfer();
|
||||
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Инициализируем файловую систему для обеих сторон
|
||||
this.initializeFileTransfer();
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error in establishConnection:', error);
|
||||
@@ -4214,6 +4257,26 @@ handleSystemMessage(message) {
|
||||
if (parsed.type && fileMessageTypes.includes(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
|
||||
if (window.fileTransferSystem) {
|
||||
console.log('📁 Forwarding to global file transfer system:', parsed.type);
|
||||
@@ -6930,14 +6993,14 @@ _getMutexSystemDiagnostics() {
|
||||
console.log('✅ Session verified - setting isVerified to true');
|
||||
}
|
||||
|
||||
// Initialize file transfer system with a delay
|
||||
setTimeout(() => {
|
||||
try {
|
||||
this.initializeFileTransfer();
|
||||
} catch (error) {
|
||||
console.warn('⚠️ File transfer initialization failed during session activation:', error.message);
|
||||
}
|
||||
}, 1000);
|
||||
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Инициализируем файловую систему для обеих сторон
|
||||
setTimeout(() => {
|
||||
try {
|
||||
this.initializeFileTransfer();
|
||||
} catch (error) {
|
||||
console.warn('⚠️ File transfer initialization failed during session activation:', error.message);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
console.log('✅ Session activation handled successfully');
|
||||
|
||||
@@ -7011,11 +7074,20 @@ checkFileTransferReadiness() {
|
||||
dataChannelState: this.dataChannel?.readyState,
|
||||
isConnected: this.isConnected(),
|
||||
isVerified: this.isVerified,
|
||||
isInitiator: this.isInitiator,
|
||||
hasEncryptionKey: !!this.encryptionKey,
|
||||
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) {
|
||||
@@ -7028,6 +7100,103 @@ checkFileTransferReadiness() {
|
||||
|
||||
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 };
|
||||
@@ -1,5 +1,5 @@
|
||||
// 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
|
||||
|
||||
class PWAOfflineManager {
|
||||
|
||||
@@ -15,13 +15,7 @@ class EnhancedSecureFileTransfer {
|
||||
window.FILE_TRANSFER_ACTIVE = true;
|
||||
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
|
||||
// Размер чанка по умолчанию (баланс нагрузки и стабильности очереди)
|
||||
@@ -31,6 +25,89 @@ class EnhancedSecureFileTransfer {
|
||||
this.CHUNK_TIMEOUT = 30000; // 30 seconds per chunk
|
||||
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
|
||||
this.activeTransfers = new Map(); // fileId -> transfer state
|
||||
this.receivingTransfers = new Map(); // fileId -> receiving state
|
||||
@@ -48,7 +125,125 @@ class EnhancedSecureFileTransfer {
|
||||
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Регистрируем обработчик сообщений
|
||||
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() {
|
||||
console.log('🔧 Setting up file message handlers');
|
||||
|
||||
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Ждем готовности dataChannel
|
||||
if (!this.webrtcManager.dataChannel) {
|
||||
console.log('⏰ DataChannel not ready, deferring setup...');
|
||||
// Попытаемся настроить через небольшой интервал
|
||||
const setupRetry = setInterval(() => {
|
||||
if (this.webrtcManager.dataChannel) {
|
||||
clearInterval(setupRetry);
|
||||
console.log('🔄 DataChannel ready, setting up handlers...');
|
||||
this.setupMessageInterception();
|
||||
}
|
||||
}, 100);
|
||||
@@ -121,7 +312,6 @@ class EnhancedSecureFileTransfer {
|
||||
// Timeout для предотвращения бесконечного ожидания
|
||||
setTimeout(() => {
|
||||
clearInterval(setupRetry);
|
||||
console.warn('⚠️ DataChannel setup timeout');
|
||||
}, 5000);
|
||||
|
||||
return;
|
||||
@@ -129,15 +319,12 @@ class EnhancedSecureFileTransfer {
|
||||
|
||||
// Если dataChannel уже готов, сразу настраиваем
|
||||
this.setupMessageInterception();
|
||||
|
||||
console.log('✅ File message handlers configured');
|
||||
}
|
||||
|
||||
// В методе setupMessageInterception(), замените весь метод на:
|
||||
setupMessageInterception() {
|
||||
try {
|
||||
if (!this.webrtcManager.dataChannel) {
|
||||
console.warn('⚠️ WebRTC manager data channel not available yet');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -145,10 +332,14 @@ class EnhancedSecureFileTransfer {
|
||||
window.FILE_TRANSFER_ACTIVE = true;
|
||||
window.fileTransferSystem = this;
|
||||
|
||||
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Устанавливаем ссылку в WebRTC менеджере
|
||||
if (this.webrtcManager) {
|
||||
this.webrtcManager.fileTransferSystem = this;
|
||||
}
|
||||
|
||||
// 1. ПЕРЕХВАТ НА УРОВНЕ dataChannel.onmessage
|
||||
if (this.webrtcManager.dataChannel.onmessage) {
|
||||
this.originalOnMessage = this.webrtcManager.dataChannel.onmessage;
|
||||
console.log('💾 Original onmessage handler saved');
|
||||
}
|
||||
|
||||
this.webrtcManager.dataChannel.onmessage = async (event) => {
|
||||
@@ -159,7 +350,6 @@ class EnhancedSecureFileTransfer {
|
||||
const parsed = JSON.parse(event.data);
|
||||
|
||||
if (this.isFileTransferMessage(parsed)) {
|
||||
console.log('🛑 FILE MESSAGE BLOCKED FROM CHAT:', parsed.type);
|
||||
await this.handleFileMessage(parsed);
|
||||
return; // КРИТИЧЕСКИ ВАЖНО: НЕ передаем дальше
|
||||
}
|
||||
@@ -179,8 +369,6 @@ class EnhancedSecureFileTransfer {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
console.log('✅ Message interception set up successfully');
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to set up message interception:', error);
|
||||
}
|
||||
@@ -201,22 +389,48 @@ class EnhancedSecureFileTransfer {
|
||||
'file_transfer_error'
|
||||
];
|
||||
|
||||
const isFileMessage = fileMessageTypes.includes(message.type);
|
||||
|
||||
if (isFileMessage) {
|
||||
console.log(`🎯 CONFIRMED FILE MESSAGE: ${message.type} - WILL BE BLOCKED FROM CHAT`);
|
||||
}
|
||||
|
||||
return isFileMessage;
|
||||
return fileMessageTypes.includes(message.type);
|
||||
}
|
||||
|
||||
// Обрабатываем файловые сообщения
|
||||
async handleFileMessage(message) {
|
||||
try {
|
||||
console.log(`🔄 Handling file message: ${message.type}`, {
|
||||
fileId: message.fileId,
|
||||
type: message.type
|
||||
});
|
||||
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Проверяем готовность файловой системы
|
||||
if (!this.webrtcManager.fileTransferSystem) {
|
||||
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) {
|
||||
case 'file_transfer_start':
|
||||
@@ -269,8 +483,6 @@ class EnhancedSecureFileTransfer {
|
||||
|
||||
async deriveFileSessionKey(fileId) {
|
||||
try {
|
||||
console.log('🔑 Deriving file session key for:', fileId);
|
||||
|
||||
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Используем keyFingerprint и sessionSalt
|
||||
// которые уже согласованы между пирами
|
||||
|
||||
@@ -323,7 +535,6 @@ class EnhancedSecureFileTransfer {
|
||||
created: Date.now()
|
||||
});
|
||||
|
||||
console.log('✅ File session key derived successfully for:', fileId);
|
||||
return { key: fileSessionKey, salt: Array.from(fileSalt) };
|
||||
|
||||
} catch (error) {
|
||||
@@ -334,8 +545,6 @@ class EnhancedSecureFileTransfer {
|
||||
|
||||
async deriveFileSessionKeyFromSalt(fileId, saltArray) {
|
||||
try {
|
||||
console.log('🔑 Deriving session key from salt for receiver:', fileId);
|
||||
|
||||
// Проверка соли
|
||||
if (!saltArray || !Array.isArray(saltArray) || saltArray.length !== 32) {
|
||||
throw new Error(`Invalid salt: ${saltArray?.length || 0} bytes`);
|
||||
@@ -389,7 +598,6 @@ class EnhancedSecureFileTransfer {
|
||||
created: Date.now()
|
||||
});
|
||||
|
||||
console.log('✅ Session key derived successfully for receiver:', fileId);
|
||||
return fileSessionKey;
|
||||
|
||||
} catch (error) {
|
||||
@@ -409,22 +617,16 @@ class EnhancedSecureFileTransfer {
|
||||
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) {
|
||||
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) {
|
||||
@@ -492,16 +694,10 @@ class EnhancedSecureFileTransfer {
|
||||
version: '2.0'
|
||||
};
|
||||
|
||||
console.log('📁 Sending file metadata for:', transferState.file.name);
|
||||
|
||||
// Send metadata through secure channel
|
||||
await this.sendSecureMessage(metadata);
|
||||
|
||||
transferState.status = 'metadata_sent';
|
||||
|
||||
// ИСПРАВЛЕНИЕ: НЕ отправляем системные сообщения в чат
|
||||
// Только логируем
|
||||
console.log(`📁 File metadata sent: ${transferState.file.name} (5% progress)`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to send file metadata:', error);
|
||||
@@ -531,23 +727,17 @@ class EnhancedSecureFileTransfer {
|
||||
transferState.sentChunks++;
|
||||
const progress = Math.round((transferState.sentChunks / totalChunks) * 95) + 5; // 5-100%
|
||||
|
||||
// ИСПРАВЛЕНИЕ: НЕ отправляем каждый чанк в чат
|
||||
// Только логируем
|
||||
console.log(`📤 Chunk sent ${transferState.sentChunks}/${totalChunks} (${progress}%)`);
|
||||
|
||||
// Backpressure: ждём разгрузки очереди перед следующим чанком
|
||||
await this.waitForBackpressure();
|
||||
}
|
||||
|
||||
transferState.status = 'waiting_confirmation';
|
||||
console.log('✅ All chunks sent, waiting for completion confirmation');
|
||||
|
||||
// Timeout for completion confirmation
|
||||
setTimeout(() => {
|
||||
if (this.activeTransfers.has(transferState.fileId)) {
|
||||
const state = this.activeTransfers.get(transferState.fileId);
|
||||
if (state.status === 'waiting_confirmation') {
|
||||
console.log('⏰ Transfer completion timeout, cleaning up');
|
||||
this.cleanupTransfer(transferState.fileId);
|
||||
}
|
||||
}
|
||||
@@ -689,8 +879,6 @@ class EnhancedSecureFileTransfer {
|
||||
|
||||
async handleFileTransferStart(metadata) {
|
||||
try {
|
||||
console.log('📥 Receiving file transfer:', metadata.fileName);
|
||||
|
||||
// Validate metadata
|
||||
if (!metadata.fileId || !metadata.fileName || !metadata.fileSize) {
|
||||
throw new Error('Invalid file transfer metadata');
|
||||
@@ -698,7 +886,6 @@ class EnhancedSecureFileTransfer {
|
||||
|
||||
// Check if we already have this transfer
|
||||
if (this.receivingTransfers.has(metadata.fileId)) {
|
||||
console.warn('⚠️ File transfer already in progress:', metadata.fileId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -737,18 +924,12 @@ class EnhancedSecureFileTransfer {
|
||||
};
|
||||
|
||||
await this.sendSecureMessage(response);
|
||||
|
||||
// ИСПРАВЛЕНИЕ: НЕ отправляем уведомления в чат
|
||||
// Только логируем
|
||||
console.log(`📥 Started receiving file: ${receivingState.fileName} (${(receivingState.fileSize / 1024 / 1024).toFixed(2)} MB)`);
|
||||
|
||||
// Process buffered chunks if any
|
||||
if (this.pendingChunks.has(metadata.fileId)) {
|
||||
console.log('🔄 Processing buffered chunks for:', metadata.fileId);
|
||||
const bufferedChunks = this.pendingChunks.get(metadata.fileId);
|
||||
|
||||
for (const [chunkIndex, chunkMessage] of bufferedChunks.entries()) {
|
||||
console.log('📦 Processing buffered chunk:', chunkIndex);
|
||||
await this.handleFileChunk(chunkMessage);
|
||||
}
|
||||
|
||||
@@ -776,8 +957,6 @@ class EnhancedSecureFileTransfer {
|
||||
|
||||
// Buffer early chunks if transfer not yet initialized
|
||||
if (!receivingState) {
|
||||
console.log('📦 Buffering early chunk for:', chunkMessage.fileId, 'chunk:', chunkMessage.chunkIndex);
|
||||
|
||||
if (!this.pendingChunks.has(chunkMessage.fileId)) {
|
||||
this.pendingChunks.set(chunkMessage.fileId, new Map());
|
||||
}
|
||||
@@ -791,7 +970,6 @@ class EnhancedSecureFileTransfer {
|
||||
|
||||
// Check if chunk already received
|
||||
if (receivingState.receivedChunks.has(chunkMessage.chunkIndex)) {
|
||||
console.log('⚠️ Duplicate chunk received:', chunkMessage.chunkIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -812,8 +990,6 @@ class EnhancedSecureFileTransfer {
|
||||
throw new Error('Missing encrypted data');
|
||||
}
|
||||
|
||||
console.log('🔓 Decrypting chunk:', chunkMessage.chunkIndex);
|
||||
|
||||
const decryptedChunk = await crypto.subtle.decrypt(
|
||||
{
|
||||
name: 'AES-GCM',
|
||||
@@ -832,14 +1008,6 @@ class EnhancedSecureFileTransfer {
|
||||
receivingState.receivedChunks.set(chunkMessage.chunkIndex, decryptedChunk);
|
||||
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
|
||||
const confirmation = {
|
||||
type: 'chunk_confirmation',
|
||||
@@ -881,8 +1049,6 @@ class EnhancedSecureFileTransfer {
|
||||
|
||||
async assembleFile(receivingState) {
|
||||
try {
|
||||
console.log('🔄 Assembling file:', receivingState.fileName);
|
||||
|
||||
receivingState.status = 'assembling';
|
||||
|
||||
// Verify we have all chunks
|
||||
@@ -979,8 +1145,6 @@ class EnhancedSecureFileTransfer {
|
||||
}
|
||||
this.receivingTransfers.delete(receivingState.fileId);
|
||||
|
||||
console.log('✅ File assembly completed:', receivingState.fileName);
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ File assembly failed:', error);
|
||||
receivingState.status = 'failed';
|
||||
@@ -1017,20 +1181,15 @@ class EnhancedSecureFileTransfer {
|
||||
|
||||
handleTransferResponse(response) {
|
||||
try {
|
||||
console.log('📨 File transfer response:', response);
|
||||
|
||||
const transferState = this.activeTransfers.get(response.fileId);
|
||||
|
||||
if (!transferState) {
|
||||
console.warn('⚠️ Received response for unknown transfer:', response.fileId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.accepted) {
|
||||
console.log('✅ File transfer accepted by peer');
|
||||
transferState.status = 'accepted';
|
||||
} else {
|
||||
console.log('❌ File transfer rejected by peer:', response.error);
|
||||
transferState.status = 'rejected';
|
||||
|
||||
if (this.onError) {
|
||||
@@ -1048,14 +1207,11 @@ class EnhancedSecureFileTransfer {
|
||||
try {
|
||||
const transferState = this.activeTransfers.get(confirmation.fileId);
|
||||
if (!transferState) {
|
||||
console.warn('⚠️ Received chunk confirmation for unknown transfer:', confirmation.fileId);
|
||||
return;
|
||||
}
|
||||
|
||||
transferState.confirmedChunks++;
|
||||
transferState.lastChunkTime = Date.now();
|
||||
|
||||
console.log(`✅ Chunk ${confirmation.chunkIndex} confirmed for ${confirmation.fileId}`);
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to handle chunk confirmation:', error);
|
||||
}
|
||||
@@ -1063,16 +1219,12 @@ class EnhancedSecureFileTransfer {
|
||||
|
||||
handleTransferComplete(completion) {
|
||||
try {
|
||||
console.log('🏁 Transfer completion:', completion);
|
||||
|
||||
const transferState = this.activeTransfers.get(completion.fileId);
|
||||
if (!transferState) {
|
||||
console.warn('⚠️ Received completion for unknown transfer:', completion.fileId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (completion.success) {
|
||||
console.log('✅ File transfer completed successfully');
|
||||
transferState.status = 'completed';
|
||||
transferState.endTime = Date.now();
|
||||
|
||||
@@ -1086,7 +1238,6 @@ class EnhancedSecureFileTransfer {
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log('❌ File transfer failed:', completion.error);
|
||||
transferState.status = 'failed';
|
||||
|
||||
if (this.onError) {
|
||||
@@ -1103,8 +1254,6 @@ class EnhancedSecureFileTransfer {
|
||||
|
||||
handleTransferError(errorMessage) {
|
||||
try {
|
||||
console.error('❌ Transfer error received:', errorMessage);
|
||||
|
||||
const transferState = this.activeTransfers.get(errorMessage.fileId);
|
||||
if (transferState) {
|
||||
transferState.status = 'failed';
|
||||
@@ -1241,32 +1390,37 @@ class EnhancedSecureFileTransfer {
|
||||
maxFileSize: this.MAX_FILE_SIZE,
|
||||
chunkSize: this.CHUNK_SIZE,
|
||||
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() {
|
||||
console.log('🧹 Cleaning up file transfer system');
|
||||
|
||||
// ИСПРАВЛЕНИЕ: Очищаем глобальные флаги
|
||||
window.FILE_TRANSFER_ACTIVE = false;
|
||||
window.fileTransferSystem = null;
|
||||
|
||||
// ИСПРАВЛЕНИЕ: Восстанавливаем ВСЕ перехваченные методы
|
||||
if (this.webrtcManager && this.webrtcManager.dataChannel && this.originalOnMessage) {
|
||||
console.log('🔄 Restoring original onmessage handler');
|
||||
this.webrtcManager.dataChannel.onmessage = this.originalOnMessage;
|
||||
this.originalOnMessage = null;
|
||||
}
|
||||
|
||||
if (this.webrtcManager && this.originalProcessMessage) {
|
||||
console.log('🔄 Restoring original processMessage handler');
|
||||
this.webrtcManager.processMessage = this.originalProcessMessage;
|
||||
this.originalProcessMessage = null;
|
||||
}
|
||||
|
||||
if (this.webrtcManager && this.originalRemoveSecurityLayers) {
|
||||
console.log('🔄 Restoring original removeSecurityLayers handler');
|
||||
this.webrtcManager.removeSecurityLayers = this.originalRemoveSecurityLayers;
|
||||
this.originalRemoveSecurityLayers = null;
|
||||
}
|
||||
@@ -1288,8 +1442,6 @@ class EnhancedSecureFileTransfer {
|
||||
this.sessionKeys.clear();
|
||||
this.transferNonces.clear();
|
||||
this.processedChunks.clear();
|
||||
|
||||
console.log('✅ File transfer system cleaned up');
|
||||
}
|
||||
|
||||
// ============================================
|
||||
@@ -1297,38 +1449,67 @@ class EnhancedSecureFileTransfer {
|
||||
// ============================================
|
||||
|
||||
onSessionUpdate(sessionData) {
|
||||
console.log('🔄 File transfer system: session updated', sessionData);
|
||||
|
||||
// Clear session keys cache for resync
|
||||
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
|
||||
// ============================================
|
||||
|
||||
// КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ: Метод для диагностики проблем с передачей файлов
|
||||
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) {
|
||||
try {
|
||||
console.log('🔍 Debug: Testing key derivation for:', fileId);
|
||||
|
||||
if (!this.webrtcManager.keyFingerprint || !this.webrtcManager.sessionSalt) {
|
||||
throw new Error('Session data not available');
|
||||
}
|
||||
|
||||
// Test sender derivation
|
||||
const senderResult = await this.deriveFileSessionKey(fileId);
|
||||
console.log('✅ Sender key derived successfully');
|
||||
|
||||
// Test receiver derivation with same salt
|
||||
const receiverKey = await this.deriveFileSessionKeyFromSalt(fileId, senderResult.salt);
|
||||
console.log('✅ Receiver key derived successfully');
|
||||
|
||||
// Test encryption/decryption
|
||||
const testData = new TextEncoder().encode('test data');
|
||||
@@ -1349,7 +1530,6 @@ class EnhancedSecureFileTransfer {
|
||||
const decryptedText = new TextDecoder().decode(decrypted);
|
||||
|
||||
if (decryptedText === 'test data') {
|
||||
console.log('✅ Cross-key encryption/decryption test successful');
|
||||
return { success: true, message: 'All tests passed' };
|
||||
} else {
|
||||
throw new Error('Decryption verification failed');
|
||||
@@ -1368,8 +1548,6 @@ class EnhancedSecureFileTransfer {
|
||||
// Если переопределение processMessage не работает,
|
||||
// используйте этот метод для явной регистрации обработчика
|
||||
registerWithWebRTCManager() {
|
||||
console.log('🔧 Registering file transfer handler with WebRTC manager');
|
||||
|
||||
if (!this.webrtcManager) {
|
||||
throw new Error('WebRTC manager not available');
|
||||
}
|
||||
@@ -1380,16 +1558,12 @@ class EnhancedSecureFileTransfer {
|
||||
// КРИТИЧЕСКИ ВАЖНО: Устанавливаем обработчик файловых сообщений
|
||||
this.webrtcManager.setFileMessageHandler = (handler) => {
|
||||
this.webrtcManager._fileMessageHandler = handler;
|
||||
console.log('✅ File message handler registered in WebRTC manager');
|
||||
};
|
||||
|
||||
// Регистрируем наш обработчик
|
||||
this.webrtcManager.setFileMessageHandler((message) => {
|
||||
console.log('📁 File message via registered handler:', message.type);
|
||||
return this.handleFileMessage(message);
|
||||
});
|
||||
|
||||
console.log('✅ File transfer handler registered');
|
||||
}
|
||||
|
||||
// Метод для прямого вызова из WebRTC менеджера
|
||||
@@ -1400,7 +1574,6 @@ class EnhancedSecureFileTransfer {
|
||||
const parsed = JSON.parse(event.data);
|
||||
|
||||
if (fileTransferSystem.isFileTransferMessage(parsed)) {
|
||||
console.log('📁 File message filtered by static method:', parsed.type);
|
||||
await fileTransferSystem.handleFileMessage(parsed);
|
||||
return true; // Сообщение обработано
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user