mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
185 lines
5.9 KiB
Swift
185 lines
5.9 KiB
Swift
import Foundation
|
|
import Postbox
|
|
|
|
public enum SecretChatKeyValidity: PostboxCoding, Equatable {
|
|
case indefinite
|
|
case sequenceBasedIndexRange(fromCanonicalIndex: Int32)
|
|
|
|
public init(decoder: PostboxDecoder) {
|
|
switch decoder.decodeInt32ForKey("r", orElse: 0) {
|
|
case 0:
|
|
self = .indefinite
|
|
case 1:
|
|
self = .sequenceBasedIndexRange(fromCanonicalIndex: decoder.decodeInt32ForKey("l", orElse: 0))
|
|
default:
|
|
assertionFailure()
|
|
self = .sequenceBasedIndexRange(fromCanonicalIndex: Int32.max)
|
|
}
|
|
}
|
|
|
|
public func encode(_ encoder: PostboxEncoder) {
|
|
switch self {
|
|
case .indefinite:
|
|
encoder.encodeInt32(0, forKey: "r")
|
|
case let .sequenceBasedIndexRange(fromCanonicalIndex):
|
|
encoder.encodeInt32(1, forKey: "r")
|
|
encoder.encodeInt32(fromCanonicalIndex, forKey: "l")
|
|
}
|
|
}
|
|
|
|
public static func ==(lhs: SecretChatKeyValidity, rhs: SecretChatKeyValidity) -> Bool {
|
|
switch lhs {
|
|
case .indefinite:
|
|
if case .indefinite = rhs {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .sequenceBasedIndexRange(fromCanonicalIndex):
|
|
if case .sequenceBasedIndexRange(fromCanonicalIndex) = rhs {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public final class SecretChatKey: PostboxCoding, Equatable {
|
|
public let fingerprint: Int64
|
|
public let key: MemoryBuffer
|
|
public let validity: SecretChatKeyValidity
|
|
public let useCount: Int32
|
|
|
|
public init(fingerprint: Int64, key: MemoryBuffer, validity: SecretChatKeyValidity, useCount: Int32) {
|
|
self.fingerprint = fingerprint
|
|
self.key = key
|
|
self.validity = validity
|
|
self.useCount = useCount
|
|
}
|
|
|
|
public init(decoder: PostboxDecoder) {
|
|
self.fingerprint = decoder.decodeInt64ForKey("f", orElse: 0)
|
|
self.key = decoder.decodeBytesForKey("k")!
|
|
self.validity = decoder.decodeObjectForKey("v", decoder: { SecretChatKeyValidity(decoder: $0) }) as! SecretChatKeyValidity
|
|
self.useCount = decoder.decodeInt32ForKey("u", orElse: 0)
|
|
}
|
|
|
|
public func encode(_ encoder: PostboxEncoder) {
|
|
encoder.encodeInt64(self.fingerprint, forKey: "f")
|
|
encoder.encodeBytes(self.key, forKey: "k")
|
|
encoder.encodeObject(self.validity, forKey: "v")
|
|
encoder.encodeInt32(self.useCount, forKey: "u")
|
|
}
|
|
|
|
public func withIncrementedUseCount() -> SecretChatKey {
|
|
return SecretChatKey(fingerprint: self.fingerprint, key: self.key, validity: self.validity, useCount: self.useCount + 1)
|
|
}
|
|
|
|
public static func ==(lhs: SecretChatKey, rhs: SecretChatKey) -> Bool {
|
|
if lhs.fingerprint != rhs.fingerprint {
|
|
return false
|
|
}
|
|
if lhs.validity != rhs.validity {
|
|
return false
|
|
}
|
|
if lhs.useCount != rhs.useCount {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
}
|
|
|
|
public final class SecretChatKeychain: PostboxCoding, Equatable {
|
|
public let keys: [SecretChatKey]
|
|
|
|
public init(keys: [SecretChatKey]) {
|
|
self.keys = keys
|
|
}
|
|
|
|
public init(decoder: PostboxDecoder) {
|
|
self.keys = decoder.decodeObjectArrayWithDecoderForKey("k")
|
|
}
|
|
|
|
public func encode(_ encoder: PostboxEncoder) {
|
|
encoder.encodeObjectArray(self.keys, forKey: "k")
|
|
}
|
|
|
|
public func key(fingerprint: Int64) -> SecretChatKey? {
|
|
for key in self.keys {
|
|
if key.fingerprint == fingerprint {
|
|
return key
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
public func indefinitelyValidKey() -> SecretChatKey? {
|
|
for key in self.keys {
|
|
if case .indefinite = key.validity {
|
|
return key
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
public func latestKey(validForSequenceBasedCanonicalIndex index: Int32) -> SecretChatKey? {
|
|
var maxFromCanonicalIndex: (Int, Int32)?
|
|
for i in 0 ..< self.keys.count {
|
|
switch self.keys[i].validity {
|
|
case .indefinite:
|
|
break
|
|
case let .sequenceBasedIndexRange(fromCanonicalIndex):
|
|
if index >= fromCanonicalIndex {
|
|
if maxFromCanonicalIndex == nil || maxFromCanonicalIndex!.1 < fromCanonicalIndex {
|
|
maxFromCanonicalIndex = (i, fromCanonicalIndex)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if let (keyIndex, _) = maxFromCanonicalIndex {
|
|
return self.keys[keyIndex]
|
|
}
|
|
|
|
for i in 0 ..< self.keys.count {
|
|
switch self.keys[i].validity {
|
|
case .indefinite:
|
|
return self.keys[i]
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
public func withUpdatedKey(fingerprint: Int64, _ f: (SecretChatKey?) -> SecretChatKey?) -> SecretChatKeychain {
|
|
var keys = self.keys
|
|
var found = false
|
|
for i in 0 ..< keys.count {
|
|
if keys[i].fingerprint == fingerprint {
|
|
found = true
|
|
let updatedKey = f(keys[i])
|
|
if let updatedKey = updatedKey {
|
|
keys[i] = updatedKey
|
|
} else {
|
|
keys.remove(at: i)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
let updatedKey = f(nil)
|
|
if let updatedKey = updatedKey {
|
|
keys.append(updatedKey)
|
|
}
|
|
}
|
|
return SecretChatKeychain(keys: keys)
|
|
}
|
|
|
|
public static func ==(lhs: SecretChatKeychain, rhs: SecretChatKeychain) -> Bool {
|
|
return lhs.keys == rhs.keys
|
|
}
|
|
}
|