2
0

Compare commits

...

39 Commits

Author SHA1 Message Date
Maarten Billemont
3ed6b93736 Keep tarballs in site directory. 2017-04-22 12:33:46 -04:00
Maarten Billemont
56a515c5ea Improve clean methods. 2017-04-22 12:20:52 -04:00
Maarten Billemont
15ac7a2dbf Improve font size and font scaling fixes. 2017-04-22 12:00:47 -04:00
Maarten Billemont
c5c7999753 Ensure the tree is clean before building the distribution archive. 2017-04-22 11:15:07 -04:00
Maarten Billemont
bb58ed0169 Update In-App Settings Kit. 2017-04-22 10:03:31 -04:00
Maarten Billemont
4545a5c745 Improve readability of some of the smaller and thinner fonts. 2017-04-22 09:52:28 -04:00
Maarten Billemont
da8c7064fe Support for reduced transparency. 2017-04-20 22:29:10 -04:00
Maarten Billemont
d9bd604436 Improve support for import/export headers on iOS/Mac.
[ADDED]     iOS/macOS support for Full Name, Algorithm and Default Type mpsites headers.
2017-04-19 21:58:10 -04:00
Maarten Billemont
c99252809d Disable ADHOC and tester functionality / bypasses. 2017-04-18 20:31:38 -04:00
Maarten Billemont
d704f451a3 Fixed issue causing emergency generator password button to not respond. 2017-04-17 22:27:36 -04:00
Maarten Billemont
2c9ab5d153 Fixed issue when cancelling touchID login. 2017-04-17 22:13:01 -04:00
Maarten Billemont
d5d33da12f Fixed UI issues with passwords list and drop-down animation + support for phrase and name default types.
[FIXED]     Fixed issues with animating changes in the passwords list during certain & multiple events.
[FIXED]     Slightly broken UI prior to drop-down animation & improved animation a bit.
[ADDED]     Phrase & Name default password types.
2017-04-17 21:57:08 -04:00
Maarten Billemont
cbef1a611b Update Mac binary to 2.5-mac-2 2017-04-16 13:03:15 -04:00
Maarten Billemont
0a1f215a1a Style login name, add login generated gear, improve logic for when to show login name. 2017-04-15 10:57:52 -04:00
Maarten Billemont
907d2a8ca6 Fixed key disappearing from NSCache after suspension and not being reloaded from keychain. 2017-04-15 02:28:11 -04:00
Maarten Billemont
89f6e77f67 Hack to ensure Xcode doesn't incorrectly link libsodium.dylib instead of libsodium.a 2017-04-14 17:23:41 -04:00
Maarten Billemont
f2fb16a0b9 Improved library check that doesn't depend on wording of error message. 2017-04-14 17:01:24 -04:00
Maarten Billemont
e3edd42b88 Fixed a bug in PearlMutableStaticTableViewController. 2017-04-14 16:10:11 -04:00
Maarten Billemont
cc5d246d7d Update Storyboard. 2017-04-14 13:20:13 -04:00
Maarten Billemont
ca320de6d9 Fix detection of ios platforms. 2017-04-14 13:08:23 -04:00
Maarten Billemont
ae979d7240 Fix up the benefits wording. 2017-04-14 10:13:44 -04:00
Maarten Billemont
eb1c443940 Small README tweaks. 2017-04-14 09:58:35 -04:00
Maarten Billemont
dadcefc9bf FAQ. 2017-04-14 09:51:44 -04:00
Maarten Billemont
cdbaec9751 Explain configuration requirements for the Android SDK. 2017-04-14 09:13:31 -04:00
Maarten Billemont
f48d480c77 Compacted build instructions a bit. 2017-04-14 09:01:04 -04:00
Maarten Billemont
23aae490df Update version calculation. 2017-04-14 00:43:34 -04:00
Maarten Billemont
3fcf1131ac Need to -resume the task to start it, fixes issue with importing sites. 2017-04-14 00:24:34 -04:00
Maarten Billemont
2bdec415e9 Update Travis to ensure mpw-tests is built. 2017-04-13 14:07:02 -04:00
Maarten Billemont
4c12f4af56 Amend the build instructions to mention libsodium and default build only to mpw. 2017-04-13 11:51:05 -04:00
Maarten Billemont
d91140439a Properly deactivate when copying password so previous app regains focus and signOut happens properly. 2017-04-13 11:33:03 -04:00
Maarten Billemont
a7912dd1b7 Small format update. 2017-04-13 00:06:46 -04:00
Maarten Billemont
05391d893e Fix slow fuzzy queries. 2017-04-12 23:41:17 -04:00
Maarten Billemont
2047422b08 Generate libsodium's ios/osx libs first run. 2017-04-10 13:29:52 -04:00
Maarten Billemont
e3fffc1923 Migrate from Tarsnap's scrypt to libsodium. 2017-04-10 11:43:55 -04:00
Maarten Billemont
9bf50569cc Fix some remaining references to libscrypt. 2017-04-09 08:32:34 -04:00
Maarten Billemont
9ef265d9de Don't add scrypt objects in twice. 2017-04-08 16:48:20 -04:00
Maarten Billemont
385f347b33 We don't need libscrypt when linking against sodium. 2017-04-08 16:20:58 -04:00
Maarten Billemont
4058d33202 Support for dynamically linking libscrypt & libsodium as alternative to statically linking Tarsnap's scrypt. 2017-04-08 14:25:54 -04:00
Maarten Billemont
98c5ee3425 Update website for 2.5-CLI-1 release and symlinks. 2017-04-07 22:41:39 -04:00
63 changed files with 2004 additions and 1468 deletions

1
.gitignore vendored
View File

@@ -40,6 +40,7 @@ core/c/lib/*/src
core/c/lib/include
platform-independent/cli-c/cli/*.o
platform-independent/cli-c/mpw-*.tar.gz
platform-independent/cli-c/mpw-*.tar.gz.sig
platform-independent/cli-c/mpw
platform-independent/cli-c/mpw-bench
platform-independent/cli-c/mpw-tests

3
.gitmodules vendored
View File

@@ -19,3 +19,6 @@
[submodule "MasterPassword/Web/js/mpw-js"]
path = platform-independent/web-js/js/mpw-js
url = https://github.com/tmthrgd/mpw-js.git
[submodule "platform-darwin/External/libsodium"]
path = platform-darwin/External/libsodium
url = https://github.com/jedisct1/libsodium.git

View File

@@ -4,6 +4,7 @@ env: TERM=dumb SHLVL=0
git:
submodules: true
script:
- "( cd ./platform-independent/cli-c && ./clean && ./build && ./mpw-tests )"
- "( brew install libsodium )"
- "( cd ./platform-independent/cli-c && ./clean && targets='mpw mpw-bench mpw-tests' ./build && ./mpw-tests )"
- "( xcodebuild -workspace platform-darwin/MasterPassword.xcworkspace -configuration 'Test' -scheme 'MasterPassword iOS' -sdk iphonesimulator )"
- "( xcodebuild -workspace platform-darwin/MasterPassword.xcworkspace -configuration 'Test' -scheme 'MasterPassword macOS' )"

View File

@@ -15,13 +15,23 @@ To skip the intro and go straight to the information on how to use the code, [cl
Master Password is available for [📲 iOS](https://itunes.apple.com/app/id510296984), [🖥 macOS](https://ssl.masterpasswordapp.com/masterpassword-mac.zip), [📲 Android](https://ssl.masterpasswordapp.com/masterpassword-android.apk), [🖥 Desktop](https://ssl.masterpasswordapp.com/masterpassword-gui.jar), and [⌨ Console](https://ssl.masterpasswordapp.com/masterpassword-cli.tar.gz).
Master Password is also available from the following package managers: [macOS: Homebrew](https://brew.sh/). Get in touch if you are interested in adding Master Password to any other package managers.
Master Password is also available from the following package managers: [macOS: Homebrew](https://brew.sh/) (`brew install mpw`).
Get in touch if you are interested in adding Master Password to any other package managers.
There are many reasons for using Master Password instead of an ordinary password manager, read below for the details, but if you want my personal favourites, they would be:
- I don't need to worry about keeping backups of my countless authentication credentials.
- I don't need to worry that when I travel, I might not have access to my passwords vault.
- I don't need to trust an external party, proprietary code or a service to be online and stay online.
- If I feel at risk of my device being stolen or confiscated, I can set a fake master password, delete my user or wipe it worry-free.
We also have a [Frequently Asked Questions](#faq).
## What is a password?
The "password". Somehow, passwords have become the default solution to authentication across the web. We've long since accepted this as the way things are, but let's stop to think for a moment about what passwords actually are:
Ah, the "password". Somehow, passwords have become the default solution to authentication across the web. We've long since accepted this as the way things are, but let's stop to think for a moment about what passwords actually are:
A password is a secret that is known only to the party providing a service and the party that should be allowed access to this service.
@@ -69,12 +79,12 @@ Master Password is *not* a password manager. It does not store your website pas
## Benefits
- You don't need to come up with a secure password every time you make a new account - Master Password gives you the key for it.
- You don't need to try to remember a password you created two years ago for that one account - Master Password just gives you the key for it.
- You don't need to that you can't get into that account you made at work when you come home because you don't have your work passwords with you - Master Password is always available.
- You don't need to try to keep password lists in sync or stored somewhere easily accessible - Master Password is always available.
- You don't need to worry what you'll do if your computer dies or you need to log into your bank while you're in the airport transit zone - Master Password is always available.
- You don't need to worry about your password manager website getting hacked, your phone getting duplicated, somebody taking a picture of your passwords book - Master Password keeps no records.
- You don't need to think up a new strong password every time you make a new account - Master Password gives you the key for it.
- You don't need to try remembering a password you created two years ago for that one account - Master Password just gives you the key for it.
- You don't need to worry about getting into that account you made at work after you come home because you don't have your office passwords with you - Master Password is availale everywhere, even offline.
- You don't need to try to keep password lists in sync or stored somewhere easily accessible - Master Password keys can be created anywhere.
- You don't need to worry what you'll do if your computer dies or you need to log into your bank while you're in the airport transit zone - your Master Password keys are always available, even when starting empty.
- You don't need to worry about your password manager website getting hacked, your phone getting duplicated, somebody taking a picture of your passwords book - Master Password stores no secrets.
@@ -94,6 +104,35 @@ We standardize `user-name` as your full name, `site-name` as the domain name of
## FAQ
1. If I lose my master password and need to set a new one, will I need to change all of my site passwords?
Yes. If your master password is compromised, it is only sensible for you to change all of your site passwords. Just like if you lose the keys in your pocket, you'll have to change all the locks they open. Master Password effectively enforces this security practice.
2. But what if I just forget my master password or I just want to change it to something else?
Sorry, still yes. Your master password is the secret component to your Master Password identity. If it changes, your identity changes. I wholly encourage you to think very carefully about what makes for a really memorable and good master password before just diving in with something lazy. A short phrase works great, eg. `banana coloured duckling`.
3. Doesn't this mean an attacker can reverse my master password from any of my site passwords?
Technically, yes. Practically, no.
You could argue that site passwords are "breadcrumbs" of your master password, but the same argument would suggest encrypted messages are breadcrumbs to the encryption key. Encryption works because it is computationally unfeasible to "guess" the encryption key that made the encrypted message, just like Master Password works because it is computationally unfeasible to "guess" your master password that made the site password.
4. The second step is just a HMAC-SHA-256, doesn't that make the SCRYPT completely pointless?
No. They are used for different reasons and one is not weaker than the other.
HMAC-SHA-256 is much faster to compute than SCRYPT, which leads some people to think "all an attacker needs to do is brute-force the SHA and ignore the SCRYPT". The reality is that the HMAC-SHA-256 guards a 64-byte authentication key (the `master-key`) which makes the search space for brute-forcing the HMAC wildly too large to compute.
The `master-password` on the other hand, is only a simple phrase, which means its search space is much smaller. This is why it is guarded by a much tougher SCRYPT operation.
5. I have another question.
Please don't hesitate to [get in touch](#support), we're more than happy to answer all your Master Password questions. Any problems or suggestions can be reported [as GitHub issues](https://github.com/Lyndir/MasterPassword/issues).
# Source Code
@@ -146,6 +185,10 @@ Go into the `gradle` directory and run `./gradlew build`. All Java components w
- `platform-android/build/outputs/apk`:
contains the Android application package. Install it on your Android device.
Note that in order to build the Android application, you will need to have the Android SDK installed and either have the environment variable `ANDROID_HOME` set to its location or a `gradle/local.properties` file with its location, eg. (for Homebrew users who installed the SDK using `brew install android-sdk`):
sdk.dir=/usr/local/opt/android-sdk
### Native CLI
@@ -158,34 +201,42 @@ For example:
./build && sudo ./install
mpw -h
The build has a few dependencies you should have installed before running it:
Normally, this is all you need to do, however note that there are a few dependencies that need to be met, depending on which targets you are building (by default, only the `mpw` target is built):
- `mpw`: `openssl-dev`, `ncurses-dev` (if `mpw_color=1`)
- `mpw-bench`: `openssl-dev`
- `mpw-tests`: `openssl-dev`, `libxml2`
- `mpw`
There are a few different ways you can modify the build process:
The C implementation depends either on `libsodium` or Tarsnap's `scrypt` and `openssl-dev`.
- You can change the targets that should be built. By default, all targets are built. These are the available targets:
- `mpw`: This is the standard command-line `mpw` tool which implements all Master Password features.
- `mpw-tests`: This is a tool to perform the standard tests script on the `mpw` implementation.
- `mpw-bench`: This is a tool to run a benchmark on the `mpw` implementation, comparing it to the performance of other algorithms.
- You can specify custom arguments to the compiler, pass them as arguments to the build script.
- The build process involves some optionals, they can by toggled from their default setting by passing variables:
- `mpw_color`: [default: 1] Colorized Identicon, depends on
We recommend you install `libsodium`. If `libsodium` is not installed when `./build` is executed, the script will try to download and statically link Tarsnap's `scrypt` instead. Tarsnap's `scrypt` depends on you having `openssl-dev` installed.
To change the targets to build, use:
If you have `mpw_color` enabled (it is enabled by default), the build also depends on `ncurses-dev` to communicate with the terminal.
targets='mpw mpw-bench' ./build
- `mpw-bench`
To add a library search path, use:
This tool compares the performance of a few cryptographic algorithms, including bcrypt. The `./build` script will try to automatically download and statically link `bcrypt`.
- `mpw-tests`
This tool runs a suite of tests to ensure the correct passwords are being generated by the algorithm under various circumstances. The test suite is declared in `mpw-tests.xml` which needs to exist in the current working directory when running the tool. In addition, `libxml2` is used to parse the file, so this target depends on you having it installed when running `./build`.
Finally, there are a few different ways you can modify the build process.
To build additional targets, set the `targets` environment variable:
targets='mpw mpw-tests' ./build
To pass additional compiler arguments, eg. add a library search path, pass them as arguments to the script:
./build -L/usr/local/lib
Change an optional feature:
There are a few toggleable features, to change them, pass them as environment variables:
mpw_color=0 ./build
Currently, there is only one toggleable feature:
- `mpw_color`: [default: 1] Colorized Identicon, depends on `ncurses-dev`.
## Support

View File

@@ -1,4 +1,4 @@
home=http://www.tarsnap.com/scrypt.html
git=https://github.com/Tarsnap/scrypt.git
pkg=http://www.tarsnap.com/scrypt/scrypt-1.2.0.tgz
pkg_sha256=1754bc89405277c8ac14220377a4c240ddc34b1ce70882aa92cd01bfdc8569d4
pkg=https://www.tarsnap.com/scrypt/scrypt-1.2.1.tgz
pkg_sha256=4621f5e7da2f802e20850436219370092e9fcda93bd598f6d4236cce33f4c577

View File

@@ -20,14 +20,22 @@
#include <stdlib.h>
#include <string.h>
#ifdef COLOR
#if COLOR
#include <unistd.h>
#include <curses.h>
#include <term.h>
#endif
#include <scrypt/sha256.h>
#if HAS_CPERCIVA
#include <scrypt/crypto_scrypt.h>
#include <scrypt/sha256.h>
#elif HAS_SODIUM
#include "sodium.h"
#endif
#ifndef trc
int mpw_verbosity;
#endif
#include "mpw-util.h"
@@ -85,30 +93,62 @@ uint8_t const *mpw_scrypt(const size_t keySize, const char *secret, const uint8_
if (!key)
return NULL;
#if HAS_CPERCIVA
if (crypto_scrypt( (const uint8_t *)secret, strlen( secret ), salt, saltSize, N, r, p, key, keySize ) < 0) {
mpw_free( key, keySize );
return NULL;
}
#elif HAS_SODIUM
if (crypto_pwhash_scryptsalsa208sha256_ll( (const uint8_t *)secret, strlen( secret ), salt, saltSize, N, r, p, key, keySize) != 0 ) {
mpw_free( key, keySize );
return NULL;
}
#endif
return key;
}
uint8_t const *mpw_hmac_sha256(const uint8_t *key, const size_t keySize, const uint8_t *salt, const size_t saltSize) {
#if HAS_CPERCIVA
uint8_t *const buffer = malloc( 32 );
if (!buffer)
return NULL;
HMAC_SHA256_Buf( key, keySize, salt, saltSize, buffer );
return buffer;
#elif HAS_SODIUM
uint8_t *const buffer = malloc( crypto_auth_hmacsha256_BYTES );
if (!buffer)
return NULL;
crypto_auth_hmacsha256_state state;
if (crypto_auth_hmacsha256_init( &state, key, keySize ) != 0 ||
crypto_auth_hmacsha256_update( &state, salt, saltSize ) != 0 ||
crypto_auth_hmacsha256_final( &state, buffer ) != 0) {
mpw_free( buffer, crypto_auth_hmacsha256_BYTES );
return NULL;
}
return buffer;
#endif
return NULL;
}
const char *mpw_id_buf(const void *buf, size_t length) {
#if HAS_CPERCIVA
uint8_t hash[32];
SHA256_Buf( buf, length, hash );
return mpw_hex( hash, 32 );
#elif HAS_SODIUM
uint8_t hash[crypto_hash_sha256_BYTES];
crypto_hash_sha256( hash, buf, length );
return mpw_hex( hash, crypto_hash_sha256_BYTES );
#endif
}
static char **mpw_hex_buf = NULL;
@@ -144,10 +184,10 @@ static int initputvar() {
if (!isatty(STDERR_FILENO))
return 0;
if (putvarc)
free(putvarc);
free( putvarc );
if (!termsetup) {
int status;
if (! (termsetup = (setupterm(NULL, STDERR_FILENO, &status) == OK && status == 1))) {
if (! (termsetup = (setupterm( NULL, STDERR_FILENO, &status ) == 0 && status == 1))) {
wrn( "Terminal doesn't support color (setupterm errno %d).\n", status );
return 0;
}
@@ -174,8 +214,9 @@ const char *mpw_identicon(const char *fullName, const char *masterPassword) {
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""
};
uint8_t identiconSeed[32];
HMAC_SHA256_Buf( masterPassword, strlen( masterPassword ), fullName, strlen( fullName ), identiconSeed );
const uint8_t *identiconSeed = mpw_hmac_sha256( (const uint8_t *)masterPassword, strlen( masterPassword ), (const uint8_t *)fullName, strlen( fullName ) );
if (!identiconSeed)
return NULL;
char *colorString, *resetString;
#ifdef COLOR
@@ -203,6 +244,7 @@ const char *mpw_identicon(const char *fullName, const char *masterPassword) {
accessory[identiconSeed[3] % (sizeof( accessory ) / sizeof( accessory[0] ))],
resetString );
mpw_free( identiconSeed, 32 );
free( colorString );
free( resetString );
return identicon;

View File

@@ -22,7 +22,7 @@
//// Logging.
#ifndef trc
int mpw_verbosity;
extern int mpw_verbosity;
#define trc_level 3
#define trc(...) \
if (mpw_verbosity >= 3) \

View File

@@ -1 +0,0 @@
/Users/lhunath/annex/secret/release-com.lyndir.masterpassword.jks

View File

@@ -12,13 +12,16 @@
93D3922A53E41A54832E90D9 /* PearlOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D390FADEB325D8D54A957D /* PearlOverlay.m */; };
93D39262A8A97DB748213309 /* PearlEMail.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D393BB973253D4BAAC84AA /* PearlEMail.m */; };
93D3928D629EA563F9EC4909 /* NSPersistentStore+PearlMigration.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399C2F3D48E57C4803BDC /* NSPersistentStore+PearlMigration.m */; };
93D392A33CCE85431E910C7B /* NSOrderedSetOrArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39789AAF49338F8AC8B02 /* NSOrderedSetOrArray.m */; };
93D392A8777DC30C11361647 /* UITextView+PearlAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39AA10CD00D05937671B1 /* UITextView+PearlAttributes.h */; };
93D392EC39DA43C46C692C12 /* NSDictionary+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */; };
93D392FD5E2052F7D7DB3774 /* NSString+MPMarkDown.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39C41A27AA42D044D68AE /* NSString+MPMarkDown.m */; };
93D3932889B6B4206E66A6D6 /* PearlEMail.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39F7C9F47BF6387FBC5C3 /* PearlEMail.h */; };
93D39392DEDA376F93C6C718 /* MPCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39BAA71DE51B4D8A1286C /* MPCell.m */; };
93D3939661CE37180AF7CD6A /* MPStoreViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3957D76F71A652716EECC /* MPStoreViewController.m */; };
93D393AA69A1193401160418 /* UIView+AlphaScale.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39488AB33616661725929 /* UIView+AlphaScale.m */; };
93D393DB5325820241BA90A7 /* PearlSizedTextView.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39A4759186F6D2D34AA6B /* PearlSizedTextView.h */; };
93D3942C1B117EE4851AA7B6 /* UIView+Visible.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3952910EDB8E0EBC94BA9 /* UIView+Visible.m */; };
93D394982CBD25D46692DD7C /* MPWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3990E0CD1B5CF9FBB2C07 /* MPWebViewController.m */; };
93D394B5036C882B33C71872 /* MPPasswordsSegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39E7A12CC352B2825AA66 /* MPPasswordsSegue.m */; };
93D39508A6814612A5B3C226 /* MPMessageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399B36CDB2004D7C51391 /* MPMessageViewController.m */; };
@@ -27,6 +30,7 @@
93D3954FCE045A3CC7E804B7 /* MPUsersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399E571F61E50A9BF8FAF /* MPUsersViewController.m */; };
93D3957237D303DE2D38C267 /* MPAvatarCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39B381350802A194BF332 /* MPAvatarCell.m */; };
93D39577FD8BB0945DB2F0A3 /* MPAlgorithmV3.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39FD9623E8D5571C0AEB3 /* MPAlgorithmV3.m */; };
93D3959696396A91961C6148 /* UIView+AlphaScale.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D392D76C091DEA3319F11D /* UIView+AlphaScale.h */; };
93D395B715D15F2B56F2A2EE /* mpw-types.c in Sources */ = {isa = PBXBuildFile; fileRef = 93D392C5A6572DB0EB5B82C8 /* mpw-types.c */; };
93D395F08A087F8A24689347 /* NSArray+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */; };
93D39673DDC085BE72C34D7C /* MPPopdownSegue.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39B050DD5F55E9794EFD4 /* MPPopdownSegue.m */; };
@@ -41,6 +45,7 @@
93D399433EA75E50656040CB /* Twitter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93D394077F8FAB8167647187 /* Twitter.framework */; };
93D39943D01E70DAC3B0DF76 /* mpw-util.c in Sources */ = {isa = PBXBuildFile; fileRef = 93D396C311C3725870343EE0 /* mpw-util.c */; };
93D399D7E08A142776A74CB8 /* MPOverlayViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D395105935859D71679931 /* MPOverlayViewController.m */; };
93D399E4BC1E092A8C8B12AE /* NSOrderedSetOrArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39FBF8FCEB4C106272334 /* NSOrderedSetOrArray.h */; };
93D39A27F2506C6FEEF9C588 /* MPAlgorithmV2.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D399A8E3181B442D347CD7 /* MPAlgorithmV2.m */; };
93D39A53D76CA70786423458 /* UICollectionView+PearlReloadFromArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39246FC21C6E63E35D615 /* UICollectionView+PearlReloadFromArray.h */; };
93D39A5FF670957C0AF8298D /* MPPasswordCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39DEA995041A13DC9CAF7 /* MPPasswordCell.m */; };
@@ -51,6 +56,7 @@
93D39B842AB9A5D072810D76 /* NSError+PearlFullDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */; };
93D39B8F90F58A5D158DDBA3 /* MPPasswordsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3924EE15017F8A12CB436 /* MPPasswordsViewController.m */; };
93D39BA1EA3CAAC8A220B4A6 /* MPAppSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3916C1D8F1427DFBDEBCA /* MPAppSettingsViewController.m */; };
93D39BFB5F5F9337F6565DE3 /* UIView+Visible.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D39B7B765546B1F1900CB7 /* UIView+Visible.h */; };
93D39C34FE35830EF5BE1D2A /* NSArray+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D396D04E57792A54D437AC /* NSArray+Indexing.h */; };
93D39D47FC623E91FC39D20C /* UICollectionView+PearlReloadFromArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3908DF8EABBD952065DC0 /* UICollectionView+PearlReloadFromArray.m */; };
93D39D596A2E376D6F6F5DA1 /* MPCombinedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D393310223DDB35218467A /* MPCombinedViewController.m */; };
@@ -64,6 +70,23 @@
DA071BF3190187FE00179766 /* empty@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA071BF1190187FE00179766 /* empty@2x.png */; };
DA071BF4190187FE00179766 /* empty.png in Resources */ = {isa = PBXBuildFile; fileRef = DA071BF2190187FE00179766 /* empty.png */; };
DA095E75172F4CD8001C948B /* MPLogsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3979190DACEBD1F6AE9F4 /* MPLogsViewController.m */; };
DA0979171E9A81EE00F0BFE8 /* libsodium.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA0979161E9A81EE00F0BFE8 /* libsodium.a */; };
DA0CC5291EAB99BA009A8ED9 /* IASKAppSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5071EAB99BA009A8ED9 /* IASKAppSettingsViewController.m */; };
DA0CC52A1EAB99BA009A8ED9 /* IASKAppSettingsWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5091EAB99BA009A8ED9 /* IASKAppSettingsWebViewController.m */; };
DA0CC52B1EAB99BA009A8ED9 /* IASKMultipleValueSelection.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC50B1EAB99BA009A8ED9 /* IASKMultipleValueSelection.m */; };
DA0CC52C1EAB99BA009A8ED9 /* IASKSpecifierValuesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC50D1EAB99BA009A8ED9 /* IASKSpecifierValuesViewController.m */; };
DA0CC52D1EAB99BA009A8ED9 /* IASKSettingsReader.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5111EAB99BA009A8ED9 /* IASKSettingsReader.m */; };
DA0CC52E1EAB99BA009A8ED9 /* IASKSettingsStore.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5131EAB99BA009A8ED9 /* IASKSettingsStore.m */; };
DA0CC52F1EAB99BA009A8ED9 /* IASKSettingsStoreFile.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5151EAB99BA009A8ED9 /* IASKSettingsStoreFile.m */; };
DA0CC5301EAB99BA009A8ED9 /* IASKSettingsStoreUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5171EAB99BA009A8ED9 /* IASKSettingsStoreUserDefaults.m */; };
DA0CC5311EAB99BA009A8ED9 /* IASKSpecifier.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5191EAB99BA009A8ED9 /* IASKSpecifier.m */; };
DA0CC5321EAB99BA009A8ED9 /* IASKPSSliderSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC51C1EAB99BA009A8ED9 /* IASKPSSliderSpecifierViewCell.m */; };
DA0CC5331EAB99BA009A8ED9 /* IASKPSTextFieldSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC51E1EAB99BA009A8ED9 /* IASKPSTextFieldSpecifierViewCell.m */; };
DA0CC5341EAB99BA009A8ED9 /* IASKSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5201EAB99BA009A8ED9 /* IASKSlider.m */; };
DA0CC5351EAB99BA009A8ED9 /* IASKSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5221EAB99BA009A8ED9 /* IASKSwitch.m */; };
DA0CC5361EAB99BA009A8ED9 /* IASKTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5241EAB99BA009A8ED9 /* IASKTextField.m */; };
DA0CC5371EAB99BA009A8ED9 /* IASKTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5261EAB99BA009A8ED9 /* IASKTextView.m */; };
DA0CC5381EAB99BA009A8ED9 /* IASKTextViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC5281EAB99BA009A8ED9 /* IASKTextViewCell.m */; };
DA24EBAE19DAD08900FF010B /* tip_basic_black_top.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD38941711E29700CF925C /* tip_basic_black_top.png */; };
DA24EBAF19DAD08C00FF010B /* tip_basic_black_top@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD38951711E29700CF925C /* tip_basic_black_top@2x.png */; };
DA24EBE819DAD6DE00FF010B /* Icon-320.png in Resources */ = {isa = PBXBuildFile; fileRef = DA24EBE619DAD6DE00FF010B /* Icon-320.png */; };
@@ -71,8 +94,8 @@
DA24EBEA19DAD6EE00FF010B /* Icon-Small.png in Resources */ = {isa = PBXBuildFile; fileRef = DA24EBBA19DAD4D000FF010B /* Icon-Small.png */; };
DA24EBEB19DAD6EE00FF010B /* Icon-Small@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA24EBBB19DAD4D000FF010B /* Icon-Small@2x.png */; };
DA24EBEC19DAD6EE00FF010B /* Icon-Small@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA24EBBC19DAD4D000FF010B /* Icon-Small@3x.png */; };
DA250A17195665A100AC23F1 /* UITableView+PearlReloadFromArray.m in Sources */ = {isa = PBXBuildFile; fileRef = DA250A13195665A100AC23F1 /* UITableView+PearlReloadFromArray.m */; };
DA250A18195665A100AC23F1 /* UITableView+PearlReloadFromArray.h in Headers */ = {isa = PBXBuildFile; fileRef = DA250A14195665A100AC23F1 /* UITableView+PearlReloadFromArray.h */; };
DA250A17195665A100AC23F1 /* UITableView+PearlReloadItems.m in Sources */ = {isa = PBXBuildFile; fileRef = DA250A13195665A100AC23F1 /* UITableView+PearlReloadItems.m */; };
DA250A18195665A100AC23F1 /* UITableView+PearlReloadItems.h in Headers */ = {isa = PBXBuildFile; fileRef = DA250A14195665A100AC23F1 /* UITableView+PearlReloadItems.h */; };
DA250A19195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m in Sources */ = {isa = PBXBuildFile; fileRef = DA250A15195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m */; };
DA250A1A195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.h in Headers */ = {isa = PBXBuildFile; fileRef = DA250A16195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.h */; };
DA25C5F8197AFFB40046CDCF /* icon_tools.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD384C1711E29700CF925C /* icon_tools.png */; };
@@ -86,7 +109,6 @@
DA25C600197DBF260046CDCF /* icon_trash.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD38501711E29700CF925C /* icon_trash.png */; };
DA25C601197DBF260046CDCF /* icon_trash@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD38511711E29700CF925C /* icon_trash@2x.png */; };
DA25C6B41980D3C50046CDCF /* openssl in Headers */ = {isa = PBXBuildFile; fileRef = DA25C6B31980D3C10046CDCF /* openssl */; settings = {ATTRIBUTES = (Public, ); }; };
DA25C6B61980D3DF0046CDCF /* scrypt in Headers */ = {isa = PBXBuildFile; fileRef = DA25C6B51980D3DD0046CDCF /* scrypt */; settings = {ATTRIBUTES = (Public, ); }; };
DA29992F19C86F5700AF7DF1 /* thumb_generated_login@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA29992D19C86F5700AF7DF1 /* thumb_generated_login@2x.png */; };
DA29993019C86F5700AF7DF1 /* thumb_generated_login.png in Resources */ = {isa = PBXBuildFile; fileRef = DA29992E19C86F5700AF7DF1 /* thumb_generated_login.png */; };
DA29993219C9132F00AF7DF1 /* thumb_generated_login@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA29993119C9132F00AF7DF1 /* thumb_generated_login@3x.png */; };
@@ -342,20 +364,6 @@
DAF4EF50190A81E400023C90 /* NSManagedObject+Pearl.m in Sources */ = {isa = PBXBuildFile; fileRef = DAF4EF4E190A81E400023C90 /* NSManagedObject+Pearl.m */; };
DAF4EF51190A81E400023C90 /* NSManagedObject+Pearl.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF4EF4F190A81E400023C90 /* NSManagedObject+Pearl.h */; };
DAFC5656172C573B00CB5CC5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
DAFC5683172C57EC00CB5CC5 /* IASKAppSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5665172C57EC00CB5CC5 /* IASKAppSettingsViewController.m */; };
DAFC5684172C57EC00CB5CC5 /* IASKAppSettingsWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5667172C57EC00CB5CC5 /* IASKAppSettingsWebViewController.m */; };
DAFC5685172C57EC00CB5CC5 /* IASKSpecifierValuesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5669172C57EC00CB5CC5 /* IASKSpecifierValuesViewController.m */; };
DAFC5686172C57EC00CB5CC5 /* IASKSettingsReader.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC566D172C57EC00CB5CC5 /* IASKSettingsReader.m */; };
DAFC5687172C57EC00CB5CC5 /* IASKSettingsStore.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC566F172C57EC00CB5CC5 /* IASKSettingsStore.m */; };
DAFC5688172C57EC00CB5CC5 /* IASKSettingsStoreFile.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5671172C57EC00CB5CC5 /* IASKSettingsStoreFile.m */; };
DAFC5689172C57EC00CB5CC5 /* IASKSettingsStoreUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5673172C57EC00CB5CC5 /* IASKSettingsStoreUserDefaults.m */; };
DAFC568A172C57EC00CB5CC5 /* IASKSpecifier.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5675172C57EC00CB5CC5 /* IASKSpecifier.m */; };
DAFC568B172C57EC00CB5CC5 /* IASKPSSliderSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5678172C57EC00CB5CC5 /* IASKPSSliderSpecifierViewCell.m */; };
DAFC568C172C57EC00CB5CC5 /* IASKPSTextFieldSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC567A172C57EC00CB5CC5 /* IASKPSTextFieldSpecifierViewCell.m */; };
DAFC568D172C57EC00CB5CC5 /* IASKPSTitleValueSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC567C172C57EC00CB5CC5 /* IASKPSTitleValueSpecifierViewCell.m */; };
DAFC568E172C57EC00CB5CC5 /* IASKSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC567E172C57EC00CB5CC5 /* IASKSlider.m */; };
DAFC568F172C57EC00CB5CC5 /* IASKSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5680172C57EC00CB5CC5 /* IASKSwitch.m */; };
DAFC5690172C57EC00CB5CC5 /* IASKTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFC5682172C57EC00CB5CC5 /* IASKTextField.m */; };
DAFE4A1315039824003ABA7C /* NSObject+PearlExport.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE45D815039823003ABA7C /* NSObject+PearlExport.h */; };
DAFE4A1415039824003ABA7C /* NSObject+PearlExport.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE45D915039823003ABA7C /* NSObject+PearlExport.m */; };
DAFE4A1515039824003ABA7C /* NSString+PearlNSArrayFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE45DA15039823003ABA7C /* NSString+PearlNSArrayFormat.h */; };
@@ -391,8 +399,6 @@
DAFE4A3715039824003ABA7C /* PearlKeyChain.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE460115039823003ABA7C /* PearlKeyChain.m */; };
DAFE4A3815039824003ABA7C /* PearlRSAKey.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460215039823003ABA7C /* PearlRSAKey.h */; };
DAFE4A3915039824003ABA7C /* PearlRSAKey.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE460315039823003ABA7C /* PearlRSAKey.m */; };
DAFE4A3A15039824003ABA7C /* PearlSCrypt.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460415039823003ABA7C /* PearlSCrypt.h */; };
DAFE4A3B15039824003ABA7C /* PearlSCrypt.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE460515039823003ABA7C /* PearlSCrypt.m */; };
DAFE4A3C15039824003ABA7C /* Pearl-UIKit-Dependencies.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460815039823003ABA7C /* Pearl-UIKit-Dependencies.h */; };
DAFE4A3D15039824003ABA7C /* Pearl-UIKit.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460915039823003ABA7C /* Pearl-UIKit.h */; };
DAFE4A3E15039824003ABA7C /* PearlAlert.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460A15039823003ABA7C /* PearlAlert.h */; };
@@ -476,6 +482,7 @@
93D3924EE15017F8A12CB436 /* MPPasswordsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordsViewController.m; sourceTree = "<group>"; };
93D392876BE5C011DE73B43F /* MPPopdownSegue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPopdownSegue.h; sourceTree = "<group>"; };
93D392C5A6572DB0EB5B82C8 /* mpw-types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-types.c"; sourceTree = "<group>"; };
93D392D76C091DEA3319F11D /* UIView+AlphaScale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+AlphaScale.h"; sourceTree = "<group>"; };
93D393310223DDB35218467A /* MPCombinedViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCombinedViewController.m; sourceTree = "<group>"; };
93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Indexing.h"; sourceTree = "<group>"; };
93D393BB973253D4BAAC84AA /* PearlEMail.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlEMail.m; sourceTree = "<group>"; };
@@ -483,8 +490,10 @@
93D394077F8FAB8167647187 /* Twitter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Twitter.framework; path = System/Library/Frameworks/Twitter.framework; sourceTree = SDKROOT; };
93D3942A356B639724157982 /* PearlOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlOverlay.h; sourceTree = "<group>"; };
93D394482BB07F90E8FD1314 /* UIResponder+PearlFirstResponder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIResponder+PearlFirstResponder.h"; sourceTree = "<group>"; };
93D39488AB33616661725929 /* UIView+AlphaScale.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+AlphaScale.m"; sourceTree = "<group>"; };
93D394D73F5BC92297CE8D7B /* MPAlgorithmV3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAlgorithmV3.h; sourceTree = "<group>"; };
93D395105935859D71679931 /* MPOverlayViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPOverlayViewController.m; sourceTree = "<group>"; };
93D3952910EDB8E0EBC94BA9 /* UIView+Visible.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Visible.m"; sourceTree = "<group>"; };
93D3956915634581E737B38C /* PearlNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlNavigationController.m; sourceTree = "<group>"; };
93D3957D76F71A652716EECC /* MPStoreViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPStoreViewController.m; sourceTree = "<group>"; };
93D3969393A3A46BD27D7078 /* mpw-algorithm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "mpw-algorithm.c"; sourceTree = "<group>"; };
@@ -495,6 +504,7 @@
93D3971FE104BB4052484151 /* MPUsersViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPUsersViewController.h; sourceTree = "<group>"; };
93D39730673227EFF6DEFF19 /* MPSetupViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSetupViewController.h; sourceTree = "<group>"; };
93D3977321EB249981821AB0 /* UITextView+PearlAttributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITextView+PearlAttributes.m"; sourceTree = "<group>"; };
93D39789AAF49338F8AC8B02 /* NSOrderedSetOrArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSOrderedSetOrArray.m; sourceTree = "<group>"; };
93D3979190DACEBD1F6AE9F4 /* MPLogsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPLogsViewController.m; sourceTree = "<group>"; };
93D397F4BAFFF7CF3F1B21A4 /* NSPersistentStore+PearlMigration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSPersistentStore+PearlMigration.h"; sourceTree = "<group>"; };
93D398567FD02DB2647B8CF3 /* PearlNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlNavigationController.h; sourceTree = "<group>"; };
@@ -523,6 +533,7 @@
93D39B1D8177A86C5B9EDDE3 /* PearlUICollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlUICollectionView.h; sourceTree = "<group>"; };
93D39B381350802A194BF332 /* MPAvatarCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAvatarCell.m; sourceTree = "<group>"; };
93D39B455A71EC98C749E623 /* MPOverlayViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPOverlayViewController.h; sourceTree = "<group>"; };
93D39B7B765546B1F1900CB7 /* UIView+Visible.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+Visible.h"; sourceTree = "<group>"; };
93D39BAA71DE51B4D8A1286C /* MPCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCell.m; sourceTree = "<group>"; };
93D39C41A27AA42D044D68AE /* NSString+MPMarkDown.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSString+MPMarkDown.m"; path = "iOS/NSString+MPMarkDown.m"; sourceTree = "<group>"; };
93D39C426E03358384018E85 /* MPAnswersViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAnswersViewController.m; sourceTree = "<group>"; };
@@ -544,10 +555,118 @@
93D39F556F2F142740A65E59 /* MPWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPWebViewController.h; sourceTree = "<group>"; };
93D39F7C9F47BF6387FBC5C3 /* PearlEMail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlEMail.h; sourceTree = "<group>"; };
93D39F9106F2CCFB94283188 /* NSError+PearlFullDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+PearlFullDescription.m"; sourceTree = "<group>"; };
93D39FBF8FCEB4C106272334 /* NSOrderedSetOrArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSOrderedSetOrArray.h; sourceTree = "<group>"; };
93D39FD9623E8D5571C0AEB3 /* MPAlgorithmV3.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAlgorithmV3.m; sourceTree = "<group>"; };
DA04E33D14B1E70400ECA4F3 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
DA071BF1190187FE00179766 /* empty@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "empty@2x.png"; sourceTree = "<group>"; };
DA071BF2190187FE00179766 /* empty.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = empty.png; sourceTree = "<group>"; };
DA0978DB1E9A81EE00F0BFE8 /* core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = core.h; sourceTree = "<group>"; };
DA0978DC1E9A81EE00F0BFE8 /* crypto_aead_aes256gcm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_aead_aes256gcm.h; sourceTree = "<group>"; };
DA0978DD1E9A81EE00F0BFE8 /* crypto_aead_chacha20poly1305.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_aead_chacha20poly1305.h; sourceTree = "<group>"; };
DA0978DE1E9A81EE00F0BFE8 /* crypto_aead_xchacha20poly1305.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_aead_xchacha20poly1305.h; sourceTree = "<group>"; };
DA0978DF1E9A81EE00F0BFE8 /* crypto_auth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_auth.h; sourceTree = "<group>"; };
DA0978E01E9A81EE00F0BFE8 /* crypto_auth_hmacsha256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_auth_hmacsha256.h; sourceTree = "<group>"; };
DA0978E11E9A81EE00F0BFE8 /* crypto_auth_hmacsha512.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_auth_hmacsha512.h; sourceTree = "<group>"; };
DA0978E21E9A81EE00F0BFE8 /* crypto_auth_hmacsha512256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_auth_hmacsha512256.h; sourceTree = "<group>"; };
DA0978E31E9A81EE00F0BFE8 /* crypto_box.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_box.h; sourceTree = "<group>"; };
DA0978E41E9A81EE00F0BFE8 /* crypto_box_curve25519xchacha20poly1305.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_box_curve25519xchacha20poly1305.h; sourceTree = "<group>"; };
DA0978E51E9A81EE00F0BFE8 /* crypto_box_curve25519xsalsa20poly1305.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_box_curve25519xsalsa20poly1305.h; sourceTree = "<group>"; };
DA0978E61E9A81EE00F0BFE8 /* crypto_core_hchacha20.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_core_hchacha20.h; sourceTree = "<group>"; };
DA0978E71E9A81EE00F0BFE8 /* crypto_core_hsalsa20.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_core_hsalsa20.h; sourceTree = "<group>"; };
DA0978E81E9A81EE00F0BFE8 /* crypto_core_salsa20.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_core_salsa20.h; sourceTree = "<group>"; };
DA0978E91E9A81EE00F0BFE8 /* crypto_core_salsa2012.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_core_salsa2012.h; sourceTree = "<group>"; };
DA0978EA1E9A81EE00F0BFE8 /* crypto_core_salsa208.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_core_salsa208.h; sourceTree = "<group>"; };
DA0978EB1E9A81EE00F0BFE8 /* crypto_generichash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_generichash.h; sourceTree = "<group>"; };
DA0978EC1E9A81EE00F0BFE8 /* crypto_generichash_blake2b.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_generichash_blake2b.h; sourceTree = "<group>"; };
DA0978ED1E9A81EE00F0BFE8 /* crypto_hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_hash.h; sourceTree = "<group>"; };
DA0978EE1E9A81EE00F0BFE8 /* crypto_hash_sha256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_hash_sha256.h; sourceTree = "<group>"; };
DA0978EF1E9A81EE00F0BFE8 /* crypto_hash_sha512.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_hash_sha512.h; sourceTree = "<group>"; };
DA0978F01E9A81EE00F0BFE8 /* crypto_kdf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_kdf.h; sourceTree = "<group>"; };
DA0978F11E9A81EE00F0BFE8 /* crypto_kdf_blake2b.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_kdf_blake2b.h; sourceTree = "<group>"; };
DA0978F21E9A81EE00F0BFE8 /* crypto_kx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_kx.h; sourceTree = "<group>"; };
DA0978F31E9A81EE00F0BFE8 /* crypto_onetimeauth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_onetimeauth.h; sourceTree = "<group>"; };
DA0978F41E9A81EE00F0BFE8 /* crypto_onetimeauth_poly1305.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_onetimeauth_poly1305.h; sourceTree = "<group>"; };
DA0978F51E9A81EE00F0BFE8 /* crypto_pwhash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_pwhash.h; sourceTree = "<group>"; };
DA0978F61E9A81EE00F0BFE8 /* crypto_pwhash_argon2i.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_pwhash_argon2i.h; sourceTree = "<group>"; };
DA0978F71E9A81EE00F0BFE8 /* crypto_pwhash_scryptsalsa208sha256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_pwhash_scryptsalsa208sha256.h; sourceTree = "<group>"; };
DA0978F81E9A81EE00F0BFE8 /* crypto_scalarmult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_scalarmult.h; sourceTree = "<group>"; };
DA0978F91E9A81EE00F0BFE8 /* crypto_scalarmult_curve25519.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_scalarmult_curve25519.h; sourceTree = "<group>"; };
DA0978FA1E9A81EE00F0BFE8 /* crypto_secretbox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_secretbox.h; sourceTree = "<group>"; };
DA0978FB1E9A81EE00F0BFE8 /* crypto_secretbox_xchacha20poly1305.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_secretbox_xchacha20poly1305.h; sourceTree = "<group>"; };
DA0978FC1E9A81EE00F0BFE8 /* crypto_secretbox_xsalsa20poly1305.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_secretbox_xsalsa20poly1305.h; sourceTree = "<group>"; };
DA0978FD1E9A81EE00F0BFE8 /* crypto_shorthash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_shorthash.h; sourceTree = "<group>"; };
DA0978FE1E9A81EE00F0BFE8 /* crypto_shorthash_siphash24.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_shorthash_siphash24.h; sourceTree = "<group>"; };
DA0978FF1E9A81EE00F0BFE8 /* crypto_sign.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_sign.h; sourceTree = "<group>"; };
DA0979001E9A81EE00F0BFE8 /* crypto_sign_ed25519.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_sign_ed25519.h; sourceTree = "<group>"; };
DA0979011E9A81EE00F0BFE8 /* crypto_sign_edwards25519sha512batch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_sign_edwards25519sha512batch.h; sourceTree = "<group>"; };
DA0979021E9A81EE00F0BFE8 /* crypto_stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_stream.h; sourceTree = "<group>"; };
DA0979031E9A81EE00F0BFE8 /* crypto_stream_aes128ctr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_stream_aes128ctr.h; sourceTree = "<group>"; };
DA0979041E9A81EE00F0BFE8 /* crypto_stream_chacha20.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_stream_chacha20.h; sourceTree = "<group>"; };
DA0979051E9A81EE00F0BFE8 /* crypto_stream_salsa20.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_stream_salsa20.h; sourceTree = "<group>"; };
DA0979061E9A81EE00F0BFE8 /* crypto_stream_salsa2012.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_stream_salsa2012.h; sourceTree = "<group>"; };
DA0979071E9A81EE00F0BFE8 /* crypto_stream_salsa208.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_stream_salsa208.h; sourceTree = "<group>"; };
DA0979081E9A81EE00F0BFE8 /* crypto_stream_xchacha20.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_stream_xchacha20.h; sourceTree = "<group>"; };
DA0979091E9A81EE00F0BFE8 /* crypto_stream_xsalsa20.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_stream_xsalsa20.h; sourceTree = "<group>"; };
DA09790A1E9A81EE00F0BFE8 /* crypto_verify_16.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_verify_16.h; sourceTree = "<group>"; };
DA09790B1E9A81EE00F0BFE8 /* crypto_verify_32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_verify_32.h; sourceTree = "<group>"; };
DA09790C1E9A81EE00F0BFE8 /* crypto_verify_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_verify_64.h; sourceTree = "<group>"; };
DA09790D1E9A81EE00F0BFE8 /* export.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = export.h; sourceTree = "<group>"; };
DA09790E1E9A81EE00F0BFE8 /* randombytes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = randombytes.h; sourceTree = "<group>"; };
DA09790F1E9A81EE00F0BFE8 /* randombytes_salsa20_random.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = randombytes_salsa20_random.h; sourceTree = "<group>"; };
DA0979101E9A81EE00F0BFE8 /* randombytes_sysrandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = randombytes_sysrandom.h; sourceTree = "<group>"; };
DA0979111E9A81EE00F0BFE8 /* runtime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = runtime.h; sourceTree = "<group>"; };
DA0979121E9A81EE00F0BFE8 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = "<group>"; };
DA0979131E9A81EE00F0BFE8 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = "<group>"; };
DA0979141E9A81EE00F0BFE8 /* sodium.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sodium.h; sourceTree = "<group>"; };
DA0979161E9A81EE00F0BFE8 /* libsodium.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libsodium.a; sourceTree = "<group>"; };
DA0CC4F61EAB99BA009A8ED9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
DA0CC4F71EAB99BA009A8ED9 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
DA0CC4F81EAB99BA009A8ED9 /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
DA0CC4F91EAB99BA009A8ED9 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
DA0CC4FA1EAB99BA009A8ED9 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
DA0CC4FB1EAB99BA009A8ED9 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
DA0CC4FC1EAB99BA009A8ED9 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
DA0CC4FD1EAB99BA009A8ED9 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
DA0CC4FE1EAB99BA009A8ED9 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
DA0CC4FF1EAB99BA009A8ED9 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/IASKLocalizable.strings"; sourceTree = "<group>"; };
DA0CC5001EAB99BA009A8ED9 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
DA0CC5011EAB99BA009A8ED9 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
DA0CC5021EAB99BA009A8ED9 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
DA0CC5031EAB99BA009A8ED9 /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
DA0CC5041EAB99BA009A8ED9 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/IASKLocalizable.strings; sourceTree = "<group>"; };
DA0CC5061EAB99BA009A8ED9 /* IASKAppSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKAppSettingsViewController.h; sourceTree = "<group>"; };
DA0CC5071EAB99BA009A8ED9 /* IASKAppSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKAppSettingsViewController.m; sourceTree = "<group>"; };
DA0CC5081EAB99BA009A8ED9 /* IASKAppSettingsWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKAppSettingsWebViewController.h; sourceTree = "<group>"; };
DA0CC5091EAB99BA009A8ED9 /* IASKAppSettingsWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKAppSettingsWebViewController.m; sourceTree = "<group>"; };
DA0CC50A1EAB99BA009A8ED9 /* IASKMultipleValueSelection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKMultipleValueSelection.h; sourceTree = "<group>"; };
DA0CC50B1EAB99BA009A8ED9 /* IASKMultipleValueSelection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKMultipleValueSelection.m; sourceTree = "<group>"; };
DA0CC50C1EAB99BA009A8ED9 /* IASKSpecifierValuesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSpecifierValuesViewController.h; sourceTree = "<group>"; };
DA0CC50D1EAB99BA009A8ED9 /* IASKSpecifierValuesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSpecifierValuesViewController.m; sourceTree = "<group>"; };
DA0CC50E1EAB99BA009A8ED9 /* IASKViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKViewController.h; sourceTree = "<group>"; };
DA0CC5101EAB99BA009A8ED9 /* IASKSettingsReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsReader.h; sourceTree = "<group>"; };
DA0CC5111EAB99BA009A8ED9 /* IASKSettingsReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsReader.m; sourceTree = "<group>"; };
DA0CC5121EAB99BA009A8ED9 /* IASKSettingsStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsStore.h; sourceTree = "<group>"; };
DA0CC5131EAB99BA009A8ED9 /* IASKSettingsStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsStore.m; sourceTree = "<group>"; };
DA0CC5141EAB99BA009A8ED9 /* IASKSettingsStoreFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsStoreFile.h; sourceTree = "<group>"; };
DA0CC5151EAB99BA009A8ED9 /* IASKSettingsStoreFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsStoreFile.m; sourceTree = "<group>"; };
DA0CC5161EAB99BA009A8ED9 /* IASKSettingsStoreUserDefaults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsStoreUserDefaults.h; sourceTree = "<group>"; };
DA0CC5171EAB99BA009A8ED9 /* IASKSettingsStoreUserDefaults.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsStoreUserDefaults.m; sourceTree = "<group>"; };
DA0CC5181EAB99BA009A8ED9 /* IASKSpecifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSpecifier.h; sourceTree = "<group>"; };
DA0CC5191EAB99BA009A8ED9 /* IASKSpecifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSpecifier.m; sourceTree = "<group>"; };
DA0CC51B1EAB99BA009A8ED9 /* IASKPSSliderSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSSliderSpecifierViewCell.h; sourceTree = "<group>"; };
DA0CC51C1EAB99BA009A8ED9 /* IASKPSSliderSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSSliderSpecifierViewCell.m; sourceTree = "<group>"; };
DA0CC51D1EAB99BA009A8ED9 /* IASKPSTextFieldSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSTextFieldSpecifierViewCell.h; sourceTree = "<group>"; };
DA0CC51E1EAB99BA009A8ED9 /* IASKPSTextFieldSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSTextFieldSpecifierViewCell.m; sourceTree = "<group>"; };
DA0CC51F1EAB99BA009A8ED9 /* IASKSlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSlider.h; sourceTree = "<group>"; };
DA0CC5201EAB99BA009A8ED9 /* IASKSlider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSlider.m; sourceTree = "<group>"; };
DA0CC5211EAB99BA009A8ED9 /* IASKSwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSwitch.h; sourceTree = "<group>"; };
DA0CC5221EAB99BA009A8ED9 /* IASKSwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSwitch.m; sourceTree = "<group>"; };
DA0CC5231EAB99BA009A8ED9 /* IASKTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKTextField.h; sourceTree = "<group>"; };
DA0CC5241EAB99BA009A8ED9 /* IASKTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKTextField.m; sourceTree = "<group>"; };
DA0CC5251EAB99BA009A8ED9 /* IASKTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKTextView.h; sourceTree = "<group>"; };
DA0CC5261EAB99BA009A8ED9 /* IASKTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKTextView.m; sourceTree = "<group>"; };
DA0CC5271EAB99BA009A8ED9 /* IASKTextViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKTextViewCell.h; sourceTree = "<group>"; };
DA0CC5281EAB99BA009A8ED9 /* IASKTextViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKTextViewCell.m; sourceTree = "<group>"; };
DA24EBB219DAD4D000FF010B /* Icon-60.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-60.png"; sourceTree = "<group>"; };
DA24EBB319DAD4D000FF010B /* Icon-60@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-60@2x.png"; sourceTree = "<group>"; };
DA24EBB419DAD4D000FF010B /* Icon-60@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-60@3x.png"; sourceTree = "<group>"; };
@@ -574,12 +693,11 @@
DA24EBCA19DAD4D000FF010B /* launch.sketch */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = launch.sketch; sourceTree = "<group>"; };
DA24EBE619DAD6DE00FF010B /* Icon-320.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-320.png"; sourceTree = "<group>"; };
DA24EBE719DAD6DE00FF010B /* Icon-64.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-64.png"; sourceTree = "<group>"; };
DA250A13195665A100AC23F1 /* UITableView+PearlReloadFromArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITableView+PearlReloadFromArray.m"; sourceTree = "<group>"; };
DA250A14195665A100AC23F1 /* UITableView+PearlReloadFromArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITableView+PearlReloadFromArray.h"; sourceTree = "<group>"; };
DA250A13195665A100AC23F1 /* UITableView+PearlReloadItems.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITableView+PearlReloadItems.m"; sourceTree = "<group>"; };
DA250A14195665A100AC23F1 /* UITableView+PearlReloadItems.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITableView+PearlReloadItems.h"; sourceTree = "<group>"; };
DA250A15195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UICollectionReusableView+PearlDequeue.m"; sourceTree = "<group>"; };
DA250A16195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UICollectionReusableView+PearlDequeue.h"; sourceTree = "<group>"; };
DA25C6B31980D3C10046CDCF /* openssl */ = {isa = PBXFileReference; lastKnownFileType = folder; path = openssl; sourceTree = "<group>"; };
DA25C6B51980D3DD0046CDCF /* scrypt */ = {isa = PBXFileReference; lastKnownFileType = folder; path = scrypt; sourceTree = "<group>"; };
DA29992D19C86F5700AF7DF1 /* thumb_generated_login@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "thumb_generated_login@2x.png"; sourceTree = "<group>"; };
DA29992E19C86F5700AF7DF1 /* thumb_generated_login.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = thumb_generated_login.png; sourceTree = "<group>"; };
DA29993119C9132F00AF7DF1 /* thumb_generated_login@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "thumb_generated_login@3x.png"; sourceTree = "<group>"; };
@@ -649,7 +767,6 @@
DA70EC7F1811B13C00F65DB2 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
DA771FE41E6E1595004D7EDE /* MasterPassword-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MasterPassword-Prefix.pch"; sourceTree = "<group>"; };
DA7F2C5E1C48B70D00404A26 /* libopensslcrypto-ios-sim.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libopensslcrypto-ios-sim.a"; sourceTree = "<group>"; };
DA7F2C5F1C48B70D00404A26 /* libscryptenc-ios-sim.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libscryptenc-ios-sim.a"; sourceTree = "<group>"; };
DA854C8118D4CFBF00106317 /* avatar-add@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "avatar-add@2x.png"; sourceTree = "<group>"; };
DA854C8218D4CFBF00106317 /* avatar-add.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "avatar-add.png"; sourceTree = "<group>"; };
DA92614C1BE1A57500369DE5 /* MPAppDelegate_InApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppDelegate_InApp.h; sourceTree = "<group>"; };
@@ -1409,35 +1526,6 @@
DAF4EF4E190A81E400023C90 /* NSManagedObject+Pearl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObject+Pearl.m"; sourceTree = "<group>"; };
DAF4EF4F190A81E400023C90 /* NSManagedObject+Pearl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObject+Pearl.h"; sourceTree = "<group>"; };
DAFC5655172C573B00CB5CC5 /* libInAppSettingsKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libInAppSettingsKit.a; sourceTree = BUILT_PRODUCTS_DIR; };
DAFC5664172C57EC00CB5CC5 /* IASKAppSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKAppSettingsViewController.h; sourceTree = "<group>"; };
DAFC5665172C57EC00CB5CC5 /* IASKAppSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKAppSettingsViewController.m; sourceTree = "<group>"; };
DAFC5666172C57EC00CB5CC5 /* IASKAppSettingsWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKAppSettingsWebViewController.h; sourceTree = "<group>"; };
DAFC5667172C57EC00CB5CC5 /* IASKAppSettingsWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKAppSettingsWebViewController.m; sourceTree = "<group>"; };
DAFC5668172C57EC00CB5CC5 /* IASKSpecifierValuesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSpecifierValuesViewController.h; sourceTree = "<group>"; };
DAFC5669172C57EC00CB5CC5 /* IASKSpecifierValuesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSpecifierValuesViewController.m; sourceTree = "<group>"; };
DAFC566A172C57EC00CB5CC5 /* IASKViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKViewController.h; sourceTree = "<group>"; };
DAFC566C172C57EC00CB5CC5 /* IASKSettingsReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsReader.h; sourceTree = "<group>"; };
DAFC566D172C57EC00CB5CC5 /* IASKSettingsReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsReader.m; sourceTree = "<group>"; };
DAFC566E172C57EC00CB5CC5 /* IASKSettingsStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsStore.h; sourceTree = "<group>"; };
DAFC566F172C57EC00CB5CC5 /* IASKSettingsStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsStore.m; sourceTree = "<group>"; };
DAFC5670172C57EC00CB5CC5 /* IASKSettingsStoreFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsStoreFile.h; sourceTree = "<group>"; };
DAFC5671172C57EC00CB5CC5 /* IASKSettingsStoreFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsStoreFile.m; sourceTree = "<group>"; };
DAFC5672172C57EC00CB5CC5 /* IASKSettingsStoreUserDefaults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsStoreUserDefaults.h; sourceTree = "<group>"; };
DAFC5673172C57EC00CB5CC5 /* IASKSettingsStoreUserDefaults.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsStoreUserDefaults.m; sourceTree = "<group>"; };
DAFC5674172C57EC00CB5CC5 /* IASKSpecifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSpecifier.h; sourceTree = "<group>"; };
DAFC5675172C57EC00CB5CC5 /* IASKSpecifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSpecifier.m; sourceTree = "<group>"; };
DAFC5677172C57EC00CB5CC5 /* IASKPSSliderSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSSliderSpecifierViewCell.h; sourceTree = "<group>"; };
DAFC5678172C57EC00CB5CC5 /* IASKPSSliderSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSSliderSpecifierViewCell.m; sourceTree = "<group>"; };
DAFC5679172C57EC00CB5CC5 /* IASKPSTextFieldSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSTextFieldSpecifierViewCell.h; sourceTree = "<group>"; };
DAFC567A172C57EC00CB5CC5 /* IASKPSTextFieldSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSTextFieldSpecifierViewCell.m; sourceTree = "<group>"; };
DAFC567B172C57EC00CB5CC5 /* IASKPSTitleValueSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSTitleValueSpecifierViewCell.h; sourceTree = "<group>"; };
DAFC567C172C57EC00CB5CC5 /* IASKPSTitleValueSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSTitleValueSpecifierViewCell.m; sourceTree = "<group>"; };
DAFC567D172C57EC00CB5CC5 /* IASKSlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSlider.h; sourceTree = "<group>"; };
DAFC567E172C57EC00CB5CC5 /* IASKSlider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSlider.m; sourceTree = "<group>"; };
DAFC567F172C57EC00CB5CC5 /* IASKSwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSwitch.h; sourceTree = "<group>"; };
DAFC5680172C57EC00CB5CC5 /* IASKSwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSwitch.m; sourceTree = "<group>"; };
DAFC5681172C57EC00CB5CC5 /* IASKTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKTextField.h; sourceTree = "<group>"; };
DAFC5682172C57EC00CB5CC5 /* IASKTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKTextField.m; sourceTree = "<group>"; };
DAFE45D815039823003ABA7C /* NSObject+PearlExport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+PearlExport.h"; sourceTree = "<group>"; };
DAFE45D915039823003ABA7C /* NSObject+PearlExport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+PearlExport.m"; sourceTree = "<group>"; };
DAFE45DA15039823003ABA7C /* NSString+PearlNSArrayFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+PearlNSArrayFormat.h"; sourceTree = "<group>"; };
@@ -1475,8 +1563,6 @@
DAFE460115039823003ABA7C /* PearlKeyChain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlKeyChain.m; sourceTree = "<group>"; };
DAFE460215039823003ABA7C /* PearlRSAKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlRSAKey.h; sourceTree = "<group>"; };
DAFE460315039823003ABA7C /* PearlRSAKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlRSAKey.m; sourceTree = "<group>"; };
DAFE460415039823003ABA7C /* PearlSCrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlSCrypt.h; sourceTree = "<group>"; };
DAFE460515039823003ABA7C /* PearlSCrypt.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlSCrypt.m; sourceTree = "<group>"; };
DAFE460615039823003ABA7C /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
DAFE460815039823003ABA7C /* Pearl-UIKit-Dependencies.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Pearl-UIKit-Dependencies.h"; sourceTree = "<group>"; };
DAFE460915039823003ABA7C /* Pearl-UIKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Pearl-UIKit.h"; sourceTree = "<group>"; };
@@ -1519,7 +1605,6 @@
DAFE4A63150399FF003ABA8F /* UIScrollView+PearlFlashingIndicators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+PearlFlashingIndicators.h"; sourceTree = "<group>"; };
DAFE4A63150399FF003ABA91 /* NSDateFormatter+RFC3339.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDateFormatter+RFC3339.m"; sourceTree = "<group>"; };
DAFE4A63150399FF003ABA93 /* NSDateFormatter+RFC3339.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDateFormatter+RFC3339.h"; sourceTree = "<group>"; };
DAFFC63E17EDDA7C007BB020 /* libscryptenc-ios.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libscryptenc-ios.a"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -1552,6 +1637,7 @@
DA48856019A5A82E000C2D79 /* Crashlytics.framework in Frameworks */,
DAC632891486D9690075AEA5 /* Security.framework in Frameworks */,
DA5BFA49147E415C00F98B1E /* UIKit.framework in Frameworks */,
DA0979171E9A81EE00F0BFE8 /* libsodium.a in Frameworks */,
DA5BFA4B147E415C00F98B1E /* Foundation.framework in Frameworks */,
DA5BFA4D147E415C00F98B1E /* CoreGraphics.framework in Frameworks */,
DA5BFA4F147E415C00F98B1E /* CoreData.framework in Frameworks */,
@@ -1622,6 +1708,159 @@
path = ../core/c;
sourceTree = "<group>";
};
DA0978D81E9A81EE00F0BFE8 /* libsodium-ios */ = {
isa = PBXGroup;
children = (
DA0978D91E9A81EE00F0BFE8 /* include */,
DA0979151E9A81EE00F0BFE8 /* lib */,
);
name = "libsodium-ios";
path = "libsodium/libsodium-ios";
sourceTree = "<group>";
};
DA0978D91E9A81EE00F0BFE8 /* include */ = {
isa = PBXGroup;
children = (
DA0978DA1E9A81EE00F0BFE8 /* sodium */,
DA0979141E9A81EE00F0BFE8 /* sodium.h */,
);
path = include;
sourceTree = "<group>";
};
DA0978DA1E9A81EE00F0BFE8 /* sodium */ = {
isa = PBXGroup;
children = (
DA0978DB1E9A81EE00F0BFE8 /* core.h */,
DA0978DC1E9A81EE00F0BFE8 /* crypto_aead_aes256gcm.h */,
DA0978DD1E9A81EE00F0BFE8 /* crypto_aead_chacha20poly1305.h */,
DA0978DE1E9A81EE00F0BFE8 /* crypto_aead_xchacha20poly1305.h */,
DA0978DF1E9A81EE00F0BFE8 /* crypto_auth.h */,
DA0978E01E9A81EE00F0BFE8 /* crypto_auth_hmacsha256.h */,
DA0978E11E9A81EE00F0BFE8 /* crypto_auth_hmacsha512.h */,
DA0978E21E9A81EE00F0BFE8 /* crypto_auth_hmacsha512256.h */,
DA0978E31E9A81EE00F0BFE8 /* crypto_box.h */,
DA0978E41E9A81EE00F0BFE8 /* crypto_box_curve25519xchacha20poly1305.h */,
DA0978E51E9A81EE00F0BFE8 /* crypto_box_curve25519xsalsa20poly1305.h */,
DA0978E61E9A81EE00F0BFE8 /* crypto_core_hchacha20.h */,
DA0978E71E9A81EE00F0BFE8 /* crypto_core_hsalsa20.h */,
DA0978E81E9A81EE00F0BFE8 /* crypto_core_salsa20.h */,
DA0978E91E9A81EE00F0BFE8 /* crypto_core_salsa2012.h */,
DA0978EA1E9A81EE00F0BFE8 /* crypto_core_salsa208.h */,
DA0978EB1E9A81EE00F0BFE8 /* crypto_generichash.h */,
DA0978EC1E9A81EE00F0BFE8 /* crypto_generichash_blake2b.h */,
DA0978ED1E9A81EE00F0BFE8 /* crypto_hash.h */,
DA0978EE1E9A81EE00F0BFE8 /* crypto_hash_sha256.h */,
DA0978EF1E9A81EE00F0BFE8 /* crypto_hash_sha512.h */,
DA0978F01E9A81EE00F0BFE8 /* crypto_kdf.h */,
DA0978F11E9A81EE00F0BFE8 /* crypto_kdf_blake2b.h */,
DA0978F21E9A81EE00F0BFE8 /* crypto_kx.h */,
DA0978F31E9A81EE00F0BFE8 /* crypto_onetimeauth.h */,
DA0978F41E9A81EE00F0BFE8 /* crypto_onetimeauth_poly1305.h */,
DA0978F51E9A81EE00F0BFE8 /* crypto_pwhash.h */,
DA0978F61E9A81EE00F0BFE8 /* crypto_pwhash_argon2i.h */,
DA0978F71E9A81EE00F0BFE8 /* crypto_pwhash_scryptsalsa208sha256.h */,
DA0978F81E9A81EE00F0BFE8 /* crypto_scalarmult.h */,
DA0978F91E9A81EE00F0BFE8 /* crypto_scalarmult_curve25519.h */,
DA0978FA1E9A81EE00F0BFE8 /* crypto_secretbox.h */,
DA0978FB1E9A81EE00F0BFE8 /* crypto_secretbox_xchacha20poly1305.h */,
DA0978FC1E9A81EE00F0BFE8 /* crypto_secretbox_xsalsa20poly1305.h */,
DA0978FD1E9A81EE00F0BFE8 /* crypto_shorthash.h */,
DA0978FE1E9A81EE00F0BFE8 /* crypto_shorthash_siphash24.h */,
DA0978FF1E9A81EE00F0BFE8 /* crypto_sign.h */,
DA0979001E9A81EE00F0BFE8 /* crypto_sign_ed25519.h */,
DA0979011E9A81EE00F0BFE8 /* crypto_sign_edwards25519sha512batch.h */,
DA0979021E9A81EE00F0BFE8 /* crypto_stream.h */,
DA0979031E9A81EE00F0BFE8 /* crypto_stream_aes128ctr.h */,
DA0979041E9A81EE00F0BFE8 /* crypto_stream_chacha20.h */,
DA0979051E9A81EE00F0BFE8 /* crypto_stream_salsa20.h */,
DA0979061E9A81EE00F0BFE8 /* crypto_stream_salsa2012.h */,
DA0979071E9A81EE00F0BFE8 /* crypto_stream_salsa208.h */,
DA0979081E9A81EE00F0BFE8 /* crypto_stream_xchacha20.h */,
DA0979091E9A81EE00F0BFE8 /* crypto_stream_xsalsa20.h */,
DA09790A1E9A81EE00F0BFE8 /* crypto_verify_16.h */,
DA09790B1E9A81EE00F0BFE8 /* crypto_verify_32.h */,
DA09790C1E9A81EE00F0BFE8 /* crypto_verify_64.h */,
DA09790D1E9A81EE00F0BFE8 /* export.h */,
DA09790E1E9A81EE00F0BFE8 /* randombytes.h */,
DA09790F1E9A81EE00F0BFE8 /* randombytes_salsa20_random.h */,
DA0979101E9A81EE00F0BFE8 /* randombytes_sysrandom.h */,
DA0979111E9A81EE00F0BFE8 /* runtime.h */,
DA0979121E9A81EE00F0BFE8 /* utils.h */,
DA0979131E9A81EE00F0BFE8 /* version.h */,
);
path = sodium;
sourceTree = "<group>";
};
DA0979151E9A81EE00F0BFE8 /* lib */ = {
isa = PBXGroup;
children = (
DA0979161E9A81EE00F0BFE8 /* libsodium.a */,
);
path = lib;
sourceTree = "<group>";
};
DA0CC4F41EAB99BA009A8ED9 /* Resources */ = {
isa = PBXGroup;
children = (
DA0CC4F51EAB99BA009A8ED9 /* IASKLocalizable.strings */,
);
path = Resources;
sourceTree = "<group>";
};
DA0CC5051EAB99BA009A8ED9 /* Controllers */ = {
isa = PBXGroup;
children = (
DA0CC5061EAB99BA009A8ED9 /* IASKAppSettingsViewController.h */,
DA0CC5071EAB99BA009A8ED9 /* IASKAppSettingsViewController.m */,
DA0CC5081EAB99BA009A8ED9 /* IASKAppSettingsWebViewController.h */,
DA0CC5091EAB99BA009A8ED9 /* IASKAppSettingsWebViewController.m */,
DA0CC50A1EAB99BA009A8ED9 /* IASKMultipleValueSelection.h */,
DA0CC50B1EAB99BA009A8ED9 /* IASKMultipleValueSelection.m */,
DA0CC50C1EAB99BA009A8ED9 /* IASKSpecifierValuesViewController.h */,
DA0CC50D1EAB99BA009A8ED9 /* IASKSpecifierValuesViewController.m */,
DA0CC50E1EAB99BA009A8ED9 /* IASKViewController.h */,
);
path = Controllers;
sourceTree = "<group>";
};
DA0CC50F1EAB99BA009A8ED9 /* Models */ = {
isa = PBXGroup;
children = (
DA0CC5101EAB99BA009A8ED9 /* IASKSettingsReader.h */,
DA0CC5111EAB99BA009A8ED9 /* IASKSettingsReader.m */,
DA0CC5121EAB99BA009A8ED9 /* IASKSettingsStore.h */,
DA0CC5131EAB99BA009A8ED9 /* IASKSettingsStore.m */,
DA0CC5141EAB99BA009A8ED9 /* IASKSettingsStoreFile.h */,
DA0CC5151EAB99BA009A8ED9 /* IASKSettingsStoreFile.m */,
DA0CC5161EAB99BA009A8ED9 /* IASKSettingsStoreUserDefaults.h */,
DA0CC5171EAB99BA009A8ED9 /* IASKSettingsStoreUserDefaults.m */,
DA0CC5181EAB99BA009A8ED9 /* IASKSpecifier.h */,
DA0CC5191EAB99BA009A8ED9 /* IASKSpecifier.m */,
);
path = Models;
sourceTree = "<group>";
};
DA0CC51A1EAB99BA009A8ED9 /* Views */ = {
isa = PBXGroup;
children = (
DA0CC51B1EAB99BA009A8ED9 /* IASKPSSliderSpecifierViewCell.h */,
DA0CC51C1EAB99BA009A8ED9 /* IASKPSSliderSpecifierViewCell.m */,
DA0CC51D1EAB99BA009A8ED9 /* IASKPSTextFieldSpecifierViewCell.h */,
DA0CC51E1EAB99BA009A8ED9 /* IASKPSTextFieldSpecifierViewCell.m */,
DA0CC51F1EAB99BA009A8ED9 /* IASKSlider.h */,
DA0CC5201EAB99BA009A8ED9 /* IASKSlider.m */,
DA0CC5211EAB99BA009A8ED9 /* IASKSwitch.h */,
DA0CC5221EAB99BA009A8ED9 /* IASKSwitch.m */,
DA0CC5231EAB99BA009A8ED9 /* IASKTextField.h */,
DA0CC5241EAB99BA009A8ED9 /* IASKTextField.m */,
DA0CC5251EAB99BA009A8ED9 /* IASKTextView.h */,
DA0CC5261EAB99BA009A8ED9 /* IASKTextView.m */,
DA0CC5271EAB99BA009A8ED9 /* IASKTextViewCell.h */,
DA0CC5281EAB99BA009A8ED9 /* IASKTextViewCell.m */,
);
path = Views;
sourceTree = "<group>";
};
DA24EBB019DAD4D000FF010B /* ios */ = {
isa = PBXGroup;
children = (
@@ -1768,8 +2007,6 @@
DA5E5C6417248959003798D8 /* include */,
DA7F2C5E1C48B70D00404A26 /* libopensslcrypto-ios-sim.a */,
DAE8E65119867AB500416A0F /* libopensslcrypto-ios.a */,
DA7F2C5F1C48B70D00404A26 /* libscryptenc-ios-sim.a */,
DAFFC63E17EDDA7C007BB020 /* libscryptenc-ios.a */,
);
path = lib;
sourceTree = "<group>";
@@ -1778,7 +2015,6 @@
isa = PBXGroup;
children = (
DA25C6B31980D3C10046CDCF /* openssl */,
DA25C6B51980D3DD0046CDCF /* scrypt */,
);
path = include;
sourceTree = "<group>";
@@ -2657,6 +2893,7 @@
DACA22121705DDC5002C6C22 /* External */ = {
isa = PBXGroup;
children = (
DA0978D81E9A81EE00F0BFE8 /* libsodium-ios */,
DAA1759319D86C610044227B /* AttributedMarkdown */,
DAFC5662172C57EC00CB5CC5 /* InAppSettingsKit */,
DAA141181922FED80032B392 /* iOS */,
@@ -2719,64 +2956,15 @@
DAFC5662172C57EC00CB5CC5 /* InAppSettingsKit */ = {
isa = PBXGroup;
children = (
DAFC5663172C57EC00CB5CC5 /* Controllers */,
DAFC566B172C57EC00CB5CC5 /* Models */,
DAFC5676172C57EC00CB5CC5 /* Views */,
DA0CC4F41EAB99BA009A8ED9 /* Resources */,
DA0CC5051EAB99BA009A8ED9 /* Controllers */,
DA0CC50F1EAB99BA009A8ED9 /* Models */,
DA0CC51A1EAB99BA009A8ED9 /* Views */,
);
name = InAppSettingsKit;
path = InAppSettingsKit/InAppSettingsKit;
sourceTree = "<group>";
};
DAFC5663172C57EC00CB5CC5 /* Controllers */ = {
isa = PBXGroup;
children = (
DAFC5664172C57EC00CB5CC5 /* IASKAppSettingsViewController.h */,
DAFC5665172C57EC00CB5CC5 /* IASKAppSettingsViewController.m */,
DAFC5666172C57EC00CB5CC5 /* IASKAppSettingsWebViewController.h */,
DAFC5667172C57EC00CB5CC5 /* IASKAppSettingsWebViewController.m */,
DAFC5668172C57EC00CB5CC5 /* IASKSpecifierValuesViewController.h */,
DAFC5669172C57EC00CB5CC5 /* IASKSpecifierValuesViewController.m */,
DAFC566A172C57EC00CB5CC5 /* IASKViewController.h */,
);
path = Controllers;
sourceTree = "<group>";
};
DAFC566B172C57EC00CB5CC5 /* Models */ = {
isa = PBXGroup;
children = (
DAFC566C172C57EC00CB5CC5 /* IASKSettingsReader.h */,
DAFC566D172C57EC00CB5CC5 /* IASKSettingsReader.m */,
DAFC566E172C57EC00CB5CC5 /* IASKSettingsStore.h */,
DAFC566F172C57EC00CB5CC5 /* IASKSettingsStore.m */,
DAFC5670172C57EC00CB5CC5 /* IASKSettingsStoreFile.h */,
DAFC5671172C57EC00CB5CC5 /* IASKSettingsStoreFile.m */,
DAFC5672172C57EC00CB5CC5 /* IASKSettingsStoreUserDefaults.h */,
DAFC5673172C57EC00CB5CC5 /* IASKSettingsStoreUserDefaults.m */,
DAFC5674172C57EC00CB5CC5 /* IASKSpecifier.h */,
DAFC5675172C57EC00CB5CC5 /* IASKSpecifier.m */,
);
path = Models;
sourceTree = "<group>";
};
DAFC5676172C57EC00CB5CC5 /* Views */ = {
isa = PBXGroup;
children = (
DAFC5677172C57EC00CB5CC5 /* IASKPSSliderSpecifierViewCell.h */,
DAFC5678172C57EC00CB5CC5 /* IASKPSSliderSpecifierViewCell.m */,
DAFC5679172C57EC00CB5CC5 /* IASKPSTextFieldSpecifierViewCell.h */,
DAFC567A172C57EC00CB5CC5 /* IASKPSTextFieldSpecifierViewCell.m */,
DAFC567B172C57EC00CB5CC5 /* IASKPSTitleValueSpecifierViewCell.h */,
DAFC567C172C57EC00CB5CC5 /* IASKPSTitleValueSpecifierViewCell.m */,
DAFC567D172C57EC00CB5CC5 /* IASKSlider.h */,
DAFC567E172C57EC00CB5CC5 /* IASKSlider.m */,
DAFC567F172C57EC00CB5CC5 /* IASKSwitch.h */,
DAFC5680172C57EC00CB5CC5 /* IASKSwitch.m */,
DAFC5681172C57EC00CB5CC5 /* IASKTextField.h */,
DAFC5682172C57EC00CB5CC5 /* IASKTextField.m */,
);
path = Views;
sourceTree = "<group>";
};
DAFE45D715039823003ABA7C /* Pearl */ = {
isa = PBXGroup;
children = (
@@ -2841,6 +3029,8 @@
DAA1411C1922FF020032B392 /* PearlTween.m */,
DAFE45F815039823003ABA7C /* README */,
DAFE45F915039823003ABA7C /* Resources */,
93D39FBF8FCEB4C106272334 /* NSOrderedSetOrArray.h */,
93D39789AAF49338F8AC8B02 /* NSOrderedSetOrArray.m */,
);
path = Pearl;
sourceTree = "<group>";
@@ -2865,8 +3055,6 @@
DAFE460115039823003ABA7C /* PearlKeyChain.m */,
DAFE460215039823003ABA7C /* PearlRSAKey.h */,
DAFE460315039823003ABA7C /* PearlRSAKey.m */,
DAFE460415039823003ABA7C /* PearlSCrypt.h */,
DAFE460515039823003ABA7C /* PearlSCrypt.m */,
DAFE460615039823003ABA7C /* README */,
);
path = "Pearl-Crypto";
@@ -2940,8 +3128,8 @@
93D390FB3110DCCE68E600DC /* UIScrollView+PearlAdjustInsets.m */,
DAFE4A63150399FF003ABA8F /* UIScrollView+PearlFlashingIndicators.h */,
DAFE4A63150399FF003ABA8D /* UIScrollView+PearlFlashingIndicators.m */,
DA250A14195665A100AC23F1 /* UITableView+PearlReloadFromArray.h */,
DA250A13195665A100AC23F1 /* UITableView+PearlReloadFromArray.m */,
DA250A14195665A100AC23F1 /* UITableView+PearlReloadItems.h */,
DA250A13195665A100AC23F1 /* UITableView+PearlReloadItems.m */,
DAE2726219CE9CB3007C5262 /* UITableViewCell+PearlDeque.h */,
DAE2726119CE9CB3007C5262 /* UITableViewCell+PearlDeque.m */,
93D39AA10CD00D05937671B1 /* UITextView+PearlAttributes.h */,
@@ -2952,6 +3140,10 @@
DAEFB01C19BCBD9E00525079 /* UIView+LayoutGone.m */,
DAEC85B418E3DD9A007FC0DF /* UIView+Touches.h */,
DAEC85B118E3DD9A007FC0DF /* UIView+Touches.m */,
93D39488AB33616661725929 /* UIView+AlphaScale.m */,
93D392D76C091DEA3319F11D /* UIView+AlphaScale.h */,
93D3952910EDB8E0EBC94BA9 /* UIView+Visible.m */,
93D39B7B765546B1F1900CB7 /* UIView+Visible.h */,
);
path = "Pearl-UIKit";
sourceTree = "<group>";
@@ -2987,7 +3179,6 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
DA25C6B61980D3DF0046CDCF /* scrypt in Headers */,
DA25C6B41980D3C50046CDCF /* openssl in Headers */,
DAFE4A1315039824003ABA7C /* NSObject+PearlExport.h in Headers */,
DAFE4A1515039824003ABA7C /* NSString+PearlNSArrayFormat.h in Headers */,
@@ -3004,7 +3195,7 @@
DAFE4A2615039824003ABA7C /* PearlLogger.h in Headers */,
DAFE4A2815039824003ABA7C /* PearlMathUtils.h in Headers */,
DAFE4A2A15039824003ABA7C /* PearlObjectUtils.h in Headers */,
DA250A18195665A100AC23F1 /* UITableView+PearlReloadFromArray.h in Headers */,
DA250A18195665A100AC23F1 /* UITableView+PearlReloadItems.h in Headers */,
DAFE4A2C15039824003ABA7C /* PearlResettable.h in Headers */,
DAFE4A2D15039824003ABA7C /* PearlStrings.h in Headers */,
DAFE4A2F15039824003ABA7C /* PearlStringUtils.h in Headers */,
@@ -3014,7 +3205,6 @@
DAFE4A3615039824003ABA7C /* PearlKeyChain.h in Headers */,
DAFE4A3815039824003ABA7C /* PearlRSAKey.h in Headers */,
DAE2726419CE9CB3007C5262 /* UITableViewCell+PearlDeque.h in Headers */,
DAFE4A3A15039824003ABA7C /* PearlSCrypt.h in Headers */,
DACE2F6E19BA6A2A0010F92E /* UIView+FontScale.h in Headers */,
DA32D01B19D046E1004F3F0E /* PearlFixedTableView.h in Headers */,
DAFE4A3C15039824003ABA7C /* Pearl-UIKit-Dependencies.h in Headers */,
@@ -3061,6 +3251,9 @@
93D392A8777DC30C11361647 /* UITextView+PearlAttributes.h in Headers */,
93D39A53D76CA70786423458 /* UICollectionView+PearlReloadFromArray.h in Headers */,
93D39AA4A0BE66A872CCC02E /* NSPersistentStore+PearlMigration.h in Headers */,
93D399E4BC1E092A8C8B12AE /* NSOrderedSetOrArray.h in Headers */,
93D3959696396A91961C6148 /* UIView+AlphaScale.h in Headers */,
93D39BFB5F5F9337F6565DE3 /* UIView+Visible.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3089,6 +3282,7 @@
buildConfigurationList = DA5BFA6D147E415C00F98B1E /* Build configuration list for PBXNativeTarget "MasterPassword" */;
buildPhases = (
DA8D88E019DA412A00B189D0 /* Run Script: genassets */,
DA0E86A81E9BED2C00F4D60E /* Run Script: libsodium/dist-build/ios.sh */,
DA5BFA40147E415C00F98B1E /* Sources */,
DA5BFA41147E415C00F98B1E /* Frameworks */,
DA5BFA42147E415C00F98B1E /* Resources */,
@@ -3329,6 +3523,8 @@
zh_HK,
zh_TW,
zu,
Base,
"pt-PT",
);
mainGroup = DA5BFA39147E415C00F98B1E;
productRefGroup = DA5BFA45147E415C00F98B1E /* Products */;
@@ -3537,6 +3733,21 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
DA0E86A81E9BED2C00F4D60E /* Run Script: libsodium/dist-build/ios.sh */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script: libsodium/dist-build/ios.sh";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = "/bin/sh -e";
shellScript = "cd External/libsodium\n[[ -d libsodium-ios ]] && exit\n\n# Xcode misinterpretes autogen.sh's stderr output as errors so we try to silence it.\n[[ -e configure ]] || { err=$(./autogen.sh 2>&1 >&3); } 3>&1 || { x=$?; echo >&2 \"$err\"; exit $x; }\n./dist-build/ios.sh";
showEnvVarsInLog = 0;
};
DA6556E314D55F3000841C99 /* Run Script: GIT version -> Info.plist */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -3699,9 +3910,8 @@
DAFE4A3515039824003ABA7C /* PearlCryptUtils.m in Sources */,
DAFE4A3715039824003ABA7C /* PearlKeyChain.m in Sources */,
DA72BD7B19C1510C00E6ACFE /* UIView+FontScale.m in Sources */,
DA250A17195665A100AC23F1 /* UITableView+PearlReloadFromArray.m in Sources */,
DA250A17195665A100AC23F1 /* UITableView+PearlReloadItems.m in Sources */,
DAFE4A3915039824003ABA7C /* PearlRSAKey.m in Sources */,
DAFE4A3B15039824003ABA7C /* PearlSCrypt.m in Sources */,
DAFE4A3F15039824003ABA7C /* PearlAlert.m in Sources */,
DAFE4A4115039824003ABA7C /* PearlArrayTVC.m in Sources */,
DAFE4A4315039824003ABA7C /* PearlBoxView.m in Sources */,
@@ -3751,6 +3961,9 @@
93D39E34FD28D24FE3442C48 /* UITextView+PearlAttributes.m in Sources */,
93D39D47FC623E91FC39D20C /* UICollectionView+PearlReloadFromArray.m in Sources */,
93D3928D629EA563F9EC4909 /* NSPersistentStore+PearlMigration.m in Sources */,
93D392A33CCE85431E910C7B /* NSOrderedSetOrArray.m in Sources */,
93D393AA69A1193401160418 /* UIView+AlphaScale.m in Sources */,
93D3942C1B117EE4851AA7B6 /* UIView+Visible.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3758,26 +3971,50 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DAFC5683172C57EC00CB5CC5 /* IASKAppSettingsViewController.m in Sources */,
DAFC5684172C57EC00CB5CC5 /* IASKAppSettingsWebViewController.m in Sources */,
DAFC5685172C57EC00CB5CC5 /* IASKSpecifierValuesViewController.m in Sources */,
DAFC5686172C57EC00CB5CC5 /* IASKSettingsReader.m in Sources */,
DAFC5687172C57EC00CB5CC5 /* IASKSettingsStore.m in Sources */,
DAFC5688172C57EC00CB5CC5 /* IASKSettingsStoreFile.m in Sources */,
DAFC5689172C57EC00CB5CC5 /* IASKSettingsStoreUserDefaults.m in Sources */,
DAFC568A172C57EC00CB5CC5 /* IASKSpecifier.m in Sources */,
DAFC568B172C57EC00CB5CC5 /* IASKPSSliderSpecifierViewCell.m in Sources */,
DAFC568C172C57EC00CB5CC5 /* IASKPSTextFieldSpecifierViewCell.m in Sources */,
DAFC568D172C57EC00CB5CC5 /* IASKPSTitleValueSpecifierViewCell.m in Sources */,
DAFC568E172C57EC00CB5CC5 /* IASKSlider.m in Sources */,
DAFC568F172C57EC00CB5CC5 /* IASKSwitch.m in Sources */,
DAFC5690172C57EC00CB5CC5 /* IASKTextField.m in Sources */,
DA0CC52B1EAB99BA009A8ED9 /* IASKMultipleValueSelection.m in Sources */,
DA0CC5321EAB99BA009A8ED9 /* IASKPSSliderSpecifierViewCell.m in Sources */,
DA0CC52D1EAB99BA009A8ED9 /* IASKSettingsReader.m in Sources */,
DA0CC52A1EAB99BA009A8ED9 /* IASKAppSettingsWebViewController.m in Sources */,
DA0CC5291EAB99BA009A8ED9 /* IASKAppSettingsViewController.m in Sources */,
DA0CC5381EAB99BA009A8ED9 /* IASKTextViewCell.m in Sources */,
DA0CC5311EAB99BA009A8ED9 /* IASKSpecifier.m in Sources */,
DA0CC5341EAB99BA009A8ED9 /* IASKSlider.m in Sources */,
DA0CC5351EAB99BA009A8ED9 /* IASKSwitch.m in Sources */,
DA0CC5331EAB99BA009A8ED9 /* IASKPSTextFieldSpecifierViewCell.m in Sources */,
DA0CC52E1EAB99BA009A8ED9 /* IASKSettingsStore.m in Sources */,
DA0CC52C1EAB99BA009A8ED9 /* IASKSpecifierValuesViewController.m in Sources */,
DA0CC5361EAB99BA009A8ED9 /* IASKTextField.m in Sources */,
DA0CC5371EAB99BA009A8ED9 /* IASKTextView.m in Sources */,
DA0CC52F1EAB99BA009A8ED9 /* IASKSettingsStoreFile.m in Sources */,
DA0CC5301EAB99BA009A8ED9 /* IASKSettingsStoreUserDefaults.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
DA0CC4F51EAB99BA009A8ED9 /* IASKLocalizable.strings */ = {
isa = PBXVariantGroup;
children = (
DA0CC4F61EAB99BA009A8ED9 /* Base */,
DA0CC4F71EAB99BA009A8ED9 /* de */,
DA0CC4F81EAB99BA009A8ED9 /* el */,
DA0CC4F91EAB99BA009A8ED9 /* en */,
DA0CC4FA1EAB99BA009A8ED9 /* es */,
DA0CC4FB1EAB99BA009A8ED9 /* fr */,
DA0CC4FC1EAB99BA009A8ED9 /* it */,
DA0CC4FD1EAB99BA009A8ED9 /* ja */,
DA0CC4FE1EAB99BA009A8ED9 /* nl */,
DA0CC4FF1EAB99BA009A8ED9 /* pt-PT */,
DA0CC5001EAB99BA009A8ED9 /* pt */,
DA0CC5011EAB99BA009A8ED9 /* ru */,
DA0CC5021EAB99BA009A8ED9 /* sv */,
DA0CC5031EAB99BA009A8ED9 /* th */,
DA0CC5041EAB99BA009A8ED9 /* tr */,
);
name = IASKLocalizable.strings;
sourceTree = "<group>";
};
DABD3BFA1711E2DC00CF925C /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
@@ -3844,7 +4081,6 @@
GCC_NO_COMMON_BLOCKS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
"ADHOC=1",
"$(inherited)",
"NDEBUG=1",
"NS_BLOCK_ASSERTIONS=1",
@@ -3913,20 +4149,10 @@
INFOPLIST_FILE = "Source/iOS/MasterPassword-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LIBRARY_SEARCH_PATHS = (
"\"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib\"",
"$(inherited)",
"$(PROJECT_DIR)/External/libsodium/libsodium-ios/lib",
);
OTHER_LDFLAGS = "$(inherited)";
"OTHER_LDFLAGS[sdk=iphoneos*]" = (
"$(inherited)",
"-lscryptenc-ios",
"-lopensslcrypto-ios",
);
"OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
"$(inherited)",
"-lscryptenc-ios-sim",
"-lopensslcrypto-ios-sim",
);
OTHER_CFLAGS = "-DHAS_SODIUM=1";
PRODUCT_BUNDLE_IDENTIFIER = com.lyndir.lhunath.MasterPassword;
SKIP_INSTALL = NO;
STRIP_INSTALLED_PRODUCT = YES;
@@ -4122,7 +4348,6 @@
GCC_NO_COMMON_BLOCKS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
"ADHOC=1",
"$(inherited)",
"NDEBUG=1",
"NS_BLOCK_ASSERTIONS=1",
@@ -4189,20 +4414,10 @@
INFOPLIST_FILE = "Source/iOS/MasterPassword-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LIBRARY_SEARCH_PATHS = (
"\"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib\"",
"$(inherited)",
"$(PROJECT_DIR)/External/libsodium/libsodium-ios/lib",
);
OTHER_LDFLAGS = "$(inherited)";
"OTHER_LDFLAGS[sdk=iphoneos*]" = (
"$(inherited)",
"-lscryptenc-ios",
"-lopensslcrypto-ios",
);
"OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
"$(inherited)",
"-lscryptenc-ios-sim",
"-lopensslcrypto-ios-sim",
);
OTHER_CFLAGS = "-DHAS_SODIUM=1";
PRODUCT_BUNDLE_IDENTIFIER = com.lyndir.lhunath.MasterPassword;
SKIP_INSTALL = NO;
TARGETED_DEVICE_FAMILY = 1;
@@ -4227,20 +4442,10 @@
INFOPLIST_FILE = "Source/iOS/MasterPassword-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LIBRARY_SEARCH_PATHS = (
"\"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib\"",
"$(inherited)",
"$(PROJECT_DIR)/External/libsodium/libsodium-ios/lib",
);
OTHER_LDFLAGS = "$(inherited)";
"OTHER_LDFLAGS[sdk=iphoneos*]" = (
"$(inherited)",
"-lscryptenc-ios",
"-lopensslcrypto-ios",
);
"OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
"$(inherited)",
"-lscryptenc-ios-sim",
"-lopensslcrypto-ios-sim",
);
OTHER_CFLAGS = "-DHAS_SODIUM=1";
PRODUCT_BUNDLE_IDENTIFIER = com.lyndir.lhunath.MasterPassword;
SKIP_INSTALL = NO;
STRIP_INSTALLED_PRODUCT = YES;

View File

@@ -23,7 +23,10 @@
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, ); }; };
DA09745A1E99582900F0BFE8 /* mpw-tests-util.c in Sources */ = {isa = PBXBuildFile; fileRef = DA0974561E99582200F0BFE8 /* mpw-tests-util.c */; };
DA09745B1E99582900F0BFE8 /* mpw-tests.c in Sources */ = {isa = PBXBuildFile; fileRef = DA0974571E99582200F0BFE8 /* mpw-tests.c */; };
DA09745E1E99586600F0BFE8 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = DA09745D1E99586600F0BFE8 /* libxml2.tbd */; };
DA0979681E9A834C00F0BFE8 /* libsodium.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA0979571E9A824700F0BFE8 /* libsodium.a */; };
DA1000801998A4C6002B873F /* openssl in Headers */ = {isa = PBXBuildFile; fileRef = DAE8E65719867AF500416A0F /* openssl */; settings = {ATTRIBUTES = (Public, ); }; };
DA16B341170661DB000A0EAB /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA16B340170661DB000A0EAB /* Carbon.framework */; };
DA16B342170661E0000A0EAB /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC632871486D95D0075AEA5 /* Security.framework */; };
@@ -60,7 +63,6 @@
DA4DAE951A7D8117003E5423 /* MPTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4DAE931A7D8117003E5423 /* MPTypes.m */; };
DA5180CA19FF2F9200A587E9 /* MPAlgorithmV2.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5180C719FF2F9200A587E9 /* MPAlgorithmV2.m */; };
DA5180CE19FF307E00A587E9 /* MPAppDelegate_Store.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5180CD19FF307E00A587E9 /* MPAppDelegate_Store.m */; };
DA5E5C9417248AA1003798D8 /* libscryptenc-osx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5E5C8717248AA1003798D8 /* libscryptenc-osx.a */; };
DA5E5CF61724A667003798D8 /* MPAlgorithm.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5C981724A667003798D8 /* MPAlgorithm.m */; };
DA5E5CF71724A667003798D8 /* MPAlgorithmV0.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5C9A1724A667003798D8 /* MPAlgorithmV0.m */; };
DA5E5CF81724A667003798D8 /* MPAlgorithmV1.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5C9C1724A667003798D8 /* MPAlgorithmV1.m */; };
@@ -154,6 +156,7 @@
DACBFCDF1C59B22E007EF90F /* NSMutableSet+Pearl.m in Sources */ = {isa = PBXBuildFile; fileRef = DACBFCDC1C59B22E007EF90F /* NSMutableSet+Pearl.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 */; };
DADD5DFA1EA173B0005E7D96 /* libsodium.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA0979571E9A824700F0BFE8 /* libsodium.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 */; };
@@ -194,8 +197,6 @@
DAFE4A3715039824003ABA7C /* PearlKeyChain.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE460115039823003ABA7C /* PearlKeyChain.m */; };
DAFE4A3815039824003ABA7C /* PearlRSAKey.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460215039823003ABA7C /* PearlRSAKey.h */; };
DAFE4A3915039824003ABA7C /* PearlRSAKey.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE460315039823003ABA7C /* PearlRSAKey.m */; };
DAFE4A3A15039824003ABA7C /* PearlSCrypt.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE460415039823003ABA7C /* PearlSCrypt.h */; };
DAFE4A3B15039824003ABA7C /* PearlSCrypt.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE460515039823003ABA7C /* PearlSCrypt.m */; };
DAFE4A5A1503982E003ABA7C /* Pearl.strings in Resources */ = {isa = PBXBuildFile; fileRef = DAFE45FA15039823003ABA7C /* Pearl.strings */; };
DAFE4A63150399FF003ABA86 /* NSObject+PearlKVO.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE4A63150399FF003ABA85 /* NSObject+PearlKVO.m */; };
DAFE4A63150399FF003ABA88 /* NSObject+PearlKVO.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE4A63150399FF003ABA87 /* NSObject+PearlKVO.h */; };
@@ -285,6 +286,70 @@
DA0933C91747A56A00DE1CEF /* MPInitialWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MPInitialWindow.xib; sourceTree = "<group>"; };
DA0933CB1747AD2D00DE1CEF /* shot-laptop-leaning-iphone.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "shot-laptop-leaning-iphone.png"; sourceTree = "<group>"; };
DA0933CF1747B91B00DE1CEF /* appstore.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = appstore.png; sourceTree = "<group>"; };
DA0974561E99582200F0BFE8 /* mpw-tests-util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mpw-tests-util.c"; path = "../../platform-independent/cli-c/cli/mpw-tests-util.c"; sourceTree = "<group>"; };
DA0974571E99582200F0BFE8 /* mpw-tests.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mpw-tests.c"; path = "../../platform-independent/cli-c/cli/mpw-tests.c"; sourceTree = "<group>"; };
DA09745C1E99583B00F0BFE8 /* mpw-tests-util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "mpw-tests-util.h"; path = "../../platform-independent/cli-c/cli/mpw-tests-util.h"; sourceTree = "<group>"; };
DA09745D1E99586600F0BFE8 /* libxml2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libxml2.tbd; path = usr/lib/libxml2.tbd; sourceTree = SDKROOT; };
DA09745F1E995EB500F0BFE8 /* mpw_tests.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = mpw_tests.xml; path = ../../core/java/tests/src/main/resources/mpw_tests.xml; sourceTree = "<group>"; };
DA09791B1E9A824700F0BFE8 /* core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = core.h; sourceTree = "<group>"; };
DA09791C1E9A824700F0BFE8 /* crypto_aead_aes256gcm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_aead_aes256gcm.h; sourceTree = "<group>"; };
DA09791D1E9A824700F0BFE8 /* crypto_aead_chacha20poly1305.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_aead_chacha20poly1305.h; sourceTree = "<group>"; };
DA09791E1E9A824700F0BFE8 /* crypto_aead_xchacha20poly1305.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_aead_xchacha20poly1305.h; sourceTree = "<group>"; };
DA09791F1E9A824700F0BFE8 /* crypto_auth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_auth.h; sourceTree = "<group>"; };
DA0979201E9A824700F0BFE8 /* crypto_auth_hmacsha256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_auth_hmacsha256.h; sourceTree = "<group>"; };
DA0979211E9A824700F0BFE8 /* crypto_auth_hmacsha512.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_auth_hmacsha512.h; sourceTree = "<group>"; };
DA0979221E9A824700F0BFE8 /* crypto_auth_hmacsha512256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_auth_hmacsha512256.h; sourceTree = "<group>"; };
DA0979231E9A824700F0BFE8 /* crypto_box.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_box.h; sourceTree = "<group>"; };
DA0979241E9A824700F0BFE8 /* crypto_box_curve25519xchacha20poly1305.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_box_curve25519xchacha20poly1305.h; sourceTree = "<group>"; };
DA0979251E9A824700F0BFE8 /* crypto_box_curve25519xsalsa20poly1305.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_box_curve25519xsalsa20poly1305.h; sourceTree = "<group>"; };
DA0979261E9A824700F0BFE8 /* crypto_core_hchacha20.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_core_hchacha20.h; sourceTree = "<group>"; };
DA0979271E9A824700F0BFE8 /* crypto_core_hsalsa20.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_core_hsalsa20.h; sourceTree = "<group>"; };
DA0979281E9A824700F0BFE8 /* crypto_core_salsa20.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_core_salsa20.h; sourceTree = "<group>"; };
DA0979291E9A824700F0BFE8 /* crypto_core_salsa2012.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_core_salsa2012.h; sourceTree = "<group>"; };
DA09792A1E9A824700F0BFE8 /* crypto_core_salsa208.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_core_salsa208.h; sourceTree = "<group>"; };
DA09792B1E9A824700F0BFE8 /* crypto_generichash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_generichash.h; sourceTree = "<group>"; };
DA09792C1E9A824700F0BFE8 /* crypto_generichash_blake2b.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_generichash_blake2b.h; sourceTree = "<group>"; };
DA09792D1E9A824700F0BFE8 /* crypto_hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_hash.h; sourceTree = "<group>"; };
DA09792E1E9A824700F0BFE8 /* crypto_hash_sha256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_hash_sha256.h; sourceTree = "<group>"; };
DA09792F1E9A824700F0BFE8 /* crypto_hash_sha512.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_hash_sha512.h; sourceTree = "<group>"; };
DA0979301E9A824700F0BFE8 /* crypto_kdf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_kdf.h; sourceTree = "<group>"; };
DA0979311E9A824700F0BFE8 /* crypto_kdf_blake2b.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_kdf_blake2b.h; sourceTree = "<group>"; };
DA0979321E9A824700F0BFE8 /* crypto_kx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_kx.h; sourceTree = "<group>"; };
DA0979331E9A824700F0BFE8 /* crypto_onetimeauth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_onetimeauth.h; sourceTree = "<group>"; };
DA0979341E9A824700F0BFE8 /* crypto_onetimeauth_poly1305.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_onetimeauth_poly1305.h; sourceTree = "<group>"; };
DA0979351E9A824700F0BFE8 /* crypto_pwhash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_pwhash.h; sourceTree = "<group>"; };
DA0979361E9A824700F0BFE8 /* crypto_pwhash_argon2i.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_pwhash_argon2i.h; sourceTree = "<group>"; };
DA0979371E9A824700F0BFE8 /* crypto_pwhash_scryptsalsa208sha256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_pwhash_scryptsalsa208sha256.h; sourceTree = "<group>"; };
DA0979381E9A824700F0BFE8 /* crypto_scalarmult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_scalarmult.h; sourceTree = "<group>"; };
DA0979391E9A824700F0BFE8 /* crypto_scalarmult_curve25519.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_scalarmult_curve25519.h; sourceTree = "<group>"; };
DA09793A1E9A824700F0BFE8 /* crypto_secretbox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_secretbox.h; sourceTree = "<group>"; };
DA09793B1E9A824700F0BFE8 /* crypto_secretbox_xchacha20poly1305.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_secretbox_xchacha20poly1305.h; sourceTree = "<group>"; };
DA09793C1E9A824700F0BFE8 /* crypto_secretbox_xsalsa20poly1305.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_secretbox_xsalsa20poly1305.h; sourceTree = "<group>"; };
DA09793D1E9A824700F0BFE8 /* crypto_shorthash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_shorthash.h; sourceTree = "<group>"; };
DA09793E1E9A824700F0BFE8 /* crypto_shorthash_siphash24.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_shorthash_siphash24.h; sourceTree = "<group>"; };
DA09793F1E9A824700F0BFE8 /* crypto_sign.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_sign.h; sourceTree = "<group>"; };
DA0979401E9A824700F0BFE8 /* crypto_sign_ed25519.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_sign_ed25519.h; sourceTree = "<group>"; };
DA0979411E9A824700F0BFE8 /* crypto_sign_edwards25519sha512batch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_sign_edwards25519sha512batch.h; sourceTree = "<group>"; };
DA0979421E9A824700F0BFE8 /* crypto_stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_stream.h; sourceTree = "<group>"; };
DA0979431E9A824700F0BFE8 /* crypto_stream_aes128ctr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_stream_aes128ctr.h; sourceTree = "<group>"; };
DA0979441E9A824700F0BFE8 /* crypto_stream_chacha20.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_stream_chacha20.h; sourceTree = "<group>"; };
DA0979451E9A824700F0BFE8 /* crypto_stream_salsa20.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_stream_salsa20.h; sourceTree = "<group>"; };
DA0979461E9A824700F0BFE8 /* crypto_stream_salsa2012.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_stream_salsa2012.h; sourceTree = "<group>"; };
DA0979471E9A824700F0BFE8 /* crypto_stream_salsa208.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_stream_salsa208.h; sourceTree = "<group>"; };
DA0979481E9A824700F0BFE8 /* crypto_stream_xchacha20.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_stream_xchacha20.h; sourceTree = "<group>"; };
DA0979491E9A824700F0BFE8 /* crypto_stream_xsalsa20.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_stream_xsalsa20.h; sourceTree = "<group>"; };
DA09794A1E9A824700F0BFE8 /* crypto_verify_16.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_verify_16.h; sourceTree = "<group>"; };
DA09794B1E9A824700F0BFE8 /* crypto_verify_32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_verify_32.h; sourceTree = "<group>"; };
DA09794C1E9A824700F0BFE8 /* crypto_verify_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_verify_64.h; sourceTree = "<group>"; };
DA09794D1E9A824700F0BFE8 /* export.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = export.h; sourceTree = "<group>"; };
DA09794E1E9A824700F0BFE8 /* randombytes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = randombytes.h; sourceTree = "<group>"; };
DA09794F1E9A824700F0BFE8 /* randombytes_salsa20_random.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = randombytes_salsa20_random.h; sourceTree = "<group>"; };
DA0979501E9A824700F0BFE8 /* randombytes_sysrandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = randombytes_sysrandom.h; sourceTree = "<group>"; };
DA0979511E9A824700F0BFE8 /* runtime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = runtime.h; sourceTree = "<group>"; };
DA0979521E9A824700F0BFE8 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = "<group>"; };
DA0979531E9A824700F0BFE8 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = "<group>"; };
DA0979541E9A824700F0BFE8 /* sodium.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sodium.h; sourceTree = "<group>"; };
DA0979571E9A824700F0BFE8 /* libsodium.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libsodium.a; sourceTree = "<group>"; };
DA16B340170661DB000A0EAB /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
DA16B343170661EE000A0EAB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
DA2508F019511D3600AC23F1 /* MPPasswordWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MPPasswordWindowController.xib; sourceTree = "<group>"; };
@@ -332,7 +397,6 @@
DA5BFA4A147E415C00F98B1E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
DA5BFA4C147E415C00F98B1E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
DA5BFA4E147E415C00F98B1E /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
DA5E5C8717248AA1003798D8 /* libscryptenc-osx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libscryptenc-osx.a"; sourceTree = "<group>"; };
DA5E5C971724A667003798D8 /* MPAlgorithm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAlgorithm.h; sourceTree = "<group>"; };
DA5E5C981724A667003798D8 /* MPAlgorithm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAlgorithm.m; sourceTree = "<group>"; };
DA5E5C991724A667003798D8 /* MPAlgorithmV0.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAlgorithmV0.h; sourceTree = "<group>"; };
@@ -868,7 +932,6 @@
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; };
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>"; };
@@ -912,8 +975,6 @@
DAFE460115039823003ABA7C /* PearlKeyChain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlKeyChain.m; sourceTree = "<group>"; };
DAFE460215039823003ABA7C /* PearlRSAKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlRSAKey.h; sourceTree = "<group>"; };
DAFE460315039823003ABA7C /* PearlRSAKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlRSAKey.m; sourceTree = "<group>"; };
DAFE460415039823003ABA7C /* PearlSCrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlSCrypt.h; sourceTree = "<group>"; };
DAFE460515039823003ABA7C /* PearlSCrypt.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlSCrypt.m; sourceTree = "<group>"; };
DAFE460615039823003ABA7C /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
DAFE4A63150399FF003ABA85 /* NSObject+PearlKVO.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+PearlKVO.m"; sourceTree = "<group>"; };
DAFE4A63150399FF003ABA87 /* NSObject+PearlKVO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+PearlKVO.h"; sourceTree = "<group>"; };
@@ -929,6 +990,7 @@
DA9261561BE1A89600369DE5 /* libz.tbd in Frameworks */,
DA9261541BE1A88900369DE5 /* libc++.tbd in Frameworks */,
DAADCC6A19FB00B500987B1D /* libKCOrderedAccessorFix.a in Frameworks */,
DADD5DFA1EA173B0005E7D96 /* libsodium.a in Frameworks */,
DA9261521BE1A86700369DE5 /* Fabric.framework in Frameworks */,
DA9261511BE1A86700369DE5 /* SystemConfiguration.framework in Frameworks */,
DA250925195148E200AC23F1 /* QuartzCore.framework in Frameworks */,
@@ -945,6 +1007,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
DA0979681E9A834C00F0BFE8 /* libsodium.a in Frameworks */,
DA09745E1E99586600F0BFE8 /* libxml2.tbd in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -970,7 +1034,6 @@
DAADCC4B19FB000C00987B1D /* QuartzCore.framework in Frameworks */,
DA4DA1D91564471A00F6F596 /* libjrswizzle.a in Frameworks */,
DAC77CAE148291A600BCF976 /* Foundation.framework in Frameworks */,
DA5E5C9417248AA1003798D8 /* libscryptenc-osx.a in Frameworks */,
DA92614B1BE1A4EA00369DE5 /* libopensslcrypto-osx.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -978,6 +1041,97 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
DA0979181E9A824700F0BFE8 /* libsodium-osx */ = {
isa = PBXGroup;
children = (
DA0979191E9A824700F0BFE8 /* include */,
DA0979551E9A824700F0BFE8 /* lib */,
);
name = "libsodium-osx";
path = "libsodium/libsodium-osx";
sourceTree = "<group>";
};
DA0979191E9A824700F0BFE8 /* include */ = {
isa = PBXGroup;
children = (
DA09791A1E9A824700F0BFE8 /* sodium */,
DA0979541E9A824700F0BFE8 /* sodium.h */,
);
path = include;
sourceTree = "<group>";
};
DA09791A1E9A824700F0BFE8 /* sodium */ = {
isa = PBXGroup;
children = (
DA09791B1E9A824700F0BFE8 /* core.h */,
DA09791C1E9A824700F0BFE8 /* crypto_aead_aes256gcm.h */,
DA09791D1E9A824700F0BFE8 /* crypto_aead_chacha20poly1305.h */,
DA09791E1E9A824700F0BFE8 /* crypto_aead_xchacha20poly1305.h */,
DA09791F1E9A824700F0BFE8 /* crypto_auth.h */,
DA0979201E9A824700F0BFE8 /* crypto_auth_hmacsha256.h */,
DA0979211E9A824700F0BFE8 /* crypto_auth_hmacsha512.h */,
DA0979221E9A824700F0BFE8 /* crypto_auth_hmacsha512256.h */,
DA0979231E9A824700F0BFE8 /* crypto_box.h */,
DA0979241E9A824700F0BFE8 /* crypto_box_curve25519xchacha20poly1305.h */,
DA0979251E9A824700F0BFE8 /* crypto_box_curve25519xsalsa20poly1305.h */,
DA0979261E9A824700F0BFE8 /* crypto_core_hchacha20.h */,
DA0979271E9A824700F0BFE8 /* crypto_core_hsalsa20.h */,
DA0979281E9A824700F0BFE8 /* crypto_core_salsa20.h */,
DA0979291E9A824700F0BFE8 /* crypto_core_salsa2012.h */,
DA09792A1E9A824700F0BFE8 /* crypto_core_salsa208.h */,
DA09792B1E9A824700F0BFE8 /* crypto_generichash.h */,
DA09792C1E9A824700F0BFE8 /* crypto_generichash_blake2b.h */,
DA09792D1E9A824700F0BFE8 /* crypto_hash.h */,
DA09792E1E9A824700F0BFE8 /* crypto_hash_sha256.h */,
DA09792F1E9A824700F0BFE8 /* crypto_hash_sha512.h */,
DA0979301E9A824700F0BFE8 /* crypto_kdf.h */,
DA0979311E9A824700F0BFE8 /* crypto_kdf_blake2b.h */,
DA0979321E9A824700F0BFE8 /* crypto_kx.h */,
DA0979331E9A824700F0BFE8 /* crypto_onetimeauth.h */,
DA0979341E9A824700F0BFE8 /* crypto_onetimeauth_poly1305.h */,
DA0979351E9A824700F0BFE8 /* crypto_pwhash.h */,
DA0979361E9A824700F0BFE8 /* crypto_pwhash_argon2i.h */,
DA0979371E9A824700F0BFE8 /* crypto_pwhash_scryptsalsa208sha256.h */,
DA0979381E9A824700F0BFE8 /* crypto_scalarmult.h */,
DA0979391E9A824700F0BFE8 /* crypto_scalarmult_curve25519.h */,
DA09793A1E9A824700F0BFE8 /* crypto_secretbox.h */,
DA09793B1E9A824700F0BFE8 /* crypto_secretbox_xchacha20poly1305.h */,
DA09793C1E9A824700F0BFE8 /* crypto_secretbox_xsalsa20poly1305.h */,
DA09793D1E9A824700F0BFE8 /* crypto_shorthash.h */,
DA09793E1E9A824700F0BFE8 /* crypto_shorthash_siphash24.h */,
DA09793F1E9A824700F0BFE8 /* crypto_sign.h */,
DA0979401E9A824700F0BFE8 /* crypto_sign_ed25519.h */,
DA0979411E9A824700F0BFE8 /* crypto_sign_edwards25519sha512batch.h */,
DA0979421E9A824700F0BFE8 /* crypto_stream.h */,
DA0979431E9A824700F0BFE8 /* crypto_stream_aes128ctr.h */,
DA0979441E9A824700F0BFE8 /* crypto_stream_chacha20.h */,
DA0979451E9A824700F0BFE8 /* crypto_stream_salsa20.h */,
DA0979461E9A824700F0BFE8 /* crypto_stream_salsa2012.h */,
DA0979471E9A824700F0BFE8 /* crypto_stream_salsa208.h */,
DA0979481E9A824700F0BFE8 /* crypto_stream_xchacha20.h */,
DA0979491E9A824700F0BFE8 /* crypto_stream_xsalsa20.h */,
DA09794A1E9A824700F0BFE8 /* crypto_verify_16.h */,
DA09794B1E9A824700F0BFE8 /* crypto_verify_32.h */,
DA09794C1E9A824700F0BFE8 /* crypto_verify_64.h */,
DA09794D1E9A824700F0BFE8 /* export.h */,
DA09794E1E9A824700F0BFE8 /* randombytes.h */,
DA09794F1E9A824700F0BFE8 /* randombytes_salsa20_random.h */,
DA0979501E9A824700F0BFE8 /* randombytes_sysrandom.h */,
DA0979511E9A824700F0BFE8 /* runtime.h */,
DA0979521E9A824700F0BFE8 /* utils.h */,
DA0979531E9A824700F0BFE8 /* version.h */,
);
path = sodium;
sourceTree = "<group>";
};
DA0979551E9A824700F0BFE8 /* lib */ = {
isa = PBXGroup;
children = (
DA0979571E9A824700F0BFE8 /* libsodium.a */,
);
path = lib;
sourceTree = "<group>";
};
DA2508F819513C1400AC23F1 /* Other Frameworks */ = {
isa = PBXGroup;
children = (
@@ -1025,6 +1179,7 @@
DA5BFA47147E415C00F98B1E /* Frameworks */ = {
isa = PBXGroup;
children = (
DA09745D1E99586600F0BFE8 /* libxml2.tbd */,
DA6701B716406A4100B61001 /* Accounts.framework */,
DA16B340170661DB000A0EAB /* Carbon.framework */,
DA16B343170661EE000A0EAB /* Cocoa.framework */,
@@ -1048,7 +1203,6 @@
children = (
DAEB938518AB0FFD000490CC /* include */,
DAE8E65319867ADA00416A0F /* libopensslcrypto-osx.a */,
DA5E5C8717248AA1003798D8 /* libscryptenc-osx.a */,
);
path = lib;
sourceTree = "<group>";
@@ -1552,6 +1706,9 @@
DA831A2A1A6E1146000AC234 /* mpw-algorithm_v3.c */,
DA6773BB1A4746AF004F356A /* mpw-algorithm.c */,
DA6773BC1A4746AF004F356A /* mpw-algorithm.h */,
DA0974561E99582200F0BFE8 /* mpw-tests-util.c */,
DA09745C1E99583B00F0BFE8 /* mpw-tests-util.h */,
DA0974571E99582200F0BFE8 /* mpw-tests.c */,
DA6773C21A4746AF004F356A /* mpw-types.c */,
DA6773C31A4746AF004F356A /* mpw-types.h */,
DA6773C51A4746AF004F356A /* mpw-util.c */,
@@ -1603,6 +1760,7 @@
DACA22121705DDC5002C6C22 /* External */ = {
isa = PBXGroup;
children = (
DA0979181E9A824700F0BFE8 /* libsodium-osx */,
DACA29751705E2BD002C6C22 /* jrswizzle */,
DAADCC6819FB007F00987B1D /* KCOrderedAccessorFix */,
DA3B8449190FC5A900246EEA /* Mac */,
@@ -1614,6 +1772,7 @@
DACA23B41705DF7D002C6C22 /* Resources */ = {
isa = PBXGroup;
children = (
DA09745F1E995EB500F0BFE8 /* mpw_tests.xml */,
DACA26991705DF81002C6C22 /* Crashlytics */,
DACA29701705E1A8002C6C22 /* Data */,
DACA23B51705DF7D002C6C22 /* Media */,
@@ -1761,7 +1920,6 @@
isa = PBXGroup;
children = (
DAE8E65719867AF500416A0F /* openssl */,
DAE8E65619867AF500416A0F /* scrypt */,
);
path = include;
sourceTree = "<group>";
@@ -1854,8 +2012,6 @@
DAFE460115039823003ABA7C /* PearlKeyChain.m */,
DAFE460215039823003ABA7C /* PearlRSAKey.h */,
DAFE460315039823003ABA7C /* PearlRSAKey.m */,
DAFE460415039823003ABA7C /* PearlSCrypt.h */,
DAFE460515039823003ABA7C /* PearlSCrypt.m */,
DAFE460615039823003ABA7C /* README */,
);
path = "Pearl-Crypto";
@@ -1876,7 +2032,6 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
DA10007F1998A4C6002B873F /* scrypt in Headers */,
DA89D4EC1A51EABD00AC64D7 /* Pearl-Cocoa.h in Headers */,
DA1000801998A4C6002B873F /* openssl in Headers */,
DA2CA4F218D323D3007798F8 /* NSTimer+PearlBlock.h in Headers */,
@@ -1903,7 +2058,6 @@
DAFE4A3415039824003ABA7C /* PearlCryptUtils.h in Headers */,
DAFE4A3615039824003ABA7C /* PearlKeyChain.h in Headers */,
DAFE4A3815039824003ABA7C /* PearlRSAKey.h in Headers */,
DAFE4A3A15039824003ABA7C /* PearlSCrypt.h in Headers */,
DA30E9D715723E6900A68B4C /* PearlLazy.h in Headers */,
DAADCC4719FAFFAD00987B1D /* NSNotificationCenter+PearlEasyCleanup.h in Headers */,
DAFE4A63150399FF003ABA88 /* NSObject+PearlKVO.h in Headers */,
@@ -1926,6 +2080,7 @@
buildConfigurationList = DA5BFA6D147E415C00F98B1E /* Build configuration list for PBXNativeTarget "MasterPassword" */;
buildPhases = (
DA4EF9CB19FD4B600032ECB5 /* Run Script: genassets */,
DA0E86A91E9BED9300F4D60E /* Run Script: libsodium/dist-build/osx.sh */,
DA5BFA40147E415C00F98B1E /* Sources */,
DA5BFA41147E415C00F98B1E /* Frameworks */,
DA5BFA42147E415C00F98B1E /* Resources */,
@@ -2160,6 +2315,21 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
DA0E86A91E9BED9300F4D60E /* Run Script: libsodium/dist-build/osx.sh */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script: libsodium/dist-build/osx.sh";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = "/bin/sh -e";
shellScript = "cd External/libsodium\nif ! [[ -d libsodium-osx ]]; then\n # Xcode misinterpretes autogen.sh's stderr output as errors so we try to silence it.\n [[ -e configure ]] || { err=$(./autogen.sh 2>&1 >&3); } 3>&1 || { x=$?; echo >&2 \"$err\"; exit $x; }\n./dist-build/osx.sh\nfi\n\n# Xcode incorrectly links the dynamic libraries if they're present instead of linking the .a.\nrm -f libsodium-osx/lib/*.dylib";
showEnvVarsInLog = 0;
};
DA4EF9CB19FD4B600032ECB5 /* Run Script: genassets */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -2252,6 +2422,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DA09745B1E99582900F0BFE8 /* mpw-tests.c in Sources */,
DA09745A1E99582900F0BFE8 /* mpw-tests-util.c in Sources */,
DA6774451A474A3B004F356A /* mpw-types.c in Sources */,
DA6774461A474A3B004F356A /* mpw-util.c in Sources */,
DA6774431A474A3B004F356A /* mpw-algorithm.c in Sources */,
@@ -2298,7 +2470,6 @@
DA89D4ED1A51EABD00AC64D7 /* Pearl-Cocoa.m in Sources */,
DAFE4A3715039824003ABA7C /* PearlKeyChain.m in Sources */,
DAFE4A3915039824003ABA7C /* PearlRSAKey.m in Sources */,
DAFE4A3B15039824003ABA7C /* PearlSCrypt.m in Sources */,
DA8ED895192906920099B726 /* PearlTween.m in Sources */,
DA2CA4F118D323D3007798F8 /* NSTimer+PearlBlock.m in Sources */,
DA3B8452190FC86F00246EEA /* NSManagedObject+Pearl.m in Sources */,
@@ -2397,7 +2568,6 @@
GCC_NO_COMMON_BLOCKS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
"ADHOC=1",
"$(inherited)",
"NDEBUG=1",
"NS_BLOCK_ASSERTIONS=1",
@@ -2468,9 +2638,10 @@
INFOPLIST_FILE = "Source/Mac/MasterPassword-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
LIBRARY_SEARCH_PATHS = (
"\"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib\"",
"$(inherited)",
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
);
OTHER_CFLAGS = "-DHAS_SODIUM=1";
PRODUCT_BUNDLE_IDENTIFIER = com.lyndir.lhunath.MasterPassword.Mac;
SKIP_INSTALL = NO;
WRAPPER_NAME = "Master Password.${WRAPPER_EXTENSION}";
@@ -2517,8 +2688,21 @@
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
/usr/include/libxml2,
/usr/local/include,
);
LIBRARY_SEARCH_PATHS = (
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
"$(inherited)",
"$(PROJECT_DIR)/External/Pearl/Pearl-Crypto/lib",
/usr/local/Cellar/libsodium/1.0.12/lib,
/usr/local/Cellar/libscrypt/1.21/lib,
"$(PROJECT_DIR)/External/libsodium/libsodium-ios/lib",
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
);
OTHER_CFLAGS = (
"-DHAS_CPERCIVA=0",
"-DHAS_SODIUM=1",
);
};
name = Test;
@@ -2653,7 +2837,6 @@
GCC_NO_COMMON_BLOCKS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
"ADHOC=1",
"$(inherited)",
"NDEBUG=1",
"NS_BLOCK_ASSERTIONS=1",
@@ -2724,9 +2907,10 @@
INFOPLIST_FILE = "Source/Mac/MasterPassword-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
LIBRARY_SEARCH_PATHS = (
"\"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib\"",
"$(inherited)",
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
);
OTHER_CFLAGS = "-DHAS_SODIUM=1";
PRODUCT_BUNDLE_IDENTIFIER = com.lyndir.lhunath.MasterPassword.Mac;
SKIP_INSTALL = NO;
WRAPPER_NAME = "Master Password.${WRAPPER_EXTENSION}";
@@ -2751,9 +2935,10 @@
INFOPLIST_FILE = "Source/Mac/MasterPassword-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
LIBRARY_SEARCH_PATHS = (
"\"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib\"",
"$(inherited)",
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
);
OTHER_CFLAGS = "-DHAS_SODIUM=1";
PRODUCT_BUNDLE_IDENTIFIER = com.lyndir.lhunath.MasterPassword.Mac;
SKIP_INSTALL = NO;
WRAPPER_NAME = "Master Password.${WRAPPER_EXTENSION}";
@@ -2766,8 +2951,21 @@
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
/usr/include/libxml2,
/usr/local/include,
);
LIBRARY_SEARCH_PATHS = (
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
"$(inherited)",
"$(PROJECT_DIR)/External/Pearl/Pearl-Crypto/lib",
/usr/local/Cellar/libsodium/1.0.12/lib,
/usr/local/Cellar/libscrypt/1.21/lib,
"$(PROJECT_DIR)/External/libsodium/libsodium-ios/lib",
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
);
OTHER_CFLAGS = (
"-DHAS_CPERCIVA=0",
"-DHAS_SODIUM=1",
);
};
name = Debug;
@@ -2778,8 +2976,21 @@
CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
/usr/include/libxml2,
/usr/local/include,
);
LIBRARY_SEARCH_PATHS = (
"$(SRCROOT)/External/Pearl/Pearl-Crypto/lib",
"$(inherited)",
"$(PROJECT_DIR)/External/Pearl/Pearl-Crypto/lib",
/usr/local/Cellar/libsodium/1.0.12/lib,
/usr/local/Cellar/libscrypt/1.21/lib,
"$(PROJECT_DIR)/External/libsodium/libsodium-ios/lib",
"$(PROJECT_DIR)/External/libsodium/libsodium-osx/lib",
);
OTHER_CFLAGS = (
"-DHAS_CPERCIVA=0",
"-DHAS_SODIUM=1",
);
};
name = Release;

View File

@@ -46,7 +46,8 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
useCustomWorkingDirectory = "YES"
customWorkingDirectory = "/Users/lhunath/Documents/workspace/lyndir/MasterPassword/platform-independent/cli-c"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"

View File

@@ -9,8 +9,9 @@
"8A15A8EA0B3D0B497C4883425BC74DF995224BB3" : 9223372036854775807,
"1712FC0BC3C9AABD8B7B5376E310E93FBDB3BCFA" : 9223372036854775807,
"2FE140B36B7D26140DC8D5E5C639DC5900EFCF35" : 9223372036854775807,
"3ED8592497DB6A564366943C9AAD5A46341B5076" : 9223372036854775807,
"4DDCFFD91B41F00326AD14553BD66CFD366ABD91" : 9223372036854775807,
"3ED8592497DB6A564366943C9AAD5A46341B5076" : 9223372036854775807,
"81A28796384A028E6C2D47C039DB8B3E5DD6D0FC" : 9223372036854775807,
"F788B28042EDBEF29EFE34687DA79A778C2CC260" : 0
},
"DVTSourceControlWorkspaceBlueprintIdentifierKey" : "1DC75A27-0030-4493-ACE8-E1D49AB9A549",
@@ -20,8 +21,9 @@
"8A15A8EA0B3D0B497C4883425BC74DF995224BB3" : "MasterPassword\/platform-darwin\/External\/jrswizzle\/",
"1712FC0BC3C9AABD8B7B5376E310E93FBDB3BCFA" : "MasterPassword\/platform-darwin\/External\/InAppSettingsKit\/",
"2FE140B36B7D26140DC8D5E5C639DC5900EFCF35" : "MasterPassword\/platform-darwin\/External\/uicolor-utilities\/",
"3ED8592497DB6A564366943C9AAD5A46341B5076" : "MasterPassword\/platform-darwin\/External\/AttributedMarkdown\/",
"4DDCFFD91B41F00326AD14553BD66CFD366ABD91" : "MasterPassword\/platform-darwin\/External\/Pearl\/",
"3ED8592497DB6A564366943C9AAD5A46341B5076" : "MasterPassword\/platform-darwin\/External\/AttributedMarkdown\/",
"81A28796384A028E6C2D47C039DB8B3E5DD6D0FC" : "MasterPassword\/platform-darwin\/External\/libsodium\/",
"F788B28042EDBEF29EFE34687DA79A778C2CC260" : "MasterPassword\/"
},
"DVTSourceControlWorkspaceBlueprintNameKey" : "MasterPassword",
@@ -58,6 +60,11 @@
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "4DDCFFD91B41F00326AD14553BD66CFD366ABD91"
},
{
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/jedisct1\/libsodium.git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "81A28796384A028E6C2D47C039DB8B3E5DD6D0FC"
},
{
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "git:\/\/github.com\/jonmarimba\/jrswizzle.git",
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",

View File

@@ -35,11 +35,15 @@ setSettingWithTitle() {
done
}
description=$(git describe --always --dirty --long --match '*-release')
version=${description%-g*}
release=${version%%-*} build=${version##*-}
printf -v version '%s.%d' "$release" "$build"
printf -v commit '%s' "${description##*-g}"
case $PLATFORM_NAME in
macosx) platform=mac ;;
iphone*) platform=ios ;;
*) ftl 'ERROR: Unknown platform: %s.' "$PLATFORM_NAME"; exit 1 ;;
esac
description=$(git describe --always --dirty --long --match "*-$platform-*")
version=${description%-g*} build=${version##*-} version=${version%-$build}
version=${version//-*-/.} release=${version%%-*} commit=${description##*-g}
addPlistWithKey GITDescription string "$description"
setPlistWithKey CFBundleVersion "$(hr "${version%%.*}" 14).${version#*.}"
@@ -55,6 +59,8 @@ if [[ $DEPLOYMENT_LOCATION = YES ]]; then
passed=1
[[ $description != *-dirty ]] || \
{ passed=0; err 'ERROR: Cannot release a dirty version, first commit any changes.'; }
[[ $build == 0 ]] || \
{ passed=0; err 'ERROR: Commit is not tagged for release, first tag accordingly.'; }
[[ -r "$crashlyticsPlist" && $(PlistBuddy -c "Print :'API Key'" "$crashlyticsPlist" 2>/dev/null) ]] || \
{ passed=0; err 'ERROR: Cannot release: Crashlytics API key is missing.'; }
(( passed )) || \

View File

@@ -58,6 +58,7 @@ NSString *NSStringFromTimeToCrack(TimeToCrack timeToCrack);
- (Class)classOfType:(MPSiteType)type;
- (NSArray *)allTypes;
- (NSArray *)allTypesStartingWith:(MPSiteType)startingType;
- (MPSiteType)defaultType;
- (MPSiteType)nextType:(MPSiteType)type;
- (MPSiteType)previousType:(MPSiteType)type;

View File

@@ -24,8 +24,6 @@
#import "MPAppDelegate_Shared.h"
#import "MPAppDelegate_InApp.h"
#import "mpw-util.h"
#include <openssl/bn.h>
#include <openssl/err.h>
/* An AMD HD 7970 calculates 2495M SHA-1 hashes per second at a cost of ~350$ per GPU */
#define CRACKING_PER_SECOND 2495000000UL
@@ -33,17 +31,13 @@
NSOperationQueue *_mpwQueue = nil;
@implementation MPAlgorithmV0 {
BN_CTX *_ctx;
}
@implementation MPAlgorithmV0
- (id)init {
if (!(self = [super init]))
return nil;
_ctx = BN_CTX_new();
static dispatch_once_t once = 0;
dispatch_once( &once, ^{
_mpwQueue = [NSOperationQueue new];
@@ -54,12 +48,6 @@ NSOperationQueue *_mpwQueue = nil;
return self;
}
- (void)dealloc {
BN_CTX_free( _ctx );
_ctx = NULL;
}
- (MPAlgorithmVersion)version {
return MPAlgorithmVersion0;
@@ -298,6 +286,11 @@ NSOperationQueue *_mpwQueue = nil;
return allTypes;
}
- (MPSiteType)defaultType {
return MPSiteTypeGeneratedLong;
}
- (MPSiteType)nextType:(MPSiteType)type {
switch (type) {
@@ -321,9 +314,9 @@ NSOperationQueue *_mpwQueue = nil;
return MPSiteTypeStoredDevicePrivate;
case MPSiteTypeStoredDevicePrivate:
return MPSiteTypeGeneratedPhrase;
default:
return MPSiteTypeGeneratedLong;
}
return [self defaultType];
}
- (MPSiteType)previousType:(MPSiteType)type {
@@ -427,9 +420,9 @@ NSOperationQueue *_mpwQueue = nil;
[PearlKeyChain deleteItemForQuery:siteQuery];
else
[PearlKeyChain addOrUpdateItemForQuery:siteQuery withAttributes:@{
(__bridge id)kSecValueData: encryptedContent,
(__bridge id)kSecValueData : encryptedContent,
#if TARGET_OS_IPHONE
(__bridge id)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
(__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
#endif
}];
((MPStoredSiteEntity *)site).contentObject = nil;
@@ -442,58 +435,38 @@ NSOperationQueue *_mpwQueue = nil;
- (NSString *)resolveLoginForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey {
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter( group );
__block NSString *result = nil;
[self resolveLoginForSite:site usingKey:siteKey result:^(NSString *result_) {
result = result_;
dispatch_group_leave( group );
}];
dispatch_group_wait( group, DISPATCH_TIME_FOREVER );
return result;
return PearlAwait( ^(void (^setResult)(id)) {
[self resolveLoginForSite:site usingKey:siteKey result:^(NSString *result_) {
setResult( result_ );
}];
} );
}
- (NSString *)resolvePasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey {
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter( group );
__block NSString *result = nil;
[self resolvePasswordForSite:site usingKey:siteKey result:^(NSString *result_) {
result = result_;
dispatch_group_leave( group );
}];
dispatch_group_wait( group, DISPATCH_TIME_FOREVER );
return result;
return PearlAwait( ^(void (^setResult)(id)) {
[self resolvePasswordForSite:site usingKey:siteKey result:^(NSString *result_) {
setResult( result_ );
}];
} );
}
- (NSString *)resolveAnswerForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey {
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter( group );
__block NSString *result = nil;
[self resolveAnswerForSite:site usingKey:siteKey result:^(NSString *result_) {
result = result_;
dispatch_group_leave( group );
}];
dispatch_group_wait( group, DISPATCH_TIME_FOREVER );
return result;
return PearlAwait( ^(void (^setResult)(id)) {
[self resolveAnswerForSite:site usingKey:siteKey result:^(NSString *result_) {
setResult( result_ );
}];
} );
}
- (NSString *)resolveAnswerForQuestion:(MPSiteQuestionEntity *)question usingKey:(MPKey *)siteKey {
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter( group );
__block NSString *result = nil;
[self resolveAnswerForQuestion:question usingKey:siteKey result:^(NSString *result_) {
result = result_;
dispatch_group_leave( group );
}];
dispatch_group_wait( group, DISPATCH_TIME_FOREVER );
return result;
return PearlAwait( ^(void (^setResult)(id)) {
[self resolveAnswerForQuestion:question usingKey:siteKey result:^(NSString *result_) {
setResult( result_ );
}];
} );
}
- (void)resolveLoginForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey result:(void ( ^ )(NSString *result))resultBlock {
@@ -510,10 +483,12 @@ NSOperationQueue *_mpwQueue = nil;
else
algorithm = site.algorithm;
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
resultBlock( loginName || !loginGenerated? loginName:
[algorithm generateLoginForSiteNamed:name usingKey:siteKey] );
} );
if (!loginGenerated || [loginName length])
resultBlock( loginName );
else
PearlNotMainQueue( ^{
resultBlock( [algorithm generateLoginForSiteNamed:name usingKey:siteKey] );
} );
}
- (void)resolvePasswordForSite:(MPSiteEntity *)site usingKey:(MPKey *)siteKey result:(void ( ^ )(NSString *result))resultBlock {
@@ -545,9 +520,8 @@ NSOperationQueue *_mpwQueue = nil;
else
algorithm = site.algorithm;
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
NSString *result = [algorithm generatePasswordForSiteNamed:name ofType:type withCounter:counter usingKey:siteKey];
resultBlock( result );
PearlNotMainQueue( ^{
resultBlock( [algorithm generatePasswordForSiteNamed:name ofType:type withCounter:counter usingKey:siteKey] );
} );
break;
}
@@ -561,9 +535,8 @@ NSOperationQueue *_mpwQueue = nil;
NSData *encryptedContent = ((MPStoredSiteEntity *)site).contentObject;
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
NSString *result = [self decryptContent:encryptedContent usingKey:siteKey];
resultBlock( result );
PearlNotMainQueue( ^{
resultBlock( [self decryptContent:encryptedContent usingKey:siteKey] );
} );
break;
}
@@ -575,9 +548,8 @@ NSOperationQueue *_mpwQueue = nil;
NSDictionary *siteQuery = [self queryForDevicePrivateSiteNamed:site.name];
NSData *encryptedContent = [PearlKeyChain dataOfItemForQuery:siteQuery];
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
NSString *result = [self decryptContent:encryptedContent usingKey:siteKey];
resultBlock( result );
PearlNotMainQueue( ^{
resultBlock( [self decryptContent:encryptedContent usingKey:siteKey] );
} );
break;
}
@@ -596,9 +568,8 @@ NSOperationQueue *_mpwQueue = nil;
else
algorithm = site.algorithm;
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
NSString *result = [algorithm generateAnswerForSiteNamed:name onQuestion:nil usingKey:siteKey];
resultBlock( result );
PearlNotMainQueue( ^{
resultBlock( [algorithm generateAnswerForSiteNamed:name onQuestion:nil usingKey:siteKey] );
} );
}
@@ -617,9 +588,8 @@ NSOperationQueue *_mpwQueue = nil;
else if ([[MPAppDelegate_Shared get] isFeatureUnlocked:MPProductGenerateAnswers])
algorithm = question.site.algorithm;
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
NSString *result = [algorithm generateAnswerForSiteNamed:name onQuestion:keyword usingKey:siteKey];
resultBlock( result );
PearlNotMainQueue( ^{
resultBlock( [algorithm generateAnswerForSiteNamed:name onQuestion:keyword usingKey:siteKey] );
} );
}
@@ -761,18 +731,17 @@ NSOperationQueue *_mpwQueue = nil;
if (!templates)
return NO;
BIGNUM *permutations = BN_new(), *templatePermutations = BN_new();
NSDecimalNumber *permutations = [NSDecimalNumber zero], *templatePermutations;
for (size_t t = 0; t < count; ++t) {
const char *template = templates[t];
BN_one( templatePermutations );
templatePermutations = [NSDecimalNumber one];
for (NSUInteger c = 0; c < strlen( template ); ++c)
BN_mul_word( templatePermutations,
(BN_ULONG)strlen( mpw_charactersInClass( template[c] ) ) );
templatePermutations = [templatePermutations decimalNumberByMultiplyingBy:
(id)[[NSDecimalNumber alloc] initWithUnsignedLong:strlen( mpw_charactersInClass( template[c] ) )]];
BN_add( permutations, permutations, templatePermutations );
permutations = [permutations decimalNumberByAdding:templatePermutations];
}
BN_free( templatePermutations );
free( templates );
return [self timeToCrack:timeToCrack permutations:permutations forAttacker:attacker];
@@ -780,114 +749,108 @@ NSOperationQueue *_mpwQueue = nil;
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack passwordString:(NSString *)password byAttacker:(MPAttacker)attacker {
BIGNUM *permutations = BN_new();
BN_one( permutations );
NSDecimalNumber *permutations = [NSDecimalNumber one];
for (NSUInteger c = 0; c < [password length]; ++c) {
const char passwordCharacter = [password substringWithRange:NSMakeRange( c, 1 )].UTF8String[0];
unsigned int characterEntropy = 0;
unsigned long characterEntropy = 0;
for (NSString *characterClass in @[ @"v", @"c", @"a", @"x" ]) {
char const *charactersForClass = mpw_charactersInClass( characterClass.UTF8String[0] );
if (strchr( charactersForClass, passwordCharacter )) {
// Found class for password character.
characterEntropy = (BN_ULONG)strlen( charactersForClass );
characterEntropy = strlen( charactersForClass );
break;
}
}
if (!characterEntropy)
characterEntropy = 256 /* a byte */;
BN_mul_word( permutations, characterEntropy );
permutations = [permutations decimalNumberByMultiplyingBy:
(id)[[NSDecimalNumber alloc] initWithUnsignedLong:characterEntropy]];
}
return [self timeToCrack:timeToCrack permutations:permutations forAttacker:attacker];
}
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack permutations:(BIGNUM *)permutations forAttacker:(MPAttacker)attacker {
- (BOOL)timeToCrack:(out TimeToCrack *)timeToCrack permutations:(NSDecimalNumber *)permutations forAttacker:(MPAttacker)attacker {
// Determine base seconds needed to calculate the permutations.
BIGNUM *secondsToCrack = BN_dup( permutations );
BN_div_word( secondsToCrack, CRACKING_PER_SECOND );
NSDecimalNumber *secondsToCrack = [permutations decimalNumberByDividingBy:
(id)[[NSDecimalNumber alloc] initWithUnsignedLong: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 );
secondsToCrack = [secondsToCrack decimalNumberByMultiplyingBy:
(id)[[NSDecimalNumber alloc] initWithUnsignedLong:CRACKING_PRICE]];
secondsToCrack = [secondsToCrack decimalNumberByDividingBy:
(id)[[NSDecimalNumber alloc] initWithUnsignedLong:5000]];
break;
case MPAttacker20M:
BN_mul_word( secondsToCrack, CRACKING_PRICE );
BN_div_word( secondsToCrack, 20000000 );
secondsToCrack = [secondsToCrack decimalNumberByMultiplyingBy:
(id)[[NSDecimalNumber alloc] initWithUnsignedLong:CRACKING_PRICE]];
secondsToCrack = [secondsToCrack decimalNumberByDividingBy:
(id)[[NSDecimalNumber alloc] initWithUnsignedLong:20000000]];
break;
case MPAttacker5B:
BN_mul_word( secondsToCrack, CRACKING_PRICE );
BN_div_word( secondsToCrack, 5000 );
BN_div_word( secondsToCrack, 1000000 );
secondsToCrack = [secondsToCrack decimalNumberByMultiplyingBy:
(id)[[NSDecimalNumber alloc] initWithUnsignedLong:CRACKING_PRICE]];
secondsToCrack = [secondsToCrack decimalNumberByDividingBy:
(id)[[NSDecimalNumber alloc] initWithUnsignedLong:5000]];
secondsToCrack = [secondsToCrack decimalNumberByDividingBy:
(id)[[NSDecimalNumber alloc] initWithUnsignedLong:1000000]];
break;
}
BIGNUM *max = BN_new();
BN_set_word( max, (BN_ULONG)-1 );
NSDecimalNumber *ulong_max = (id)[[NSDecimalNumber alloc] initWithUnsignedLong:ULONG_MAX];
BIGNUM *hoursToCrack = BN_dup( secondsToCrack );
BN_div_word( hoursToCrack, 3600 );
if (BN_cmp( hoursToCrack, max ) < 0)
timeToCrack->hours = BN_get_word( hoursToCrack );
NSDecimalNumber *hoursToCrack = [secondsToCrack decimalNumberByDividingBy:
(id)[[NSDecimalNumber alloc] initWithUnsignedLong:3600L]];
if ([hoursToCrack compare:ulong_max] == NSOrderedAscending)
timeToCrack->hours = (unsigned long long)[hoursToCrack doubleValue];
else
timeToCrack->hours = (BN_ULONG)-1;
timeToCrack->hours = ULONG_MAX;
BIGNUM *daysToCrack = BN_dup( hoursToCrack );
BN_div_word( daysToCrack, 24 );
if (BN_cmp( daysToCrack, max ) < 0)
timeToCrack->days = BN_get_word( daysToCrack );
NSDecimalNumber *daysToCrack = [hoursToCrack decimalNumberByDividingBy:
(id)[[NSDecimalNumber alloc] initWithUnsignedLong:24L]];
if ([daysToCrack compare:ulong_max] == NSOrderedAscending)
timeToCrack->days = (unsigned long long)[daysToCrack doubleValue];
else
timeToCrack->days = (BN_ULONG)-1;
timeToCrack->days = ULONG_MAX;
BIGNUM *weeksToCrack = BN_dup( daysToCrack );
BN_div_word( weeksToCrack, 7 );
if (BN_cmp( weeksToCrack, max ) < 0)
timeToCrack->weeks = BN_get_word( weeksToCrack );
NSDecimalNumber *weeksToCrack = [daysToCrack decimalNumberByDividingBy:
(id)[[NSDecimalNumber alloc] initWithUnsignedLong:7L]];
if ([weeksToCrack compare:ulong_max] == NSOrderedAscending)
timeToCrack->weeks = (unsigned long long)[weeksToCrack doubleValue];
else
timeToCrack->weeks = (BN_ULONG)-1;
timeToCrack->weeks = ULONG_MAX;
BIGNUM *monthsToCrack = BN_dup( daysToCrack );
BN_div_word( monthsToCrack, 31 );
if (BN_cmp( monthsToCrack, max ) < 0)
timeToCrack->months = BN_get_word( monthsToCrack );
NSDecimalNumber *monthsToCrack = [daysToCrack decimalNumberByDividingBy:
(id)[[NSDecimalNumber alloc] initWithUnsignedLong:31L]];
if ([monthsToCrack compare:ulong_max] == NSOrderedAscending)
timeToCrack->months = (unsigned long long)[monthsToCrack doubleValue];
else
timeToCrack->months = (BN_ULONG)-1;
timeToCrack->months = ULONG_MAX;
BIGNUM *yearsToCrack = BN_dup( daysToCrack );
BN_div_word( yearsToCrack, 356 );
if (BN_cmp( yearsToCrack, max ) < 0)
timeToCrack->years = BN_get_word( yearsToCrack );
NSDecimalNumber *yearsToCrack = [daysToCrack decimalNumberByDividingBy:
(id)[[NSDecimalNumber alloc] initWithUnsignedLong:356L]];
if ([yearsToCrack compare:ulong_max] == NSOrderedAscending)
timeToCrack->years = (unsigned long long)[yearsToCrack doubleValue];
else
timeToCrack->years = (BN_ULONG)-1;
timeToCrack->years = ULONG_MAX;
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 );
NSDecimalNumber *universesToCrack = [yearsToCrack decimalNumberByDividingBy:
(id)[[NSDecimalNumber alloc] initWithUnsignedLong:14000L]];
universesToCrack = [universesToCrack decimalNumberByDividingBy:
(id)[[NSDecimalNumber alloc] initWithUnsignedLong:1000000L]];
if ([universesToCrack compare:ulong_max] == NSOrderedAscending)
timeToCrack->universes = (unsigned long long)[universesToCrack doubleValue];
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 );
timeToCrack->universes = ULONG_MAX;
return YES;
}

View File

@@ -75,7 +75,7 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve
// Consumable product.
return NO;
#if ADHOC || DEBUG
#if DEBUG
// All features are unlocked for beta / debug / mac versions.
return YES;
#else

View File

@@ -72,14 +72,23 @@ static NSDictionary *createKeyQuery(MPUserEntity *user, BOOL newItem, MPKeyOrigi
MPKeyOrigin keyOrigin;
NSDictionary *keyQuery = createKeyQuery( user, NO, &keyOrigin );
NSData *keyData = [PearlKeyChain dataOfItemForQuery:keyQuery];
if (!keyData) {
id<MPAlgorithm> keyAlgorithm = user.algorithm;
MPKey *key = [[MPKey alloc] initForFullName:user.name withKeyResolver:^NSData *(id<MPAlgorithm> algorithm) {
return ![algorithm isEqual:keyAlgorithm]? nil:
PearlMainQueueAwait( (id)^{
return [PearlKeyChain dataOfItemForQuery:keyQuery];
} );
} keyOrigin:keyOrigin];
if ([key keyIDForAlgorithm:user.algorithm])
inf( @"Found key in keychain for user: %@", user.userID );
else {
inf( @"No key found in keychain for user: %@", user.userID );
return nil;
key = nil;
}
inf( @"Found key in keychain for user: %@", user.userID );
return [[MPKey alloc] initForFullName:user.name withKeyData:keyData forAlgorithm:user.algorithm keyOrigin:keyOrigin];
return key;
}
- (void)storeSavedKeyFor:(MPUserEntity *)user {
@@ -230,28 +239,22 @@ static NSDictionary *createKeyQuery(MPUserEntity *user, BOOL newItem, MPKeyOrigi
NSString *content;
while (!(content = [site.algorithm storedPasswordForSite:(MPStoredSiteEntity *)site usingKey:recoverKey])) {
// Failed to decrypt site with the current recoveryKey. Ask user for a new one to use.
__block NSString *masterPassword = nil;
NSString *masterPassword = nil;
#ifdef PEARL_UIKIT
dispatch_group_t recoverPasswordGroup = dispatch_group_create();
dispatch_group_enter( recoverPasswordGroup );
[PearlAlert showAlertWithTitle:@"Enter Old Master Password"
message:PearlString( @"Your old master password is required to migrate the stored password for %@",
site.name )
viewStyle:UIAlertViewStyleSecureTextInput
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
@try {
masterPassword = PearlAwait( ^(void (^setResult)(id)) {
[PearlAlert showAlertWithTitle:@"Enter Old Master Password"
message:PearlString(
@"Your old master password is required to migrate the stored password for %@",
site.name )
viewStyle:UIAlertViewStyleSecureTextInput
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
if (buttonIndex_ == [alert_ cancelButtonIndex])
// Don't Migrate
return;
masterPassword = [alert_ textFieldAtIndex:0].text;
}
@finally {
dispatch_group_leave( recoverPasswordGroup );
}
} cancelTitle:@"Don't Migrate" otherTitles:@"Migrate", nil];
dispatch_group_wait( recoverPasswordGroup, DISPATCH_TIME_FOREVER );
setResult( nil );
else
setResult( [alert_ textFieldAtIndex:0].text );
} cancelTitle:@"Don't Migrate" otherTitles:@"Migrate", nil];
} );
#endif
if (!masterPassword)
// Don't Migrate

View File

@@ -537,12 +537,13 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
// Parse import data.
inf( @"Importing sites." );
__block MPUserEntity *user = nil;
id<MPAlgorithm> importAlgorithm = nil;
NSUInteger importFormat = 0;
__block MPUserEntity *user = nil;
NSUInteger importAvatar = NSNotFound;
NSString *importBundleVersion = nil, *importUserName = nil;
NSData *importKeyID = nil;
NSString *importBundleVersion = nil, *importUserName = nil;
id<MPAlgorithm> importAlgorithm = nil;
MPSiteType importDefaultType = (MPSiteType)0;
BOOL headerStarted = NO, headerEnded = NO, clearText = NO;
NSArray *importedSiteLines = [importedSitesString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
NSMutableSet *sitesToDelete = [NSMutableSet set];
@@ -573,7 +574,15 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
range:NSMakeRange( 0, [importedSiteLine length] )] lastObject];
NSString *headerName = [importedSiteLine substringWithRange:[headerSites rangeAtIndex:1]];
NSString *headerValue = [importedSiteLine substringWithRange:[headerSites rangeAtIndex:2]];
if ([headerName isEqualToString:@"User Name"]) {
if ([headerName isEqualToString:@"Format"]) {
importFormat = (NSUInteger)[headerValue integerValue];
if (importFormat >= [sitePatterns count]) {
err( @"Unsupported import format: %lu", (unsigned long)importFormat );
return MPImportResultInternalError;
}
}
if (([headerName isEqualToString:@"User Name"] || [headerName isEqualToString:@"Full Name"]) && !importUserName) {
importUserName = headerValue;
NSFetchRequest *userFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )];
@@ -591,21 +600,18 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
user = [users lastObject];
dbg( @"Existing user? %@", [user debugDescription] );
}
if ([headerName isEqualToString:@"Avatar"])
importAvatar = (NSUInteger)[headerValue integerValue];
if ([headerName isEqualToString:@"Key ID"])
importKeyID = [headerValue decodeHex];
if ([headerName isEqualToString:@"Version"]) {
importBundleVersion = headerValue;
importAlgorithm = MPAlgorithmDefaultForBundleVersion( importBundleVersion );
}
if ([headerName isEqualToString:@"Format"]) {
importFormat = (NSUInteger)[headerValue integerValue];
if (importFormat >= [sitePatterns count]) {
err( @"Unsupported import format: %lu", (unsigned long)importFormat );
return MPImportResultInternalError;
}
}
if ([headerName isEqualToString:@"Avatar"])
importAvatar = (NSUInteger)[headerValue integerValue];
if ([headerName isEqualToString:@"Algorithm"])
importAlgorithm = MPAlgorithmForVersion( (MPAlgorithmVersion)[headerValue integerValue] );
if ([headerName isEqualToString:@"Default Type"])
importDefaultType = (MPSiteType)[headerValue integerValue];
if ([headerName isEqualToString:@"Passwords"]) {
if ([headerValue isEqualToString:@"VISIBLE"])
clearText = YES;
@@ -709,6 +715,8 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
if (user) {
if (importAvatar != NSNotFound)
user.avatar = importAvatar;
if (importDefaultType)
user.defaultType = importDefaultType;
dbg( @"Updating User: %@", [user debugDescription] );
}
else {
@@ -716,6 +724,7 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
user.name = importUserName;
user.algorithm = MPAlgorithmDefault;
user.keyID = [userKey keyIDForAlgorithm:user.algorithm];
user.defaultType = importDefaultType?: user.algorithm.defaultType;
if (importAvatar != NSNotFound)
user.avatar = importAvatar;
dbg( @"Created User: %@", [user debugDescription] );
@@ -785,16 +794,16 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
[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:@"# Format: 1\n"];
[export appendFormat:@"# Date: %@\n", [[NSDateFormatter rfc3339DateFormatter] stringFromDate:[NSDate date]]];
[export appendFormat:@"# User Name: %@\n", activeUser.name];
[export appendFormat:@"# Full 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:@"# Algorithm: %d\n", activeUser.algorithm.version];
[export appendFormat:@"# Default Type: %d\n", activeUser.defaultType];
[export appendFormat:@"# Passwords: %@\n", revealPasswords? @"VISIBLE": @"PROTECTED"];
[export appendFormat:@"##\n"];
[export appendFormat:@"#\n"];
[export appendFormat:@"# Last Times Password Login\t Site\tSite\n"];

View File

@@ -237,8 +237,8 @@
// Invalid self.user.defaultType
result = MPApplyFix( result, ^MPFixableResult {
wrn( @"Invalid type for: %@ of %@, type: %ld. Will use %ld instead.",
self.name, self.user.name, (long)self.type, (long)MPSiteTypeGeneratedLong );
self.type = MPSiteTypeGeneratedLong;
self.name, self.user.name, (long)self.type, (long)[self.algorithm defaultType] );
self.type = [self.algorithm defaultType];
return MPFixableResultProblemsFixed;
} );
if (![self isKindOfClass:[self.algorithm classOfType:self.type]])
@@ -330,7 +330,7 @@
- (MPSiteType)defaultType {
return (MPSiteType)[self.defaultType_ unsignedIntegerValue]?: MPSiteTypeGeneratedLong;
return (MPSiteType)[self.defaultType_ unsignedIntegerValue]?: self.algorithm.defaultType;
}
- (void)setDefaultType:(MPSiteType)aDefaultType {

View File

@@ -28,12 +28,12 @@ typedef NS_ENUM( NSUInteger, MPKeyOrigin ) {
@interface MPKey : NSObject
@property(nonatomic, readonly) NSString *fullName;
@property(nonatomic, readonly) MPKeyOrigin origin;
@property(nonatomic, readonly, copy) NSString *fullName;
- (instancetype)initForFullName:(NSString *)fullName withMasterPassword:(NSString *)masterPassword;
- (instancetype)initForFullName:(NSString *)fullName withKeyData:(NSData *)keyData
forAlgorithm:(id<MPAlgorithm>)algorithm keyOrigin:(MPKeyOrigin)origin;
- (instancetype)initForFullName:(NSString *)fullName withKeyResolver:(NSData *( ^ )(id<MPAlgorithm>))keyResolver
keyOrigin:(MPKeyOrigin)origin;
- (NSData *)keyIDForAlgorithm:(id<MPAlgorithm>)algorithm;
- (NSData *)keyDataForAlgorithm:(id<MPAlgorithm>)algorithm;

View File

@@ -19,9 +19,9 @@
@interface MPKey()
@property(nonatomic) NSString *fullName;
@property(nonatomic) MPKeyOrigin origin;
@property(nonatomic) NSString *masterPassword;
@property(nonatomic, copy) NSString *fullName;
@property(nonatomic, copy) NSData *( ^keyResolver )(id<MPAlgorithm>);
@end
@@ -31,25 +31,22 @@
- (instancetype)initForFullName:(NSString *)fullName withMasterPassword:(NSString *)masterPassword {
return [self initForFullName:fullName withKeyResolver:^NSData *(id<MPAlgorithm> algorithm) {
return [algorithm keyDataForFullName:self.fullName withMasterPassword:masterPassword];
} keyOrigin:MPKeyOriginMasterPassword];
}
- (instancetype)initForFullName:(NSString *)fullName withKeyResolver:(NSData *( ^ )(id<MPAlgorithm>))keyResolver
keyOrigin:(MPKeyOrigin)origin {
if (!(self = [super init]))
return nil;
_keyCache = [NSCache new];
self.fullName = fullName;
self.origin = MPKeyOriginMasterPassword;
self.masterPassword = masterPassword;
return self;
}
- (instancetype)initForFullName:(NSString *)fullName withKeyData:(NSData *)keyData
forAlgorithm:(id<MPAlgorithm>)algorithm keyOrigin:(MPKeyOrigin)origin {
if (!(self = [self initForFullName:fullName withMasterPassword:nil]))
return nil;
self.origin = origin;
[_keyCache setObject:keyData forKey:algorithm];
self.fullName = fullName;
self.keyResolver = keyResolver;
return self;
}
@@ -61,15 +58,17 @@
- (NSData *)keyDataForAlgorithm:(id<MPAlgorithm>)algorithm {
NSData *keyData = [_keyCache objectForKey:algorithm];
if (keyData)
@synchronized (self) {
NSData *keyData = [_keyCache objectForKey:algorithm];
if (keyData)
return keyData;
keyData = self.keyResolver( algorithm );
if (keyData)
[_keyCache setObject:keyData forKey:algorithm];
return keyData;
keyData = [algorithm keyDataForFullName:self.fullName withMasterPassword:self.masterPassword];
if (keyData)
[_keyCache setObject:keyData forKey:algorithm];
return keyData;
}
}
- (NSData *)keyDataForAlgorithm:(id<MPAlgorithm>)algorithm trimmedLength:(NSUInteger)subKeyLength {
@@ -80,7 +79,7 @@
- (BOOL)isEqualToKey:(MPKey *)key {
return [self.fullName isEqualToString:key.fullName] && [self.masterPassword isEqualToString:self.masterPassword];
return [[self keyIDForAlgorithm:MPAlgorithmDefault] isEqualToData:[key keyIDForAlgorithm:MPAlgorithmDefault]];
}
- (BOOL)isEqual:(id)object {

View File

@@ -28,10 +28,10 @@
[super windowDidLoad];
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:self.window
queue:nil usingBlock:^(NSNotification *note) {
[MPMacAppDelegate get].initialWindowController = nil;
}];
PearlAddNotificationObserver( NSWindowWillCloseNotification, self.window, nil, ^(id host, NSNotification *note) {
PearlRemoveNotificationObserversFrom( host );
[MPMacAppDelegate get].initialWindowController = nil;
} );
}
#pragma mark - Actions

View File

@@ -72,7 +72,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
NSString *crashlyticsAPIKey = [self crashlyticsAPIKey];
if ([crashlyticsAPIKey length]) {
inf(@"Initializing Crashlytics");
#if defined (DEBUG) || defined (ADHOC)
#if DEBUG
[Crashlytics sharedInstance].debugMode = YES;
#endif
[[Crashlytics sharedInstance] setUserIdentifier:[PearlKeyChain deviceIdentifier]];
@@ -269,80 +269,80 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
NSURL *url = openPanel.URL;
[openPanel close];
[[NSURLSession sharedSession]
dataTaskWithURL:url completionHandler:^(NSData *importedSitesData, NSURLResponse *response, NSError *error) {
if (error)
err( @"While reading imported sites from %@: %@", url, [error fullDescription] );
if (!importedSitesData)
return;
[[[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:
^(NSData *importedSitesData, NSURLResponse *response, NSError *error) {
if (error)
err( @"While reading imported sites from %@: %@", url, [error fullDescription] );
if (!importedSitesData)
return;
NSString *importedSitesString = [[NSString alloc] initWithData:importedSitesData encoding:NSUTF8StringEncoding];
MPImportResult result = [self importSites:importedSitesString askImportPassword:^NSString *(NSString *userName) {
__block NSString *masterPassword = nil;
NSString *importedSitesString = [[NSString alloc] initWithData:importedSitesData encoding:NSUTF8StringEncoding];
MPImportResult result = [self importSites:importedSitesString askImportPassword:^NSString *(NSString *userName) {
__block NSString *masterPassword = nil;
PearlMainQueueWait( ^{
NSAlert *alert = [NSAlert new];
[alert addButtonWithTitle:@"Unlock"];
[alert addButtonWithTitle:@"Cancel"];
alert.messageText = @"Import File's Master Password";
alert.informativeText = strf( @"%@'s export was done using a different master password.\n"
@"Enter that master password to unlock the exported data.", userName );
alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
[alert layout];
if ([alert runModal] == NSAlertFirstButtonReturn)
masterPassword = ((NSTextField *)alert.accessoryView).stringValue;
} );
PearlMainQueueWait( ^{
NSAlert *alert = [NSAlert new];
[alert addButtonWithTitle:@"Unlock"];
[alert addButtonWithTitle:@"Cancel"];
alert.messageText = @"Import File's Master Password";
alert.informativeText = strf( @"%@'s export was done using a different master password.\n"
@"Enter that master password to unlock the exported data.", userName );
alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
[alert layout];
if ([alert runModal] == NSAlertFirstButtonReturn)
masterPassword = ((NSTextField *)alert.accessoryView).stringValue;
} );
return masterPassword;
} askUserPassword:^NSString *(NSString *userName, NSUInteger importCount, NSUInteger deleteCount) {
__block NSString *masterPassword = nil;
return masterPassword;
} askUserPassword:^NSString *(NSString *userName, NSUInteger importCount, NSUInteger deleteCount) {
__block NSString *masterPassword = nil;
PearlMainQueueWait( ^{
NSAlert *alert = [NSAlert new];
[alert addButtonWithTitle:@"Import"];
[alert addButtonWithTitle:@"Cancel"];
alert.messageText = strf( @"Master Password for\n%@", userName );
alert.informativeText = strf( @"Imports %lu sites, overwriting %lu.",
(unsigned long)importCount, (unsigned long)deleteCount );
alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
[alert layout];
if ([alert runModal] == NSAlertFirstButtonReturn)
masterPassword = ((NSTextField *)alert.accessoryView).stringValue;
} );
PearlMainQueueWait( ^{
NSAlert *alert = [NSAlert new];
[alert addButtonWithTitle:@"Import"];
[alert addButtonWithTitle:@"Cancel"];
alert.messageText = strf( @"Master Password for\n%@", userName );
alert.informativeText = strf( @"Imports %lu sites, overwriting %lu.",
(unsigned long)importCount, (unsigned long)deleteCount );
alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
[alert layout];
if ([alert runModal] == NSAlertFirstButtonReturn)
masterPassword = ((NSTextField *)alert.accessoryView).stringValue;
} );
return masterPassword;
}];
return masterPassword;
}];
PearlMainQueue( ^{
switch (result) {
case MPImportResultSuccess: {
[self updateUsers];
PearlMainQueue( ^{
switch (result) {
case MPImportResultSuccess: {
[self updateUsers];
NSAlert *alert = [NSAlert new];
alert.messageText = @"Successfully imported sites.";
[alert runModal];
break;
}
case MPImportResultCancelled:
break;
case MPImportResultInternalError:
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
NSLocalizedDescriptionKey: @"Import failed because of an internal error."
}]] runModal];
break;
case MPImportResultMalformedInput:
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
NSLocalizedDescriptionKey: @"The import doesn't look like a Master Password export."
}]] runModal];
break;
case MPImportResultInvalidPassword:
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
NSLocalizedDescriptionKey: @"Incorrect master password for the import sites."
}]] runModal];
break;
}
} );
}];
NSAlert *alert = [NSAlert new];
alert.messageText = @"Successfully imported sites.";
[alert runModal];
break;
}
case MPImportResultCancelled:
break;
case MPImportResultInternalError:
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
NSLocalizedDescriptionKey: @"Import failed because of an internal error."
}]] runModal];
break;
case MPImportResultMalformedInput:
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
NSLocalizedDescriptionKey: @"The import doesn't look like a Master Password export."
}]] runModal];
break;
case MPImportResultInvalidPassword:
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
NSLocalizedDescriptionKey: @"Incorrect master password for the import sites."
}]] runModal];
break;
}
} );
}] resume];
}
- (IBAction)togglePreference:(id)sender {

View File

@@ -41,41 +41,38 @@
[self replaceFonts:self.window.contentView];
prof_rewind( @"replaceFonts" );
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidBecomeKeyNotification object:self.window
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
PearlAddNotificationObserver( NSWindowDidBecomeKeyNotification, self.window, [NSOperationQueue mainQueue],
^(id host, NSNotification *note) {
prof_new( @"didBecomeKey" );
[self.window makeKeyAndOrderFront:nil];
prof_rewind( @"fadeIn" );
[self updateUser];
prof_finish( @"updateUser" );
}];
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:self.window
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
} );
PearlAddNotificationObserver( NSWindowWillCloseNotification, self.window, [NSOperationQueue mainQueue],
^(id host, NSNotification *note) {
PearlRemoveNotificationObservers();
NSWindow *sheet = [self.window attachedSheet];
if (sheet)
[self.window endSheet:sheet];
}];
[[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillResignActiveNotification object:nil
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
} );
PearlAddNotificationObserver( NSApplicationWillResignActiveNotification, nil, [NSOperationQueue mainQueue],
^(id host, NSNotification *note) {
[self.window close];
}];
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedInNotification object:nil
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
[self updateUser];
}];
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedOutNotification object:nil
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
[self updateUser];
}];
[self observeKeyPath:@"sitesController.selection"
withBlock:^(id from, id to, NSKeyValueChange cause, id _self) {
prof_new( @"sitesController.selection" );
[_self updateSelection];
prof_finish( @"updateSelection" );
}];
} );
PearlAddNotificationObserver( MPSignedInNotification, nil, [NSOperationQueue mainQueue], ^(id host, NSNotification *note) {
[self updateUser];
} );
PearlAddNotificationObserver( MPSignedOutNotification, nil, [NSOperationQueue mainQueue], ^(id host, NSNotification *note) {
[self updateUser];
} );
[self observeKeyPath:@"sitesController.selection" withBlock:^(id from, id to, NSKeyValueChange cause, id _self) {
[_self updateSelection];
}];
prof_rewind( @"observers" );
NSSearchFieldCell *siteFieldCell = (NSSearchFieldCell *)self.siteField.cell;
NSSearchFieldCell *siteFieldCell = self.siteField.cell;
siteFieldCell.searchButtonCell = nil;
siteFieldCell.cancelButtonCell = nil;
@@ -479,7 +476,7 @@
// Performing action while content is available. Copy it.
[self copyContent:self.shiftPressed? selectedSite.answer: selectedSite.content];
[self.window close];
[NSApp hide:nil];
NSUserNotification *notification = [NSUserNotification new];
notification.title = @"Password Copied";
@@ -535,30 +532,33 @@
fuzzyRE = [NSRegularExpression regularExpressionWithPattern:@"(.)" options:0 error:nil];
} );
prof_new( @"updateSites" );
NSString *queryString = self.siteField.stringValue;
NSString *queryPattern;
if ([queryString length] < 13)
queryPattern = [queryString stringByReplacingMatchesOfExpression:fuzzyRE withTemplate:@"*$1*"];
else
// If query is too long, a wildcard per character makes the CoreData fetch take excessively long.
queryPattern = strf( @"*%@*", queryString );
NSString *queryPattern = [[queryString stringByReplacingMatchesOfExpression:fuzzyRE withTemplate:@"*$1"] stringByAppendingString:@"*"];
prof_rewind( @"queryPattern" );
NSMutableArray *fuzzyGroups = [NSMutableArray new];
[fuzzyRE enumerateMatchesInString:queryString options:0 range:NSMakeRange( 0, queryString.length )
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
[fuzzyGroups addObject:[queryString substringWithRange:result.range]];
}];
prof_rewind( @"fuzzyRE" );
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
prof_rewind( @"moc" );
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPSiteEntity class] )];
fetchRequest.sortDescriptors = @[ [[NSSortDescriptor alloc] initWithKey:@"lastUsed" ascending:NO] ];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(%@ == '' OR name LIKE[cd] %@) AND user == %@",
queryPattern, queryPattern, [MPMacAppDelegate get].activeUserOID];
prof_rewind( @"fetchRequest" );
NSError *error = nil;
NSArray *siteResults = [context executeFetchRequest:fetchRequest error:&error];
if (!siteResults) {
prof_finish( @"executeFetchRequest: %@ // %@", fetchRequest.predicate, [error fullDescription] );
err( @"While fetching sites for completion: %@", [error fullDescription] );
return;
}
prof_rewind( @"executeFetchRequest: %@", fetchRequest.predicate );
BOOL exact = NO;
NSMutableArray *newSites = [NSMutableArray arrayWithCapacity:[siteResults count]];
@@ -566,10 +566,12 @@
[newSites addObject:[[MPSiteModel alloc] initWithEntity:site fuzzyGroups:fuzzyGroups]];
exact |= [site.name isEqualToString:queryString];
}
prof_rewind( @"newSites: %u, exact: %d", (uint)[siteResults count], exact );
if (!exact && [queryString length]) {
MPUserEntity *activeUser = [[MPAppDelegate_Shared get] activeUserInContext:context];
[newSites addObject:[[MPSiteModel alloc] initWithName:queryString forUser:activeUser]];
}
prof_finish( @"newSites: %@", newSites );
dbg( @"newSites: %@", newSites );
if (![newSites isEqualToArray:self.sites])

View File

@@ -80,7 +80,6 @@
self.uses = entity.uses_;
self.counter = [entity isKindOfClass:[MPGeneratedSiteEntity class]]? [(MPGeneratedSiteEntity *)entity counter]: 0;
self.loginGenerated = entity.loginGenerated;
NSLog( @"%@: loginGenerated: %d", self.name, self.loginGenerated );
// Find all password types and the index of the current type amongst them.
[self updateContent:entity];
@@ -276,7 +275,6 @@
PearlMainQueue( ^{
self.loginName = loginName;
NSLog( @"%@: loginGenerated: %d, loginName: %@", self.name, self.loginGenerated, loginName );
} );
}

View File

@@ -5,24 +5,21 @@
#ifdef __OBJC__
#import <Foundation/Foundation.h>
#define PEARL_WITH_SCRYPT
#define PEARL_WITH_MESSAGEUI
#define PEARL
#define PEARL_CRYPTO
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
#if TARGET_OS_IOS
#define PEARL_UIKIT
#endif
#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
#elif TARGET_OS_OSX
#define PEARL_COCOA
#endif
#import "Pearl.h"
#import "Pearl-Crypto.h"
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
#if TARGET_OS_IOS
#import "Pearl-UIKit.h"
#endif
#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
#elif TARGET_OS_OSX
#import "Pearl-Cocoa.h"
#endif
#endif

View File

@@ -49,11 +49,10 @@ const long MPAvatarAdd = 10000;
[super awakeFromNib];
self.alpha = 0;
self.visible = NO;
self.nameContainer.layer.cornerRadius = 5;
self.avatarImageView.hidden = NO;
self.avatarImageView.layer.cornerRadius = self.avatarImageView.bounds.size.height / 2;
self.avatarImageView.layer.masksToBounds = NO;
self.avatarImageView.backgroundColor = [UIColor clearColor];
@@ -211,7 +210,7 @@ const long MPAvatarAdd = 10000;
[UIView animateWithDuration:animated? 0.5f: 0 delay:0
options:UIViewAnimationOptionOverrideInheritedDuration | UIViewAnimationOptionBeginFromCurrentState
animations:^{
self.alpha = 1;
self.visible = YES;
if (self.newUser) {
if (self.mode == MPAvatarModeLowered)
@@ -220,6 +219,10 @@ const long MPAvatarAdd = 10000;
self.avatar = arc4random() % MPAvatarCount;
}
self.nameContainer.alpha = self.visibility;
self.avatarImageView.alpha = self.visibility * 0.7f + 0.3f;
self.avatarImageView.layer.shadowRadius = 15 * self.visibility * self.visibility;
switch (self.mode) {
case MPAvatarModeLowered: {
[self.avatarSizeConstraint updateConstant:
@@ -227,10 +230,9 @@ const long MPAvatarAdd = 10000;
[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultLow];
[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow];
[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultLow];
self.nameContainer.alpha = self.visibility;
self.nameContainer.visible = YES;
self.nameContainer.backgroundColor = [UIColor clearColor];
self.avatarImageView.alpha = self.visibility * 0.7f + 0.3f;
self.avatarImageView.layer.shadowRadius = 15 * self.visibility * self.visibility;
self.avatarImageView.visible = YES;
break;
}
case MPAvatarModeRaisedButInactive: {
@@ -239,10 +241,9 @@ const long MPAvatarAdd = 10000;
[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultHigh];
[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow];
[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultLow];
self.nameContainer.alpha = self.visibility;
self.nameContainer.visible = YES;
self.nameContainer.backgroundColor = [UIColor clearColor];
self.avatarImageView.alpha = 0;
self.avatarImageView.layer.shadowRadius = 15 * self.visibility * self.visibility;
self.avatarImageView.visible = NO;
break;
}
case MPAvatarModeRaisedAndActive: {
@@ -251,10 +252,9 @@ const long MPAvatarAdd = 10000;
[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultHigh];
[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow];
[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultHigh];
self.nameContainer.alpha = self.visibility;
self.nameContainer.visible = YES;
self.nameContainer.backgroundColor = [UIColor blackColor];
self.avatarImageView.alpha = 1;
self.avatarImageView.layer.shadowRadius = 15 * self.visibility * self.visibility;
self.avatarImageView.visible = YES;
break;
}
case MPAvatarModeRaisedAndHidden: {
@@ -263,10 +263,9 @@ const long MPAvatarAdd = 10000;
[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultHigh];
[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultLow];
[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultHigh];
self.nameContainer.alpha = 0;
self.nameContainer.visible = NO;
self.nameContainer.backgroundColor = [UIColor blackColor];
self.avatarImageView.alpha = 0;
self.avatarImageView.layer.shadowRadius = 15 * self.visibility * self.visibility;
self.avatarImageView.visible = NO;
break;
}
case MPAvatarModeRaisedAndMinimized: {
@@ -274,9 +273,9 @@ const long MPAvatarAdd = 10000;
[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultLow];
[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultHigh + 2];
[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultHigh];
self.nameContainer.alpha = 0;
self.nameContainer.visible = NO;
self.nameContainer.backgroundColor = [UIColor blackColor];
self.avatarImageView.alpha = 1;
self.avatarImageView.visible = YES;
break;
}
}
@@ -293,7 +292,7 @@ const long MPAvatarAdd = 10000;
else
self.avatarImageView.backgroundColor = [UIColor clearColor];
self.avatarImageView.layer.cornerRadius = self.avatarImageView.bounds.size.height / 2;
self.spinner.alpha = self.spinnerActive? 1: 0;
self.spinner.visible = self.spinnerActive;
[self.contentView layoutIfNeeded];
} completion:nil];

View File

@@ -28,17 +28,16 @@
[super viewDidLoad];
_views = [NSArray arrayWithObjects:
self.view0, self.view1, self.view2, self.view3, self.view4, self.view5, self.view6, self.view7, self.view8, self.view9, nil];
_views = @[ self.view0, self.view1, self.view2, self.view3, self.view4, self.view5, self.view6, self.view7, self.view8, self.view9 ];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.viewProgress.hidden = NO;
self.viewProgress.visible = YES;
self.viewProgress.progress = 0;
[_views makeObjectsPerformSelector:@selector( setAlpha: ) withObject:@0];
[_views makeObjectsPerformSelector:@selector( setVisible: ) withObject:@NO];
_nextView = 0;
}
@@ -47,7 +46,7 @@
[super viewDidAppear:animated];
[UIView animateWithDuration:0.3f animations:^{
[_views[_nextView++] setAlpha:1];
[_views[_nextView++] setVisible:YES];
}];
_viewTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 block:^(NSTimer *timer) {
@@ -56,11 +55,11 @@
if (self.viewProgress.progress == 1)
[UIView animateWithDuration:0.3f animations:^{
self.viewProgress.progress = 0;
[_views[_nextView++] setAlpha:1];
[_views[_nextView++] setVisible:YES];
if (_nextView >= [_views count]) {
[_viewTimer invalidate];
self.viewProgress.hidden = YES;
self.viewProgress.visible = NO;
}
}];
} repeats:YES];

View File

@@ -28,7 +28,7 @@
@property(weak, nonatomic) IBOutlet UISegmentedControl *typeControl;
@property(weak, nonatomic) IBOutlet UILabel *counterLabel;
@property(weak, nonatomic) IBOutlet UIActivityIndicatorView *activity;
@property(weak, nonatomic) IBOutlet UILabel *passwordLabel;
@property(weak, nonatomic) IBOutlet UIButton *passwordButton;
@property(weak, nonatomic) IBOutlet UIView *tipContainer;
- (IBAction)controlChanged:(UIControl *)control;

View File

@@ -81,21 +81,20 @@
[self updatePassword];
}
- (IBAction)copyPassword:(UITapGestureRecognizer *)recognizer {
- (IBAction)copyPassword:(id)sender {
if (recognizer.state == UIGestureRecognizerStateEnded) {
NSString *sitePassword = self.passwordLabel.text;
if ([sitePassword length]) {
[UIPasteboard generalPasteboard].string = sitePassword;
[UIView animateWithDuration:0.3f animations:^{
self.tipContainer.alpha = 1;
} completion:^(BOOL finished) {
if (finished)
PearlMainQueueAfter( 3, ^{
self.tipContainer.alpha = 0;
} );
}];
}
NSString *sitePassword = [self.passwordButton titleForState:UIControlStateNormal];
if ([sitePassword length]) {
[UIPasteboard generalPasteboard].string = sitePassword;
[UIView animateWithDuration:0.3f animations:^{
self.tipContainer.visible = YES;
} completion:^(BOOL finished) {
PearlMainQueueAfter( 3, ^{
[UIView animateWithDuration:0.3f animations:^{
self.tipContainer.visible = NO;
}];
} );
}];
}
}
@@ -106,7 +105,7 @@
NSString *fullName = self.fullNameField.text;
NSString *masterPassword = self.masterPasswordField.text;
self.passwordLabel.text = nil;
[self.passwordButton setTitle:nil forState:UIControlStateNormal];
[self.activity startAnimating];
[_emergencyKeyQueue cancelAllOperations];
[_emergencyKeyQueue addOperationWithBlock:^{
@@ -128,7 +127,7 @@
NSUInteger siteCounter = (NSUInteger)self.counterStepper.value;
self.counterLabel.text = strf( @"%lu", (unsigned long)siteCounter );
self.passwordLabel.text = nil;
[self.passwordButton setTitle:nil forState:UIControlStateNormal];
[self.activity startAnimating];
[_emergencyPasswordQueue cancelAllOperations];
[_emergencyPasswordQueue addOperationWithBlock:^{
@@ -138,7 +137,7 @@
PearlMainQueue( ^{
[self.activity stopAnimating];
self.passwordLabel.text = sitePassword;
[self.passwordButton setTitle:sitePassword forState:UIControlStateNormal];
} );
}];
}

View File

@@ -57,7 +57,7 @@
UIButton *dismissButton = [UIButton buttonWithType:UIButtonTypeCustom];
[dismissButton addTarget:self action:@selector( dismissOverlay: ) forControlEvents:UIControlEventTouchUpInside];
dismissButton.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5f];
dismissButton.alpha = 0;
dismissButton.visible = NO;
dismissButton.frame = self.view.bounds;
dismissButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_dismissSegueByButton[[NSValue valueWithNonretainedObject:dismissButton]] =
@@ -89,7 +89,7 @@
[_dismissSegueByButton removeObjectForKey:dismissSegueKey];
[UIView animateWithDuration:0.1f animations:^{
dismissButton.alpha = 0;
dismissButton.visible = NO;
} completion:^(BOOL finished) {
[dismissButton removeFromSuperview];
}];
@@ -127,14 +127,14 @@
CGRectSetY( destinationViewController.view.frame, 100 );
destinationViewController.view.transform = CGAffineTransformMakeScale( 1.2f, 1.2f );
destinationViewController.view.alpha = 0;
destinationViewController.view.visible = NO;
[UIView transitionWithView:containerViewController.view duration:0.3f
options:UIViewAnimationOptionAllowAnimatedContent animations:^{
destinationViewController.view.transform = CGAffineTransformIdentity;
CGRectSetY( destinationViewController.view.frame, 0 );
destinationViewController.view.alpha = 1;
dismissButton.alpha = 1;
destinationViewController.view.visible = YES;
dismissButton.visible = YES;
} completion:^(BOOL finished) {
[destinationViewController didMoveToParentViewController:containerViewController];
[containerViewController setNeedsStatusBarAppearanceUpdate];
@@ -147,7 +147,7 @@
options:UIViewAnimationOptionAllowAnimatedContent animations:^{
CGRectSetY( sourceViewController.view.frame, 100 );
sourceViewController.view.transform = CGAffineTransformMakeScale( 0.8f, 0.8f );
sourceViewController.view.alpha = 0;
sourceViewController.view.visible = NO;
[containerViewController removeDismissButtonForViewController:sourceViewController];
} completion:^(BOOL finished) {
if (finished) {

View File

@@ -28,6 +28,7 @@
@property(nonatomic, strong) IBOutlet UITextField *passwordField;
@property(nonatomic, strong) IBOutlet UIView *loginNameContainer;
@property(nonatomic, strong) IBOutlet UITextField *loginNameField;
@property(nonatomic, strong) IBOutlet UILabel *loginNameGenerated;
@property(nonatomic, strong) IBOutlet UILabel *strengthLabel;
@property(nonatomic, strong) IBOutlet UILabel *counterLabel;
@property(nonatomic, strong) IBOutlet UIButton *counterButton;
@@ -199,7 +200,7 @@
atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:YES];
if (textField == self.loginNameField)
self.loginNameButton.titleLabel.alpha = [self.loginNameField.text length] || self.loginNameField.enabled? 0: 1;
self.loginNameButton.hidden = [self.loginNameField.attributedText length] || self.loginNameField.enabled;
}
- (IBAction)textFieldDidChange:(UITextField *)textField {
@@ -224,7 +225,7 @@
if (textField == self.passwordField || textField == self.loginNameField) {
textField.enabled = NO;
NSString *text = textField.text;
NSString *text = [textField.attributedText string]?: textField.text;
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
MPSiteEntity *site = [self siteInContext:context];
@@ -235,10 +236,8 @@
if ([site.algorithm savePassword:text toSite:site usingKey:[MPiOSAppDelegate get].key])
[PearlOverlay showTemporaryOverlayWithTitle:@"Password Updated" dismissAfter:2];
}
else if (textField == self.loginNameField &&
((site.loginGenerated && ![text length]) ||
(!site.loginGenerated && ![text isEqualToString:site.loginName]))) {
if (site.loginGenerated || !([site.loginName isEqualToString:text] || (!text && !site.loginName))) {
else if (textField == self.loginNameField) {
if (![text isEqualToString:[site.algorithm resolveLoginForSite:site usingKey:[MPiOSAppDelegate get].key]]) {
site.loginGenerated = NO;
site.loginName = text;
@@ -282,12 +281,12 @@
[self setMode:MPPasswordCellModePassword animated:YES];
MPSiteEntity *mainSite = [self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
[PearlSheet showSheetWithTitle:@"Change Password Type" viewStyle:UIActionSheetStyleAutomatic
initSheet:^(UIActionSheet *sheet) {
MPSiteEntity *mainSite = [self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]];
for (NSNumber *typeNumber in [MPAlgorithmDefault allTypes]) {
for (NSNumber *typeNumber in [mainSite.algorithm allTypes]) {
MPSiteType type = (MPSiteType)[typeNumber unsignedIntegerValue];
NSString *typeName = [MPAlgorithmDefault nameOfType:type];
NSString *typeName = [mainSite.algorithm nameOfType:type];
if (type == mainSite.type)
[sheet addButtonWithTitle:strf( @"● %@", typeName )];
else
@@ -297,7 +296,8 @@
if (buttonIndex == [sheet cancelButtonIndex])
return;
MPSiteType type = (MPSiteType)[[MPAlgorithmDefault allTypes][buttonIndex] unsignedIntegerValue]?: MPSiteTypeGeneratedLong;
MPSiteType type = (MPSiteType)[[mainSite.algorithm allTypes][buttonIndex] unsignedIntegerValue]?:
mainSite.user.defaultType?: mainSite.algorithm.defaultType;
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
MPSiteEntity *site = [self siteInContext:context];
@@ -507,10 +507,10 @@
self.upgradeButton.gone = !mainSite.requiresExplicitMigration && ![[MPiOSConfig get].allowDowngrade boolValue];
self.answersButton.gone = ![[MPiOSAppDelegate get] isFeatureUnlocked:MPProductGenerateAnswers];
BOOL settingsMode = self.mode == MPPasswordCellModeSettings;
self.loginNameContainer.alpha = settingsMode || mainSite.loginGenerated || [mainSite.loginName length]? 0.7f: 0;
self.loginNameField.textColor = [UIColor colorWithHexString:mainSite.loginGenerated? @"5E636D": @"6D5E63"];
self.modeButton.alpha = self.transientSite? 0: settingsMode? 0.5f: 0.1f;
self.counterLabel.alpha = self.counterButton.alpha = mainSite.type & MPSiteTypeClassGenerated? 0.5f: 0;
self.loginNameContainer.visible = settingsMode || mainSite.loginGenerated || [mainSite.loginName length];
self.modeButton.visible = !self.transientSite;
self.modeButton.alpha = settingsMode? 0.5f: 0.1f;
self.counterLabel.visible = self.counterButton.visible = mainSite.type & MPSiteTypeClassGenerated;
self.modeButton.selected = settingsMode;
self.strengthLabel.gone = !settingsMode;
self.modeScrollView.scrollEnabled = !self.transientSite;
@@ -520,13 +520,21 @@
[self.passwordField resignFirstResponder];
}
if ([[MPiOSAppDelegate get] isFeatureUnlocked:MPProductGenerateLogins])
[self.loginNameButton setTitle:@"Tap to generate username or use pencil to save one" forState:UIControlStateNormal];
[self.loginNameButton setTitle:@"Tap here to ⚙ generate username or the pencil to type one" forState:UIControlStateNormal];
else
[self.loginNameButton setTitle:@"Tap the pencil to save a username" forState:UIControlStateNormal];
[self.loginNameButton setTitle:@"Tap the pencil to type a username" forState:UIControlStateNormal];
// Site Name
[self updateSiteName:mainSite];
// Site Counter
if ([mainSite isKindOfClass:[MPGeneratedSiteEntity class]])
self.counterLabel.text = strf( @"%lu", (unsigned long)((MPGeneratedSiteEntity *)mainSite).counter );
// Site Login Name
self.loginNameField.enabled = self.passwordField.enabled = //
[self.loginNameField isFirstResponder] || [self.passwordField isFirstResponder];
// Site Password
self.passwordField.secureTextEntry = [[MPiOSConfig get].hidePasswords boolValue];
self.passwordField.attributedPlaceholder = stra(
@@ -534,14 +542,17 @@
mainSite.type & MPSiteTypeClassGenerated? strl( @"..." ): @"", @{
NSForegroundColorAttributeName: [UIColor whiteColor]
} );
// Calculate Fields
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
MPSiteEntity *site = [self siteInContext:context];
MPKey *key = [MPiOSAppDelegate get].key;
if (!key)
return;
BOOL loginGenerated = site.loginGenerated;
NSString *password = nil, *loginName = [site resolveLoginUsingKey:key];
MPSiteType transientType = [[MPiOSAppDelegate get] activeUserInContext:context].defaultType?: MPSiteTypeGeneratedLong;
MPSiteType transientType = [[MPiOSAppDelegate get] activeUserInContext:context].defaultType?: MPAlgorithmDefault.defaultType;
if (self.transientSite && transientType & MPSiteTypeClassGenerated)
password = [MPAlgorithmDefault generatePasswordForSiteNamed:self.transientSite ofType:transientType
withCounter:1 usingKey:key];
@@ -559,13 +570,15 @@
BOOL requiresExplicitMigration = site.requiresExplicitMigration;
PearlMainQueue( ^{
self.loginNameField.text = loginName;
self.passwordField.text = password;
self.strengthLabel.text = timeToCrackString;
self.loginNameButton.titleLabel.alpha = [loginName length] || self.loginNameField.enabled? 0: 1;
self.loginNameGenerated.hidden = !loginGenerated;
self.loginNameField.attributedText =
strarm( stra( loginName?: @"", self.siteNameLabel.textAttributes ), NSParagraphStyleAttributeName, nil );
self.loginNameButton.hidden = [loginName length] || self.loginNameField.enabled;
if (![password length]) {
self.indicatorView.alpha = 1;
self.indicatorView.hidden = NO;
[self.indicatorView removeFromSuperview];
[self.modeScrollView addSubview:self.indicatorView];
[self.contentView addConstraintsWithVisualFormat:@"V:[indicator][target]" options:NSLayoutFormatAlignAllCenterX
@@ -575,7 +588,7 @@
}];
}
else if (requiresExplicitMigration) {
self.indicatorView.alpha = 1;
self.indicatorView.hidden = NO;
[self.indicatorView removeFromSuperview];
[self.modeScrollView addSubview:self.indicatorView];
[self.contentView addConstraintsWithVisualFormat:@"V:[indicator][target]" options:NSLayoutFormatAlignAllCenterX
@@ -585,18 +598,10 @@
}];
}
else
self.indicatorView.alpha = 0;
self.indicatorView.hidden = YES;
} );
}];
// Site Counter
if ([mainSite isKindOfClass:[MPGeneratedSiteEntity class]])
self.counterLabel.text = strf( @"%lu", (unsigned long)((MPGeneratedSiteEntity *)mainSite).counter );
// Site Login Name
self.loginNameField.enabled = self.passwordField.enabled = //
[self.loginNameField isFirstResponder] || [self.passwordField isFirstResponder];
[self.contentView layoutIfNeeded];
}];
}
@@ -616,8 +621,9 @@
range:NSMakeRange( s, [self.fuzzyGroups[f] length] )];
}
[attributedSiteName appendAttributedString:stra(
strf( @" - %@", self.transientSite? @"Tap to create": [site.algorithm shortNameOfType:site.type] ), @{} )];
if (self.transientSite)
[attributedSiteName appendAttributedString:stra( @" Tap to create", @{} )];
self.siteNameLabel.attributedText = attributedSiteName;
}

View File

@@ -46,6 +46,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
NSUInteger _transientItem;
NSCharacterSet *_siteNameAcceptableCharactersSet;
NSArray *_fuzzyGroups;
NSMutableArray *_passwordCollectionViewUpdatesBatch;
}
#pragma mark - Life
@@ -62,6 +63,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
_backgroundColor = self.passwordCollectionView.backgroundColor;
_darkenedBackgroundColor = [_backgroundColor colorWithAlphaComponent:0.6f];
_transientItem = NSNotFound;
_passwordCollectionViewUpdatesBatch = [NSMutableArray arrayWithCapacity:4];
self.view.backgroundColor = [UIColor clearColor];
[self.passwordCollectionView automaticallyAdjustInsetsForKeyboard];
@@ -181,10 +183,13 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
Weakify( self );
if (controller == _fetchedResultsController) {
@try {
[self.passwordCollectionView performBatchUpdates:^{
[self fetchedItemsDidUpdate];
@synchronized (_passwordCollectionViewUpdatesBatch) {
[_passwordCollectionViewUpdatesBatch addObject:[^{
Strongify( self );
switch (type) {
case NSFetchedResultsChangeInsert:
[self.passwordCollectionView insertItemsAtIndexPaths:@[ newIndexPath ]];
@@ -193,18 +198,35 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
[self.passwordCollectionView deleteItemsAtIndexPaths:@[ indexPath ]];
break;
case NSFetchedResultsChangeMove:
[self.passwordCollectionView moveItemAtIndexPath:indexPath toIndexPath:newIndexPath];
if (![indexPath isEqual:newIndexPath])
[self.passwordCollectionView moveItemAtIndexPath:indexPath toIndexPath:newIndexPath];
break;
case NSFetchedResultsChangeUpdate:
[self.passwordCollectionView reloadItemsAtIndexPaths:@[ indexPath ]];
break;
}
} completion:nil];
}
@catch (NSException *exception) {
wrn( @"While updating password cells: %@", [exception fullDescription] );
[self.passwordCollectionView reloadData];
} copy]];
}
[controller.managedObjectContext performBlock:^{
PearlMainQueueOperation( ^{
@try {
[self.passwordCollectionView performBatchUpdates:^{
[self updateTransientItem];
@synchronized (_passwordCollectionViewUpdatesBatch) {
for (VoidBlock block in _passwordCollectionViewUpdatesBatch)
block();
[_passwordCollectionViewUpdatesBatch removeAllObjects];
}
} completion:nil];
}
@catch (NSException *exception) {
wrn( @"While updating password cells: %@", [exception fullDescription] );
[self.passwordCollectionView reloadData];
}
} );
}];
}
}
@@ -278,37 +300,35 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
[UIView animateWithDuration:0.3f animations:^{
if (showTips & MPPasswordsBadNameTip)
self.badNameTipContainer.alpha = 1;
self.badNameTipContainer.visible = YES;
} completion:^(BOOL finished) {
if (finished)
PearlMainQueueAfter( 5, ^{
[UIView animateWithDuration:0.3f animations:^{
if (showTips & MPPasswordsBadNameTip)
self.badNameTipContainer.alpha = 0;
}];
} );
PearlMainQueueAfter( 5, ^{
[UIView animateWithDuration:0.3f animations:^{
if (showTips & MPPasswordsBadNameTip)
self.badNameTipContainer.visible = NO;
}];
} );
}];
}
- (void)fetchedItemsDidUpdate {
- (void)updateTransientItem {
NSString *query = self.query;
_showTransientItem = [query length] > 0;
NSUInteger objects = ((id<NSFetchedResultsSectionInfo>)self.fetchedResultsController.sections[0]).numberOfObjects;
if (_showTransientItem && objects == 1 &&
[[[self.fetchedResultsController.fetchedObjects firstObject] name] isEqualToString:query])
_showTransientItem = NO;
if ([self.passwordCollectionView numberOfSections] > 0) {
if (!_showTransientItem && _transientItem != NSNotFound)
[self.passwordCollectionView deleteItemsAtIndexPaths:
@[ [NSIndexPath indexPathForItem:_transientItem inSection:0] ]];
else if (_showTransientItem && _transientItem == NSNotFound)
[self.passwordCollectionView insertItemsAtIndexPaths:
@[ [NSIndexPath indexPathForItem:objects inSection:0] ]];
else if (_transientItem != NSNotFound)
[self.passwordCollectionView reloadItemsAtIndexPaths:
@[ [NSIndexPath indexPathForItem:_transientItem inSection:0] ]];
_showTransientItem = [query length] > 0 && ![[[self.fetchedResultsController.sections[0] objects] filteredArrayUsingPredicate:
[NSPredicate predicateWithBlock:^BOOL(MPSiteEntity *site, NSDictionary<NSString *, id> *bindings) {
return [site.name isEqualToString:query];
}]] count];
if (!_showTransientItem && _transientItem != NSNotFound)
[self.passwordCollectionView deleteItemsAtIndexPaths:
@[ [NSIndexPath indexPathForItem:_transientItem inSection:0] ]];
else if (_showTransientItem && _transientItem == NSNotFound) {
NSUInteger objects = [self.fetchedResultsController.sections[0] numberOfObjects];
[self.passwordCollectionView insertItemsAtIndexPaths:
@[ [NSIndexPath indexPathForItem:objects inSection:0] ]];
}
else if (_transientItem != NSNotFound)
[self.passwordCollectionView reloadItemsAtIndexPaths:
@[ [NSIndexPath indexPathForItem:_transientItem inSection:0] ]];
}
- (void)registerObservers {
@@ -316,7 +336,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
PearlRemoveNotificationObservers();
PearlAddNotificationObserver( UIApplicationDidEnterBackgroundNotification, nil, [NSOperationQueue mainQueue],
^(MPPasswordsViewController *self, NSNotification *note) {
self.passwordSelectionContainer.alpha = 0;
self.passwordSelectionContainer.visible = NO;
} );
PearlAddNotificationObserver( UIApplicationWillEnterForegroundNotification, nil, [NSOperationQueue mainQueue],
^(MPPasswordsViewController *self, NSNotification *note) {
@@ -325,7 +345,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
PearlAddNotificationObserver( UIApplicationDidBecomeActiveNotification, nil, [NSOperationQueue mainQueue],
^(MPPasswordsViewController *self, NSNotification *note) {
[UIView animateWithDuration:0.7f animations:^{
self.passwordSelectionContainer.alpha = 1;
self.passwordSelectionContainer.visible = YES;
}];
} );
PearlAddNotificationObserver( MPSignedOutNotification, nil, nil,
@@ -361,6 +381,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
if (mainContext)
PearlAddNotificationObserver( NSManagedObjectContextDidSaveNotification, mainContext, nil,
^(MPPasswordsViewController *self, NSNotification *note) {
// TODO: either move this into the app delegate or remove the duplicate signOutAnimated: call from the app delegate.
if (![[MPiOSAppDelegate get] activeUserInContext:note.object])
[[MPiOSAppDelegate get] signOutAnimated:YES];
} );
@@ -421,7 +442,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
PearlMainQueue( ^{
@try {
[self.passwordCollectionView performBatchUpdates:^{
[self fetchedItemsDidUpdate];
[self updateTransientItem];
NSInteger fromSections = self.passwordCollectionView.numberOfSections;
NSInteger toSections = [self numberOfSectionsInCollectionView:self.passwordCollectionView];

View File

@@ -22,8 +22,6 @@
@implementation MPPopdownSegue {
}
static char UnwindingObserverKey;
- (void)perform {
MPPasswordsViewController *passwordsVC;
@@ -39,19 +37,20 @@ static char UnwindingObserverKey;
[passwordsVC.popdownContainer addConstraintsWithVisualFormats:@[ @"H:|[popdownView]|", @"V:|[popdownView]|" ] options:0
metrics:nil views:NSDictionaryOfVariableBindings( popdownView )];
[UIView animateWithDuration:0.3f animations:^{
[[passwordsVC.popdownToTopConstraint updatePriority:1] layoutIfNeeded];
} completion:^(BOOL finished) {
[popdownVC didMoveToParentViewController:passwordsVC];
[passwordsVC.popdownToTopConstraint layoutIfNeeded];
id<NSObject> observer = [[NSNotificationCenter defaultCenter] addObserverForName:MPSignedOutNotification object:nil
queue:[NSOperationQueue mainQueue] usingBlock:
^(NSNotification *note) {
[[[MPPopdownSegue alloc] initWithIdentifier:@"unwind-popdown" source:popdownVC
destination:passwordsVC] perform];
}];
objc_setAssociatedObject( popdownVC, &UnwindingObserverKey, observer, OBJC_ASSOCIATION_RETAIN );
}];
[UIView animateWithDuration:0.6f delay:0 usingSpringWithDamping:0.75f initialSpringVelocity:1
options:UIViewAnimationOptionCurveEaseOut animations:^{
[[passwordsVC.popdownToTopConstraint updatePriority:1] layoutIfNeeded];
} completion:^(BOOL finished) {
[popdownVC didMoveToParentViewController:passwordsVC];
PearlAddNotificationObserverTo( popdownVC, MPSignedOutNotification, nil, [NSOperationQueue mainQueue],
^(id host, NSNotification *note) {
[[[MPPopdownSegue alloc] initWithIdentifier:@"unwind-popdown" source:popdownVC destination:passwordsVC]
perform];
} );
}];
}
else {
popdownVC = self.sourceViewController;
@@ -59,16 +58,16 @@ static char UnwindingObserverKey;
passwordsVC = (id)passwordsVC.parentViewController);
NSAssert( passwordsVC, @"Couldn't find passwords VC to pop back to." );
[[NSNotificationCenter defaultCenter] removeObserver:objc_getAssociatedObject( popdownVC, &UnwindingObserverKey )];
objc_setAssociatedObject( popdownVC, &UnwindingObserverKey, nil, OBJC_ASSOCIATION_RETAIN );
PearlRemoveNotificationObserversFrom( popdownVC );
[popdownVC willMoveToParentViewController:nil];
[UIView animateWithDuration:0.3f delay:0 options:UIViewAnimationOptionOverrideInheritedDuration animations:^{
[[passwordsVC.popdownToTopConstraint updatePriority:UILayoutPriorityDefaultHigh] layoutIfNeeded];
} completion:^(BOOL finished) {
[popdownVC.view removeFromSuperview];
[popdownVC removeFromParentViewController];
}];
[UIView animateWithDuration:0.4f delay:0 options:UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionOverrideInheritedDuration
animations:^{
[[passwordsVC.popdownToTopConstraint updatePriority:UILayoutPriorityDefaultHigh] layoutIfNeeded];
} completion:^(BOOL finished) {
[popdownVC.view removeFromSuperview];
[popdownVC removeFromParentViewController];
}];
}
}

View File

@@ -29,8 +29,10 @@
@property(weak, nonatomic) IBOutlet UITableViewCell *exportCell;
@property(weak, nonatomic) IBOutlet UITableViewCell *checkInconsistencies;
@property(weak, nonatomic) IBOutlet UIImageView *avatarImage;
@property(weak, nonatomic) IBOutlet UISegmentedControl *generatedTypeControl;
@property(weak, nonatomic) IBOutlet UISegmentedControl *generated1TypeControl;
@property(weak, nonatomic) IBOutlet UISegmentedControl *generated2TypeControl;
@property(weak, nonatomic) IBOutlet UISegmentedControl *storedTypeControl;
@property(weak, nonatomic) IBOutlet UILabel *passwordTypeExample;
- (IBAction)previousAvatar:(id)sender;
- (IBAction)nextAvatar:(id)sender;

View File

@@ -55,12 +55,24 @@
- (void)reload {
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForMainThread];
self.generatedTypeControl.selectedSegmentIndex = [self generatedSegmentIndexForType:activeUser.defaultType];
self.storedTypeControl.selectedSegmentIndex = [self storedSegmentIndexForType:activeUser.defaultType];
self.avatarImage.image = [UIImage imageNamed:strf( @"avatar-%lu", (unsigned long)activeUser.avatar )];
self.savePasswordSwitch.on = activeUser.saveKey;
self.touchIDSwitch.on = activeUser.touchID;
self.touchIDSwitch.enabled = self.savePasswordSwitch.on && [[MPiOSAppDelegate get] isFeatureUnlocked:MPProductTouchID];
MPSiteType defaultType = activeUser.defaultType;
self.generated1TypeControl.selectedSegmentIndex = [self generated1SegmentIndexForType:defaultType];
self.generated2TypeControl.selectedSegmentIndex = [self generated2SegmentIndexForType:defaultType];
self.storedTypeControl.selectedSegmentIndex = [self storedSegmentIndexForType:defaultType];
PearlNotMainQueue( ^{
NSString *examplePassword = nil;
if (defaultType & MPSiteTypeClassGenerated)
examplePassword = [MPAlgorithmDefault generatePasswordForSiteNamed:@"test" ofType:defaultType
withCounter:1 usingKey:[MPiOSAppDelegate get].key];
PearlMainQueue( ^{
self.passwordTypeExample.text = [examplePassword length]? [NSString stringWithFormat:@"eg. %@", examplePassword]: nil;
} );
} );
}
#pragma mark - UITableViewDelegate
@@ -88,14 +100,18 @@
[self dismissPopup];
[[MPiOSAppDelegate get] signOutAnimated:YES];
}
if (cell == self.feedbackCell)
[[MPiOSAppDelegate get] showFeedbackWithLogs:YES forVC:self];
if (cell == self.exportCell)
[[MPiOSAppDelegate get] showExportForVC:self];
if (cell == self.showHelpCell) {
MPPasswordsViewController *passwordsVC = [self dismissPopup];
[passwordsVC performSegueWithIdentifier:@"guide" sender:self];
}
if (cell == self.checkInconsistencies)
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
if ([[MPiOSAppDelegate get] findAndFixInconsistenciesSaveInContext:context] == MPFixableResultNoProblems)
@@ -140,11 +156,13 @@
} );
}];
if (sender == self.generatedTypeControl || sender == self.storedTypeControl) {
if (sender == self.generatedTypeControl)
if (sender == self.generated1TypeControl || sender == self.generated2TypeControl || sender == self.storedTypeControl) {
if (sender != self.generated1TypeControl)
self.generated1TypeControl.selectedSegmentIndex = -1;
if (sender != self.generated2TypeControl)
self.generated2TypeControl.selectedSegmentIndex = -1;
if (sender != self.storedTypeControl)
self.storedTypeControl.selectedSegmentIndex = -1;
else if (sender == self.storedTypeControl)
self.generatedTypeControl.selectedSegmentIndex = -1;
MPSiteType defaultType = [self typeForSelectedSegment];
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
@@ -226,10 +244,17 @@
- (MPSiteType)typeForSelectedSegment {
NSInteger selectedGeneratedIndex = self.generatedTypeControl.selectedSegmentIndex;
NSInteger selectedGenerated1Index = self.generated1TypeControl.selectedSegmentIndex;
NSInteger selectedGenerated2Index = self.generated2TypeControl.selectedSegmentIndex;
NSInteger selectedStoredIndex = self.storedTypeControl.selectedSegmentIndex;
switch (selectedGeneratedIndex) {
switch (selectedGenerated1Index) {
case 0:
return MPSiteTypeGeneratedPhrase;
case 1:
return MPSiteTypeGeneratedName;
default:
switch (selectedGenerated2Index) {
case 0:
return MPSiteTypeGeneratedMaximum;
case 1:
@@ -250,13 +275,26 @@
case 1:
return MPSiteTypeStoredDevicePrivate;
default:
Throw( @"unsupported selected type index: generated=%ld, stored=%ld", (long)selectedGeneratedIndex,
(long)selectedStoredIndex );
Throw( @"unsupported selected type index: generated1=%ld, generated2=%ld, stored=%ld",
(long)selectedGenerated1Index, (long)selectedGenerated2Index, (long)selectedStoredIndex );
}
}
}
}
- (NSInteger)generatedSegmentIndexForType:(MPSiteType)type {
- (NSInteger)generated1SegmentIndexForType:(MPSiteType)type {
switch (type) {
case MPSiteTypeGeneratedPhrase:
return 0;
case MPSiteTypeGeneratedName:
return 1;
default:
return -1;
}
}
- (NSInteger)generated2SegmentIndexForType:(MPSiteType)type {
switch (type) {
case MPSiteTypeGeneratedMaximum:

View File

@@ -76,7 +76,7 @@ PearlEnum( MPDevelopmentFuelConsumption,
[self reloadCellsHiding:self.allCellsBySection[0] showing:@[ self.loadingCell ]];
[self.allCellsBySection[0] enumerateObjectsUsingBlock:^(MPStoreProductCell *cell, NSUInteger idx, BOOL *stop) {
if ([cell isKindOfClass:[MPStoreProductCell class]]) {
cell.purchasedIndicator.alpha = 0;
cell.purchasedIndicator.visible = NO;
[cell.activityIndicator stopAnimating];
}
}];
@@ -245,7 +245,7 @@ PearlEnum( MPDevelopmentFuelConsumption,
NSMutableArray *showCells = [NSMutableArray array];
NSMutableArray *hideCells = [NSMutableArray array];
[hideCells addObjectsFromArray:self.allCellsBySection[0]];
[hideCells addObjectsFromArray:[self.allCellsBySection[0] array]];
[hideCells addObject:self.loadingCell];
for (SKProduct *product in self.products) {
@@ -313,7 +313,7 @@ PearlEnum( MPDevelopmentFuelConsumption,
BOOL purchased = [[MPiOSAppDelegate get] isFeatureUnlocked:productIdentifier];
NSInteger quantity = [self quantityForProductIdentifier:productIdentifier];
cell.priceLabel.text = purchased? @"": [self.currencyFormatter stringFromNumber:@([product.price floatValue] * quantity)];
cell.purchasedIndicator.alpha = purchased? 1: 0;
cell.purchasedIndicator.visible = purchased;
}
- (NSInteger)quantityForProductIdentifier:(NSString *)productIdentifier {

View File

@@ -33,7 +33,7 @@
- (void)viewWillAppear:(BOOL)animated {
inf( @"Type selection will appear" );
self.recommendedTipContainer.alpha = 0;
self.recommendedTipContainer.visible = NO;
[super viewWillAppear:animated];
}
@@ -42,15 +42,13 @@
if ([[MPiOSConfig get].firstRun boolValue])
[UIView animateWithDuration:animated? 0.3f: 0 animations:^{
self.recommendedTipContainer.alpha = 1;
self.recommendedTipContainer.visible = YES;
} completion:^(BOOL finished) {
if (finished) {
dispatch_after( dispatch_time( DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC) ), dispatch_get_main_queue(), ^{
[UIView animateWithDuration:0.2f animations:^{
self.recommendedTipContainer.alpha = 0;
}];
} );
}
PearlMainQueueAfter( 5, ^{
[UIView animateWithDuration:0.2f animations:^{
self.recommendedTipContainer.visible = NO;
}];
} );
}];
[super viewDidAppear:animated];
@@ -89,11 +87,11 @@
if ([selectedSite isKindOfClass:[MPGeneratedSiteEntity class]])
counter = ((MPGeneratedSiteEntity *)selectedSite).counter;
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ), ^{
PearlNotMainQueue( ^{
NSString *typeContent = [MPAlgorithmDefault generatePasswordForSiteNamed:name ofType:cellType
withCounter:counter usingKey:[MPiOSAppDelegate get].key];
dispatch_async( dispatch_get_main_queue(), ^{
PearlMainQueue( ^{
[(UITextField *)[[tableView cellForRowAtIndexPath:indexPath] viewWithTag:2] setText:typeContent];
} );
} );

View File

@@ -76,7 +76,7 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) {
self.avatarCollectionView.allowsMultipleSelection = YES;
[self.entryField addTarget:self action:@selector( textFieldEditingChanged: ) forControlEvents:UIControlEventEditingChanged];
self.preferencesTipContainer.alpha = 0;
self.preferencesTipContainer.visible = NO;
[self setActive:YES animated:NO];
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"tipped.thanks"])
@@ -87,7 +87,7 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) {
[super viewWillAppear:animated];
self.userSelectionContainer.alpha = 0;
self.userSelectionContainer.visible = NO;
}
- (void)viewWillDisappear:(BOOL)animated {
@@ -220,6 +220,7 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) {
if (isNew) {
user = [MPUserEntity insertNewObjectInContext:context];
user.algorithm = MPAlgorithmDefault;
user.defaultType = user.algorithm.defaultType;
user.avatar = newUserAvatar;
user.name = newUserName;
}
@@ -497,25 +498,25 @@ referenceSizeForFooterInSection:(NSInteger)section {
[UIView animateWithDuration:0.3f animations:^{
if (showTips & MPUsersThanksTip)
self.thanksTipContainer.alpha = 1;
self.thanksTipContainer.visible = YES;
if (showTips & MPUsersAvatarTip)
self.avatarTipContainer.alpha = 1;
self.avatarTipContainer.visible = YES;
if (showTips & MPUsersMasterPasswordTip)
self.entryTipContainer.alpha = 1;
self.entryTipContainer.visible = YES;
if (showTips & MPUsersPreferencesTip)
self.preferencesTipContainer.alpha = 1;
self.preferencesTipContainer.visible = YES;
} completion:^(BOOL finished) {
if (finished)
PearlMainQueueAfter( 5, ^{
[UIView animateWithDuration:0.3f animations:^{
if (showTips & MPUsersThanksTip)
self.thanksTipContainer.alpha = 0;
self.thanksTipContainer.visible = NO;
if (showTips & MPUsersAvatarTip)
self.avatarTipContainer.alpha = 0;
self.avatarTipContainer.visible = NO;
if (showTips & MPUsersMasterPasswordTip)
self.entryTipContainer.alpha = 0;
self.entryTipContainer.visible = NO;
if (showTips & MPUsersPreferencesTip)
self.preferencesTipContainer.alpha = 0;
self.preferencesTipContainer.visible = NO;
}];
} );
}];
@@ -538,14 +539,14 @@ referenceSizeForFooterInSection:(NSInteger)section {
return;
[UIView animateWithDuration:timer? 0.5f: 0 animations:^{
self.marqueeButton.alpha = 0;
self.marqueeButton.visible = NO;
} completion:^(BOOL finished) {
if (!finished)
return;
[self.marqueeButton setTitle:nextMarqueeString forState:UIControlStateNormal];
[UIView animateWithDuration:timer? 0.5f: 0 animations:^{
self.marqueeButton.alpha = 0.5f;
self.marqueeButton.visible = YES;
}];
}];
}
@@ -588,8 +589,6 @@ referenceSizeForFooterInSection:(NSInteger)section {
- (void)updateAvatarVisibility {
self.previousAvatarButton.alpha = 0;
self.nextAvatarButton.alpha = 0;
for (NSIndexPath *indexPath in self.avatarCollectionView.indexPathsForVisibleItems) {
MPAvatarCell *cell = (MPAvatarCell *)[self.avatarCollectionView cellForItemAtIndexPath:indexPath];
[self updateVisibilityForAvatar:cell atIndexPath:indexPath animated:NO];
@@ -633,10 +632,10 @@ referenceSizeForFooterInSection:(NSInteger)section {
CGFloat visibility = MAX( 0, MIN( 1, 1 - ABS( current / (max / 2) - 1 ) ) );
[cell setVisibility:visibility animated:animated];
if (cell.newUser) {
self.previousAvatarButton.alpha = cell.mode == MPAvatarModeRaisedAndActive? visibility * 0.7f: 0;
self.nextAvatarButton.alpha = cell.mode == MPAvatarModeRaisedAndActive? visibility * 0.7f: 0;
}
[UIView animateWithDuration:animated? 0.3f: 0 animations:^{
self.nextAvatarButton.visible = self.previousAvatarButton.visible = cell.newUser && cell.mode == MPAvatarModeRaisedAndActive;
self.nextAvatarButton.alpha = self.previousAvatarButton.alpha = visibility * 0.7f;
}];
}
- (void)afterUpdatesMainQueue:(void ( ^ )(void))block {
@@ -657,7 +656,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
PearlRemoveNotificationObservers();
PearlAddNotificationObserver( UIApplicationDidEnterBackgroundNotification, nil, [NSOperationQueue mainQueue],
^(MPUsersViewController *self, NSNotification *note) {
self.userSelectionContainer.alpha = 0;
self.userSelectionContainer.visible = NO;
} );
PearlAddNotificationObserver( UIApplicationWillEnterForegroundNotification, nil, [NSOperationQueue mainQueue],
^(MPUsersViewController *self, NSNotification *note) {
@@ -666,7 +665,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
PearlAddNotificationObserver( UIApplicationDidBecomeActiveNotification, nil, [NSOperationQueue mainQueue],
^(MPUsersViewController *self, NSNotification *note) {
[UIView animateWithDuration:0.5f animations:^{
self.userSelectionContainer.alpha = 1;
self.userSelectionContainer.visible = YES;
}];
} );
PearlAddNotificationObserver( UIKeyboardWillShowNotification, nil, [NSOperationQueue mainQueue],
@@ -678,7 +677,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
NSManagedObjectContext *mainContext = [MPiOSAppDelegate managedObjectContextForMainThreadIfReady];
[UIView animateWithDuration:0.3f animations:^{
self.avatarCollectionView.alpha = mainContext? 1: 0;
self.avatarCollectionView.visible = mainContext != nil;
}];
if (mainContext && self.storeLoadingActivity.isAnimating)
[self.storeLoadingActivity stopAnimating];
@@ -763,7 +762,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];
[UIView animateWithDuration:0.3f animations:^{
self.userSelectionContainer.alpha = 1;
self.userSelectionContainer.visible = YES;
}];
} );
}
@@ -828,8 +827,8 @@ referenceSizeForFooterInSection:(NSInteger)section {
switch (activeUserState) {
case MPActiveUserStateNone: {
self.avatarCollectionView.scrollEnabled = YES;
self.entryContainer.alpha = 0;
self.footerContainer.alpha = 1;
self.entryContainer.visible = NO;
self.footerContainer.visible = YES;
break;
}
case MPActiveUserStateLogin:
@@ -837,15 +836,15 @@ referenceSizeForFooterInSection:(NSInteger)section {
case MPActiveUserStateMasterPasswordChoice:
case MPActiveUserStateMasterPasswordConfirmation: {
self.avatarCollectionView.scrollEnabled = NO;
self.entryContainer.alpha = 1;
self.footerContainer.alpha = 1;
self.entryContainer.visible = YES;
self.footerContainer.visible = YES;
requestFirstResponder = YES;
break;
}
case MPActiveUserStateMinimized: {
self.avatarCollectionView.scrollEnabled = NO;
self.entryContainer.alpha = 0;
self.footerContainer.alpha = 0;
self.entryContainer.visible = NO;
self.footerContainer.visible = NO;
break;
}
}

View File

@@ -36,7 +36,7 @@
self.webNavigationItem.title = self.initialURL.host;
self.webView.alpha = 0;
self.webView.visible = NO;
[self.webView loadRequest:[[NSURLRequest alloc] initWithURL:self.initialURL]];
}
@@ -75,7 +75,7 @@
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[UIView animateWithDuration:0.3 animations:^{
self.webView.alpha = 1;
self.webView.visible = YES;
}];
[self.webNavigationItem setLeftBarButtonItem:[webView canGoBack]? [[UIBarButtonItem alloc]

View File

@@ -19,7 +19,6 @@
#import "MPiOSAppDelegate.h"
#import "MPAppDelegate_Key.h"
#import "MPAppDelegate_Store.h"
#import "IASKSettingsReader.h"
#import "MPStoreViewController.h"
@interface MPiOSAppDelegate()<UIDocumentInteractionControllerDelegate>
@@ -53,7 +52,7 @@
NSString *crashlyticsAPIKey = [self crashlyticsAPIKey];
if ([crashlyticsAPIKey length]) {
inf( @"Initializing Crashlytics" );
#if defined (DEBUG) || defined (ADHOC)
#if DEBUG
[Crashlytics sharedInstance].debugMode = YES;
#endif
[[Crashlytics sharedInstance] setUserIdentifier:[PearlKeyChain deviceIdentifier]];
@@ -89,18 +88,6 @@
PearlAddNotificationObserver( NSUserDefaultsDidChangeNotification, nil, nil, ^(id self, NSNotification *note) {
[[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification object:nil];
} );
#ifdef ADHOC
[PearlAlert showAlertWithTitle:@"Welcome, tester!" message:
@"Thank you for taking the time to test Master Password.\n\n"
@"Please provide any feedback, however minor it may seem, via the Feedback action item accessible from the top right.\n\n"
@"Contact me directly at:\n"
@"lhunath@lyndir.com\n"
@"Or report detailed issues at:\n"
@"https://youtrack.lyndir.com\n"
viewStyle:UIAlertViewStyleDefault initAlert:nil tappedButtonBlock:nil
cancelTitle:nil otherTitles:[PearlStrings get].commonButtonOkay, nil];
#endif
}
@catch (id exception) {
err( @"During Config Test: %@", exception );
@@ -164,26 +151,24 @@
return NO;
// Arbitrary URL to mpsites data.
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
NSError *error;
NSURLResponse *response;
NSData *importedSitesData = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:url]
returningResponse:&response error:&error];
if (error)
err( @"While reading imported sites from %@: %@", url, [error fullDescription] );
if (!importedSitesData) {
[PearlAlert showError:strf( @"Master Password couldn't read the import sites.\n\n%@", [error localizedDescription]?: error )];
return;
}
[[[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:
^(NSData *importedSitesData, NSURLResponse *response, NSError *error) {
if (error)
err( @"While reading imported sites from %@: %@", url, [error fullDescription] );
if (!importedSitesData) {
[PearlAlert showError:strf( @"Master Password couldn't read the import sites.\n\n%@",
[error localizedDescription]?: error )];
return;
}
NSString *importedSitesString = [[NSString alloc] initWithData:importedSitesData encoding:NSUTF8StringEncoding];
if (!importedSitesString) {
[PearlAlert showError:@"Master Password couldn't understand the import file."];
return;
}
NSString *importedSitesString = [[NSString alloc] initWithData:importedSitesData encoding:NSUTF8StringEncoding];
if (!importedSitesString) {
[PearlAlert showError:@"Master Password couldn't understand the import file."];
return;
}
[self importSites:importedSitesString];
} );
[self importSites:importedSitesString];
}] resume];
return YES;
}
@@ -199,57 +184,33 @@
PearlOverlay *activityOverlay = [PearlOverlay showProgressOverlayWithTitle:@"Importing"];
MPImportResult result = [self importSites:importedSitesString askImportPassword:^NSString *(NSString *userName) {
__block NSString *masterPassword = nil;
dispatch_group_t importPasswordGroup = dispatch_group_create();
dispatch_group_enter( importPasswordGroup );
dispatch_async( dispatch_get_main_queue(), ^{
return PearlAwait( ^(void (^setResult)(id)) {
[PearlAlert showAlertWithTitle:@"Import File's Master Password"
message:strf( @"%@'s export was done using a different master password.\n"
@"Enter that master password to unlock the exported data.", userName )
viewStyle:UIAlertViewStyleSecureTextInput
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
@try {
if (buttonIndex_ == [alert_ cancelButtonIndex])
return;
masterPassword = [alert_ textFieldAtIndex:0].text;
}
@finally {
dispatch_group_leave( importPasswordGroup );
}
if (buttonIndex_ == [alert_ cancelButtonIndex])
setResult( nil );
else
setResult( [alert_ textFieldAtIndex:0].text );
}
cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Unlock Import", nil];
} );
dispatch_group_wait( importPasswordGroup, DISPATCH_TIME_FOREVER );
return masterPassword;
} askUserPassword:^NSString *(NSString *userName, NSUInteger importCount, NSUInteger deleteCount) {
__block NSString *masterPassword = nil;
dispatch_group_t userPasswordGroup = dispatch_group_create();
dispatch_group_enter( userPasswordGroup );
dispatch_async( dispatch_get_main_queue(), ^{
return PearlAwait( (id)^(void (^setResult)(id)) {
[PearlAlert showAlertWithTitle:strf( @"Master Password for\n%@", userName )
message:strf( @"Imports %lu sites, overwriting %lu.",
(unsigned long)importCount, (unsigned long)deleteCount )
viewStyle:UIAlertViewStyleSecureTextInput
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
@try {
if (buttonIndex_ == [alert_ cancelButtonIndex])
return;
masterPassword = [alert_ textFieldAtIndex:0].text;
}
@finally {
dispatch_group_leave( userPasswordGroup );
}
if (buttonIndex_ == [alert_ cancelButtonIndex])
setResult( nil );
else
setResult( [alert_ textFieldAtIndex:0].text );
}
cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:@"Import", nil];
} );
dispatch_group_wait( userPasswordGroup, DISPATCH_TIME_FOREVER );
return masterPassword;
}];
switch (result) {

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
project(mpw)
cmake_minimum_required(VERSION 3.0.2)
set(CMAKE_BUILD_TYPE Release)
set(CMAKE_C_FLAGS "-O3 -DHAS_SODIUM=1")
include_directories(core cli)
file(GLOB SOURCES "core/*.c" "cli/mpw-cli.c")
add_executable(mpw ${SOURCES})
find_library(libsodium REQUIRED)
target_link_libraries(mpw sodium)

View File

@@ -32,21 +32,25 @@ else
# Default targets.
# Modify here or override using targets='mpw mpw-bench' ./build
targets=(
mpw # C CLI version of Master Password.
mpw-bench # C CLI Master Password benchmark utility.
mpw-tests # C Master Password algorithm tester.
mpw # C CLI version of Master Password, requires libsodium or openssl-dev.
#mpw-bench # C CLI Master Password benchmark utility.
#mpw-tests # C Master Password algorithm test suite, requires libxml2.
)
fi
# Optional features.
mpw_color=${mpw_color:-1} # Colorized Identicon, requires libncurses-dev
mpw_color=${mpw_color:-1} # Colorized Identicon, requires libncurses-dev.
# Default build flags.
export CFLAGS="-O3 $CFLAGS"
export LDFLAGS="$LDFLAGS"
# Distribution specific configuration.
# Homebrew
# Homebrew - openssl for scrypt
if hash brew 2>/dev/null; then
opensslPath=$(brew --prefix openssl)
export CFLAGS="$CFLAGS -I$opensslPath/include"
export LDFLAGS="$LDFLAGS -L$opensslPath/lib"
CFLAGS+=" -I$opensslPath/include"
LDFLAGS+=" -L$opensslPath/lib"
fi
### DEPENDENCIES
@@ -208,26 +212,44 @@ depend() {
popd
popd
}
depend_scrypt() {
if haslib sodium; then
if [[ $CFLAGS != *HAS_SODIUM=1* ]]; then
CFLAGS+=" -DHAS_SODIUM=1"
LDFLAGS+=" -lsodium"
fi
return
fi
depend scrypt
if [[ $CFLAGS != *HAS_CPERCIVA=1* ]]; then
local objects=(
"lib/scrypt/src/libcperciva/"*/*.o
"lib/scrypt/src/lib/crypto/"*.o
)
CFLAGS+=" -DHAS_CPERCIVA=1"
LDFLAGS+=" -Llib/scrypt/src ${objects[*]}"
fi
}
### MPW
mpw() {
depend scrypt
depend_scrypt
echo
echo "Building target: $target..."
local CFLAGS=(
$CFLAGS
# library paths
-I"lib/include"
# mpw paths
-I"core" -I"cli"
)
local LDFLAGS=(
# scrypt
"lib/scrypt/src/libcperciva/"*/*.o
"lib/scrypt/src/lib/crypto/"*.o
# library paths
-L"lib/scrypt/src"
$LDFLAGS
# link libraries
-l"crypto"
)
@@ -245,28 +267,28 @@ mpw() {
### MPW-BENCH
mpw-bench() {
depend scrypt
depend_scrypt
depend bcrypt
echo
echo "Building target: $target..."
local CFLAGS=(
$CFLAGS
# library paths
-I"lib/include"
# mpw paths
-I"core" -I"cli"
)
local LDFLAGS=(
# scrypt
"lib/scrypt/src/libcperciva/"*/*.o
"lib/scrypt/src/lib/crypto/"*.o
$LDFLAGS
# bcrypt
"lib/bcrypt/src/crypt_blowfish.o"
"lib/bcrypt/src/crypt_gensalt.o"
"lib/bcrypt/src/wrapper.o"
"lib/bcrypt/src/x86.o"
# library paths
-L"lib/scrypt/src"
-L"lib/bcrypt/src"
# link libraries
-l"crypto"
@@ -283,11 +305,13 @@ mpw-bench() {
### MPW-TESTS
mpw-tests() {
depend scrypt
depend_scrypt
echo
echo "Building target: $target..."
local CFLAGS=(
$CFLAGS
# library paths
-I"lib/include"
-I"/usr/include/libxml2"
@@ -296,11 +320,8 @@ mpw-tests() {
-I"core" -I"cli"
)
local LDFLAGS=(
# scrypt
"lib/scrypt/src/libcperciva/"*/*.o
"lib/scrypt/src/lib/crypto/"*.o
# library paths
-L"lib/scrypt/src"
$LDFLAGS
# link libraries
-l"crypto" -l"xml2"
)
@@ -318,7 +339,7 @@ mpw-tests() {
### TARGETS
haslib() {
! LC_ALL=C cc -l"$1" 2>&1 | grep -q 'library not found'
return cc -l"$1" -x c -o /dev/null - <<< 'int main() { return 0; }'
}
cc() {
if hash llvm-gcc 2>/dev/null; then

View File

@@ -5,4 +5,4 @@ set -e
cd "${BASH_SOURCE%/*}"
rm -vfr lib/*/{.unpacked,.patched,src} lib/include
rm -vfr {core,cli}{*.o,*.dSYM} mpw mpw-bench mpw-tests
rm -vfr {core,cli,.}/{*.o,*.dSYM} mpw mpw-bench mpw-tests

View File

@@ -13,7 +13,6 @@
#include <errno.h>
#include <sys/time.h>
#include <scrypt/sha256.h>
#include <bcrypt/ow-crypt.h>
#include "mpw-algorithm.h"

View File

@@ -213,8 +213,12 @@ int main(int argc, char *const argv[]) {
// Summarize operation.
const char *identicon = mpw_identicon( fullName, masterPassword );
fprintf( stderr, "%s's password for %s:\n[ %s ]: ", fullName, siteName, identicon );
mpw_free_string( identicon );
if (!identicon) {
err( "Couldn't determine identicon.\n" );
} else {
fprintf( stderr, "%s's password for %s:\n[ %s ]: ", fullName, siteName, identicon );
mpw_free_string( identicon );
}
// Output the password.
const uint8_t *masterKey = mpw_masterKeyForUser(

View File

@@ -15,6 +15,11 @@ int main(int argc, char *const argv[]) {
int failedTests = 0;
xmlNodePtr tests = xmlDocGetRootElement( xmlParseFile( "mpw_tests.xml" ) );
if (!tests) {
ftl( "Couldn't find test case: mpw_tests.xml\n" );
abort();
}
for (xmlNodePtr testCase = tests->children; testCase; testCase = testCase->next) {
if (testCase->type != XML_ELEMENT_NODE || xmlStrcmp( testCase->name, BAD_CAST "case" ) != 0)
continue;

View File

@@ -11,19 +11,24 @@ mpwArchive=mpw-$commit.tar.gz
[[ -e $mpwArchive ]] && echo >&2 "WARNING: $mpwArchive already exists. Will overwrite."
read -n1 -p "Will prepare and release $mpwArchive. Press a key to continue or ^C to abort."
echo "Cleaning .."
( git clean -ffdx . && cd core && git clean -ffdx . )
echo "Creating archive $mpwArchive .."
git ls-files -z . | xargs -0 tar -Lcvzf "$mpwArchive"
echo "Creating archive signature $mpwArchive.sig .."
gpg --detach-sign "$mpwArchive"
echo "Installing archive and signature in current site .."
cd ../../public/site/current
ln -sf "../../../platform-independent/cli-c/$mpwArchive"; [[ -e $_ ]]
ln -sf "../../../platform-independent/cli-c/$mpwArchive.sig"; [[ -e $_ ]]
mv "../../../platform-independent/cli-c/$mpwArchive" .; [[ -e $_ ]]
mv "../../../platform-independent/cli-c/$mpwArchive.sig" .; [[ -e $_ ]]
ln -sf "$mpwArchive" "masterpassword-cli.tar.gz"; [[ -e $_ ]]
ln -sf "$mpwArchive.sig" "masterpassword-cli.tar.gz.sig"; [[ -e $_ ]]
echo
echo "Done. Don't forget to publish the site."
echo "package: $mpwArchive"
echo "signature: $mpwArchive.sig"
echo "Done. Ready to publish the site."
echo " package: $mpwArchive"
echo " signature: $mpwArchive.sig"
echo " url: https://ssl.masterpasswordapp.com/$mpwArchive"

View File

@@ -0,0 +1 @@
/Users/lhunath/annex/secret/masterpassword.keystore

View File

@@ -1 +0,0 @@
/Users/lhunath/SpiderOak Hive/secret/release-com.lyndir.masterpassword.jks

View File

@@ -1 +1 @@
mpw-2.1-cli4-0-gf6b2287.tar.gz
mpw-2.5-cli-1-0-gb01e370f.tar.gz

View File

@@ -0,0 +1 @@
mpw-2.5-cli-1-0-gb01e370f.tar.gz.sig

View File

@@ -1 +0,0 @@
../../MasterPassword/C/mpw-2.1-cli1-0-g10f1001.tar.gz

Binary file not shown.

View File

@@ -1 +0,0 @@
../../MasterPassword/C/mpw-2.1-cli2-2-g82c96dd.tar.gz

Binary file not shown.

View File

@@ -1 +0,0 @@
../../MasterPassword/C/mpw-2.1-cli3-0-g438daf2.tar.gz

Binary file not shown.

View File

@@ -1 +0,0 @@
../../MasterPassword/C/mpw-2.1-cli4-0-gf6b2287.tar.gz

Binary file not shown.

Binary file not shown.