From f98d56753b0d17ba93a354ab9074760d44bd1b8a Mon Sep 17 00:00:00 2001 From: David Beitey Date: Wed, 27 Feb 2019 21:49:21 +1000 Subject: [PATCH] Add ability to hide password images This disables loading of favicon images associated with password entries and hides any images that are already loaded, using the generic icon instead. The key benefit to this option is to prevent passforios revealing that a given device has a password in its store, which could be gleaned from the fact that favicons are being loaded in this manner. --- .../GeneralSettingsTableViewController.swift | 33 +++++++++++++++++++ .../PasswordDetailTableViewController.swift | 14 +++++--- pass/en.lproj/Localizable.strings | 2 ++ passKit/Helpers/DefaultsKeys.swift | 1 + 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/pass/Controllers/GeneralSettingsTableViewController.swift b/pass/Controllers/GeneralSettingsTableViewController.swift index 955c606..22227b3 100644 --- a/pass/Controllers/GeneralSettingsTableViewController.swift +++ b/pass/Controllers/GeneralSettingsTableViewController.swift @@ -55,6 +55,15 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController { return uiSwitch }() + let hidePasswordImagesSwitch: UISwitch = { + let uiSwitch = UISwitch() + uiSwitch.onTintColor = Globals.blue + uiSwitch.sizeToFit() + uiSwitch.addTarget(self, action: #selector(hidePasswordImagesSwitchAction(_:)), for: UIControlEvents.valueChanged) + uiSwitch.isOn = SharedDefaults[.isHidePasswordImagesOn] + return uiSwitch + }() + override func viewDidLoad() { tableData = [ // section 0 @@ -72,6 +81,7 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController { ], [ [.title: "ShowFolders".localize(), .action: "none",], + [.title: "HidePasswordImages".localize(), .action: "none",], [.title: "HideUnknownFields".localize(), .action: "none",], [.title: "HideOtpFields".localize(), .action: "none",], ], @@ -120,6 +130,18 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController { cell.accessoryType = .none cell.selectionStyle = .none cell.accessoryView = showFolderSwitch + case "HidePasswordImages".localize(): + cell.accessoryType = .none + let detailButton = UIButton(type: .detailDisclosure) + hidePasswordImagesSwitch.frame = CGRect(x: detailButton.bounds.width+10, y: 0, width: hidePasswordImagesSwitch.bounds.width, height: hidePasswordImagesSwitch.bounds.height) + detailButton.frame = CGRect(x: 0, y: 5, width: detailButton.bounds.width, height: detailButton.bounds.height) + detailButton.addTarget(self, action: #selector(GeneralSettingsTableViewController.tapHidePasswordImagesSwitchDetailButton(_:)), for: UIControlEvents.touchDown) + let accessoryView = UIView(frame: CGRect(x: 0, y: 0, width: detailButton.bounds.width + hidePasswordImagesSwitch.bounds.width+10, height: hidePasswordImagesSwitch.bounds.height)) + accessoryView.addSubview(detailButton) + accessoryView.addSubview(hidePasswordImagesSwitch) + cell.accessoryView = accessoryView + cell.selectionStyle = .none + hidePasswordImagesSwitch.isOn = SharedDefaults[.isHidePasswordImagesOn] case "PasswordGeneratorFlavor".localize(): cell.accessoryType = .disclosureIndicator cell.detailTextLabel?.text = PasswordGeneratorFlavour.from(SharedDefaults[.passwordGeneratorFlavor]).name @@ -180,6 +202,12 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController { Utils.alert(title: alertTitle, message: alertMessage, controller: self, completion: nil) } + @objc func tapHidePasswordImagesSwitchDetailButton(_ sender: Any?) { + let alertMessage = "HidePasswordImagesExplanation.".localize() + let alertTitle = "HidePasswordImages".localize() + Utils.alert(title: alertTitle, message: alertMessage, controller: self, completion: nil) + } + @objc func hideUnknownSwitchAction(_ sender: Any?) { SharedDefaults[.isHideUnknownOn] = hideUnknownSwitch.isOn NotificationCenter.default.post(name: .passwordDetailDisplaySettingChanged, object: nil) @@ -210,4 +238,9 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController { NotificationCenter.default.post(name: .passwordDisplaySettingChanged, object: nil) } + @objc func hidePasswordImagesSwitchAction(_ sender: Any?) { + SharedDefaults[.isHidePasswordImagesOn] = hidePasswordImagesSwitch.isOn + NotificationCenter.default.post(name: .passwordDetailDisplaySettingChanged, object: nil) + } + } diff --git a/pass/Controllers/PasswordDetailTableViewController.swift b/pass/Controllers/PasswordDetailTableViewController.swift index bbf7f01..bccf20b 100644 --- a/pass/Controllers/PasswordDetailTableViewController.swift +++ b/pass/Controllers/PasswordDetailTableViewController.swift @@ -148,9 +148,11 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni self?.setTableData() self?.tableView.reloadData() self?.editUIBarButtonItem.isEnabled = true - if let urlString = self?.password?.urlString { - if self?.passwordEntity?.getImage() == nil { - self?.updatePasswordImage(urlString: urlString) + if !SharedDefaults[.isHidePasswordImagesOn] { + if let urlString = self?.password?.urlString { + if self?.passwordEntity?.getImage() == nil { + self?.updatePasswordImage(urlString: urlString) + } } } } @@ -395,7 +397,11 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni switch(tableData[sectionIndex].type) { case .name: let cell = tableView.dequeueReusableCell(withIdentifier: "passwordDetailTitleTableViewCell", for: indexPath) as! PasswordDetailTitleTableViewCell - cell.passwordImageImageView.image = passwordImage ?? #imageLiteral(resourceName: "PasswordImagePlaceHolder") + if !SharedDefaults[.isHidePasswordImagesOn] { + cell.passwordImageImageView.image = passwordImage ?? #imageLiteral(resourceName: "PasswordImagePlaceHolder") + } else { + cell.passwordImageImageView.image = #imageLiteral(resourceName: "PasswordImagePlaceHolder") + } let passwordName = passwordEntity!.getName() if passwordEntity!.synced == false { cell.nameLabel.text = "\(passwordName) ↻" diff --git a/pass/en.lproj/Localizable.strings b/pass/en.lproj/Localizable.strings index 9969a74..2dbf5af 100644 --- a/pass/en.lproj/Localizable.strings +++ b/pass/en.lproj/Localizable.strings @@ -41,6 +41,8 @@ "RememberPgpKeyPassphrase" = "Remember PGP Key Passphrase"; "RememberGitCredentialPassphrase" = "Remember Git Credential Passphrase"; "ShowFolders" = "Show Folders"; +"HidePasswordImages" = "Hide Password Images"; +"HidePasswordImagesExplanation." = "Associated favicon images are loaded and shown based upon the URL associated with an entry. Enable this option to hide these images and prevent them from being loaded."; "HideUnknownFields" = "Hide Unknown Fields"; "HideUnknownFieldsExplanation." = "Only \"key: value\" format in additional fields is supported. Unsupported fields will be given \"unknown\" keys. Turn on this switch to hide unsupported fields."; "HideOtpFields" = "Hide OTP Fields"; diff --git a/passKit/Helpers/DefaultsKeys.swift b/passKit/Helpers/DefaultsKeys.swift index e5b08f5..ccec2b7 100644 --- a/passKit/Helpers/DefaultsKeys.swift +++ b/passKit/Helpers/DefaultsKeys.swift @@ -39,6 +39,7 @@ public extension DefaultsKeys { static let isRememberPGPPassphraseOn = DefaultsKey("isRememberPGPPassphraseOn") static let isRememberGitCredentialPassphraseOn = DefaultsKey("isRememberGitCredentialPassphraseOn") static let isShowFolderOn = DefaultsKey("isShowFolderOn") + static let isHidePasswordImagesOn = DefaultsKey("isHidePasswordImagesOn") static let isSearchDefaultAll = DefaultsKey("isSearchDefaultAll") static let passwordGeneratorFlavor = DefaultsKey("passwordGeneratorFlavor")