Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10f100186c | ||
|
|
2af2351ebf | ||
|
|
49b3fe7913 | ||
|
|
9d926be8ae | ||
|
|
c3474de2ff | ||
|
|
68b9b4e09a | ||
|
|
b810c1032b | ||
|
|
a4ab3c7bc9 | ||
|
|
039547b735 | ||
|
|
6f741f6f2f | ||
|
|
38d4b761b7 | ||
|
|
18f8ebb9dc | ||
|
|
794d064a99 | ||
|
|
090b274363 | ||
|
|
25ba87f119 | ||
|
|
f0b659a0c7 | ||
|
|
7736788920 | ||
|
|
e3be98f3ad | ||
|
|
d9b1b44de0 | ||
|
|
c3c2de5d14 | ||
|
|
6aa50bac04 | ||
|
|
5268039c3d | ||
|
|
0d66d4660e | ||
|
|
e981df3c8b | ||
|
|
543ebd4bac | ||
|
|
e6d21e1c1d | ||
|
|
a3ebcf0608 | ||
|
|
556d1d3d58 | ||
|
|
979d3a2a5a | ||
|
|
480e7f192a | ||
|
|
a18793b161 | ||
|
|
9b24efa65c | ||
|
|
3e217d5a69 | ||
|
|
c8ca1c80e6 | ||
|
|
88c18db010 | ||
|
|
f909cdbae4 | ||
|
|
8b8d5d325e | ||
|
|
c7670f47db |
6
.gitignore
vendored
@@ -16,6 +16,9 @@
|
||||
xcuserdata/
|
||||
/DerivedData/
|
||||
|
||||
# Generated
|
||||
MasterPassword/Resources/Media/Images.xcassets/
|
||||
|
||||
# Media
|
||||
Press/Background.png
|
||||
Press/Front-Page.png
|
||||
@@ -29,7 +32,10 @@ Press/MasterPassword_PressKit/MasterPassword_pressrelease_*.pdf
|
||||
MasterPassword/Java/**/target
|
||||
|
||||
# C
|
||||
MasterPassword/C/VERSION
|
||||
MasterPassword/C/*.o
|
||||
MasterPassword/C/mpw-*.tar.gz
|
||||
MasterPassword/C/mpw
|
||||
MasterPassword/C/mpw-bench
|
||||
MasterPassword/C/lib/*/*
|
||||
!MasterPassword/C/lib/*/.source
|
||||
|
||||
6
.gitmodules
vendored
@@ -13,3 +13,9 @@
|
||||
[submodule "External/AttributedMarkdown"]
|
||||
path = External/AttributedMarkdown
|
||||
url = https://github.com/dreamwieber/AttributedMarkdown.git
|
||||
[submodule "External/uicolor-utilities"]
|
||||
path = External/uicolor-utilities
|
||||
url = git://github.com/lhunath/uicolor-utilities.git
|
||||
[submodule "External/jrswizzle"]
|
||||
path = External/jrswizzle
|
||||
url = git://github.com/jonmarimba/jrswizzle.git
|
||||
|
||||
2
External/Pearl
vendored
1
External/jrswizzle
vendored
Submodule
1
External/uicolor-utilities
vendored
Submodule
@@ -50,7 +50,7 @@
|
||||
<key>3E67FB08419C920516AAC3B00DAAF23073B8CF77</key>
|
||||
<string>../External/RHStatusItemView</string>
|
||||
<key>3ED8592497DB6A564366943C9AAD5A46341B5076</key>
|
||||
<string>../External/AttributedMarkdown/</string>
|
||||
<string>../External/AttributedMarkdown</string>
|
||||
<key>4DDCFFD91B41F00326AD14553BD66CFD366ABD91</key>
|
||||
<string>../External/Pearl</string>
|
||||
<key>8A15A8EA0B3D0B497C4883425BC74DF995224BB3</key>
|
||||
|
||||
@@ -1,9 +1,258 @@
|
||||
#!/usr/bin/env bash
|
||||
# Run with -DDEBUG to enable trace-level output.
|
||||
#
|
||||
# TROUBLESHOOTING
|
||||
# - To enable verbose algorithm/implementation debugging, use ./build -DDEBUG
|
||||
# - If you see 'undefined reference to `clock_gettime'', try ./build -lrt instead
|
||||
#
|
||||
# BUGS
|
||||
# masterpassword@lyndir.com
|
||||
#
|
||||
# AUTHOR
|
||||
# Maarten Billemont
|
||||
#
|
||||
cd "${BASH_SOURCE%/*}"
|
||||
shopt -s extglob
|
||||
set -e
|
||||
|
||||
[[ -e lib/scrypt/scryptenc.o ]] || { echo >&2 "Missing scrypt. First get and build the scrypt source in lib/scrypt from <$(<lib/scrypt/.source)>.\n"; exit 1; }
|
||||
|
||||
deps=( -I"lib/scrypt/lib" -I"lib/scrypt/libcperciva" -l "crypto_aesctr.o" -l "sha256.o" -l "crypto_scrypt-nosse.o" -l "memlimit.o" -l "scryptenc_cpuperf.o" -l"scryptenc.o" -l"crypto" -L"." -L"lib/scrypt" )
|
||||
### CONFIGURATION
|
||||
|
||||
gcc "${deps[@]}" -Qunused-arguments -c types.c -o types.o "$@"
|
||||
gcc "${deps[@]}" -Qunused-arguments -l"types.o" mpw.c -o mpw "$@"
|
||||
# Targets to build.
|
||||
if [[ $targets ]]; then
|
||||
read -ra targets <<< "$targets"
|
||||
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.
|
||||
)
|
||||
fi
|
||||
|
||||
|
||||
### DEPENDENCIES
|
||||
|
||||
fetch() {
|
||||
if hash wget 2>/dev/null; then
|
||||
wget -O "${1##*/}" "$1"
|
||||
elif hash curl 2>/dev/null; then
|
||||
curl "$1" > "${1##*/}"
|
||||
fi
|
||||
}
|
||||
unpack() {
|
||||
if [[ $1 = *.tar.gz || $1 = *.tgz ]]; then
|
||||
tar -xvzf "$1"
|
||||
|
||||
elif [[ $1 = *.tar.bz2 || $1 = *.tbz2 ]]; then
|
||||
tar -xvjf "$1"
|
||||
|
||||
elif [[ $1 = *.tar ]]; then
|
||||
tar -xvf "$1"
|
||||
|
||||
else
|
||||
echo 2>&1 "Don't know how to unpack: $1"
|
||||
fi
|
||||
|
||||
printf 'Verifying package: %s, against digest: %s...' "$1" "$2"
|
||||
[[ $(openssl sha < "$1") = $2 ]] || {
|
||||
printf ' mismatch!\n'
|
||||
echo 2>&1 "Downloaded package doesn't match digest."
|
||||
exit 1
|
||||
}
|
||||
printf ' OK!\n'
|
||||
|
||||
files=( !("$1") )
|
||||
if [[ -d $files ]] && (( ${#files[@]} == 1 )); then
|
||||
mv "$files"/* .
|
||||
rmdir "$files"
|
||||
fi
|
||||
}
|
||||
fetchSource() (
|
||||
source .source
|
||||
|
||||
if [[ $pkg && -e "${pkg##*/}" ]]; then
|
||||
files=( !("${pkg##*/}") )
|
||||
[[ -e $files ]] || {
|
||||
echo
|
||||
echo "Unpacking: ${PWD##*/}, using package..."
|
||||
unpack "${pkg##*/}" "$pkg_sha"
|
||||
}
|
||||
|
||||
elif [[ $git ]] && hash git 2>/dev/null; then
|
||||
[[ -e .git ]] || {
|
||||
echo
|
||||
echo "Fetching: ${PWD##*/}, using git..."
|
||||
git clone "$svn" .
|
||||
printf '%s' "$(git describe --always)" > "${PWD##*/}-version"
|
||||
}
|
||||
|
||||
elif [[ $svn ]] && hash git 2>/dev/null && [[ -x "$(git --exec-path)/git-svn" ]]; then
|
||||
[[ -e .git ]] || {
|
||||
echo
|
||||
echo "Fetching: ${PWD##*/}, using git-svn..."
|
||||
git svn clone --prefix=origin/ --stdlayout "$svn" .
|
||||
printf '%s' "$(git describe --always)" > "${PWD##*/}-version"
|
||||
}
|
||||
|
||||
elif [[ $svn ]] && hash svn 2>/dev/null; then
|
||||
[[ -e .svn ]] || {
|
||||
echo
|
||||
echo "Fetching: ${PWD##*/}, using svn..."
|
||||
svn checkout "$svn/trunk" .
|
||||
printf 'r%s' "$(svn info | awk '/^Revision:/{ print $2 }')" > "${PWD##*/}-version"
|
||||
}
|
||||
|
||||
elif [[ $pkg ]]; then
|
||||
files=( !("${pkg##*/}") )
|
||||
[[ -e $files ]] || {
|
||||
echo
|
||||
echo "Fetching: ${PWD##*/}, using package..."
|
||||
fetch "$pkg"
|
||||
unpack "${pkg##*/}" "$pkg_sha"
|
||||
}
|
||||
|
||||
else
|
||||
|
||||
echo >&2 "error: Missing git-svn or svn."
|
||||
echo >&2 "error: Please install either or manually check out the sources"
|
||||
echo >&2 "error: from: $home"
|
||||
echo >&2 "error: into: $PWD"
|
||||
exit 1
|
||||
fi
|
||||
)
|
||||
depend() {
|
||||
|
||||
echo
|
||||
echo "Checking dependency: $1..."
|
||||
[[ -e "lib/$1/.built" ]] && return
|
||||
|
||||
pushd "lib/$1"
|
||||
fetchSource
|
||||
|
||||
echo
|
||||
echo "Configuring dependency: $1..."
|
||||
if [[ -e configure.ac ]]; then
|
||||
if [[ ! -e configure ]]; then
|
||||
# create configure using autotools.
|
||||
if ! hash aclocal || ! hash automake; then
|
||||
echo >&2 "Need autotools to build $1. Please install automake and autoconf."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
aclocal
|
||||
autoheader
|
||||
autoconf
|
||||
mkdir -p config.aux
|
||||
automake --add-missing
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -e configure ]]; then
|
||||
./configure
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Building dependency: $1..."
|
||||
if [[ -e Makefile ]]; then
|
||||
if ! hash make; then
|
||||
echo >&2 "Need make to build $1. Please install GNU make."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
make
|
||||
date > .built
|
||||
else
|
||||
echo >&2 "error: Don't know how to build: $1"
|
||||
exit 1
|
||||
fi
|
||||
popd
|
||||
}
|
||||
|
||||
|
||||
### MPW
|
||||
mpw() {
|
||||
depend scrypt
|
||||
|
||||
echo
|
||||
echo "Building target: $target..."
|
||||
CFLAGS=(
|
||||
# include paths
|
||||
-I"lib/scrypt/lib" -I"lib/scrypt/libcperciva"
|
||||
)
|
||||
LDFLAGS=(
|
||||
# library paths
|
||||
-L"." -L"lib/scrypt"
|
||||
# link libraries
|
||||
-l"crypto"
|
||||
# scrypt
|
||||
"lib/scrypt/scrypt-crypto_aesctr.o"
|
||||
"lib/scrypt/scrypt-sha256.o"
|
||||
"lib/scrypt/scrypt-crypto_scrypt-nosse.o"
|
||||
"lib/scrypt/scrypt-memlimit.o"
|
||||
"lib/scrypt/scrypt-scryptenc_cpuperf.o"
|
||||
"lib/scrypt/scrypt-scryptenc.o"
|
||||
)
|
||||
|
||||
cc "${CFLAGS[@]}" -c types.c -o types.o "$@"
|
||||
cc "${CFLAGS[@]}" "${LDFLAGS[@]}" "types.o" mpw.c -o mpw "$@"
|
||||
echo "done! Now run ./install or use ./mpw"
|
||||
}
|
||||
|
||||
|
||||
### MPW-BENCH
|
||||
mpw-bench() {
|
||||
depend scrypt
|
||||
depend bcrypt
|
||||
|
||||
echo
|
||||
echo "Building target: $target..."
|
||||
CFLAGS=(
|
||||
# include paths
|
||||
-I"lib/scrypt/lib" -I"lib/scrypt/libcperciva"
|
||||
-I"lib/bcrypt"
|
||||
)
|
||||
LDFLAGS=(
|
||||
# library paths
|
||||
-L"." -L"lib/scrypt"
|
||||
-L"lib/bcrypt"
|
||||
# libraries
|
||||
-l"crypto"
|
||||
# scrypt
|
||||
"lib/scrypt/scrypt-crypto_aesctr.o"
|
||||
"lib/scrypt/scrypt-sha256.o"
|
||||
"lib/scrypt/scrypt-crypto_scrypt-nosse.o"
|
||||
"lib/scrypt/scrypt-memlimit.o"
|
||||
"lib/scrypt/scrypt-scryptenc_cpuperf.o"
|
||||
"lib/scrypt/scrypt-scryptenc.o"
|
||||
# bcrypt
|
||||
"lib/bcrypt/crypt_blowfish.o"
|
||||
"lib/bcrypt/crypt_gensalt.o"
|
||||
"lib/bcrypt/wrapper.o"
|
||||
"lib/bcrypt/x86.o"
|
||||
)
|
||||
|
||||
cc "${CFLAGS[@]}" -c types.c -o types.o "$@"
|
||||
cc "${CFLAGS[@]}" "${LDFLAGS[@]}" "types.o" mpw-bench.c -o mpw-bench "$@"
|
||||
echo "done! Now use ./mpw-bench"
|
||||
}
|
||||
|
||||
|
||||
### TARGETS
|
||||
|
||||
cc() {
|
||||
if hash llvm-gcc 2>/dev/null; then
|
||||
llvm-gcc "$@"
|
||||
elif hash gcc 2>/dev/null; then
|
||||
gcc -std=gnu99 "$@"
|
||||
elif hash clang 2>/dev/null; then
|
||||
clang "$@"
|
||||
else
|
||||
echo >&2 "Need a compiler. Please install GCC or LLVM."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
echo "Will build targets: ${targets[*]}..."
|
||||
for target in "${targets[@]}"; do
|
||||
"$target" "$@"
|
||||
done
|
||||
|
||||
20
MasterPassword/C/distribute
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
cd "${BASH_SOURCE%/*}"
|
||||
tag=$(git describe)
|
||||
commit=$(git describe --long --dirty)
|
||||
[[ $tag && $commit = $tag-* ]] || exit 1
|
||||
git show --show-signature --pretty=format:%H --quiet "$tag" > VERSION
|
||||
|
||||
mpwArchive=mpw-$commit.tar.gz
|
||||
[[ -e $mpwArchive ]] && echo "WARNING: $mpwArchive already exists. Will overwrite."
|
||||
read -n1 -p "Will prepare and release $mpwArchive. Press a key to continue or ^C to abort."
|
||||
|
||||
git ls-files -z . | xargs -0 tar -cvzf "$mpwArchive"
|
||||
echo "$mpwArchive ready, SHA256: $(openssl sha -sha256 < "$mpwArchive")"
|
||||
|
||||
cd ../../Site/current
|
||||
ln -sf "../../MasterPassword/C/$mpwArchive"
|
||||
[[ -e $_ ]]
|
||||
echo "Linked from site, please update your hyperlinks to point to http://masterpasswordapp.com/$mpwArchive"
|
||||
3
MasterPassword/C/lib/bcrypt/.source
Normal file
@@ -0,0 +1,3 @@
|
||||
home=http://www.openwall.com/crypt/
|
||||
pkg=http://www.openwall.com/crypt/crypt_blowfish-1.3.tar.gz
|
||||
pkg_sha=7253c86c8fe890e67ec782749f95ce3f1517b065
|
||||
@@ -1 +1,4 @@
|
||||
https://code.google.com/p/scrypt/
|
||||
home=https://code.google.com/p/scrypt/
|
||||
svn=http://scrypt.googlecode.com/svn
|
||||
pkg=http://masterpasswordapp.com/libscrypt-b12b554.tar.gz
|
||||
pkg_sha=a86445c3e031392d20652f4163adfd3fb0b1994e
|
||||
|
||||
187
MasterPassword/C/mpw-bench.c
Normal file
@@ -0,0 +1,187 @@
|
||||
#include <sys/time.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <pwd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <alg/sha256.h>
|
||||
#include <crypto/crypto_scrypt.h>
|
||||
#include <ow-crypt.h>
|
||||
#include "types.h"
|
||||
|
||||
#define MP_N 32768
|
||||
#define MP_r 8
|
||||
#define MP_p 2
|
||||
#define MP_dkLen 64
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
|
||||
int main(int argc, char *const argv[]) {
|
||||
|
||||
char *userName = "Robert Lee Mitchel";
|
||||
char *masterPassword = "banana colored duckling";
|
||||
char *siteName = "masterpasswordapp.com";
|
||||
uint32_t siteCounter = 1;
|
||||
MPElementType siteType = MPElementTypeGeneratedLong;
|
||||
|
||||
// Start MP
|
||||
struct timeval startTime;
|
||||
if (gettimeofday(&startTime, NULL) != 0) {
|
||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int iterations = 100;
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
// Calculate the master key salt.
|
||||
char *mpNameSpace = "com.lyndir.masterpassword";
|
||||
const uint32_t n_userNameLength = htonl(strlen(userName));
|
||||
const size_t masterKeySaltLength = strlen(mpNameSpace) + sizeof(n_userNameLength) + strlen(userName);
|
||||
char *masterKeySalt = malloc( masterKeySaltLength );
|
||||
if (!masterKeySalt) {
|
||||
fprintf(stderr, "Could not allocate master key salt: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *mKS = masterKeySalt;
|
||||
memcpy(mKS, mpNameSpace, strlen(mpNameSpace)); mKS += strlen(mpNameSpace);
|
||||
memcpy(mKS, &n_userNameLength, sizeof(n_userNameLength)); mKS += sizeof(n_userNameLength);
|
||||
memcpy(mKS, userName, strlen(userName)); mKS += strlen(userName);
|
||||
if (mKS - masterKeySalt != masterKeySaltLength)
|
||||
abort();
|
||||
trc("masterKeySalt ID: %s\n", IDForBuf(masterKeySalt, masterKeySaltLength));
|
||||
|
||||
// Calculate the master key.
|
||||
uint8_t *masterKey = malloc( MP_dkLen );
|
||||
if (!masterKey) {
|
||||
fprintf(stderr, "Could not allocate master key: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
if (crypto_scrypt( (const uint8_t *)masterPassword, strlen(masterPassword), (const uint8_t *)masterKeySalt, masterKeySaltLength, MP_N, MP_r, MP_p, masterKey, MP_dkLen ) < 0) {
|
||||
fprintf(stderr, "Could not generate master key: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
memset(masterKeySalt, 0, masterKeySaltLength);
|
||||
free(masterKeySalt);
|
||||
|
||||
// Calculate the site seed.
|
||||
const uint32_t n_siteNameLength = htonl(strlen(siteName));
|
||||
const uint32_t n_siteCounter = htonl(siteCounter);
|
||||
const size_t sitePasswordInfoLength = strlen(mpNameSpace) + sizeof(n_siteNameLength) + strlen(siteName) + sizeof(n_siteCounter);
|
||||
char *sitePasswordInfo = malloc( sitePasswordInfoLength );
|
||||
if (!sitePasswordInfo) {
|
||||
fprintf(stderr, "Could not allocate site seed: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *sPI = sitePasswordInfo;
|
||||
memcpy(sPI, mpNameSpace, strlen(mpNameSpace)); sPI += strlen(mpNameSpace);
|
||||
memcpy(sPI, &n_siteNameLength, sizeof(n_siteNameLength)); sPI += sizeof(n_siteNameLength);
|
||||
memcpy(sPI, siteName, strlen(siteName)); sPI += strlen(siteName);
|
||||
memcpy(sPI, &n_siteCounter, sizeof(n_siteCounter)); sPI += sizeof(n_siteCounter);
|
||||
if (sPI - sitePasswordInfo != sitePasswordInfoLength)
|
||||
abort();
|
||||
|
||||
uint8_t sitePasswordSeed[32];
|
||||
HMAC_SHA256_Buf(masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoLength, sitePasswordSeed);
|
||||
memset(masterKey, 0, MP_dkLen);
|
||||
memset(sitePasswordInfo, 0, sitePasswordInfoLength);
|
||||
free(masterKey);
|
||||
free(sitePasswordInfo);
|
||||
|
||||
// Determine the cipher.
|
||||
const char *cipher = CipherForType(siteType, sitePasswordSeed[0]);
|
||||
trc("type %d, cipher: %s\n", siteType, cipher);
|
||||
if (strlen(cipher) > 32)
|
||||
abort();
|
||||
|
||||
// Encode the password from the seed using the cipher.
|
||||
char *sitePassword = calloc(strlen(cipher) + 1, sizeof(char));
|
||||
for (int c = 0; c < strlen(cipher); ++c) {
|
||||
sitePassword[c] = CharacterFromClass(cipher[c], sitePasswordSeed[c + 1]);
|
||||
trc("class %c, character: %c\n", cipher[c], sitePassword[c]);
|
||||
}
|
||||
memset(sitePasswordSeed, 0, sizeof(sitePasswordSeed));
|
||||
|
||||
if (i % 1 == 0)
|
||||
fprintf( stderr, "\rmpw: iteration %d / %d..", i, iterations );
|
||||
}
|
||||
|
||||
// Output timing results.
|
||||
struct timeval endTime;
|
||||
if (gettimeofday(&endTime, NULL) != 0) {
|
||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
long long secs = (endTime.tv_sec - startTime.tv_sec);
|
||||
long long usecs = (endTime.tv_usec - startTime.tv_usec);
|
||||
double elapsed = secs + usecs / 1000000.0;
|
||||
double mpwSpeed = iterations / elapsed;
|
||||
fprintf( stdout, " done. %d iterations in %llds %lldµs -> %.2f/s\n", iterations, secs, usecs, mpwSpeed );
|
||||
|
||||
// Start SHA-256
|
||||
if (gettimeofday(&startTime, NULL) != 0) {
|
||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
iterations = 50000000;
|
||||
uint8_t hash[32];
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
SHA256_Buf(masterPassword, strlen(masterPassword), hash);
|
||||
|
||||
if (i % 1000 == 0)
|
||||
fprintf( stderr, "\rsha256: iteration %d / %d..", i, iterations );
|
||||
}
|
||||
|
||||
// Output timing results.
|
||||
if (gettimeofday(&endTime, NULL) != 0) {
|
||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
secs = (endTime.tv_sec - startTime.tv_sec);
|
||||
usecs = (endTime.tv_usec - startTime.tv_usec);
|
||||
elapsed = secs + usecs / 1000000.0;
|
||||
double sha256Speed = iterations / elapsed;
|
||||
fprintf( stdout, " done. %d iterations in %llds %lldµs -> %.2f/s\n", iterations, secs, usecs, sha256Speed );
|
||||
|
||||
// Start BCrypt
|
||||
if (gettimeofday(&startTime, NULL) != 0) {
|
||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bcrypt_cost = 9;
|
||||
iterations = 600;
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
crypt(masterPassword, crypt_gensalt("$2b$", bcrypt_cost, userName, strlen(userName)));
|
||||
|
||||
if (i % 10 == 0)
|
||||
fprintf( stderr, "\rbcrypt (cost %d): iteration %d / %d..", bcrypt_cost, i, iterations );
|
||||
}
|
||||
|
||||
// Output timing results.
|
||||
if (gettimeofday(&endTime, NULL) != 0) {
|
||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
secs = (endTime.tv_sec - startTime.tv_sec);
|
||||
usecs = (endTime.tv_usec - startTime.tv_usec);
|
||||
elapsed = secs + usecs / 1000000.0;
|
||||
double bcrypt9Speed = iterations / elapsed;
|
||||
fprintf( stdout, " done. %d iterations in %llds %lldµs -> %.2f/s\n", iterations, secs, usecs, bcrypt9Speed );
|
||||
|
||||
// Summarize.
|
||||
fprintf( stdout, "\n== SUMMARY ==\nOn this machine,\n" );
|
||||
fprintf( stdout, "mpw is %f times slower than sha256\n", sha256Speed / mpwSpeed );
|
||||
fprintf( stdout, "mpw is %f times slower than bcrypt (cost 9)\n", bcrypt9Speed / mpwSpeed );
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
#define _WITH_GETLINE
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
@@ -23,6 +24,12 @@
|
||||
#include <crypto/crypto_scrypt.h>
|
||||
#include "types.h"
|
||||
|
||||
#if defined(READLINE)
|
||||
#include <readline/readline.h>
|
||||
#elif defined(EDITLINE)
|
||||
#include <histedit.h>
|
||||
#endif
|
||||
|
||||
#define MP_N 32768
|
||||
#define MP_r 8
|
||||
#define MP_p 2
|
||||
@@ -52,7 +59,14 @@ void usage() {
|
||||
fprintf(stderr, " -v variant The kind of content to generate.\n"
|
||||
" Defaults to 'password'.\n"
|
||||
" p, password | The password to log in with.\n"
|
||||
" l, login | The username to log in as.\n\n");
|
||||
" l, login | The username to log in as.\n"
|
||||
" a, answer | The answer to a security question.\n\n");
|
||||
fprintf(stderr, " -C context A variant-specific context.\n"
|
||||
" Defaults to empty.\n"
|
||||
" -v p, password | Doesn't currently use a context.\n"
|
||||
" -v l, login | Doesn't currently use a context.\n"
|
||||
" -v a, answer | Empty for a universal site answer or\n"
|
||||
" | the most significant word(s) of the question.\n\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -94,27 +108,30 @@ int main(int argc, char *const argv[]) {
|
||||
const char *siteTypeString = getenv( MP_env_sitetype );
|
||||
MPElementVariant siteVariant = MPElementVariantPassword;
|
||||
const char *siteVariantString = NULL;
|
||||
const char *siteContextString = NULL;
|
||||
uint32_t siteCounter = 1;
|
||||
const char *siteCounterString = getenv( MP_env_sitecounter );
|
||||
|
||||
// Read the options.
|
||||
char opt;
|
||||
while ((opt = getopt(argc, argv, "u:t:c:v:h")) != -1)
|
||||
for (int opt; (opt = getopt(argc, argv, "u:t:c:v:C:h")) != -1;)
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
usage();
|
||||
break;
|
||||
case 'u':
|
||||
userName = optarg;
|
||||
break;
|
||||
case 't':
|
||||
siteTypeString = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
siteCounterString = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
siteVariantString = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
siteCounterString = optarg;
|
||||
case 'C':
|
||||
siteContextString = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
break;
|
||||
case '?':
|
||||
switch (optopt) {
|
||||
@@ -160,6 +177,8 @@ int main(int argc, char *const argv[]) {
|
||||
trc("siteVariant: %d (%s)\n", siteVariant, siteVariantString);
|
||||
if (siteVariant == MPElementVariantLogin)
|
||||
siteType = MPElementTypeGeneratedName;
|
||||
if (siteVariant == MPElementVariantAnswer)
|
||||
siteType = MPElementTypeGeneratedPhrase;
|
||||
if (siteTypeString)
|
||||
siteType = TypeWithName( siteTypeString );
|
||||
trc("siteType: %d (%s)\n", siteType, siteTypeString);
|
||||
@@ -172,31 +191,27 @@ int main(int argc, char *const argv[]) {
|
||||
}
|
||||
trc("mpwConfigPath: %s\n", mpwConfigPath);
|
||||
FILE *mpwConfig = fopen(mpwConfigPath, "r");
|
||||
if (!mpwConfig) {
|
||||
fprintf(stderr, "Couldn't open configuration file: %s: %d\n", mpwConfigPath, errno);
|
||||
return 1;
|
||||
}
|
||||
free(mpwConfigPath);
|
||||
char *line = NULL;
|
||||
size_t linecap = 0;
|
||||
ssize_t linelen;
|
||||
while ((linelen = getline(&line, &linecap, mpwConfig)) > 0)
|
||||
if (strcmp(strsep(&line, ":"), userName) == 0) {
|
||||
masterPassword = strsep(&line, "\n");
|
||||
break;
|
||||
}
|
||||
if (!masterPassword) {
|
||||
fprintf(stderr, "Missing master password for user: %s\n", userName);
|
||||
return 1;
|
||||
if (mpwConfig) {
|
||||
char *line = NULL;
|
||||
size_t linecap = 0;
|
||||
ssize_t linelen;
|
||||
while ((linelen = getline(&line, &linecap, mpwConfig)) > 0)
|
||||
if (strcmp(strsep(&line, ":"), userName) == 0) {
|
||||
masterPassword = strsep(&line, "\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!masterPassword)
|
||||
masterPassword = getpass( "Your master password: " );
|
||||
trc("masterPassword: %s\n", masterPassword);
|
||||
|
||||
// Calculate the master key salt.
|
||||
const char *mpKeyScope = ScopeForVariant(MPElementVariantPassword);
|
||||
trc("key scope: %s\n", mpKeyScope);
|
||||
const uint32_t n_userNameLength = htonl(strlen(userName));
|
||||
size_t masterKeySaltLength = strlen(mpKeyScope) + sizeof(n_userNameLength) + strlen(userName);
|
||||
char *masterKeySalt = malloc( masterKeySaltLength );
|
||||
const size_t masterKeySaltLength = strlen(mpKeyScope) + sizeof(n_userNameLength) + strlen(userName);
|
||||
char *masterKeySalt = (char *)malloc( masterKeySaltLength );
|
||||
if (!masterKeySalt) {
|
||||
fprintf(stderr, "Could not allocate master key salt: %d\n", errno);
|
||||
return 1;
|
||||
@@ -211,7 +226,7 @@ int main(int argc, char *const argv[]) {
|
||||
trc("masterKeySalt ID: %s\n", IDForBuf(masterKeySalt, masterKeySaltLength));
|
||||
|
||||
// Calculate the master key.
|
||||
uint8_t *masterKey = malloc( MP_dkLen );
|
||||
uint8_t *masterKey = (uint8_t *)malloc( MP_dkLen );
|
||||
if (!masterKey) {
|
||||
fprintf(stderr, "Could not allocate master key: %d\n", errno);
|
||||
return 1;
|
||||
@@ -228,11 +243,14 @@ int main(int argc, char *const argv[]) {
|
||||
|
||||
// Calculate the site seed.
|
||||
const char *mpSiteScope = ScopeForVariant(siteVariant);
|
||||
trc("site scope: %s\n", mpSiteScope);
|
||||
trc("site scope: %s, context: %s\n", mpSiteScope, siteContextString == NULL? "<empty>": siteContextString);
|
||||
const uint32_t n_siteNameLength = htonl(strlen(siteName));
|
||||
const uint32_t n_siteCounter = htonl(siteCounter);
|
||||
const uint32_t n_siteContextLength = siteContextString == NULL? 0: htonl(strlen(siteContextString));
|
||||
size_t sitePasswordInfoLength = strlen(mpSiteScope) + sizeof(n_siteNameLength) + strlen(siteName) + sizeof(n_siteCounter);
|
||||
char *sitePasswordInfo = malloc( sitePasswordInfoLength );
|
||||
if (siteContextString)
|
||||
sitePasswordInfoLength += sizeof(n_siteContextLength) + strlen(siteContextString);
|
||||
char *sitePasswordInfo = (char *)malloc( sitePasswordInfoLength );
|
||||
if (!sitePasswordInfo) {
|
||||
fprintf(stderr, "Could not allocate site seed: %d\n", errno);
|
||||
return 1;
|
||||
@@ -243,9 +261,13 @@ int main(int argc, char *const argv[]) {
|
||||
memcpy(sPI, &n_siteNameLength, sizeof(n_siteNameLength)); sPI += sizeof(n_siteNameLength);
|
||||
memcpy(sPI, siteName, strlen(siteName)); sPI += strlen(siteName);
|
||||
memcpy(sPI, &n_siteCounter, sizeof(n_siteCounter)); sPI += sizeof(n_siteCounter);
|
||||
if (siteContextString) {
|
||||
memcpy(sPI, &n_siteContextLength, sizeof(n_siteContextLength)); sPI += sizeof(n_siteContextLength);
|
||||
memcpy(sPI, siteContextString, strlen(siteContextString)); sPI += strlen(siteContextString);
|
||||
}
|
||||
if (sPI - sitePasswordInfo != sitePasswordInfoLength)
|
||||
abort();
|
||||
trc("seed from: hmac-sha256(masterKey, %s | %s | %s | %s)\n", mpSiteScope, Hex(&n_siteNameLength, sizeof(n_siteNameLength)), siteName, Hex(&n_siteCounter, sizeof(n_siteCounter)));
|
||||
trc("seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n", mpSiteScope, Hex(&n_siteNameLength, sizeof(n_siteNameLength)), siteName, Hex(&n_siteCounter, sizeof(n_siteCounter)), Hex(&n_siteContextLength, sizeof(n_siteContextLength)), siteContextString);
|
||||
trc("sitePasswordInfo ID: %s\n", IDForBuf(sitePasswordInfo, sitePasswordInfoLength));
|
||||
|
||||
uint8_t sitePasswordSeed[32];
|
||||
@@ -263,7 +285,7 @@ int main(int argc, char *const argv[]) {
|
||||
abort();
|
||||
|
||||
// Encode the password from the seed using the cipher.
|
||||
char *sitePassword = calloc(strlen(cipher) + 1, sizeof(char));
|
||||
char *sitePassword = (char *)calloc(strlen(cipher) + 1, sizeof(char));
|
||||
for (int c = 0; c < strlen(cipher); ++c) {
|
||||
sitePassword[c] = CharacterFromClass(cipher[c], sitePasswordSeed[c + 1]);
|
||||
trc("class %c, character: %c\n", cipher[c], sitePassword[c]);
|
||||
|
||||
@@ -50,19 +50,19 @@ const char *CipherForType(MPElementType type, uint8_t seedByte) {
|
||||
|
||||
switch (type) {
|
||||
case MPElementTypeGeneratedMaximum: {
|
||||
char *ciphers[] = { "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" };
|
||||
const char *ciphers[] = { "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" };
|
||||
return ciphers[seedByte % 2];
|
||||
}
|
||||
case MPElementTypeGeneratedLong: {
|
||||
char *ciphers[] = { "CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno", "CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno", "CvcvnoCvccCvcv", "CvcvCvccnoCvcv", "CvcvCvccCvcvno", "CvcvnoCvcvCvcc", "CvcvCvcvnoCvcc", "CvcvCvcvCvccno", "CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno", "CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno", "CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno" };
|
||||
const char *ciphers[] = { "CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno", "CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno", "CvcvnoCvccCvcv", "CvcvCvccnoCvcv", "CvcvCvccCvcvno", "CvcvnoCvcvCvcc", "CvcvCvcvnoCvcc", "CvcvCvcvCvccno", "CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno", "CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno", "CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno" };
|
||||
return ciphers[seedByte % 21];
|
||||
}
|
||||
case MPElementTypeGeneratedMedium: {
|
||||
char *ciphers[] = { "CvcnoCvc", "CvcCvcno" };
|
||||
const char *ciphers[] = { "CvcnoCvc", "CvcCvcno" };
|
||||
return ciphers[seedByte % 2];
|
||||
}
|
||||
case MPElementTypeGeneratedBasic: {
|
||||
char *ciphers[] = { "aaanaaan", "aannaaan", "aaannaaa" };
|
||||
const char *ciphers[] = { "aaanaaan", "aannaaan", "aaannaaa" };
|
||||
return ciphers[seedByte % 3];
|
||||
}
|
||||
case MPElementTypeGeneratedShort: {
|
||||
@@ -75,7 +75,7 @@ const char *CipherForType(MPElementType type, uint8_t seedByte) {
|
||||
return "cvccvcvcv";
|
||||
}
|
||||
case MPElementTypeGeneratedPhrase: {
|
||||
char *ciphers[] = { "cvcc cvc cvccvcv cvc", "cvc cvccvcvcv cvcv", "cv cvccv cvc cvcvccv" };
|
||||
const char *ciphers[] = { "cvcc cvc cvccvcv cvc", "cvc cvccvcvcv cvcv", "cv cvccv cvc cvcvccv" };
|
||||
return ciphers[seedByte % 3];
|
||||
}
|
||||
default: {
|
||||
@@ -95,6 +95,8 @@ const MPElementVariant VariantWithName(const char *variantName) {
|
||||
return MPElementVariantPassword;
|
||||
if (0 == strcmp(lowerVariantName, "l") || 0 == strcmp(lowerVariantName, "login"))
|
||||
return MPElementVariantLogin;
|
||||
if (0 == strcmp(lowerVariantName, "a") || 0 == strcmp(lowerVariantName, "answer"))
|
||||
return MPElementVariantAnswer;
|
||||
|
||||
fprintf(stderr, "Not a variant name: %s", lowerVariantName);
|
||||
abort();
|
||||
@@ -108,6 +110,9 @@ const char *ScopeForVariant(MPElementVariant variant) {
|
||||
case MPElementVariantLogin: {
|
||||
return "com.lyndir.masterpassword.login";
|
||||
}
|
||||
case MPElementVariantAnswer: {
|
||||
return "com.lyndir.masterpassword.answer";
|
||||
}
|
||||
default: {
|
||||
fprintf(stderr, "Unknown variant: %d", variant);
|
||||
abort();
|
||||
@@ -170,7 +175,7 @@ const char *IDForBuf(const void *buf, size_t length) {
|
||||
uint8_t hash[32];
|
||||
SHA256_Buf(buf, length, hash);
|
||||
|
||||
char *id = calloc(65, sizeof(char));
|
||||
char *id = (char *)calloc(65, sizeof(char));
|
||||
for (int kH = 0; kH < 32; kH++)
|
||||
sprintf(&(id[kH * 2]), "%02X", hash[kH]);
|
||||
|
||||
@@ -178,7 +183,7 @@ const char *IDForBuf(const void *buf, size_t length) {
|
||||
}
|
||||
|
||||
const char *Hex(const void *buf, size_t length) {
|
||||
char *id = calloc(length*2+1, sizeof(char));
|
||||
char *id = (char *)calloc(length*2+1, sizeof(char));
|
||||
for (int kH = 0; kH < length; kH++)
|
||||
sprintf(&(id[kH * 2]), "%02X", ((const uint8_t*)buf)[kH]);
|
||||
return id;
|
||||
|
||||
@@ -11,6 +11,8 @@ typedef enum {
|
||||
MPElementVariantPassword,
|
||||
/** Generate the login name to log in as. */
|
||||
MPElementVariantLogin,
|
||||
/** Generate the answer to a security question. */
|
||||
MPElementVariantAnswer,
|
||||
} MPElementVariant;
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -139,9 +139,9 @@ PearlAssociatedObjectProperty( NSMutableArray*, ProductObservers, productObserve
|
||||
case SKPaymentTransactionStatePurchased: {
|
||||
inf( @"purchased: %@", transaction.payment.productIdentifier );
|
||||
if ([transaction.payment.productIdentifier isEqualToString:MPProductFuel]) {
|
||||
float currentFuel = [[MPiOSConfig get].developmentFuel floatValue];
|
||||
float currentFuel = [[MPiOSConfig get].developmentFuelRemaining floatValue];
|
||||
float purchasedFuel = transaction.payment.quantity / MP_FUEL_HOURLY_RATE;
|
||||
[MPiOSConfig get].developmentFuel = @(currentFuel + purchasedFuel);
|
||||
[MPiOSConfig get].developmentFuelRemaining = @(currentFuel + purchasedFuel);
|
||||
if (![MPiOSConfig get].developmentFuelChecked || !currentFuel)
|
||||
[MPiOSConfig get].developmentFuelChecked = [NSDate date];
|
||||
}
|
||||
|
||||
@@ -41,6 +41,6 @@
|
||||
@property(nonatomic) IBOutlet UITextField *questionField;
|
||||
@property(nonatomic) IBOutlet UITextField *answerField;
|
||||
|
||||
- (void)setQuestion:(MPSiteQuestionEntity *)question forSite:(MPSiteEntity *)site;
|
||||
- (void)setQuestion:(MPSiteQuestionEntity *)question forSite:(MPSiteEntity *)site inVC:(MPAnswersViewController *)VC;
|
||||
|
||||
@end
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
if (!_multiple)
|
||||
return 0;
|
||||
|
||||
return MAX( 2, [[self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]].questions count] );
|
||||
return [[self siteInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]].questions count] + 1;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
@@ -118,7 +118,7 @@
|
||||
MPSiteQuestionEntity *question = nil;
|
||||
if ([site.questions count] > indexPath.item)
|
||||
question = site.questions[indexPath.item];
|
||||
[cell setQuestion:question forSite:site];
|
||||
[cell setQuestion:question forSite:site inVC:self];
|
||||
|
||||
return cell;
|
||||
}
|
||||
@@ -217,6 +217,17 @@
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)didAddQuestion:(MPSiteQuestionEntity *)question toSite:(MPSiteEntity *)site {
|
||||
|
||||
NSUInteger newQuestionRow = [site.questions count];
|
||||
PearlMainQueue( ^{
|
||||
[self.tableView beginUpdates];
|
||||
[self.tableView insertRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:newQuestionRow inSection:1] ]
|
||||
withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
[self.tableView endUpdates];
|
||||
} );
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPGlobalAnswersCell
|
||||
@@ -247,14 +258,16 @@
|
||||
@implementation MPAnswersQuestionCell {
|
||||
NSManagedObjectID *_siteOID;
|
||||
NSManagedObjectID *_questionOID;
|
||||
__weak MPAnswersViewController *_answersVC;
|
||||
}
|
||||
|
||||
#pragma mark - State
|
||||
|
||||
- (void)setQuestion:(MPSiteQuestionEntity *)question forSite:(MPSiteEntity *)site {
|
||||
- (void)setQuestion:(MPSiteQuestionEntity *)question forSite:(MPSiteEntity *)site inVC:(MPAnswersViewController *)answersVC {
|
||||
|
||||
_siteOID = site.objectID;
|
||||
_questionOID = question.objectID;
|
||||
_answersVC = answersVC;
|
||||
|
||||
[self updateAnswerForQuestion:question ofSite:site];
|
||||
}
|
||||
@@ -272,9 +285,11 @@
|
||||
|
||||
NSString *keyword = textField.text;
|
||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
BOOL didAddQuestionObject = NO;
|
||||
MPSiteEntity *site = [MPSiteEntity existingObjectWithID:_siteOID inContext:context];
|
||||
MPSiteQuestionEntity *question = [MPSiteQuestionEntity existingObjectWithID:_questionOID inContext:context];
|
||||
if (!question) {
|
||||
didAddQuestionObject = YES;
|
||||
[site addQuestionsObject:question = [MPSiteQuestionEntity insertNewObjectInContext:context]];
|
||||
question.site = site;
|
||||
}
|
||||
@@ -291,6 +306,9 @@
|
||||
|
||||
_questionOID = question.objectID;
|
||||
[self updateAnswerForQuestion:question ofSite:site];
|
||||
|
||||
if (didAddQuestionObject)
|
||||
[_answersVC didAddQuestion:question toSite:site];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ const long MPAvatarAdd = 10000;
|
||||
@property(strong, nonatomic) IBOutlet NSLayoutConstraint *avatarSizeConstraint;
|
||||
@property(strong, nonatomic) IBOutlet NSLayoutConstraint *avatarToTopConstraint;
|
||||
@property(strong, nonatomic) IBOutlet NSLayoutConstraint *avatarRaisedConstraint;
|
||||
@property(strong, nonatomic) IBOutlet NSLayoutConstraint *keyboardHeightConstraint;
|
||||
|
||||
@end
|
||||
|
||||
@@ -66,6 +67,12 @@ const long MPAvatarAdd = 10000;
|
||||
[self observeKeyPath:@"highlighted" withBlock:^(id from, id to, NSKeyValueChange cause, MPAvatarCell *_self) {
|
||||
[_self updateAnimated:_self.superview != nil];
|
||||
}];
|
||||
PearlAddNotificationObserver( UIKeyboardWillShowNotification, nil, [NSOperationQueue mainQueue],
|
||||
^(MPAvatarCell *self, NSNotification *note) {
|
||||
CGRect keyboardRect = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
|
||||
CGFloat keyboardHeight = CGRectGetHeight( self.window.screen.bounds ) - CGRectGetMinY( keyboardRect );
|
||||
[self.keyboardHeightConstraint updateConstant:keyboardHeight];
|
||||
} );
|
||||
|
||||
CABasicAnimation *toShadowOpacityAnimation = [CABasicAnimation animationWithKeyPath:@"shadowOpacity"];
|
||||
toShadowOpacityAnimation.toValue = @0.2f;
|
||||
@@ -99,6 +106,7 @@ const long MPAvatarAdd = 10000;
|
||||
- (void)dealloc {
|
||||
|
||||
[self removeKeyPathObservers];
|
||||
PearlRemoveNotificationObservers();
|
||||
}
|
||||
|
||||
#pragma mark - Properties
|
||||
@@ -264,7 +272,7 @@ const long MPAvatarAdd = 10000;
|
||||
case MPAvatarModeRaisedAndMinimized: {
|
||||
[self.avatarSizeConstraint updateConstant:36];
|
||||
[self.avatarRaisedConstraint updatePriority:UILayoutPriorityDefaultLow];
|
||||
[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultHigh];
|
||||
[self.avatarToTopConstraint updatePriority:UILayoutPriorityDefaultHigh + 2];
|
||||
[self.nameToCenterConstraint updatePriority:UILayoutPriorityDefaultHigh];
|
||||
self.nameContainer.alpha = 0;
|
||||
self.nameContainer.backgroundColor = [UIColor blackColor];
|
||||
|
||||
@@ -516,7 +516,7 @@
|
||||
TimeToCrack timeToCrack;
|
||||
NSString *timeToCrackString = nil;
|
||||
id<MPAlgorithm> algorithm = site.algorithm?: MPAlgorithmDefault;
|
||||
MPAttacker attackHardware = [[MPConfig get].siteAttacker unsignedIntegerValue];
|
||||
MPAttacker attackHardware = [[MPConfig get].siteAttacker integerValue];
|
||||
if ([algorithm timeToCrack:&timeToCrack passwordOfType:site.type byAttacker:attackHardware] ||
|
||||
[algorithm timeToCrack:&timeToCrack passwordString:password byAttacker:attackHardware])
|
||||
timeToCrackString = NSStringFromTimeToCrack( timeToCrack );
|
||||
|
||||
@@ -63,10 +63,14 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
||||
|
||||
self.view.backgroundColor = [UIColor clearColor];
|
||||
[self.passwordCollectionView automaticallyAdjustInsetsForKeyboard];
|
||||
[self.passwordsSearchBar enumerateViews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
|
||||
if ([subview isKindOfClass:[UITextField class]])
|
||||
((UITextField *)subview).keyboardAppearance = UIKeyboardAppearanceDark;
|
||||
} recurse:YES];
|
||||
self.passwordsSearchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
|
||||
if ([self.passwordsSearchBar respondsToSelector:@selector(keyboardAppearance)])
|
||||
self.passwordsSearchBar.keyboardAppearance = UIKeyboardAppearanceDark;
|
||||
else
|
||||
[self.passwordsSearchBar enumerateViews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
|
||||
if ([subview isKindOfClass:[UITextField class]])
|
||||
((UITextField *)subview).keyboardAppearance = UIKeyboardAppearanceDark;
|
||||
} recurse:YES];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
@property(weak, nonatomic) IBOutlet UITableViewCell *loadingCell;
|
||||
@property(weak, nonatomic) IBOutlet NSLayoutConstraint *fuelMeterConstraint;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *fuelSpeedButton;
|
||||
@property(weak, nonatomic) IBOutlet UILabel *fuelStatusLabel;
|
||||
|
||||
+ (NSString *)latestStoreFeatures;
|
||||
|
||||
|
||||
@@ -82,16 +82,21 @@ PearlEnum( MPDevelopmentFuelConsumption,
|
||||
PearlRemoveNotificationObservers();
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDelegate
|
||||
#pragma mark - UITableViewDataSource
|
||||
|
||||
- (MPStoreProductCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
MPStoreProductCell *cell = (MPStoreProductCell *)[super tableView:tableView cellForRowAtIndexPath:indexPath];
|
||||
if (cell.contentView.translatesAutoresizingMaskIntoConstraints) {
|
||||
cell.contentView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[cell addConstraint:
|
||||
[NSLayoutConstraint constraintWithItem:cell attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual
|
||||
toItem:cell.contentView attribute:NSLayoutAttributeWidth multiplier:1 constant:0]];
|
||||
[cell addConstraints:@[
|
||||
[NSLayoutConstraint constraintWithItem:cell attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
|
||||
toItem:cell.contentView attribute:NSLayoutAttributeTop multiplier:1 constant:0],
|
||||
[NSLayoutConstraint constraintWithItem:cell attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual
|
||||
toItem:cell.contentView attribute:NSLayoutAttributeRight multiplier:1 constant:0],
|
||||
[NSLayoutConstraint constraintWithItem:cell attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual
|
||||
toItem:cell.contentView attribute:NSLayoutAttributeLeft multiplier:1 constant:0],
|
||||
]];
|
||||
}
|
||||
|
||||
if (indexPath.section == 0)
|
||||
@@ -106,13 +111,20 @@ PearlEnum( MPDevelopmentFuelConsumption,
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDelegate
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
|
||||
[cell layoutIfNeeded];
|
||||
[cell layoutIfNeeded];
|
||||
|
||||
dbg_return_tr( cell.contentView.bounds.size.height, @ );
|
||||
dbg_return_tr( cell.contentView.bounds.size.height, @, indexPath );
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
@@ -252,18 +264,24 @@ PearlEnum( MPDevelopmentFuelConsumption,
|
||||
- (void)updateFuel {
|
||||
|
||||
CGFloat weeklyFuelConsumption = [self weeklyFuelConsumption]; /* consume x fuel / week */
|
||||
CGFloat fuel = [[MPiOSConfig get].developmentFuel floatValue]; /* x fuel left */
|
||||
CGFloat fuelRemaining = [[MPiOSConfig get].developmentFuelRemaining floatValue]; /* x fuel left */
|
||||
CGFloat fuelInvested = [[MPiOSConfig get].developmentFuelInvested floatValue]; /* x fuel left */
|
||||
NSDate *now = [NSDate date];
|
||||
NSTimeInterval fuelSecondsElapsed = -[[MPiOSConfig get].developmentFuelChecked timeIntervalSinceDate:now];
|
||||
if (fuelSecondsElapsed > 3600 || ![MPiOSConfig get].developmentFuelChecked) {
|
||||
NSTimeInterval weeksElapsed = fuelSecondsElapsed / (3600 * 24 * 7 /* 1 week */); /* x weeks elapsed */
|
||||
fuel -= weeklyFuelConsumption * weeksElapsed;
|
||||
NSTimeInterval fuelConsumed = weeklyFuelConsumption * weeksElapsed;
|
||||
fuelRemaining -= fuelConsumed;
|
||||
fuelInvested += fuelConsumed;
|
||||
[MPiOSConfig get].developmentFuelChecked = now;
|
||||
[MPiOSConfig get].developmentFuel = @(fuel);
|
||||
[MPiOSConfig get].developmentFuelRemaining = @(fuelRemaining);
|
||||
[MPiOSConfig get].developmentFuelInvested = @(fuelInvested);
|
||||
}
|
||||
|
||||
CGFloat fuelRatio = weeklyFuelConsumption == 0? 0: fuel / weeklyFuelConsumption; /* x weeks worth of fuel left */
|
||||
CGFloat fuelRatio = weeklyFuelConsumption == 0? 0: fuelRemaining / weeklyFuelConsumption; /* x weeks worth of fuel left */
|
||||
[self.fuelMeterConstraint updateConstant:MIN( 0.5f, fuelRatio - 0.5f ) * 160]; /* -80pt = 0 weeks left, 80pt = >=1 week left */
|
||||
self.fuelStatusLabel.text = strf( @"fuel left: %0.1f work hours\ninvested: %0.1f work hours", fuelRemaining, fuelInvested );
|
||||
self.fuelStatusLabel.hidden = (fuelRemaining + fuelInvested) == 0;
|
||||
}
|
||||
|
||||
- (CGFloat)weeklyFuelConsumption {
|
||||
@@ -302,7 +320,7 @@ PearlEnum( MPDevelopmentFuelConsumption,
|
||||
- (NSInteger)quantityForProductIdentifier:(NSString *)productIdentifier {
|
||||
|
||||
if ([productIdentifier isEqualToString:MPProductFuel])
|
||||
return (NSInteger)(MP_FUEL_HOURLY_RATE * [self weeklyFuelConsumption]);
|
||||
return (NSInteger)(MP_FUEL_HOURLY_RATE * [self weeklyFuelConsumption] + .5f);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
@property(weak, nonatomic) IBOutlet UIView *thanksTipContainer;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *nextAvatarButton;
|
||||
@property(weak, nonatomic) IBOutlet UIButton *previousAvatarButton;
|
||||
@property(weak, nonatomic) IBOutlet NSLayoutConstraint *keyboardHeightConstraint;
|
||||
|
||||
@property(assign, nonatomic, readonly) BOOL active;
|
||||
|
||||
|
||||
@@ -649,6 +649,12 @@ referenceSizeForFooterInSection:(NSInteger)section {
|
||||
self.userSelectionContainer.alpha = 1;
|
||||
}];
|
||||
} );
|
||||
PearlAddNotificationObserver( UIKeyboardWillShowNotification, nil, [NSOperationQueue mainQueue],
|
||||
^(MPUsersViewController *self, NSNotification *note) {
|
||||
CGRect keyboardRect = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
|
||||
CGFloat keyboardHeight = CGRectGetHeight( self.view.window.screen.bounds ) - CGRectGetMinY( keyboardRect );
|
||||
[self.keyboardHeightConstraint updateConstant:keyboardHeight];
|
||||
} );
|
||||
|
||||
NSManagedObjectContext *mainContext = [MPiOSAppDelegate managedObjectContextForMainThreadIfReady];
|
||||
[UIView animateWithDuration:0.3f animations:^{
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
@property(nonatomic, retain) NSNumber *loginNameTipShown;
|
||||
@property(nonatomic, retain) NSNumber *traceMode;
|
||||
@property(nonatomic, retain) NSNumber *dictationSearch;
|
||||
@property(nonatomic, retain) NSNumber *developmentFuel;
|
||||
@property(nonatomic, retain) NSNumber *developmentFuelRemaining;
|
||||
@property(nonatomic, retain) NSNumber *developmentFuelInvested;
|
||||
@property(nonatomic, retain) NSNumber *developmentFuelConsumption;
|
||||
@property(nonatomic, retain) NSDate *developmentFuelChecked;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
@implementation MPiOSConfig
|
||||
|
||||
@dynamic helpHidden, siteInfoHidden, showSetup, actionsTipShown, typeTipShown, loginNameTipShown, traceMode, dictationSearch;
|
||||
@dynamic developmentFuel, developmentFuelConsumption, developmentFuelChecked;
|
||||
@dynamic developmentFuelRemaining, developmentFuelInvested, developmentFuelConsumption, developmentFuelChecked;
|
||||
|
||||
- (id)init {
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
<string>mpsites</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFiles</key>
|
||||
<array/>
|
||||
<array>
|
||||
<string>Icon-Small</string>
|
||||
</array>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Master Password sites</string>
|
||||
<key>LSHandlerRank</key>
|
||||
@@ -44,7 +46,7 @@
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>© 2011-2013, Lyndir</string>
|
||||
<string>© 2011-2014, Lyndir</string>
|
||||
<key>UIAppFonts</key>
|
||||
<array>
|
||||
<string>Exo2.0-Bold.otf</string>
|
||||
@@ -105,9 +107,9 @@
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>com.lyndir.masterpassword.sites</string>
|
||||
<key>UTTypeSize320IconFile</key>
|
||||
<string></string>
|
||||
<string>Icon-320.png</string>
|
||||
<key>UTTypeSize64IconFile</key>
|
||||
<string></string>
|
||||
<string>Icon-64.png</string>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
|
||||
@@ -58,6 +58,13 @@
|
||||
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 */; };
|
||||
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 */; };
|
||||
DA24EBE919DAD6DE00FF010B /* Icon-64.png in Resources */ = {isa = PBXBuildFile; fileRef = DA24EBE719DAD6DE00FF010B /* Icon-64.png */; };
|
||||
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 */; };
|
||||
DA250A19195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m in Sources */ = {isa = PBXBuildFile; fileRef = DA250A15195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m */; };
|
||||
@@ -172,8 +179,6 @@
|
||||
DAA175F519D86C620044227B /* markdown_lib.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA175B719D86C620044227B /* markdown_lib.m */; };
|
||||
DAA175F619D86C620044227B /* markdown_output.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA175B819D86C620044227B /* markdown_output.m */; };
|
||||
DAA175F719D86C620044227B /* markdown_parser.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA175BA19D86C620044227B /* markdown_parser.m */; };
|
||||
DAA1760F19D86C620044227B /* README.markdown in Sources */ = {isa = PBXBuildFile; fileRef = DAA175ED19D86C620044227B /* README.markdown */; };
|
||||
DAA1761019D86C620044227B /* README_PEG-MARKDWON.markdown in Sources */ = {isa = PBXBuildFile; fileRef = DAA175EE19D86C620044227B /* README_PEG-MARKDWON.markdown */; };
|
||||
DAA1761B19D86D0D0044227B /* libAttributedMarkdown.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAA1757D19D86BE70044227B /* libAttributedMarkdown.a */; };
|
||||
DAA1762319D89B600044227B /* thumb_touch_id@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DAA1761D19D89B600044227B /* thumb_touch_id@3x.png */; };
|
||||
DAA1762419D89B610044227B /* thumb_touch_id@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DAA1761E19D89B600044227B /* thumb_touch_id@2x.png */; };
|
||||
@@ -521,6 +526,32 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
DA24EBB519DAD4D000FF010B /* Icon-76.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-76.png"; sourceTree = "<group>"; };
|
||||
DA24EBB619DAD4D000FF010B /* Icon-76@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-76@2x.png"; sourceTree = "<group>"; };
|
||||
DA24EBB719DAD4D000FF010B /* Icon-Small-40.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-40.png"; sourceTree = "<group>"; };
|
||||
DA24EBB819DAD4D000FF010B /* Icon-Small-40@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-40@2x.png"; sourceTree = "<group>"; };
|
||||
DA24EBB919DAD4D000FF010B /* Icon-Small-40@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-40@3x.png"; sourceTree = "<group>"; };
|
||||
DA24EBBA19DAD4D000FF010B /* Icon-Small.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small.png"; sourceTree = "<group>"; };
|
||||
DA24EBBB19DAD4D000FF010B /* Icon-Small@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small@2x.png"; sourceTree = "<group>"; };
|
||||
DA24EBBC19DAD4D000FF010B /* Icon-Small@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small@3x.png"; sourceTree = "<group>"; };
|
||||
DA24EBBD19DAD4D000FF010B /* iTunesArtwork.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = iTunesArtwork.png; sourceTree = "<group>"; };
|
||||
DA24EBBE19DAD4D000FF010B /* iTunesArtwork@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iTunesArtwork@2x.png"; sourceTree = "<group>"; };
|
||||
DA24EBBF19DAD4D000FF010B /* icon.sketch */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = icon.sketch; sourceTree = "<group>"; };
|
||||
DA24EBC119DAD4D000FF010B /* 32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = 32.png; sourceTree = "<group>"; };
|
||||
DA24EBC219DAD4D000FF010B /* 320-480.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "320-480.png"; sourceTree = "<group>"; };
|
||||
DA24EBC319DAD4D000FF010B /* 320-480@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "320-480@2x.png"; sourceTree = "<group>"; };
|
||||
DA24EBC419DAD4D000FF010B /* 320-568@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "320-568@2x.png"; sourceTree = "<group>"; };
|
||||
DA24EBC519DAD4D000FF010B /* 375-667@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "375-667@2x.png"; sourceTree = "<group>"; };
|
||||
DA24EBC619DAD4D000FF010B /* 414-736@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "414-736@3x.png"; sourceTree = "<group>"; };
|
||||
DA24EBC719DAD4D000FF010B /* background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = background.png; sourceTree = "<group>"; };
|
||||
DA24EBC819DAD4D000FF010B /* background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "background@2x.png"; sourceTree = "<group>"; };
|
||||
DA24EBC919DAD4D000FF010B /* background@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "background@3x.png"; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
DA250A15195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UICollectionReusableView+PearlDequeue.m"; sourceTree = "<group>"; };
|
||||
@@ -1547,6 +1578,55 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
DA24EBB019DAD4D000FF010B /* ios */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA24EBB119DAD4D000FF010B /* icon */,
|
||||
DA24EBBF19DAD4D000FF010B /* icon.sketch */,
|
||||
DA24EBC019DAD4D000FF010B /* launch */,
|
||||
DA24EBCA19DAD4D000FF010B /* launch.sketch */,
|
||||
);
|
||||
path = ios;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA24EBB119DAD4D000FF010B /* icon */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA24EBE619DAD6DE00FF010B /* Icon-320.png */,
|
||||
DA24EBE719DAD6DE00FF010B /* Icon-64.png */,
|
||||
DA24EBB219DAD4D000FF010B /* Icon-60.png */,
|
||||
DA24EBB319DAD4D000FF010B /* Icon-60@2x.png */,
|
||||
DA24EBB419DAD4D000FF010B /* Icon-60@3x.png */,
|
||||
DA24EBB519DAD4D000FF010B /* Icon-76.png */,
|
||||
DA24EBB619DAD4D000FF010B /* Icon-76@2x.png */,
|
||||
DA24EBB719DAD4D000FF010B /* Icon-Small-40.png */,
|
||||
DA24EBB819DAD4D000FF010B /* Icon-Small-40@2x.png */,
|
||||
DA24EBB919DAD4D000FF010B /* Icon-Small-40@3x.png */,
|
||||
DA24EBBA19DAD4D000FF010B /* Icon-Small.png */,
|
||||
DA24EBBB19DAD4D000FF010B /* Icon-Small@2x.png */,
|
||||
DA24EBBC19DAD4D000FF010B /* Icon-Small@3x.png */,
|
||||
DA24EBBD19DAD4D000FF010B /* iTunesArtwork.png */,
|
||||
DA24EBBE19DAD4D000FF010B /* iTunesArtwork@2x.png */,
|
||||
);
|
||||
path = icon;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA24EBC019DAD4D000FF010B /* launch */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA24EBC119DAD4D000FF010B /* 32.png */,
|
||||
DA24EBC219DAD4D000FF010B /* 320-480.png */,
|
||||
DA24EBC319DAD4D000FF010B /* 320-480@2x.png */,
|
||||
DA24EBC419DAD4D000FF010B /* 320-568@2x.png */,
|
||||
DA24EBC519DAD4D000FF010B /* 375-667@2x.png */,
|
||||
DA24EBC619DAD4D000FF010B /* 414-736@3x.png */,
|
||||
DA24EBC719DAD4D000FF010B /* background.png */,
|
||||
DA24EBC819DAD4D000FF010B /* background@2x.png */,
|
||||
DA24EBC919DAD4D000FF010B /* background@3x.png */,
|
||||
);
|
||||
path = launch;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA2509B619563E1E00AC23F1 /* Guide */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1703,6 +1783,7 @@
|
||||
DABD360D1711E29400CF925C /* Media */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA24EBB019DAD4D000FF010B /* ios */,
|
||||
DAA1761D19D89B600044227B /* thumb_touch_id@3x.png */,
|
||||
DAA1761E19D89B600044227B /* thumb_touch_id@2x.png */,
|
||||
DAA1761F19D89B600044227B /* thumb_touch_id.png */,
|
||||
@@ -2518,8 +2599,6 @@
|
||||
DAFE45FC15039823003ABA7C /* Pearl-Crypto */,
|
||||
DAFE460715039823003ABA7C /* Pearl-UIKit */,
|
||||
DAC77CB1148291A600BCF976 /* Pearl-Prefix.pch */,
|
||||
DACA29751705E2BD002C6C22 /* jrswizzle */,
|
||||
DACA29B41705E2DE002C6C22 /* uicolor-utilities */,
|
||||
);
|
||||
path = Pearl;
|
||||
sourceTree = "<group>";
|
||||
@@ -2531,6 +2610,8 @@
|
||||
DA32D03719D111EB004F3F0E /* KCOrderedAccessorFix */,
|
||||
DAA141181922FED80032B392 /* iOS */,
|
||||
DAFC5662172C57EC00CB5CC5 /* InAppSettingsKit */,
|
||||
DACA29751705E2BD002C6C22 /* jrswizzle */,
|
||||
DACA29B41705E2DE002C6C22 /* uicolor-utilities */,
|
||||
DAC77CAF148291A600BCF976 /* Pearl */,
|
||||
);
|
||||
name = External;
|
||||
@@ -2572,8 +2653,7 @@
|
||||
DACA29771705E2BD002C6C22 /* JRSwizzle.h */,
|
||||
DACA298C1705E2BD002C6C22 /* JRSwizzle.m */,
|
||||
);
|
||||
name = jrswizzle;
|
||||
path = External/jrswizzle;
|
||||
path = jrswizzle;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DACA29B41705E2DE002C6C22 /* uicolor-utilities */ = {
|
||||
@@ -2584,8 +2664,7 @@
|
||||
DACA29BA1705E2DE002C6C22 /* UIColor+Expanded.m */,
|
||||
DACA29BB1705E2DE002C6C22 /* UIColor+HSV.m */,
|
||||
);
|
||||
name = "uicolor-utilities";
|
||||
path = "External/uicolor-utilities";
|
||||
path = "uicolor-utilities";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAFC5662172C57EC00CB5CC5 /* InAppSettingsKit */ = {
|
||||
@@ -2961,6 +3040,7 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = DA5BFA6D147E415C00F98B1E /* Build configuration list for PBXNativeTarget "MasterPassword" */;
|
||||
buildPhases = (
|
||||
DA8D88E019DA412A00B189D0 /* Run Script: genassets */,
|
||||
DA5BFA40147E415C00F98B1E /* Sources */,
|
||||
DA5BFA41147E415C00F98B1E /* Frameworks */,
|
||||
DA5BFA42147E415C00F98B1E /* Resources */,
|
||||
@@ -3230,6 +3310,7 @@
|
||||
DA7304E5194E025900E72520 /* tip_basic_black.png in Resources */,
|
||||
DABD393A1711E29700CF925C /* avatar-10.png in Resources */,
|
||||
DABD393B1711E29700CF925C /* avatar-10@2x.png in Resources */,
|
||||
DA24EBAE19DAD08900FF010B /* tip_basic_black_top.png in Resources */,
|
||||
DABD393C1711E29700CF925C /* avatar-11.png in Resources */,
|
||||
DABD393D1711E29700CF925C /* avatar-11@2x.png in Resources */,
|
||||
DA73049D194E022700E72520 /* ui_spinner.png in Resources */,
|
||||
@@ -3238,9 +3319,11 @@
|
||||
DA67461018DE7F0C00DFE240 /* Exo2.0-Bold.otf in Resources */,
|
||||
DABD39401711E29700CF925C /* avatar-13.png in Resources */,
|
||||
DA32D07C19D7D784004F3F0E /* background.png in Resources */,
|
||||
DA24EBE919DAD6DE00FF010B /* Icon-64.png in Resources */,
|
||||
DABD39411711E29700CF925C /* avatar-13@2x.png in Resources */,
|
||||
DABD39421711E29700CF925C /* avatar-14.png in Resources */,
|
||||
DABD39431711E29700CF925C /* avatar-14@2x.png in Resources */,
|
||||
DA24EBE819DAD6DE00FF010B /* Icon-320.png in Resources */,
|
||||
DAA1764419D8B82B0044227B /* personal_pw.png in Resources */,
|
||||
DABD39441711E29700CF925C /* avatar-15.png in Resources */,
|
||||
DABD39451711E29700CF925C /* avatar-15@2x.png in Resources */,
|
||||
@@ -3320,6 +3403,7 @@
|
||||
DABD39F31711E29700CF925C /* icon_cancel@2x.png in Resources */,
|
||||
DABD3A261711E29700CF925C /* icon_edit.png in Resources */,
|
||||
DABD3A271711E29700CF925C /* icon_edit@2x.png in Resources */,
|
||||
DA24EBAF19DAD08C00FF010B /* tip_basic_black_top@2x.png in Resources */,
|
||||
DABD3A3A1711E29700CF925C /* icon_find.png in Resources */,
|
||||
DABD3A3B1711E29700CF925C /* icon_find@2x.png in Resources */,
|
||||
DAA1765319D8B82B0044227B /* choose_type@2x.png in Resources */,
|
||||
@@ -3348,6 +3432,7 @@
|
||||
DABD3B951711E29800CF925C /* pull-down.png in Resources */,
|
||||
DABD3B961711E29800CF925C /* pull-down@2x.png in Resources */,
|
||||
DABD3B971711E29800CF925C /* pull-up.png in Resources */,
|
||||
DA24EBEA19DAD6EE00FF010B /* Icon-Small.png in Resources */,
|
||||
DABD3B981711E29800CF925C /* pull-up@2x.png in Resources */,
|
||||
DA7304A0194E022B00E72520 /* ui_textfield@2x.png in Resources */,
|
||||
DAA1765119D8B82B0044227B /* copy_pw@2x.png in Resources */,
|
||||
@@ -3356,6 +3441,7 @@
|
||||
DAA1764519D8B82B0044227B /* name_new@2x.png in Resources */,
|
||||
DA45224819062899008F650A /* icon_settings@2x.png in Resources */,
|
||||
DA854C8418D4CFBF00106317 /* avatar-add.png in Resources */,
|
||||
DA24EBEB19DAD6EE00FF010B /* Icon-Small@2x.png in Resources */,
|
||||
DAA1764B19D8B82B0044227B /* login_name@2x.png in Resources */,
|
||||
DABD3C241711E2DC00CF925C /* MasterPassword.entitlements in Resources */,
|
||||
DABD3C251711E2DC00CF925C /* Settings.bundle in Resources */,
|
||||
@@ -3374,6 +3460,7 @@
|
||||
DAE1EF2217E942DE00BC0086 /* Localizable.strings in Resources */,
|
||||
DA38D6A318CCB5BF009AEB3E /* Storyboard.storyboard in Resources */,
|
||||
DA5A09DF171A70E4005284AB /* play.png in Resources */,
|
||||
DA24EBEC19DAD6EE00FF010B /* Icon-Small@3x.png in Resources */,
|
||||
DA5A09E0171A70E4005284AB /* play@2x.png in Resources */,
|
||||
DA5A09EA171BB0F7005284AB /* unlocked.png in Resources */,
|
||||
DAA1762819D89B610044227B /* thumb_ios_integration.png in Resources */,
|
||||
@@ -3399,6 +3486,21 @@
|
||||
shellPath = "/bin/bash -e";
|
||||
shellScript = "PATH+=:/usr/libexec\n\naddPlistWithKey() {\n local key=$1 type=$2 value=$3 plist=${4:-\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"}\n \n PlistBuddy -c \"Delete :'$key'\" \"$plist\" 2>/dev/null || true\n PlistBuddy -c \"Add :'$key' '$type' '$value'\" \"$plist\"\n}\nsetPlistWithKey() {\n local key=$1 value=$2 plist=${3:-\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"}\n \n PlistBuddy -c \"Set :'$key' '$value'\" \"$plist\"\n}\ngetPlistWithKey() {\n local key=$1 plist=${2:-\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"}\n \n PlistBuddy -c \"Print :'$key'\" \"$plist\"\n}\nsetSettingWithTitle() {\n local i title=$1 value=$2 plist=${3:-\"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Settings.bundle/Root.plist\"}\n \n for (( i=0; 1; ++i )); do\n PlistBuddy -c \"Print :PreferenceSpecifiers:$i\" \"$plist\" &>/dev/null || break\n echo \"Checking preference specifier $i\"\n \n [[ $(PlistBuddy -c \"Print :PreferenceSpecifiers:$i:Title\" \"$plist\" 2>/dev/null) = $title ]] || continue\n \n echo \"Correct title, setting value.\"\n PlistBuddy -c \"Set :PreferenceSpecifiers:$i:DefaultValue $value\" \"$plist\"\n break\n done\n}\n\ndescription=$(git describe --always --dirty --long)\nversion=${description%-g*}\nIFS=- read major minor <<< \"$version\"\nprintf -v version '%s.%02d' \"$major\" \"$minor\"\nprintf -v commit '%09d' \"$((16#${description##*-g}))\"\n\naddPlistWithKey GITDescription string \"$description\"\nsetPlistWithKey CFBundleVersion \"${version//.}$commit\" # No separator between version and commit because I had already submitted a CFBundleVersion with a really high major. Cry.\nsetPlistWithKey CFBundleShortVersionString \"$version\"\n\nsetSettingWithTitle \"Build\" \"$commit\"\nsetSettingWithTitle \"Version\" \"$version\"\nsetSettingWithTitle \"Copyright\" \"$(getPlistWithKey NSHumanReadableCopyright)\"\n\nif [[ $DEPLOYMENT_LOCATION = YES ]]; then\n # This build is a release. Do some release checks.\n passed=1\n [[ $description != *-dirty ]] || \\\n { passed=0; echo >&2 \"ERROR: Cannot release a dirty version, first commit any changes.\"; }\n [[ $(PlistBuddy -c \"Print :'API Key'\" \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Crashlytics.plist\") ]] || \\\n { passed=0; echo >&2 \"ERROR: Cannot release: Crashlytics API key is missing.\"; }\n (( passed )) || \\\n { echo >&2 \"Failed to pass release checks. Fix the above errors and re-try. Aborting.\"; exit 1; }\nfi";
|
||||
};
|
||||
DA8D88E019DA412A00B189D0 /* Run Script: genassets */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run Script: genassets";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = "/bin/sh -e";
|
||||
shellScript = "exec env PATH=\"/usr/local/bin:$PATH\" ../../../Scripts/genassets";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
DAD3125D155288AA00A3F9ED /* Run Script: Crashlytics */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -3481,8 +3583,6 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DAA175F519D86C620044227B /* markdown_lib.m in Sources */,
|
||||
DAA1761019D86C620044227B /* README_PEG-MARKDWON.markdown in Sources */,
|
||||
DAA1760F19D86C620044227B /* README.markdown in Sources */,
|
||||
DAA175F719D86C620044227B /* markdown_parser.m in Sources */,
|
||||
DAA175F619D86C620044227B /* markdown_output.m in Sources */,
|
||||
);
|
||||
@@ -3830,7 +3930,7 @@
|
||||
Reveal,
|
||||
);
|
||||
PROVISIONING_PROFILE = "";
|
||||
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "78fbee53-abe7-4a47-b917-c223df3a6952";
|
||||
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "3251b7d3-04df-4c8e-a410-d020ffc92d10";
|
||||
SKIP_INSTALL = NO;
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
};
|
||||
@@ -3856,7 +3956,7 @@
|
||||
"$(inherited)",
|
||||
);
|
||||
PROVISIONING_PROFILE = "";
|
||||
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "7142c408-252a-43c0-94c6-1ae1f43173f4";
|
||||
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "59b587d0-3ef3-4691-9f12-c48f7f283002";
|
||||
SKIP_INSTALL = NO;
|
||||
STRIP_INSTALLED_PRODUCT = YES;
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
@@ -3963,7 +4063,7 @@
|
||||
"$(inherited)",
|
||||
);
|
||||
PROVISIONING_PROFILE = "";
|
||||
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "48f9bae8-b80e-41c7-8792-663102bed54f";
|
||||
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "a1d8cfc8-b8db-4544-af34-28cc75e46c40";
|
||||
SKIP_INSTALL = NO;
|
||||
STRIP_INSTALLED_PRODUCT = YES;
|
||||
TARGETED_DEVICE_FAMILY = 1;
|
||||
|
||||
@@ -26,18 +26,8 @@
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "AppStore-iOS">
|
||||
buildConfiguration = "Debug-iOS">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DADEF42E1810D5530052CA3E"
|
||||
BuildableName = "LoveLyndirTests.xctest"
|
||||
BlueprintName = "LoveLyndirTests"
|
||||
ReferencedContainer = "container:MasterPassword-iOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
@@ -54,7 +44,7 @@
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "AppStore-iOS"
|
||||
buildConfiguration = "Debug-iOS"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
@@ -74,7 +64,7 @@
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "AppStore-iOS"
|
||||
buildConfiguration = "Debug-iOS"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable>
|
||||
<BuildableReference
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<key>FooterText</key>
|
||||
<string>When enabled, you will not be logged out when switching out of the application. This will help you get to your passwords faster, but when someone finds your device unlocked, they can too.</string>
|
||||
<key>Title</key>
|
||||
<string>Master Password</string>
|
||||
<string>Security</string>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
@@ -70,24 +70,6 @@
|
||||
<key>Type</key>
|
||||
<string>PSToggleSwitchSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>Enabling support for dictation in the site search box will enable the dictation button next to the space bar at the bottom of the keyboard. Press this button and speak the name of your site to look it up. Enabling dictation will change your keyboard which might make it slightly more difficult to enter a site name manually.</string>
|
||||
<key>Title</key>
|
||||
<string></string>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>DefaultValue</key>
|
||||
<false/>
|
||||
<key>Key</key>
|
||||
<string>dictationSearch</string>
|
||||
<key>Title</key>
|
||||
<string>Dictation Search</string>
|
||||
<key>Type</key>
|
||||
<string>PSToggleSwitchSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>This will keep your site's passwords hidden from view. Enable this if you're worried about people watching your screen while you use the app.
|
||||
@@ -110,7 +92,7 @@ To see a site's password anyway, tap and hold your finger down for a while
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>The password strength indicator estimates the time necessary to break the password from a stolen database of SHA-1 hashes. Use this setting to choose the budget the attacker is willing to devote to breaking your site password.</string>
|
||||
<string>The password strength indicator estimates the time necessary to break the password from a stolen database of SHA-1 hashes. Use this setting to choose the budget the attacker is willing to devote exclusively to breaking your site password.</string>
|
||||
<key>Title</key>
|
||||
<string></string>
|
||||
<key>Type</key>
|
||||
@@ -144,15 +126,34 @@ To see a site's password anyway, tap and hold your finger down for a while
|
||||
<integer>0</integer>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
<integer>3</integer>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>Enabling support for dictation in the site search box will enable the dictation button next to the space bar at the bottom of the keyboard. Press this button and speak the name of your site to look it up. Enabling dictation will change your keyboard which might make it slightly more difficult to enter a site name manually.</string>
|
||||
<key>Title</key>
|
||||
<string>Miscellaneous</string>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>DefaultValue</key>
|
||||
<false/>
|
||||
<key>Key</key>
|
||||
<string>dictationSearch</string>
|
||||
<key>Title</key>
|
||||
<string>Dictation Search</string>
|
||||
<key>Type</key>
|
||||
<string>PSToggleSwitchSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
<key>Title</key>
|
||||
<string></string>
|
||||
<key>FooterText</key>
|
||||
<string>If the app tends to crash on login, enable this to check if there are any inconsistencies in your site data. It may slow down login a bit, so keep it off when no issues are reported on login.</string>
|
||||
<string>Enable this if the app crashes when you log in. Master Password will scan for and repair any inconsistencies in your sites history.</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Type</key>
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6238"/>
|
||||
<capability name="Alignment constraints with different attributes" minToolsVersion="5.1"/>
|
||||
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
||||
<capability name="Unknown constraint types" minToolsVersion="5.1"/>
|
||||
</dependencies>
|
||||
@@ -97,6 +96,7 @@
|
||||
<string>Exo2.0-Thin</string>
|
||||
<string>Exo2.0-Thin</string>
|
||||
<string>Exo2.0-Thin</string>
|
||||
<string>Exo2.0-Thin</string>
|
||||
</mutableArray>
|
||||
<mutableArray key="SourceCodePro-Black.otf">
|
||||
<string>SourceCodePro-Black</string>
|
||||
@@ -133,7 +133,6 @@
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="216" id="GcG-kq-fq2"/>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="216" id="yUb-JQ-gv0"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="rWM-08-aab" userLabel="Users Root">
|
||||
@@ -173,10 +172,10 @@
|
||||
</constraints>
|
||||
</view>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="ui_spinner.png" translatesAutoresizingMaskIntoConstraints="NO" id="y4j-ds-HM7" userLabel="Spinner">
|
||||
<rect key="frame" x="52" y="-13" width="110" height="110"/>
|
||||
<rect key="frame" x="52" y="216" width="110" height="110"/>
|
||||
</imageView>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="avatar-0.png" translatesAutoresizingMaskIntoConstraints="NO" id="Aca-he-7Qi" userLabel="Avatar">
|
||||
<rect key="frame" x="52" y="-13" width="110" height="110"/>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="755" verticalCompressionResistancePriority="755" image="avatar-0.png" translatesAutoresizingMaskIntoConstraints="NO" id="Aca-he-7Qi" userLabel="Avatar">
|
||||
<rect key="frame" x="52" y="216" width="110" height="110"/>
|
||||
<color key="tintColor" red="0.47450980390000003" green="0.86666666670000003" blue="0.98431372549999996" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="110" id="Ezz-dq-dfq"/>
|
||||
@@ -184,7 +183,7 @@
|
||||
</constraints>
|
||||
</imageView>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0Sa-Vg-EEI" userLabel="Name Backdrop">
|
||||
<rect key="frame" x="43" y="34" width="128.5" height="16"/>
|
||||
<rect key="frame" x="43" y="263" width="128.5" height="16"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalCompressionResistancePriority="1000" text="Maarten Billemont" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="10" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cLT-s0-4SQ" userLabel="Name Field">
|
||||
<rect key="frame" x="5" y="0.0" width="118.5" height="16"/>
|
||||
@@ -206,7 +205,7 @@
|
||||
</view>
|
||||
<constraints>
|
||||
<constraint firstItem="J7b-uT-zY2" firstAttribute="leading" secondItem="Zab-uQ-uk9" secondAttribute="leading" id="1Sw-vq-MuH"/>
|
||||
<constraint firstItem="CQo-kd-XAU" firstAttribute="centerY" secondItem="Aca-he-7Qi" secondAttribute="centerY" priority="750" id="1zu-ay-NUc"/>
|
||||
<constraint firstItem="CQo-kd-XAU" firstAttribute="centerY" secondItem="Aca-he-7Qi" secondAttribute="centerY" priority="250" id="1zu-ay-NUc"/>
|
||||
<constraint firstItem="y4j-ds-HM7" firstAttribute="centerX" secondItem="Aca-he-7Qi" secondAttribute="centerX" id="D6m-xp-Ja0"/>
|
||||
<constraint firstAttribute="centerX" secondItem="0Sa-Vg-EEI" secondAttribute="centerX" id="EYH-CQ-6TX"/>
|
||||
<constraint firstItem="0Sa-Vg-EEI" firstAttribute="top" secondItem="Aca-he-7Qi" secondAttribute="bottom" priority="500" constant="8" symbolic="YES" id="F67-h9-FDi"/>
|
||||
@@ -218,16 +217,18 @@
|
||||
<constraint firstItem="y4j-ds-HM7" firstAttribute="centerY" secondItem="Aca-he-7Qi" secondAttribute="centerY" id="b7q-13-zb4"/>
|
||||
<constraint firstAttribute="centerY" secondItem="Aca-he-7Qi" secondAttribute="centerY" priority="500" id="fKx-ZZ-sJa"/>
|
||||
<constraint firstItem="CQo-kd-XAU" firstAttribute="top" secondItem="Zab-uQ-uk9" secondAttribute="top" constant="20" id="kO6-Hn-9ab"/>
|
||||
<constraint firstItem="Aca-he-7Qi" firstAttribute="centerY" relation="greaterThanOrEqual" secondItem="Zab-uQ-uk9" secondAttribute="top" priority="751" constant="60" id="qu4-jD-JoX"/>
|
||||
<constraint firstAttribute="bottom" secondItem="J7b-uT-zY2" secondAttribute="bottom" id="sKD-RY-oA8"/>
|
||||
<constraint firstItem="CQo-kd-XAU" firstAttribute="leading" secondItem="Zab-uQ-uk9" secondAttribute="leading" id="trm-Bp-zf3"/>
|
||||
<constraint firstItem="y4j-ds-HM7" firstAttribute="height" secondItem="Aca-he-7Qi" secondAttribute="height" id="wyT-4c-SaV"/>
|
||||
<constraint firstItem="J7b-uT-zY2" firstAttribute="top" secondItem="Aca-he-7Qi" secondAttribute="centerY" priority="250" constant="180" id="xgw-C1-V3h"/>
|
||||
<constraint firstItem="J7b-uT-zY2" firstAttribute="top" secondItem="Aca-he-7Qi" secondAttribute="centerY" priority="750" constant="180" id="xgw-C1-V3h"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="avatarImageView" destination="Aca-he-7Qi" id="Me2-jn-hSX"/>
|
||||
<outlet property="avatarRaisedConstraint" destination="xgw-C1-V3h" id="cHf-dg-hD9"/>
|
||||
<outlet property="avatarSizeConstraint" destination="Ezz-dq-dfq" id="FLf-Gq-Pdw"/>
|
||||
<outlet property="avatarToTopConstraint" destination="1zu-ay-NUc" id="i4J-5Z-Ky7"/>
|
||||
<outlet property="keyboardHeightConstraint" destination="KPB-We-gf0" id="gG1-Fl-VqV"/>
|
||||
<outlet property="nameContainer" destination="0Sa-Vg-EEI" id="VLy-AI-Yh8"/>
|
||||
<outlet property="nameLabel" destination="cLT-s0-4SQ" id="85r-AJ-Zkb"/>
|
||||
<outlet property="nameToCenterConstraint" destination="Ht7-Iz-cAW" id="zeF-2U-6GW"/>
|
||||
@@ -460,9 +461,11 @@
|
||||
<constraints>
|
||||
<constraint firstAttribute="centerX" secondItem="VDd-oM-ZOO" secondAttribute="centerX" id="0j9-vM-WFA"/>
|
||||
<constraint firstItem="zCP-wo-gTl" firstAttribute="top" secondItem="rWM-08-aab" secondAttribute="top" constant="20" id="1ly-9W-ybj"/>
|
||||
<constraint firstItem="cF4-TE-GEj" firstAttribute="bottom" secondItem="9u7-pu-Wtv" secondAttribute="top" id="3oq-Zs-Ann"/>
|
||||
<constraint firstItem="cF4-TE-GEj" firstAttribute="bottom" secondItem="9u7-pu-Wtv" secondAttribute="top" priority="500" id="3oq-Zs-Ann"/>
|
||||
<constraint firstItem="0Um-Ot-hI6" firstAttribute="top" secondItem="zCP-wo-gTl" secondAttribute="centerY" id="6zz-7f-HLz"/>
|
||||
<constraint firstAttribute="trailing" secondItem="L6J-pd-gcp" secondAttribute="trailing" id="9fV-8e-y3E"/>
|
||||
<constraint firstItem="fUK-gJ-NRE" firstAttribute="centerY" relation="greaterThanOrEqual" secondItem="L6J-pd-gcp" secondAttribute="top" constant="60" id="ADW-TA-Iha"/>
|
||||
<constraint firstItem="9u7-pu-Wtv" firstAttribute="centerY" relation="greaterThanOrEqual" secondItem="L6J-pd-gcp" secondAttribute="top" constant="60" id="AQZ-W6-Xkf"/>
|
||||
<constraint firstItem="L6J-pd-gcp" firstAttribute="leading" secondItem="rWM-08-aab" secondAttribute="leading" id="BcO-0y-Nih"/>
|
||||
<constraint firstAttribute="centerX" secondItem="cF4-TE-GEj" secondAttribute="centerX" id="CvC-rv-8KE"/>
|
||||
<constraint firstItem="qp1-nX-o4i" firstAttribute="leading" secondItem="rWM-08-aab" secondAttribute="leading" id="DY1-Ad-Mbi"/>
|
||||
@@ -470,6 +473,7 @@
|
||||
<constraint firstItem="0Um-Ot-hI6" firstAttribute="centerX" secondItem="zCP-wo-gTl" secondAttribute="centerX" id="OJA-7u-h1T"/>
|
||||
<constraint firstAttribute="bottom" secondItem="XEP-O3-ayG" secondAttribute="bottom" id="PpW-Of-YOc"/>
|
||||
<constraint firstAttribute="trailing" secondItem="fUK-gJ-NRE" secondAttribute="trailing" id="TBr-pS-kEK"/>
|
||||
<constraint firstItem="cF4-TE-GEj" firstAttribute="top" relation="greaterThanOrEqual" secondItem="L6J-pd-gcp" secondAttribute="top" constant="4" id="VHh-25-0mJ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="qp1-nX-o4i" secondAttribute="trailing" id="cOq-BS-Xmo"/>
|
||||
<constraint firstAttribute="centerY" secondItem="VDd-oM-ZOO" secondAttribute="centerY" id="dxP-im-1dM"/>
|
||||
<constraint firstItem="zCP-wo-gTl" firstAttribute="leading" secondItem="rWM-08-aab" secondAttribute="leading" id="jBY-Gd-orW"/>
|
||||
@@ -486,9 +490,9 @@
|
||||
<constraint firstItem="VGz-R0-vMD" firstAttribute="top" secondItem="X8H-vh-j7B" secondAttribute="bottom" id="8Ed-3Y-ll0"/>
|
||||
<constraint firstAttribute="trailing" secondItem="X8H-vh-j7B" secondAttribute="trailing" id="8Gr-Dq-UpZ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="rWM-08-aab" secondAttribute="bottom" id="9Yx-cj-wHh"/>
|
||||
<constraint firstItem="X8H-vh-j7B" firstAttribute="top" secondItem="9u7-pu-Wtv" secondAttribute="centerY" constant="180" id="Gp5-h6-53S"/>
|
||||
<constraint firstItem="X8H-vh-j7B" firstAttribute="top" secondItem="9u7-pu-Wtv" secondAttribute="centerY" priority="500" constant="180" id="Gp5-h6-53S"/>
|
||||
<constraint firstItem="rWM-08-aab" firstAttribute="leading" secondItem="DOr-Xu-P9q" secondAttribute="leading" id="Il8-kg-Dra"/>
|
||||
<constraint firstItem="X8H-vh-j7B" firstAttribute="top" secondItem="fUK-gJ-NRE" secondAttribute="centerY" constant="180" id="PgC-ZL-cQo"/>
|
||||
<constraint firstItem="X8H-vh-j7B" firstAttribute="top" secondItem="fUK-gJ-NRE" secondAttribute="centerY" priority="500" constant="180" id="PgC-ZL-cQo"/>
|
||||
<constraint firstAttribute="trailing" secondItem="rWM-08-aab" secondAttribute="trailing" id="UPP-1n-zIe"/>
|
||||
<constraint firstItem="X8H-vh-j7B" firstAttribute="top" secondItem="qp1-nX-o4i" secondAttribute="bottom" constant="20" id="WdK-tA-njz"/>
|
||||
<constraint firstItem="X8H-vh-j7B" firstAttribute="leading" secondItem="DOr-Xu-P9q" secondAttribute="leading" id="jbn-ko-MPq"/>
|
||||
@@ -506,6 +510,7 @@
|
||||
<outlet property="entryTipSubtitleLabel" destination="KhE-Yj-Kvm" id="G0X-19-RmH"/>
|
||||
<outlet property="entryTipTitleLabel" destination="ZI7-qg-7OW" id="dZj-rZ-efd"/>
|
||||
<outlet property="footerContainer" destination="XEP-O3-ayG" id="9cI-p9-av3"/>
|
||||
<outlet property="keyboardHeightConstraint" destination="GcG-kq-fq2" id="V1s-Sz-0Zp"/>
|
||||
<outlet property="marqueeButton" destination="4md-Gp-SLG" id="bUt-IL-8P1"/>
|
||||
<outlet property="nextAvatarButton" destination="fUK-gJ-NRE" id="5qo-lK-rSa"/>
|
||||
<outlet property="preferencesTipContainer" destination="0Um-Ot-hI6" id="Cv8-Bp-ZZs"/>
|
||||
@@ -2294,7 +2299,7 @@ Suspendisse potenti. Etiam ut nisi id augue tempor ultrices et sit amet sapien.
|
||||
<rect key="frame" x="20" y="20" width="335" height="80"/>
|
||||
</imageView>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Stay Logged In?" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5X1-J4-TbH">
|
||||
<rect key="frame" x="20" y="108" width="335" height="20"/>
|
||||
<rect key="frame" x="20" y="108" width="335" height="20.5"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Bold" family="Exo 2.0" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@@ -2303,8 +2308,8 @@ Suspendisse potenti. Etiam ut nisi id augue tempor ultrices et sit amet sapien.
|
||||
<rect key="frame" x="163" y="532" width="51" height="31"/>
|
||||
<color key="onTintColor" red="0.37254901959999998" green="0.3921568627" blue="0.42745098040000001" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</switch>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="e80-98-V6D">
|
||||
<rect key="frame" x="20" y="136.5" width="335" height="147"/>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="e80-98-V6D">
|
||||
<rect key="frame" x="20" y="137" width="335" height="151.5"/>
|
||||
<string key="text">The right balance between security and convenience is often very personal.
|
||||
|
||||
To make getting to your passwords faster, you can remain logged in after you close Master Password. This allows you to skip having to log in the next time.
|
||||
@@ -2809,7 +2814,7 @@ See </string>
|
||||
<outlet property="purchasedIndicator" destination="yZX-ns-8oV" id="7x0-eq-oSs"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MPStoreProductCellFuel" rowHeight="394" id="le3-Q5-MSO" userLabel="Fuel" customClass="MPStoreProductCell">
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MPStoreProductCellFuel" rowHeight="407" id="le3-Q5-MSO" userLabel="Fuel" customClass="MPStoreProductCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="97"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="le3-Q5-MSO" id="SzQ-Y5-XIF">
|
||||
@@ -2823,12 +2828,13 @@ See </string>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fz2-AO-aGW">
|
||||
<rect key="frame" x="20" y="254" width="335" height="119.5"/>
|
||||
<string key="text">You really love Master Password and how it's solving your password problems. You're eager to encourage the maintenance, technical support and development of new features. I am a one-man shop, more fuel means I can allocate more hours to Master Password.
|
||||
<rect key="frame" x="20" y="254" width="335" height="132"/>
|
||||
<string key="text">You really love Master Password and how it's solving your password problems. You're eager to encourage the maintenance, technical support and development of new features. I am a one-man shop, fuel enables me to allocate more work hours to Master Password.
|
||||
|
||||
UPCOMING:
|
||||
– Safari integration
|
||||
– Touch ID support
|
||||
– Multi-platform support
|
||||
– Your feedback</string>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Thin" family="Exo 2.0" pointSize="11"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -2862,6 +2868,14 @@ UPCOMING:
|
||||
<action selector="toggleFuelConsumption:" destination="pdl-xv-zjX" eventType="touchUpInside" id="NkB-Dy-IeY"/>
|
||||
</connections>
|
||||
</button>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kYb-j4-32C">
|
||||
<rect key="frame" x="20" y="64" width="117.5" height="26.5"/>
|
||||
<string key="text">fuel left: 0.3 work hours
|
||||
invested: 3.7 work hours</string>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Thin" family="Exo 2.0" pointSize="11"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="aGb-QC-A92" firstAttribute="bottom" secondItem="PnG-hP-syh" secondAttribute="bottom" id="0Jx-M5-xlh"/>
|
||||
@@ -2873,14 +2887,16 @@ UPCOMING:
|
||||
<constraint firstItem="Jnv-uN-xeg" firstAttribute="bottom" secondItem="EbU-DV-fKF" secondAttribute="bottom" id="KbL-rF-pVN"/>
|
||||
<constraint firstItem="Jnv-uN-xeg" firstAttribute="top" secondItem="PnG-hP-syh" secondAttribute="bottom" constant="8" symbolic="YES" id="OZV-m1-YZ1"/>
|
||||
<constraint firstItem="dsR-fr-dY4" firstAttribute="top" secondItem="SzQ-Y5-XIF" secondAttribute="top" constant="20" id="VH2-O8-CGj"/>
|
||||
<constraint firstAttribute="bottom" secondItem="fz2-AO-aGW" secondAttribute="bottom" constant="20" symbolic="YES" id="Wqo-Le-AcG"/>
|
||||
<constraint firstItem="eS4-59-Xny" firstAttribute="centerX" secondItem="PnG-hP-syh" secondAttribute="centerX" id="ZbQ-LX-kmS"/>
|
||||
<constraint firstItem="kYb-j4-32C" firstAttribute="leading" secondItem="dsR-fr-dY4" secondAttribute="leading" id="bih-Ha-Tz7"/>
|
||||
<constraint firstItem="EbU-DV-fKF" firstAttribute="leading" secondItem="Jnv-uN-xeg" secondAttribute="trailing" constant="8" symbolic="YES" id="cku-JX-4bK"/>
|
||||
<constraint firstItem="kYb-j4-32C" firstAttribute="top" secondItem="dsR-fr-dY4" secondAttribute="bottom" id="eJU-g8-KuU"/>
|
||||
<constraint firstItem="aGb-QC-A92" firstAttribute="centerX" secondItem="PnG-hP-syh" secondAttribute="centerX" constant="80" id="eMa-Gj-BUc"/>
|
||||
<constraint firstItem="dsR-fr-dY4" firstAttribute="leading" secondItem="SzQ-Y5-XIF" secondAttribute="leading" constant="20" id="eX0-7y-eHi"/>
|
||||
<constraint firstAttribute="centerX" secondItem="PnG-hP-syh" secondAttribute="centerX" id="gO5-ME-YVO"/>
|
||||
<constraint firstAttribute="trailing" secondItem="EbU-DV-fKF" secondAttribute="trailing" constant="20" id="hae-Jv-wOU"/>
|
||||
<constraint firstAttribute="trailing" secondItem="fz2-AO-aGW" secondAttribute="trailing" constant="20" id="vlt-qH-1Xx"/>
|
||||
<constraint firstAttribute="bottom" secondItem="fz2-AO-aGW" secondAttribute="bottom" constant="20" symbolic="YES" id="xkO-cL-7m2"/>
|
||||
<constraint firstItem="eS4-59-Xny" firstAttribute="centerY" secondItem="PnG-hP-syh" secondAttribute="centerY" id="yUc-2F-y1r"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
@@ -2912,7 +2928,7 @@ UPCOMING:
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="ARC-xH-0U0" secondAttribute="bottom" constant="40" id="4ux-Ao-e12"/>
|
||||
<constraint firstAttribute="bottom" secondItem="ARC-xH-0U0" secondAttribute="bottom" constant="48" id="5L9-Ag-d1G"/>
|
||||
<constraint firstAttribute="centerX" secondItem="ARC-xH-0U0" secondAttribute="centerX" id="asI-QK-u6O"/>
|
||||
<constraint firstItem="ARC-xH-0U0" firstAttribute="top" secondItem="Vjt-7c-BJ4" secondAttribute="bottom" constant="40" id="g1T-rA-vOW"/>
|
||||
<constraint firstAttribute="centerX" secondItem="Vjt-7c-BJ4" secondAttribute="centerX" id="j2l-mA-Duf"/>
|
||||
@@ -2939,7 +2955,7 @@ UPCOMING:
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bCe-a3-cDC">
|
||||
<rect key="frame" x="16" y="24" width="343" height="26"/>
|
||||
<rect key="frame" x="8" y="24" width="359" height="26"/>
|
||||
<fontDescription key="fontDescription" name="Exo2.0-Regular" family="Exo 2.0" pointSize="11"/>
|
||||
<state key="normal" title="Send Thanks">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -2957,13 +2973,13 @@ UPCOMING:
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="IOk-WZ-HJ8" secondAttribute="trailing" constant="20" symbolic="YES" id="CuJ-h7-aGJ"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="bCe-a3-cDC" secondAttribute="trailing" constant="8" id="Lfp-Hx-vLN"/>
|
||||
<constraint firstAttribute="trailing" secondItem="bCe-a3-cDC" secondAttribute="trailing" constant="8" id="Lfp-Hx-vLN"/>
|
||||
<constraint firstAttribute="trailing" secondItem="DxV-2L-bxL" secondAttribute="trailing" constant="20" symbolic="YES" id="QHU-Jw-LPy"/>
|
||||
<constraint firstItem="IOk-WZ-HJ8" firstAttribute="top" secondItem="bCe-a3-cDC" secondAttribute="bottom" constant="8" symbolic="YES" id="bfe-bp-fGn"/>
|
||||
<constraint firstItem="DxV-2L-bxL" firstAttribute="leading" secondItem="4Zu-Ig-Ws4" secondAttribute="leading" constant="20" symbolic="YES" id="fAD-At-gqS"/>
|
||||
<constraint firstItem="DxV-2L-bxL" firstAttribute="top" secondItem="4Zu-Ig-Ws4" secondAttribute="top" constant="4" id="hTN-Cx-hOS"/>
|
||||
<constraint firstItem="bCe-a3-cDC" firstAttribute="top" secondItem="DxV-2L-bxL" secondAttribute="bottom" constant="8" symbolic="YES" id="hfr-MK-Me2"/>
|
||||
<constraint firstItem="bCe-a3-cDC" firstAttribute="leading" secondItem="4Zu-Ig-Ws4" secondAttribute="leadingMargin" constant="8" id="l4A-fH-9fA"/>
|
||||
<constraint firstItem="bCe-a3-cDC" firstAttribute="leading" secondItem="4Zu-Ig-Ws4" secondAttribute="leading" constant="8" id="l4A-fH-9fA"/>
|
||||
<constraint firstItem="IOk-WZ-HJ8" firstAttribute="leading" secondItem="4Zu-Ig-Ws4" secondAttribute="leading" constant="20" symbolic="YES" id="mx2-Jk-5jo"/>
|
||||
<constraint firstAttribute="bottom" secondItem="IOk-WZ-HJ8" secondAttribute="bottom" id="xEZ-X4-5oi"/>
|
||||
</constraints>
|
||||
@@ -2985,6 +3001,7 @@ UPCOMING:
|
||||
<outlet property="fuelCell" destination="le3-Q5-MSO" id="oAk-6g-cFj"/>
|
||||
<outlet property="fuelMeterConstraint" destination="eMa-Gj-BUc" id="9iF-EO-UU6"/>
|
||||
<outlet property="fuelSpeedButton" destination="dsR-fr-dY4" id="XGI-PE-9mh"/>
|
||||
<outlet property="fuelStatusLabel" destination="kYb-j4-32C" id="o5R-0u-kGL"/>
|
||||
<outlet property="generateAnswersCell" destination="l1g-Ul-Vg8" id="GlG-iZ-7FP"/>
|
||||
<outlet property="generateLoginCell" destination="JVW-tG-xxe" id="PXM-WX-8Qe"/>
|
||||
<outlet property="iOSIntegrationCell" destination="9Na-CL-jBq" id="LSO-OV-9KA"/>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{"images":[{"size":"60x60","filename":"Icon-60@3x.png","scale":"3x","idiom":"iphone","minimum-system-version":"8.0"},{"size":"40x40","filename":"Icon-Small-40@3x.png","scale":"3x","idiom":"iphone","minimum-system-version":"8.0"},{"size":"60x60","filename":"Icon-60@2x.png","scale":"2x","idiom":"iphone","minimum-system-version":"7.0"},{"size":"40x40","filename":"Icon-Small-40@2x.png","scale":"2x","idiom":"iphone","minimum-system-version":"7.0"},{"size":"29x29","filename":"Icon-Small@3x.png","scale":"3x","idiom":"iphone"},{"size":"29x29","filename":"Icon-Small@2x.png","scale":"2x","idiom":"iphone"},{"size":"76x76","filename":"Icon-76.png","scale":"1x","idiom":"ipad","minimum-system-version":"7.0"},{"size":"76x76","filename":"Icon-76@2x.png","scale":"2x","idiom":"ipad","minimum-system-version":"7.0"},{"size":"40x40","filename":"Icon-Small-40.png","scale":"1x","idiom":"ipad","minimum-system-version":"7.0"},{"size":"40x40","filename":"Icon-Small-40@2x.png","scale":"2x","idiom":"ipad","minimum-system-version":"7.0"},{"size":"29x29","filename":"Icon-Small.png","scale":"1x","idiom":"ipad"},{"size":"29x29","filename":"Icon-Small@2x.png","scale":"2x","idiom":"ipad"}],"info":{"version":1,"author":"genassets"},"properties":{"pre-rendered":true}}
|
||||
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 9.6 KiB |
@@ -1 +0,0 @@
|
||||
{"images":[{"extent":"full-screen","filename":"Default-8.0-736h@3x~iphone.png","orientation":"portrait","scale":"3x","idiom":"iphone","minimum-system-version":"8.0","subtype":"736h"},{"extent":"full-screen","filename":"Default-8.0-667h@2x~iphone.png","orientation":"portrait","scale":"2x","idiom":"iphone","minimum-system-version":"8.0","subtype":"667h"},{"extent":"full-screen","filename":"Default-7.0-retina4@2x~iphone.png","orientation":"portrait","scale":"2x","idiom":"iphone","minimum-system-version":"7.0","subtype":"retina4"},{"extent":"full-screen","filename":"Default-retina4@2x~iphone.png","orientation":"portrait","scale":"2x","idiom":"iphone","subtype":"retina4"},{"extent":"full-screen","filename":"Default-7.0@2x~iphone.png","orientation":"portrait","scale":"2x","idiom":"iphone","minimum-system-version":"7.0"},{"extent":"full-screen","filename":"Default@2x~iphone.png","orientation":"portrait","scale":"2x","idiom":"iphone"},{"extent":"full-screen","filename":"Default~iphone.png","orientation":"portrait","scale":"1x","idiom":"iphone"}],"info":{"version":1,"author":"genassets"}}
|
||||
|
Before Width: | Height: | Size: 371 KiB |
|
Before Width: | Height: | Size: 321 KiB |
|
Before Width: | Height: | Size: 501 KiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 371 KiB |
|
Before Width: | Height: | Size: 321 KiB |
|
Before Width: | Height: | Size: 89 KiB |
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>app</key>
|
||||
<string>com.bohemiancoding.sketch3</string>
|
||||
<key>build</key>
|
||||
<integer>8053</integer>
|
||||
<key>commit</key>
|
||||
<string>104f8b8798002207eebbbee810c02306c5ce85c9</string>
|
||||
<key>fonts</key>
|
||||
<array>
|
||||
<string>SourceCodePro-Light</string>
|
||||
<string>LucidaGrande</string>
|
||||
<string>HelveticaNeue-Medium</string>
|
||||
</array>
|
||||
<key>length</key>
|
||||
<integer>371142</integer>
|
||||
<key>version</key>
|
||||
<integer>37</integer>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1 +0,0 @@
|
||||
37
|
||||
BIN
MasterPassword/Resources/Media/ios/icon/Icon-320.png
Normal file
|
After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 25 KiB |
BIN
MasterPassword/Resources/Media/ios/icon/Icon-64.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 245 KiB After Width: | Height: | Size: 137 KiB |
|
Before Width: | Height: | Size: 891 KiB After Width: | Height: | Size: 499 KiB |
@@ -715,15 +715,15 @@ log() {
|
||||
&& printf >> "$_logFile" '%s' "$logMsg"
|
||||
|
||||
# Start the spinner.
|
||||
if [[ $type = startProgress && ! $_logSpinner ]]; then
|
||||
if [[ $type = startProgress && ! $_logSpinner && $TERM != dumb ]]; then
|
||||
{
|
||||
set +m
|
||||
trap 'printf %s "$show"' EXIT
|
||||
printf %s "$hide"
|
||||
while printf "$eel$blue$bold[$reset%s$reset$blue$bold]$reset\b\b\b" "${spinner[s++ % ${#spinner[@]}]}" && sleep .1
|
||||
trap 'printf >&2 %s "$show"' EXIT
|
||||
printf >&2 %s "$hide"
|
||||
while printf >&2 "$eel$blue$bold[$reset%s$reset$blue$bold]$reset\b\b\b" "${spinner[s++ % ${#spinner[@]}]}" && sleep .1
|
||||
do :; done
|
||||
} & _logSpinner=$!
|
||||
fi 2>/dev/null
|
||||
fi
|
||||
|
||||
return $exitcode
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
# See https://developer.apple.com/library/ios/qa/qa1686/_index.html
|
||||
cd "${BASH_SOURCE%/*}"
|
||||
source bashlib
|
||||
cd ..
|
||||
|
||||
# icons format: [pixel size]@[scale]@[idiom]@[os]:[filename] -- if os is "anything lower", omit it
|
||||
icons=(
|
||||
@@ -63,7 +65,7 @@ launchimage="$xcassets/LaunchImage.launchimage"
|
||||
ios_icon=MasterPassword/Resources/Media/ios/icon
|
||||
ios_launch=MasterPassword/Resources/Media/ios/launch
|
||||
|
||||
[[ "$(latest "$ios_icon"/*)" -nt "$appiconset/Contents.json" ]] && {
|
||||
if [[ "$(latest "$ios_icon"/*)" -nt "$appiconset/Contents.json" ]]; then
|
||||
rm -rf "$appiconset"; mkdir -p "$appiconset"
|
||||
{
|
||||
comma=
|
||||
@@ -82,14 +84,17 @@ ios_launch=MasterPassword/Resources/Media/ios/launch
|
||||
printf '}'
|
||||
|
||||
comma=,
|
||||
else
|
||||
rm "$appiconset/Contents.json"
|
||||
exit
|
||||
fi
|
||||
|
||||
done
|
||||
printf '],"info":{"version":1,"author":"genassets"},"properties":{"pre-rendered":true}}\n'
|
||||
} > "$appiconset/Contents.json"
|
||||
}
|
||||
fi
|
||||
|
||||
[[ "$(latest "$ios_launch"/*)" -nt "$launchimage/Contents.json" ]] && {
|
||||
if [[ "$(latest "$ios_launch"/*)" -nt "$launchimage/Contents.json" ]]; then
|
||||
rm -rf "$launchimage"; mkdir -p "$launchimage"
|
||||
{
|
||||
comma=
|
||||
@@ -114,11 +119,14 @@ ios_launch=MasterPassword/Resources/Media/ios/launch
|
||||
printf '}'
|
||||
|
||||
comma=,
|
||||
else
|
||||
rm "$launchimage/Contents.json"
|
||||
exit
|
||||
fi
|
||||
done
|
||||
printf '],"info":{"version":1,"author":"genassets"}}\n'
|
||||
} > "$launchimage/Contents.json"
|
||||
}
|
||||
fi
|
||||
|
||||
#for file in resources/images/mdpi/*.png; do
|
||||
# name=${file##*/} name=${name%.*} name=${name/.9/}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<link rel="shortcut icon" href="img/favicon.png" type="image/x-png" />
|
||||
<link rel="stylesheet" href="css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="css/bootstrap-responsive.min.css">
|
||||
<link rel="stylesheet" href="css/main.css?1">
|
||||
<link rel="stylesheet" href="css/main.css?7">
|
||||
|
||||
<script src="js/vendor/modernizr-2.6.2.min.js"></script>
|
||||
<script src="js/vendor/prefixfree.min.js"></script>
|
||||
@@ -35,18 +35,16 @@
|
||||
<a class="brand" href="./">●●●|</a>
|
||||
<div class="nav-collapse collapse">
|
||||
<ul class="nav">
|
||||
<li><a href="./">App</a></li>
|
||||
<li><a href="security.html">Security</a></li>
|
||||
<li><a href="faq.html">FAQ</a></li>
|
||||
<li class="active"><a href="algorithm.html">Algorithm</a></li>
|
||||
<li><a href="support.html">Support</a></li>
|
||||
<li><a href="http://github.com/Lyndir/MasterPassword/" onclick="_gaq.push(['_trackPageview', '/outbound/github']);">Source (GPL)</a></li>
|
||||
<li><a href="what.html">What is it? How do I use it?</a></li>
|
||||
<li><a href="security.html">Is it safe?</a></li>
|
||||
<li class="active"><a href="algorithm.html">How does it work?</a></li>
|
||||
</ul>
|
||||
<ul class="nav pull-right">
|
||||
<li><a href="irc://irc.freenode.net/#masterpassword" onclick="_gaq.push(['_trackPageview', '/outbound/irc']);">#masterpassword (freenode)</a></li>
|
||||
<li><a href="irc://irc.freenode.net/#masterpassword" onclick="_gaq.push(['_trackPageview', '/outbound/irc']);">#masterpassword</a></li>
|
||||
<li class="divider-vertical"></li>
|
||||
<li><a href="MasterPassword_PressKit.zip" onclick="_gaq.push(['_trackPageview', '/outbound/presskit']);">⬇ Press Kit</a></li>
|
||||
<li><a href="http://itunes.apple.com/app/id510296984" onclick="goog_report_conversion('index-fixed-header');_gaq.push(['_trackPageview', '/outbound/itunes']);" class="img"><img src="img/appstore.svg" /></a></li>
|
||||
<li><a href="faq.html">FAQ</a></li>
|
||||
<li><a href="support.html">Support</a></li>
|
||||
<li><a href="http://github.com/Lyndir/MasterPassword/" onclick="_gaq.push(['_trackPageview', '/outbound/github']);">Source</a></li>
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
@@ -77,42 +75,6 @@
|
||||
<p><b>Master Password is <em>an algorithm used to generate unique passwords</em></b> for websites, email accounts, or anything else <em>based only on easily reproducible input</em>.<br />
|
||||
The goal is a process that avoids all the problems involved with other password solutions.</p>
|
||||
<p>The Master Password algorithm is <i>open</i>: this page describes its inner workings in detail. We believe the following is an important lesson we should all learn: Regardless of how much encryption a solution claims, <a href="http://www.geekzone.co.nz/foobar/5823" onclick="_gaq.push(['_trackPageview', '/outbound/skype']);">if you don't know how it works, you <strong>cannot</strong> assume it is secure</a> (at least, not the kind of secure you care about).</p>
|
||||
|
||||
<h1>The Password Problem</h1>
|
||||
<img class="pull-right" src="img/thumb-authenticate.png" />
|
||||
<p>Passwords are used to authenticate you to someone else. That means, convince someone that you really are who you say you are. The theory is that when you two are the only ones that know a certain secret word, then the other party can be certain of your identity when you prove to them you know the secret word.</p>
|
||||
<p>Authentication using passwords is pretty good in theory but <strong>fails when</strong> the password is either:
|
||||
<ul>
|
||||
<li>Easily guessed by an impersonator.</li>
|
||||
<li>Known by others.</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>So the only way to do passwords right is by inventing a secure (ie. hard to guess) and unique (ie. different for each site) password each time.</p>
|
||||
<p>Unfortunately, secure passwords are hard to come up with and even harder to remember.</p>
|
||||
<p>People generally give up and begin reusing passwords between sites. The password is now no longer secret. This can lead to your identity getting stolen when sites get hacked, you get conned by a hoax site, or you sign up with an untrustworthy website.</p>
|
||||
|
||||
<h1>Password Solutions</h1>
|
||||
<p>To help with these problems, there are a bunch of apps available that remember your passwords for you. They accomplish this by saving your passwords in an encrypted vault or by sending them off to a cloud server.</p>
|
||||
<p>These approaches are very helpful, but they come with a few very <em>important</em> <strong>downsides</strong>:
|
||||
<ul>
|
||||
<li>Vaults need to be backed-up to avoid the risk of complete identity loss.</li>
|
||||
<li>Vaults need to be kept nearby and in-sync across the your devices or you won't always be able to access the password you need.</li>
|
||||
<li>Sending passwords to the cloud means handing your keys to a company.</li>
|
||||
<li>When your passwords are in the cloud they may not be available when you have no Internet access.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h1>Solving Availability</h1>
|
||||
<p>Losing all your passwords or other password availability issues are frustrating and sometimes even disastrous.</p>
|
||||
<p>Master Password solves this problem by being a <em>stateless</em> solution. That means that no information needs to be saved in order for the program to be able to give you your password again in the future.</p>
|
||||
<p>Since Master Password doesn't save your passwords and doesn't send them anywhere, it <strong>avoids the following risks</strong>:
|
||||
<ul>
|
||||
<li>Your passwords cannot be found in a file or even a backup.</li>
|
||||
<li>Your passwords cannot be intercepted during sync.</li>
|
||||
<li>You don't need to trust a third party with your secrets.</li>
|
||||
<li>You can't lose your passwords.</li>
|
||||
</ul>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="thumb clearfix">
|
||||
|
||||
@@ -189,6 +189,8 @@ header {
|
||||
background: black;
|
||||
text-shadow: black 0 1px 50px;
|
||||
box-shadow: 0 1px 5px #000;
|
||||
|
||||
transition: height 0.3s;
|
||||
}
|
||||
header .container {
|
||||
position: relative;
|
||||
@@ -267,15 +269,19 @@ header .box .maximized {
|
||||
height: 80%;
|
||||
}
|
||||
#app header .background {
|
||||
background: url('../img/shot-laptop-leaning-iphone.png') center center;
|
||||
background: url('../img/shot-laptop-leaning-iphone.jpg') center center;
|
||||
background-size: cover;
|
||||
}
|
||||
#what header,
|
||||
#security header,
|
||||
#algorithm header,
|
||||
#support header {
|
||||
height: 40%;
|
||||
|
||||
background: #272727;
|
||||
}
|
||||
#what header .background,
|
||||
#security header .background,
|
||||
#algorithm header .background,
|
||||
#support header .background {
|
||||
width: 940px;
|
||||
@@ -284,6 +290,8 @@ header .box .maximized {
|
||||
top: -10%;
|
||||
margin-left: -470px;
|
||||
}
|
||||
#what header .container,
|
||||
#security header .container,
|
||||
#algorithm header .container,
|
||||
#support header .container {
|
||||
background: radial-gradient(center, ellipse cover, rgba(0,0,0,0.3) 50%,rgba(0,0,0,0.8) 100%);
|
||||
@@ -321,6 +329,92 @@ header h2 {
|
||||
font-size: 2em;
|
||||
font-style: oblique;
|
||||
}
|
||||
header .movie {
|
||||
display: none;
|
||||
background: url('../img/about.png') no-repeat scroll 50% 40px/cover black;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding-top: 40px;
|
||||
}
|
||||
header .movie::after {
|
||||
display: block;
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: url('../img/loading-spin.svg') no-repeat scroll center center transparent;
|
||||
}
|
||||
header.play {
|
||||
height: auto !important;
|
||||
max-height: 94%;
|
||||
}
|
||||
header.play .movie {
|
||||
display: block;
|
||||
}
|
||||
header.play .movie video {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
}
|
||||
header.play h1, header.play h2, header.play .box {
|
||||
display: none;
|
||||
}
|
||||
header .moviecontrol {
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: 9;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-top: -.5em;
|
||||
margin-left: -.5em;
|
||||
|
||||
font-size: 400%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
header .moviecontrol::before {
|
||||
content: "▶";
|
||||
}
|
||||
header .moviecontrol:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
header.play .moviecontrol {
|
||||
right: 1em;
|
||||
bottom: 1em;
|
||||
left: auto;
|
||||
top: auto;
|
||||
}
|
||||
header.play .moviecontrol::before {
|
||||
content: "❙❙";
|
||||
}
|
||||
header .movie::before {
|
||||
display: block;
|
||||
content: " ";
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: url('../img/video-pattern.png') repeat;
|
||||
background: url('../img/video-bg.png') no-repeat scroll 50% 100%/cover transparent;
|
||||
}
|
||||
header .movie video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
height: calc(100% - 40px);
|
||||
height: auto;
|
||||
}
|
||||
header .movie .fallback {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 60px;
|
||||
text-align: center;
|
||||
z-index: 5;
|
||||
color: #BBB;
|
||||
}
|
||||
footer {
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
@@ -392,3 +486,29 @@ table .box.green {
|
||||
background: #6A6;
|
||||
border: 1px solid #3C3;
|
||||
}
|
||||
|
||||
@media (max-width: 979px) {
|
||||
.content {
|
||||
width: auto;
|
||||
}
|
||||
header .content {
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
.pull-right, .pull-left {
|
||||
float: none;
|
||||
}
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
header h1 {
|
||||
font-size: 4em;
|
||||
}
|
||||
header h2 {
|
||||
font-size: 2em;
|
||||
}
|
||||
header .moviecontrol {
|
||||
top: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<link rel="shortcut icon" href="img/favicon.png" type="image/x-png" />
|
||||
<link rel="stylesheet" href="css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="css/bootstrap-responsive.min.css">
|
||||
<link rel="stylesheet" href="css/main.css?1">
|
||||
<link rel="stylesheet" href="css/main.css?7">
|
||||
|
||||
<script src="js/vendor/modernizr-2.6.2.min.js"></script>
|
||||
<script src="js/vendor/prefixfree.min.js"></script>
|
||||
@@ -35,18 +35,16 @@
|
||||
<a class="brand" href="./">●●●|</a>
|
||||
<div class="nav-collapse collapse">
|
||||
<ul class="nav">
|
||||
<li><a href="./">App</a></li>
|
||||
<li><a href="security.html">Security</a></li>
|
||||
<li class="active"><a href="faq.html">FAQ</a></li>
|
||||
<li><a href="algorithm.html">Algorithm</a></li>
|
||||
<li><a href="support.html">Support</a></li>
|
||||
<li><a href="http://github.com/Lyndir/MasterPassword/" onclick="_gaq.push(['_trackPageview', '/outbound/github']);">Source (GPL)</a></li>
|
||||
<li><a href="what.html">What is it? How do I use it?</a></li>
|
||||
<li><a href="security.html">Is it safe?</a></li>
|
||||
<li><a href="algorithm.html">How does it work?</a></li>
|
||||
</ul>
|
||||
<ul class="nav pull-right">
|
||||
<li><a href="irc://irc.freenode.net/#masterpassword" onclick="_gaq.push(['_trackPageview', '/outbound/irc']);">#masterpassword (freenode)</a></li>
|
||||
<li><a href="irc://irc.freenode.net/#masterpassword" onclick="_gaq.push(['_trackPageview', '/outbound/irc']);">#masterpassword</a></li>
|
||||
<li class="divider-vertical"></li>
|
||||
<li><a href="MasterPassword_PressKit.zip" onclick="_gaq.push(['_trackPageview', '/outbound/presskit']);">⬇ Press Kit</a></li>
|
||||
<li><a href="http://itunes.apple.com/app/id510296984" onclick="goog_report_conversion('index-fixed-header');_gaq.push(['_trackPageview', '/outbound/itunes']);" class="img"><img src="img/appstore.svg" /></a></li>
|
||||
<li class="active"><a href="faq.html">FAQ</a></li>
|
||||
<li><a href="support.html">Support</a></li>
|
||||
<li><a href="http://github.com/Lyndir/MasterPassword/" onclick="_gaq.push(['_trackPageview', '/outbound/github']);">Source</a></li>
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
|
||||
BIN
Site/2013-05/img/howto-mp-copy.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
Site/2013-05/img/howto-mp-copy@2x.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
Site/2013-05/img/howto-mp-create-confirm.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
Site/2013-05/img/howto-mp-create-confirm@2x.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
Site/2013-05/img/howto-mp-create.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
Site/2013-05/img/howto-mp-create@2x.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
Site/2013-05/img/howto-mp-login.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
Site/2013-05/img/howto-mp-login@2x.png
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
Site/2013-05/img/howto-mp-type-basic.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
Site/2013-05/img/howto-mp-type-basic@2x.png
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
Site/2013-05/img/howto-mp-type-change.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
Site/2013-05/img/howto-mp-type-change@2x.png
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
Site/2013-05/img/howto-twitter-done.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
Site/2013-05/img/howto-twitter-done@2x.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
Site/2013-05/img/howto-twitter-paste.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
Site/2013-05/img/howto-twitter-paste@2x.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
Site/2013-05/img/howto-twitter-signup.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
Site/2013-05/img/howto-twitter-signup@2x.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
Site/2013-05/img/mac-icon-256.png
Normal file
|
After Width: | Height: | Size: 113 KiB |
BIN
Site/2013-05/img/play.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
Site/2013-05/img/shot-laptop-leaning-iphone-800@2x.png
Normal file
|
After Width: | Height: | Size: 569 KiB |
BIN
Site/2013-05/img/shot-laptop-leaning-iphone.jpg
Normal file
|
After Width: | Height: | Size: 317 KiB |
BIN
Site/2013-05/img/video-bg.png
Normal file
|
After Width: | Height: | Size: 144 KiB |
BIN
Site/2013-05/img/video-pattern.png
Normal file
|
After Width: | Height: | Size: 939 B |