session-ios/Session/Signal/CompareSafetyNumbersActivit...

104 lines
3.9 KiB
Swift

//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
import SignalUtilitiesKit
let CompareSafetyNumbersActivityType = "org.whispersystems.signal.activity.CompareSafetyNumbers"
@objc(OWSCompareSafetyNumbersActivityDelegate)
protocol CompareSafetyNumbersActivityDelegate {
func compareSafetyNumbersActivitySucceeded(activity: CompareSafetyNumbersActivity)
func compareSafetyNumbersActivity(_ activity: CompareSafetyNumbersActivity, failedWithError error: Error)
}
@objc (OWSCompareSafetyNumbersActivity)
class CompareSafetyNumbersActivity: UIActivity {
var mySafetyNumbers: String?
let delegate: CompareSafetyNumbersActivityDelegate
@objc
required init(delegate: CompareSafetyNumbersActivityDelegate) {
self.delegate = delegate
super.init()
}
// MARK: UIActivity
override class var activityCategory: UIActivity.Category {
get { return .action }
}
override var activityType: UIActivity.ActivityType? {
get { return UIActivity.ActivityType(rawValue: CompareSafetyNumbersActivityType) }
}
override var activityTitle: String? {
get {
return NSLocalizedString("COMPARE_SAFETY_NUMBER_ACTION", comment: "Activity Sheet label")
}
}
override var activityImage: UIImage? {
get {
return #imageLiteral(resourceName: "ic_lock_outline")
}
}
override func canPerform(withActivityItems activityItems: [Any]) -> Bool {
return stringsFrom(activityItems: activityItems).count > 0
}
override func prepare(withActivityItems activityItems: [Any]) {
let myFormattedSafetyNumbers = stringsFrom(activityItems: activityItems).first
mySafetyNumbers = numericOnly(string: myFormattedSafetyNumbers)
}
override func perform() {
defer { activityDidFinish(true) }
let pasteboardString = numericOnly(string: UIPasteboard.general.string)
guard (pasteboardString != nil && pasteboardString!.count == 60) else {
Logger.warn("no valid safety numbers found in pasteboard: \(String(describing: pasteboardString))")
let error = OWSErrorWithCodeDescription(OWSErrorCode.userError,
NSLocalizedString("PRIVACY_VERIFICATION_FAILED_NO_SAFETY_NUMBERS_IN_CLIPBOARD", comment: "Alert body for user error"))
delegate.compareSafetyNumbersActivity(self, failedWithError: error)
return
}
let pasteboardSafetyNumbers = pasteboardString!
if pasteboardSafetyNumbers == mySafetyNumbers {
Logger.info("successfully matched safety numbers. local numbers: \(String(describing: mySafetyNumbers)) pasteboard:\(pasteboardSafetyNumbers)")
delegate.compareSafetyNumbersActivitySucceeded(activity: self)
} else {
Logger.warn("local numbers: \(String(describing: mySafetyNumbers)) didn't match pasteboard:\(pasteboardSafetyNumbers)")
let error = OWSErrorWithCodeDescription(OWSErrorCode.privacyVerificationFailure,
NSLocalizedString("PRIVACY_VERIFICATION_FAILED_MISMATCHED_SAFETY_NUMBERS_IN_CLIPBOARD", comment: "Alert body"))
delegate.compareSafetyNumbersActivity(self, failedWithError: error)
}
}
// MARK: Helpers
func numericOnly(string: String?) -> String? {
guard let string = string else {
return nil
}
var numericOnly: String?
if let regex = try? NSRegularExpression(pattern: "\\D", options: .caseInsensitive) {
numericOnly = regex.stringByReplacingMatches(in: string, options: .withTransparentBounds, range: NSRange(location: 0, length: string.utf16.count), withTemplate: "")
}
return numericOnly
}
func stringsFrom(activityItems: [Any]) -> [String] {
return activityItems.map { $0 as? String }.filter { $0 != nil }.map { $0! }
}
}