Retry import after passphrase input
Isolate .ovpn parsing routines. - AppDelegate (external URL) - ImportedHosts Only delete URL if error is not encryption passphrase.
This commit is contained in:
parent
50aebe2310
commit
dc81356b31
|
@ -94,23 +94,27 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele
|
|||
}
|
||||
|
||||
let topmost = root.presentedViewController ?? root
|
||||
|
||||
let fm = FileManager.default
|
||||
guard let parsingResult = ConfigurationParser.ParsingResult.from(url, withErrorAlertIn: topmost) else {
|
||||
try? fm.removeItem(at: url)
|
||||
return tryParseURL(url, passphrase: nil, target: topmost)
|
||||
}
|
||||
|
||||
private func tryParseURL(_ url: URL, passphrase: String?, target: UIViewController) -> Bool {
|
||||
let passphraseBlock = { (passphrase) in
|
||||
_ = self.tryParseURL(url, passphrase: passphrase, target: target)
|
||||
}
|
||||
guard let parsingResult = ConfigurationParser.ParsingResult.from(url, withErrorAlertIn: target, passphraseBlock: passphraseBlock) else {
|
||||
return true
|
||||
}
|
||||
if let warning = parsingResult.warning {
|
||||
ConfigurationParser.ParsingResult.alertImportWarning(url: url, in: topmost, withWarning: warning) {
|
||||
ConfigurationParser.ParsingResult.alertImportWarning(url: url, in: target, withWarning: warning) {
|
||||
if $0 {
|
||||
self.handleParsingResult(parsingResult, in: topmost)
|
||||
self.handleParsingResult(parsingResult, in: target)
|
||||
} else {
|
||||
try? fm.removeItem(at: url)
|
||||
try? FileManager.default.removeItem(at: url)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
handleParsingResult(parsingResult, in: topmost)
|
||||
handleParsingResult(parsingResult, in: target)
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -32,14 +32,39 @@ import Passepartout_Core
|
|||
private let log = SwiftyBeaver.self
|
||||
|
||||
extension ConfigurationParser.ParsingResult {
|
||||
static func from(_ url: URL, withErrorAlertIn viewController: UIViewController) -> ConfigurationParser.ParsingResult? {
|
||||
static func from(_ url: URL, withErrorAlertIn viewController: UIViewController, passphraseBlock: @escaping (String) -> Void) -> ConfigurationParser.ParsingResult? {
|
||||
let result: ConfigurationParser.ParsingResult
|
||||
let fm = FileManager.default
|
||||
|
||||
log.debug("Parsing configuration URL: \(url)")
|
||||
do {
|
||||
result = try ConfigurationParser.parsed(fromURL: url)
|
||||
} catch let e as ConfigurationParser.ParsingError {
|
||||
switch e {
|
||||
case .encryptionPassphrase, .unableToDecrypt(_):
|
||||
let alert = Macros.alert(url.normalizedFilename, L10n.ParsedFile.Alerts.EncryptionPassphrase.message)
|
||||
alert.addTextField(configurationHandler: nil)
|
||||
alert.addDefaultAction(L10n.Global.ok) {
|
||||
guard let passphrase = alert.textFields?.first?.text else {
|
||||
return
|
||||
}
|
||||
passphraseBlock(passphrase)
|
||||
}
|
||||
alert.addCancelAction(L10n.Global.cancel) {
|
||||
try? fm.removeItem(at: url)
|
||||
}
|
||||
viewController.present(alert, animated: true, completion: nil)
|
||||
|
||||
default:
|
||||
let message = localizedMessage(forError: e)
|
||||
alertImportError(url: url, in: viewController, withMessage: message)
|
||||
try? fm.removeItem(at: url)
|
||||
}
|
||||
return nil
|
||||
} catch let e {
|
||||
let message = localizedMessage(forError: e)
|
||||
alertImportError(url: url, in: viewController, withMessage: message)
|
||||
try? fm.removeItem(at: url)
|
||||
return nil
|
||||
}
|
||||
return result
|
||||
|
@ -78,6 +103,9 @@ extension ConfigurationParser.ParsingResult {
|
|||
case .unsupportedConfiguration(let option):
|
||||
log.error("Could not parse configuration URL: unsupported configuration, \(option)")
|
||||
return L10n.ParsedFile.Alerts.Unsupported.message(option)
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
log.error("Could not parse configuration URL: \(error)")
|
||||
|
@ -91,6 +119,9 @@ extension ConfigurationParser.ParsingResult {
|
|||
|
||||
case .unsupportedConfiguration(let option):
|
||||
return option
|
||||
|
||||
default:
|
||||
return "" // XXX: should never get here
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,24 +76,35 @@ class ImportedHostsViewController: UITableViewController {
|
|||
return false
|
||||
}
|
||||
let url = pendingConfigurationURLs[indexPath.row]
|
||||
guard let parsingResult = ConfigurationParser.ParsingResult.from(url, withErrorAlertIn: self) else {
|
||||
deselectSelectedRow()
|
||||
return false
|
||||
return tryParseURL(url, passphrase: nil, cell: cell)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private func tryParseURL(_ url: URL, passphrase: String?, cell: UITableViewCell) -> Bool {
|
||||
let passphraseBlock: (String) -> Void = { (passphrase) in
|
||||
guard self.tryParseURL(url, passphrase: passphrase, cell: cell) else {
|
||||
return
|
||||
}
|
||||
self.parsingResult = parsingResult
|
||||
|
||||
// postpone segue until alert dismissal
|
||||
if let warning = parsingResult.warning {
|
||||
ConfigurationParser.ParsingResult.alertImportWarning(url: url, in: self, withWarning: warning) {
|
||||
self.deselectSelectedRow()
|
||||
if $0 {
|
||||
self.perform(segue: StoryboardSegue.Organizer.importHostSegueIdentifier)
|
||||
} else {
|
||||
self.parsingResult = nil
|
||||
}
|
||||
self.perform(segue: StoryboardSegue.Organizer.importHostSegueIdentifier, sender: cell)
|
||||
}
|
||||
guard let parsingResult = ConfigurationParser.ParsingResult.from(url, withErrorAlertIn: self, passphraseBlock: passphraseBlock) else {
|
||||
deselectSelectedRow()
|
||||
return false
|
||||
}
|
||||
self.parsingResult = parsingResult
|
||||
|
||||
// postpone segue until alert dismissal
|
||||
if let warning = parsingResult.warning {
|
||||
ConfigurationParser.ParsingResult.alertImportWarning(url: url, in: self, withWarning: warning) {
|
||||
self.deselectSelectedRow()
|
||||
if $0 {
|
||||
self.perform(segue: StoryboardSegue.Organizer.importHostSegueIdentifier)
|
||||
} else {
|
||||
self.parsingResult = nil
|
||||
}
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -59,6 +59,8 @@
|
|||
"parsed_file.alerts.missing.message" = "The configuration file lacks a required option (%@).";
|
||||
"parsed_file.alerts.unsupported.message" = "The configuration file contains an unsupported option (%@).";
|
||||
"parsed_file.alerts.potentially_unsupported.message" = "The configuration file is correct but contains a potentially unsupported option (%@).\n\nConnectivity may break depending on server settings.";
|
||||
"parsed_file.alerts.encryption_passphrase.message" = "Please enter the encryption passphrase.";
|
||||
"parsed_file.alerts.decryption.message" = "The configuration contains an encrypted private key and it could not be decrypted. Double check your entered passphrase.";
|
||||
"parsed_file.alerts.parsing.message" = "Unable to parse the provided configuration file (%@).";
|
||||
"parsed_file.alerts.buttons.report" = "Report an issue";
|
||||
|
||||
|
|
|
@ -403,6 +403,14 @@ public enum L10n {
|
|||
/// Report an issue
|
||||
public static let report = L10n.tr("Localizable", "parsed_file.alerts.buttons.report")
|
||||
}
|
||||
public enum Decryption {
|
||||
/// The configuration contains an encrypted private key and it could not be decrypted. Double check your entered passphrase.
|
||||
public static let message = L10n.tr("Localizable", "parsed_file.alerts.decryption.message")
|
||||
}
|
||||
public enum EncryptionPassphrase {
|
||||
/// Please enter the encryption passphrase.
|
||||
public static let message = L10n.tr("Localizable", "parsed_file.alerts.encryption_passphrase.message")
|
||||
}
|
||||
public enum Missing {
|
||||
/// The configuration file lacks a required option (%@).
|
||||
public static func message(_ p1: String) -> String {
|
||||
|
|
Loading…
Reference in New Issue