Compare commits
27 Commits
2.0-appsto
...
2.0.254-ap
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
609675f663 | ||
|
|
c57bd5d5d3 | ||
|
|
a4fe13842a | ||
|
|
56bb5bf5db | ||
|
|
f720d552bb | ||
|
|
ce8a00fd48 | ||
|
|
d72defb0bc | ||
|
|
27f6bd7905 | ||
|
|
2aebcadf70 | ||
|
|
cf750f30e0 | ||
|
|
cf52221175 | ||
|
|
adc79d331b | ||
|
|
942d10e7a2 | ||
|
|
aa60dcfbe4 | ||
|
|
a831e15b3e | ||
|
|
18ae7a316f | ||
|
|
7bcc631caf | ||
|
|
caab474355 | ||
|
|
2d4e26e009 | ||
|
|
7ce8df664c | ||
|
|
6597a44096 | ||
|
|
b481af2a51 | ||
|
|
60ecd8181e | ||
|
|
31b2f22ded | ||
|
|
9d5c2e29af | ||
|
|
3740ade240 | ||
|
|
9f2c83e4a9 |
2
External/InAppSettingsKit
vendored
2
External/Pearl
vendored
2
External/UbiquityStoreManager
vendored
@@ -15,13 +15,13 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.2.1</string>
|
||||
<string>2.2.2</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>iPhoneOS</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>35</string>
|
||||
<string>36</string>
|
||||
<key>DTPlatformName</key>
|
||||
<string>iphoneos</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
|
||||
BIN
External/iOS/Crashlytics.framework/run
vendored
BIN
External/iOS/Crashlytics.framework/submit
vendored
@@ -2,11 +2,11 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.lyndir.lhunath.masterpassword" android:versionCode="1" android:versionName="GIT-SNAPSHOT">
|
||||
|
||||
<uses-sdk android:minSdkVersion="8"
|
||||
<uses-sdk android:minSdkVersion="11"
|
||||
android:targetSdkVersion="16" />
|
||||
|
||||
<application android:icon="@drawable/icon" android:label="@string/app_name">
|
||||
<activity android:name=".HelloAndroidActivity">
|
||||
<activity android:name=".UsersActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/*___Generated_by_IDEA___*/
|
||||
|
||||
package com.lyndir.lhunath.masterpassword;
|
||||
|
||||
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
|
||||
public final class BuildConfig {
|
||||
public final static boolean DEBUG = Boolean.parseBoolean(null);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/*___Generated_by_IDEA___*/
|
||||
|
||||
package com.lyndir.lhunath.masterpassword;
|
||||
|
||||
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
|
||||
public final class Manifest {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/*___Generated_by_IDEA___*/
|
||||
|
||||
package com.lyndir.lhunath.masterpassword;
|
||||
|
||||
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
|
||||
public final class R {
|
||||
}
|
||||
@@ -44,6 +44,12 @@
|
||||
<version>GIT-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.jakewharton</groupId>
|
||||
<artifactId>butterknife</artifactId>
|
||||
<version>5.1.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
|
||||
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 244 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<size
|
||||
android:width="20dp"
|
||||
android:height="20dp" />
|
||||
</shape>
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/background">
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/users"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:divider="@drawable/divider20"
|
||||
android:showDividers="middle" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp" />
|
||||
</LinearLayout>
|
||||
</HorizontalScrollView>
|
||||
</FrameLayout>
|
||||
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
>
|
||||
<TextView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/hello"
|
||||
/>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/userName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableTop="@drawable/avatar0"
|
||||
android:drawablePadding="8dp"
|
||||
android:text="Maarten Billemont" />
|
||||
@@ -2,4 +2,5 @@
|
||||
<resources>
|
||||
<string name="hello">Hello masterpassword-android!</string>
|
||||
<string name="app_name">masterpassword-android</string>
|
||||
<string name="avatar">User Avatar</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.lyndir.lhunath.masterpassword;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
public class HelloAndroidActivity extends Activity {
|
||||
|
||||
private static String TAG = "masterpassword-android";
|
||||
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
* @param savedInstanceState If the activity is being re-initialized after
|
||||
* previously being shut down then this Bundle contains the data it most
|
||||
* recently supplied in onSaveInstanceState(Bundle). <b>Note: Otherwise it is null.</b>
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
Log.i(TAG, "onCreate");
|
||||
setContentView(R.layout.main);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.lyndir.lhunath.masterpassword;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.widget.LinearLayout;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.InjectView;
|
||||
import com.lyndir.lhunath.masterpassword.model.Avatar;
|
||||
import com.lyndir.lhunath.masterpassword.model.User;
|
||||
import com.lyndir.lhunath.masterpassword.view.AvatarView;
|
||||
|
||||
|
||||
public class UsersActivity extends Activity {
|
||||
|
||||
@InjectView(R.id.users)
|
||||
LinearLayout users;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate( savedInstanceState );
|
||||
setContentView( R.layout.activity_users );
|
||||
ButterKnife.inject( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
AvatarView avatarView = new AvatarView( this );
|
||||
avatarView.setUser( new User( "Maarten Billemont", Avatar.EIGHT ) );
|
||||
users.addView( avatarView );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.lyndir.lhunath.masterpassword.model;
|
||||
|
||||
import com.lyndir.lhunath.masterpassword.R;
|
||||
|
||||
|
||||
/**
|
||||
* @author lhunath, 2014-08-20
|
||||
*/
|
||||
public enum Avatar {
|
||||
ZERO( R.drawable.avatar0 ),
|
||||
ONE( R.drawable.avatar1 ),
|
||||
TWO( R.drawable.avatar2 ),
|
||||
THREE( R.drawable.avatar3 ),
|
||||
FOUR( R.drawable.avatar4 ),
|
||||
FIVE( R.drawable.avatar5 ),
|
||||
SIX( R.drawable.avatar6 ),
|
||||
SEVEN( R.drawable.avatar7 ),
|
||||
EIGHT( R.drawable.avatar8 ),
|
||||
NINE( R.drawable.avatar9 ),
|
||||
TEN( R.drawable.avatar10 ),
|
||||
ELEVEN( R.drawable.avatar11 ),
|
||||
TWELVE( R.drawable.avatar12 ),
|
||||
THIRTEEN( R.drawable.avatar13 ),
|
||||
FOURTEEN( R.drawable.avatar14 ),
|
||||
FIFTEEN( R.drawable.avatar15 ),
|
||||
SIXTEEN( R.drawable.avatar16 ),
|
||||
SEVENTEEN( R.drawable.avatar17 ),
|
||||
EIGHTEEN( R.drawable.avatar18 );
|
||||
|
||||
private final int imageResource;
|
||||
|
||||
Avatar(final int imageResource) {
|
||||
this.imageResource = imageResource;
|
||||
}
|
||||
|
||||
public int getImageResource() {
|
||||
return imageResource;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.lyndir.lhunath.masterpassword.model;
|
||||
|
||||
/**
|
||||
* @author lhunath, 2014-08-20
|
||||
*/
|
||||
public class User {
|
||||
|
||||
private String name;
|
||||
private Avatar avatar;
|
||||
|
||||
public User(final String name, final Avatar avatar) {
|
||||
this.name = name;
|
||||
this.avatar = avatar;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Avatar getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.lyndir.lhunath.masterpassword.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
import butterknife.ButterKnife;
|
||||
import com.lyndir.lhunath.masterpassword.R;
|
||||
import com.lyndir.lhunath.masterpassword.model.User;
|
||||
|
||||
|
||||
/**
|
||||
* @author lhunath, 2014-08-20
|
||||
*/
|
||||
public class AvatarView extends FrameLayout {
|
||||
|
||||
private final TextView userName;
|
||||
|
||||
public AvatarView(final Context context) {
|
||||
super( context );
|
||||
|
||||
addView( userName = (TextView) LayoutInflater.from( context ).inflate( R.layout.view_user_avatar, this, false ) );
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
userName.setText( user.getName() );
|
||||
userName.setCompoundDrawables( null, getResources().getDrawable( user.getAvatar().getImageResource() ), null, null );
|
||||
}
|
||||
}
|
||||
@@ -22,9 +22,17 @@
|
||||
<module>masterpassword-algorithm</module>
|
||||
<module>masterpassword-cli</module>
|
||||
<module>masterpassword-gui</module>
|
||||
<!--module>masterpassword-android</module-->
|
||||
</modules>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>mod:android</id>
|
||||
<modules>
|
||||
<module>masterpassword-android</module>
|
||||
</modules>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<!-- REMOTE ARTIFACT REPOSITORIES -->
|
||||
<repositories>
|
||||
<repository>
|
||||
|
||||
@@ -22,6 +22,23 @@
|
||||
#define MPAlgorithmDefaultVersion 1
|
||||
#define MPAlgorithmDefault MPAlgorithmForVersion(MPAlgorithmDefaultVersion)
|
||||
|
||||
id<MPAlgorithm> MPAlgorithmForVersion(NSUInteger version);
|
||||
id<MPAlgorithm> MPAlgorithmDefaultForBundleVersion(NSString *bundleVersion);
|
||||
|
||||
PearlEnum( MPAttacker,
|
||||
MPAttacker1, MPAttacker5K, MPAttacker20M, MPAttacker5B );
|
||||
|
||||
typedef struct TimeToCrack {
|
||||
unsigned long long hours;
|
||||
unsigned long long days;
|
||||
unsigned long long weeks;
|
||||
unsigned long long months;
|
||||
unsigned long long years;
|
||||
unsigned long long universes;
|
||||
} TimeToCrack;
|
||||
|
||||
NSString *NSStringFromTimeToCrack(TimeToCrack timeToCrack);
|
||||
|
||||
@protocol MPAlgorithm<NSObject>
|
||||
|
||||
@required
|
||||
@@ -56,7 +73,7 @@
|
||||
usingKey:(MPKey *)elementKey;
|
||||
- (NSString *)exportContentForElement:(MPElementEntity *)element usingKey:(MPKey *)elementKey;
|
||||
|
||||
@end
|
||||
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack passwordOfType:(MPElementType)type byAttacker:(MPAttacker)attacker;
|
||||
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack passwordString:(NSString *)password byAttacker:(MPAttacker)attacker;
|
||||
|
||||
id<MPAlgorithm> MPAlgorithmForVersion(NSUInteger version);
|
||||
id<MPAlgorithm> MPAlgorithmDefaultForBundleVersion(NSString *bundleVersion);
|
||||
@end
|
||||
|
||||
@@ -38,3 +38,21 @@ id<MPAlgorithm> MPAlgorithmDefaultForBundleVersion(NSString *bundleVersion) {
|
||||
|
||||
return MPAlgorithmDefault;
|
||||
}
|
||||
|
||||
NSString *NSStringFromTimeToCrack(TimeToCrack timeToCrack) {
|
||||
|
||||
if (timeToCrack.universes > 1)
|
||||
return strl( @"> age of the universe" );
|
||||
else if (timeToCrack.years > 1)
|
||||
return strl( @"%d years", timeToCrack.years );
|
||||
else if (timeToCrack.months > 1)
|
||||
return strl( @"%d months", timeToCrack.months );
|
||||
else if (timeToCrack.weeks > 1)
|
||||
return strl( @"%d weeks", timeToCrack.weeks );
|
||||
else if (timeToCrack.days > 1)
|
||||
return strl( @"%d days", timeToCrack.days );
|
||||
else if (timeToCrack.hours > 1)
|
||||
return strl( @"%d hours", timeToCrack.hours );
|
||||
else
|
||||
return strl( @"trivial" );
|
||||
}
|
||||
|
||||
@@ -18,4 +18,11 @@
|
||||
#import "MPAlgorithm.h"
|
||||
|
||||
@interface MPAlgorithmV0 : NSObject<MPAlgorithm>
|
||||
|
||||
- (NSDictionary *)allCiphers;
|
||||
- (NSArray *)ciphersForType:(MPElementType)type;
|
||||
- (NSArray *)cipherClasses;
|
||||
- (NSArray *)cipherClassCharacters;
|
||||
- (NSString *)charactersForCipherClass:(NSString *)cipherClass;
|
||||
|
||||
@end
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
#import "MPAlgorithmV0.h"
|
||||
#import "MPEntities.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#define MP_N 32768
|
||||
#define MP_r 8
|
||||
@@ -24,7 +26,29 @@
|
||||
#define MP_dkLen 64
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
@implementation MPAlgorithmV0
|
||||
/* An AMD HD 7970 calculates 2495M SHA-1 hashes per second at a cost of ~350$ per GPU */
|
||||
#define CRACKING_PER_SECOND 2495000000UL
|
||||
#define CRACKING_PRICE 350
|
||||
|
||||
@implementation MPAlgorithmV0 {
|
||||
BN_CTX *ctx;
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
|
||||
BN_CTX_free( ctx );
|
||||
ctx = NULL;
|
||||
}
|
||||
|
||||
- (NSUInteger)version {
|
||||
|
||||
@@ -239,21 +263,21 @@
|
||||
|
||||
switch (type) {
|
||||
case MPElementTypeGeneratedMaximum:
|
||||
return MPElementTypeStoredDevicePrivate;
|
||||
case MPElementTypeGeneratedLong:
|
||||
return MPElementTypeGeneratedMaximum;
|
||||
case MPElementTypeGeneratedMedium:
|
||||
return MPElementTypeGeneratedLong;
|
||||
case MPElementTypeGeneratedBasic:
|
||||
case MPElementTypeGeneratedLong:
|
||||
return MPElementTypeGeneratedMedium;
|
||||
case MPElementTypeGeneratedShort:
|
||||
case MPElementTypeGeneratedMedium:
|
||||
return MPElementTypeGeneratedBasic;
|
||||
case MPElementTypeGeneratedPIN:
|
||||
case MPElementTypeGeneratedBasic:
|
||||
return MPElementTypeGeneratedShort;
|
||||
case MPElementTypeStoredPersonal:
|
||||
case MPElementTypeGeneratedShort:
|
||||
return MPElementTypeGeneratedPIN;
|
||||
case MPElementTypeStoredDevicePrivate:
|
||||
case MPElementTypeGeneratedPIN:
|
||||
return MPElementTypeStoredPersonal;
|
||||
case MPElementTypeStoredPersonal:
|
||||
return MPElementTypeStoredDevicePrivate;
|
||||
case MPElementTypeStoredDevicePrivate:
|
||||
return MPElementTypeGeneratedMaximum;
|
||||
default:
|
||||
return MPElementTypeGeneratedLong;
|
||||
}
|
||||
@@ -268,12 +292,41 @@
|
||||
return previousType;
|
||||
}
|
||||
|
||||
- (NSString *)generateContentNamed:(NSString *)name ofType:(MPElementType)type withCounter:(NSUInteger)counter usingKey:(MPKey *)key {
|
||||
- (NSDictionary *)allCiphers {
|
||||
|
||||
static NSDictionary *MPTypes_ciphers = nil;
|
||||
if (MPTypes_ciphers == nil)
|
||||
MPTypes_ciphers = [NSDictionary dictionaryWithContentsOfURL:
|
||||
static NSDictionary *ciphers = nil;
|
||||
static dispatch_once_t once = 0;
|
||||
dispatch_once( &once, ^{
|
||||
ciphers = [NSDictionary dictionaryWithContentsOfURL:
|
||||
[[NSBundle mainBundle] URLForResource:@"ciphers" withExtension:@"plist"]];
|
||||
} );
|
||||
|
||||
return ciphers;
|
||||
}
|
||||
|
||||
- (NSArray *)ciphersForType:(MPElementType)type {
|
||||
|
||||
NSString *typeClass = [self classNameOfType:type];
|
||||
NSString *typeName = [self nameOfType:type];
|
||||
return [[[self allCiphers] valueForKey:typeClass] valueForKey:typeName];
|
||||
}
|
||||
|
||||
- (NSArray *)cipherClasses {
|
||||
|
||||
return [[[self allCiphers] valueForKey:@"MPCharacterClasses"] allKeys];
|
||||
}
|
||||
|
||||
- (NSArray *)cipherClassCharacters {
|
||||
|
||||
return [[[self allCiphers] valueForKey:@"MPCharacterClasses"] allValues];
|
||||
}
|
||||
|
||||
- (NSString *)charactersForCipherClass:(NSString *)cipherClass {
|
||||
|
||||
return [NSNullToNil( [NSNullToNil( [[self allCiphers] valueForKey:@"MPCharacterClasses"] ) valueForKey:cipherClass] ) copy];
|
||||
}
|
||||
|
||||
- (NSString *)generateContentNamed:(NSString *)name ofType:(MPElementType)type withCounter:(NSUInteger)counter usingKey:(MPKey *)key {
|
||||
|
||||
// Determine the seed whose bytes will be used for calculating a password
|
||||
uint32_t ncounter = htonl( counter ), nnameLength = htonl( name.length );
|
||||
@@ -291,12 +344,9 @@
|
||||
|
||||
// Determine the cipher from the first seed byte.
|
||||
NSAssert( [seed length], @"Missing seed." );
|
||||
NSString *typeClass = [self classNameOfType:type];
|
||||
NSString *typeName = [self nameOfType:type];
|
||||
id classCiphers = [MPTypes_ciphers valueForKey:typeClass];
|
||||
NSArray *typeCiphers = [classCiphers valueForKey:typeName];
|
||||
NSArray *typeCiphers = [self ciphersForType:type];
|
||||
NSString *cipher = typeCiphers[htons( seedBytes[0] ) % [typeCiphers count]];
|
||||
trc( @"type %@, ciphers: %@, selected: %@", typeName, typeCiphers, cipher );
|
||||
trc( @"type %@, ciphers: %@, selected: %@", [self nameOfType:type], typeCiphers, cipher );
|
||||
|
||||
// Encode the content, character by character, using subsequent seed bytes and the cipher.
|
||||
NSAssert( [seed length] >= [cipher length] + 1, @"Insufficient seed bytes to encode cipher." );
|
||||
@@ -304,7 +354,7 @@
|
||||
for (NSUInteger c = 0; c < [cipher length]; ++c) {
|
||||
uint16_t keyByte = htons( seedBytes[c + 1] );
|
||||
NSString *cipherClass = [cipher substringWithRange:NSMakeRange( c, 1 )];
|
||||
NSString *cipherClassCharacters = [[MPTypes_ciphers valueForKey:@"MPCharacterClasses"] valueForKey:cipherClass];
|
||||
NSString *cipherClassCharacters = [self charactersForCipherClass:cipherClass];
|
||||
NSString *character = [cipherClassCharacters substringWithRange:NSMakeRange( keyByte % [cipherClassCharacters length], 1 )];
|
||||
|
||||
trc( @"class %@ has characters: %@, index: %u, selected: %@", cipherClass, cipherClassCharacters, keyByte, character );
|
||||
@@ -334,9 +384,11 @@
|
||||
}
|
||||
|
||||
case MPElementTypeStoredPersonal: {
|
||||
NSAssert( [element isKindOfClass:[MPElementStoredEntity class]],
|
||||
@"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", (long)element.type,
|
||||
[element class] );
|
||||
if (![element isKindOfClass:[MPElementStoredEntity class]]) {
|
||||
wrn( @"Element with stored type %lu is not an MPElementStoredEntity, but a %@.",
|
||||
(long)element.type, [element class] );
|
||||
break;
|
||||
}
|
||||
|
||||
NSData *encryptedContent = [[clearContent dataUsingEncoding:NSUTF8StringEncoding]
|
||||
encryptWithSymmetricKey:[elementKey subKeyOfLength:PearlCryptKeySize].keyData padding:YES];
|
||||
@@ -344,9 +396,11 @@
|
||||
break;
|
||||
}
|
||||
case MPElementTypeStoredDevicePrivate: {
|
||||
NSAssert( [element isKindOfClass:[MPElementStoredEntity class]],
|
||||
@"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", (long)element.type,
|
||||
[element class] );
|
||||
if (![element isKindOfClass:[MPElementStoredEntity class]]) {
|
||||
wrn( @"Element with stored type %lu is not an MPElementStoredEntity, but a %@.",
|
||||
(long)element.type, [element class] );
|
||||
break;
|
||||
}
|
||||
|
||||
NSData *encryptedContent = [[clearContent dataUsingEncoding:NSUTF8StringEncoding]
|
||||
encryptWithSymmetricKey:[elementKey subKeyOfLength:PearlCryptKeySize].keyData padding:YES];
|
||||
@@ -390,9 +444,11 @@
|
||||
case MPElementTypeGeneratedBasic:
|
||||
case MPElementTypeGeneratedShort:
|
||||
case MPElementTypeGeneratedPIN: {
|
||||
NSAssert( [element isKindOfClass:[MPElementGeneratedEntity class]],
|
||||
@"Element with generated type %lu is not an MPElementGeneratedEntity, but a %@.", (long)element.type,
|
||||
[element class] );
|
||||
if (![element isKindOfClass:[MPElementGeneratedEntity class]]) {
|
||||
wrn( @"Element with generated type %lu is not an MPElementGeneratedEntity, but a %@.",
|
||||
(long)element.type, [element class] );
|
||||
break;
|
||||
}
|
||||
|
||||
NSString *name = element.name;
|
||||
MPElementType type = element.type;
|
||||
@@ -413,9 +469,11 @@
|
||||
}
|
||||
|
||||
case MPElementTypeStoredPersonal: {
|
||||
NSAssert( [element isKindOfClass:[MPElementStoredEntity class]],
|
||||
@"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", (long)element.type,
|
||||
[element class] );
|
||||
if (![element isKindOfClass:[MPElementStoredEntity class]]) {
|
||||
wrn( @"Element with stored type %lu is not an MPElementStoredEntity, but a %@.",
|
||||
(long)element.type, [element class] );
|
||||
break;
|
||||
}
|
||||
|
||||
NSData *encryptedContent = ((MPElementStoredEntity *)element).contentObject;
|
||||
|
||||
@@ -456,9 +514,11 @@
|
||||
break;
|
||||
|
||||
case MPElementTypeStoredPersonal: {
|
||||
NSAssert( [element isKindOfClass:[MPElementStoredEntity class]],
|
||||
@"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", (long)element.type,
|
||||
[element class] );
|
||||
if (![element isKindOfClass:[MPElementStoredEntity class]]) {
|
||||
wrn( @"Element with stored type %lu is not an MPElementStoredEntity, but a %@.",
|
||||
(long)element.type, [element class] );
|
||||
break;
|
||||
}
|
||||
if ([importKey.keyID isEqualToData:elementKey.keyID])
|
||||
((MPElementStoredEntity *)element).contentObject = [protectedContent decodeBase64];
|
||||
|
||||
@@ -515,9 +575,11 @@
|
||||
}
|
||||
|
||||
case MPElementTypeStoredPersonal: {
|
||||
NSAssert( [element isKindOfClass:[MPElementStoredEntity class]],
|
||||
@"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", (long)element.type,
|
||||
[element class] );
|
||||
if (![element isKindOfClass:[MPElementStoredEntity class]]) {
|
||||
wrn( @"Element with stored type %lu is not an MPElementStoredEntity, but a %@.",
|
||||
(long)element.type, [element class] );
|
||||
break;
|
||||
}
|
||||
result = [((MPElementStoredEntity *)element).contentObject encodeBase64];
|
||||
break;
|
||||
}
|
||||
@@ -557,4 +619,145 @@
|
||||
return [[NSString alloc] initWithBytes:decryptedContent.bytes length:decryptedContent.length encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack passwordOfType:(MPElementType)type byAttacker:(MPAttacker)attacker {
|
||||
|
||||
if (!type)
|
||||
return NO;
|
||||
NSArray *ciphers = [self ciphersForType:type];
|
||||
if (!ciphers)
|
||||
return NO;
|
||||
|
||||
BIGNUM *permutations = BN_new(), *cipherPermutations = BN_new();
|
||||
for (NSString *cipher in ciphers) {
|
||||
BN_one( cipherPermutations );
|
||||
|
||||
for (NSUInteger c = 0; c < [cipher length]; ++c)
|
||||
BN_mul_word( cipherPermutations,
|
||||
(BN_ULONG)[[self charactersForCipherClass:[cipher substringWithRange:NSMakeRange( c, 1 )]] length] );
|
||||
|
||||
BN_add( permutations, permutations, cipherPermutations );
|
||||
}
|
||||
BN_free( cipherPermutations );
|
||||
|
||||
return [self timeToCrack:timeToCrack permutations:permutations forAttacker:attacker];
|
||||
}
|
||||
|
||||
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack passwordString:(NSString *)password byAttacker:(MPAttacker)attacker {
|
||||
|
||||
BIGNUM *permutations = BN_new();
|
||||
BN_one( permutations );
|
||||
|
||||
NSMutableString *cipher = [NSMutableString new];
|
||||
for (NSUInteger c = 0; c < [password length]; ++c) {
|
||||
NSString *passwordCharacter = [password substringWithRange:NSMakeRange( c, 1 )];
|
||||
|
||||
unsigned int characterEntropy = 0;
|
||||
for (NSString *cipherClass in @[ @"v", @"c", @"a", @"x" ]) {
|
||||
NSString *charactersForClass = [self charactersForCipherClass:cipherClass];
|
||||
|
||||
if ([charactersForClass rangeOfString:passwordCharacter].location != NSNotFound) {
|
||||
// Found class for password character.
|
||||
characterEntropy = (BN_ULONG)[charactersForClass length];
|
||||
[cipher appendString:cipherClass];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!characterEntropy) {
|
||||
[cipher appendString:@"b"];
|
||||
characterEntropy = 256 /* a byte */;
|
||||
}
|
||||
|
||||
BN_mul_word( permutations, characterEntropy );
|
||||
}
|
||||
|
||||
return [self timeToCrack:timeToCrack permutations:permutations forAttacker:attacker];
|
||||
}
|
||||
|
||||
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack permutations:(BIGNUM *)permutations forAttacker:(MPAttacker)attacker {
|
||||
|
||||
// Determine base seconds needed to calculate the permutations.
|
||||
BIGNUM *secondsToCrack = BN_dup( permutations );
|
||||
BN_div_word( secondsToCrack, CRACKING_PER_SECOND );
|
||||
|
||||
// Modify seconds needed by applying our hardware budget.
|
||||
switch (attacker) {
|
||||
case MPAttacker1:
|
||||
break;
|
||||
case MPAttacker5K:
|
||||
BN_mul_word( secondsToCrack, CRACKING_PRICE );
|
||||
BN_div_word( secondsToCrack, 5000 );
|
||||
break;
|
||||
case MPAttacker20M:
|
||||
BN_mul_word( secondsToCrack, CRACKING_PRICE );
|
||||
BN_div_word( secondsToCrack, 20000000 );
|
||||
break;
|
||||
case MPAttacker5B:
|
||||
BN_mul_word( secondsToCrack, CRACKING_PRICE );
|
||||
BN_div_word( secondsToCrack, 5000 );
|
||||
BN_div_word( secondsToCrack, 1000000 );
|
||||
break;
|
||||
}
|
||||
|
||||
BIGNUM *max = BN_new();
|
||||
BN_set_word( max, (BN_ULONG)-1 );
|
||||
|
||||
BIGNUM *hoursToCrack = BN_dup( secondsToCrack );
|
||||
BN_div_word( hoursToCrack, 3600 );
|
||||
if (BN_cmp( hoursToCrack, max ) < 0)
|
||||
timeToCrack->hours = BN_get_word( hoursToCrack );
|
||||
else
|
||||
timeToCrack->hours = (BN_ULONG)-1;
|
||||
|
||||
BIGNUM *daysToCrack = BN_dup( hoursToCrack );
|
||||
BN_div_word( daysToCrack, 24 );
|
||||
if (BN_cmp( daysToCrack, max ) < 0)
|
||||
timeToCrack->days = BN_get_word( daysToCrack );
|
||||
else
|
||||
timeToCrack->days = (BN_ULONG)-1;
|
||||
|
||||
BIGNUM *weeksToCrack = BN_dup( daysToCrack );
|
||||
BN_div_word( weeksToCrack, 7 );
|
||||
if (BN_cmp( weeksToCrack, max ) < 0)
|
||||
timeToCrack->weeks = BN_get_word( weeksToCrack );
|
||||
else
|
||||
timeToCrack->weeks = (BN_ULONG)-1;
|
||||
|
||||
BIGNUM *monthsToCrack = BN_dup( daysToCrack );
|
||||
BN_div_word( monthsToCrack, 31 );
|
||||
if (BN_cmp( monthsToCrack, max ) < 0)
|
||||
timeToCrack->months = BN_get_word( monthsToCrack );
|
||||
else
|
||||
timeToCrack->months = (BN_ULONG)-1;
|
||||
|
||||
BIGNUM *yearsToCrack = BN_dup( daysToCrack );
|
||||
BN_div_word( yearsToCrack, 356 );
|
||||
if (BN_cmp( yearsToCrack, max ) < 0)
|
||||
timeToCrack->years = BN_get_word( yearsToCrack );
|
||||
else
|
||||
timeToCrack->years = (BN_ULONG)-1;
|
||||
|
||||
BIGNUM *universesToCrack = BN_dup( yearsToCrack );
|
||||
BN_div_word( universesToCrack, 14000 );
|
||||
BN_div_word( universesToCrack, 1000000 );
|
||||
if (BN_cmp( universesToCrack, max ) < 0)
|
||||
timeToCrack->universes = BN_get_word( universesToCrack );
|
||||
else
|
||||
timeToCrack->universes = (BN_ULONG)-1;
|
||||
|
||||
for (unsigned long error = ERR_get_error(); error; error = ERR_get_error())
|
||||
err( @"bignum error: %lu", error );
|
||||
|
||||
BN_free( max );
|
||||
BN_free( permutations );
|
||||
BN_free( secondsToCrack );
|
||||
BN_free( hoursToCrack );
|
||||
BN_free( daysToCrack );
|
||||
BN_free( weeksToCrack );
|
||||
BN_free( monthsToCrack );
|
||||
BN_free( yearsToCrack );
|
||||
BN_free( universesToCrack );
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -47,18 +47,12 @@
|
||||
|
||||
- (NSString *)generateContentNamed:(NSString *)name ofType:(MPElementType)type withCounter:(NSUInteger)counter usingKey:(MPKey *)key {
|
||||
|
||||
static __strong NSDictionary *MPTypes_ciphers = nil;
|
||||
static dispatch_once_t once = 0;
|
||||
dispatch_once(&once, ^{
|
||||
MPTypes_ciphers = [NSDictionary dictionaryWithContentsOfURL:
|
||||
[[NSBundle mainBundle] URLForResource:@"ciphers" withExtension:@"plist"]];
|
||||
});
|
||||
|
||||
// Determine the seed whose bytes will be used for calculating a password
|
||||
uint32_t ncounter = htonl( counter ), nnameLength = htonl( name.length );
|
||||
NSData *counterBytes = [NSData dataWithBytes:&ncounter length:sizeof( ncounter )];
|
||||
NSData *nameLengthBytes = [NSData dataWithBytes:&nnameLength length:sizeof( nnameLength )];
|
||||
trc(@"seed from: hmac-sha256(%@, 'com.lyndir.masterpassword' | %@ | %@ | %@)", [key.keyData encodeBase64], [nameLengthBytes encodeHex], name, [counterBytes encodeHex]);
|
||||
trc( @"seed from: hmac-sha256(%@, 'com.lyndir.masterpassword' | %@ | %@ | %@)", [key.keyData encodeBase64], [nameLengthBytes encodeHex],
|
||||
name, [counterBytes encodeHex] );
|
||||
NSData *seed = [[NSData dataByConcatenatingDatas:
|
||||
[@"com.lyndir.masterpassword" dataUsingEncoding:NSUTF8StringEncoding],
|
||||
nameLengthBytes,
|
||||
@@ -71,7 +65,7 @@
|
||||
|
||||
// Determine the cipher from the first seed byte.
|
||||
NSAssert( [seed length], @"Missing seed." );
|
||||
NSArray *typeCiphers = [[MPTypes_ciphers valueForKey:[self classNameOfType:type]] valueForKey:[self nameOfType:type]];
|
||||
NSArray *typeCiphers = [self ciphersForType:type];
|
||||
NSString *cipher = typeCiphers[seedBytes[0] % [typeCiphers count]];
|
||||
trc( @"type %@, ciphers: %@, selected: %@", [self nameOfType:type], typeCiphers, cipher );
|
||||
|
||||
@@ -81,7 +75,7 @@
|
||||
for (NSUInteger c = 0; c < [cipher length]; ++c) {
|
||||
uint16_t keyByte = seedBytes[c + 1];
|
||||
NSString *cipherClass = [cipher substringWithRange:NSMakeRange( c, 1 )];
|
||||
NSString *cipherClassCharacters = [[MPTypes_ciphers valueForKey:@"MPCharacterClasses"] valueForKey:cipherClass];
|
||||
NSString *cipherClassCharacters = [self charactersForCipherClass:cipherClass];
|
||||
NSString *character = [cipherClassCharacters substringWithRange:NSMakeRange( keyByte % [cipherClassCharacters length], 1 )];
|
||||
|
||||
trc( @"class %@ has characters: %@, index: %u, selected: %@", cipherClass, cipherClassCharacters, keyByte, character );
|
||||
|
||||
@@ -31,7 +31,7 @@ typedef NS_ENUM( NSUInteger, MPImportResult ) {
|
||||
- (MPFixableResult)findAndFixInconsistenciesSaveInContext:(NSManagedObjectContext *)context;
|
||||
|
||||
/** @param completion The block to execute after adding the element, executed from the main thread with the new element in the main MOC. */
|
||||
- (void)addElementNamed:(NSString *)siteName completion:(void (^)(MPElementEntity *element))completion;
|
||||
- (void)addElementNamed:(NSString *)siteName completion:(void ( ^ )(MPElementEntity *element, NSManagedObjectContext *context))completion;
|
||||
- (MPElementEntity *)changeElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context toType:(MPElementType)type;
|
||||
- (MPImportResult)importSites:(NSString *)importedSitesString
|
||||
askImportPassword:(NSString *(^)(NSString *userName))importPassword
|
||||
|
||||
@@ -435,10 +435,10 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
|
||||
#pragma mark - Utilities
|
||||
|
||||
- (void)addElementNamed:(NSString *)siteName completion:(void ( ^ )(MPElementEntity *element))completion {
|
||||
- (void)addElementNamed:(NSString *)siteName completion:(void ( ^ )(MPElementEntity *element, NSManagedObjectContext *context))completion {
|
||||
|
||||
if (![siteName length]) {
|
||||
completion( nil );
|
||||
completion( nil, nil );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -446,7 +446,7 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
MPUserEntity *activeUser = [self activeUserInContext:context];
|
||||
NSAssert( activeUser, @"Missing user." );
|
||||
if (!activeUser) {
|
||||
completion( nil );
|
||||
completion( nil, nil );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -466,7 +466,7 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
|
||||
[context saveToStore];
|
||||
|
||||
completion( element );
|
||||
completion( element, context );
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -532,7 +532,8 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
saveInContext:(NSManagedObjectContext *)context {
|
||||
|
||||
// Compile patterns.
|
||||
static NSRegularExpression *headerPattern, *sitePattern;
|
||||
static NSRegularExpression *headerPattern;
|
||||
static NSArray *sitePatterns;
|
||||
NSError *error = nil;
|
||||
if (!headerPattern) {
|
||||
headerPattern = [[NSRegularExpression alloc]
|
||||
@@ -543,12 +544,17 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
return MPImportResultInternalError;
|
||||
}
|
||||
}
|
||||
if (!sitePattern) {
|
||||
sitePattern = [[NSRegularExpression alloc]
|
||||
initWithPattern:@"^([^[:space:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:digit:]]+)(:[[:digit:]]+)?[[:space:]]+([^\t]+)\t(.*)"
|
||||
options:(NSRegularExpressionOptions)0 error:&error];
|
||||
if (!sitePatterns) {
|
||||
sitePatterns = @[
|
||||
[[NSRegularExpression alloc] // Format 0
|
||||
initWithPattern:@"^([^ ]+) +([[:digit:]]+) +([[:digit:]]+)(:[[:digit:]]+)? +([^\t]+)\t(.*)"
|
||||
options:(NSRegularExpressionOptions)0 error:&error],
|
||||
[[NSRegularExpression alloc] // Format 1
|
||||
initWithPattern:@"^([^ ]+) +([[:digit:]]+) +([[:digit:]]+)(:[[:digit:]]+)?(:[[:digit:]]+)? +([^\t]*)\t *([^\t]+)\t(.*)"
|
||||
options:(NSRegularExpressionOptions)0 error:&error]
|
||||
];
|
||||
if (error) {
|
||||
err( @"Error loading the site pattern: %@", error );
|
||||
err( @"Error loading the site patterns: %@", error );
|
||||
return MPImportResultInternalError;
|
||||
}
|
||||
}
|
||||
@@ -557,6 +563,8 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
inf( @"Importing sites." );
|
||||
__block MPUserEntity *user = nil;
|
||||
id<MPAlgorithm> importAlgorithm = nil;
|
||||
NSUInteger importFormat = 0;
|
||||
NSUInteger importAvatar = NSNotFound;
|
||||
NSString *importBundleVersion = nil, *importUserName = nil;
|
||||
NSData *importKeyID = nil;
|
||||
BOOL headerStarted = NO, headerEnded = NO, clearText = NO;
|
||||
@@ -604,8 +612,8 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
return MPImportResultInternalError;
|
||||
}
|
||||
|
||||
user = [users count]? [users lastObject]: nil;
|
||||
dbg( @"Found user: %@", [user debugDescription] );
|
||||
user = [users lastObject];
|
||||
dbg( @"Existing user? %@", [user debugDescription] );
|
||||
}
|
||||
if ([headerName isEqualToString:@"Key ID"])
|
||||
importKeyID = [headerValue decodeHex];
|
||||
@@ -613,6 +621,15 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
importBundleVersion = headerValue;
|
||||
importAlgorithm = MPAlgorithmDefaultForBundleVersion( importBundleVersion );
|
||||
}
|
||||
if ([headerName isEqualToString:@"Format"]) {
|
||||
importFormat = [headerValue integerValue];
|
||||
if (importFormat >= [sitePatterns count]) {
|
||||
err( @"Unsupported import format: %lu", (unsigned long)importFormat );
|
||||
return MPImportResultInternalError;
|
||||
}
|
||||
}
|
||||
if ([headerName isEqualToString:@"Avatar"])
|
||||
importAvatar = [headerValue integerValue];
|
||||
if ([headerName isEqualToString:@"Passwords"]) {
|
||||
if ([headerValue isEqualToString:@"VISIBLE"])
|
||||
clearText = YES;
|
||||
@@ -628,6 +645,7 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
continue;
|
||||
|
||||
// Site
|
||||
NSRegularExpression *sitePattern = sitePatterns[importFormat];
|
||||
if ([sitePattern numberOfMatchesInString:importedSiteLine options:(NSMatchingOptions)0
|
||||
range:NSMakeRange( 0, [importedSiteLine length] )] != 1) {
|
||||
err( @"Invalid site format in line: %@", importedSiteLine );
|
||||
@@ -635,21 +653,45 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
}
|
||||
NSTextCheckingResult *siteElements = [[sitePattern matchesInString:importedSiteLine options:(NSMatchingOptions)0
|
||||
range:NSMakeRange( 0, [importedSiteLine length] )] lastObject];
|
||||
NSString *lastUsed = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:1]];
|
||||
NSString *uses = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:2]];
|
||||
NSString *type = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:3]];
|
||||
NSString *version = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:4]];
|
||||
NSString *lastUsed, *uses, *type, *version, *counter, *siteName, *loginName, *exportContent;
|
||||
switch (importFormat) {
|
||||
case 0:
|
||||
lastUsed = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:1]];
|
||||
uses = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:2]];
|
||||
type = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:3]];
|
||||
version = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:4]];
|
||||
if ([version length])
|
||||
version = [version substringFromIndex:1]; // Strip the leading colon.
|
||||
NSString *name = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:5]];
|
||||
NSString *exportContent = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:6]];
|
||||
counter = @"";
|
||||
loginName = @"";
|
||||
siteName = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:5]];
|
||||
exportContent = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:6]];
|
||||
break;
|
||||
case 1:
|
||||
lastUsed = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:1]];
|
||||
uses = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:2]];
|
||||
type = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:3]];
|
||||
version = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:4]];
|
||||
if ([version length])
|
||||
version = [version substringFromIndex:1]; // Strip the leading colon.
|
||||
counter = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:5]];
|
||||
if ([counter length])
|
||||
counter = [counter substringFromIndex:1]; // Strip the leading colon.
|
||||
loginName = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:6]];
|
||||
siteName = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:7]];
|
||||
exportContent = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:8]];
|
||||
break;
|
||||
default:
|
||||
err( @"Unexpected import format: %lu", (unsigned long)importFormat );
|
||||
return MPImportResultInternalError;
|
||||
}
|
||||
|
||||
// Find existing site.
|
||||
if (user) {
|
||||
elementFetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@ AND user == %@", name, user];
|
||||
elementFetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@ AND user == %@", siteName, user];
|
||||
NSArray *existingSites = [context executeFetchRequest:elementFetchRequest error:&error];
|
||||
if (!existingSites) {
|
||||
err( @"Lookup of existing sites failed for site: %@, user: %@, error: %@", name, user.userID, error );
|
||||
err( @"Lookup of existing sites failed for site: %@, user: %@, error: %@", siteName, user.userID, error );
|
||||
return MPImportResultInternalError;
|
||||
}
|
||||
if ([existingSites count]) {
|
||||
@@ -657,9 +699,9 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
[elementsToDelete addObjectsFromArray:existingSites];
|
||||
}
|
||||
}
|
||||
[importedSiteElements addObject:@[ lastUsed, uses, type, version, name, exportContent ]];
|
||||
dbg( @"Will import site: lastUsed=%@, uses=%@, type=%@, version=%@, name=%@, exportContent=%@",
|
||||
lastUsed, uses, type, version, name, exportContent );
|
||||
[importedSiteElements addObject:@[ lastUsed, uses, type, version, counter, loginName, siteName, exportContent ]];
|
||||
dbg( @"Will import site: lastUsed=%@, uses=%@, type=%@, version=%@, counter=%@, loginName=%@, siteName=%@, exportContent=%@",
|
||||
lastUsed, uses, type, version, counter, loginName, siteName, exportContent );
|
||||
}
|
||||
|
||||
// Ask for confirmation to import these sites and the master password of the user.
|
||||
@@ -689,10 +731,16 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
}];
|
||||
|
||||
// Make sure there is a user.
|
||||
if (!user) {
|
||||
if (user) {
|
||||
if (importAvatar != NSNotFound)
|
||||
user.avatar = importAvatar;
|
||||
dbg( @"Updating User: %@", [user debugDescription] );
|
||||
} else {
|
||||
user = [MPUserEntity insertNewObjectInContext:context];
|
||||
user.name = importUserName;
|
||||
user.keyID = importKeyID;
|
||||
if (importAvatar != NSNotFound)
|
||||
user.avatar = importAvatar;
|
||||
dbg( @"Created User: %@", [user debugDescription] );
|
||||
}
|
||||
|
||||
@@ -702,13 +750,16 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
NSUInteger uses = (unsigned)[siteElements[1] integerValue];
|
||||
MPElementType type = (MPElementType)[siteElements[2] integerValue];
|
||||
NSUInteger version = (unsigned)[siteElements[3] integerValue];
|
||||
NSString *name = siteElements[4];
|
||||
NSString *exportContent = siteElements[5];
|
||||
NSUInteger counter = [siteElements[4] length]? (unsigned)[siteElements[4] integerValue]: NSNotFound;
|
||||
NSString *loginName = [siteElements[5] length]? siteElements[5]: nil;
|
||||
NSString *siteName = siteElements[6];
|
||||
NSString *exportContent = siteElements[7];
|
||||
|
||||
// Create new site.
|
||||
NSString *typeEntityName = [MPAlgorithmForVersion( version ) classNameOfType:type];
|
||||
MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:typeEntityName inManagedObjectContext:context];
|
||||
element.name = name;
|
||||
element.name = siteName;
|
||||
element.loginName = loginName;
|
||||
element.user = user;
|
||||
element.type = type;
|
||||
element.uses = uses;
|
||||
@@ -720,6 +771,8 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
else
|
||||
[element.algorithm importProtectedContent:exportContent protectedByKey:importKey intoElement:element usingKey:userKey];
|
||||
}
|
||||
if ([element isKindOfClass:[MPElementGeneratedEntity class]] && counter != NSNotFound)
|
||||
((MPElementGeneratedEntity *)element).counter = counter;
|
||||
|
||||
dbg( @"Created Element: %@", [element debugDescription] );
|
||||
}
|
||||
@@ -751,18 +804,20 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
[export appendFormat:@"# Export of site names and stored passwords (unless device-private) encrypted with the master key.\n"];
|
||||
[export appendFormat:@"# \n"];
|
||||
[export appendFormat:@"##\n"];
|
||||
[export appendFormat:@"# Version: %@\n", [PearlInfoPlist get].CFBundleVersion];
|
||||
[export appendFormat:@"# User Name: %@\n", activeUser.name];
|
||||
[export appendFormat:@"# Avatar: %lu\n", (unsigned long)activeUser.avatar];
|
||||
[export appendFormat:@"# Key ID: %@\n", [activeUser.keyID encodeHex]];
|
||||
[export appendFormat:@"# Date: %@\n", [[NSDateFormatter rfc3339DateFormatter] stringFromDate:[NSDate date]]];
|
||||
[export appendFormat:@"# Version: %@\n", [PearlInfoPlist get].CFBundleVersion];
|
||||
[export appendFormat:@"# Format: 1\n"];
|
||||
if (revealPasswords)
|
||||
[export appendFormat:@"# Passwords: VISIBLE\n"];
|
||||
else
|
||||
[export appendFormat:@"# Passwords: PROTECTED\n"];
|
||||
[export appendFormat:@"##\n"];
|
||||
[export appendFormat:@"#\n"];
|
||||
[export appendFormat:@"# Last Times Password Site\tSite\n"];
|
||||
[export appendFormat:@"# used used type name\tpassword\n"];
|
||||
[export appendFormat:@"# Last Times Password Login\t Site\tSite\n"];
|
||||
[export appendFormat:@"# used used type name\t name\tpassword\n"];
|
||||
|
||||
// Sites.
|
||||
for (MPElementEntity *element in activeUser.elements) {
|
||||
@@ -770,9 +825,16 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
NSUInteger uses = element.uses;
|
||||
MPElementType type = element.type;
|
||||
NSUInteger version = element.version;
|
||||
NSString *name = element.name;
|
||||
NSUInteger counter = 0;
|
||||
NSString *loginName = element.loginName;
|
||||
NSString *siteName = element.name;
|
||||
NSString *content = nil;
|
||||
|
||||
// Generated-specific
|
||||
if ([element isKindOfClass:[MPElementGeneratedEntity class]])
|
||||
counter = ((MPElementGeneratedEntity *)element).counter;
|
||||
|
||||
|
||||
// Determine the content to export.
|
||||
if (!(type & MPElementFeatureDevicePrivate)) {
|
||||
if (revealPasswords)
|
||||
@@ -781,10 +843,10 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
content = [element.algorithm exportContentForElement:element usingKey:self.key];
|
||||
}
|
||||
|
||||
[export appendFormat:@"%@ %8ld %8s %20s\t%@\n",
|
||||
[export appendFormat:@"%@ %8ld %8s %25s\t%25s\t%@\n",
|
||||
[[NSDateFormatter rfc3339DateFormatter] stringFromDate:lastUsed], (long)uses,
|
||||
[strf( @"%lu:%lu", (long)type, (unsigned long)version ) UTF8String], [name UTF8String], content
|
||||
? content: @""];
|
||||
[strf( @"%lu:%lu:%lu", (long)type, (long)version, (long)counter ) UTF8String],
|
||||
[(loginName?: @"") UTF8String], [siteName UTF8String], content?: @""];
|
||||
}
|
||||
|
||||
MPCheckpoint( MPCheckpointSitesExported, @{
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
@property(nonatomic, retain) NSNumber *rememberLogin;
|
||||
@property(nonatomic, retain) NSNumber *hidePasswords;
|
||||
|
||||
@property(nonatomic, retain) NSNumber *iCloudDecided;
|
||||
@property(nonatomic, retain) NSNumber *checkInconsistency;
|
||||
|
||||
@property(nonatomic, strong) NSNumber *siteAttacker;
|
||||
|
||||
@end
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
@implementation MPConfig
|
||||
|
||||
@dynamic sendInfo, rememberLogin, iCloudDecided, checkInconsistency, hidePasswords;
|
||||
@dynamic sendInfo, rememberLogin, checkInconsistency, hidePasswords, siteAttacker;
|
||||
|
||||
- (id)init {
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
NSStringFromSelector( @selector( sendInfo ) ) : @NO,
|
||||
NSStringFromSelector( @selector( rememberLogin ) ) : @NO,
|
||||
NSStringFromSelector( @selector( hidePasswords ) ) : @NO,
|
||||
NSStringFromSelector( @selector( iCloudDecided ) ) : @NO,
|
||||
NSStringFromSelector( @selector( checkInconsistency ) ) : @NO
|
||||
NSStringFromSelector( @selector( checkInconsistency ) ) : @NO,
|
||||
NSStringFromSelector( @selector( siteAttacker ) ) : @(MPAttacker1),
|
||||
}];
|
||||
|
||||
self.delegate = [MPAppDelegate_Shared get];
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
@try {
|
||||
NSError *error = nil;
|
||||
if (!(success = [self save:&error]))
|
||||
err(@"While saving: %@", error);
|
||||
err( @"While saving: %@", [error fullDescription] );
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
success = NO;
|
||||
@@ -115,7 +115,8 @@
|
||||
- (NSString *)debugDescription {
|
||||
|
||||
return strf( @"{%@: name=%@, user=%@, type=%lu, uses=%ld, lastUsed=%@, version=%ld, loginName=%@, requiresExplicitMigration=%d}",
|
||||
NSStringFromClass( [self class] ), self.name, self.user.name, (long)self.type, (long)self.uses, self.lastUsed, (long)self.version,
|
||||
NSStringFromClass( [self class] ), self.name, self.user.name, (long)self.type, (long)self.uses, self.lastUsed,
|
||||
(long)self.version,
|
||||
self.loginName, self.requiresExplicitMigration );
|
||||
}
|
||||
|
||||
@@ -123,9 +124,11 @@
|
||||
|
||||
while (self.version < MPAlgorithmDefaultVersion)
|
||||
if ([MPAlgorithmForVersion( self.version + 1 ) migrateElement:self explicit:explicit])
|
||||
inf(@"%@ migration to version: %ld succeeded for element: %@", explicit? @"Explicit": @"Automatic", (long)self.version + 1, self);
|
||||
inf( @"%@ migration to version: %ld succeeded for element: %@",
|
||||
explicit? @"Explicit": @"Automatic", (long)self.version + 1, self );
|
||||
else {
|
||||
wrn(@"%@ migration to version: %ld failed for element: %@", explicit? @"Explicit": @"Automatic", (long)self.version + 1, self);
|
||||
wrn( @"%@ migration to version: %ld failed for element: %@",
|
||||
explicit? @"Explicit": @"Automatic", (long)self.version + 1, self );
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ static EventHotKeyID MPLockHotKey = { .signature = 'lock', .id = 1 };
|
||||
|
||||
+ (void)initialize {
|
||||
|
||||
static dispatch_once_t initialize = 0;
|
||||
dispatch_once( &initialize, ^{
|
||||
static dispatch_once_t once = 0;
|
||||
dispatch_once( &once, ^{
|
||||
[MPMacConfig get];
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
@@ -229,7 +229,7 @@
|
||||
switch (returnCode) {
|
||||
case NSAlertFirstButtonReturn: {
|
||||
// "Create" button.
|
||||
[[MPMacAppDelegate get] addElementNamed:[self.siteField stringValue] completion:^(MPElementEntity *element) {
|
||||
[[MPMacAppDelegate get] addElementNamed:[self.siteField stringValue] completion:^(MPElementEntity *element, NSManagedObjectContext *context) {
|
||||
if (element)
|
||||
PearlMainQueue( ^{ [self updateElements]; } );
|
||||
}];
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
93D39F833DEC1C89B2F795AC /* MPPasswordWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39A57A7823DE98A0FF83C /* MPPasswordWindowController.m */; };
|
||||
DA0933CC1747AD2D00DE1CEF /* shot-laptop-leaning-iphone.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0933CB1747AD2D00DE1CEF /* shot-laptop-leaning-iphone.png */; };
|
||||
DA0933D01747B91B00DE1CEF /* appstore.png in Resources */ = {isa = PBXBuildFile; fileRef = DA0933CF1747B91B00DE1CEF /* appstore.png */; };
|
||||
DA10007F1998A4C6002B873F /* scrypt in Headers */ = {isa = PBXBuildFile; fileRef = DAE8E65619867AF500416A0F /* scrypt */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
DA1000801998A4C6002B873F /* openssl in Headers */ = {isa = PBXBuildFile; fileRef = DAE8E65719867AF500416A0F /* openssl */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
DA16B33F170661D4000A0EAB /* libUbiquityStoreManager.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA4425CB1557BED40052177D /* libUbiquityStoreManager.a */; };
|
||||
DA16B341170661DB000A0EAB /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA16B340170661DB000A0EAB /* Carbon.framework */; };
|
||||
DA16B342170661E0000A0EAB /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC632871486D95D0075AEA5 /* Security.framework */; };
|
||||
@@ -137,87 +139,7 @@
|
||||
DACA299A1705E2BD002C6C22 /* JRSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = DACA298C1705E2BD002C6C22 /* JRSwizzle.m */; };
|
||||
DAD9B5F01762CAA4001835F9 /* ServiceManagement.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAD9B5EF1762CAA4001835F9 /* ServiceManagement.framework */; };
|
||||
DAD9B5F11762CAB9001835F9 /* MasterPassword-Mac-LoginHelper.app in Copy LoginHelper */ = {isa = PBXBuildFile; fileRef = DAD9B5E6176299BA001835F9 /* MasterPassword-Mac-LoginHelper.app */; };
|
||||
DAEB93D918AB0FFD000490CC /* aes.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB938718AB0FFD000490CC /* aes.h */; };
|
||||
DAEB93DA18AB0FFD000490CC /* asn1.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB938818AB0FFD000490CC /* asn1.h */; };
|
||||
DAEB93DB18AB0FFD000490CC /* asn1_mac.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB938918AB0FFD000490CC /* asn1_mac.h */; };
|
||||
DAEB93DC18AB0FFD000490CC /* asn1t.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB938A18AB0FFD000490CC /* asn1t.h */; };
|
||||
DAEB93DD18AB0FFD000490CC /* bio.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB938B18AB0FFD000490CC /* bio.h */; };
|
||||
DAEB93DE18AB0FFD000490CC /* blowfish.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB938C18AB0FFD000490CC /* blowfish.h */; };
|
||||
DAEB93DF18AB0FFD000490CC /* bn.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB938D18AB0FFD000490CC /* bn.h */; };
|
||||
DAEB93E018AB0FFD000490CC /* buffer.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB938E18AB0FFD000490CC /* buffer.h */; };
|
||||
DAEB93E118AB0FFD000490CC /* camellia.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB938F18AB0FFD000490CC /* camellia.h */; };
|
||||
DAEB93E218AB0FFD000490CC /* cast.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB939018AB0FFD000490CC /* cast.h */; };
|
||||
DAEB93E318AB0FFD000490CC /* cms.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB939118AB0FFD000490CC /* cms.h */; };
|
||||
DAEB93E418AB0FFD000490CC /* comp.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB939218AB0FFD000490CC /* comp.h */; };
|
||||
DAEB93E518AB0FFD000490CC /* conf.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB939318AB0FFD000490CC /* conf.h */; };
|
||||
DAEB93E618AB0FFD000490CC /* conf_api.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB939418AB0FFD000490CC /* conf_api.h */; };
|
||||
DAEB93E718AB0FFD000490CC /* crypto.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB939518AB0FFD000490CC /* crypto.h */; };
|
||||
DAEB93E818AB0FFD000490CC /* des.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB939618AB0FFD000490CC /* des.h */; };
|
||||
DAEB93E918AB0FFD000490CC /* des_old.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB939718AB0FFD000490CC /* des_old.h */; };
|
||||
DAEB93EA18AB0FFD000490CC /* dh.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB939818AB0FFD000490CC /* dh.h */; };
|
||||
DAEB93EB18AB0FFD000490CC /* dsa.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB939918AB0FFD000490CC /* dsa.h */; };
|
||||
DAEB93EC18AB0FFD000490CC /* dso.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB939A18AB0FFD000490CC /* dso.h */; };
|
||||
DAEB93ED18AB0FFD000490CC /* dtls1.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB939B18AB0FFD000490CC /* dtls1.h */; };
|
||||
DAEB93EE18AB0FFD000490CC /* e_os2.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB939C18AB0FFD000490CC /* e_os2.h */; };
|
||||
DAEB93EF18AB0FFD000490CC /* ebcdic.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB939D18AB0FFD000490CC /* ebcdic.h */; };
|
||||
DAEB93F018AB0FFD000490CC /* ec.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB939E18AB0FFD000490CC /* ec.h */; };
|
||||
DAEB93F118AB0FFD000490CC /* ecdh.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB939F18AB0FFD000490CC /* ecdh.h */; };
|
||||
DAEB93F218AB0FFD000490CC /* ecdsa.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93A018AB0FFD000490CC /* ecdsa.h */; };
|
||||
DAEB93F318AB0FFD000490CC /* engine.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93A118AB0FFD000490CC /* engine.h */; };
|
||||
DAEB93F418AB0FFD000490CC /* err.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93A218AB0FFD000490CC /* err.h */; };
|
||||
DAEB93F518AB0FFD000490CC /* evp.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93A318AB0FFD000490CC /* evp.h */; };
|
||||
DAEB93F618AB0FFD000490CC /* hmac.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93A418AB0FFD000490CC /* hmac.h */; };
|
||||
DAEB93F718AB0FFD000490CC /* idea.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93A518AB0FFD000490CC /* idea.h */; };
|
||||
DAEB93F818AB0FFD000490CC /* krb5_asn.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93A618AB0FFD000490CC /* krb5_asn.h */; };
|
||||
DAEB93F918AB0FFD000490CC /* kssl.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93A718AB0FFD000490CC /* kssl.h */; };
|
||||
DAEB93FA18AB0FFD000490CC /* lhash.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93A818AB0FFD000490CC /* lhash.h */; };
|
||||
DAEB93FB18AB0FFD000490CC /* md4.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93A918AB0FFD000490CC /* md4.h */; };
|
||||
DAEB93FC18AB0FFD000490CC /* md5.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93AA18AB0FFD000490CC /* md5.h */; };
|
||||
DAEB93FD18AB0FFD000490CC /* mdc2.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93AB18AB0FFD000490CC /* mdc2.h */; };
|
||||
DAEB93FE18AB0FFD000490CC /* modes.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93AC18AB0FFD000490CC /* modes.h */; };
|
||||
DAEB93FF18AB0FFD000490CC /* obj_mac.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93AD18AB0FFD000490CC /* obj_mac.h */; };
|
||||
DAEB940018AB0FFD000490CC /* objects.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93AE18AB0FFD000490CC /* objects.h */; };
|
||||
DAEB940118AB0FFD000490CC /* ocsp.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93AF18AB0FFD000490CC /* ocsp.h */; };
|
||||
DAEB940218AB0FFD000490CC /* opensslconf.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93B018AB0FFD000490CC /* opensslconf.h */; };
|
||||
DAEB940318AB0FFD000490CC /* opensslv.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93B118AB0FFD000490CC /* opensslv.h */; };
|
||||
DAEB940418AB0FFD000490CC /* ossl_typ.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93B218AB0FFD000490CC /* ossl_typ.h */; };
|
||||
DAEB940518AB0FFD000490CC /* pem.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93B318AB0FFD000490CC /* pem.h */; };
|
||||
DAEB940618AB0FFD000490CC /* pem2.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93B418AB0FFD000490CC /* pem2.h */; };
|
||||
DAEB940718AB0FFD000490CC /* pkcs12.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93B518AB0FFD000490CC /* pkcs12.h */; };
|
||||
DAEB940818AB0FFD000490CC /* pkcs7.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93B618AB0FFD000490CC /* pkcs7.h */; };
|
||||
DAEB940918AB0FFD000490CC /* pqueue.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93B718AB0FFD000490CC /* pqueue.h */; };
|
||||
DAEB940A18AB0FFD000490CC /* rand.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93B818AB0FFD000490CC /* rand.h */; };
|
||||
DAEB940B18AB0FFD000490CC /* rc2.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93B918AB0FFD000490CC /* rc2.h */; };
|
||||
DAEB940C18AB0FFD000490CC /* rc4.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93BA18AB0FFD000490CC /* rc4.h */; };
|
||||
DAEB940D18AB0FFD000490CC /* ripemd.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93BB18AB0FFD000490CC /* ripemd.h */; };
|
||||
DAEB940E18AB0FFD000490CC /* rsa.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93BC18AB0FFD000490CC /* rsa.h */; };
|
||||
DAEB940F18AB0FFD000490CC /* safestack.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93BD18AB0FFD000490CC /* safestack.h */; };
|
||||
DAEB941018AB0FFD000490CC /* seed.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93BE18AB0FFD000490CC /* seed.h */; };
|
||||
DAEB941118AB0FFD000490CC /* sha.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93BF18AB0FFD000490CC /* sha.h */; };
|
||||
DAEB941218AB0FFD000490CC /* ssl.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93C018AB0FFD000490CC /* ssl.h */; };
|
||||
DAEB941318AB0FFD000490CC /* ssl2.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93C118AB0FFD000490CC /* ssl2.h */; };
|
||||
DAEB941418AB0FFD000490CC /* ssl23.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93C218AB0FFD000490CC /* ssl23.h */; };
|
||||
DAEB941518AB0FFD000490CC /* ssl3.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93C318AB0FFD000490CC /* ssl3.h */; };
|
||||
DAEB941618AB0FFD000490CC /* stack.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93C418AB0FFD000490CC /* stack.h */; };
|
||||
DAEB941718AB0FFD000490CC /* symhacks.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93C518AB0FFD000490CC /* symhacks.h */; };
|
||||
DAEB941818AB0FFD000490CC /* tls1.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93C618AB0FFD000490CC /* tls1.h */; };
|
||||
DAEB941918AB0FFD000490CC /* ts.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93C718AB0FFD000490CC /* ts.h */; };
|
||||
DAEB941A18AB0FFD000490CC /* txt_db.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93C818AB0FFD000490CC /* txt_db.h */; };
|
||||
DAEB941B18AB0FFD000490CC /* ui.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93C918AB0FFD000490CC /* ui.h */; };
|
||||
DAEB941C18AB0FFD000490CC /* ui_compat.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93CA18AB0FFD000490CC /* ui_compat.h */; };
|
||||
DAEB941D18AB0FFD000490CC /* whrlpool.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93CB18AB0FFD000490CC /* whrlpool.h */; };
|
||||
DAEB941E18AB0FFD000490CC /* x509.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93CC18AB0FFD000490CC /* x509.h */; };
|
||||
DAEB941F18AB0FFD000490CC /* x509_vfy.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93CD18AB0FFD000490CC /* x509_vfy.h */; };
|
||||
DAEB942018AB0FFD000490CC /* x509v3.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93CE18AB0FFD000490CC /* x509v3.h */; };
|
||||
DAEB942118AB0FFD000490CC /* crypto_aesctr.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93D018AB0FFD000490CC /* crypto_aesctr.h */; };
|
||||
DAEB942218AB0FFD000490CC /* crypto_scrypt.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93D118AB0FFD000490CC /* crypto_scrypt.h */; };
|
||||
DAEB942318AB0FFD000490CC /* memlimit.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93D218AB0FFD000490CC /* memlimit.h */; };
|
||||
DAEB942418AB0FFD000490CC /* readpass.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93D318AB0FFD000490CC /* readpass.h */; };
|
||||
DAEB942518AB0FFD000490CC /* scryptenc.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93D418AB0FFD000490CC /* scryptenc.h */; };
|
||||
DAEB942618AB0FFD000490CC /* scryptenc_cpuperf.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93D518AB0FFD000490CC /* scryptenc_cpuperf.h */; };
|
||||
DAEB942718AB0FFD000490CC /* sha256.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93D618AB0FFD000490CC /* sha256.h */; };
|
||||
DAEB942818AB0FFD000490CC /* sysendian.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93D718AB0FFD000490CC /* sysendian.h */; };
|
||||
DAEB942918AB0FFD000490CC /* warn.h in Headers */ = {isa = PBXBuildFile; fileRef = DAEB93D818AB0FFD000490CC /* warn.h */; };
|
||||
DAE8E65519867AE200416A0F /* libopensslcrypto-osx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAE8E65319867ADA00416A0F /* libopensslcrypto-osx.a */; };
|
||||
DAEB942E18B47FB3000490CC /* MPInitialWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA0933C91747A56A00DE1CEF /* MPInitialWindow.xib */; };
|
||||
DAF4EF56190A828100023C90 /* Exo2.0-Thin.otf in Resources */ = {isa = PBXBuildFile; fileRef = DAF4EF52190A828100023C90 /* Exo2.0-Thin.otf */; };
|
||||
DAF4EF57190A828100023C90 /* Exo2.0-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = DAF4EF53190A828100023C90 /* Exo2.0-Regular.otf */; };
|
||||
@@ -350,7 +272,6 @@
|
||||
DA30E9D615723E6900A68B4C /* PearlLazy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlLazy.m; sourceTree = "<group>"; };
|
||||
DA3509FC15F101A500C14A8E /* PearlQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlQueue.h; sourceTree = "<group>"; };
|
||||
DA3509FD15F101A500C14A8E /* PearlQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlQueue.m; sourceTree = "<group>"; };
|
||||
DA3B8448190FC5A900246EEA /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Crashlytics.framework; sourceTree = "<group>"; };
|
||||
DA3B844A190FC5A900246EEA /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Crashlytics.framework; sourceTree = "<group>"; };
|
||||
DA3B8450190FC86F00246EEA /* NSManagedObject+Pearl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObject+Pearl.m"; sourceTree = "<group>"; };
|
||||
DA3B8451190FC86F00246EEA /* NSManagedObject+Pearl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObject+Pearl.h"; sourceTree = "<group>"; };
|
||||
@@ -877,87 +798,9 @@
|
||||
DAD312C01552A20800A3F9ED /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; };
|
||||
DAD9B5E1176299B9001835F9 /* MasterPassword-Mac-LoginHelper.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "MasterPassword-Mac-LoginHelper.xcodeproj"; path = "MasterPassword-Mac-LoginHelper/MasterPassword-Mac-LoginHelper.xcodeproj"; sourceTree = "<group>"; };
|
||||
DAD9B5EF1762CAA4001835F9 /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; };
|
||||
DAEB938718AB0FFD000490CC /* aes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes.h; sourceTree = "<group>"; };
|
||||
DAEB938818AB0FFD000490CC /* asn1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = asn1.h; sourceTree = "<group>"; };
|
||||
DAEB938918AB0FFD000490CC /* asn1_mac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = asn1_mac.h; sourceTree = "<group>"; };
|
||||
DAEB938A18AB0FFD000490CC /* asn1t.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = asn1t.h; sourceTree = "<group>"; };
|
||||
DAEB938B18AB0FFD000490CC /* bio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bio.h; sourceTree = "<group>"; };
|
||||
DAEB938C18AB0FFD000490CC /* blowfish.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blowfish.h; sourceTree = "<group>"; };
|
||||
DAEB938D18AB0FFD000490CC /* bn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bn.h; sourceTree = "<group>"; };
|
||||
DAEB938E18AB0FFD000490CC /* buffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = buffer.h; sourceTree = "<group>"; };
|
||||
DAEB938F18AB0FFD000490CC /* camellia.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = camellia.h; sourceTree = "<group>"; };
|
||||
DAEB939018AB0FFD000490CC /* cast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cast.h; sourceTree = "<group>"; };
|
||||
DAEB939118AB0FFD000490CC /* cms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cms.h; sourceTree = "<group>"; };
|
||||
DAEB939218AB0FFD000490CC /* comp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = comp.h; sourceTree = "<group>"; };
|
||||
DAEB939318AB0FFD000490CC /* conf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = conf.h; sourceTree = "<group>"; };
|
||||
DAEB939418AB0FFD000490CC /* conf_api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = conf_api.h; sourceTree = "<group>"; };
|
||||
DAEB939518AB0FFD000490CC /* crypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto.h; sourceTree = "<group>"; };
|
||||
DAEB939618AB0FFD000490CC /* des.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = des.h; sourceTree = "<group>"; };
|
||||
DAEB939718AB0FFD000490CC /* des_old.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = des_old.h; sourceTree = "<group>"; };
|
||||
DAEB939818AB0FFD000490CC /* dh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dh.h; sourceTree = "<group>"; };
|
||||
DAEB939918AB0FFD000490CC /* dsa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dsa.h; sourceTree = "<group>"; };
|
||||
DAEB939A18AB0FFD000490CC /* dso.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dso.h; sourceTree = "<group>"; };
|
||||
DAEB939B18AB0FFD000490CC /* dtls1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dtls1.h; sourceTree = "<group>"; };
|
||||
DAEB939C18AB0FFD000490CC /* e_os2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = e_os2.h; sourceTree = "<group>"; };
|
||||
DAEB939D18AB0FFD000490CC /* ebcdic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ebcdic.h; sourceTree = "<group>"; };
|
||||
DAEB939E18AB0FFD000490CC /* ec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ec.h; sourceTree = "<group>"; };
|
||||
DAEB939F18AB0FFD000490CC /* ecdh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ecdh.h; sourceTree = "<group>"; };
|
||||
DAEB93A018AB0FFD000490CC /* ecdsa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ecdsa.h; sourceTree = "<group>"; };
|
||||
DAEB93A118AB0FFD000490CC /* engine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = engine.h; sourceTree = "<group>"; };
|
||||
DAEB93A218AB0FFD000490CC /* err.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = err.h; sourceTree = "<group>"; };
|
||||
DAEB93A318AB0FFD000490CC /* evp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = evp.h; sourceTree = "<group>"; };
|
||||
DAEB93A418AB0FFD000490CC /* hmac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hmac.h; sourceTree = "<group>"; };
|
||||
DAEB93A518AB0FFD000490CC /* idea.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = idea.h; sourceTree = "<group>"; };
|
||||
DAEB93A618AB0FFD000490CC /* krb5_asn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = krb5_asn.h; sourceTree = "<group>"; };
|
||||
DAEB93A718AB0FFD000490CC /* kssl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kssl.h; sourceTree = "<group>"; };
|
||||
DAEB93A818AB0FFD000490CC /* lhash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lhash.h; sourceTree = "<group>"; };
|
||||
DAEB93A918AB0FFD000490CC /* md4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = md4.h; sourceTree = "<group>"; };
|
||||
DAEB93AA18AB0FFD000490CC /* md5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = md5.h; sourceTree = "<group>"; };
|
||||
DAEB93AB18AB0FFD000490CC /* mdc2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mdc2.h; sourceTree = "<group>"; };
|
||||
DAEB93AC18AB0FFD000490CC /* modes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = modes.h; sourceTree = "<group>"; };
|
||||
DAEB93AD18AB0FFD000490CC /* obj_mac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = obj_mac.h; sourceTree = "<group>"; };
|
||||
DAEB93AE18AB0FFD000490CC /* objects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = objects.h; sourceTree = "<group>"; };
|
||||
DAEB93AF18AB0FFD000490CC /* ocsp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ocsp.h; sourceTree = "<group>"; };
|
||||
DAEB93B018AB0FFD000490CC /* opensslconf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = opensslconf.h; sourceTree = "<group>"; };
|
||||
DAEB93B118AB0FFD000490CC /* opensslv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = opensslv.h; sourceTree = "<group>"; };
|
||||
DAEB93B218AB0FFD000490CC /* ossl_typ.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossl_typ.h; sourceTree = "<group>"; };
|
||||
DAEB93B318AB0FFD000490CC /* pem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pem.h; sourceTree = "<group>"; };
|
||||
DAEB93B418AB0FFD000490CC /* pem2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pem2.h; sourceTree = "<group>"; };
|
||||
DAEB93B518AB0FFD000490CC /* pkcs12.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pkcs12.h; sourceTree = "<group>"; };
|
||||
DAEB93B618AB0FFD000490CC /* pkcs7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pkcs7.h; sourceTree = "<group>"; };
|
||||
DAEB93B718AB0FFD000490CC /* pqueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pqueue.h; sourceTree = "<group>"; };
|
||||
DAEB93B818AB0FFD000490CC /* rand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rand.h; sourceTree = "<group>"; };
|
||||
DAEB93B918AB0FFD000490CC /* rc2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rc2.h; sourceTree = "<group>"; };
|
||||
DAEB93BA18AB0FFD000490CC /* rc4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rc4.h; sourceTree = "<group>"; };
|
||||
DAEB93BB18AB0FFD000490CC /* ripemd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ripemd.h; sourceTree = "<group>"; };
|
||||
DAEB93BC18AB0FFD000490CC /* rsa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rsa.h; sourceTree = "<group>"; };
|
||||
DAEB93BD18AB0FFD000490CC /* safestack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = safestack.h; sourceTree = "<group>"; };
|
||||
DAEB93BE18AB0FFD000490CC /* seed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = seed.h; sourceTree = "<group>"; };
|
||||
DAEB93BF18AB0FFD000490CC /* sha.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha.h; sourceTree = "<group>"; };
|
||||
DAEB93C018AB0FFD000490CC /* ssl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ssl.h; sourceTree = "<group>"; };
|
||||
DAEB93C118AB0FFD000490CC /* ssl2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ssl2.h; sourceTree = "<group>"; };
|
||||
DAEB93C218AB0FFD000490CC /* ssl23.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ssl23.h; sourceTree = "<group>"; };
|
||||
DAEB93C318AB0FFD000490CC /* ssl3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ssl3.h; sourceTree = "<group>"; };
|
||||
DAEB93C418AB0FFD000490CC /* stack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stack.h; sourceTree = "<group>"; };
|
||||
DAEB93C518AB0FFD000490CC /* symhacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = symhacks.h; sourceTree = "<group>"; };
|
||||
DAEB93C618AB0FFD000490CC /* tls1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tls1.h; sourceTree = "<group>"; };
|
||||
DAEB93C718AB0FFD000490CC /* ts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ts.h; sourceTree = "<group>"; };
|
||||
DAEB93C818AB0FFD000490CC /* txt_db.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = txt_db.h; sourceTree = "<group>"; };
|
||||
DAEB93C918AB0FFD000490CC /* ui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ui.h; sourceTree = "<group>"; };
|
||||
DAEB93CA18AB0FFD000490CC /* ui_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ui_compat.h; sourceTree = "<group>"; };
|
||||
DAEB93CB18AB0FFD000490CC /* whrlpool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = whrlpool.h; sourceTree = "<group>"; };
|
||||
DAEB93CC18AB0FFD000490CC /* x509.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x509.h; sourceTree = "<group>"; };
|
||||
DAEB93CD18AB0FFD000490CC /* x509_vfy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x509_vfy.h; sourceTree = "<group>"; };
|
||||
DAEB93CE18AB0FFD000490CC /* x509v3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x509v3.h; sourceTree = "<group>"; };
|
||||
DAEB93D018AB0FFD000490CC /* crypto_aesctr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_aesctr.h; sourceTree = "<group>"; };
|
||||
DAEB93D118AB0FFD000490CC /* crypto_scrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_scrypt.h; sourceTree = "<group>"; };
|
||||
DAEB93D218AB0FFD000490CC /* memlimit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memlimit.h; sourceTree = "<group>"; };
|
||||
DAEB93D318AB0FFD000490CC /* readpass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = readpass.h; sourceTree = "<group>"; };
|
||||
DAEB93D418AB0FFD000490CC /* scryptenc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scryptenc.h; sourceTree = "<group>"; };
|
||||
DAEB93D518AB0FFD000490CC /* scryptenc_cpuperf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scryptenc_cpuperf.h; sourceTree = "<group>"; };
|
||||
DAEB93D618AB0FFD000490CC /* sha256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha256.h; sourceTree = "<group>"; };
|
||||
DAEB93D718AB0FFD000490CC /* sysendian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sysendian.h; sourceTree = "<group>"; };
|
||||
DAEB93D818AB0FFD000490CC /* warn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = warn.h; sourceTree = "<group>"; };
|
||||
DAE8E65319867ADA00416A0F /* libopensslcrypto-osx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libopensslcrypto-osx.a"; sourceTree = "<group>"; };
|
||||
DAE8E65619867AF500416A0F /* scrypt */ = {isa = PBXFileReference; lastKnownFileType = folder; path = scrypt; sourceTree = "<group>"; };
|
||||
DAE8E65719867AF500416A0F /* openssl */ = {isa = PBXFileReference; lastKnownFileType = folder; path = openssl; sourceTree = "<group>"; };
|
||||
DAEBC45214F6364500987BF6 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
|
||||
DAF4EF52190A828100023C90 /* Exo2.0-Thin.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Exo2.0-Thin.otf"; sourceTree = "<group>"; };
|
||||
DAF4EF53190A828100023C90 /* Exo2.0-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Exo2.0-Regular.otf"; sourceTree = "<group>"; };
|
||||
@@ -1062,6 +905,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DAE8E65519867AE200416A0F /* libopensslcrypto-osx.a in Frameworks */,
|
||||
DA4DA1D91564471A00F6F596 /* libjrswizzle.a in Frameworks */,
|
||||
DAC77CAE148291A600BCF976 /* Foundation.framework in Frameworks */,
|
||||
DA5E5C9417248AA1003798D8 /* libscryptenc-osx.a in Frameworks */,
|
||||
@@ -1081,14 +925,6 @@
|
||||
name = "Other Frameworks";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA3B8447190FC5A900246EEA /* iOS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA3B8448190FC5A900246EEA /* Crashlytics.framework */,
|
||||
);
|
||||
path = iOS;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA3B8449190FC5A900246EEA /* Mac */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1149,8 +985,9 @@
|
||||
DA5E5C7917248AA1003798D8 /* lib */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAEB938518AB0FFD000490CC /* include */,
|
||||
DA5E5C8717248AA1003798D8 /* libscryptenc-osx.a */,
|
||||
DAE8E65319867ADA00416A0F /* libopensslcrypto-osx.a */,
|
||||
DAEB938518AB0FFD000490CC /* include */,
|
||||
);
|
||||
path = lib;
|
||||
sourceTree = "<group>";
|
||||
@@ -1664,7 +1501,6 @@
|
||||
DACA22121705DDC5002C6C22 /* External */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA3B8447190FC5A900246EEA /* iOS */,
|
||||
DA3B8449190FC5A900246EEA /* Mac */,
|
||||
DABC6C0E175D8CE1000C15D4 /* RHStatusItemView */,
|
||||
DACA29751705E2BD002C6C22 /* jrswizzle */,
|
||||
@@ -1822,107 +1658,12 @@
|
||||
DAEB938518AB0FFD000490CC /* include */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAEB938618AB0FFD000490CC /* openssl */,
|
||||
DAEB93CF18AB0FFD000490CC /* scrypt */,
|
||||
DAE8E65619867AF500416A0F /* scrypt */,
|
||||
DAE8E65719867AF500416A0F /* openssl */,
|
||||
);
|
||||
path = include;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAEB938618AB0FFD000490CC /* openssl */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAEB938718AB0FFD000490CC /* aes.h */,
|
||||
DAEB938818AB0FFD000490CC /* asn1.h */,
|
||||
DAEB938918AB0FFD000490CC /* asn1_mac.h */,
|
||||
DAEB938A18AB0FFD000490CC /* asn1t.h */,
|
||||
DAEB938B18AB0FFD000490CC /* bio.h */,
|
||||
DAEB938C18AB0FFD000490CC /* blowfish.h */,
|
||||
DAEB938D18AB0FFD000490CC /* bn.h */,
|
||||
DAEB938E18AB0FFD000490CC /* buffer.h */,
|
||||
DAEB938F18AB0FFD000490CC /* camellia.h */,
|
||||
DAEB939018AB0FFD000490CC /* cast.h */,
|
||||
DAEB939118AB0FFD000490CC /* cms.h */,
|
||||
DAEB939218AB0FFD000490CC /* comp.h */,
|
||||
DAEB939318AB0FFD000490CC /* conf.h */,
|
||||
DAEB939418AB0FFD000490CC /* conf_api.h */,
|
||||
DAEB939518AB0FFD000490CC /* crypto.h */,
|
||||
DAEB939618AB0FFD000490CC /* des.h */,
|
||||
DAEB939718AB0FFD000490CC /* des_old.h */,
|
||||
DAEB939818AB0FFD000490CC /* dh.h */,
|
||||
DAEB939918AB0FFD000490CC /* dsa.h */,
|
||||
DAEB939A18AB0FFD000490CC /* dso.h */,
|
||||
DAEB939B18AB0FFD000490CC /* dtls1.h */,
|
||||
DAEB939C18AB0FFD000490CC /* e_os2.h */,
|
||||
DAEB939D18AB0FFD000490CC /* ebcdic.h */,
|
||||
DAEB939E18AB0FFD000490CC /* ec.h */,
|
||||
DAEB939F18AB0FFD000490CC /* ecdh.h */,
|
||||
DAEB93A018AB0FFD000490CC /* ecdsa.h */,
|
||||
DAEB93A118AB0FFD000490CC /* engine.h */,
|
||||
DAEB93A218AB0FFD000490CC /* err.h */,
|
||||
DAEB93A318AB0FFD000490CC /* evp.h */,
|
||||
DAEB93A418AB0FFD000490CC /* hmac.h */,
|
||||
DAEB93A518AB0FFD000490CC /* idea.h */,
|
||||
DAEB93A618AB0FFD000490CC /* krb5_asn.h */,
|
||||
DAEB93A718AB0FFD000490CC /* kssl.h */,
|
||||
DAEB93A818AB0FFD000490CC /* lhash.h */,
|
||||
DAEB93A918AB0FFD000490CC /* md4.h */,
|
||||
DAEB93AA18AB0FFD000490CC /* md5.h */,
|
||||
DAEB93AB18AB0FFD000490CC /* mdc2.h */,
|
||||
DAEB93AC18AB0FFD000490CC /* modes.h */,
|
||||
DAEB93AD18AB0FFD000490CC /* obj_mac.h */,
|
||||
DAEB93AE18AB0FFD000490CC /* objects.h */,
|
||||
DAEB93AF18AB0FFD000490CC /* ocsp.h */,
|
||||
DAEB93B018AB0FFD000490CC /* opensslconf.h */,
|
||||
DAEB93B118AB0FFD000490CC /* opensslv.h */,
|
||||
DAEB93B218AB0FFD000490CC /* ossl_typ.h */,
|
||||
DAEB93B318AB0FFD000490CC /* pem.h */,
|
||||
DAEB93B418AB0FFD000490CC /* pem2.h */,
|
||||
DAEB93B518AB0FFD000490CC /* pkcs12.h */,
|
||||
DAEB93B618AB0FFD000490CC /* pkcs7.h */,
|
||||
DAEB93B718AB0FFD000490CC /* pqueue.h */,
|
||||
DAEB93B818AB0FFD000490CC /* rand.h */,
|
||||
DAEB93B918AB0FFD000490CC /* rc2.h */,
|
||||
DAEB93BA18AB0FFD000490CC /* rc4.h */,
|
||||
DAEB93BB18AB0FFD000490CC /* ripemd.h */,
|
||||
DAEB93BC18AB0FFD000490CC /* rsa.h */,
|
||||
DAEB93BD18AB0FFD000490CC /* safestack.h */,
|
||||
DAEB93BE18AB0FFD000490CC /* seed.h */,
|
||||
DAEB93BF18AB0FFD000490CC /* sha.h */,
|
||||
DAEB93C018AB0FFD000490CC /* ssl.h */,
|
||||
DAEB93C118AB0FFD000490CC /* ssl2.h */,
|
||||
DAEB93C218AB0FFD000490CC /* ssl23.h */,
|
||||
DAEB93C318AB0FFD000490CC /* ssl3.h */,
|
||||
DAEB93C418AB0FFD000490CC /* stack.h */,
|
||||
DAEB93C518AB0FFD000490CC /* symhacks.h */,
|
||||
DAEB93C618AB0FFD000490CC /* tls1.h */,
|
||||
DAEB93C718AB0FFD000490CC /* ts.h */,
|
||||
DAEB93C818AB0FFD000490CC /* txt_db.h */,
|
||||
DAEB93C918AB0FFD000490CC /* ui.h */,
|
||||
DAEB93CA18AB0FFD000490CC /* ui_compat.h */,
|
||||
DAEB93CB18AB0FFD000490CC /* whrlpool.h */,
|
||||
DAEB93CC18AB0FFD000490CC /* x509.h */,
|
||||
DAEB93CD18AB0FFD000490CC /* x509_vfy.h */,
|
||||
DAEB93CE18AB0FFD000490CC /* x509v3.h */,
|
||||
);
|
||||
path = openssl;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAEB93CF18AB0FFD000490CC /* scrypt */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAEB93D018AB0FFD000490CC /* crypto_aesctr.h */,
|
||||
DAEB93D118AB0FFD000490CC /* crypto_scrypt.h */,
|
||||
DAEB93D218AB0FFD000490CC /* memlimit.h */,
|
||||
DAEB93D318AB0FFD000490CC /* readpass.h */,
|
||||
DAEB93D418AB0FFD000490CC /* scryptenc.h */,
|
||||
DAEB93D518AB0FFD000490CC /* scryptenc_cpuperf.h */,
|
||||
DAEB93D618AB0FFD000490CC /* sha256.h */,
|
||||
DAEB93D718AB0FFD000490CC /* sysendian.h */,
|
||||
DAEB93D818AB0FFD000490CC /* warn.h */,
|
||||
);
|
||||
path = scrypt;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAFE45D715039823003ABA7C /* Pearl */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -2044,120 +1785,41 @@
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DAEB941818AB0FFD000490CC /* tls1.h in Headers */,
|
||||
DAEB940C18AB0FFD000490CC /* rc4.h in Headers */,
|
||||
DAEB93F418AB0FFD000490CC /* err.h in Headers */,
|
||||
DAEB93F118AB0FFD000490CC /* ecdh.h in Headers */,
|
||||
DAEB93FD18AB0FFD000490CC /* mdc2.h in Headers */,
|
||||
DAEB942718AB0FFD000490CC /* sha256.h in Headers */,
|
||||
DAEB940818AB0FFD000490CC /* pkcs7.h in Headers */,
|
||||
DA10007F1998A4C6002B873F /* scrypt in Headers */,
|
||||
DA1000801998A4C6002B873F /* openssl in Headers */,
|
||||
DA2CA4F218D323D3007798F8 /* NSTimer+PearlBlock.h in Headers */,
|
||||
DAEB93DF18AB0FFD000490CC /* bn.h in Headers */,
|
||||
DAEB940718AB0FFD000490CC /* pkcs12.h in Headers */,
|
||||
DAEB941A18AB0FFD000490CC /* txt_db.h in Headers */,
|
||||
DAFE4A1315039824003ABA7C /* NSObject+PearlExport.h in Headers */,
|
||||
DAFE4A1515039824003ABA7C /* NSString+PearlNSArrayFormat.h in Headers */,
|
||||
DAEB942218AB0FFD000490CC /* crypto_scrypt.h in Headers */,
|
||||
DAEB941018AB0FFD000490CC /* seed.h in Headers */,
|
||||
DAEB942618AB0FFD000490CC /* scryptenc_cpuperf.h in Headers */,
|
||||
DAFE4A1715039824003ABA7C /* NSString+PearlSEL.h in Headers */,
|
||||
DA3B8453190FC86F00246EEA /* NSManagedObject+Pearl.h in Headers */,
|
||||
DAEB93F518AB0FFD000490CC /* evp.h in Headers */,
|
||||
DAEB941918AB0FFD000490CC /* ts.h in Headers */,
|
||||
DA8ED897192906920099B726 /* map-macro.h in Headers */,
|
||||
DAEB93F818AB0FFD000490CC /* krb5_asn.h in Headers */,
|
||||
DAFE4A1915039824003ABA7C /* Pearl.h in Headers */,
|
||||
DAEB93F318AB0FFD000490CC /* engine.h in Headers */,
|
||||
DAFE4A1A15039824003ABA7C /* PearlAbstractStrings.h in Headers */,
|
||||
DAFE4A1E15039824003ABA7C /* PearlCodeUtils.h in Headers */,
|
||||
DAEB940918AB0FFD000490CC /* pqueue.h in Headers */,
|
||||
DAFE4A2015039824003ABA7C /* PearlConfig.h in Headers */,
|
||||
DAEB941B18AB0FFD000490CC /* ui.h in Headers */,
|
||||
DAEB941D18AB0FFD000490CC /* whrlpool.h in Headers */,
|
||||
DAEB940418AB0FFD000490CC /* ossl_typ.h in Headers */,
|
||||
DAEB93DC18AB0FFD000490CC /* asn1t.h in Headers */,
|
||||
DAFE4A2215039824003ABA7C /* PearlDeviceUtils.h in Headers */,
|
||||
DA8ED896192906920099B726 /* PearlTween.h in Headers */,
|
||||
DAEB93E518AB0FFD000490CC /* conf.h in Headers */,
|
||||
DAFE4A2415039824003ABA7C /* PearlInfoPlist.h in Headers */,
|
||||
DAEB940618AB0FFD000490CC /* pem2.h in Headers */,
|
||||
DAFE4A2615039824003ABA7C /* PearlLogger.h in Headers */,
|
||||
DA2CA4F018D323D3007798F8 /* NSArray+Pearl.h in Headers */,
|
||||
DAEB93FC18AB0FFD000490CC /* md5.h in Headers */,
|
||||
DAFE4A2815039824003ABA7C /* PearlMathUtils.h in Headers */,
|
||||
DAFE4A2A15039824003ABA7C /* PearlObjectUtils.h in Headers */,
|
||||
DAEB93E318AB0FFD000490CC /* cms.h in Headers */,
|
||||
DAEB942518AB0FFD000490CC /* scryptenc.h in Headers */,
|
||||
DAEB93FA18AB0FFD000490CC /* lhash.h in Headers */,
|
||||
DAFE4A2C15039824003ABA7C /* PearlResettable.h in Headers */,
|
||||
DAEB940B18AB0FFD000490CC /* rc2.h in Headers */,
|
||||
DAFE4A2D15039824003ABA7C /* PearlStrings.h in Headers */,
|
||||
DAEB93DA18AB0FFD000490CC /* asn1.h in Headers */,
|
||||
DAEB93EA18AB0FFD000490CC /* dh.h in Headers */,
|
||||
DAEB93F918AB0FFD000490CC /* kssl.h in Headers */,
|
||||
DAFE4A2F15039824003ABA7C /* PearlStringUtils.h in Headers */,
|
||||
DAEB940318AB0FFD000490CC /* opensslv.h in Headers */,
|
||||
DAEB93ED18AB0FFD000490CC /* dtls1.h in Headers */,
|
||||
DAEB93E018AB0FFD000490CC /* buffer.h in Headers */,
|
||||
DAEB940218AB0FFD000490CC /* opensslconf.h in Headers */,
|
||||
DAEB93E918AB0FFD000490CC /* des_old.h in Headers */,
|
||||
DAFE4A3315039824003ABA7C /* Pearl-Crypto.h in Headers */,
|
||||
DAEB941C18AB0FFD000490CC /* ui_compat.h in Headers */,
|
||||
DAEB93E218AB0FFD000490CC /* cast.h in Headers */,
|
||||
DAEB942318AB0FFD000490CC /* memlimit.h in Headers */,
|
||||
DAFE4A3415039824003ABA7C /* PearlCryptUtils.h in Headers */,
|
||||
DAEB940018AB0FFD000490CC /* objects.h in Headers */,
|
||||
DAEB93E818AB0FFD000490CC /* des.h in Headers */,
|
||||
DAEB941418AB0FFD000490CC /* ssl23.h in Headers */,
|
||||
DAEB93EB18AB0FFD000490CC /* dsa.h in Headers */,
|
||||
DAEB941218AB0FFD000490CC /* ssl.h in Headers */,
|
||||
DAEB93FE18AB0FFD000490CC /* modes.h in Headers */,
|
||||
DAEB940A18AB0FFD000490CC /* rand.h in Headers */,
|
||||
DAEB93EE18AB0FFD000490CC /* e_os2.h in Headers */,
|
||||
DAEB940E18AB0FFD000490CC /* rsa.h in Headers */,
|
||||
DAEB93E618AB0FFD000490CC /* conf_api.h in Headers */,
|
||||
DAFE4A3615039824003ABA7C /* PearlKeyChain.h in Headers */,
|
||||
DAEB941518AB0FFD000490CC /* ssl3.h in Headers */,
|
||||
DAEB941618AB0FFD000490CC /* stack.h in Headers */,
|
||||
DAFE4A3815039824003ABA7C /* PearlRSAKey.h in Headers */,
|
||||
DAEB93DD18AB0FFD000490CC /* bio.h in Headers */,
|
||||
DAEB942418AB0FFD000490CC /* readpass.h in Headers */,
|
||||
DAEB93F018AB0FFD000490CC /* ec.h in Headers */,
|
||||
DAEB93E418AB0FFD000490CC /* comp.h in Headers */,
|
||||
DAFE4A3A15039824003ABA7C /* PearlSCrypt.h in Headers */,
|
||||
DAEB93D918AB0FFD000490CC /* aes.h in Headers */,
|
||||
DA30E9CE15722ECA00A68B4C /* NSBundle+PearlMutableInfo.h in Headers */,
|
||||
DAEB93FB18AB0FFD000490CC /* md4.h in Headers */,
|
||||
DAEB941118AB0FFD000490CC /* sha.h in Headers */,
|
||||
DAEB941F18AB0FFD000490CC /* x509_vfy.h in Headers */,
|
||||
DA30E9D715723E6900A68B4C /* PearlLazy.h in Headers */,
|
||||
DAEB93EC18AB0FFD000490CC /* dso.h in Headers */,
|
||||
DAEB940118AB0FFD000490CC /* ocsp.h in Headers */,
|
||||
DAFE4A63150399FF003ABA88 /* NSObject+PearlKVO.h in Headers */,
|
||||
DAFE4A63150399FF003ABA94 /* NSDateFormatter+RFC3339.h in Headers */,
|
||||
DAEB93F718AB0FFD000490CC /* idea.h in Headers */,
|
||||
DAEB940F18AB0FFD000490CC /* safestack.h in Headers */,
|
||||
DAEB941E18AB0FFD000490CC /* x509.h in Headers */,
|
||||
DAEB93EF18AB0FFD000490CC /* ebcdic.h in Headers */,
|
||||
DAEB93DE18AB0FFD000490CC /* blowfish.h in Headers */,
|
||||
DAEB941718AB0FFD000490CC /* symhacks.h in Headers */,
|
||||
93D39C34FE35830EF5BE1D2A /* NSArray+Indexing.h in Headers */,
|
||||
DAEB942118AB0FFD000490CC /* crypto_aesctr.h in Headers */,
|
||||
DAEB93F218AB0FFD000490CC /* ecdsa.h in Headers */,
|
||||
DAEB942018AB0FFD000490CC /* x509v3.h in Headers */,
|
||||
DAEB93E118AB0FFD000490CC /* camellia.h in Headers */,
|
||||
DAEB93F618AB0FFD000490CC /* hmac.h in Headers */,
|
||||
93D392EC39DA43C46C692C12 /* NSDictionary+Indexing.h in Headers */,
|
||||
DA3509FE15F101A500C14A8E /* PearlQueue.h in Headers */,
|
||||
DAEB942918AB0FFD000490CC /* warn.h in Headers */,
|
||||
DAEB93DB18AB0FFD000490CC /* asn1_mac.h in Headers */,
|
||||
DAEB940518AB0FFD000490CC /* pem.h in Headers */,
|
||||
DAEB942818AB0FFD000490CC /* sysendian.h in Headers */,
|
||||
DA2CA4EE18D323D3007798F8 /* NSError+PearlFullDescription.h in Headers */,
|
||||
DAEB93FF18AB0FFD000490CC /* obj_mac.h in Headers */,
|
||||
DAEB93E718AB0FFD000490CC /* crypto.h in Headers */,
|
||||
DAEB941318AB0FFD000490CC /* ssl2.h in Headers */,
|
||||
DAEB940D18AB0FFD000490CC /* ripemd.h in Headers */,
|
||||
93D39D304F73B3BBA031522A /* PearlProfiler.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -2257,9 +1919,10 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = DAC77CB7148291A600BCF976 /* Build configuration list for PBXNativeTarget "Pearl" */;
|
||||
buildPhases = (
|
||||
DA10008119994255002B873F /* ShellScript */,
|
||||
DAC77CAB148291A600BCF976 /* Headers */,
|
||||
DAC77CA9148291A600BCF976 /* Sources */,
|
||||
DAC77CAA148291A600BCF976 /* Frameworks */,
|
||||
DAC77CAB148291A600BCF976 /* Headers */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -2284,6 +1947,11 @@
|
||||
TargetAttributes = {
|
||||
DA5BFA43147E415C00F98B1E = {
|
||||
DevelopmentTeam = HL3Q45LX9N;
|
||||
SystemCapabilities = {
|
||||
com.apple.iCloud = {
|
||||
enabled = 0;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -2402,6 +2070,19 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
DA10008119994255002B873F /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "";
|
||||
};
|
||||
DA6556E314D55F3000841C99 /* Run Script: GIT version -> Info.plist */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -2643,10 +2324,6 @@
|
||||
CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherit)",
|
||||
"\"$(SRCROOT)/../../../External\"",
|
||||
);
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
@@ -2720,10 +2397,6 @@
|
||||
CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherit)",
|
||||
"\"$(SRCROOT)/../../../External\"",
|
||||
);
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
@@ -2782,6 +2455,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = MasterPassword.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -2789,7 +2463,11 @@
|
||||
);
|
||||
GCC_PREFIX_HEADER = "MasterPassword-Prefix.pch";
|
||||
INFOPLIST_FILE = "MasterPassword-Info.plist";
|
||||
PROVISIONING_PROFILE = "0FAB9494-7BD5-4638-9B60-66DED5D23B9A";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"/Users/lhunath/Documents/workspace/lyndir/MasterPassword/External/Pearl/Pearl-Crypto/lib",
|
||||
);
|
||||
PROVISIONING_PROFILE = "";
|
||||
SKIP_INSTALL = NO;
|
||||
WRAPPER_NAME = "Master Password.${WRAPPER_EXTENSION}";
|
||||
};
|
||||
@@ -2801,6 +2479,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = MasterPassword.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Developer ID Application";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -2808,7 +2487,11 @@
|
||||
);
|
||||
GCC_PREFIX_HEADER = "MasterPassword-Prefix.pch";
|
||||
INFOPLIST_FILE = "MasterPassword-Info.plist";
|
||||
PROVISIONING_PROFILE = "0FAB9494-7BD5-4638-9B60-66DED5D23B9A";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"/Users/lhunath/Documents/workspace/lyndir/MasterPassword/External/Pearl/Pearl-Crypto/lib",
|
||||
);
|
||||
PROVISIONING_PROFILE = "";
|
||||
SKIP_INSTALL = NO;
|
||||
WRAPPER_NAME = "Master Password.${WRAPPER_EXTENSION}";
|
||||
};
|
||||
@@ -2836,10 +2519,6 @@
|
||||
CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherit)",
|
||||
"\"$(SRCROOT)/../../../External\"",
|
||||
);
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
@@ -2906,7 +2585,11 @@
|
||||
);
|
||||
GCC_PREFIX_HEADER = "MasterPassword-Prefix.pch";
|
||||
INFOPLIST_FILE = "MasterPassword-Info.plist";
|
||||
PROVISIONING_PROFILE = "16F3EA2E-5241-42F7-8F39-125ED9FCD536";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"/Users/lhunath/Documents/workspace/lyndir/MasterPassword/External/Pearl/Pearl-Crypto/lib",
|
||||
);
|
||||
PROVISIONING_PROFILE = "";
|
||||
SKIP_INSTALL = NO;
|
||||
WRAPPER_NAME = "Master Password.${WRAPPER_EXTENSION}";
|
||||
};
|
||||
@@ -2922,9 +2605,11 @@
|
||||
"$(inherited)",
|
||||
"\"$(SRCROOT)/../../../External/Pearl/Pearl-Crypto\"",
|
||||
"\"$(SRCROOT)/../../../External/Pearl/Pearl-Crypto/lib\"",
|
||||
"/Users/lhunath/Documents/workspace/lyndir/MasterPassword/External/Pearl/Pearl-Crypto/lib",
|
||||
);
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PUBLIC_HEADERS_FOLDER_PATH = "../../BuildProductsPath/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/include";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = "AppStore-Mac";
|
||||
@@ -2993,9 +2678,11 @@
|
||||
"$(inherited)",
|
||||
"\"$(SRCROOT)/../../../External/Pearl/Pearl-Crypto\"",
|
||||
"\"$(SRCROOT)/../../../External/Pearl/Pearl-Crypto/lib\"",
|
||||
"/Users/lhunath/Documents/workspace/lyndir/MasterPassword/External/Pearl/Pearl-Crypto/lib",
|
||||
);
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PUBLIC_HEADERS_FOLDER_PATH = include;
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = "Debug-Mac";
|
||||
@@ -3010,9 +2697,11 @@
|
||||
"$(inherited)",
|
||||
"\"$(SRCROOT)/../../../External/Pearl/Pearl-Crypto\"",
|
||||
"\"$(SRCROOT)/../../../External/Pearl/Pearl-Crypto/lib\"",
|
||||
"/Users/lhunath/Documents/workspace/lyndir/MasterPassword/External/Pearl/Pearl-Crypto/lib",
|
||||
);
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PUBLIC_HEADERS_FOLDER_PATH = "../../BuildProductsPath/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/include";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = "AdHoc-Mac";
|
||||
|
||||
@@ -2,13 +2,6 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.developer.ubiquity-container-identifiers</key>
|
||||
<array>
|
||||
<string>HL3Q45LX9N.com.lyndir.lhunath.MasterPassword.Mac</string>
|
||||
<string>HL3Q45LX9N.com.lyndir.lhunath.MasterPassword.shared</string>
|
||||
</array>
|
||||
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
|
||||
<string>HL3Q45LX9N.com.lyndir.lhunath.MasterPassword.shared</string>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
//
|
||||
|
||||
#import "MPAvatarCell.h"
|
||||
#import "MPPasswordLargeCell.h"
|
||||
|
||||
const long MPAvatarAdd = 10000;
|
||||
|
||||
@@ -140,9 +139,7 @@ const long MPAvatarAdd = 10000;
|
||||
|
||||
super.highlighted = highlighted;
|
||||
|
||||
[UIView animateWithDuration:0.1f animations:^{
|
||||
self.avatarImageView.transform = highlighted? CGAffineTransformMakeScale( 1.1f, 1.1f ): CGAffineTransformIdentity;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)setMode:(MPAvatarMode)mode {
|
||||
@@ -169,7 +166,7 @@ const long MPAvatarAdd = 10000;
|
||||
_spinnerActive = spinnerActive;
|
||||
|
||||
CABasicAnimation *rotate = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
|
||||
rotate.toValue = [NSNumber numberWithDouble:2 * M_PI];
|
||||
rotate.toValue = @(2 * M_PI);
|
||||
rotate.duration = 5.0;
|
||||
|
||||
if (spinnerActive) {
|
||||
@@ -207,10 +204,10 @@ const long MPAvatarAdd = 10000;
|
||||
|
||||
switch (self.mode) {
|
||||
case MPAvatarModeLowered: {
|
||||
[self.avatarSizeConstraint layoutWithConstant:self.avatarImageView.image.size.height];
|
||||
[self.avatarRaisedConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
|
||||
[self.avatarToTopConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
|
||||
[self.nameToCenterConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
|
||||
[self.avatarSizeConstraint updateConstant:self.avatarImageView.image.size.height];
|
||||
[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultLow];
|
||||
[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow];
|
||||
[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultLow];
|
||||
self.nameContainer.alpha = self.visibility;
|
||||
self.nameContainer.backgroundColor = [UIColor clearColor];
|
||||
self.avatarImageView.alpha = self.visibility / 0.7f + 0.3f;
|
||||
@@ -218,10 +215,10 @@ const long MPAvatarAdd = 10000;
|
||||
break;
|
||||
}
|
||||
case MPAvatarModeRaisedButInactive: {
|
||||
[self.avatarSizeConstraint layoutWithConstant:self.avatarImageView.image.size.height];
|
||||
[self.avatarRaisedConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
|
||||
[self.avatarToTopConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
|
||||
[self.nameToCenterConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
|
||||
[self.avatarSizeConstraint updateConstant:self.avatarImageView.image.size.height];
|
||||
[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultHigh];
|
||||
[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow];
|
||||
[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultLow];
|
||||
self.nameContainer.alpha = self.visibility;
|
||||
self.nameContainer.backgroundColor = [UIColor clearColor];
|
||||
self.avatarImageView.alpha = 0;
|
||||
@@ -229,10 +226,10 @@ const long MPAvatarAdd = 10000;
|
||||
break;
|
||||
}
|
||||
case MPAvatarModeRaisedAndActive: {
|
||||
[self.avatarSizeConstraint layoutWithConstant:self.avatarImageView.image.size.height];
|
||||
[self.avatarRaisedConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
|
||||
[self.avatarToTopConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
|
||||
[self.nameToCenterConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
|
||||
[self.avatarSizeConstraint updateConstant:self.avatarImageView.image.size.height];
|
||||
[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultHigh];
|
||||
[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow];
|
||||
[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultHigh];
|
||||
self.nameContainer.alpha = self.visibility;
|
||||
self.nameContainer.backgroundColor = [UIColor blackColor];
|
||||
self.avatarImageView.alpha = 1;
|
||||
@@ -240,10 +237,10 @@ const long MPAvatarAdd = 10000;
|
||||
break;
|
||||
}
|
||||
case MPAvatarModeRaisedAndHidden: {
|
||||
[self.avatarSizeConstraint layoutWithConstant:self.avatarImageView.image.size.height];
|
||||
[self.avatarRaisedConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
|
||||
[self.avatarToTopConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
|
||||
[self.nameToCenterConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
|
||||
[self.avatarSizeConstraint updateConstant:self.avatarImageView.image.size.height];
|
||||
[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultHigh];
|
||||
[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow];
|
||||
[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultHigh];
|
||||
self.nameContainer.alpha = 0;
|
||||
self.nameContainer.backgroundColor = [UIColor blackColor];
|
||||
self.avatarImageView.alpha = 0;
|
||||
@@ -251,10 +248,10 @@ const long MPAvatarAdd = 10000;
|
||||
break;
|
||||
}
|
||||
case MPAvatarModeRaisedAndMinimized: {
|
||||
[self.avatarSizeConstraint layoutWithConstant:36];
|
||||
[self.avatarRaisedConstraint layoutWithPriority:UILayoutPriorityDefaultLow];
|
||||
[self.avatarToTopConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
|
||||
[self.nameToCenterConstraint layoutWithPriority:UILayoutPriorityDefaultHigh];
|
||||
[self.avatarSizeConstraint updateConstant:36];
|
||||
[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultLow];
|
||||
[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultHigh];
|
||||
[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultHigh];
|
||||
self.nameContainer.alpha = 0;
|
||||
self.nameContainer.backgroundColor = [UIColor blackColor];
|
||||
self.avatarImageView.alpha = 1;
|
||||
@@ -275,6 +272,8 @@ const long MPAvatarAdd = 10000;
|
||||
self.avatarImageView.backgroundColor = [UIColor clearColor];
|
||||
self.avatarImageView.layer.cornerRadius = self.avatarImageView.bounds.size.height / 2;
|
||||
self.spinner.alpha = self.spinnerActive? 1: 0;
|
||||
|
||||
[self layoutSubviews];
|
||||
} completion:nil];
|
||||
}
|
||||
|
||||
|
||||
@@ -50,16 +50,14 @@
|
||||
[MPGuideStep stepWithImage:[UIImage imageNamed:@"image-5"] caption:
|
||||
@"Your sites are easy to find and sorted by recency.\nTap any site to copy its password.\nYou can now switch and paste it in another app."],
|
||||
[MPGuideStep stepWithImage:[UIImage imageNamed:@"image-6"] caption:
|
||||
@"If the site you're looking for isn't easy to find, just type a few letters in the search box to filter the site list."],
|
||||
[MPGuideStep stepWithImage:[UIImage imageNamed:@"image-7"] caption:
|
||||
@"If you ever need a new password for the site, just tap the plus icon to increment its counter.\nYou can hold down to reset it back to 1."],
|
||||
[MPGuideStep stepWithImage:[UIImage imageNamed:@"image-8"] caption:
|
||||
@"The user icon lets you save your site's login.\nThis is useful if you find it hard to remember the user name for this site."],
|
||||
[MPGuideStep stepWithImage:[UIImage imageNamed:@"image-7"] caption:
|
||||
@"To make changes to the site password, tap the settings icon or swipe left to reveal extra buttons."],
|
||||
[MPGuideStep stepWithImage:[UIImage imageNamed:@"image-8"] caption:
|
||||
@"If you ever need a new password for the site, just tap the plus icon to increment its counter.\nYou can hold down to reset it back to 1."],
|
||||
[MPGuideStep stepWithImage:[UIImage imageNamed:@"image-9"] caption:
|
||||
@"Master Password lets you swipe to upgrade or downgrade your password's complexity.\nSome sites won't let you use complex passwords."],
|
||||
@"Use the list icon to upgrade or downgrade your password's complexity.\nSome sites won't let you use complex passwords."],
|
||||
[MPGuideStep stepWithImage:[UIImage imageNamed:@"image-10"] caption:
|
||||
@"To delete a site, swipe it all the way left to find the \"Delete Site\" button."],
|
||||
[MPGuideStep stepWithImage:[UIImage imageNamed:@"image-11"] caption:
|
||||
@"If you have a password that you cannot change, you can save it as a Personal password. Device Private means the site will not be backed up."],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -20,9 +20,15 @@
|
||||
#import "MPEntities.h"
|
||||
#import "MPCell.h"
|
||||
|
||||
@interface MPPasswordCell : MPCell
|
||||
typedef NS_ENUM ( NSUInteger, MPPasswordCellMode ) {
|
||||
MPPasswordCellModePassword,
|
||||
MPPasswordCellModeSettings,
|
||||
};
|
||||
|
||||
/** Populate our UI to reflect the current state. */
|
||||
- (void)updateAnimated:(BOOL)animated;
|
||||
@interface MPPasswordCell : MPCell <UIScrollViewDelegate, UITextFieldDelegate>
|
||||
|
||||
- (void)setElement:(MPElementEntity *)element animated:(BOOL)animated;
|
||||
- (void)setTransientSite:(NSString *)siteName animated:(BOOL)animated;
|
||||
- (void)setMode:(MPPasswordCellMode)mode animated:(BOOL)animated;
|
||||
|
||||
@end
|
||||
|
||||
@@ -20,40 +20,346 @@
|
||||
#import "MPiOSAppDelegate.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
|
||||
@implementation MPPasswordCell
|
||||
@interface MPPasswordCell()
|
||||
|
||||
@property(nonatomic, strong) IBOutlet UILabel *siteNameLabel;
|
||||
@property(nonatomic, strong) IBOutlet UITextField *passwordField;
|
||||
@property(nonatomic, strong) IBOutlet UITextField *loginNameField;
|
||||
@property(nonatomic, strong) IBOutlet UIPageControl *pageControl;
|
||||
@property(nonatomic, strong) IBOutlet UILabel *strengthLabel;
|
||||
@property(nonatomic, strong) IBOutlet UILabel *counterLabel;
|
||||
@property(nonatomic, strong) IBOutlet UIButton *counterButton;
|
||||
@property(nonatomic, strong) IBOutlet UIButton *upgradeButton;
|
||||
@property(nonatomic, strong) IBOutlet UIButton *modeButton;
|
||||
@property(nonatomic, strong) IBOutlet UIButton *loginModeButton;
|
||||
@property(nonatomic, strong) IBOutlet UIButton *editButton;
|
||||
@property(nonatomic, strong) IBOutlet UIScrollView *modeScrollView;
|
||||
@property(nonatomic, strong) IBOutlet UIButton *selectionButton;
|
||||
@property(nonatomic, strong) IBOutlet UIView *indicatorView;
|
||||
|
||||
@property(nonatomic) MPPasswordCellMode mode;
|
||||
@property(nonatomic, copy) NSString *transientSite;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPPasswordCell {
|
||||
NSManagedObjectID *_elementOID;
|
||||
}
|
||||
|
||||
#pragma mark - Life cycle
|
||||
|
||||
- (void)awakeFromNib {
|
||||
|
||||
[super awakeFromNib];
|
||||
|
||||
[self addGestureRecognizer:
|
||||
[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector( doRevealPassword: )]];
|
||||
[self.counterButton addGestureRecognizer:
|
||||
[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector( doResetCounter: )]];
|
||||
|
||||
self.selectionButton.layer.cornerRadius = 5;
|
||||
self.selectionButton.layer.shadowOffset = CGSizeZero;
|
||||
self.selectionButton.layer.shadowRadius = 5;
|
||||
self.selectionButton.layer.shadowOpacity = 0;
|
||||
self.selectionButton.layer.shadowColor = [UIColor whiteColor].CGColor;
|
||||
|
||||
self.pageControl.transform = CGAffineTransformMakeScale( 0.4f, 0.4f );
|
||||
|
||||
[self.selectionButton observeKeyPath:@"highlighted"
|
||||
withBlock:^(id from, id to, NSKeyValueChange cause, UIButton *button) {
|
||||
button.layer.shadowOpacity = button.selected? 1: button.highlighted? 0.3f: 0;
|
||||
}];
|
||||
[self.selectionButton observeKeyPath:@"selected"
|
||||
withBlock:^(id from, id to, NSKeyValueChange cause, UIButton *button) {
|
||||
button.layer.shadowOpacity = button.selected? 1: button.highlighted? 0.3f: 0;
|
||||
}];
|
||||
|
||||
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position.y"];
|
||||
animation.byValue = @(10);
|
||||
animation.repeatCount = HUGE_VALF;
|
||||
animation.autoreverses = YES;
|
||||
animation.duration = 0.3f;
|
||||
[self.indicatorView.layer addAnimation:animation forKey:@"bounce"];
|
||||
}
|
||||
|
||||
- (void)prepareForReuse {
|
||||
|
||||
[super prepareForReuse];
|
||||
|
||||
_elementOID = nil;
|
||||
self.transientSite = nil;
|
||||
self.loginModeButton.selected = NO;
|
||||
self.mode = MPPasswordCellModePassword;
|
||||
[self updateAnimated:NO];
|
||||
}
|
||||
|
||||
// Unblocks animations for all CALayer properties (eg. shadowOpacity)
|
||||
- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event {
|
||||
#pragma mark - State
|
||||
|
||||
id<CAAction> defaultAction = [super actionForLayer:layer forKey:event];
|
||||
if (defaultAction == (id)[NSNull null] && [event isEqualToString:@"position"])
|
||||
return defaultAction;
|
||||
- (void)setMode:(MPPasswordCellMode)mode animated:(BOOL)animated {
|
||||
|
||||
return NSNullToNil(defaultAction);
|
||||
if (mode == _mode)
|
||||
return;
|
||||
|
||||
_mode = mode;
|
||||
[self updateAnimated:animated];
|
||||
}
|
||||
|
||||
#pragma mark - Properties
|
||||
- (void)setElement:(MPElementEntity *)element animated:(BOOL)animated {
|
||||
|
||||
- (void)setSelected:(BOOL)selected {
|
||||
_elementOID = [element objectID];
|
||||
[self updateAnimated:animated];
|
||||
}
|
||||
|
||||
[super setSelected:selected];
|
||||
- (void)setTransientSite:(NSString *)siteName animated:(BOOL)animated {
|
||||
|
||||
self.transientSite = siteName;
|
||||
[self updateAnimated:animated];
|
||||
}
|
||||
|
||||
#pragma mark - UITextFieldDelegate
|
||||
|
||||
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
|
||||
|
||||
[textField resignFirstResponder];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)textFieldDidBeginEditing:(UITextField *)textField {
|
||||
|
||||
UICollectionView *collectionView = [UICollectionView findAsSuperviewOf:self];
|
||||
[collectionView scrollToItemAtIndexPath:[collectionView indexPathForCell:self]
|
||||
atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:YES];
|
||||
}
|
||||
|
||||
- (IBAction)textFieldDidChange:(UITextField *)textField {
|
||||
|
||||
if (textField == self.passwordField) {
|
||||
NSString *password = self.passwordField.text;
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
TimeToCrack timeToCrack;
|
||||
MPElementEntity *element = [self elementInContext:context];
|
||||
id<MPAlgorithm> algorithm = element.algorithm?: MPAlgorithmDefault;
|
||||
MPAttacker attackHardware = [[MPConfig get].siteAttacker unsignedIntegerValue];
|
||||
if ([algorithm timeToCrack:&timeToCrack passwordOfType:[self elementInContext:context].type byAttacker:attackHardware] ||
|
||||
[algorithm timeToCrack:&timeToCrack passwordString:password byAttacker:attackHardware])
|
||||
PearlMainQueue( ^{
|
||||
self.strengthLabel.text = NSStringFromTimeToCrack( timeToCrack );
|
||||
} );
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)textFieldDidEndEditing:(UITextField *)textField {
|
||||
|
||||
if (textField == self.passwordField || textField == self.loginNameField) {
|
||||
NSString *text = textField.text;
|
||||
textField.enabled = NO;
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPElementEntity *element = [self elementInContext:context];
|
||||
if (!element)
|
||||
return;
|
||||
|
||||
if (textField == self.passwordField) {
|
||||
[element.algorithm saveContent:text toElement:element usingKey:[MPiOSAppDelegate get].key];
|
||||
[PearlOverlay showTemporaryOverlayWithTitle:@"Password Updated" dismissAfter:2];
|
||||
}
|
||||
else if (textField == self.loginNameField) {
|
||||
element.loginName = text;
|
||||
[PearlOverlay showTemporaryOverlayWithTitle:@"Login Updated" dismissAfter:2];
|
||||
}
|
||||
|
||||
[context saveToStore];
|
||||
[self updateAnimated:YES];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (IBAction)doLoginMode:(UIButton *)sender {
|
||||
|
||||
self.loginModeButton.selected = !self.loginModeButton.selected;
|
||||
[self updateAnimated:YES];
|
||||
}
|
||||
|
||||
- (IBAction)doDelete:(UIButton *)sender {
|
||||
|
||||
MPElementEntity *element = [self elementInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
|
||||
if (!element)
|
||||
return;
|
||||
|
||||
[PearlSheet showSheetWithTitle:strf( @"Delete %@?", element.name ) viewStyle:UIActionSheetStyleAutomatic
|
||||
initSheet:nil tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [sheet cancelButtonIndex])
|
||||
return;
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
[context deleteObject:[self elementInContext:context]];
|
||||
[context saveToStore];
|
||||
}];
|
||||
} cancelTitle:@"Cancel" destructiveTitle:@"Delete Site" otherTitles:nil];
|
||||
}
|
||||
|
||||
- (IBAction)doChangeType:(UIButton *)sender {
|
||||
|
||||
[self setMode:MPPasswordCellModePassword animated:YES];
|
||||
|
||||
[PearlSheet showSheetWithTitle:@"Change Password Type" viewStyle:UIActionSheetStyleAutomatic
|
||||
initSheet:^(UIActionSheet *sheet) {
|
||||
MPElementEntity
|
||||
*mainElement = [self elementInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
|
||||
for (NSNumber *typeNumber in [MPAlgorithmDefault allTypes]) {
|
||||
MPElementType type = [typeNumber unsignedIntegerValue];
|
||||
NSString *typeName = [MPAlgorithmDefault nameOfType:type];
|
||||
if (type == mainElement.type)
|
||||
[sheet addButtonWithTitle:strf( @"● %@", typeName )];
|
||||
else
|
||||
[sheet addButtonWithTitle:typeName];
|
||||
}
|
||||
} tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [sheet cancelButtonIndex])
|
||||
return;
|
||||
|
||||
MPElementType type = [[MPAlgorithmDefault allTypes][buttonIndex] unsignedIntegerValue]?: MPElementTypeGeneratedLong;
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPElementEntity *element = [self elementInContext:context];
|
||||
element = [[MPiOSAppDelegate get] changeElement:element saveInContext:context toType:type];
|
||||
[self setElement:element animated:YES];
|
||||
}];
|
||||
} cancelTitle:@"Cancel" destructiveTitle:nil otherTitles:nil];
|
||||
}
|
||||
|
||||
- (IBAction)doEdit:(UIButton *)sender {
|
||||
|
||||
if (self.loginModeButton.selected) {
|
||||
self.loginNameField.enabled = YES;
|
||||
[self.loginNameField becomeFirstResponder];
|
||||
}
|
||||
else if ([self elementInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]].type & MPElementTypeClassStored) {
|
||||
self.passwordField.enabled = YES;
|
||||
[self.passwordField becomeFirstResponder];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)doMode:(UIButton *)sender {
|
||||
|
||||
switch (self.mode) {
|
||||
case MPPasswordCellModePassword:
|
||||
[self setMode:MPPasswordCellModeSettings animated:YES];
|
||||
break;
|
||||
case MPPasswordCellModeSettings:
|
||||
[self setMode:MPPasswordCellModePassword animated:YES];
|
||||
break;
|
||||
}
|
||||
|
||||
[self updateAnimated:YES];
|
||||
}
|
||||
|
||||
- (void)setHighlighted:(BOOL)highlighted {
|
||||
- (IBAction)doUpgrade:(UIButton *)sender {
|
||||
|
||||
[super setHighlighted:highlighted];
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
if (![[self elementInContext:context] migrateExplicitly:YES]) {
|
||||
[PearlOverlay showTemporaryOverlayWithTitle:@"Couldn't Upgrade Site" dismissAfter:2];
|
||||
return;
|
||||
}
|
||||
|
||||
[context saveToStore];
|
||||
[PearlOverlay showTemporaryOverlayWithTitle:@"Site Upgraded" dismissAfter:2];
|
||||
[self updateAnimated:YES];
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)doIncrementCounter:(UIButton *)sender {
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPElementEntity *element = [self elementInContext:context];
|
||||
if (!element || ![element isKindOfClass:[MPElementGeneratedEntity class]])
|
||||
return;
|
||||
|
||||
++((MPElementGeneratedEntity *)element).counter;
|
||||
[context saveToStore];
|
||||
|
||||
[PearlOverlay showTemporaryOverlayWithTitle:@"Generating New Password" dismissAfter:2];
|
||||
[self updateAnimated:YES];
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)doRevealPassword:(UILongPressGestureRecognizer *)recognizer {
|
||||
|
||||
if (recognizer.state != UIGestureRecognizerStateBegan)
|
||||
return;
|
||||
|
||||
if (self.passwordField.secureTextEntry) {
|
||||
self.passwordField.secureTextEntry = NO;
|
||||
|
||||
PearlMainQueueAfter( 3, ^{
|
||||
self.passwordField.secureTextEntry = [[MPiOSConfig get].hidePasswords boolValue];
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)doResetCounter:(UILongPressGestureRecognizer *)recognizer {
|
||||
|
||||
if (recognizer.state != UIGestureRecognizerStateBegan)
|
||||
return;
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPElementEntity *element = [self elementInContext:context];
|
||||
if (!element || ![element isKindOfClass:[MPElementGeneratedEntity class]])
|
||||
return;
|
||||
|
||||
((MPElementGeneratedEntity *)element).counter = 1;
|
||||
[context saveToStore];
|
||||
|
||||
[PearlOverlay showTemporaryOverlayWithTitle:@"Counter Reset" dismissAfter:2];
|
||||
[self updateAnimated:YES];
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)doUse:(id)sender {
|
||||
|
||||
self.selectionButton.selected = YES;
|
||||
|
||||
if (self.transientSite) {
|
||||
[[UIResponder findFirstResponder] resignFirstResponder];
|
||||
[PearlAlert showAlertWithTitle:@"Create Site"
|
||||
message:strf( @"Remember site named:\n%@", self.transientSite )
|
||||
viewStyle:UIAlertViewStyleDefault
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||
if (buttonIndex == [alert cancelButtonIndex]) {
|
||||
self.selectionButton.selected = NO;
|
||||
return;
|
||||
}
|
||||
|
||||
[[MPiOSAppDelegate get]
|
||||
addElementNamed:self.transientSite completion:^(MPElementEntity *element, NSManagedObjectContext *context) {
|
||||
[self copyContentOfElement:element saveInContext:context];
|
||||
PearlMainQueue( ^{
|
||||
self.selectionButton.selected = NO;
|
||||
} );
|
||||
}];
|
||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonYes, nil];
|
||||
return;
|
||||
}
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
[self copyContentOfElement:[self elementInContext:context] saveInContext:context];
|
||||
PearlMainQueue( ^{
|
||||
self.selectionButton.selected = NO;
|
||||
} );
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - UIScrollViewDelegate
|
||||
|
||||
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
|
||||
|
||||
if (roundf( (float)(scrollView.contentOffset.x / self.bounds.size.width) ) == 0.0f)
|
||||
[self setMode:MPPasswordCellModePassword animated:YES];
|
||||
else
|
||||
[self setMode:MPPasswordCellModeSettings animated:YES];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
@@ -68,8 +374,148 @@
|
||||
}
|
||||
|
||||
[UIView animateWithDuration:animated? 0.3f: 0 animations:^{
|
||||
self.layer.shadowOpacity = self.selected? 1: self.highlighted? 0.3f: 0;
|
||||
MPElementEntity *mainElement = [self elementInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
|
||||
|
||||
// UI
|
||||
self.selectionButton.layer.shadowOpacity = self.selectionButton.selected? 1: self.selectionButton.highlighted? 0.3f: 0;
|
||||
self.upgradeButton.alpha = mainElement.requiresExplicitMigration? 1: 0;
|
||||
self.passwordField.alpha = self.loginModeButton.selected? 0: 1;
|
||||
self.loginNameField.alpha = self.loginModeButton.selected? 1: 0;
|
||||
self.modeButton.alpha = self.transientSite? 0: 1;
|
||||
self.loginModeButton.alpha = self.transientSite? 0: 1;
|
||||
self.counterLabel.alpha = self.counterButton.alpha = mainElement.type & MPElementTypeClassGenerated? 1: 0;
|
||||
self.modeButton.selected = self.mode == MPPasswordCellModeSettings;
|
||||
self.pageControl.currentPage = self.mode == MPPasswordCellModePassword? 0: 1;
|
||||
self.strengthLabel.alpha = self.mode == MPPasswordCellModePassword? 0: 1;
|
||||
self.editButton.enabled = self.loginModeButton.selected || mainElement.type & MPElementTypeClassStored;
|
||||
self.modeScrollView.scrollEnabled = !self.transientSite;
|
||||
self.pageControl.alpha = self.transientSite? 0: 1;
|
||||
[self.modeScrollView setContentOffset:CGPointMake( self.mode * self.modeScrollView.frame.size.width, 0 ) animated:animated];
|
||||
|
||||
// Indicator
|
||||
if (self.loginModeButton.selected) {
|
||||
if ([mainElement.loginName length])
|
||||
self.indicatorView.alpha = 0;
|
||||
else {
|
||||
self.indicatorView.alpha = 1;
|
||||
[self.indicatorView removeFromSuperview];
|
||||
[self.modeScrollView addSubview:self.indicatorView];
|
||||
[self.contentView addConstraintsWithVisualFormat:@"V:[indicator][view]" options:NSLayoutFormatAlignAllCenterX
|
||||
metrics:nil views:@{
|
||||
@"indicator" : self.indicatorView,
|
||||
@"view" : self.mode == MPPasswordCellModeSettings? self.editButton: self.modeButton
|
||||
}];
|
||||
}
|
||||
}
|
||||
switch (self.mode) {
|
||||
case MPPasswordCellModePassword:
|
||||
if (mainElement.type & MPElementTypeClassStored)
|
||||
break;
|
||||
case MPPasswordCellModeSettings:
|
||||
break;
|
||||
}
|
||||
|
||||
// Site Name
|
||||
self.siteNameLabel.text = strl( @"%@ - %@", self.transientSite?: mainElement.name,
|
||||
self.transientSite? @"Tap to create": [mainElement.algorithm shortNameOfType:mainElement.type] );
|
||||
|
||||
// Site Password
|
||||
self.passwordField.enabled = NO;
|
||||
self.passwordField.secureTextEntry = [[MPiOSConfig get].hidePasswords boolValue];
|
||||
self.passwordField.attributedPlaceholder = stra(
|
||||
mainElement.type & MPElementTypeClassStored? strl( @"No password" ):
|
||||
mainElement.type & MPElementTypeClassGenerated? strl( @"..." ): @"", @{
|
||||
NSForegroundColorAttributeName : [UIColor whiteColor]
|
||||
} );
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
NSString *password;
|
||||
if (self.transientSite)
|
||||
password = [MPAlgorithmDefault generateContentNamed:self.transientSite ofType:
|
||||
[[MPiOSAppDelegate get] activeUserInContext:context].defaultType?: MPElementTypeGeneratedLong
|
||||
withCounter:1 usingKey:[MPiOSAppDelegate get].key];
|
||||
else
|
||||
password = [[self elementInContext:context] resolveContentUsingKey:[MPiOSAppDelegate get].key];
|
||||
|
||||
TimeToCrack timeToCrack;
|
||||
NSString *timeToCrackString = nil;
|
||||
id<MPAlgorithm> algorithm = mainElement.algorithm?: MPAlgorithmDefault;
|
||||
MPAttacker attackHardware = [[MPConfig get].siteAttacker unsignedIntegerValue];
|
||||
if ([algorithm timeToCrack:&timeToCrack passwordOfType:[self elementInContext:context].type byAttacker:attackHardware] ||
|
||||
[algorithm timeToCrack:&timeToCrack passwordString:password byAttacker:attackHardware])
|
||||
timeToCrackString = NSStringFromTimeToCrack( timeToCrack );
|
||||
|
||||
PearlMainQueue( ^{
|
||||
self.passwordField.text = password;
|
||||
self.strengthLabel.text = timeToCrackString;
|
||||
|
||||
if (!self.loginModeButton.selected) {
|
||||
if ([password length])
|
||||
self.indicatorView.alpha = 0;
|
||||
else {
|
||||
self.indicatorView.alpha = 1;
|
||||
[self.indicatorView removeFromSuperview];
|
||||
[self.modeScrollView addSubview:self.indicatorView];
|
||||
[self.contentView addConstraintsWithVisualFormat:@"V:[indicator][view]" options:NSLayoutFormatAlignAllCenterX
|
||||
metrics:nil views:@{
|
||||
@"indicator" : self.indicatorView,
|
||||
@"view" : self.mode == MPPasswordCellModeSettings? self.editButton: self.modeButton
|
||||
}];
|
||||
}
|
||||
}
|
||||
} );
|
||||
}];
|
||||
|
||||
// Site Counter
|
||||
if ([mainElement isKindOfClass:[MPElementGeneratedEntity class]])
|
||||
self.counterLabel.text = strf( @"%lu", (unsigned long)((MPElementGeneratedEntity *)mainElement).counter );
|
||||
|
||||
// Site Login Name
|
||||
self.loginNameField.enabled = NO;
|
||||
self.loginNameField.text = mainElement.loginName;
|
||||
self.loginNameField.attributedPlaceholder = stra( strl( @"Set login name" ), @{
|
||||
NSForegroundColorAttributeName : [UIColor whiteColor]
|
||||
} );
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)copyContentOfElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context {
|
||||
|
||||
// Copy content.
|
||||
if (self.loginModeButton.selected) {
|
||||
// Login Mode
|
||||
inf( @"Copying login for: %@", element.name );
|
||||
NSString *loginName = element.loginName;
|
||||
if (![loginName length])
|
||||
return;
|
||||
|
||||
PearlMainQueue( ^{
|
||||
[PearlOverlay showTemporaryOverlayWithTitle:strl( @"Login Name Copied" ) dismissAfter:2];
|
||||
[UIPasteboard generalPasteboard].string = loginName;
|
||||
} );
|
||||
|
||||
[element use];
|
||||
[context saveToStore];
|
||||
}
|
||||
else {
|
||||
// Password Mode
|
||||
inf( @"Copying password for: %@", element.name );
|
||||
NSString *password = [element resolveContentUsingKey:[MPAppDelegate_Shared get].key];
|
||||
if (![password length])
|
||||
return;
|
||||
|
||||
PearlMainQueue( ^{
|
||||
[PearlOverlay showTemporaryOverlayWithTitle:strl( @"Password Copied" ) dismissAfter:2];
|
||||
[UIPasteboard generalPasteboard].string = password;
|
||||
} );
|
||||
|
||||
[element use];
|
||||
[context saveToStore];
|
||||
}
|
||||
}
|
||||
|
||||
- (MPElementEntity *)elementInContext:(NSManagedObjectContext *)context {
|
||||
|
||||
return [MPElementEntity existingObjectWithID:_elementOID inContext:context];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPAvatarCell.h
|
||||
// MPAvatarCell
|
||||
//
|
||||
// Created by lhunath on 2014-03-11.
|
||||
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPEntities.h"
|
||||
#import "MPCell.h"
|
||||
#import "MPPasswordCell.h"
|
||||
|
||||
typedef NS_ENUM (NSUInteger, MPContentFieldMode) {
|
||||
MPContentFieldModePassword,
|
||||
MPContentFieldModeUser,
|
||||
};
|
||||
|
||||
@interface MPPasswordLargeCell : MPPasswordCell <UITextFieldDelegate>
|
||||
|
||||
@property(nonatomic) MPElementType type;
|
||||
@property(nonatomic) MPContentFieldMode contentFieldMode;
|
||||
@property(nonatomic, strong) IBOutlet UILabel *typeLabel;
|
||||
@property(nonatomic, strong) IBOutlet UITextField *contentField;
|
||||
@property(nonatomic, strong) IBOutlet UIButton *upgradeButton;
|
||||
@property(nonatomic, strong) IBOutlet UILabel *nameLabel;
|
||||
@property(nonatomic, strong) IBOutlet UIButton *loginButton;
|
||||
|
||||
+ (instancetype)dequeueCellWithType:(MPElementType)type fromCollectionView:(UICollectionView *)collectionView atIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
- (void)update;
|
||||
- (void)updateWithElement:(MPElementEntity *)mainElement;
|
||||
- (void)updateWithTransientSite:(NSString *)siteName;
|
||||
|
||||
- (void)resolveContentOfCellTypeForTransientSite:(NSString *)siteName usingKey:(MPKey *)key result:(void (^)(NSString *result))resultBlock;
|
||||
- (void)resolveContentOfCellTypeForElement:(MPElementEntity *)element usingKey:(MPKey *)key result:(void (^)(NSString *result))resultBlock;
|
||||
|
||||
- (void)willBeginDragging;
|
||||
- (MPElementEntity *)saveContentTypeWithElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context;
|
||||
|
||||
@end
|
||||
@@ -1,271 +0,0 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPAvatarCell.h
|
||||
// MPAvatarCell
|
||||
//
|
||||
// Created by lhunath on 2014-03-11.
|
||||
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPPasswordLargeCell.h"
|
||||
#import "MPiOSAppDelegate.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "MPPasswordLargeGeneratedCell.h"
|
||||
#import "MPPasswordLargeStoredCell.h"
|
||||
#import "MPPasswordTypesCell.h"
|
||||
|
||||
@implementation MPPasswordLargeCell
|
||||
|
||||
#pragma mark - Life
|
||||
|
||||
+ (instancetype)dequeueCellWithType:(MPElementType)type fromCollectionView:(UICollectionView *)collectionView
|
||||
atIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
NSAssert( type != 0 && type != (MPElementType)NSNotFound, @"Cannot dequeue a password cell without a type." );
|
||||
|
||||
NSString *reuseIdentifier;
|
||||
if (type & MPElementTypeClassGenerated)
|
||||
reuseIdentifier = NSStringFromClass( [MPPasswordLargeGeneratedCell class] );
|
||||
else if (type & MPElementTypeClassStored)
|
||||
reuseIdentifier = NSStringFromClass( [MPPasswordLargeStoredCell class] );
|
||||
else
|
||||
Throw( @"Unexpected password type: %@", [MPAlgorithmDefault nameOfType:type] );
|
||||
|
||||
MPPasswordLargeCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
|
||||
cell.type = type;
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (void)awakeFromNib {
|
||||
|
||||
[super awakeFromNib];
|
||||
|
||||
self.layer.cornerRadius = 5;
|
||||
self.layer.shadowOffset = CGSizeZero;
|
||||
self.layer.shadowRadius = 5;
|
||||
self.layer.shadowOpacity = 0;
|
||||
self.layer.shadowColor = [UIColor whiteColor].CGColor;
|
||||
|
||||
[self addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector( didLongPress: )]];
|
||||
|
||||
[self prepareForReuse];
|
||||
}
|
||||
|
||||
- (void)didLongPress:(UILongPressGestureRecognizer *)recognizer {
|
||||
|
||||
if (recognizer.state != UIGestureRecognizerStateBegan)
|
||||
return;
|
||||
|
||||
if (self.contentField.secureTextEntry) {
|
||||
self.contentField.secureTextEntry = NO;
|
||||
PearlMainQueueAfter( 3, ^{
|
||||
self.contentField.secureTextEntry = [[MPiOSConfig get].hidePasswords boolValue];
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
- (void)prepareForReuse {
|
||||
|
||||
_contentFieldMode = 0;
|
||||
self.contentField.text = nil;
|
||||
|
||||
[super prepareForReuse];
|
||||
}
|
||||
|
||||
- (void)update {
|
||||
|
||||
self.loginButton.alpha = 0;
|
||||
self.upgradeButton.alpha = 0;
|
||||
self.nameLabel.text = @"";
|
||||
self.typeLabel.text = @"";
|
||||
self.contentField.text = @"";
|
||||
self.contentField.secureTextEntry = [[MPiOSConfig get].hidePasswords boolValue];
|
||||
self.contentField.attributedPlaceholder = nil;
|
||||
self.contentField.enabled = self.contentFieldMode == MPContentFieldModeUser;
|
||||
self.loginButton.selected = self.contentFieldMode == MPContentFieldModeUser;
|
||||
|
||||
switch (self.contentFieldMode) {
|
||||
case MPContentFieldModePassword: {
|
||||
self.contentField.keyboardType = UIKeyboardTypeDefault;
|
||||
if (self.type & MPElementTypeClassStored)
|
||||
self.contentField.attributedPlaceholder = stra( strl( @"Set custom password" ), @{
|
||||
NSForegroundColorAttributeName : [UIColor whiteColor]
|
||||
} );
|
||||
else if (self.type & MPElementTypeClassGenerated)
|
||||
self.contentField.attributedPlaceholder = stra( strl( @"Generating..." ), @{
|
||||
NSForegroundColorAttributeName : [UIColor whiteColor]
|
||||
} );
|
||||
break;
|
||||
}
|
||||
case MPContentFieldModeUser: {
|
||||
self.contentField.keyboardType = UIKeyboardTypeEmailAddress;
|
||||
self.contentField.attributedPlaceholder = stra( strl( @"Enter your login name" ), @{
|
||||
NSForegroundColorAttributeName : [UIColor whiteColor]
|
||||
} );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateWithTransientSite:(NSString *)siteName {
|
||||
|
||||
[self update];
|
||||
|
||||
self.nameLabel.text = strl( @"%@ - Tap to create", siteName );
|
||||
self.typeLabel.text = [MPAlgorithmDefault nameOfType:self.type];
|
||||
|
||||
[self resolveContentOfCellTypeForTransientSite:siteName usingKey:[MPiOSAppDelegate get].key result:^(NSString *result) {
|
||||
PearlMainQueue( ^{ self.contentField.text = result; } );
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)updateWithElement:(MPElementEntity *)mainElement {
|
||||
|
||||
[self update];
|
||||
|
||||
if (!mainElement)
|
||||
return;
|
||||
|
||||
self.loginButton.alpha = 1;
|
||||
if (mainElement.requiresExplicitMigration)
|
||||
self.upgradeButton.alpha = 1;
|
||||
|
||||
self.nameLabel.text = mainElement.name;
|
||||
if (self.type == (MPElementType)NSNotFound)
|
||||
self.typeLabel.text = @"Delete";
|
||||
else
|
||||
self.typeLabel.text = [mainElement.algorithm nameOfType:self.type];
|
||||
|
||||
switch (self.contentFieldMode) {
|
||||
case MPContentFieldModePassword: {
|
||||
MPKey *key = [MPiOSAppDelegate get].key;
|
||||
if (self.type == mainElement.type)
|
||||
[mainElement resolveContentUsingKey:key result:^(NSString *result) {
|
||||
PearlMainQueue( ^{ self.contentField.text = result; } );
|
||||
}];
|
||||
else
|
||||
[self resolveContentOfCellTypeForElement:mainElement usingKey:key result:^(NSString *result) {
|
||||
PearlMainQueue( ^{ self.contentField.text = result; } );
|
||||
}];
|
||||
break;
|
||||
}
|
||||
case MPContentFieldModeUser: {
|
||||
self.contentField.text = mainElement.loginName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)resolveContentOfCellTypeForTransientSite:(NSString *)siteName usingKey:(MPKey *)key result:(void ( ^ )(NSString *))resultBlock {
|
||||
|
||||
resultBlock( nil );
|
||||
}
|
||||
|
||||
- (void)resolveContentOfCellTypeForElement:(MPElementEntity *)element usingKey:(MPKey *)key result:(void ( ^ )(NSString *))resultBlock {
|
||||
|
||||
resultBlock( nil );
|
||||
}
|
||||
|
||||
- (void)willBeginDragging {
|
||||
}
|
||||
|
||||
- (MPElementEntity *)saveContentTypeWithElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context {
|
||||
|
||||
return [[MPiOSAppDelegate get] changeElement:element saveInContext:context toType:self.type];
|
||||
}
|
||||
|
||||
#pragma mark - UITextFieldDelegate
|
||||
|
||||
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
|
||||
|
||||
[textField resignFirstResponder];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)textFieldDidBeginEditing:(UITextField *)textField {
|
||||
|
||||
UICollectionView *collectionView = [UICollectionView findAsSuperviewOf:self];
|
||||
[collectionView scrollToItemAtIndexPath:[collectionView indexPathForCell:self]
|
||||
atScrollPosition:UICollectionViewScrollPositionTop animated:YES];
|
||||
}
|
||||
|
||||
- (void)textFieldDidEndEditing:(UITextField *)textField {
|
||||
|
||||
if (textField == self.contentField) {
|
||||
NSString *newContent = textField.text;
|
||||
textField.enabled = NO;
|
||||
|
||||
if (self.contentFieldMode == MPContentFieldModeUser)
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPElementEntity *element = [[MPPasswordTypesCell findAsSuperviewOf:self] elementInContext:context];
|
||||
if (!element)
|
||||
return;
|
||||
|
||||
element.loginName = newContent;
|
||||
[context saveToStore];
|
||||
|
||||
PearlMainQueue( ^{
|
||||
[self updateAnimated:YES];
|
||||
[PearlOverlay showTemporaryOverlayWithTitle:@"Login Updated" dismissAfter:2];
|
||||
} );
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (IBAction)doUser:(id)sender {
|
||||
|
||||
switch (self.contentFieldMode) {
|
||||
case MPContentFieldModePassword: {
|
||||
self.contentFieldMode = MPContentFieldModeUser;
|
||||
break;
|
||||
}
|
||||
case MPContentFieldModeUser: {
|
||||
self.contentFieldMode = MPContentFieldModePassword;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)doUpgrade:(UIButton *)sender {
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
if ([[[MPPasswordTypesCell findAsSuperviewOf:self] elementInContext:context] migrateExplicitly:YES]) {
|
||||
[context saveToStore];
|
||||
|
||||
PearlMainQueue( ^{
|
||||
[[MPPasswordTypesCell findAsSuperviewOf:self] reloadData];
|
||||
[PearlOverlay showTemporaryOverlayWithTitle:@"Site Upgraded" dismissAfter:2];
|
||||
} );
|
||||
}
|
||||
else
|
||||
PearlMainQueue( ^{
|
||||
[PearlOverlay showTemporaryOverlayWithTitle:@"Site Not Upgraded" dismissAfter:2];
|
||||
} );
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Properties
|
||||
|
||||
- (void)setContentFieldMode:(MPContentFieldMode)contentFieldMode {
|
||||
|
||||
if (_contentFieldMode == contentFieldMode)
|
||||
return;
|
||||
|
||||
_contentFieldMode = contentFieldMode;
|
||||
|
||||
[[MPPasswordTypesCell findAsSuperviewOf:self] reloadData:self];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,25 +0,0 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPPasswordLargeDeleteCell.h
|
||||
// MPPasswordLargeDeleteCell
|
||||
//
|
||||
// Created by lhunath on 2014-03-19.
|
||||
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPPasswordLargeCell.h"
|
||||
|
||||
@interface MPPasswordLargeDeleteCell : MPPasswordLargeCell
|
||||
|
||||
+ (MPPasswordLargeCell *)dequeueCellFromCollectionView:(UICollectionView *)view atIndexPath:(NSIndexPath *)path;
|
||||
@end
|
||||
@@ -1,39 +0,0 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPPasswordLargeDeleteCell.h
|
||||
// MPPasswordLargeDeleteCell
|
||||
//
|
||||
// Created by lhunath on 2014-03-19.
|
||||
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPPasswordLargeDeleteCell.h"
|
||||
|
||||
@implementation MPPasswordLargeDeleteCell
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
+ (MPPasswordLargeCell *)dequeueCellFromCollectionView:(UICollectionView *)collectionView atIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
MPPasswordLargeCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass( [self class] )
|
||||
forIndexPath:indexPath];
|
||||
cell.type = (MPElementType)NSNotFound;
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (MPElementEntity *)saveContentTypeWithElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context {
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,28 +0,0 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPPasswordLargeGeneratedCell.h
|
||||
// MPPasswordLargeGeneratedCell
|
||||
//
|
||||
// Created by lhunath on 2014-03-19.
|
||||
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPPasswordLargeCell.h"
|
||||
|
||||
@interface MPPasswordLargeGeneratedCell : MPPasswordLargeCell
|
||||
|
||||
@property(strong, nonatomic) IBOutlet UILabel *strengthLabel;
|
||||
@property(strong, nonatomic) IBOutlet UILabel *counterLabel;
|
||||
@property(strong, nonatomic) IBOutlet UIButton *counterButton;
|
||||
|
||||
@end
|
||||
@@ -1,200 +0,0 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPPasswordLargeGeneratedCell.h
|
||||
// MPPasswordLargeGeneratedCell
|
||||
//
|
||||
// Created by lhunath on 2014-03-19.
|
||||
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPPasswordLargeGeneratedCell.h"
|
||||
#import "MPiOSAppDelegate.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "MPPasswordTypesCell.h"
|
||||
|
||||
@interface MPPasswordLargeGeneratedCell()
|
||||
|
||||
@property(nonatomic, weak) NSTimer *hideStrengthTimer;
|
||||
@end
|
||||
|
||||
@implementation MPPasswordLargeGeneratedCell
|
||||
|
||||
- (void)awakeFromNib {
|
||||
|
||||
[super awakeFromNib];
|
||||
|
||||
UILongPressGestureRecognizer *gestureRecognizer = [[UILongPressGestureRecognizer alloc]
|
||||
initWithTarget:self action:@selector( doResetCounterRecognizer: )];
|
||||
[self.counterButton addGestureRecognizer:gestureRecognizer];
|
||||
}
|
||||
|
||||
- (void)prepareForReuse {
|
||||
|
||||
[super prepareForReuse];
|
||||
|
||||
self.strengthLabel.alpha = 0;
|
||||
}
|
||||
|
||||
- (void)willBeginDragging {
|
||||
|
||||
[super willBeginDragging];
|
||||
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.strengthLabel.alpha = 1;
|
||||
}];
|
||||
|
||||
[self.hideStrengthTimer invalidate];
|
||||
self.hideStrengthTimer = [NSTimer scheduledTimerWithTimeInterval:1 block:^(NSTimer *timer) {
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
self.strengthLabel.alpha = 0;
|
||||
}];
|
||||
} repeats:NO];
|
||||
}
|
||||
|
||||
- (void)update {
|
||||
|
||||
[super update];
|
||||
|
||||
self.counterLabel.alpha = self.counterButton.alpha = 0;
|
||||
}
|
||||
|
||||
- (void)updateWithElement:(MPElementEntity *)mainElement {
|
||||
|
||||
[super updateWithElement:mainElement];
|
||||
|
||||
MPElementGeneratedEntity *generatedElement = [self generatedElement:mainElement];
|
||||
if (generatedElement)
|
||||
self.counterLabel.text = strf( @"%lu", (unsigned long)generatedElement.counter );
|
||||
else
|
||||
self.counterLabel.text = @"1";
|
||||
|
||||
if (mainElement && !mainElement.requiresExplicitMigration)
|
||||
self.counterLabel.alpha = self.counterButton.alpha = 1;
|
||||
}
|
||||
|
||||
- (void)resolveContentOfCellTypeForTransientSite:(NSString *)siteName usingKey:(MPKey *)key result:(void ( ^ )(NSString *))resultBlock {
|
||||
|
||||
PearlNotMainQueue( ^{
|
||||
resultBlock( [MPAlgorithmDefault generateContentNamed:siteName ofType:self.type withCounter:1 usingKey:key] );
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)resolveContentOfCellTypeForElement:(MPElementEntity *)element usingKey:(MPKey *)key result:(void ( ^ )(NSString *))resultBlock {
|
||||
|
||||
id<MPAlgorithm> algorithm = element.algorithm;
|
||||
NSString *siteName = element.name;
|
||||
|
||||
PearlNotMainQueue( ^{
|
||||
resultBlock( [algorithm generateContentNamed:siteName ofType:self.type withCounter:1 usingKey:key] );
|
||||
} );
|
||||
}
|
||||
|
||||
- (MPElementEntity *)saveContentTypeWithElement:(MPElementEntity *)element saveInContext:(NSManagedObjectContext *)context {
|
||||
|
||||
element = [super saveContentTypeWithElement:element saveInContext:context];
|
||||
|
||||
MPElementGeneratedEntity *generatedElement = [self generatedElement:element];
|
||||
if (generatedElement) {
|
||||
generatedElement.counter = [self.counterLabel.text intValue];
|
||||
[context saveToStore];
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (IBAction)doIncrementCounter:(UIButton *)sender {
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPElementGeneratedEntity *generatedElement = [self generatedElementInContext:context];
|
||||
if (!generatedElement)
|
||||
return;
|
||||
|
||||
++generatedElement.counter;
|
||||
[context saveToStore];
|
||||
|
||||
PearlMainQueue( ^{
|
||||
[self updateAnimated:YES];
|
||||
[PearlOverlay showTemporaryOverlayWithTitle:@"Counter Incremented" dismissAfter:2];
|
||||
} );
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)doResetCounterRecognizer:(UILongPressGestureRecognizer *)gestureRecognizer {
|
||||
|
||||
if (gestureRecognizer.state != UIGestureRecognizerStateBegan)
|
||||
return;
|
||||
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPElementGeneratedEntity *generatedElement = [self generatedElementInContext:context];
|
||||
if (!generatedElement)
|
||||
return;
|
||||
|
||||
generatedElement.counter = 1;
|
||||
[context saveToStore];
|
||||
|
||||
PearlMainQueue( ^{
|
||||
[self updateAnimated:YES];
|
||||
[PearlOverlay showTemporaryOverlayWithTitle:@"Counter Reset" dismissAfter:2];
|
||||
} );
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Properties
|
||||
|
||||
- (void)setType:(MPElementType)type {
|
||||
|
||||
[super setType:type];
|
||||
|
||||
switch (type) {
|
||||
case MPElementTypeGeneratedMaximum:
|
||||
self.strengthLabel.text = @"422 quintillion years";
|
||||
break;
|
||||
case MPElementTypeGeneratedLong:
|
||||
self.strengthLabel.text = @"1.4 years";
|
||||
break;
|
||||
case MPElementTypeGeneratedMedium:
|
||||
self.strengthLabel.text = @"2 seconds";
|
||||
break;
|
||||
case MPElementTypeGeneratedBasic:
|
||||
self.strengthLabel.text = @"trivial";
|
||||
break;
|
||||
case MPElementTypeGeneratedShort:
|
||||
self.strengthLabel.text = @"trivial";
|
||||
break;
|
||||
case MPElementTypeGeneratedPIN:
|
||||
self.strengthLabel.text = @"trivial";
|
||||
break;
|
||||
case MPElementTypeStoredPersonal:
|
||||
self.strengthLabel.text = @"";
|
||||
break;
|
||||
case MPElementTypeStoredDevicePrivate:
|
||||
self.strengthLabel.text = @"";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (MPElementGeneratedEntity *)generatedElementInContext:(NSManagedObjectContext *)context {
|
||||
|
||||
return [self generatedElement:[[MPPasswordTypesCell findAsSuperviewOf:self] elementInContext:context]];
|
||||
}
|
||||
|
||||
- (MPElementGeneratedEntity *)generatedElement:(MPElementEntity *)element {
|
||||
|
||||
if (![element isKindOfClass:[MPElementGeneratedEntity class]])
|
||||
return nil;
|
||||
|
||||
return (MPElementGeneratedEntity *)element;
|
||||
}
|
||||
|
||||
@end
|
||||