From c602d31ebab99e24e3eafcd7f84ef3e50ff51136 Mon Sep 17 00:00:00 2001 From: Peter Date: Tue, 24 Apr 2018 16:42:07 +0300 Subject: [PATCH] no message --- TelegramCore.xcodeproj/project.pbxproj | 4 + TelegramCore/Api0.swift | 18 +++- TelegramCore/ProxyServersStatuses.swift | 6 +- TelegramCore/RequestSecureIdForm.swift | 16 +-- TelegramCore/SaveSecureIdValue.swift | 2 +- TelegramCore/SecureIdValue.swift | 4 +- TelegramCore/SecureIdValueContentError.swift | 105 +++++++++++++++++++ 7 files changed, 139 insertions(+), 16 deletions(-) create mode 100644 TelegramCore/SecureIdValueContentError.swift diff --git a/TelegramCore.xcodeproj/project.pbxproj b/TelegramCore.xcodeproj/project.pbxproj index bfd0c8be5f..06d8c42b4a 100644 --- a/TelegramCore.xcodeproj/project.pbxproj +++ b/TelegramCore.xcodeproj/project.pbxproj @@ -100,6 +100,7 @@ D00DBBD81E64E41100DB5485 /* CreateSecretChat.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00DBBD61E64E41100DB5485 /* CreateSecretChat.swift */; }; D00DBBDA1E64E67E00DB5485 /* UpdateSecretChat.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00DBBD91E64E67E00DB5485 /* UpdateSecretChat.swift */; }; D00DBBDB1E64E67E00DB5485 /* UpdateSecretChat.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00DBBD91E64E67E00DB5485 /* UpdateSecretChat.swift */; }; + D0136309208F3B0900EB3653 /* SecureIdValueContentError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0136308208F3B0900EB3653 /* SecureIdValueContentError.swift */; }; D01749591E1092BC0057C89A /* RequestStartBot.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01749581E1092BC0057C89A /* RequestStartBot.swift */; }; D017495E1E118F790057C89A /* AccountStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D017495D1E118F790057C89A /* AccountStateManager.swift */; }; D01749601E118FC30057C89A /* AccountIntermediateState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D017495F1E118FC30057C89A /* AccountIntermediateState.swift */; }; @@ -741,6 +742,7 @@ D00D97C91E32917C00E5C2B6 /* PeerInputActivityManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerInputActivityManager.swift; sourceTree = ""; }; D00DBBD61E64E41100DB5485 /* CreateSecretChat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateSecretChat.swift; sourceTree = ""; }; D00DBBD91E64E67E00DB5485 /* UpdateSecretChat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdateSecretChat.swift; sourceTree = ""; }; + D0136308208F3B0900EB3653 /* SecureIdValueContentError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdValueContentError.swift; sourceTree = ""; }; D01749581E1092BC0057C89A /* RequestStartBot.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestStartBot.swift; sourceTree = ""; }; D017495D1E118F790057C89A /* AccountStateManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountStateManager.swift; sourceTree = ""; }; D017495F1E118FC30057C89A /* AccountIntermediateState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountIntermediateState.swift; sourceTree = ""; }; @@ -1690,6 +1692,7 @@ D0E412D6206A866B00BEE4A2 /* UploadSecureIdFile.swift */, D0E412ED206AF65500BEE4A2 /* GrantSecureIdAccess.swift */, D02D60AA206BA64100FEFE1E /* VerifySecureIdValue.swift */, + D0136308208F3B0900EB3653 /* SecureIdValueContentError.swift */, D093D7E82064135300BC3599 /* Values */, ); name = "Secure ID"; @@ -2024,6 +2027,7 @@ D0AAD1A81E32602500D5B9DE /* AutoremoveTimeoutMessageAttribute.swift in Sources */, C2366C831E4F3EAA0097CCFF /* GroupReturnAndLeft.swift in Sources */, C230BEB61EE9A3760029586C /* ChannelAdminEventLogs.swift in Sources */, + D0136309208F3B0900EB3653 /* SecureIdValueContentError.swift in Sources */, D03B0D3D1D6319E200955575 /* Fetch.swift in Sources */, D02D60A7206BA5F900FEFE1E /* SecureIdValue.swift in Sources */, D0DF0C931D81AD09008AEB01 /* MessageUtils.swift in Sources */, diff --git a/TelegramCore/Api0.swift b/TelegramCore/Api0.swift index c0b643eeed..c7e5d5388f 100644 --- a/TelegramCore/Api0.swift +++ b/TelegramCore/Api0.swift @@ -680,11 +680,19 @@ public struct Api { return nil } } - if let item = Api.parse(reader, signature: signature) as? T { - array.append(item) - } - else { - return nil + if elementType == Buffer.self { + if let item = parseBytes(reader) as? T { + array.append(item) + } else { + return nil + } + } else { + if let item = Api.parse(reader, signature: signature) as? T { + array.append(item) + } + else { + return nil + } } i += 1 } diff --git a/TelegramCore/ProxyServersStatuses.swift b/TelegramCore/ProxyServersStatuses.swift index da8b40bbc7..115671426b 100644 --- a/TelegramCore/ProxyServersStatuses.swift +++ b/TelegramCore/ProxyServersStatuses.swift @@ -32,9 +32,9 @@ private final class ProxyServerItemContext { return ActionDisposable { disposable?.dispose() } - } |> runOn(queue)).start(next: { status in - updated(status) - }) + } |> runOn(queue)).start(next: { status in + updated(status) + }) } deinit { diff --git a/TelegramCore/RequestSecureIdForm.swift b/TelegramCore/RequestSecureIdForm.swift index 624070dd74..4780145400 100644 --- a/TelegramCore/RequestSecureIdForm.swift +++ b/TelegramCore/RequestSecureIdForm.swift @@ -49,7 +49,7 @@ struct ParsedSecureValue { let valueWithContext: SecureIdValueWithContext } -func parseSecureValue(context: SecureIdAccessContext, value: Api.SecureValue) -> ParsedSecureValue? { +func parseSecureValue(context: SecureIdAccessContext, value: Api.SecureValue, errors: [Api.SecureValueError]) -> ParsedSecureValue? { switch value { case let .secureValue(_, type, data, files, plainData, selfie, hash): let parsedFileReferences = files.flatMap { $0.compactMap(SecureIdFileReference.init) } ?? [] @@ -60,11 +60,14 @@ func parseSecureValue(context: SecureIdAccessContext, value: Api.SecureValue) -> let encryptedMetadata: SecureIdEncryptedValueMetadata? var parsedFileMetadata: [SecureIdEncryptedValueFileMetadata] = [] var parsedSelfieMetadata: SecureIdEncryptedValueFileMetadata? + var contentsId: Data? if let data = data { let (encryptedData, decryptedHash, encryptedSecret) = parseSecureData(data) guard let valueContext = decryptedSecureValueAccessContext(context: context, encryptedSecret: encryptedSecret, decryptedDataHash: decryptedHash) else { return nil } + + contentsId = decryptedHash decryptedData = decryptedSecureValueData(context: valueContext, encryptedData: encryptedData, decryptedDataHash: decryptedHash) if decryptedData == nil { @@ -169,12 +172,12 @@ func parseSecureValue(context: SecureIdAccessContext, value: Api.SecureValue) -> } } - return ParsedSecureValue(valueWithContext: SecureIdValueWithContext(value: value, files: parsedFileMetadata, selfie: parsedSelfieMetadata, encryptedMetadata: encryptedMetadata, opaqueHash: hash.makeData())) + return ParsedSecureValue(valueWithContext: SecureIdValueWithContext(value: value, errors: parseSecureIdValueContentErrors(dataHash: contentsId, fileHashes: Set(parsedFileMetadata.map { $0.hash }), selfieHash: parsedSelfieMetadata?.hash, errors: errors), files: parsedFileMetadata, selfie: parsedSelfieMetadata, encryptedMetadata: encryptedMetadata, opaqueHash: hash.makeData())) } } -private func parseSecureValues(context: SecureIdAccessContext, values: [Api.SecureValue]) -> [SecureIdValueWithContext] { - return values.map({ parseSecureValue(context: context, value: $0) }).compactMap({ $0?.valueWithContext }) +private func parseSecureValues(context: SecureIdAccessContext, values: [Api.SecureValue], errors: [Api.SecureValueError]) -> [SecureIdValueWithContext] { + return values.map({ parseSecureValue(context: context, value: $0, errors: errors) }).compactMap({ $0?.valueWithContext }) } public struct EncryptedSecureIdForm { @@ -183,6 +186,7 @@ public struct EncryptedSecureIdForm { public let termsUrl: String? let encryptedValues: [Api.SecureValue] + let errors: [Api.SecureValueError] } public func requestSecureIdForm(postbox: Postbox, network: Network, peerId: PeerId, scope: String, publicKey: String) -> Signal { @@ -208,12 +212,12 @@ public func requestSecureIdForm(postbox: Postbox, network: Network, peerId: Peer return EncryptedSecureIdForm(peerId: peerId, requestedFields: requiredTypes.map { return parseSecureValueType($0, selfie: (flags & 1 << 1) != 0) - }, termsUrl: termsUrl, encryptedValues: values) + }, termsUrl: termsUrl, encryptedValues: values, errors: errors) } } |> mapError { _ in return RequestSecureIdFormError.generic } } } public func decryptedSecureIdForm(context: SecureIdAccessContext, form: EncryptedSecureIdForm) -> SecureIdForm? { - return SecureIdForm(peerId: form.peerId, requestedFields: form.requestedFields, values: parseSecureValues(context: context, values: form.encryptedValues)) + return SecureIdForm(peerId: form.peerId, requestedFields: form.requestedFields, values: parseSecureValues(context: context, values: form.encryptedValues, errors: form.errors)) } diff --git a/TelegramCore/SaveSecureIdValue.swift b/TelegramCore/SaveSecureIdValue.swift index 1ea78d97ef..f1bdcd7896 100644 --- a/TelegramCore/SaveSecureIdValue.swift +++ b/TelegramCore/SaveSecureIdValue.swift @@ -210,7 +210,7 @@ public func saveSecureIdValue(postbox: Postbox, network: Network, context: Secur return .generic } |> mapToSignal { result -> Signal in - guard let parsedValue = parseSecureValue(context: context, value: result) else { + guard let parsedValue = parseSecureValue(context: context, value: result, errors: []) else { return .fail(.generic) } diff --git a/TelegramCore/SecureIdValue.swift b/TelegramCore/SecureIdValue.swift index 06faeab746..b1ac910886 100644 --- a/TelegramCore/SecureIdValue.swift +++ b/TelegramCore/SecureIdValue.swift @@ -124,13 +124,15 @@ struct SecureIdEncryptedValueMetadata: Equatable { public struct SecureIdValueWithContext: Equatable { public let value: SecureIdValue + public let errors: [SecureIdValueContentErrorKey: SecureIdValueContentError] let files: [SecureIdEncryptedValueFileMetadata] let selfie: SecureIdEncryptedValueFileMetadata? let encryptedMetadata: SecureIdEncryptedValueMetadata? let opaqueHash: Data - init(value: SecureIdValue, files: [SecureIdEncryptedValueFileMetadata], selfie: SecureIdEncryptedValueFileMetadata?, encryptedMetadata: SecureIdEncryptedValueMetadata?, opaqueHash: Data) { + init(value: SecureIdValue, errors: [SecureIdValueContentErrorKey: SecureIdValueContentError], files: [SecureIdEncryptedValueFileMetadata], selfie: SecureIdEncryptedValueFileMetadata?, encryptedMetadata: SecureIdEncryptedValueMetadata?, opaqueHash: Data) { self.value = value + self.errors = errors self.files = files self.selfie = selfie self.encryptedMetadata = encryptedMetadata diff --git a/TelegramCore/SecureIdValueContentError.swift b/TelegramCore/SecureIdValueContentError.swift new file mode 100644 index 0000000000..087efce102 --- /dev/null +++ b/TelegramCore/SecureIdValueContentError.swift @@ -0,0 +1,105 @@ +import Foundation + +public enum SecureIdValueContentErrorKey: Hashable { + case field(SecureIdValueContentErrorField) + case file(hash: Data) + case files + case selfie +} + +public enum SecureIdValueContentErrorField: Hashable { + case personalDetails(SecureIdValueContentErrorPersonalDetailsField) + case passport(SecureIdValueContentErrorPassportField) + case driversLicense(SecureIdValueContentErrorDriversLicenseField) + case idCard(SecureIdValueContentErrorIdCardField) + case address(SecureIdValueContentErrorAddressField) +} + +public enum SecureIdValueContentErrorPersonalDetailsField: String, Hashable { + case firstName = "first_name" + case lastName = "last_name" + case birthdate = "birth_date" + case gender = "gender" + case countryCode = "country_code" +} + +public enum SecureIdValueContentErrorPassportField: String, Hashable { + case documentId = "document_no" + case expiryDate = "expiry_date" +} + +public enum SecureIdValueContentErrorDriversLicenseField: String, Hashable { + case documentId = "document_no" + case expiryDate = "expiry_date" +} + +public enum SecureIdValueContentErrorIdCardField: String, Hashable { + case documentId = "document_no" + case expiryDate = "expiry_date" +} + +public enum SecureIdValueContentErrorAddressField: String, Hashable { + case streetLine1 = "street_line1" + case streetLine2 = "street_line2" + case city = "city" + case state = "state" + case countryCode = "country_code" + case postCode = "post_code" +} + +public typealias SecureIdValueContentError = String + +func parseSecureIdValueContentErrors(dataHash: Data?, fileHashes: Set, selfieHash: Data?, errors: [Api.SecureValueError]) -> [SecureIdValueContentErrorKey: SecureIdValueContentError] { + var result: [SecureIdValueContentErrorKey: SecureIdValueContentError] = [:] + for error in errors { + switch error { + case let .secureValueErrorData(type, errorDataHash, field, text): + if errorDataHash.makeData() == dataHash { + switch type { + case .secureValueTypePersonalDetails: + if let parsedField = SecureIdValueContentErrorPersonalDetailsField(rawValue: field) { + result[.field(.personalDetails(parsedField))] = text + } + case .secureValueTypePassport: + if let parsedField = SecureIdValueContentErrorPassportField(rawValue: field) { + result[.field(.passport(parsedField))] = text + } + case .secureValueTypeDriverLicense: + if let parsedField = SecureIdValueContentErrorDriversLicenseField(rawValue: field) { + result[.field(.driversLicense(parsedField))] = text + } + case .secureValueTypeIdentityCard: + if let parsedField = SecureIdValueContentErrorIdCardField(rawValue: field) { + result[.field(.idCard(parsedField))] = text + } + case .secureValueTypeAddress: + if let parsedField = SecureIdValueContentErrorAddressField(rawValue: field) { + result[.field(.address(parsedField))] = text + } + default: + break + } + } + case let .secureValueErrorFile(_, fileHash, text): + if fileHashes.contains(fileHash.makeData()) { + result[.file(hash: fileHash.makeData())] = text + } + case let .secureValueErrorFiles(_, fileHash, text): + var containsAll = true + loop: for hash in fileHash { + if !fileHashes.contains(hash.makeData()) { + containsAll = false + break loop + } + } + if containsAll { + result[.files] = text + } + case let .secureValueErrorSelfie(_, fileHash, text): + if selfieHash == fileHash.makeData() { + result[.selfie] = text + } + } + } + return result +}