mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-24 23:45:18 +00:00
Remove local logging functionality
- Delete LoggingService.swift - Remove all bitchatLog() function calls throughout the codebase - Update Xcode project to remove LoggingService references - Clean up debug logging statements from all services and views
This commit is contained in:
@@ -19,10 +19,8 @@
|
|||||||
4E778E5A414571ACAC2A0F01 /* MessageRetentionService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A85BFDDE65B4CD8BDF6DDB /* MessageRetentionService.swift */; };
|
4E778E5A414571ACAC2A0F01 /* MessageRetentionService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A85BFDDE65B4CD8BDF6DDB /* MessageRetentionService.swift */; };
|
||||||
5D95F2BFBE257A1225998389 /* BatteryOptimizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED176FF3B274E35C2D827894 /* BatteryOptimizer.swift */; };
|
5D95F2BFBE257A1225998389 /* BatteryOptimizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED176FF3B274E35C2D827894 /* BatteryOptimizer.swift */; };
|
||||||
61C81ED5F679D5E973EE0C07 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448F84BF86A42A3CC4A9379 /* NotificationService.swift */; };
|
61C81ED5F679D5E973EE0C07 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448F84BF86A42A3CC4A9379 /* NotificationService.swift */; };
|
||||||
6A624D9359BCCAAE58CE0D64 /* LoggingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96CDF6D0AF0F2052A6C7E634 /* LoggingService.swift */; };
|
|
||||||
6DE056E1EE9850E9FBF50157 /* BitchatProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 229F17B68CFF7AB1BC91C847 /* BitchatProtocol.swift */; };
|
6DE056E1EE9850E9FBF50157 /* BitchatProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 229F17B68CFF7AB1BC91C847 /* BitchatProtocol.swift */; };
|
||||||
6E7761E21C99F28AE2F9BE5F /* BitchatApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF625BB3AD919322C01A46B2 /* BitchatApp.swift */; };
|
6E7761E21C99F28AE2F9BE5F /* BitchatApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF625BB3AD919322C01A46B2 /* BitchatApp.swift */; };
|
||||||
72BDC660D445E2D24AB90326 /* LoggingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96CDF6D0AF0F2052A6C7E634 /* LoggingService.swift */; };
|
|
||||||
739429DFDE5C5829CF70DA7D /* EncryptionService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DC1563390A15C042D059CF9 /* EncryptionService.swift */; };
|
739429DFDE5C5829CF70DA7D /* EncryptionService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DC1563390A15C042D059CF9 /* EncryptionService.swift */; };
|
||||||
749D8CF8A362B6CD0786782D /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448F84BF86A42A3CC4A9379 /* NotificationService.swift */; };
|
749D8CF8A362B6CD0786782D /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448F84BF86A42A3CC4A9379 /* NotificationService.swift */; };
|
||||||
7576A357B278E5733E9D9F33 /* ChatViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6B8F7B7D55092C2540A7996 /* ChatViewModel.swift */; };
|
7576A357B278E5733E9D9F33 /* ChatViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6B8F7B7D55092C2540A7996 /* ChatViewModel.swift */; };
|
||||||
@@ -85,7 +83,6 @@
|
|||||||
763E0DBA9492A654FC0CDCB9 /* AppInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppInfoView.swift; sourceTree = "<group>"; };
|
763E0DBA9492A654FC0CDCB9 /* AppInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppInfoView.swift; sourceTree = "<group>"; };
|
||||||
7EEBDA723E1CFD88758DA4AC /* bitchat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = bitchat.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
7EEBDA723E1CFD88758DA4AC /* bitchat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = bitchat.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
8DE9CDF66D4E52D268851048 /* MessagePaddingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagePaddingTests.swift; sourceTree = "<group>"; };
|
8DE9CDF66D4E52D268851048 /* MessagePaddingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagePaddingTests.swift; sourceTree = "<group>"; };
|
||||||
96CDF6D0AF0F2052A6C7E634 /* LoggingService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggingService.swift; sourceTree = "<group>"; };
|
|
||||||
997D512074C64904D75DDD40 /* bitchat.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = bitchat.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
997D512074C64904D75DDD40 /* bitchat.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = bitchat.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
A08E03AA0C63E97C91749AEC /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
A08E03AA0C63E97C91749AEC /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||||
A2136C3E22D02D4A8DBE7EAB /* BinaryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BinaryProtocol.swift; sourceTree = "<group>"; };
|
A2136C3E22D02D4A8DBE7EAB /* BinaryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BinaryProtocol.swift; sourceTree = "<group>"; };
|
||||||
@@ -192,7 +189,6 @@
|
|||||||
D5C3D880FF8AE1673B20E1E3 /* BluetoothMeshService.swift */,
|
D5C3D880FF8AE1673B20E1E3 /* BluetoothMeshService.swift */,
|
||||||
6DC1563390A15C042D059CF9 /* EncryptionService.swift */,
|
6DC1563390A15C042D059CF9 /* EncryptionService.swift */,
|
||||||
136696FC4436A02D98CE6A77 /* KeychainManager.swift */,
|
136696FC4436A02D98CE6A77 /* KeychainManager.swift */,
|
||||||
96CDF6D0AF0F2052A6C7E634 /* LoggingService.swift */,
|
|
||||||
67A85BFDDE65B4CD8BDF6DDB /* MessageRetentionService.swift */,
|
67A85BFDDE65B4CD8BDF6DDB /* MessageRetentionService.swift */,
|
||||||
AA4D7595A613F7ED3B386132 /* MessageRetryService.swift */,
|
AA4D7595A613F7ED3B386132 /* MessageRetryService.swift */,
|
||||||
3448F84BF86A42A3CC4A9379 /* NotificationService.swift */,
|
3448F84BF86A42A3CC4A9379 /* NotificationService.swift */,
|
||||||
@@ -349,7 +345,6 @@
|
|||||||
92D34E7A07C990C8A815B0CE /* ContentView.swift in Sources */,
|
92D34E7A07C990C8A815B0CE /* ContentView.swift in Sources */,
|
||||||
739429DFDE5C5829CF70DA7D /* EncryptionService.swift in Sources */,
|
739429DFDE5C5829CF70DA7D /* EncryptionService.swift in Sources */,
|
||||||
FB8819B4C84FAFEF5C36B216 /* KeychainManager.swift in Sources */,
|
FB8819B4C84FAFEF5C36B216 /* KeychainManager.swift in Sources */,
|
||||||
72BDC660D445E2D24AB90326 /* LoggingService.swift in Sources */,
|
|
||||||
4E778E5A414571ACAC2A0F01 /* MessageRetentionService.swift in Sources */,
|
4E778E5A414571ACAC2A0F01 /* MessageRetentionService.swift in Sources */,
|
||||||
C99763A4761567F587D21688 /* MessageRetryService.swift in Sources */,
|
C99763A4761567F587D21688 /* MessageRetryService.swift in Sources */,
|
||||||
749D8CF8A362B6CD0786782D /* NotificationService.swift in Sources */,
|
749D8CF8A362B6CD0786782D /* NotificationService.swift in Sources */,
|
||||||
@@ -372,7 +367,6 @@
|
|||||||
1D9674FA5F998503831DC281 /* ContentView.swift in Sources */,
|
1D9674FA5F998503831DC281 /* ContentView.swift in Sources */,
|
||||||
DDA1DFAB1FF7AADE52DC0F53 /* EncryptionService.swift in Sources */,
|
DDA1DFAB1FF7AADE52DC0F53 /* EncryptionService.swift in Sources */,
|
||||||
8F737CE0435792CC2AD65FCB /* KeychainManager.swift in Sources */,
|
8F737CE0435792CC2AD65FCB /* KeychainManager.swift in Sources */,
|
||||||
6A624D9359BCCAAE58CE0D64 /* LoggingService.swift in Sources */,
|
|
||||||
4274B6016F755946FBF2513E /* MessageRetentionService.swift in Sources */,
|
4274B6016F755946FBF2513E /* MessageRetentionService.swift in Sources */,
|
||||||
CEAE115C9C3EB3C4ED82F128 /* MessageRetryService.swift in Sources */,
|
CEAE115C9C3EB3C4ED82F128 /* MessageRetryService.swift in Sources */,
|
||||||
61C81ED5F679D5E973EE0C07 /* NotificationService.swift in Sources */,
|
61C81ED5F679D5E973EE0C07 /* NotificationService.swift in Sources */,
|
||||||
|
|||||||
@@ -662,7 +662,6 @@ class BluetoothMeshService: NSObject {
|
|||||||
ttl: 3 // Short TTL for leave notifications
|
ttl: 3 // Short TTL for leave notifications
|
||||||
)
|
)
|
||||||
|
|
||||||
bitchatLog("Sending room leave notification for \(room)", category: "room")
|
|
||||||
self.broadcastPacket(packet)
|
self.broadcastPacket(packet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -687,7 +686,6 @@ class BluetoothMeshService: NSObject {
|
|||||||
ttl: 5 // Allow wider propagation for room announcements
|
ttl: 5 // Allow wider propagation for room announcements
|
||||||
)
|
)
|
||||||
|
|
||||||
bitchatLog("Announcing room \(room) protection status: \(isProtected)", category: "room")
|
|
||||||
self.broadcastPacket(packet)
|
self.broadcastPacket(packet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -710,7 +708,6 @@ class BluetoothMeshService: NSObject {
|
|||||||
ttl: 5 // Allow wider propagation for room announcements
|
ttl: 5 // Allow wider propagation for room announcements
|
||||||
)
|
)
|
||||||
|
|
||||||
bitchatLog("Announcing room \(room) retention status: \(enabled)", category: "room")
|
|
||||||
self.broadcastPacket(packet)
|
self.broadcastPacket(packet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -727,12 +724,10 @@ class BluetoothMeshService: NSObject {
|
|||||||
|
|
||||||
// Debug logging
|
// Debug logging
|
||||||
let keyData = roomKey.withUnsafeBytes { Data($0) }
|
let keyData = roomKey.withUnsafeBytes { Data($0) }
|
||||||
bitchatLog("Encrypting message for room \(room) with key hash: \(keyData.prefix(8).hexEncodedString())", category: "crypto")
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let sealedBox = try AES.GCM.seal(contentData, using: roomKey)
|
let sealedBox = try AES.GCM.seal(contentData, using: roomKey)
|
||||||
let encryptedData = sealedBox.combined!
|
let encryptedData = sealedBox.combined!
|
||||||
bitchatLog("Successfully encrypted message, size: \(encryptedData.count) bytes", category: "crypto")
|
|
||||||
|
|
||||||
// Create message with encrypted content
|
// Create message with encrypted content
|
||||||
let message = BitchatMessage(
|
let message = BitchatMessage(
|
||||||
@@ -770,10 +765,8 @@ class BluetoothMeshService: NSObject {
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.broadcastPacket(packet)
|
self.broadcastPacket(packet)
|
||||||
bitchatLog("Sent encrypted message to room \(room)", category: "room")
|
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
bitchatLog("Failed to encrypt room message: \(error)", category: "crypto")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1253,7 +1246,6 @@ class BluetoothMeshService: NSObject {
|
|||||||
recipientNickname: message.recipientNickname,
|
recipientNickname: message.recipientNickname,
|
||||||
roomKey: roomKeyData
|
roomKey: roomKeyData
|
||||||
)
|
)
|
||||||
bitchatLog("No peers available, added message to retry queue", category: "mesh")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1370,15 +1362,12 @@ class BluetoothMeshService: NSObject {
|
|||||||
// Handle encrypted room messages
|
// Handle encrypted room messages
|
||||||
var finalContent = message.content
|
var finalContent = message.content
|
||||||
if message.isEncrypted, let room = message.room, let encryptedData = message.encryptedContent {
|
if message.isEncrypted, let room = message.room, let encryptedData = message.encryptedContent {
|
||||||
bitchatLog("Processing encrypted message in room \(room), encrypted data size: \(encryptedData.count)", category: "crypto")
|
|
||||||
// Try to decrypt the content
|
// Try to decrypt the content
|
||||||
if let decryptedContent = self.delegate?.decryptRoomMessage(encryptedData, room: room) {
|
if let decryptedContent = self.delegate?.decryptRoomMessage(encryptedData, room: room) {
|
||||||
finalContent = decryptedContent
|
finalContent = decryptedContent
|
||||||
bitchatLog("Successfully decrypted message in room \(room): \(decryptedContent.prefix(20))...", category: "crypto")
|
|
||||||
} else {
|
} else {
|
||||||
// Unable to decrypt - show placeholder
|
// Unable to decrypt - show placeholder
|
||||||
finalContent = "[Encrypted message - password required]"
|
finalContent = "[Encrypted message - password required]"
|
||||||
bitchatLog("Failed to decrypt message in room \(room) - will pass to ChatViewModel for re-attempt", category: "crypto")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1780,7 +1769,6 @@ class BluetoothMeshService: NSObject {
|
|||||||
if let room = String(data: packet.payload, encoding: .utf8),
|
if let room = String(data: packet.payload, encoding: .utf8),
|
||||||
room.hasPrefix("#") {
|
room.hasPrefix("#") {
|
||||||
// Room leave notification
|
// Room leave notification
|
||||||
bitchatLog("Received room leave notification from \(senderID) for room \(room)", category: "room")
|
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.delegate?.didReceiveRoomLeave(room, from: senderID)
|
self.delegate?.didReceiveRoomLeave(room, from: senderID)
|
||||||
@@ -1844,7 +1832,6 @@ class BluetoothMeshService: NSObject {
|
|||||||
let creatorID = components[2]
|
let creatorID = components[2]
|
||||||
let keyCommitment = components.count >= 4 ? components[3] : nil
|
let keyCommitment = components.count >= 4 ? components[3] : nil
|
||||||
|
|
||||||
bitchatLog("Received room announcement: \(room) is \(isProtected ? "protected" : "public") by \(creatorID)" + (keyCommitment != nil ? " with commitment" : ""), category: "room")
|
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.delegate?.didReceivePasswordProtectedRoomAnnouncement(room, isProtected: isProtected, creatorID: creatorID, keyCommitment: keyCommitment)
|
self.delegate?.didReceivePasswordProtectedRoomAnnouncement(room, isProtected: isProtected, creatorID: creatorID, keyCommitment: keyCommitment)
|
||||||
@@ -1868,7 +1855,6 @@ class BluetoothMeshService: NSObject {
|
|||||||
let enabled = components[1] == "1"
|
let enabled = components[1] == "1"
|
||||||
let creatorID = components[2]
|
let creatorID = components[2]
|
||||||
|
|
||||||
bitchatLog("Received room retention announcement: \(room) retention \(enabled ? "enabled" : "disabled") by \(creatorID)", category: "room")
|
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.delegate?.didReceiveRoomRetentionAnnouncement(room, enabled: enabled, creatorID: creatorID)
|
self.delegate?.didReceiveRoomRetentionAnnouncement(room, enabled: enabled, creatorID: creatorID)
|
||||||
@@ -2701,4 +2687,4 @@ extension BluetoothMeshService: CBPeripheralManagerDelegate {
|
|||||||
private func updatePeerLastSeen(_ peerID: String) {
|
private func updatePeerLastSeen(_ peerID: String) {
|
||||||
peerLastSeenTimestamps[peerID] = Date()
|
peerLastSeenTimestamps[peerID] = Date()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
//
|
|
||||||
// LoggingService.swift
|
|
||||||
// bitchat
|
|
||||||
//
|
|
||||||
// This is free and unencumbered software released into the public domain.
|
|
||||||
// For more information, see <https://unlicense.org>
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import os
|
|
||||||
|
|
||||||
class LoggingService {
|
|
||||||
static let shared = LoggingService()
|
|
||||||
|
|
||||||
private let logger = Logger(subsystem: "com.bitchat", category: "general")
|
|
||||||
private let fileURL: URL
|
|
||||||
private let dateFormatter: DateFormatter
|
|
||||||
private let queue = DispatchQueue(label: "bitchat.logging", qos: .background)
|
|
||||||
|
|
||||||
private init() {
|
|
||||||
// Set up date formatter
|
|
||||||
dateFormatter = DateFormatter()
|
|
||||||
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
|
|
||||||
|
|
||||||
#if os(macOS)
|
|
||||||
// Only create log files on macOS
|
|
||||||
// Get documents directory
|
|
||||||
let documentsPath = FileManager.default.urls(for: .documentDirectory,
|
|
||||||
in: .userDomainMask).first!
|
|
||||||
|
|
||||||
// Create logs directory
|
|
||||||
let logsDirectory = documentsPath.appendingPathComponent("Logs")
|
|
||||||
try? FileManager.default.createDirectory(at: logsDirectory,
|
|
||||||
withIntermediateDirectories: true)
|
|
||||||
|
|
||||||
// Create log file with today's date
|
|
||||||
let dateString = DateFormatter.localizedString(from: Date(),
|
|
||||||
dateStyle: .short,
|
|
||||||
timeStyle: .none)
|
|
||||||
.replacingOccurrences(of: "/", with: "-")
|
|
||||||
fileURL = logsDirectory.appendingPathComponent("bitchat-\(dateString).log")
|
|
||||||
|
|
||||||
// Create file if it doesn't exist
|
|
||||||
if !FileManager.default.fileExists(atPath: fileURL.path) {
|
|
||||||
FileManager.default.createFile(atPath: fileURL.path, contents: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
log("=== BitChat Started ===")
|
|
||||||
log("Log file: \(fileURL.path)")
|
|
||||||
#else
|
|
||||||
// On iOS, just create a dummy URL since we won't write to disk
|
|
||||||
fileURL = URL(fileURLWithPath: "/dev/null")
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
func log(_ message: String, category: String = "general") {
|
|
||||||
let timestamp = dateFormatter.string(from: Date())
|
|
||||||
let logLine = "[\(timestamp)] [\(category)] \(message)\n"
|
|
||||||
|
|
||||||
// Log to console for debugging
|
|
||||||
print(logLine.trimmingCharacters(in: .newlines))
|
|
||||||
|
|
||||||
// Log to system logger
|
|
||||||
logger.log("\(message, privacy: .public)")
|
|
||||||
|
|
||||||
// Write to file asynchronously
|
|
||||||
queue.async { [weak self] in
|
|
||||||
guard let self = self else { return }
|
|
||||||
|
|
||||||
if let data = logLine.data(using: .utf8) {
|
|
||||||
do {
|
|
||||||
let fileHandle = try FileHandle(forWritingTo: self.fileURL)
|
|
||||||
fileHandle.seekToEndOfFile()
|
|
||||||
fileHandle.write(data)
|
|
||||||
fileHandle.closeFile()
|
|
||||||
} catch {
|
|
||||||
print("Failed to write to log file: \(error)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getLogFileURL() -> URL {
|
|
||||||
return fileURL
|
|
||||||
}
|
|
||||||
|
|
||||||
func clearLogs() {
|
|
||||||
queue.async { [weak self] in
|
|
||||||
guard let self = self else { return }
|
|
||||||
try? "".write(to: self.fileURL, atomically: true, encoding: .utf8)
|
|
||||||
self.log("=== Logs Cleared ===")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Global logging function for convenience
|
|
||||||
func bitchatLog(_ message: String, category: String = "general") {
|
|
||||||
LoggingService.shared.log(message, category: category)
|
|
||||||
}
|
|
||||||
@@ -135,7 +135,6 @@ class MessageRetentionService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
bitchatLog("Failed to load messages for room \(room): \(error)", category: "retention")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return messages.sorted { $0.timestamp < $1.timestamp }
|
return messages.sorted { $0.timestamp < $1.timestamp }
|
||||||
@@ -148,7 +147,6 @@ class MessageRetentionService {
|
|||||||
let sealedBox = try AES.GCM.seal(data, using: encryptionKey)
|
let sealedBox = try AES.GCM.seal(data, using: encryptionKey)
|
||||||
return sealedBox.combined
|
return sealedBox.combined
|
||||||
} catch {
|
} catch {
|
||||||
bitchatLog("Failed to encrypt message: \(error)", category: "retention")
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,7 +156,6 @@ class MessageRetentionService {
|
|||||||
let sealedBox = try AES.GCM.SealedBox(combined: data)
|
let sealedBox = try AES.GCM.SealedBox(combined: data)
|
||||||
return try AES.GCM.open(sealedBox, using: encryptionKey)
|
return try AES.GCM.open(sealedBox, using: encryptionKey)
|
||||||
} catch {
|
} catch {
|
||||||
bitchatLog("Failed to decrypt message: \(error)", category: "retention")
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,7 +176,6 @@ class MessageRetentionService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
bitchatLog("Failed to cleanup old messages: \(error)", category: "retention")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +188,6 @@ class MessageRetentionService {
|
|||||||
try? FileManager.default.removeItem(at: fileURL)
|
try? FileManager.default.removeItem(at: fileURL)
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
bitchatLog("Failed to delete messages for room \(room): \(error)", category: "retention")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,10 +198,9 @@ class MessageRetentionService {
|
|||||||
try? FileManager.default.removeItem(at: fileURL)
|
try? FileManager.default.removeItem(at: fileURL)
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
bitchatLog("Failed to delete all stored messages: \(error)", category: "retention")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear favorite rooms
|
// Clear favorite rooms
|
||||||
UserDefaults.standard.removeObject(forKey: favoriteRoomsKey)
|
UserDefaults.standard.removeObject(forKey: favoriteRoomsKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ class MessageRetryService {
|
|||||||
) {
|
) {
|
||||||
// Don't queue if we're at capacity
|
// Don't queue if we're at capacity
|
||||||
guard retryQueue.count < maxQueueSize else {
|
guard retryQueue.count < maxQueueSize else {
|
||||||
bitchatLog("Retry queue full, dropping message", category: "retry")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +76,6 @@ class MessageRetryService {
|
|||||||
)
|
)
|
||||||
|
|
||||||
retryQueue.append(retryMessage)
|
retryQueue.append(retryMessage)
|
||||||
bitchatLog("Added message to retry queue: \(content.prefix(20))...", category: "retry")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func processRetryQueue() {
|
private func processRetryQueue() {
|
||||||
@@ -100,7 +98,6 @@ class MessageRetryService {
|
|||||||
for message in messagesToRetry {
|
for message in messagesToRetry {
|
||||||
// Check if we should still retry
|
// Check if we should still retry
|
||||||
if message.retryCount >= message.maxRetries {
|
if message.retryCount >= message.maxRetries {
|
||||||
bitchatLog("Max retries reached for message: \(message.content.prefix(20))...", category: "retry")
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +115,6 @@ class MessageRetryService {
|
|||||||
to: recipientID,
|
to: recipientID,
|
||||||
recipientNickname: message.recipientNickname ?? "unknown"
|
recipientNickname: message.recipientNickname ?? "unknown"
|
||||||
)
|
)
|
||||||
bitchatLog("Retried private message to \(recipientID)", category: "retry")
|
|
||||||
} else {
|
} else {
|
||||||
// Recipient not connected, keep in queue with updated retry time
|
// Recipient not connected, keep in queue with updated retry time
|
||||||
var updatedMessage = message
|
var updatedMessage = message
|
||||||
@@ -147,7 +143,6 @@ class MessageRetryService {
|
|||||||
room: room,
|
room: room,
|
||||||
roomKey: roomKey
|
roomKey: roomKey
|
||||||
)
|
)
|
||||||
bitchatLog("Retried encrypted room message to \(room)", category: "retry")
|
|
||||||
} else {
|
} else {
|
||||||
// No peers connected, keep in queue
|
// No peers connected, keep in queue
|
||||||
var updatedMessage = message
|
var updatedMessage = message
|
||||||
@@ -173,7 +168,6 @@ class MessageRetryService {
|
|||||||
mentions: message.mentions ?? [],
|
mentions: message.mentions ?? [],
|
||||||
room: message.room
|
room: message.room
|
||||||
)
|
)
|
||||||
bitchatLog("Retried regular message", category: "retry")
|
|
||||||
} else {
|
} else {
|
||||||
// No peers connected, keep in queue
|
// No peers connected, keep in queue
|
||||||
var updatedMessage = message
|
var updatedMessage = message
|
||||||
@@ -197,10 +191,9 @@ class MessageRetryService {
|
|||||||
|
|
||||||
func clearRetryQueue() {
|
func clearRetryQueue() {
|
||||||
retryQueue.removeAll()
|
retryQueue.removeAll()
|
||||||
bitchatLog("Cleared retry queue", category: "retry")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRetryQueueCount() -> Int {
|
func getRetryQueueCount() -> Int {
|
||||||
return retryQueue.count
|
return retryQueue.count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,8 +78,6 @@ class ChatViewModel: ObservableObject {
|
|||||||
meshService.delegate = self
|
meshService.delegate = self
|
||||||
|
|
||||||
// Log startup info
|
// Log startup info
|
||||||
bitchatLog("ChatViewModel initialized", category: "startup")
|
|
||||||
bitchatLog("Nickname: \(nickname)", category: "startup")
|
|
||||||
|
|
||||||
// Start mesh service immediately
|
// Start mesh service immediately
|
||||||
meshService.startServices()
|
meshService.startServices()
|
||||||
@@ -136,7 +134,6 @@ class ChatViewModel: ObservableObject {
|
|||||||
let savedMessages = MessageRetentionService.shared.loadMessagesForRoom(room)
|
let savedMessages = MessageRetentionService.shared.loadMessagesForRoom(room)
|
||||||
if !savedMessages.isEmpty {
|
if !savedMessages.isEmpty {
|
||||||
roomMessages[room] = savedMessages
|
roomMessages[room] = savedMessages
|
||||||
bitchatLog("Loaded \(savedMessages.count) saved messages for room \(room) on startup", category: "retention")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,7 +191,6 @@ class ChatViewModel: ObservableObject {
|
|||||||
// Ensure room starts with #
|
// Ensure room starts with #
|
||||||
let roomTag = room.hasPrefix("#") ? room : "#\(room)"
|
let roomTag = room.hasPrefix("#") ? room : "#\(room)"
|
||||||
|
|
||||||
bitchatLog("joinRoom called for \(roomTag), password provided: \(password != nil), is protected: \(passwordProtectedRooms.contains(roomTag)), has key: \(roomKeys[roomTag] != nil)", category: "room")
|
|
||||||
|
|
||||||
// Check if room is already joined and we can access it
|
// Check if room is already joined and we can access it
|
||||||
if joinedRooms.contains(roomTag) {
|
if joinedRooms.contains(roomTag) {
|
||||||
@@ -202,7 +198,6 @@ class ChatViewModel: ObservableObject {
|
|||||||
if passwordProtectedRooms.contains(roomTag) && roomKeys[roomTag] == nil {
|
if passwordProtectedRooms.contains(roomTag) && roomKeys[roomTag] == nil {
|
||||||
if let password = password {
|
if let password = password {
|
||||||
// User provided password for already-joined room - verify it
|
// User provided password for already-joined room - verify it
|
||||||
bitchatLog("Verifying password for already-joined room \(roomTag)", category: "room")
|
|
||||||
|
|
||||||
// Derive key and try to verify
|
// Derive key and try to verify
|
||||||
let key = deriveRoomKey(from: password, roomName: roomTag)
|
let key = deriveRoomKey(from: password, roomName: roomTag)
|
||||||
@@ -211,10 +206,8 @@ class ChatViewModel: ObservableObject {
|
|||||||
if let expectedCommitment = roomKeyCommitments[roomTag] {
|
if let expectedCommitment = roomKeyCommitments[roomTag] {
|
||||||
let actualCommitment = computeKeyCommitment(for: key)
|
let actualCommitment = computeKeyCommitment(for: key)
|
||||||
if actualCommitment != expectedCommitment {
|
if actualCommitment != expectedCommitment {
|
||||||
bitchatLog("Password verification failed - key commitment mismatch for already-joined room \(roomTag)", category: "room")
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
bitchatLog("Password verified via key commitment for already-joined room \(roomTag)", category: "room")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we have messages to verify against
|
// Check if we have messages to verify against
|
||||||
@@ -224,10 +217,8 @@ class ChatViewModel: ObservableObject {
|
|||||||
let encryptedData = encryptedMsg.encryptedContent {
|
let encryptedData = encryptedMsg.encryptedContent {
|
||||||
let testDecrypted = decryptRoomMessage(encryptedData, room: roomTag, testKey: key)
|
let testDecrypted = decryptRoomMessage(encryptedData, room: roomTag, testKey: key)
|
||||||
if testDecrypted == nil {
|
if testDecrypted == nil {
|
||||||
bitchatLog("Password verification failed for already-joined room", category: "room")
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
bitchatLog("Password verified for already-joined room", category: "room")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +233,6 @@ class ChatViewModel: ObservableObject {
|
|||||||
// Need password to access
|
// Need password to access
|
||||||
passwordPromptRoom = roomTag
|
passwordPromptRoom = roomTag
|
||||||
showPasswordPrompt = true
|
showPasswordPrompt = true
|
||||||
bitchatLog("Room \(roomTag) already joined but needs password, showing prompt", category: "room")
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -255,7 +245,6 @@ class ChatViewModel: ObservableObject {
|
|||||||
if passwordProtectedRooms.contains(roomTag) && roomKeys[roomTag] == nil {
|
if passwordProtectedRooms.contains(roomTag) && roomKeys[roomTag] == nil {
|
||||||
// Allow room creator to bypass password check
|
// Allow room creator to bypass password check
|
||||||
if roomCreators[roomTag] == meshService.myPeerID {
|
if roomCreators[roomTag] == meshService.myPeerID {
|
||||||
bitchatLog("Room creator bypassing password check for room \(roomTag)", category: "room")
|
|
||||||
// Room creator should already have the key set when they created the password
|
// Room creator should already have the key set when they created the password
|
||||||
// This is a failsafe - just proceed without password
|
// This is a failsafe - just proceed without password
|
||||||
} else if let password = password {
|
} else if let password = password {
|
||||||
@@ -266,11 +255,8 @@ class ChatViewModel: ObservableObject {
|
|||||||
if let expectedCommitment = roomKeyCommitments[roomTag] {
|
if let expectedCommitment = roomKeyCommitments[roomTag] {
|
||||||
let actualCommitment = computeKeyCommitment(for: key)
|
let actualCommitment = computeKeyCommitment(for: key)
|
||||||
if actualCommitment != expectedCommitment {
|
if actualCommitment != expectedCommitment {
|
||||||
bitchatLog("Password verification failed - key commitment mismatch for room \(roomTag)", category: "room")
|
|
||||||
bitchatLog("Expected: \(expectedCommitment), Got: \(actualCommitment)", category: "room")
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
bitchatLog("Password verified via key commitment for room \(roomTag)", category: "room")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to verify password if there are existing encrypted messages
|
// Try to verify password if there are existing encrypted messages
|
||||||
@@ -280,24 +266,19 @@ class ChatViewModel: ObservableObject {
|
|||||||
if let roomMsgs = roomMessages[roomTag], !roomMsgs.isEmpty {
|
if let roomMsgs = roomMessages[roomTag], !roomMsgs.isEmpty {
|
||||||
// Look for encrypted messages to verify against
|
// Look for encrypted messages to verify against
|
||||||
let encryptedMessages = roomMsgs.filter { $0.isEncrypted && $0.encryptedContent != nil }
|
let encryptedMessages = roomMsgs.filter { $0.isEncrypted && $0.encryptedContent != nil }
|
||||||
bitchatLog("Found \(encryptedMessages.count) encrypted messages in room \(roomTag) to verify against", category: "room")
|
|
||||||
|
|
||||||
if let encryptedMsg = encryptedMessages.first,
|
if let encryptedMsg = encryptedMessages.first,
|
||||||
let encryptedData = encryptedMsg.encryptedContent {
|
let encryptedData = encryptedMsg.encryptedContent {
|
||||||
// Test decryption with the derived key
|
// Test decryption with the derived key
|
||||||
bitchatLog("Testing password by decrypting message from \(encryptedMsg.sender)", category: "room")
|
|
||||||
let testDecrypted = decryptRoomMessage(encryptedData, room: roomTag, testKey: key)
|
let testDecrypted = decryptRoomMessage(encryptedData, room: roomTag, testKey: key)
|
||||||
if testDecrypted == nil {
|
if testDecrypted == nil {
|
||||||
// Password is wrong, can't decrypt
|
// Password is wrong, can't decrypt
|
||||||
bitchatLog("WRONG PASSWORD - decryption failed for room \(roomTag)", category: "room")
|
|
||||||
shouldProceed = false
|
shouldProceed = false
|
||||||
} else {
|
} else {
|
||||||
bitchatLog("Password VERIFIED - successfully decrypted message: \(testDecrypted?.prefix(20) ?? "")", category: "room")
|
|
||||||
passwordVerified = true
|
passwordVerified = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// No encrypted messages yet - accept tentatively
|
// No encrypted messages yet - accept tentatively
|
||||||
bitchatLog("No encrypted messages to verify password for room \(roomTag) - accepting tentatively", category: "room")
|
|
||||||
|
|
||||||
// Add warning message
|
// Add warning message
|
||||||
let warningMsg = BitchatMessage(
|
let warningMsg = BitchatMessage(
|
||||||
@@ -310,7 +291,6 @@ class ChatViewModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Empty room - accept tentatively
|
// Empty room - accept tentatively
|
||||||
bitchatLog("Room \(roomTag) is empty - accepting password tentatively", category: "room")
|
|
||||||
|
|
||||||
// Add info message
|
// Add info message
|
||||||
let infoMsg = BitchatMessage(
|
let infoMsg = BitchatMessage(
|
||||||
@@ -334,21 +314,17 @@ class ChatViewModel: ObservableObject {
|
|||||||
_ = KeychainManager.shared.saveRoomPassword(password, for: roomTag)
|
_ = KeychainManager.shared.saveRoomPassword(password, for: roomTag)
|
||||||
|
|
||||||
if passwordVerified {
|
if passwordVerified {
|
||||||
bitchatLog("Password stored for room \(roomTag) - verified", category: "room")
|
|
||||||
} else {
|
} else {
|
||||||
bitchatLog("Password stored for room \(roomTag) - tentative, awaiting verification", category: "room")
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Show password prompt and return early - don't join the room yet
|
// Show password prompt and return early - don't join the room yet
|
||||||
passwordPromptRoom = roomTag
|
passwordPromptRoom = roomTag
|
||||||
showPasswordPrompt = true
|
showPasswordPrompt = true
|
||||||
bitchatLog("Room \(roomTag) is password protected, showing prompt", category: "room")
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point, room is either not password protected or we don't know yet
|
// At this point, room is either not password protected or we don't know yet
|
||||||
bitchatLog("Joining room \(roomTag) - not known to be password protected or have key", category: "room")
|
|
||||||
|
|
||||||
joinedRooms.insert(roomTag)
|
joinedRooms.insert(roomTag)
|
||||||
saveJoinedRooms()
|
saveJoinedRooms()
|
||||||
@@ -358,7 +334,6 @@ class ChatViewModel: ObservableObject {
|
|||||||
if roomCreators[roomTag] == nil && !passwordProtectedRooms.contains(roomTag) {
|
if roomCreators[roomTag] == nil && !passwordProtectedRooms.contains(roomTag) {
|
||||||
roomCreators[roomTag] = meshService.myPeerID
|
roomCreators[roomTag] = meshService.myPeerID
|
||||||
saveRoomData()
|
saveRoomData()
|
||||||
bitchatLog("Set room creator for new room \(roomTag) to \(meshService.myPeerID)", category: "room")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add ourselves as a member
|
// Add ourselves as a member
|
||||||
@@ -393,7 +368,6 @@ class ChatViewModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
// Sort by timestamp
|
// Sort by timestamp
|
||||||
roomMessages[roomTag]?.sort { $0.timestamp < $1.timestamp }
|
roomMessages[roomTag]?.sort { $0.timestamp < $1.timestamp }
|
||||||
bitchatLog("Loaded \(savedMessages.count) saved messages for favorite room \(roomTag)", category: "retention")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,13 +406,11 @@ class ChatViewModel: ObservableObject {
|
|||||||
|
|
||||||
// Check if room already has a creator
|
// Check if room already has a creator
|
||||||
if let existingCreator = roomCreators[room], existingCreator != meshService.myPeerID {
|
if let existingCreator = roomCreators[room], existingCreator != meshService.myPeerID {
|
||||||
bitchatLog("Cannot set password - room \(room) already has creator: \(existingCreator)", category: "room")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If room is already password protected by someone else, we can't claim it
|
// If room is already password protected by someone else, we can't claim it
|
||||||
if passwordProtectedRooms.contains(room) && roomCreators[room] != meshService.myPeerID {
|
if passwordProtectedRooms.contains(room) && roomCreators[room] != meshService.myPeerID {
|
||||||
bitchatLog("Cannot set password - room \(room) is already password protected by another user", category: "room")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,13 +454,11 @@ class ChatViewModel: ObservableObject {
|
|||||||
let initMessage = "🔐 Room \(room) initialized | Protected room created by \(nickname) | Metadata: \(metadataStr)"
|
let initMessage = "🔐 Room \(room) initialized | Protected room created by \(nickname) | Metadata: \(metadataStr)"
|
||||||
meshService.sendEncryptedRoomMessage(initMessage, mentions: [], room: room, roomKey: key)
|
meshService.sendEncryptedRoomMessage(initMessage, mentions: [], room: room, roomKey: key)
|
||||||
|
|
||||||
bitchatLog("Set password for room \(room) and sent init message", category: "room")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeRoomPassword(for room: String) {
|
func removeRoomPassword(for room: String) {
|
||||||
// Only room creator can remove password
|
// Only room creator can remove password
|
||||||
guard roomCreators[room] == meshService.myPeerID else {
|
guard roomCreators[room] == meshService.myPeerID else {
|
||||||
bitchatLog("Only room creator can remove password", category: "room")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,7 +475,6 @@ class ChatViewModel: ObservableObject {
|
|||||||
// Announce that this room is no longer password protected
|
// Announce that this room is no longer password protected
|
||||||
meshService.announcePasswordProtectedRoom(room, isProtected: false, creatorID: meshService.myPeerID)
|
meshService.announcePasswordProtectedRoom(room, isProtected: false, creatorID: meshService.myPeerID)
|
||||||
|
|
||||||
bitchatLog("Removed password for room \(room)", category: "room")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transfer room ownership to another user
|
// Transfer room ownership to another user
|
||||||
@@ -576,7 +545,6 @@ class ChatViewModel: ObservableObject {
|
|||||||
meshService.sendMessage(transferMsg.content, mentions: [targetNick])
|
meshService.sendMessage(transferMsg.content, mentions: [targetNick])
|
||||||
}
|
}
|
||||||
|
|
||||||
bitchatLog("Transferred ownership of room \(currentRoom) to \(targetPeerID)", category: "room")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change password for current room
|
// Change password for current room
|
||||||
@@ -667,7 +635,6 @@ class ChatViewModel: ObservableObject {
|
|||||||
)
|
)
|
||||||
messages.append(successMsg)
|
messages.append(successMsg)
|
||||||
|
|
||||||
bitchatLog("Changed password for room \(currentRoom)", category: "room")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute SHA256 hash of the derived key for public verification
|
// Compute SHA256 hash of the derived key for public verification
|
||||||
@@ -683,7 +650,6 @@ class ChatViewModel: ObservableObject {
|
|||||||
let keyData = pbkdf2(password: password, salt: salt, iterations: 100000, keyLength: 32)
|
let keyData = pbkdf2(password: password, salt: salt, iterations: 100000, keyLength: 32)
|
||||||
|
|
||||||
// Debug logging
|
// Debug logging
|
||||||
bitchatLog("Derived key for room \(roomName) with password '\(password)' - key hash: \(keyData.prefix(8).hexEncodedString())", category: "crypto")
|
|
||||||
|
|
||||||
return SymmetricKey(data: keyData)
|
return SymmetricKey(data: keyData)
|
||||||
}
|
}
|
||||||
@@ -848,7 +814,6 @@ class ChatViewModel: ObservableObject {
|
|||||||
roomMembers[room] = Set()
|
roomMembers[room] = Set()
|
||||||
}
|
}
|
||||||
roomMembers[room]?.insert(meshService.myPeerID)
|
roomMembers[room]?.insert(meshService.myPeerID)
|
||||||
bitchatLog("Added self \(meshService.myPeerID) to room \(room), total members: \(roomMembers[room]?.count ?? 0)", category: "room")
|
|
||||||
} else {
|
} else {
|
||||||
// Add to main messages
|
// Add to main messages
|
||||||
messages.append(message)
|
messages.append(message)
|
||||||
@@ -990,7 +955,6 @@ class ChatViewModel: ObservableObject {
|
|||||||
// Force UI update
|
// Force UI update
|
||||||
objectWillChange.send()
|
objectWillChange.send()
|
||||||
|
|
||||||
bitchatLog("PANIC: All data cleared for safety", category: "security")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1274,7 +1238,6 @@ extension ChatViewModel: BitchatDelegate {
|
|||||||
// Remove peer from room members
|
// Remove peer from room members
|
||||||
if roomMembers[room] != nil {
|
if roomMembers[room] != nil {
|
||||||
roomMembers[room]?.remove(peerID)
|
roomMembers[room]?.remove(peerID)
|
||||||
bitchatLog("Removed peer \(peerID) from room \(room) members", category: "room")
|
|
||||||
|
|
||||||
// Force UI update
|
// Force UI update
|
||||||
objectWillChange.send()
|
objectWillChange.send()
|
||||||
@@ -1293,12 +1256,10 @@ extension ChatViewModel: BitchatDelegate {
|
|||||||
// Store the key commitment if provided
|
// Store the key commitment if provided
|
||||||
if let commitment = keyCommitment {
|
if let commitment = keyCommitment {
|
||||||
roomKeyCommitments[room] = commitment
|
roomKeyCommitments[room] = commitment
|
||||||
bitchatLog("Stored key commitment for room \(room): \(commitment)", category: "room")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we just learned this room is protected and we're in it without a key, prompt for password
|
// If we just learned this room is protected and we're in it without a key, prompt for password
|
||||||
if !wasAlreadyProtected && joinedRooms.contains(room) && roomKeys[room] == nil {
|
if !wasAlreadyProtected && joinedRooms.contains(room) && roomKeys[room] == nil {
|
||||||
bitchatLog("Just learned room \(room) is password protected, need to prompt for password", category: "room")
|
|
||||||
|
|
||||||
// Add system message
|
// Add system message
|
||||||
let systemMessage = BitchatMessage(
|
let systemMessage = BitchatMessage(
|
||||||
@@ -1326,41 +1287,34 @@ extension ChatViewModel: BitchatDelegate {
|
|||||||
// Save updated room data
|
// Save updated room data
|
||||||
saveRoomData()
|
saveRoomData()
|
||||||
|
|
||||||
bitchatLog("Room \(room) is now \(isProtected ? "password protected" : "public")", category: "room")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func decryptRoomMessage(_ encryptedContent: Data, room: String, testKey: SymmetricKey? = nil) -> String? {
|
func decryptRoomMessage(_ encryptedContent: Data, room: String, testKey: SymmetricKey? = nil) -> String? {
|
||||||
let key = testKey ?? roomKeys[room]
|
let key = testKey ?? roomKeys[room]
|
||||||
guard let key = key else {
|
guard let key = key else {
|
||||||
bitchatLog("No key available for encrypted room \(room)", category: "room")
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug logging
|
// Debug logging
|
||||||
let keyData = key.withUnsafeBytes { Data($0) }
|
let keyData = key.withUnsafeBytes { Data($0) }
|
||||||
bitchatLog("Attempting to decrypt with key hash: \(keyData.prefix(8).hexEncodedString()) for room \(room)", category: "crypto")
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let sealedBox = try AES.GCM.SealedBox(combined: encryptedContent)
|
let sealedBox = try AES.GCM.SealedBox(combined: encryptedContent)
|
||||||
let decryptedData = try AES.GCM.open(sealedBox, using: key)
|
let decryptedData = try AES.GCM.open(sealedBox, using: key)
|
||||||
let decryptedString = String(data: decryptedData, encoding: .utf8)
|
let decryptedString = String(data: decryptedData, encoding: .utf8)
|
||||||
bitchatLog("Successfully decrypted message: \(decryptedString?.prefix(20) ?? "nil")", category: "crypto")
|
|
||||||
return decryptedString
|
return decryptedString
|
||||||
} catch {
|
} catch {
|
||||||
bitchatLog("Failed to decrypt room message: \(error)", category: "crypto")
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func didReceiveRoomRetentionAnnouncement(_ room: String, enabled: Bool, creatorID: String?) {
|
func didReceiveRoomRetentionAnnouncement(_ room: String, enabled: Bool, creatorID: String?) {
|
||||||
bitchatLog("Received retention announcement for room \(room): \(enabled ? "enabled" : "disabled") by \(creatorID ?? "unknown")", category: "room")
|
|
||||||
|
|
||||||
// Only process if we're a member of this room
|
// Only process if we're a member of this room
|
||||||
guard joinedRooms.contains(room) else { return }
|
guard joinedRooms.contains(room) else { return }
|
||||||
|
|
||||||
// Verify the announcement is from the room owner
|
// Verify the announcement is from the room owner
|
||||||
if let creatorID = creatorID, roomCreators[room] != creatorID {
|
if let creatorID = creatorID, roomCreators[room] != creatorID {
|
||||||
bitchatLog("Ignoring retention announcement from non-owner \(creatorID) for room \(room)", category: "room")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1658,15 +1612,12 @@ extension ChatViewModel: BitchatDelegate {
|
|||||||
if let room = currentRoom {
|
if let room = currentRoom {
|
||||||
// Clear room messages
|
// Clear room messages
|
||||||
roomMessages[room]?.removeAll()
|
roomMessages[room]?.removeAll()
|
||||||
bitchatLog("cleared messages in room \(room)", category: "chat")
|
|
||||||
} else if let peerID = selectedPrivateChatPeer {
|
} else if let peerID = selectedPrivateChatPeer {
|
||||||
// Clear private chat
|
// Clear private chat
|
||||||
privateChats[peerID]?.removeAll()
|
privateChats[peerID]?.removeAll()
|
||||||
bitchatLog("cleared private chat with \(peerID)", category: "chat")
|
|
||||||
} else {
|
} else {
|
||||||
// Clear main messages
|
// Clear main messages
|
||||||
messages.removeAll()
|
messages.removeAll()
|
||||||
bitchatLog("cleared main chat", category: "chat")
|
|
||||||
}
|
}
|
||||||
case "/save":
|
case "/save":
|
||||||
// Toggle retention for current room (owner only)
|
// Toggle retention for current room (owner only)
|
||||||
@@ -1766,7 +1717,6 @@ extension ChatViewModel: BitchatDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func didReceiveMessage(_ message: BitchatMessage) {
|
func didReceiveMessage(_ message: BitchatMessage) {
|
||||||
bitchatLog("Received message from \(message.sender), room: \(message.room ?? "nil"), senderPeerID: \(message.senderPeerID ?? "nil")", category: "message")
|
|
||||||
|
|
||||||
if message.isPrivate {
|
if message.isPrivate {
|
||||||
// Handle private message
|
// Handle private message
|
||||||
@@ -1812,7 +1762,6 @@ extension ChatViewModel: BitchatDelegate {
|
|||||||
if wasNewlyDiscovered {
|
if wasNewlyDiscovered {
|
||||||
passwordProtectedRooms.insert(room)
|
passwordProtectedRooms.insert(room)
|
||||||
saveRoomData()
|
saveRoomData()
|
||||||
bitchatLog("Discovered room \(room) is password protected from encrypted message", category: "room")
|
|
||||||
|
|
||||||
// Add a system message to indicate the room is password protected (only once)
|
// Add a system message to indicate the room is password protected (only once)
|
||||||
let systemMessage = BitchatMessage(
|
let systemMessage = BitchatMessage(
|
||||||
@@ -1831,11 +1780,9 @@ extension ChatViewModel: BitchatDelegate {
|
|||||||
if currentRoom == room {
|
if currentRoom == room {
|
||||||
passwordPromptRoom = room
|
passwordPromptRoom = room
|
||||||
showPasswordPrompt = true
|
showPasswordPrompt = true
|
||||||
bitchatLog("Showing password prompt for encrypted message in current room \(room)", category: "room")
|
|
||||||
}
|
}
|
||||||
} else if message.isEncrypted && roomKeys[room] != nil && message.content == "[Encrypted message - password required]" {
|
} else if message.isEncrypted && roomKeys[room] != nil && message.content == "[Encrypted message - password required]" {
|
||||||
// We have a key but the message shows as encrypted - try to decrypt it again
|
// We have a key but the message shows as encrypted - try to decrypt it again
|
||||||
bitchatLog("Received encrypted message placeholder but we have a key - attempting re-decryption", category: "room")
|
|
||||||
|
|
||||||
// Check if this is the first encrypted message in the room (password verification opportunity)
|
// Check if this is the first encrypted message in the room (password verification opportunity)
|
||||||
let isFirstEncryptedMessage = roomMessages[room]?.filter { $0.isEncrypted }.isEmpty ?? true
|
let isFirstEncryptedMessage = roomMessages[room]?.filter { $0.isEncrypted }.isEmpty ?? true
|
||||||
@@ -1843,10 +1790,8 @@ extension ChatViewModel: BitchatDelegate {
|
|||||||
if let encryptedData = message.encryptedContent {
|
if let encryptedData = message.encryptedContent {
|
||||||
if let decryptedContent = decryptRoomMessage(encryptedData, room: room) {
|
if let decryptedContent = decryptRoomMessage(encryptedData, room: room) {
|
||||||
// Successfully decrypted - update the message content
|
// Successfully decrypted - update the message content
|
||||||
bitchatLog("Re-decryption successful! Content: \(decryptedContent.prefix(20))", category: "room")
|
|
||||||
|
|
||||||
if isFirstEncryptedMessage {
|
if isFirstEncryptedMessage {
|
||||||
bitchatLog("First encrypted message successfully decrypted - password VERIFIED for room \(room)", category: "room")
|
|
||||||
|
|
||||||
// Add success message
|
// Add success message
|
||||||
let verifiedMsg = BitchatMessage(
|
let verifiedMsg = BitchatMessage(
|
||||||
@@ -1878,7 +1823,6 @@ extension ChatViewModel: BitchatDelegate {
|
|||||||
messageToAdd = decryptedMessage
|
messageToAdd = decryptedMessage
|
||||||
} else {
|
} else {
|
||||||
// Decryption really failed - wrong password
|
// Decryption really failed - wrong password
|
||||||
bitchatLog("Re-decryption failed - password is actually wrong", category: "room")
|
|
||||||
|
|
||||||
// Clear the wrong password
|
// Clear the wrong password
|
||||||
roomKeys.removeValue(forKey: room)
|
roomKeys.removeValue(forKey: room)
|
||||||
@@ -1886,7 +1830,6 @@ extension ChatViewModel: BitchatDelegate {
|
|||||||
|
|
||||||
// If this was the first encrypted message, we need to kick the user out
|
// If this was the first encrypted message, we need to kick the user out
|
||||||
if isFirstEncryptedMessage {
|
if isFirstEncryptedMessage {
|
||||||
bitchatLog("First encrypted message failed to decrypt - WRONG PASSWORD, removing user from room", category: "room")
|
|
||||||
|
|
||||||
// Leave the room
|
// Leave the room
|
||||||
joinedRooms.remove(room)
|
joinedRooms.remove(room)
|
||||||
@@ -1951,9 +1894,7 @@ extension ChatViewModel: BitchatDelegate {
|
|||||||
}
|
}
|
||||||
if let senderPeerID = message.senderPeerID {
|
if let senderPeerID = message.senderPeerID {
|
||||||
roomMembers[room]?.insert(senderPeerID)
|
roomMembers[room]?.insert(senderPeerID)
|
||||||
bitchatLog("Added member \(senderPeerID) to room \(room), total members: \(roomMembers[room]?.count ?? 0)", category: "room")
|
|
||||||
} else {
|
} else {
|
||||||
bitchatLog("No senderPeerID for message in room \(room)", category: "room")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update unread count if not currently viewing this room
|
// Update unread count if not currently viewing this room
|
||||||
@@ -1962,7 +1903,6 @@ extension ChatViewModel: BitchatDelegate {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// We're not in this room, ignore the message
|
// We're not in this room, ignore the message
|
||||||
bitchatLog("Ignoring message for room \(room) - not joined", category: "room")
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Regular public message (main chat)
|
// Regular public message (main chat)
|
||||||
@@ -2094,4 +2034,4 @@ extension ChatViewModel: BitchatDelegate {
|
|||||||
return favoritePeers.contains(fingerprint)
|
return favoritePeers.contains(fingerprint)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -840,9 +840,6 @@ struct ContentView: View {
|
|||||||
if let currentRoom = viewModel.currentRoom,
|
if let currentRoom = viewModel.currentRoom,
|
||||||
let roomMemberIDs = viewModel.roomMembers[currentRoom] {
|
let roomMemberIDs = viewModel.roomMembers[currentRoom] {
|
||||||
// Show only peers who have sent messages to this room (including self)
|
// Show only peers who have sent messages to this room (including self)
|
||||||
bitchatLog("Room \(currentRoom) has members: \(roomMemberIDs)", category: "view")
|
|
||||||
bitchatLog("Connected peers: \(viewModel.connectedPeers)", category: "view")
|
|
||||||
bitchatLog("My peer ID: \(myPeerID)", category: "view")
|
|
||||||
|
|
||||||
// Start with room members who are also connected
|
// Start with room members who are also connected
|
||||||
var memberPeers = viewModel.connectedPeers.filter { roomMemberIDs.contains($0) }
|
var memberPeers = viewModel.connectedPeers.filter { roomMemberIDs.contains($0) }
|
||||||
@@ -852,7 +849,6 @@ struct ContentView: View {
|
|||||||
memberPeers.append(myPeerID)
|
memberPeers.append(myPeerID)
|
||||||
}
|
}
|
||||||
|
|
||||||
bitchatLog("Peers to show in room: \(memberPeers)", category: "view")
|
|
||||||
return memberPeers
|
return memberPeers
|
||||||
} else {
|
} else {
|
||||||
// Show all connected peers in main chat
|
// Show all connected peers in main chat
|
||||||
@@ -1064,4 +1060,4 @@ struct MessageContentView: View {
|
|||||||
|
|
||||||
return segments
|
return segments
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user