Compare commits

..

3 Commits

Author SHA1 Message Date
matthewpalmer 0e6f35c8bb Bump podspec 2016-01-24 10:43:06 +11:00
matthewpalmer b0e072ca75 Merge branch 'master' of https://github.com/matthewpalmer/Locksmith
* 'master' of https://github.com/matthewpalmer/Locksmith:
  full bitcode is needed for running Debug on device
  don't set ONLY_ACTIVE_ARCH to YES
2016-01-24 10:40:20 +11:00
matthewpalmer a9c1a6022b Bump podspec version 2016-01-17 15:43:00 +11:00
34 changed files with 291 additions and 1114 deletions
-1
View File
@@ -1 +0,0 @@
3.0
+13 -19
View File
@@ -1,29 +1,23 @@
# Taken from https://github.com/Alamofire/AlamofireImage
language: objective-c
osx_image: xcode8
osx_image: xcode7
env:
global:
- LC_CTYPE=en_US.UTF-8
- LANG=en_US.UTF-8
matrix:
- DESTINATION="OS=3.0,name=Apple Watch - 42mm" SCHEME="Locksmith watchOS" SDK=watchsimulator3.0 RUN_TESTS="NO" BUILD_EXAMPLE="NO" POD_LINT="YES"
- DESTINATION="OS=2.0,name=Apple Watch - 42mm" SCHEME="Locksmith watchOS" SDK=watchsimulator3.0 RUN_TESTS="NO" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="arch=x86_64" SCHEME="Locksmith OS X" SDK=macosx10.12 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="OS=2.0,name=Apple Watch - 42mm" SCHEME="Locksmith watchOS" SDK=watchsimulator2.0 RUN_TESTS="NO" BUILD_EXAMPLE="NO" POD_LINT="YES"
- DESTINATION="arch=x86_64" SCHEME="Locksmith OS X" SDK=macosx10.11 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
# "build_example" should be YES but travis was giving me grief
- DESTINATION="OS=10.0,name=iPad Air 2" SCHEME="Locksmith iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="OS=10.0,name=iPhone 7" SCHEME="Locksmith iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="OS=10.0,name=iPhone 7 Plus" SCHEME="Locksmith iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="OS=9.0,name=iPad 2" SCHEME="Locksmith iOS" SDK=iphonesimulator9.0 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="OS=9.0,name=iPhone 6" SCHEME="Locksmith iOS" SDK=iphonesimulator9.0 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="Locksmith iOS" SDK=iphonesimulator9.0 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="OS=9.0,name=iPad 2" SCHEME="Locksmith iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="OS=9.0,name=iPhone 6" SCHEME="Locksmith iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="Locksmith iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="OS=8.1,name=iPad 2" SCHEME="Locksmith iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="OS=8.2,name=iPhone 4S" SCHEME="Locksmith iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="OS=8.3,name=iPhone 5" SCHEME="Locksmith iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="OS=8.4,name=iPhone 5S" SCHEME="Locksmith iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="OS=8.1,name=iPad 2" SCHEME="Locksmith iOS" SDK=iphonesimulator9.0 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="OS=8.2,name=iPhone 4S" SCHEME="Locksmith iOS" SDK=iphonesimulator9.0 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="OS=8.3,name=iPhone 5" SCHEME="Locksmith iOS" SDK=iphonesimulator9.0 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
- DESTINATION="OS=8.4,name=iPhone 5S" SCHEME="Locksmith iOS" SDK=iphonesimulator9.0 RUN_TESTS="YES" BUILD_EXAMPLE="NO" POD_LINT="NO"
before_install:
- gem install cocoapods --no-rdoc --no-ri --no-document --quiet
- gem install xcpretty --no-rdoc --no-ri --no-document --quiet
@@ -52,11 +46,11 @@ script:
fi
# Build example in Debug and Release
- if [ $BUILD_EXAMPLE == "YES" ]; then
- if [ $BUILD_EXAMPLE == "YES" ]; then
xcodebuild -workspace Locksmith.xcworkspace -scheme "Locksmith iOS Example" -sdk "$SDK" -destination "$DESTINATION"
-configuration Debug ONLY_ACTIVE_ARCH=NO build | xcpretty -c;
fi
- if [ $BUILD_EXAMPLE == "YES" ]; then
- if [ $BUILD_EXAMPLE == "YES" ]; then
xcodebuild -workspace Locksmith.xcworkspace -scheme "Locksmith iOS Example" -sdk "$SDK" -destination "$DESTINATION"
-configuration Release ONLY_ACTIVE_ARCH=NO build | xcpretty -c;
fi
@@ -64,4 +58,4 @@ script:
# Run pod lib lint quick if specified
- if [ $POD_LINT == "YES" ]; then
pod lib lint --quick;
fi
fi
@@ -17,9 +17,9 @@ class InterfaceController: WKInterfaceController, WCSessionDelegate {
super.willActivate()
if (WCSession.isSupported()) {
let session = WCSession.default()
let session = WCSession.defaultSession()
session.delegate = self
session.activate()
session.activateSession()
}
struct TwitterAccount: ReadableSecureStorable, CreateableSecureStorable, DeleteableSecureStorable, GenericPasswordSecureStorable {
@@ -30,7 +30,7 @@ class InterfaceController: WKInterfaceController, WCSessionDelegate {
var account: String { return username }
var data: [String: Any] {
var data: [String: AnyObject] {
return ["password": password]
}
}
@@ -48,8 +48,4 @@ class InterfaceController: WKInterfaceController, WCSessionDelegate {
// DeleteableSecureStorable lets us delete the account from the keychain
try! account.deleteFromSecureStore()
}
@available(watchOSApplicationExtension 2.2, *)
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
}
}
@@ -98,12 +98,6 @@
379DD1E5C8CDE5ABD6E50A38 /* Pods-watch.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-watch.release.xcconfig"; path = "Pods/Target Support Files/Pods-watch/Pods-watch.release.xcconfig"; sourceTree = "<group>"; };
74E67F961D2CBE4F8D171223 /* Pods-watch.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-watch.debug.xcconfig"; path = "Pods/Target Support Files/Pods-watch/Pods-watch.debug.xcconfig"; sourceTree = "<group>"; };
8D5C601685F38F2EA6AA2CA0 /* Pods-app.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.release.xcconfig"; path = "Pods/Target Support Files/Pods-app/Pods-app.release.xcconfig"; sourceTree = "<group>"; };
E3DD3B201D84354F00A59312 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
E3DD3B221D84354F00A59312 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
E3DD3B251D84354F00A59312 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
E3DD3B271D84354F00A59312 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
E3DD3B2A1D84354F00A59312 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
E3DD3B2C1D84354F00A59312 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
FFB6EBF2507E751B53E55514 /* Pods-app.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.debug.xcconfig"; path = "Pods/Target Support Files/Pods-app/Pods-app.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -154,7 +148,6 @@
0E13A9A21BA3EE8700A06FF9 /* Locksmith iOS Example */,
056F2A701BA42E3C00B24B65 /* Locksmith */,
056F2A7F1BA42E3C00B24B65 /* Locksmith Extension */,
E3DD3B1F1D84354F00A59312 /* Test Host */,
0E13A9A11BA3EE8700A06FF9 /* Products */,
74B88A8534E794C2027D6B3D /* Pods */,
D1E3110F9ED1A0EE737E7A37 /* Frameworks */,
@@ -206,19 +199,6 @@
name = Frameworks;
sourceTree = "<group>";
};
E3DD3B1F1D84354F00A59312 /* Test Host */ = {
isa = PBXGroup;
children = (
E3DD3B201D84354F00A59312 /* AppDelegate.swift */,
E3DD3B221D84354F00A59312 /* ViewController.swift */,
E3DD3B241D84354F00A59312 /* Main.storyboard */,
E3DD3B271D84354F00A59312 /* Assets.xcassets */,
E3DD3B291D84354F00A59312 /* LaunchScreen.storyboard */,
E3DD3B2C1D84354F00A59312 /* Info.plist */,
);
path = "Test Host";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -282,8 +262,7 @@
0E13A9981BA3EE8600A06FF9 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0800;
LastUpgradeCheck = 0800;
LastUpgradeCheck = 0700;
ORGANIZATIONNAME = "Matthew Palmer";
TargetAttributes = {
056F2A6E1BA42E3C00B24B65 = {
@@ -406,30 +385,14 @@
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
E3DD3B241D84354F00A59312 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
E3DD3B251D84354F00A59312 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
E3DD3B291D84354F00A59312 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
E3DD3B2A1D84354F00A59312 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
056F2A8A1BA42E3C00B24B65 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
IBSC_MODULE = Locksmith_Extension;
INFOPLIST_FILE = Locksmith/Info.plist;
PRODUCT_BUNDLE_IDENTIFIER = "net.matthewpalmer.Locksmith-iOS-Example.watchkitapp";
@@ -444,8 +407,8 @@
056F2A8B1BA42E3C00B24B65 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
IBSC_MODULE = Locksmith_Extension;
INFOPLIST_FILE = Locksmith/Info.plist;
PRODUCT_BUNDLE_IDENTIFIER = "net.matthewpalmer.Locksmith-iOS-Example.watchkitapp";
@@ -467,7 +430,6 @@
PRODUCT_NAME = "${TARGET_NAME}";
SDKROOT = watchos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = 4;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
};
@@ -483,8 +445,6 @@
PRODUCT_NAME = "${TARGET_NAME}";
SDKROOT = watchos;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = 4;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
};
@@ -583,7 +543,6 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "net.matthewpalmer.Locksmith-iOS-Example";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
@@ -597,8 +556,6 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "net.matthewpalmer.Locksmith-iOS-Example";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
};
name = Release;
};
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0720"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -12,8 +12,8 @@ import Locksmith
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
struct TwitterAccount: ReadableSecureStorable, CreateableSecureStorable, DeleteableSecureStorable, GenericPasswordSecureStorable {
let username: String
let password: String
@@ -22,7 +22,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var account: String { return username }
var data: [String: Any] {
var data: [String: AnyObject] {
return ["password": password]
}
}
@@ -1,46 +0,0 @@
//
// AppDelegate.swift
// Test Host
//
// Created by Federico Trimboli on 9/10/16.
// Copyright © 2016 Matthew Palmer. All rights reserved.
//
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
@@ -1,68 +0,0 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
@@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
@@ -1,25 +0,0 @@
//
// ViewController.swift
// Test Host
//
// Created by Federico Trimboli on 9/10/16.
// Copyright © 2016 Matthew Palmer. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "Locksmith"
s.version = "3.0.0"
s.version = "2.0.6"
s.summary = "Locksmith is a powerful, protocol-oriented library for working with the keychain in Swift."
s.description = <<-DESC
Locksmith is a powerful, protocol-oriented library for working with the iOS, Mac OS X, watchOS, and tvOS keychain in Swift. It provides extensive support for a lot of different keychain requests, and extensively uses Swift-native concepts.
+2 -198
View File
@@ -35,11 +35,6 @@
DF6BD4B91BB0524500A3EB64 /* Locksmith.h in Headers */ = {isa = PBXBuildFile; fileRef = DF6BD4B61BB051ED00A3EB64 /* Locksmith.h */; settings = {ATTRIBUTES = (Public, ); }; };
DF6BD4BC1BB054CB00A3EB64 /* Locksmith.h in Headers */ = {isa = PBXBuildFile; fileRef = DF6BD4B61BB051ED00A3EB64 /* Locksmith.h */; settings = {ATTRIBUTES = (Public, ); }; };
DF6BD4BD1BB054D400A3EB64 /* Locksmith.h in Headers */ = {isa = PBXBuildFile; fileRef = DF6BD4B61BB051ED00A3EB64 /* Locksmith.h */; settings = {ATTRIBUTES = (Public, ); }; };
E3DD3B371D84356600A59312 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3DD3B361D84356500A59312 /* AppDelegate.swift */; };
E3DD3B391D84356600A59312 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3DD3B381D84356600A59312 /* ViewController.swift */; };
E3DD3B3C1D84356600A59312 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E3DD3B3A1D84356600A59312 /* Main.storyboard */; };
E3DD3B3E1D84356600A59312 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E3DD3B3D1D84356600A59312 /* Assets.xcassets */; };
E3DD3B411D84356600A59312 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E3DD3B3F1D84356600A59312 /* LaunchScreen.storyboard */; };
FBD0C9511C18693200291F2A /* Dictionary_Initializers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EC25C401BA38539004191AF /* Dictionary_Initializers.swift */; };
FBD0C9521C18693900291F2A /* Locksmith.h in Headers */ = {isa = PBXBuildFile; fileRef = DF6BD4B61BB051ED00A3EB64 /* Locksmith.h */; settings = {ATTRIBUTES = (Public, ); }; };
FBD0C9531C18694100291F2A /* Locksmith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EC25C421BA38539004191AF /* Locksmith.swift */; };
@@ -65,13 +60,6 @@
remoteGlobalIDString = 0EC25C741BA385F6004191AF;
remoteInfo = "Locksmith OS X";
};
E3DD3B471D84360300A59312 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BFFB19C71A4870A300CCFFC3 /* Project object */;
proxyType = 1;
remoteGlobalIDString = E3DD3B331D84356500A59312;
remoteInfo = "Test Host";
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
@@ -91,14 +79,6 @@
0EC25C9E1BA389CB004191AF /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0EC25CA71BA39C9F004191AF /* Locksmith.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Locksmith.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DF6BD4B61BB051ED00A3EB64 /* Locksmith.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Locksmith.h; sourceTree = "<group>"; };
E3DD3B341D84356500A59312 /* Test Host.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Test Host.app"; sourceTree = BUILT_PRODUCTS_DIR; };
E3DD3B361D84356500A59312 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
E3DD3B381D84356600A59312 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
E3DD3B3B1D84356600A59312 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
E3DD3B3D1D84356600A59312 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
E3DD3B401D84356600A59312 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
E3DD3B421D84356600A59312 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E3DD3B461D84358100A59312 /* Test Host.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Test Host.entitlements"; sourceTree = "<group>"; };
FBD0C9491C1866BE00291F2A /* Locksmith.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Locksmith.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
@@ -140,13 +120,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
E3DD3B311D84356500A59312 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
FBD0C9451C1866BE00291F2A /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -203,7 +176,6 @@
children = (
0EC25C481BA38539004191AF /* Source */,
0EC25C4A1BA38539004191AF /* Tests */,
E3DD3B351D84356500A59312 /* Test Host */,
BFFB19D11A4870A300CCFFC3 /* Products */,
);
sourceTree = "<group>";
@@ -217,25 +189,10 @@
0EC25C7E1BA385F6004191AF /* Locksmith OS X Tests.xctest */,
0EC25CA71BA39C9F004191AF /* Locksmith.framework */,
FBD0C9491C1866BE00291F2A /* Locksmith.framework */,
E3DD3B341D84356500A59312 /* Test Host.app */,
);
name = Products;
sourceTree = "<group>";
};
E3DD3B351D84356500A59312 /* Test Host */ = {
isa = PBXGroup;
children = (
E3DD3B461D84358100A59312 /* Test Host.entitlements */,
E3DD3B361D84356500A59312 /* AppDelegate.swift */,
E3DD3B381D84356600A59312 /* ViewController.swift */,
E3DD3B3A1D84356600A59312 /* Main.storyboard */,
E3DD3B3D1D84356600A59312 /* Assets.xcassets */,
E3DD3B3F1D84356600A59312 /* LaunchScreen.storyboard */,
E3DD3B421D84356600A59312 /* Info.plist */,
);
path = "Test Host";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@@ -304,7 +261,6 @@
);
dependencies = (
0EC25C651BA385AB004191AF /* PBXTargetDependency */,
E3DD3B481D84360300A59312 /* PBXTargetDependency */,
);
name = "Locksmith iOS Tests";
productName = "Locksmith iOSTests";
@@ -365,23 +321,6 @@
productReference = 0EC25CA71BA39C9F004191AF /* Locksmith.framework */;
productType = "com.apple.product-type.framework";
};
E3DD3B331D84356500A59312 /* Test Host */ = {
isa = PBXNativeTarget;
buildConfigurationList = E3DD3B451D84356600A59312 /* Build configuration list for PBXNativeTarget "Test Host" */;
buildPhases = (
E3DD3B301D84356500A59312 /* Sources */,
E3DD3B311D84356500A59312 /* Frameworks */,
E3DD3B321D84356500A59312 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = "Test Host";
productName = "Test Host";
productReference = E3DD3B341D84356500A59312 /* Test Host.app */;
productType = "com.apple.product-type.application";
};
FBD0C9481C1866BE00291F2A /* Locksmith tvOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = FBD0C9501C1866BE00291F2A /* Build configuration list for PBXNativeTarget "Locksmith tvOS" */;
@@ -406,18 +345,15 @@
BFFB19C71A4870A300CCFFC3 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0800;
LastUpgradeCheck = 0800;
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0720;
ORGANIZATIONNAME = "Mathew Palmer";
TargetAttributes = {
0EC25C581BA385AA004191AF = {
CreatedOnToolsVersion = 7.0;
LastSwiftMigration = 0800;
};
0EC25C611BA385AB004191AF = {
CreatedOnToolsVersion = 7.0;
LastSwiftMigration = 0800;
TestTargetID = E3DD3B331D84356500A59312;
};
0EC25C741BA385F6004191AF = {
CreatedOnToolsVersion = 7.0;
@@ -428,16 +364,6 @@
0EC25CA61BA39C9F004191AF = {
CreatedOnToolsVersion = 7.0;
};
E3DD3B331D84356500A59312 = {
CreatedOnToolsVersion = 8.0;
LastSwiftMigration = 0800;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.Keychain = {
enabled = 1;
};
};
};
FBD0C9481C1866BE00291F2A = {
CreatedOnToolsVersion = 7.2;
};
@@ -449,7 +375,6 @@
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = BFFB19C61A4870A300CCFFC3;
productRefGroup = BFFB19D11A4870A300CCFFC3 /* Products */;
@@ -462,7 +387,6 @@
0EC25C7D1BA385F6004191AF /* Locksmith OS X Tests */,
0EC25CA61BA39C9F004191AF /* Locksmith watchOS */,
FBD0C9481C1866BE00291F2A /* Locksmith tvOS */,
E3DD3B331D84356500A59312 /* Test Host */,
);
};
/* End PBXProject section */
@@ -503,16 +427,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
E3DD3B321D84356500A59312 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E3DD3B411D84356600A59312 /* LaunchScreen.storyboard in Resources */,
E3DD3B3E1D84356600A59312 /* Assets.xcassets in Resources */,
E3DD3B3C1D84356600A59312 /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FBD0C9471C1866BE00291F2A /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -581,15 +495,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
E3DD3B301D84356500A59312 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E3DD3B391D84356600A59312 /* ViewController.swift in Sources */,
E3DD3B371D84356600A59312 /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FBD0C9441C1866BE00291F2A /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -617,32 +522,8 @@
target = 0EC25C741BA385F6004191AF /* Locksmith OS X */;
targetProxy = 0EC25C801BA385F6004191AF /* PBXContainerItemProxy */;
};
E3DD3B481D84360300A59312 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = E3DD3B331D84356500A59312 /* Test Host */;
targetProxy = E3DD3B471D84360300A59312 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
E3DD3B3A1D84356600A59312 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
E3DD3B3B1D84356600A59312 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
E3DD3B3F1D84356600A59312 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
E3DD3B401D84356600A59312 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
0EC25C6B1BA385AB004191AF /* Debug */ = {
isa = XCBuildConfiguration;
@@ -661,7 +542,6 @@
PRODUCT_BUNDLE_IDENTIFIER = "net.matthewpalmer.Locksmith-iOS";
PRODUCT_NAME = Locksmith;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
};
name = Debug;
};
@@ -682,8 +562,6 @@
PRODUCT_BUNDLE_IDENTIFIER = "net.matthewpalmer.Locksmith-iOS";
PRODUCT_NAME = Locksmith;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
};
name = Release;
};
@@ -698,8 +576,6 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "net.matthewpalmer.Locksmith-iOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Test Host.app/Test Host";
};
name = Debug;
};
@@ -714,9 +590,6 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "net.matthewpalmer.Locksmith-iOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Test Host.app/Test Host";
};
name = Release;
};
@@ -740,7 +613,6 @@
PRODUCT_NAME = Locksmith;
SDKROOT = macosx;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
};
name = Debug;
};
@@ -764,8 +636,6 @@
PRODUCT_NAME = Locksmith;
SDKROOT = macosx;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
};
name = Release;
};
@@ -782,7 +652,6 @@
PRODUCT_BUNDLE_IDENTIFIER = "net.matthewpalmer.Locksmith-OS-XTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SWIFT_VERSION = 3.0;
};
name = Debug;
};
@@ -799,8 +668,6 @@
PRODUCT_BUNDLE_IDENTIFIER = "net.matthewpalmer.Locksmith-OS-XTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
};
name = Release;
};
@@ -820,7 +687,6 @@
PRODUCT_NAME = Locksmith;
SDKROOT = watchos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = 4;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
};
@@ -843,8 +709,6 @@
PRODUCT_NAME = Locksmith;
SDKROOT = watchos;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = 4;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
};
@@ -854,7 +718,6 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
@@ -875,7 +738,6 @@
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
@@ -891,7 +753,6 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "";
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -905,7 +766,6 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
@@ -925,7 +785,6 @@
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
@@ -944,49 +803,6 @@
};
name = Release;
};
E3DD3B431D84356600A59312 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ANALYZER_NONNULL = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CODE_SIGN_ENTITLEMENTS = "Test Host/Test Host.entitlements";
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "Test Host/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "net.matthewpalmer.Test-Host";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_VERSION = 3.0;
};
name = Debug;
};
E3DD3B441D84356600A59312 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ANALYZER_NONNULL = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CODE_SIGN_ENTITLEMENTS = "Test Host/Test Host.entitlements";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "Test Host/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "net.matthewpalmer.Test-Host";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
};
name = Release;
};
FBD0C94E1C1866BE00291F2A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -1005,7 +821,6 @@
PRODUCT_NAME = Locksmith;
SDKROOT = appletvos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = 3;
TVOS_DEPLOYMENT_TARGET = 9.0;
};
@@ -1030,8 +845,6 @@
PRODUCT_NAME = Locksmith;
SDKROOT = appletvos;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = 3;
TVOS_DEPLOYMENT_TARGET = 9.0;
};
@@ -1094,15 +907,6 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E3DD3B451D84356600A59312 /* Build configuration list for PBXNativeTarget "Test Host" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E3DD3B431D84356600A59312 /* Debug */,
E3DD3B441D84356600A59312 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
FBD0C9501C1866BE00291F2A /* Build configuration list for PBXNativeTarget "Locksmith tvOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0720"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0720"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0720"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0720"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
+1 -11
View File
@@ -7,14 +7,6 @@ A powerful, protocol-oriented library for working with the keychain in Swift.
- [x] ⌚️ watchOS 2
- [x] 📺 tvOS
> &nbsp;
>
> 🚀 I make [Rocket](http://matthewpalmer.net/rocket?utm_source=locksmith&utm_medium=readme&utm_campaign=open_source), an app that gives you Slack-style emoji everywhere on your Mac.
>
> &nbsp;
## Details
How is Locksmith different to other keychain wrappers?
* Locksmiths API is both super-simple and deeply powerful
@@ -30,8 +22,6 @@ How is Locksmith different to other keychain wrappers?
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![Build Status](https://travis-ci.org/matthewpalmer/Locksmith.svg?branch=master)](https://travis-ci.org/matthewpalmer/Locksmith)
* Locksmith 3.0 and greater is Swift 3 compatible. See the `swift-2.3` branch for compatibility with older versions of Swift.
### CocoaPods
Locksmith is available through [CocoaPods](http://cocoapods.org).
@@ -42,7 +32,7 @@ Locksmith is available through [CocoaPods](http://cocoapods.org).
Locksmith is available through [Carthage](https://github.com/Carthage/Carthage).
github "matthewpalmer/Locksmith"
github 'matthewpalmer/Locksmith'
## Quick start
+1 -1
View File
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>3.0</string>
<string>2.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
+67 -95
View File
@@ -1,13 +1,13 @@
import Foundation
public let LocksmithDefaultService = Bundle.main.infoDictionary![String(kCFBundleIdentifierKey)] as? String ?? "com.locksmith.defaultService"
public let LocksmithDefaultService = NSBundle.mainBundle().infoDictionary![String(kCFBundleIdentifierKey)] as? String ?? "com.locksmith.defaultService"
public typealias PerformRequestClosureType = (_ requestReference: CFDictionary, _ result: inout AnyObject?) -> (OSStatus)
public typealias PerformRequestClosureType = (requestReference: CFDictionaryRef, inout result: AnyObject?) -> (OSStatus)
// MARK: - Locksmith
public struct Locksmith {
public static func loadDataForUserAccount(userAccount: String, inService service: String = LocksmithDefaultService) -> [String: Any]? {
public static func loadDataForUserAccount(userAccount: String, inService service: String = LocksmithDefaultService) -> [String: AnyObject]? {
struct ReadRequest: GenericPasswordSecureStorable, ReadableSecureStorable {
let service: String
let account: String
@@ -17,11 +17,11 @@ public struct Locksmith {
return request.readFromSecureStore()?.data
}
public static func saveData(data: [String: Any], forUserAccount userAccount: String, inService service: String = LocksmithDefaultService) throws {
public static func saveData(data: [String: AnyObject], forUserAccount userAccount: String, inService service: String = LocksmithDefaultService) throws {
struct CreateRequest: GenericPasswordSecureStorable, CreateableSecureStorable {
let service: String
let account: String
let data: [String: Any]
let data: [String: AnyObject]
}
let request = CreateRequest(service: service, account: userAccount, data: data)
@@ -38,15 +38,16 @@ public struct Locksmith {
return try request.deleteFromSecureStore()
}
public static func updateData(data: [String: Any], forUserAccount userAccount: String, inService service: String = LocksmithDefaultService) throws {
struct UpdateRequest: GenericPasswordSecureStorable, CreateableSecureStorable {
let service: String
let account: String
let data: [String: Any]
public static func updateData(data: [String: AnyObject], forUserAccount userAccount: String, inService service: String = LocksmithDefaultService) throws {
// Delete and then re-save
do {
try Locksmith.deleteDataForUserAccount(userAccount, inService: service)
} catch {
// Deletion is likely to fail if the piece of data doesn't exist yet.
// This doesn't matter--we only tell the user about errors on the save request.
}
let request = UpdateRequest(service: service, account: userAccount, data: data)
try request.updateInSecureStore()
return try Locksmith.saveData(data, forUserAccount: userAccount, inService: service)
}
}
@@ -61,7 +62,7 @@ public extension SecureStorable {
var accessible: LocksmithAccessibleOption? { return nil }
var accessGroup: String? { return nil }
var secureStorableBaseStoragePropertyDictionary: [String: Any] {
var secureStorableBaseStoragePropertyDictionary: [String: AnyObject] {
let dictionary = [
String(kSecAttrAccessGroup): accessGroup,
String(kSecAttrAccessible): accessible?.rawValue
@@ -70,13 +71,12 @@ public extension SecureStorable {
return Dictionary(withoutOptionalValues: dictionary)
}
@discardableResult
fileprivate func performSecureStorageAction(closure: PerformRequestClosureType, secureStoragePropertyDictionary: [String: Any]) throws -> [String: Any]? {
private func performSecureStorageAction(closure: PerformRequestClosureType, secureStoragePropertyDictionary: [String: AnyObject]) throws -> [String: AnyObject]? {
var result: AnyObject?
let request = secureStoragePropertyDictionary
let requestReference = request as CFDictionary
let requestReference = request as CFDictionaryRef
let status = closure(requestReference, &result)
let status = closure(requestReference: requestReference, result: &result)
let statusCode = Int(status)
@@ -97,13 +97,13 @@ public extension SecureStorable {
return nil
}
return result as? [String: Any]
return result as? [String: AnyObject]
}
}
public extension SecureStorable where Self : InternetPasswordSecureStorable {
fileprivate var internetPasswordBaseStoragePropertyDictionary: [String: Any] {
var dictionary = [String: Any]()
private var internetPasswordBaseStoragePropertyDictionary: [String: AnyObject] {
var dictionary = [String: AnyObject]()
// add in whatever turns out to be required...
dictionary[String(kSecAttrServer)] = server
@@ -112,7 +112,7 @@ public extension SecureStorable where Self : InternetPasswordSecureStorable {
dictionary[String(kSecAttrAuthenticationType)] = authenticationType.rawValue
dictionary[String(kSecAttrSecurityDomain)] = securityDomain
dictionary[String(kSecAttrPath)] = path
dictionary[String(kSecClass)] = LocksmithSecurityClass.internetPassword.rawValue
dictionary[String(kSecClass)] = LocksmithSecurityClass.InternetPassword.rawValue
let toMergeWith = [
accountSecureStoragePropertyDictionary,
@@ -138,7 +138,7 @@ public protocol AccountBasedSecureStorable {
}
public extension AccountBasedSecureStorable {
fileprivate var accountSecureStoragePropertyDictionary: [String: Any] {
private var accountSecureStoragePropertyDictionary: [String: AnyObject] {
return [String(kSecAttrAccount): account]
}
}
@@ -159,7 +159,7 @@ public protocol DescribableSecureStorable {
public extension DescribableSecureStorable {
var description: String? { return nil }
fileprivate var describableSecureStoragePropertyDictionary: [String: Any] {
private var describableSecureStoragePropertyDictionary: [String: AnyObject] {
return Dictionary(withoutOptionalValues: [
String(kSecAttrDescription): description
])
@@ -182,7 +182,7 @@ public protocol CommentableSecureStorable {
public extension CommentableSecureStorable {
var comment: String? { return nil }
fileprivate var commentableSecureStoragePropertyDictionary: [String: Any] {
private var commentableSecureStoragePropertyDictionary: [String: AnyObject] {
return Dictionary(withoutOptionalValues: [
String(kSecAttrComment): comment
])
@@ -205,7 +205,7 @@ public protocol CreatorDesignatableSecureStorable {
public extension CreatorDesignatableSecureStorable {
var creator: UInt? { return nil }
fileprivate var creatorDesignatableSecureStoragePropertyDictionary: [String: Any] {
private var creatorDesignatableSecureStoragePropertyDictionary: [String: AnyObject] {
return Dictionary(withoutOptionalValues: [String(kSecAttrCreator): creator])
}
}
@@ -226,7 +226,7 @@ public protocol LabellableSecureStorable {
public extension LabellableSecureStorable {
var label: String? { return nil }
fileprivate var labellableSecureStoragePropertyDictionary: [String: Any] {
private var labellableSecureStoragePropertyDictionary: [String: AnyObject] {
return Dictionary(withoutOptionalValues: [String(kSecAttrLabel): label])
}
}
@@ -247,7 +247,7 @@ public protocol TypeDesignatableSecureStorable {
public extension TypeDesignatableSecureStorable {
var type: UInt? { return nil }
fileprivate var typeDesignatableSecureStoragePropertyDictionary: [String: Any] {
private var typeDesignatableSecureStoragePropertyDictionary: [String: AnyObject] {
return Dictionary(withoutOptionalValues: [String(kSecAttrType): type])
}
}
@@ -267,7 +267,7 @@ public protocol IsInvisibleAssignableSecureStorable {
public extension IsInvisibleAssignableSecureStorable {
var isInvisible: Bool? { return nil }
fileprivate var isInvisibleSecureStoragePropertyDictionary: [String: Any] {
private var isInvisibleSecureStoragePropertyDictionary: [String: AnyObject] {
return Dictionary(withoutOptionalValues: [String(kSecAttrIsInvisible): isInvisible])
}
}
@@ -287,7 +287,7 @@ public protocol IsNegativeAssignableSecureStorable {
public extension IsNegativeAssignableSecureStorable {
var isNegative: Bool? { return nil }
fileprivate var isNegativeSecureStoragePropertyDictionary: [String: Any] {
private var isNegativeSecureStoragePropertyDictionary: [String: AnyObject] {
return Dictionary(withoutOptionalValues: [String(kSecAttrIsNegative): isNegative])
}
}
@@ -332,12 +332,12 @@ public extension GenericPasswordSecureStorableResultType {
}
public extension SecureStorable where Self : GenericPasswordSecureStorable {
fileprivate var genericPasswordBaseStoragePropertyDictionary: [String: Any] {
var dictionary = [String: Any?]()
private var genericPasswordBaseStoragePropertyDictionary: [String: AnyObject] {
var dictionary = [String: AnyObject?]()
dictionary[String(kSecAttrService)] = service
dictionary[String(kSecAttrGeneric)] = generic
dictionary[String(kSecClass)] = LocksmithSecurityClass.genericPassword.rawValue
dictionary[String(kSecClass)] = LocksmithSecurityClass.GenericPassword.rawValue
dictionary = Dictionary(initial: dictionary, toMerge: describableSecureStoragePropertyDictionary)
@@ -385,7 +385,7 @@ public extension InternetPasswordSecureStorableResultType {
}
var server: String {
return stringFromResultDictionary(key: kSecAttrServer)!
return stringFromResultDictionary(kSecAttrServer)!
}
var port: Int {
@@ -393,19 +393,19 @@ public extension InternetPasswordSecureStorableResultType {
}
var internetProtocol: LocksmithInternetProtocol {
return LocksmithInternetProtocol(rawValue: stringFromResultDictionary(key: kSecAttrProtocol)!)!
return LocksmithInternetProtocol(rawValue: stringFromResultDictionary(kSecAttrProtocol)!)!
}
var authenticationType: LocksmithInternetAuthenticationType {
return LocksmithInternetAuthenticationType(rawValue: stringFromResultDictionary(key: kSecAttrAuthenticationType)!)!
return LocksmithInternetAuthenticationType(rawValue: stringFromResultDictionary(kSecAttrAuthenticationType)!)!
}
var securityDomain: String? {
return stringFromResultDictionary(key: kSecAttrSecurityDomain)
return stringFromResultDictionary(kSecAttrSecurityDomain)
}
var path: String? {
return stringFromResultDictionary(key: kSecAttrPath)
return stringFromResultDictionary(kSecAttrPath)
}
}
@@ -421,10 +421,9 @@ public protocol KeySecureStorable: SecureStorable {}
/// Conformance to this protocol indicates that your type is able to be created and saved to a secure storage container.
public protocol CreateableSecureStorable: SecureStorable {
var data: [String: Any] { get }
var data: [String: AnyObject] { get }
var performCreateRequestClosure: PerformRequestClosureType { get }
func createInSecureStore() throws
func updateInSecureStore() throws
}
// MARK: - ReadableSecureStorable
@@ -436,8 +435,8 @@ public protocol ReadableSecureStorable: SecureStorable {
public extension ReadableSecureStorable {
var performReadRequestClosure: PerformRequestClosureType {
return { (requestReference: CFDictionary, result: inout AnyObject?) in
return withUnsafeMutablePointer(to: &result) { SecItemCopyMatching(requestReference, UnsafeMutablePointer($0)) }
return { (requestReference: CFDictionaryRef, inout result: AnyObject?) in
return withUnsafeMutablePointer(&result) { SecItemCopyMatching(requestReference, UnsafeMutablePointer($0)) }
}
}
@@ -448,9 +447,9 @@ public extension ReadableSecureStorable {
}
public extension ReadableSecureStorable where Self : GenericPasswordSecureStorable {
var asReadableSecureStoragePropertyDictionary: [String: Any] {
var asReadableSecureStoragePropertyDictionary: [String: AnyObject] {
var old = genericPasswordBaseStoragePropertyDictionary
old[String(kSecReturnData)] = kCFBooleanTrue
old[String(kSecReturnData)] = true
old[String(kSecMatchLimit)] = kSecMatchLimitOne
old[String(kSecReturnAttributes)] = kCFBooleanTrue
@@ -459,9 +458,9 @@ public extension ReadableSecureStorable where Self : GenericPasswordSecureStorab
}
public extension ReadableSecureStorable where Self : InternetPasswordSecureStorable {
var asReadableSecureStoragePropertyDictionary: [String: Any] {
var asReadableSecureStoragePropertyDictionary: [String: AnyObject] {
var old = internetPasswordBaseStoragePropertyDictionary
old[String(kSecReturnData)] = kCFBooleanTrue
old[String(kSecReturnData)] = true
old[String(kSecMatchLimit)] = kSecMatchLimitOne
old[String(kSecReturnAttributes)] = kCFBooleanTrue
return old
@@ -469,13 +468,13 @@ public extension ReadableSecureStorable where Self : InternetPasswordSecureStora
}
struct GenericPasswordResult: GenericPasswordSecureStorableResultType {
var resultDictionary: [String: Any]
var resultDictionary: [String: AnyObject]
}
public extension ReadableSecureStorable where Self : GenericPasswordSecureStorable {
func readFromSecureStore() -> GenericPasswordSecureStorableResultType? {
do {
if let result = try performSecureStorageAction(closure: performReadRequestClosure, secureStoragePropertyDictionary: asReadableSecureStoragePropertyDictionary) {
if let result = try performSecureStorageAction(performReadRequestClosure, secureStoragePropertyDictionary: asReadableSecureStoragePropertyDictionary) {
return GenericPasswordResult(resultDictionary: result)
} else {
return nil
@@ -489,7 +488,7 @@ public extension ReadableSecureStorable where Self : GenericPasswordSecureStorab
public extension ReadableSecureStorable where Self : InternetPasswordSecureStorable {
func readFromSecureStore() -> InternetPasswordSecureStorableResultType? {
do {
if let result = try performSecureStorageAction(closure: performReadRequestClosure, secureStoragePropertyDictionary: asReadableSecureStoragePropertyDictionary) {
if let result = try performSecureStorageAction(performReadRequestClosure, secureStoragePropertyDictionary: asReadableSecureStoragePropertyDictionary) {
return InternetPasswordResult(resultDictionary: result)
} else {
return nil
@@ -510,66 +509,39 @@ public protocol DeleteableSecureStorable: SecureStorable {
// MARK: - Default property dictionaries
extension CreateableSecureStorable {
func updateInSecureStore(query: [String: Any]) throws {
var attributesToUpdate = query
attributesToUpdate[String(kSecClass)] = nil
let status = SecItemUpdate(query as CFDictionary, attributesToUpdate as CFDictionary)
if let error = LocksmithError(fromStatusCode: Int(status)) {
if error == .notFound || error == .notAvailable {
try self.createInSecureStore()
} else {
throw error
}
} else {
if status != errSecSuccess {
throw LocksmithError.undefined
}
}
}
}
public extension CreateableSecureStorable where Self : GenericPasswordSecureStorable {
var asCreateableSecureStoragePropertyDictionary: [String: Any] {
var asCreateableSecureStoragePropertyDictionary: [String: AnyObject] {
var old = genericPasswordBaseStoragePropertyDictionary
old[String(kSecValueData)] = NSKeyedArchiver.archivedData(withRootObject: data)
old[String(kSecValueData)] = NSKeyedArchiver.archivedDataWithRootObject(data)
return old
}
}
public extension CreateableSecureStorable where Self : GenericPasswordSecureStorable {
func createInSecureStore() throws {
try performSecureStorageAction(closure: performCreateRequestClosure, secureStoragePropertyDictionary: asCreateableSecureStoragePropertyDictionary)
}
func updateInSecureStore() throws {
try self.updateInSecureStore(query: self.asCreateableSecureStoragePropertyDictionary)
try performSecureStorageAction(performCreateRequestClosure, secureStoragePropertyDictionary: asCreateableSecureStoragePropertyDictionary)
}
}
public extension CreateableSecureStorable where Self : InternetPasswordSecureStorable {
var asCreateableSecureStoragePropertyDictionary: [String: Any] {
var asCreateableSecureStoragePropertyDictionary: [String: AnyObject] {
var old = internetPasswordBaseStoragePropertyDictionary
old[String(kSecValueData)] = NSKeyedArchiver.archivedData(withRootObject: data)
old[String(kSecValueData)] = NSKeyedArchiver.archivedDataWithRootObject(data)
return old
}
}
public extension CreateableSecureStorable {
var performCreateRequestClosure: PerformRequestClosureType {
return { (requestReference: CFDictionary, result: inout AnyObject?) in
return withUnsafeMutablePointer(to: &result) { SecItemAdd(requestReference, UnsafeMutablePointer($0)) }
return { (requestReference: CFDictionaryRef, inout result: AnyObject?) in
return withUnsafeMutablePointer(&result) { SecItemAdd(requestReference, UnsafeMutablePointer($0)) }
}
}
}
public extension CreateableSecureStorable where Self : InternetPasswordSecureStorable {
func createInSecureStore() throws {
try performSecureStorageAction(closure: performCreateRequestClosure, secureStoragePropertyDictionary: asCreateableSecureStoragePropertyDictionary)
}
func updateInSecureStore() throws {
try self.updateInSecureStore(query: self.asCreateableSecureStoragePropertyDictionary)
try performSecureStorageAction(performCreateRequestClosure, secureStoragePropertyDictionary: asCreateableSecureStoragePropertyDictionary)
}
}
@@ -582,49 +554,49 @@ public extension DeleteableSecureStorable {
}
public extension DeleteableSecureStorable where Self : GenericPasswordSecureStorable {
var asDeleteableSecureStoragePropertyDictionary: [String: Any] {
var asDeleteableSecureStoragePropertyDictionary: [String: AnyObject] {
return genericPasswordBaseStoragePropertyDictionary
}
}
public extension DeleteableSecureStorable where Self : InternetPasswordSecureStorable {
var asDeleteableSecureStoragePropertyDictionary: [String: Any] {
var asDeleteableSecureStoragePropertyDictionary: [String: AnyObject] {
return internetPasswordBaseStoragePropertyDictionary
}
}
public extension DeleteableSecureStorable where Self : GenericPasswordSecureStorable {
func deleteFromSecureStore() throws {
try performSecureStorageAction(closure: performDeleteRequestClosure, secureStoragePropertyDictionary: asDeleteableSecureStoragePropertyDictionary)
try performSecureStorageAction(performDeleteRequestClosure, secureStoragePropertyDictionary: asDeleteableSecureStoragePropertyDictionary)
}
}
public extension DeleteableSecureStorable where Self : InternetPasswordSecureStorable {
func deleteFromSecureStore() throws {
try performSecureStorageAction(closure: performDeleteRequestClosure, secureStoragePropertyDictionary: asDeleteableSecureStoragePropertyDictionary)
try performSecureStorageAction(performDeleteRequestClosure, secureStoragePropertyDictionary: asDeleteableSecureStoragePropertyDictionary)
}
}
// MARK: ResultTypes
public protocol SecureStorableResultType: SecureStorable {
var resultDictionary: [String: Any] { get }
var data: [String: Any]? { get }
var resultDictionary: [String: AnyObject] { get }
var data: [String: AnyObject]? { get }
}
struct InternetPasswordResult: InternetPasswordSecureStorableResultType {
var resultDictionary: [String: Any]
var resultDictionary: [String: AnyObject]
}
public extension SecureStorableResultType {
var resultDictionary: [String: Any] {
return [String: Any]()
var resultDictionary: [String: AnyObject] {
return [String: AnyObject]()
}
var data: [String: Any]? {
var data: [String: AnyObject]? {
guard let aData = resultDictionary[String(kSecValueData)] as? NSData else {
return nil
}
return NSKeyedUnarchiver.unarchiveObject(with: aData as Data) as? [String: Any]
return NSKeyedUnarchiver.unarchiveObjectWithData(aData) as? [String: AnyObject]
}
}
+16 -16
View File
@@ -2,44 +2,44 @@ import Foundation
// MARK: Accessible
public enum LocksmithAccessibleOption: RawRepresentable {
case whenUnlocked, afterFirstUnlock, always, whenUnlockedThisDeviceOnly, afterFirstUnlockThisDeviceOnly, alwaysThisDeviceOnly, whenPasscodeSetThisDeviceOnly
case WhenUnlocked, AfterFirstUnlock, Always, WhenUnlockedThisDeviceOnly, AfterFirstUnlockThisDeviceOnly, AlwaysThisDeviceOnly, WhenPasscodeSetThisDeviceOnly
public init?(rawValue: String) {
switch rawValue {
case String(kSecAttrAccessibleWhenUnlocked):
self = .whenUnlocked
self = WhenUnlocked
case String(kSecAttrAccessibleAfterFirstUnlock):
self = .afterFirstUnlock
self = AfterFirstUnlock
case String(kSecAttrAccessibleAlways):
self = .always
self = Always
case String(kSecAttrAccessibleWhenUnlockedThisDeviceOnly):
self = .whenUnlockedThisDeviceOnly
self = WhenUnlockedThisDeviceOnly
case String(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly):
self = .afterFirstUnlockThisDeviceOnly
self = AfterFirstUnlockThisDeviceOnly
case String(kSecAttrAccessibleAlwaysThisDeviceOnly):
self = .alwaysThisDeviceOnly
self = AlwaysThisDeviceOnly
case String(kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly):
self = .whenPasscodeSetThisDeviceOnly
self = WhenPasscodeSetThisDeviceOnly
default:
self = .whenUnlocked
self = WhenUnlocked
}
}
public var rawValue: String {
switch self {
case .whenUnlocked:
case .WhenUnlocked:
return String(kSecAttrAccessibleWhenUnlocked)
case .afterFirstUnlock:
case .AfterFirstUnlock:
return String(kSecAttrAccessibleAfterFirstUnlock)
case .always:
case .Always:
return String(kSecAttrAccessibleAlways)
case .whenPasscodeSetThisDeviceOnly:
case .WhenPasscodeSetThisDeviceOnly:
return String(kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly)
case .whenUnlockedThisDeviceOnly:
case .WhenUnlockedThisDeviceOnly:
return String(kSecAttrAccessibleWhenUnlockedThisDeviceOnly)
case .afterFirstUnlockThisDeviceOnly:
case .AfterFirstUnlockThisDeviceOnly:
return String(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly)
case .alwaysThisDeviceOnly:
case .AlwaysThisDeviceOnly:
return String(kSecAttrAccessibleAlwaysThisDeviceOnly)
}
}
+24 -24
View File
@@ -1,42 +1,42 @@
import Foundation
// MARK: Locksmith Error
public enum LocksmithError: String, Error {
case allocate = "Failed to allocate memory."
case authFailed = "Authorization/Authentication failed."
case decode = "Unable to decode the provided data."
case duplicate = "The item already exists."
case interactionNotAllowed = "Interaction with the Security Server is not allowed."
case noError = "No error."
case notAvailable = "No trust results are available."
case notFound = "The item cannot be found."
case param = "One or more parameters passed to the function were not valid."
case requestNotSet = "The request was not set"
case typeNotFound = "The type was not found"
case unableToClear = "Unable to clear the keychain"
case undefined = "An undefined error occurred"
case unimplemented = "Function or operation not implemented."
public enum LocksmithError: String, ErrorType {
case Allocate = "Failed to allocate memory."
case AuthFailed = "Authorization/Authentication failed."
case Decode = "Unable to decode the provided data."
case Duplicate = "The item already exists."
case InteractionNotAllowed = "Interaction with the Security Server is not allowed."
case NoError = "No error."
case NotAvailable = "No trust results are available."
case NotFound = "The item cannot be found."
case Param = "One or more parameters passed to the function were not valid."
case RequestNotSet = "The request was not set"
case TypeNotFound = "The type was not found"
case UnableToClear = "Unable to clear the keychain"
case Undefined = "An undefined error occurred"
case Unimplemented = "Function or operation not implemented."
init?(fromStatusCode code: Int) {
switch code {
case Int(errSecAllocate):
self = .allocate
self = Allocate
case Int(errSecAuthFailed):
self = .authFailed
self = AuthFailed
case Int(errSecDecode):
self = .decode
self = Decode
case Int(errSecDuplicateItem):
self = .duplicate
self = Duplicate
case Int(errSecInteractionNotAllowed):
self = .interactionNotAllowed
self = InteractionNotAllowed
case Int(errSecItemNotFound):
self = .notFound
self = NotFound
case Int(errSecNotAvailable):
self = .notAvailable
self = NotAvailable
case Int(errSecParam):
self = .param
self = Param
case Int(errSecUnimplemented):
self = .unimplemented
self = Unimplemented
default:
return nil
}
@@ -1,48 +1,48 @@
import Foundation
public enum LocksmithInternetAuthenticationType: RawRepresentable {
case ntlm, msn, dpa, rpa, httpBasic, httpDigest, htmlForm, `default`
case NTLM, MSN, DPA, RPA, HTTPBasic, HTTPDigest, HTMLForm, Default
public init?(rawValue: String) {
switch rawValue {
case String(kSecAttrAuthenticationTypeNTLM):
self = .ntlm
self = NTLM
case String(kSecAttrAuthenticationTypeMSN):
self = .msn
self = MSN
case String(kSecAttrAuthenticationTypeDPA):
self = .dpa
self = DPA
case String(kSecAttrAuthenticationTypeRPA):
self = .rpa
self = RPA
case String(kSecAttrAuthenticationTypeHTTPBasic):
self = .httpBasic
self = HTTPBasic
case String(kSecAttrAuthenticationTypeHTTPDigest):
self = .httpDigest
self = HTTPDigest
case String(kSecAttrAuthenticationTypeHTMLForm):
self = .htmlForm
self = HTMLForm
case String(kSecAttrAuthenticationTypeDefault):
self = .default
self = Default
default:
self = .default
self = Default
}
}
public var rawValue: String {
switch self {
case .ntlm:
case .NTLM:
return String(kSecAttrAuthenticationTypeNTLM)
case .msn:
case .MSN:
return String(kSecAttrAuthenticationTypeMSN)
case .dpa:
case .DPA:
return String(kSecAttrAuthenticationTypeDPA)
case .rpa:
case .RPA:
return String(kSecAttrAuthenticationTypeRPA)
case .httpBasic:
case .HTTPBasic:
return String(kSecAttrAuthenticationTypeHTTPBasic)
case .httpDigest:
case .HTTPDigest:
return String(kSecAttrAuthenticationTypeHTTPDigest)
case .htmlForm:
case .HTMLForm:
return String(kSecAttrAuthenticationTypeHTMLForm)
case .default:
case .Default:
return String(kSecAttrAuthenticationTypeDefault)
}
}
+64 -64
View File
@@ -1,140 +1,140 @@
import Foundation
public enum LocksmithInternetProtocol: RawRepresentable {
case ftp, ftpAccount, http, irc, nntp, pop3, smtp, socks, imap, ldap, appleTalk, afp, telnet, ssh, ftps, https, httpProxy, httpsProxy, ftpProxy, smb, rtsp, rtspProxy, daap, eppc, ipp, nntps, ldaps, telnetS, imaps, ircs, pop3S
case FTP, FTPAccount, HTTP, IRC, NNTP, POP3, SMTP, SOCKS, IMAP, LDAP, AppleTalk, AFP, Telnet, SSH, FTPS, HTTPS, HTTPProxy, HTTPSProxy, FTPProxy, SMB, RTSP, RTSPProxy, DAAP, EPPC, IPP, NNTPS, LDAPS, TelnetS, IMAPS, IRCS, POP3S
public init?(rawValue: String) {
switch rawValue {
case String(kSecAttrProtocolFTP):
self = .ftp
self = FTP
case String(kSecAttrProtocolFTPAccount):
self = .ftpAccount
self = FTPAccount
case String(kSecAttrProtocolHTTP):
self = .http
self = HTTP
case String(kSecAttrProtocolIRC):
self = .irc
self = IRC
case String(kSecAttrProtocolNNTP):
self = .nntp
self = NNTP
case String(kSecAttrProtocolPOP3):
self = .pop3
self = POP3
case String(kSecAttrProtocolSMTP):
self = .smtp
self = SMTP
case String(kSecAttrProtocolSOCKS):
self = .socks
self = SOCKS
case String(kSecAttrProtocolIMAP):
self = .imap
self = IMAP
case String(kSecAttrProtocolLDAP):
self = .ldap
self = LDAP
case String(kSecAttrProtocolAppleTalk):
self = .appleTalk
self = AppleTalk
case String(kSecAttrProtocolAFP):
self = .afp
self = AFP
case String(kSecAttrProtocolTelnet):
self = .telnet
self = Telnet
case String(kSecAttrProtocolSSH):
self = .ssh
self = SSH
case String(kSecAttrProtocolFTPS):
self = .ftps
self = FTPS
case String(kSecAttrProtocolHTTPS):
self = .https
self = HTTPS
case String(kSecAttrProtocolHTTPProxy):
self = .httpProxy
self = HTTPProxy
case String(kSecAttrProtocolHTTPSProxy):
self = .httpsProxy
self = HTTPSProxy
case String(kSecAttrProtocolFTPProxy):
self = .ftpProxy
self = FTPProxy
case String(kSecAttrProtocolSMB):
self = .smb
self = SMB
case String(kSecAttrProtocolRTSP):
self = .rtsp
self = RTSP
case String(kSecAttrProtocolRTSPProxy):
self = .rtspProxy
self = RTSPProxy
case String(kSecAttrProtocolDAAP):
self = .daap
self = DAAP
case String(kSecAttrProtocolEPPC):
self = .eppc
self = EPPC
case String(kSecAttrProtocolIPP):
self = .ipp
self = IPP
case String(kSecAttrProtocolNNTPS):
self = .nntps
self = NNTPS
case String(kSecAttrProtocolLDAPS):
self = .ldaps
self = LDAPS
case String(kSecAttrProtocolTelnetS):
self = .telnetS
self = TelnetS
case String(kSecAttrProtocolIMAPS):
self = .imaps
self = IMAPS
case String(kSecAttrProtocolIRCS):
self = .ircs
self = IRCS
case String(kSecAttrProtocolPOP3S):
self = .pop3S
self = POP3S
default:
self = .http
self = HTTP
}
}
public var rawValue: String {
switch self {
case .ftp:
case .FTP:
return String(kSecAttrProtocolFTP)
case .ftpAccount:
case .FTPAccount:
return String(kSecAttrProtocolFTPAccount)
case .http:
case .HTTP:
return String(kSecAttrProtocolHTTP)
case .irc:
case .IRC:
return String(kSecAttrProtocolIRC)
case .nntp:
case .NNTP:
return String(kSecAttrProtocolNNTP)
case .pop3:
case .POP3:
return String(kSecAttrProtocolPOP3)
case .smtp:
case .SMTP:
return String(kSecAttrProtocolSMTP)
case .socks:
case .SOCKS:
return String(kSecAttrProtocolSOCKS)
case .imap:
case .IMAP:
return String(kSecAttrProtocolIMAP)
case .ldap:
case .LDAP:
return String(kSecAttrProtocolLDAP)
case .appleTalk:
case .AppleTalk:
return String(kSecAttrProtocolAppleTalk)
case .afp:
case .AFP:
return String(kSecAttrProtocolAFP)
case .telnet:
case .Telnet:
return String(kSecAttrProtocolTelnet)
case .ssh:
case .SSH:
return String(kSecAttrProtocolSSH)
case .ftps:
case .FTPS:
return String(kSecAttrProtocolFTPS)
case .https:
case .HTTPS:
return String(kSecAttrProtocolHTTPS)
case .httpProxy:
case .HTTPProxy:
return String(kSecAttrProtocolHTTPProxy)
case .httpsProxy:
case .HTTPSProxy:
return String(kSecAttrProtocolHTTPSProxy)
case .ftpProxy:
case .FTPProxy:
return String(kSecAttrProtocolFTPProxy)
case .smb:
case .SMB:
return String(kSecAttrProtocolSMB)
case .rtsp:
case .RTSP:
return String(kSecAttrProtocolRTSP)
case .rtspProxy:
case .RTSPProxy:
return String(kSecAttrProtocolRTSPProxy)
case .daap:
case .DAAP:
return String(kSecAttrProtocolDAAP)
case .eppc:
case .EPPC:
return String(kSecAttrProtocolEPPC)
case .ipp:
case .IPP:
return String(kSecAttrProtocolIPP)
case .nntps:
case .NNTPS:
return String(kSecAttrProtocolNNTPS)
case .ldaps:
case .LDAPS:
return String(kSecAttrProtocolLDAPS)
case .telnetS:
case .TelnetS:
return String(kSecAttrProtocolTelnetS)
case .imaps:
case .IMAPS:
return String(kSecAttrProtocolIMAPS)
case .ircs:
case .IRCS:
return String(kSecAttrProtocolIRCS)
case .pop3S:
case .POP3S:
return String(kSecAttrProtocolPOP3S)
}
}
+12 -12
View File
@@ -3,36 +3,36 @@ import Foundation
// With thanks to http://iosdeveloperzone.com/2014/10/22/taming-foundation-constants-into-swift-enums/
// MARK: Security Class
public enum LocksmithSecurityClass: RawRepresentable {
case genericPassword, internetPassword, certificate, key, identity
case GenericPassword, InternetPassword, Certificate, Key, Identity
public init?(rawValue: String) {
switch rawValue {
case String(kSecClassGenericPassword):
self = .genericPassword
self = GenericPassword
case String(kSecClassInternetPassword):
self = .internetPassword
self = InternetPassword
case String(kSecClassCertificate):
self = .certificate
self = Certificate
case String(kSecClassKey):
self = .key
self = Key
case String(kSecClassIdentity):
self = .identity
self = Identity
default:
self = .genericPassword
self = GenericPassword
}
}
public var rawValue: String {
switch self {
case .genericPassword:
case .GenericPassword:
return String(kSecClassGenericPassword)
case .internetPassword:
case .InternetPassword:
return String(kSecClassInternetPassword)
case .certificate:
case .Certificate:
return String(kSecClassCertificate)
case .key:
case .Key:
return String(kSecClassKey)
case .identity:
case .Identity:
return String(kSecClassIdentity)
}
}
-46
View File
@@ -1,46 +0,0 @@
//
// AppDelegate.swift
// Test Host
//
// Created by Federico Trimboli on 9/10/16.
// Copyright © 2016 Locksmith. All rights reserved.
//
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
@@ -1,68 +0,0 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
-26
View File
@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
-45
View File
@@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
-10
View File
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)net.matthewpalmer.Test-Host</string>
</array>
</dict>
</plist>
-25
View File
@@ -1,25 +0,0 @@
//
// ViewController.swift
// Test Host
//
// Created by Federico Trimboli on 9/10/16.
// Copyright © 2016 Locksmith. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
+58 -109
View File
@@ -17,8 +17,8 @@ class LocksmithTests: XCTestCase {
func clear() {
do {
try Locksmith.deleteDataForUserAccount(userAccount: userAccount, inService: service)
try Locksmith.deleteDataForUserAccount(userAccount: userAccount)
try Locksmith.deleteDataForUserAccount(userAccount, inService: service)
try Locksmith.deleteDataForUserAccount(userAccount)
} catch {
// no-op
}
@@ -34,59 +34,53 @@ class LocksmithTests: XCTestCase {
func testStaticMethods() {
let data = ["some": "data"]
try! Locksmith.saveData(data: data, forUserAccount: userAccount, inService: service)
try! Locksmith.saveData(data, forUserAccount: userAccount, inService: service)
let loaded = Locksmith.loadDataForUserAccount(userAccount: userAccount, inService: service)! as! TestingDictionaryType
let loaded = Locksmith.loadDataForUserAccount(userAccount, inService: service)! as! TestingDictionaryType
XCTAssertEqual(loaded, data)
try! Locksmith.deleteDataForUserAccount(userAccount: userAccount, inService: service)
try! Locksmith.deleteDataForUserAccount(userAccount, inService: service)
let otherData: TestingDictionaryType = ["something": "way different"]
try! Locksmith.saveData(data: otherData, forUserAccount: userAccount, inService: service)
try! Locksmith.saveData(otherData, forUserAccount: userAccount, inService: service)
let loadedAgain = Locksmith.loadDataForUserAccount(userAccount: userAccount, inService: service)! as! TestingDictionaryType
let loadedAgain = Locksmith.loadDataForUserAccount(userAccount, inService: service)! as! TestingDictionaryType
XCTAssertEqual(loadedAgain, otherData)
let updatedData = ["this update": "brings the ruckus"]
try! Locksmith.updateData(data: updatedData, forUserAccount: userAccount, inService: service)
try! Locksmith.updateData(updatedData, forUserAccount: userAccount, inService: service)
let loaded3 = Locksmith.loadDataForUserAccount(userAccount: userAccount, inService: service)! as! TestingDictionaryType
let loaded3 = Locksmith.loadDataForUserAccount(userAccount, inService: service)! as! TestingDictionaryType
XCTAssertEqual(loaded3, updatedData)
try! Locksmith.deleteDataForUserAccount(userAccount: userAccount, inService: service)
try! Locksmith.updateData(data: ["some update": "data"], forUserAccount: userAccount, inService: service)
let updateResult = Locksmith.loadDataForUserAccount(userAccount: userAccount, inService: service)! as! [String: String]
XCTAssertEqual(updateResult, ["some update": "data"])
}
func testStaticMethodsForDefaultService() {
let data = ["some": "data"]
try! Locksmith.saveData(data: data, forUserAccount: userAccount)
try! Locksmith.saveData(data, forUserAccount: userAccount)
let loaded = Locksmith.loadDataForUserAccount(userAccount: userAccount)! as! TestingDictionaryType
let loaded = Locksmith.loadDataForUserAccount(userAccount)! as! TestingDictionaryType
XCTAssertEqual(loaded, data)
try! Locksmith.deleteDataForUserAccount(userAccount: userAccount)
try! Locksmith.deleteDataForUserAccount(userAccount)
let otherData: TestingDictionaryType = ["something": "way different"]
try! Locksmith.saveData(data: otherData, forUserAccount: userAccount)
try! Locksmith.saveData(otherData, forUserAccount: userAccount)
let loadedAgain = Locksmith.loadDataForUserAccount(userAccount: userAccount)! as! TestingDictionaryType
let loadedAgain = Locksmith.loadDataForUserAccount(userAccount)! as! TestingDictionaryType
XCTAssertEqual(loadedAgain, otherData)
let updatedData = ["this update": "brings the ruckus"]
try! Locksmith.updateData(data: updatedData, forUserAccount: userAccount)
try! Locksmith.updateData(updatedData, forUserAccount: userAccount)
let loaded3 = Locksmith.loadDataForUserAccount(userAccount: userAccount)! as! TestingDictionaryType
let loaded3 = Locksmith.loadDataForUserAccount(userAccount)! as! TestingDictionaryType
XCTAssertEqual(loaded3, updatedData)
}
func createGenericPasswordWithData(_ data: [String: Any]) {
func createGenericPasswordWithData(data: [String: AnyObject]) {
struct CreateGenericPassword: CreateableSecureStorable, GenericPasswordSecureStorable {
let data: [String: Any]
let data: [String: AnyObject]
let account: String
let service: String
}
@@ -100,40 +94,6 @@ class LocksmithTests: XCTestCase {
createGenericPasswordWithData(data)
}
func testUpdateCreatesIfNotExists() {
let data = ["some": "data"]
struct CreateGenericPassword: CreateableSecureStorable, GenericPasswordSecureStorable, ReadableSecureStorable {
var data: [String: Any]
let account: String
let service: String
}
let update = CreateGenericPassword(data: data, account: userAccount, service: service)
try! update.updateInSecureStore()
let read = update.readFromSecureStore()!.data as! [String: String]
XCTAssertEqual(read, ["some": "data"])
}
func testUpdateForGenericPassword() {
let data = ["some": "data"]
struct CreateGenericPassword: CreateableSecureStorable, GenericPasswordSecureStorable, ReadableSecureStorable {
var data: [String: Any]
let account: String
let service: String
}
var create = CreateGenericPassword(data: data, account: userAccount, service: service)
try! create.createInSecureStore() // make sure it doesn't throw
create.data = ["other": "data"]
try! create.updateInSecureStore()
let read = create.readFromSecureStore()!.data as! [String: String]
XCTAssertEqual(read, ["other": "data"])
}
func testLoadForGenericPassword() {
let data = ["one": "two"]
createGenericPasswordWithData(data)
@@ -161,7 +121,7 @@ class LocksmithTests: XCTestCase {
let delete = DeleteGenericPassword(account: userAccount, service: service)
try! delete.deleteFromSecureStore()
let d = Locksmith.loadDataForUserAccount(userAccount: userAccount, inService: service)
let d = Locksmith.loadDataForUserAccount(userAccount, inService: service)
XCTAssertNil(d)
}
@@ -169,7 +129,7 @@ class LocksmithTests: XCTestCase {
struct Omnivore: ReadableSecureStorable, CreateableSecureStorable, DeleteableSecureStorable, GenericPasswordSecureStorable {
let account: String
let service: String
let data: [String: Any]
let data: [String: AnyObject]
}
let data: [String: String] = ["something": "else"]
@@ -199,7 +159,7 @@ class LocksmithTests: XCTestCase {
struct Create : CreateableSecureStorable, InternetPasswordSecureStorable {
let account: String
let server: String
let data: [String: Any]
let data: [String: AnyObject]
let port: Int
let internetProtocol: LocksmithInternetProtocol
let authenticationType: LocksmithInternetAuthenticationType
@@ -208,8 +168,8 @@ class LocksmithTests: XCTestCase {
let server = "server"
let initialData = ["one": "two"]
let port = 8080
let internetProtocol = LocksmithInternetProtocol.https
let authenticationType = LocksmithInternetAuthenticationType.dpa
let internetProtocol = LocksmithInternetProtocol.HTTPS
let authenticationType = LocksmithInternetAuthenticationType.DPA
struct Delete: DeleteableSecureStorable, InternetPasswordSecureStorable {
let account: String
@@ -247,7 +207,7 @@ class LocksmithTests: XCTestCase {
let comment: String?
let description: String?
let creator: UInt?
let data: [String: Any]
let data: [String: AnyObject]
}
let initialData = ["one": "two"]
@@ -279,7 +239,7 @@ class LocksmithTests: XCTestCase {
func testInternetPasswordMetaAttributesAreCreatedAndReturned() {
struct CreateInternetPassword: CreateableSecureStorable, InternetPasswordSecureStorable {
let account: String
var data: [String: Any]
let data: [String: AnyObject]
let server: String
let port: Int
let internetProtocol: LocksmithInternetProtocol
@@ -288,12 +248,12 @@ class LocksmithTests: XCTestCase {
let securityDomain: String?
}
let userAccount = "user \(Date())"
let userAccount = "user \(NSDate())"
let initialData = ["internet": "data"]
let server = "net.matthewpalmer"
let port = 8080
let internetProtocol = LocksmithInternetProtocol.ftp
let authenticationType = LocksmithInternetAuthenticationType.httpBasic
let internetProtocol = LocksmithInternetProtocol.FTP
let authenticationType = LocksmithInternetAuthenticationType.HTTPBasic
let path = "somePath"
let securityDomain = "someDomain"
@@ -305,36 +265,25 @@ class LocksmithTests: XCTestCase {
let authenticationType: LocksmithInternetAuthenticationType
}
var c = CreateInternetPassword(account: userAccount, data: initialData, server: server, port: port, internetProtocol: internetProtocol, authenticationType: authenticationType, path: path, securityDomain: securityDomain)
let c = CreateInternetPassword(account: userAccount, data: initialData, server: server, port: port, internetProtocol: internetProtocol, authenticationType: authenticationType, path: path, securityDomain: securityDomain)
try! c.createInSecureStore()
func assertResultMetadataIsOk(_ result: InternetPasswordSecureStorableResultType?) {
XCTAssertEqual(result?.account, userAccount)
XCTAssertEqual(result?.server, server)
XCTAssertEqual(result?.port, port)
XCTAssertEqual(result?.internetProtocol, internetProtocol)
XCTAssertEqual(result?.authenticationType, authenticationType)
XCTAssertEqual(result?.securityDomain, securityDomain)
XCTAssertEqual(result?.path, path)
}
let r = ReadInternetPassword(account: userAccount, server: server, port: port, internetProtocol: internetProtocol, authenticationType: authenticationType)
let result = r.readFromSecureStore()
XCTAssertEqual(result?.account, userAccount)
XCTAssertEqual(result!.data as! [String: String], initialData)
assertResultMetadataIsOk(result)
// Assert that metadata is maintained after an update
c.data = ["other internet": "junk"]
try! c.updateInSecureStore()
let result2 = r.readFromSecureStore()
XCTAssertEqual(result2!.data as! [String: String], ["other internet": "junk"])
assertResultMetadataIsOk(result2)
XCTAssertEqual(result?.server, server)
XCTAssertEqual(result?.port, port)
XCTAssertEqual(result?.internetProtocol, internetProtocol)
XCTAssertEqual(result?.authenticationType, authenticationType)
XCTAssertEqual(result?.securityDomain, securityDomain)
XCTAssertEqual(result?.path, path)
}
func assertStringPairsMatchInDictionary(_ dictionary: NSDictionary, pairs: [(key: CFString, expectedOutput: String)]) {
func assertStringPairsMatchInDictionary(dictionary: NSDictionary, pairs: [(key: CFString, expectedOutput: String)]) {
for pair in pairs {
let a = dictionary[String(pair.0)] as! CFString
let a = dictionary[String(pair.0)] as! CFStringRef
XCTAssertEqual(a as String, pair.1)
}
}
@@ -343,7 +292,7 @@ class LocksmithTests: XCTestCase {
struct CreateInternetPassword: CreateableSecureStorable, InternetPasswordSecureStorable, DeleteableSecureStorable {
let account: String
let service: String
let data: [String: Any]
let data: [String: AnyObject]
let server: String
let port: Int
let internetProtocol: LocksmithInternetProtocol
@@ -355,14 +304,14 @@ class LocksmithTests: XCTestCase {
let account = "myUser"
let port = 8080
let internetProtocol = LocksmithInternetProtocol.http
let authenticationType = LocksmithInternetAuthenticationType.httpBasic
let internetProtocol = LocksmithInternetProtocol.HTTP
let authenticationType = LocksmithInternetAuthenticationType.HTTPBasic
let path = "some_path"
let securityDomain = "secdomain"
let data = ["some": "data"]
let server = "server"
let expect = expectation(description: "Must enter the closure")
let expect = expectationWithDescription("Must enter the closure")
let performRequestClosure: PerformRequestClosureType = { (requestReference, result) in
let dict = requestReference as NSDictionary
@@ -377,7 +326,7 @@ class LocksmithTests: XCTestCase {
(kSecClass, String(kSecClassInternetPassword))
])
let p = dict[String(kSecAttrPort)] as! CFNumber
let p = dict[String(kSecAttrPort)] as! CFNumberRef
XCTAssertEqual(p as Int, port)
expect.fulfill()
@@ -389,12 +338,12 @@ class LocksmithTests: XCTestCase {
do { try create.deleteFromSecureStore() } catch {}
try! create.createInSecureStore()
waitForExpectations(timeout: 0.1, handler: nil)
waitForExpectationsWithTimeout(0.1, handler: nil)
}
func testGenericPasswordOptionalAttributesAreAppliedForConformingTypes() {
struct CreateGenericPassword: CreateableSecureStorable, GenericPasswordSecureStorable {
let data: [String: Any]
let data: [String: AnyObject]
let account: String
let service: String
let accessGroup: String?
@@ -406,23 +355,23 @@ class LocksmithTests: XCTestCase {
let type: UInt?
let isInvisible: Bool?
let isNegative: Bool?
let generic: Data?
let generic: NSData?
}
let data: [String: Any] = ["some": "data"]
let data: [String: AnyObject] = ["some": "data"]
let account: String = "myUser"
let service: String = "myService"
let accessGroup: String = "myAccessGroup"
let description: String = "myDescription"
let creator: UInt = 5
let accessible: LocksmithAccessibleOption = LocksmithAccessibleOption.always
let accessible: LocksmithAccessibleOption = LocksmithAccessibleOption.Always
let comment: String = "myComment"
let type: UInt = 10
let isInvisible: Bool = false
let isNegative: Bool = false
let generic: Data = Data()
let generic: NSData = NSData()
let expect = expectation(description: "Must enter the closure")
let expect = expectationWithDescription("Must enter the closure")
let performRequestClosure: PerformRequestClosureType = { (requestReference, result) in
let dict = requestReference as NSDictionary
@@ -437,20 +386,20 @@ class LocksmithTests: XCTestCase {
(kSecClass, String(kSecClassGenericPassword))
])
let cr = dict[String(kSecAttrCreator)] as! CFNumber
let cr = dict[String(kSecAttrCreator)] as! CFNumberRef
XCTAssertEqual(cr as UInt, creator)
let ty = dict[String(kSecAttrType)] as! CFNumber
let ty = dict[String(kSecAttrType)] as! CFNumberRef
XCTAssertEqual(ty as UInt, type)
let inv = dict[String(kSecAttrIsInvisible)] as! CFBoolean
let inv = dict[String(kSecAttrIsInvisible)] as! CFBooleanRef
XCTAssertEqual(inv as Bool, isInvisible)
let neg = dict[String(kSecAttrIsNegative)] as! CFBoolean
let neg = dict[String(kSecAttrIsNegative)] as! CFBooleanRef
XCTAssertEqual(neg as Bool, isNegative)
let gen = dict[String(kSecAttrGeneric)]
XCTAssertNil(gen)
let gen = dict[String(kSecAttrGeneric)] as! CFDataRef
XCTAssertEqual(gen, generic)
expect.fulfill()
@@ -461,6 +410,6 @@ class LocksmithTests: XCTestCase {
try! create.createInSecureStore()
waitForExpectations(timeout: 0.1, handler: nil)
waitForExpectationsWithTimeout(0.1, handler: nil)
}
}