From f7eabd8258fb115bbbab04fccff8e4da883fe7c8 Mon Sep 17 00:00:00 2001 From: Yishi Lin Date: Wed, 4 Apr 2018 12:54:35 +0800 Subject: [PATCH 1/6] Recognize *url* as url fields --- pass/Views/LabelTableViewCell.swift | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/pass/Views/LabelTableViewCell.swift b/pass/Views/LabelTableViewCell.swift index b1d8def..c49d5c2 100644 --- a/pass/Views/LabelTableViewCell.swift +++ b/pass/Views/LabelTableViewCell.swift @@ -39,8 +39,7 @@ class LabelTableViewCell: UITableViewCell { return } titleLabel.text = title - switch title.lowercased() { - case "password": + if title.caseInsensitiveCompare("password") == .orderedSame { type = .password if isReveal { contentLabel.attributedText = Utils.attributedPassword(plainPassword: content) @@ -52,7 +51,7 @@ class LabelTableViewCell: UITableViewCell { } } contentLabel.font = Globals.passwordFont - case "hmac-based": + } else if title.caseInsensitiveCompare("hmac-based") == .orderedSame { type = .HOTP if isReveal { contentLabel.text = content @@ -60,11 +59,12 @@ class LabelTableViewCell: UITableViewCell { contentLabel.text = Globals.oneTimePasswordDots } contentLabel.font = Globals.passwordFont - case "url": + } else if title.lowercased().range(of: "url") != nil || verifyUrl(content) { type = .URL contentLabel.text = content contentLabel.font = UIFont.systemFont(ofSize: contentLabel.font.pointSize) - default: + } else { + // default type = .other contentLabel.text = content contentLabel.font = UIFont.systemFont(ofSize: contentLabel.font.pointSize) @@ -198,4 +198,12 @@ class LabelTableViewCell: UITableViewCell { } self.accessoryView = buttons } + + private func verifyUrl(_ urlString: String?) -> Bool { + guard let urlString = urlString, + let _ = URL(string: urlString) else { + return false + } + return true + } } From 54c7acf65132ebacb13aebbc164836b22d58c730 Mon Sep 17 00:00:00 2001 From: Yishi Lin Date: Sat, 7 Apr 2018 00:16:06 +0800 Subject: [PATCH 2/6] Check duplicated tags before parsing a file as yaml --- passKit/Helpers/AppError.swift | 3 +++ passKit/Models/Password.swift | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/passKit/Helpers/AppError.swift b/passKit/Helpers/AppError.swift index 5386ee1..515c18a 100644 --- a/passKit/Helpers/AppError.swift +++ b/passKit/Helpers/AppError.swift @@ -16,6 +16,7 @@ public enum AppError: Error { case GitResetError case PGPPublicKeyNotExistError case WrongPasswordFilename + case YamlLoadError case UnknownError } @@ -36,6 +37,8 @@ extension AppError: LocalizedError { return "PGP public key doesn't exist." case .WrongPasswordFilename: return "Cannot write to the password file." + case .YamlLoadError: + return "Cannot be parsed as a YAML file." case .UnknownError: return "Unknown error." } diff --git a/passKit/Models/Password.swift b/passKit/Models/Password.swift index d610e84..662286d 100644 --- a/passKit/Models/Password.swift +++ b/passKit/Models/Password.swift @@ -126,9 +126,29 @@ public class Password { // construct the otp token self.updateOtpToken() } + + // check whether the file has lines with duplicated field names + private func checkDuplicatedFields(lines: String) -> Bool { + var keys = Set() + var hasDuplicatedFields = false + lines.enumerateLines { (line, stop) -> () in + let (key, _) = Password.getKeyValuePair(from: line) + if let key = key { + if keys.contains(key) { + hasDuplicatedFields = true + stop = true + } + keys.insert(key) + } + } + return hasDuplicatedFields + } private func getAdditionalFields(fromYaml: String) throws { guard !fromYaml.isEmpty else { return } + if checkDuplicatedFields(lines: fromYaml) { + throw AppError.YamlLoadError + } let yamlFile = try Yams.load(yaml: fromYaml) as! [String: Any] additions.append(contentsOf: yamlFile.map { ($0, String(describing: $1)) }) } From 3ffbf68ab860cda74113b183813711b9294be406 Mon Sep 17 00:00:00 2001 From: Yishi Lin Date: Sat, 7 Apr 2018 00:17:00 +0800 Subject: [PATCH 3/6] Avoid crash during yaml parsing --- passKit/Models/Password.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/passKit/Models/Password.swift b/passKit/Models/Password.swift index 662286d..51f223c 100644 --- a/passKit/Models/Password.swift +++ b/passKit/Models/Password.swift @@ -149,7 +149,9 @@ public class Password { if checkDuplicatedFields(lines: fromYaml) { throw AppError.YamlLoadError } - let yamlFile = try Yams.load(yaml: fromYaml) as! [String: Any] + guard let yamlFile = try Yams.load(yaml: fromYaml) as? [String: Any] else { + throw AppError.YamlLoadError + } additions.append(contentsOf: yamlFile.map { ($0, String(describing: $1)) }) } From 867a59b513e1f895a4b8a42d2a851754be8d1baf Mon Sep 17 00:00:00 2001 From: Yishi Lin Date: Sat, 7 Apr 2018 00:39:56 +0800 Subject: [PATCH 4/6] Keep the first line as the password even if it is empty --- passKit/Models/Password.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passKit/Models/Password.swift b/passKit/Models/Password.swift index 51f223c..ce9eff9 100644 --- a/passKit/Models/Password.swift +++ b/passKit/Models/Password.swift @@ -87,15 +87,15 @@ public class Password { additions.removeAll() // split the plain text - let plainTextSplit = self.plainText.split(omittingEmptySubsequences: true) { + let plainTextSplit = self.plainText.split(omittingEmptySubsequences: false) { $0 == "\n" || $0 == "\r\n" }.map(String.init) // get password password = plainTextSplit.first ?? "" - // get remaining lines - let additionalLines = plainTextSplit[1...] + // get remaining lines (filter out empty lines) + let additionalLines = plainTextSplit[1...].filter { !$0.isEmpty } // separate normal lines (no otp tokens) let normalAdditionalLines = additionalLines.filter { From 0579662263e0e8f5fde55b4f10b3b4724a83dd41 Mon Sep 17 00:00:00 2001 From: Yishi Lin Date: Sat, 7 Apr 2018 01:30:25 +0800 Subject: [PATCH 5/6] Update provisioning files --- pass.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pass.xcodeproj/project.pbxproj b/pass.xcodeproj/project.pbxproj index ef17326..983f06c 100644 --- a/pass.xcodeproj/project.pbxproj +++ b/pass.xcodeproj/project.pbxproj @@ -1541,7 +1541,7 @@ OTHER_LDFLAGS = "${inherited}"; PRODUCT_BUNDLE_IDENTIFIER = "$(PRODUCT_BUNDLE_IDENTIFIER)"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "6bb836f2-68a1-44cc-8c45-f6b6e53ba64a"; + PROVISIONING_PROFILE = "3c4f599a-ce77-4184-b4c4-edebf09cba3b"; PROVISIONING_PROFILE_SPECIFIER = "match Development me.mssun.passforios"; SWIFT_OBJC_BRIDGING_HEADER = "pass/Helpers/Objective-CBridgingHeader.h"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; From 6981860caa03306a71cb962ad21be22771941c63 Mon Sep 17 00:00:00 2001 From: Yishi Lin Date: Sat, 7 Apr 2018 01:40:34 +0800 Subject: [PATCH 6/6] Set the passextension device to universal --- pass.xcodeproj/project.pbxproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pass.xcodeproj/project.pbxproj b/pass.xcodeproj/project.pbxproj index 983f06c..3c9f607 100644 --- a/pass.xcodeproj/project.pbxproj +++ b/pass.xcodeproj/project.pbxproj @@ -1330,6 +1330,7 @@ SKIP_INSTALL = YES; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; @@ -1363,6 +1364,7 @@ SKIP_INSTALL = YES; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; };