From caa5ce77a3feb4694308b511d094b4ea39ed71b9 Mon Sep 17 00:00:00 2001 From: Danny Moesch Date: Mon, 26 Feb 2018 16:53:39 +0100 Subject: [PATCH] Use YAML library to parse password files --- Cartfile | 1 + pass.xcodeproj/project.pbxproj | 5 ++ ...nSourceComponentsTableViewController.swift | 3 ++ .../PasswordEditorTableViewController.swift | 2 +- passKit/Models/Password.swift | 48 ++++++++++++------- 5 files changed, 42 insertions(+), 17 deletions(-) diff --git a/Cartfile b/Cartfile index 8a5489e..60924ca 100644 --- a/Cartfile +++ b/Cartfile @@ -6,3 +6,4 @@ github "yishilin14/SwiftPasscodeLock" "app-extension-support" github "mssun/FavIcon" "master" github "kishikawakatsumi/KeychainAccess" github "mattrubin/OneTimePassword" +github "jpsim/Yams" diff --git a/pass.xcodeproj/project.pbxproj b/pass.xcodeproj/project.pbxproj index 4081695..b58cef1 100644 --- a/pass.xcodeproj/project.pbxproj +++ b/pass.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 18F19A67B0C07F13C17169E0 /* Pods_pass.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A5620D17DF5E86B61761D0E /* Pods_pass.framework */; }; 23B82F0228254275DBA609E7 /* Pods_passExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B975797E0F0B7476CADD6A7D /* Pods_passExtension.framework */; }; + 3012B06D2039D6E400BE1793 /* Yams.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3012B06C2039D6E400BE1793 /* Yams.framework */; }; 61326CDA7A73757FB68DCB04 /* Pods_passKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAB3F5541E51ADC8C6B56642 /* Pods_passKit.framework */; }; A20691F41F2A3D0E0096483D /* SecurePasteboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = A20691F31F2A3D0E0096483D /* SecurePasteboard.swift */; }; A2168A7F1EFD40D5005EA873 /* OnePasswordExtensionConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2168A7E1EFD40D5005EA873 /* OnePasswordExtensionConstants.swift */; }; @@ -157,6 +158,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 3012B06C2039D6E400BE1793 /* Yams.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Yams.framework; path = Carthage/Build/iOS/Yams.framework; sourceTree = ""; }; 31C3033E8868D05B2C55C8B1 /* Pods-passExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-passExtension.debug.xcconfig"; path = "Pods/Target Support Files/Pods-passExtension/Pods-passExtension.debug.xcconfig"; sourceTree = ""; }; 3A5620D17DF5E86B61761D0E /* Pods_pass.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_pass.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 666769E0B255666D02945C15 /* Pods-passKitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-passKitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-passKitTests/Pods-passKitTests.release.xcconfig"; sourceTree = ""; }; @@ -317,6 +319,7 @@ DCC408C71E307DBB00F29B0E /* SVProgressHUD.framework in Frameworks */, DC193FFC1E49E0340077E0A3 /* PasscodeLock.framework in Frameworks */, 18F19A67B0C07F13C17169E0 /* Pods_pass.framework in Frameworks */, + 3012B06D2039D6E400BE1793 /* Yams.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -542,6 +545,7 @@ DC917BED1E2F38C4000FDF54 /* Frameworks */ = { isa = PBXGroup; children = ( + 3012B06C2039D6E400BE1793 /* Yams.framework */, A2A61C101EEF8E3500CFE063 /* libPods-passKit.a */, A2A61C0C1EEF8DFE00CFE063 /* libPods-passExtension.a */, A2227D541EEE5E78002A69A9 /* libObjectivePGP.a */, @@ -989,6 +993,7 @@ "$(SRCROOT)/Carthage/Build/iOS/KeychainAccess.framework", "$(SRCROOT)/Carthage/Build/iOS/OneTimePassword.framework", "$(SRCROOT)/Carthage/Build/iOS/Base32.framework", + "$(SRCROOT)/Carthage/Build/iOS/Yams.framework", ); name = "Run Script"; outputPaths = ( diff --git a/pass/Controllers/OpenSourceComponentsTableViewController.swift b/pass/Controllers/OpenSourceComponentsTableViewController.swift index b67fb40..b220434 100644 --- a/pass/Controllers/OpenSourceComponentsTableViewController.swift +++ b/pass/Controllers/OpenSourceComponentsTableViewController.swift @@ -35,6 +35,9 @@ class OpenSourceComponentsTableViewController: BasicStaticTableViewController { ["SVProgressHUD", "https://github.com/SVProgressHUD/SVProgressHUD", "https://github.com/SVProgressHUD/SVProgressHUD/blob/master/LICENSE.txt"], + ["Yams", + "https://github.com/jpsim/Yams", + "https://github.com/jpsim/Yams/blob/master/LICENSE"], ] override func viewDidLoad() { diff --git a/pass/Controllers/PasswordEditorTableViewController.swift b/pass/Controllers/PasswordEditorTableViewController.swift index 7ed2ed6..e03eb48 100644 --- a/pass/Controllers/PasswordEditorTableViewController.swift +++ b/pass/Controllers/PasswordEditorTableViewController.swift @@ -28,7 +28,7 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl private var navigationItemTitle: String? private var sectionHeaderTitles = ["name", "password", "additions",""].map {$0.uppercased()} - private var sectionFooterTitles = ["", "", "Use \"key: value\" format for additional fields.", ""] + private var sectionFooterTitles = ["", "", "Use YAML format for additional fields.", ""] private let nameSection = 0 private let passwordSection = 1 private let additionsSection = 2 diff --git a/passKit/Models/Password.swift b/passKit/Models/Password.swift index cae9fee..9a9c15f 100644 --- a/passKit/Models/Password.swift +++ b/passKit/Models/Password.swift @@ -10,6 +10,7 @@ import Foundation import SwiftyUserDefaults import OneTimePassword import Base32 +import Yams struct AdditionField { var title: String @@ -84,29 +85,25 @@ public class Password { additions.removeAll() // split the plain text - let plainTextSplit = plainText.split(maxSplits: 1, omittingEmptySubsequences: false) { + let plainTextSplit = self.plainText.split(maxSplits: 1, omittingEmptySubsequences: false) { $0 == "\n" || $0 == "\r\n" }.map(String.init) // get password password = plainTextSplit.first ?? "" - // get additonal fields - if plainTextSplit.count == 2 { - var unknownIndex = 0 - plainTextSplit[1].enumerateLines() { line, _ in - if !line.isEmpty { - var (key, value) = Password.getKeyValuePair(from: line) - if key == nil { - unknownIndex += 1 - key = "unknown \(unknownIndex)" - } - self.additions.append((key!, value)) - } - } + // get remaining lines + let additionalFields = plainTextSplit.last ?? "" + + // try to interpret the text format as YAML first + do { + try getAdditionalFields(fromYaml: additionalFields) } - - // check whether the first line of the plainText looks like an otp entry + catch { + getAdditionalFields(fromPlainText: additionalFields) + } + + // check whether the first line looks like an otp entry let (key, value) = Password.getKeyValuePair(from: self.password) if Password.otpKeywords.contains(key ?? "") { firstLineIsOTPField = true @@ -118,6 +115,25 @@ public class Password { // construct the otp token self.updateOtpToken() } + + private func getAdditionalFields(fromYaml: String) throws { + let yamlFile = try Yams.load(yaml: fromYaml) as! [String: Any] + additions.append(contentsOf: yamlFile.map { ($0, String(describing: $1)) }) + } + + private func getAdditionalFields(fromPlainText: String) { + var unknownIndex = 0 + fromPlainText.enumerateLines() { line, _ in + if !line.isEmpty { + var (key, value) = Password.getKeyValuePair(from: line) + if key == nil { + unknownIndex += 1 + key = "unknown \(unknownIndex)" + } + self.additions.append((key!, value)) + } + } + } public func getFilteredAdditions() -> [(String, String)] { var filteredAdditions = [(String, String)]()