mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
287 lines
20 KiB
Swift
287 lines
20 KiB
Swift
import Foundation
|
|
import Postbox
|
|
|
|
private enum SecretChatOutgoingFileValue: Int32 {
|
|
case remote = 0
|
|
case uploadedRegular = 1
|
|
case uploadedLarge = 2
|
|
}
|
|
|
|
public enum SecretChatOutgoingFileReference: PostboxCoding {
|
|
case remote(id: Int64, accessHash: Int64)
|
|
case uploadedRegular(id: Int64, partCount: Int32, md5Digest: String, keyFingerprint: Int32)
|
|
case uploadedLarge(id: Int64, partCount: Int32, keyFingerprint: Int32)
|
|
|
|
public init(decoder: PostboxDecoder) {
|
|
switch decoder.decodeInt32ForKey("v", orElse: 0) {
|
|
case SecretChatOutgoingFileValue.remote.rawValue:
|
|
self = .remote(id: decoder.decodeInt64ForKey("i", orElse: 0), accessHash: decoder.decodeInt64ForKey("a", orElse: 0))
|
|
case SecretChatOutgoingFileValue.uploadedRegular.rawValue:
|
|
self = .uploadedRegular(id: decoder.decodeInt64ForKey("i", orElse: 0), partCount: decoder.decodeInt32ForKey("p", orElse: 0), md5Digest: decoder.decodeStringForKey("d", orElse: ""), keyFingerprint: decoder.decodeInt32ForKey("f", orElse: 0))
|
|
case SecretChatOutgoingFileValue.uploadedLarge.rawValue:
|
|
self = .uploadedLarge(id: decoder.decodeInt64ForKey("i", orElse: 0), partCount: decoder.decodeInt32ForKey("p", orElse: 0), keyFingerprint: decoder.decodeInt32ForKey("f", orElse: 0))
|
|
default:
|
|
assertionFailure()
|
|
self = .remote(id: 0, accessHash: 0)
|
|
}
|
|
}
|
|
|
|
public func encode(_ encoder: PostboxEncoder) {
|
|
switch self {
|
|
case let .remote(id, accessHash):
|
|
encoder.encodeInt32(SecretChatOutgoingFileValue.remote.rawValue, forKey: "v")
|
|
encoder.encodeInt64(id, forKey: "i")
|
|
encoder.encodeInt64(accessHash, forKey: "a")
|
|
case let .uploadedRegular(id, partCount, md5Digest, keyFingerprint):
|
|
encoder.encodeInt32(SecretChatOutgoingFileValue.uploadedRegular.rawValue, forKey: "v")
|
|
encoder.encodeInt64(id, forKey: "i")
|
|
encoder.encodeInt32(partCount, forKey: "p")
|
|
encoder.encodeString(md5Digest, forKey: "d")
|
|
encoder.encodeInt32(keyFingerprint, forKey: "f")
|
|
case let .uploadedLarge(id, partCount, keyFingerprint):
|
|
encoder.encodeInt32(SecretChatOutgoingFileValue.uploadedLarge.rawValue, forKey: "v")
|
|
encoder.encodeInt64(id, forKey: "i")
|
|
encoder.encodeInt32(partCount, forKey: "p")
|
|
encoder.encodeInt32(keyFingerprint, forKey: "f")
|
|
}
|
|
}
|
|
}
|
|
|
|
public struct SecretChatOutgoingFile: PostboxCoding {
|
|
public let reference: SecretChatOutgoingFileReference
|
|
public let size: Int32
|
|
public let key: SecretFileEncryptionKey
|
|
|
|
public init(reference: SecretChatOutgoingFileReference, size: Int32, key: SecretFileEncryptionKey) {
|
|
self.reference = reference
|
|
self.size = size
|
|
self.key = key
|
|
}
|
|
|
|
public init(decoder: PostboxDecoder) {
|
|
self.reference = decoder.decodeObjectForKey("r", decoder: { SecretChatOutgoingFileReference(decoder: $0) }) as! SecretChatOutgoingFileReference
|
|
self.size = decoder.decodeInt32ForKey("s", orElse: 0)
|
|
self.key = SecretFileEncryptionKey(aesKey: decoder.decodeBytesForKey("k")!.makeData(), aesIv: decoder.decodeBytesForKey("i")!.makeData())
|
|
}
|
|
|
|
public func encode(_ encoder: PostboxEncoder) {
|
|
encoder.encodeObject(self.reference, forKey: "r")
|
|
encoder.encodeInt32(self.size, forKey: "s")
|
|
encoder.encodeBytes(MemoryBuffer(data: self.key.aesKey), forKey: "k")
|
|
encoder.encodeBytes(MemoryBuffer(data: self.key.aesIv), forKey: "i")
|
|
}
|
|
}
|
|
|
|
public enum SecretChatSequenceBasedLayer: Int32 {
|
|
case layer46 = 46
|
|
case layer73 = 73
|
|
case layer101 = 101
|
|
|
|
public var secretChatLayer: SecretChatLayer {
|
|
switch self {
|
|
case .layer46:
|
|
return .layer46
|
|
case .layer73:
|
|
return .layer73
|
|
case .layer101:
|
|
return .layer101
|
|
}
|
|
}
|
|
}
|
|
|
|
private enum SecretChatOutgoingOperationValue: Int32 {
|
|
case initialHandshakeAccept = 0
|
|
case sendMessage = 1
|
|
case readMessagesContent = 2
|
|
case deleteMessages = 3
|
|
case screenshotMessages = 4
|
|
case clearHistory = 5
|
|
case resendOperations = 6
|
|
case reportLayerSupport = 7
|
|
case pfsRequestKey = 8
|
|
case pfsAcceptKey = 9
|
|
case pfsAbortSession = 10
|
|
case pfsCommitKey = 11
|
|
case noop = 12
|
|
case setMessageAutoremoveTimeout = 13
|
|
case terminate = 14
|
|
}
|
|
|
|
public enum SecretChatOutgoingOperationContents: PostboxCoding {
|
|
case initialHandshakeAccept(gA: MemoryBuffer, accessHash: Int64, b: MemoryBuffer)
|
|
case sendMessage(layer: SecretChatLayer, id: MessageId, file: SecretChatOutgoingFile?)
|
|
case readMessagesContent(layer: SecretChatLayer, actionGloballyUniqueId: Int64, globallyUniqueIds: [Int64])
|
|
case deleteMessages(layer: SecretChatLayer, actionGloballyUniqueId: Int64, globallyUniqueIds: [Int64])
|
|
case screenshotMessages(layer: SecretChatLayer, actionGloballyUniqueId: Int64, globallyUniqueIds: [Int64], messageId: MessageId)
|
|
case clearHistory(layer: SecretChatLayer, actionGloballyUniqueId: Int64)
|
|
case resendOperations(layer : SecretChatSequenceBasedLayer, actionGloballyUniqueId: Int64, fromSeqNo: Int32, toSeqNo: Int32)
|
|
case reportLayerSupport(layer: SecretChatLayer, actionGloballyUniqueId: Int64, layerSupport: Int32)
|
|
case pfsRequestKey(layer: SecretChatSequenceBasedLayer, actionGloballyUniqueId: Int64, rekeySessionId: Int64, a: MemoryBuffer)
|
|
case pfsAcceptKey(layer: SecretChatSequenceBasedLayer, actionGloballyUniqueId: Int64, rekeySessionId: Int64, gA: MemoryBuffer, b: MemoryBuffer)
|
|
case pfsAbortSession(layer: SecretChatSequenceBasedLayer, actionGloballyUniqueId: Int64, rekeySessionId: Int64)
|
|
case pfsCommitKey(layer: SecretChatSequenceBasedLayer, actionGloballyUniqueId: Int64, rekeySessionId: Int64, keyFingerprint: Int64)
|
|
case noop(layer: SecretChatSequenceBasedLayer, actionGloballyUniqueId: Int64)
|
|
case setMessageAutoremoveTimeout(layer: SecretChatLayer, actionGloballyUniqueId: Int64, timeout: Int32, messageId: MessageId)
|
|
case terminate(reportSpam: Bool, requestRemoteHistoryRemoval: Bool)
|
|
|
|
public init(decoder: PostboxDecoder) {
|
|
switch decoder.decodeInt32ForKey("r", orElse: 0) {
|
|
case SecretChatOutgoingOperationValue.initialHandshakeAccept.rawValue:
|
|
self = .initialHandshakeAccept(gA: decoder.decodeBytesForKey("g")!, accessHash: decoder.decodeInt64ForKey("h", orElse: 0), b: decoder.decodeBytesForKey("b")!)
|
|
case SecretChatOutgoingOperationValue.sendMessage.rawValue:
|
|
self = .sendMessage(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, id: MessageId(peerId: PeerId(decoder.decodeInt64ForKey("i.p", orElse: 0)), namespace: decoder.decodeInt32ForKey("i.n", orElse: 0), id: decoder.decodeInt32ForKey("i.i", orElse: 0)), file: decoder.decodeObjectForKey("f", decoder: { SecretChatOutgoingFile(decoder: $0) }) as? SecretChatOutgoingFile)
|
|
case SecretChatOutgoingOperationValue.readMessagesContent.rawValue:
|
|
self = .readMessagesContent(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), globallyUniqueIds: decoder.decodeInt64ArrayForKey("u"))
|
|
case SecretChatOutgoingOperationValue.deleteMessages.rawValue:
|
|
self = .deleteMessages(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), globallyUniqueIds: decoder.decodeInt64ArrayForKey("u"))
|
|
case SecretChatOutgoingOperationValue.screenshotMessages.rawValue:
|
|
self = .screenshotMessages(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), globallyUniqueIds: decoder.decodeInt64ArrayForKey("u"), messageId: MessageId(peerId: PeerId(decoder.decodeInt64ForKey("m.p", orElse: 0)), namespace: decoder.decodeInt32ForKey("m.n", orElse: 0), id: decoder.decodeInt32ForKey("m.i", orElse: 0)))
|
|
case SecretChatOutgoingOperationValue.clearHistory.rawValue:
|
|
self = .clearHistory(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0))
|
|
case SecretChatOutgoingOperationValue.resendOperations.rawValue:
|
|
self = .resendOperations(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), fromSeqNo: decoder.decodeInt32ForKey("f", orElse: 0), toSeqNo: decoder.decodeInt32ForKey("t", orElse: 0))
|
|
case SecretChatOutgoingOperationValue.reportLayerSupport.rawValue:
|
|
self = .reportLayerSupport(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), layerSupport: decoder.decodeInt32ForKey("l", orElse: 0))
|
|
case SecretChatOutgoingOperationValue.pfsRequestKey.rawValue:
|
|
self = .pfsRequestKey(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), rekeySessionId: decoder.decodeInt64ForKey("s", orElse: 0), a: decoder.decodeBytesForKey("a")!)
|
|
case SecretChatOutgoingOperationValue.pfsAcceptKey.rawValue:
|
|
self = .pfsAcceptKey(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), rekeySessionId: decoder.decodeInt64ForKey("s", orElse: 0), gA: decoder.decodeBytesForKey("g")!, b: decoder.decodeBytesForKey("b")!)
|
|
case SecretChatOutgoingOperationValue.pfsAbortSession.rawValue:
|
|
self = .pfsAbortSession(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), rekeySessionId: decoder.decodeInt64ForKey("s", orElse: 0))
|
|
case SecretChatOutgoingOperationValue.pfsCommitKey.rawValue:
|
|
self = .pfsCommitKey(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), rekeySessionId: decoder.decodeInt64ForKey("s", orElse: 0), keyFingerprint: decoder.decodeInt64ForKey("f", orElse: 0))
|
|
case SecretChatOutgoingOperationValue.noop.rawValue:
|
|
self = .noop(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0))
|
|
case SecretChatOutgoingOperationValue.setMessageAutoremoveTimeout.rawValue:
|
|
self = .setMessageAutoremoveTimeout(layer: SecretChatLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: decoder.decodeInt64ForKey("i", orElse: 0), timeout: decoder.decodeInt32ForKey("t", orElse: 0), messageId: MessageId(peerId: PeerId(decoder.decodeInt64ForKey("m.p", orElse: 0)), namespace: decoder.decodeInt32ForKey("m.n", orElse: 0), id: decoder.decodeInt32ForKey("m.i", orElse: 0)))
|
|
case SecretChatOutgoingOperationValue.terminate.rawValue:
|
|
self = .terminate(reportSpam: decoder.decodeInt32ForKey("rs", orElse: 0) != 0, requestRemoteHistoryRemoval: decoder.decodeInt32ForKey("requestRemoteHistoryRemoval", orElse: 0) != 0)
|
|
default:
|
|
self = .noop(layer: SecretChatSequenceBasedLayer(rawValue: decoder.decodeInt32ForKey("l", orElse: 0))!, actionGloballyUniqueId: 0)
|
|
assertionFailure()
|
|
}
|
|
}
|
|
|
|
public func encode(_ encoder: PostboxEncoder) {
|
|
switch self {
|
|
case let .initialHandshakeAccept(gA, accessHash, b):
|
|
encoder.encodeInt32(SecretChatOutgoingOperationValue.initialHandshakeAccept.rawValue, forKey: "r")
|
|
encoder.encodeBytes(gA, forKey: "g")
|
|
encoder.encodeInt64(accessHash, forKey: "h")
|
|
encoder.encodeBytes(b, forKey: "b")
|
|
case let .sendMessage(layer, id, file):
|
|
encoder.encodeInt32(SecretChatOutgoingOperationValue.sendMessage.rawValue, forKey: "r")
|
|
encoder.encodeInt32(layer.rawValue, forKey: "l")
|
|
encoder.encodeInt64(id.peerId.toInt64(), forKey: "i.p")
|
|
encoder.encodeInt32(id.namespace, forKey: "i.n")
|
|
encoder.encodeInt32(id.id, forKey: "i.i")
|
|
if let file = file {
|
|
encoder.encodeObject(file, forKey: "f")
|
|
} else {
|
|
encoder.encodeNil(forKey: "f")
|
|
}
|
|
case let .readMessagesContent(layer, actionGloballyUniqueId, globallyUniqueIds):
|
|
encoder.encodeInt32(SecretChatOutgoingOperationValue.readMessagesContent.rawValue, forKey: "r")
|
|
encoder.encodeInt32(layer.rawValue, forKey: "l")
|
|
encoder.encodeInt64(actionGloballyUniqueId, forKey: "i")
|
|
encoder.encodeInt64Array(globallyUniqueIds, forKey: "u")
|
|
case let .deleteMessages(layer, actionGloballyUniqueId, globallyUniqueIds):
|
|
encoder.encodeInt32(SecretChatOutgoingOperationValue.deleteMessages.rawValue, forKey: "r")
|
|
encoder.encodeInt32(layer.rawValue, forKey: "l")
|
|
encoder.encodeInt64(actionGloballyUniqueId, forKey: "i")
|
|
encoder.encodeInt64Array(globallyUniqueIds, forKey: "u")
|
|
case let .screenshotMessages(layer, actionGloballyUniqueId, globallyUniqueIds, messageId):
|
|
encoder.encodeInt32(SecretChatOutgoingOperationValue.screenshotMessages.rawValue, forKey: "r")
|
|
encoder.encodeInt32(layer.rawValue, forKey: "l")
|
|
encoder.encodeInt64(actionGloballyUniqueId, forKey: "i")
|
|
encoder.encodeInt64Array(globallyUniqueIds, forKey: "u")
|
|
encoder.encodeInt64(messageId.peerId.toInt64(), forKey: "m.p")
|
|
encoder.encodeInt32(messageId.namespace, forKey: "m.n")
|
|
encoder.encodeInt32(messageId.id, forKey: "m.i")
|
|
case let .clearHistory(layer, actionGloballyUniqueId):
|
|
encoder.encodeInt32(SecretChatOutgoingOperationValue.clearHistory.rawValue, forKey: "r")
|
|
encoder.encodeInt32(layer.rawValue, forKey: "l")
|
|
encoder.encodeInt64(actionGloballyUniqueId, forKey: "i")
|
|
case let .resendOperations(layer, actionGloballyUniqueId, fromSeqNo, toSeqNo):
|
|
encoder.encodeInt32(SecretChatOutgoingOperationValue.resendOperations.rawValue, forKey: "r")
|
|
encoder.encodeInt32(layer.rawValue, forKey: "l")
|
|
encoder.encodeInt64(actionGloballyUniqueId, forKey: "i")
|
|
encoder.encodeInt32(fromSeqNo, forKey: "f")
|
|
encoder.encodeInt32(toSeqNo, forKey: "t")
|
|
case let .reportLayerSupport(layer, actionGloballyUniqueId, layerSupport):
|
|
encoder.encodeInt32(SecretChatOutgoingOperationValue.reportLayerSupport.rawValue, forKey: "r")
|
|
encoder.encodeInt32(layer.rawValue, forKey: "l")
|
|
encoder.encodeInt64(actionGloballyUniqueId, forKey: "i")
|
|
encoder.encodeInt32(layerSupport, forKey: "l")
|
|
case let .pfsRequestKey(layer, actionGloballyUniqueId, rekeySessionId, a):
|
|
encoder.encodeInt32(SecretChatOutgoingOperationValue.pfsRequestKey.rawValue, forKey: "r")
|
|
encoder.encodeInt32(layer.rawValue, forKey: "l")
|
|
encoder.encodeInt64(actionGloballyUniqueId, forKey: "i")
|
|
encoder.encodeInt64(rekeySessionId, forKey: "s")
|
|
encoder.encodeBytes(a, forKey: "a")
|
|
case let .pfsAcceptKey(layer, actionGloballyUniqueId, rekeySessionId, gA, b):
|
|
encoder.encodeInt32(SecretChatOutgoingOperationValue.pfsAcceptKey.rawValue, forKey: "r")
|
|
encoder.encodeInt32(layer.rawValue, forKey: "l")
|
|
encoder.encodeInt64(actionGloballyUniqueId, forKey: "i")
|
|
encoder.encodeInt64(rekeySessionId, forKey: "s")
|
|
encoder.encodeBytes(gA, forKey: "g")
|
|
encoder.encodeBytes(b, forKey: "b")
|
|
case let .pfsAbortSession(layer, actionGloballyUniqueId, rekeySessionId):
|
|
encoder.encodeInt32(SecretChatOutgoingOperationValue.pfsAbortSession.rawValue, forKey: "r")
|
|
encoder.encodeInt32(layer.rawValue, forKey: "l")
|
|
encoder.encodeInt64(actionGloballyUniqueId, forKey: "i")
|
|
encoder.encodeInt64(rekeySessionId, forKey: "s")
|
|
case let .pfsCommitKey(layer, actionGloballyUniqueId, rekeySessionId, keyFingerprint):
|
|
encoder.encodeInt32(SecretChatOutgoingOperationValue.pfsCommitKey.rawValue, forKey: "r")
|
|
encoder.encodeInt32(layer.rawValue, forKey: "l")
|
|
encoder.encodeInt64(actionGloballyUniqueId, forKey: "i")
|
|
encoder.encodeInt64(rekeySessionId, forKey: "s")
|
|
encoder.encodeInt64(keyFingerprint, forKey: "f")
|
|
case let .noop(layer, actionGloballyUniqueId):
|
|
encoder.encodeInt32(SecretChatOutgoingOperationValue.noop.rawValue, forKey: "r")
|
|
encoder.encodeInt32(layer.rawValue, forKey: "l")
|
|
encoder.encodeInt64(actionGloballyUniqueId, forKey: "i")
|
|
case let .setMessageAutoremoveTimeout(layer, actionGloballyUniqueId, timeout, messageId):
|
|
encoder.encodeInt32(SecretChatOutgoingOperationValue.setMessageAutoremoveTimeout.rawValue, forKey: "r")
|
|
encoder.encodeInt32(layer.rawValue, forKey: "l")
|
|
encoder.encodeInt64(actionGloballyUniqueId, forKey: "i")
|
|
encoder.encodeInt32(timeout, forKey: "t")
|
|
encoder.encodeInt64(messageId.peerId.toInt64(), forKey: "m.p")
|
|
encoder.encodeInt32(messageId.namespace, forKey: "m.n")
|
|
encoder.encodeInt32(messageId.id, forKey: "m.i")
|
|
case let .terminate(reportSpam, requestRemoteHistoryRemoval):
|
|
encoder.encodeInt32(SecretChatOutgoingOperationValue.terminate.rawValue, forKey: "r")
|
|
encoder.encodeInt32(reportSpam ? 1 : 0, forKey: "rs")
|
|
encoder.encodeInt32(requestRemoteHistoryRemoval ? 1 : 0, forKey: "requestRemoteHistoryRemoval")
|
|
}
|
|
}
|
|
}
|
|
|
|
public final class SecretChatOutgoingOperation: PostboxCoding {
|
|
public let contents: SecretChatOutgoingOperationContents
|
|
public let mutable: Bool
|
|
public let delivered: Bool
|
|
|
|
public init(contents: SecretChatOutgoingOperationContents, mutable: Bool, delivered: Bool) {
|
|
self.contents = contents
|
|
self.mutable = mutable
|
|
self.delivered = delivered
|
|
}
|
|
|
|
public init(decoder: PostboxDecoder) {
|
|
self.contents = decoder.decodeObjectForKey("c", decoder: { SecretChatOutgoingOperationContents(decoder: $0) }) as! SecretChatOutgoingOperationContents
|
|
self.mutable = decoder.decodeInt32ForKey("m", orElse: 0) != 0
|
|
self.delivered = decoder.decodeInt32ForKey("d", orElse: 0) != 0
|
|
}
|
|
|
|
public func encode(_ encoder: PostboxEncoder) {
|
|
encoder.encodeObject(self.contents, forKey: "c")
|
|
encoder.encodeInt32(self.mutable ? 1 : 0, forKey: "m")
|
|
encoder.encodeInt32(self.delivered ? 1 : 0, forKey: "d")
|
|
}
|
|
|
|
public func withUpdatedDelivered(_ delivered: Bool) -> SecretChatOutgoingOperation {
|
|
return SecretChatOutgoingOperation(contents: self.contents, mutable: self.mutable, delivered: delivered)
|
|
}
|
|
}
|