Compare commits
9 Commits
2.7-java-8
...
2.7-java-9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f35ac5f64 | ||
|
|
06100510c3 | ||
|
|
1bf6109038 | ||
|
|
f2fa2a25b2 | ||
|
|
2a0cfd3a32 | ||
|
|
3070967d34 | ||
|
|
e4837a284a | ||
|
|
06ebe954f1 | ||
|
|
48d4668575 |
@@ -2,7 +2,7 @@ allprojects {
|
|||||||
apply plugin: 'findbugs'
|
apply plugin: 'findbugs'
|
||||||
|
|
||||||
group = 'com.lyndir.masterpassword'
|
group = 'com.lyndir.masterpassword'
|
||||||
version = '2.7.8'
|
version = '2.7.9'
|
||||||
|
|
||||||
tasks.withType( JavaCompile ) {
|
tasks.withType( JavaCompile ) {
|
||||||
options.encoding = 'UTF-8'
|
options.encoding = 'UTF-8'
|
||||||
|
|||||||
2
platform-darwin/External/Pearl
vendored
2
platform-darwin/External/Pearl
vendored
Submodule platform-darwin/External/Pearl updated: b713577cd6...bc737d41fa
@@ -1,10 +1,14 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
#
|
#
|
||||||
# USAGE
|
# USAGE
|
||||||
# [targets='...'] [mpw_feature=0|1 ...] [CFLAGS='...'] [LDFLAGS='...'] ./build [cc arguments ...]
|
# [targets='...'] [mpw_feature=0|1 ...] [CFLAGS='...'] [LDFLAGS='...'] ./build [-v|-d|-h|--] [cc arguments ...]
|
||||||
#
|
#
|
||||||
# By default, you should only need to run ./build
|
# By default, you should only need to run ./build
|
||||||
#
|
#
|
||||||
|
# -v: verbose mode, outputs state information and compiler commands.
|
||||||
|
# -d: debug build, modifies default build flags to produce binaries best suited for debugging.
|
||||||
|
# -h: show this usage information.
|
||||||
|
#
|
||||||
# You can customize the targets that are built using targets='...'. Use targets='all' to build all targets.
|
# You can customize the targets that are built using targets='...'. Use targets='all' to build all targets.
|
||||||
# By default, we only build the 'mpw' target.
|
# By default, we only build the 'mpw' target.
|
||||||
# See targets_all for all possible targets as well as the features they support and require.
|
# See targets_all for all possible targets as well as the features they support and require.
|
||||||
@@ -27,29 +31,53 @@ set -e
|
|||||||
|
|
||||||
|
|
||||||
### CONFIGURATION
|
### CONFIGURATION
|
||||||
# Targets to build.
|
verbose=0
|
||||||
|
|
||||||
|
# Options
|
||||||
|
while getopts :vdh opt; do
|
||||||
|
case $opt in
|
||||||
|
v) verbose=1 ;;
|
||||||
|
d) debug=1 ;;
|
||||||
|
h|?) sed -n '/^[^#]/q;p' "${BASH_SOURCE##*/}"; exit ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
shift "$(( OPTIND - 1 ))"
|
||||||
|
|
||||||
|
# Targets to build
|
||||||
targets_all=(
|
targets_all=(
|
||||||
mpw # C CLI version of Master Password (needs: mpw_sodium, optional: mpw_color, mpw_json).
|
mpw # C CLI version of Master Password (needs: mpw_sodium, optional: mpw_color, mpw_json).
|
||||||
mpw-bench # C CLI Master Password benchmark utility (needs: mpw_sodium).
|
mpw-bench # C CLI Master Password benchmark utility (needs: mpw_sodium).
|
||||||
mpw-tests # C Master Password algorithm test suite (needs: mpw_sodium, mpw_xml).
|
mpw-tests # C Master Password algorithm test suite (needs: mpw_sodium, mpw_xml).
|
||||||
)
|
)
|
||||||
targets_default='mpw' # Override with: targets='...' ./build
|
targets_default='mpw' # Override with: targets='...' ./build
|
||||||
|
targets=${targets[*]:-$targets_default}
|
||||||
|
|
||||||
# Features.
|
# Features
|
||||||
mpw_sodium=${mpw_sodium:-1} # Implement crypto functions with sodium (depends on libsodium).
|
mpw_sodium=${mpw_sodium:-1} # Implement crypto functions with sodium (depends on libsodium).
|
||||||
mpw_json=${mpw_json:-1} # Support JSON-based user configuration format (depends on libjson-c).
|
mpw_json=${mpw_json:-1} # Support JSON-based user configuration format (depends on libjson-c).
|
||||||
mpw_color=${mpw_color:-1} # Colorized identicon (depends on libncurses).
|
mpw_color=${mpw_color:-1} # Colorized identicon (depends on libncurses).
|
||||||
mpw_xml=${mpw_xml:-1} # XML parsing (depends on libxml2).
|
mpw_xml=${mpw_xml:-1} # XML parsing (depends on libxml2).
|
||||||
|
|
||||||
# Default build flags.
|
# Default build flags
|
||||||
cflags=( -O3 $CFLAGS )
|
cflags=( -O3 $CFLAGS ); unset CFLAGS
|
||||||
ldflags=( $LDFLAGS )
|
ldflags=( $LDFLAGS ); unset LDFLAGS
|
||||||
|
if (( debug )); then
|
||||||
|
cflags+=( -O0 -g )
|
||||||
|
fi
|
||||||
|
|
||||||
# Version.
|
# Version
|
||||||
if { mpw_version=$(git describe --match '*-cli*' --long --dirty) || mpw_version=$(<VERSION); } 2>/dev/null; then
|
if { mpw_version=$(git describe --match '*-cli*' --long --dirty) || mpw_version=$(<VERSION); } 2>/dev/null; then
|
||||||
cflags+=( -D"MP_VERSION=$mpw_version" )
|
cflags+=( -D"MP_VERSION=$mpw_version" )
|
||||||
fi
|
fi
|
||||||
echo 2>&1 "Current mpw source version ${mpw_version:-<unknown>}..."
|
echo "Current mpw source version ${mpw_version:-<unknown>}..."
|
||||||
|
|
||||||
|
# Meta
|
||||||
|
if (( verbose )); then
|
||||||
|
echo "mpw_sodium=${mpw_sodium}, mpw_json=${mpw_json}, mpw_color=${mpw_color}, mpw_xml=${mpw_xml}"
|
||||||
|
echo "CFLAGS: ${cflags[*]}"
|
||||||
|
echo "LDFLAGS: ${ldflags[*]}"
|
||||||
|
echo "targets: ${targets[*]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
### TARGET: MPW
|
### TARGET: MPW
|
||||||
@@ -132,18 +160,20 @@ mpw-tests() {
|
|||||||
haslib() {
|
haslib() {
|
||||||
cc -x c "${ldflags[@]}" -l"$1" -o /dev/null - <<< 'int main() { return 0; }' &>/dev/null
|
cc -x c "${ldflags[@]}" -l"$1" -o /dev/null - <<< 'int main() { return 0; }' &>/dev/null
|
||||||
}
|
}
|
||||||
cc() {
|
cc() (
|
||||||
if hash llvm-gcc 2>/dev/null; then
|
(( verbose )) && set -x
|
||||||
|
|
||||||
|
if { hash llvm-gcc; } 2>/dev/null; then
|
||||||
llvm-gcc "$@"
|
llvm-gcc "$@"
|
||||||
elif hash gcc 2>/dev/null; then
|
elif { hash gcc; } 2>/dev/null; then
|
||||||
gcc -std=c11 "$@"
|
gcc -std=c11 "$@"
|
||||||
elif hash clang 2>/dev/null; then
|
elif { hash clang; } 2>/dev/null; then
|
||||||
clang "$@"
|
clang "$@"
|
||||||
else
|
else
|
||||||
echo >&2 "Need a compiler. Please install GCC or LLVM."
|
echo >&2 "Need a compiler. Please install GCC or LLVM."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
### DEPENDENCIES
|
### DEPENDENCIES
|
||||||
@@ -156,7 +186,7 @@ use() {
|
|||||||
for lib in "$lib" "$@"; do
|
for lib in "$lib" "$@"; do
|
||||||
haslib "$lib" && ldflags+=( -l"$lib" )
|
haslib "$lib" && ldflags+=( -l"$lib" )
|
||||||
done
|
done
|
||||||
echo >&2 "INFO: Enabled $option (lib$lib)."
|
echo "INFO: Enabled $option (lib$lib)."
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
elif [[ $requisite == required ]]; then
|
elif [[ $requisite == required ]]; then
|
||||||
@@ -174,7 +204,7 @@ use() {
|
|||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
else
|
else
|
||||||
echo >&2 "INFO: $option is supported but not enabled."
|
echo "INFO: $option is supported but not enabled."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -192,13 +222,13 @@ use_mpw_json() {
|
|||||||
}
|
}
|
||||||
use_mpw_xml() {
|
use_mpw_xml() {
|
||||||
local requisite=$1
|
local requisite=$1
|
||||||
use mpw_xml "$requisite" xml2 && cflags+=( -D"MPW_XML=1" -I"/usr/include/libxml2" -I"/usr/local/include/libxml2" ) ||:
|
use mpw_xml "$requisite" xml2 && cflags+=( $(xml2-config --cflags) ) ldflags+=( $(xml2-config --libs) ) ||:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
### BUILD TARGETS
|
### BUILD TARGETS
|
||||||
for target in "${targets_all[@]}"; do
|
for target in "${targets_all[@]}"; do
|
||||||
if [[ ${targets:-$targets_default} == 'all' || " ${targets:-$targets_default} " = *" $target "* ]]; then
|
if [[ $targets == 'all' || " $targets " = *" $target "* ]]; then
|
||||||
echo
|
echo
|
||||||
echo "Building target: $target..."
|
echo "Building target: $target..."
|
||||||
( "$target" "$@" )
|
( "$target" "$@" )
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ const char *mpw_getenv(const char *variableName) {
|
|||||||
return envBuf? mpw_strdup( envBuf ): NULL;
|
return envBuf? mpw_strdup( envBuf ): NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *mpw_askpass(const char *prompt) {
|
const char *mpw_askpass(const char *prompt) {
|
||||||
|
|
||||||
const char *askpass = mpw_getenv( MP_ENV_askpass );
|
const char *askpass = mpw_getenv( MP_ENV_askpass );
|
||||||
if (!askpass)
|
if (!askpass)
|
||||||
@@ -74,7 +74,7 @@ char *mpw_askpass(const char *prompt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
close( pipes[1] );
|
close( pipes[1] );
|
||||||
char *answer = mpw_read_fd( pipes[0] );
|
const char *answer = mpw_read_fd( pipes[0] );
|
||||||
close( pipes[0] );
|
close( pipes[0] );
|
||||||
int status;
|
int status;
|
||||||
if (waitpid( pid, &status, 0 ) == ERR) {
|
if (waitpid( pid, &status, 0 ) == ERR) {
|
||||||
@@ -86,7 +86,7 @@ char *mpw_askpass(const char *prompt) {
|
|||||||
if (WIFEXITED( status ) && WEXITSTATUS( status ) == EXIT_SUCCESS && answer && strlen( answer )) {
|
if (WIFEXITED( status ) && WEXITSTATUS( status ) == EXIT_SUCCESS && answer && strlen( answer )) {
|
||||||
// Remove trailing newline.
|
// Remove trailing newline.
|
||||||
if (answer[strlen( answer ) - 1] == '\n')
|
if (answer[strlen( answer ) - 1] == '\n')
|
||||||
answer[strlen( answer ) - 1] = '\0';
|
mpw_replace_string( answer, mpw_strndup( answer, strlen( answer ) - 1 ) );
|
||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,71 +97,74 @@ char *mpw_askpass(const char *prompt) {
|
|||||||
static const char *_mpw_getline(const char *prompt, bool silent) {
|
static const char *_mpw_getline(const char *prompt, bool silent) {
|
||||||
|
|
||||||
// Get answer from askpass.
|
// Get answer from askpass.
|
||||||
char *answer = mpw_askpass( prompt );
|
const char *answer = mpw_askpass( prompt );
|
||||||
if (answer)
|
if (answer)
|
||||||
return answer;
|
return answer;
|
||||||
|
|
||||||
#if MPW_COLOR
|
#if MPW_COLOR
|
||||||
// Initialize a curses screen.
|
// Initialize a curses screen.
|
||||||
SCREEN *screen = newterm( NULL, stderr, stdin );
|
SCREEN *screen = newterm( NULL, stderr, stdin );
|
||||||
start_color();
|
if (screen) {
|
||||||
init_pair( 1, COLOR_WHITE, COLOR_BLUE );
|
start_color();
|
||||||
init_pair( 2, COLOR_BLACK, COLOR_WHITE );
|
init_pair( 1, COLOR_WHITE, COLOR_BLUE );
|
||||||
int rows, cols;
|
init_pair( 2, COLOR_BLACK, COLOR_WHITE );
|
||||||
getmaxyx( stdscr, rows, cols );
|
int rows, cols;
|
||||||
|
getmaxyx( stdscr, rows, cols );
|
||||||
|
|
||||||
// Display a dialog box.
|
// Display a dialog box.
|
||||||
int width = max( prompt? (int)strlen( prompt ): 0, MPW_MAX_INPUT ) + 6;
|
int width = max( prompt? (int)strlen( prompt ): 0, MPW_MAX_INPUT ) + 6;
|
||||||
char *version = "mpw v" stringify_def( MP_VERSION );
|
char *version = "mpw v" stringify_def( MP_VERSION );
|
||||||
mvprintw( rows - 1, (cols - (int)strlen( version )) / 2, "%s", version );
|
mvprintw( rows - 1, (cols - (int)strlen( version )) / 2, "%s", version );
|
||||||
attron( A_BOLD );
|
attron( A_BOLD );
|
||||||
color_set( 2, NULL );
|
color_set( 2, NULL );
|
||||||
mvprintw( rows / 2 - 1, (cols - width) / 2, "%s%*s%s", "*", width - 2, "", "*" );
|
mvprintw( rows / 2 - 1, (cols - width) / 2, "%s%*s%s", "*", width - 2, "", "*" );
|
||||||
mvprintw( rows / 2 - 1, (cols - (int)strlen( prompt )) / 2, "%s", prompt );
|
mvprintw( rows / 2 - 1, (cols - (int)strlen( prompt )) / 2, "%s", prompt );
|
||||||
color_set( 1, NULL );
|
color_set( 1, NULL );
|
||||||
mvprintw( rows / 2 + 0, (cols - width) / 2, "%s%*s%s", "|", width - 2, "", "|" );
|
mvprintw( rows / 2 + 0, (cols - width) / 2, "%s%*s%s", "|", width - 2, "", "|" );
|
||||||
mvprintw( rows / 2 + 1, (cols - width) / 2, "%s%*s%s", "|", width - 2, "", "|" );
|
mvprintw( rows / 2 + 1, (cols - width) / 2, "%s%*s%s", "|", width - 2, "", "|" );
|
||||||
mvprintw( rows / 2 + 2, (cols - width) / 2, "%s%*s%s", "|", width - 2, "", "|" );
|
mvprintw( rows / 2 + 2, (cols - width) / 2, "%s%*s%s", "|", width - 2, "", "|" );
|
||||||
|
|
||||||
// Read response.
|
// Read response.
|
||||||
color_set( 2, NULL );
|
color_set( 2, NULL );
|
||||||
attron( A_STANDOUT );
|
attron( A_STANDOUT );
|
||||||
int result = ERR;
|
int result = ERR;
|
||||||
char str[MPW_MAX_INPUT + 1];
|
char str[MPW_MAX_INPUT + 1];
|
||||||
if (silent) {
|
if (silent) {
|
||||||
mvprintw( rows / 2 + 1, (cols - 5) / 2, "[ * ]" );
|
mvprintw( rows / 2 + 1, (cols - 5) / 2, "[ * ]" );
|
||||||
refresh();
|
refresh();
|
||||||
|
|
||||||
noecho();
|
noecho();
|
||||||
result = mvgetnstr( rows / 2 + 1, (cols - 1) / 2, str, MPW_MAX_INPUT );
|
result = mvgetnstr( rows / 2 + 1, (cols - 1) / 2, str, MPW_MAX_INPUT );
|
||||||
echo();
|
echo();
|
||||||
} else {
|
}
|
||||||
mvprintw( rows / 2 + 1, (cols - (MPW_MAX_INPUT + 2)) / 2, "%*s", MPW_MAX_INPUT + 2, "" );
|
else {
|
||||||
refresh();
|
mvprintw( rows / 2 + 1, (cols - (MPW_MAX_INPUT + 2)) / 2, "%*s", MPW_MAX_INPUT + 2, "" );
|
||||||
|
refresh();
|
||||||
|
|
||||||
echo();
|
echo();
|
||||||
result = mvgetnstr( rows / 2 + 1, (cols - MPW_MAX_INPUT) / 2, str, MPW_MAX_INPUT );
|
result = mvgetnstr( rows / 2 + 1, (cols - MPW_MAX_INPUT) / 2, str, MPW_MAX_INPUT );
|
||||||
|
}
|
||||||
|
attrset( 0 );
|
||||||
|
endwin();
|
||||||
|
delscreen( screen );
|
||||||
|
|
||||||
|
return result == ERR? NULL: mpw_strndup( str, MPW_MAX_INPUT );
|
||||||
}
|
}
|
||||||
attrset( 0 );
|
#endif
|
||||||
endwin();
|
|
||||||
delscreen( screen );
|
|
||||||
|
|
||||||
return result == ERR? NULL: mpw_strndup( str, MPW_MAX_INPUT );
|
|
||||||
#else
|
|
||||||
// Get password from terminal.
|
// Get password from terminal.
|
||||||
fprintf( stderr, "%s ", prompt );
|
fprintf( stderr, "%s ", prompt );
|
||||||
|
|
||||||
size_t bufSize = 0;
|
size_t bufSize = 0;
|
||||||
ssize_t lineSize = getline( &answer, &bufSize, stdin );
|
ssize_t lineSize = getline( (char **)&answer, &bufSize, stdin );
|
||||||
if (lineSize <= 1) {
|
if (lineSize <= 1) {
|
||||||
mpw_free_string( &answer );
|
mpw_free_string( &answer );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove trailing newline.
|
// Remove trailing newline.
|
||||||
answer[lineSize - 1] = '\0';
|
mpw_replace_string( answer, mpw_strndup( answer, (size_t)lineSize - 1 ) );
|
||||||
return answer;
|
return answer;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *mpw_getline(const char *prompt) {
|
const char *mpw_getline(const char *prompt) {
|
||||||
@@ -250,7 +253,7 @@ bool mpw_mkdirs(const char *filePath) {
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *mpw_read_fd(int fd) {
|
const char *mpw_read_fd(int fd) {
|
||||||
|
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
size_t blockSize = 4096, bufSize = 0, bufOffset = 0;
|
size_t blockSize = 4096, bufSize = 0, bufOffset = 0;
|
||||||
@@ -263,7 +266,7 @@ char *mpw_read_fd(int fd) {
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *mpw_read_file(FILE *file) {
|
const char *mpw_read_file(FILE *file) {
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const char *mpw_getenv(const char *variableName);
|
|||||||
|
|
||||||
/** Use the askpass program to prompt the user.
|
/** Use the askpass program to prompt the user.
|
||||||
* @return A newly allocated string or NULL if askpass is not supported or an error occurred. */
|
* @return A newly allocated string or NULL if askpass is not supported or an error occurred. */
|
||||||
char *mpw_askpass(const char *prompt);
|
const char *mpw_askpass(const char *prompt);
|
||||||
|
|
||||||
/** Ask the user a question.
|
/** Ask the user a question.
|
||||||
* @return A newly allocated string or NULL if an error occurred trying to read from the user. */
|
* @return A newly allocated string or NULL if an error occurred trying to read from the user. */
|
||||||
@@ -58,11 +58,11 @@ bool mpw_mkdirs(const char *filePath);
|
|||||||
|
|
||||||
/** Read until EOF from the given file descriptor.
|
/** Read until EOF from the given file descriptor.
|
||||||
* @return A newly allocated string or NULL the read buffer couldn't be allocated. */
|
* @return A newly allocated string or NULL the read buffer couldn't be allocated. */
|
||||||
char *mpw_read_fd(int fd);
|
const char *mpw_read_fd(int fd);
|
||||||
|
|
||||||
/** Read the file contents of a given file.
|
/** Read the file contents of a given file.
|
||||||
* @return A newly allocated string or NULL the read buffer couldn't be allocated. */
|
* @return A newly allocated string or NULL the read buffer couldn't be allocated. */
|
||||||
char *mpw_read_file(FILE *file);
|
const char *mpw_read_file(FILE *file);
|
||||||
|
|
||||||
/** Encode a visual fingerprint for a user.
|
/** Encode a visual fingerprint for a user.
|
||||||
* @return A newly allocated string. */
|
* @return A newly allocated string. */
|
||||||
|
|||||||
@@ -476,8 +476,8 @@ void cli_user(Arguments *args, Operation *operation) {
|
|||||||
|
|
||||||
else {
|
else {
|
||||||
// Read file.
|
// Read file.
|
||||||
char *sitesInputData = mpw_read_file( sitesFile );
|
const char *sitesInputData = mpw_read_file( sitesFile );
|
||||||
if (ferror( sitesFile ))
|
if (!sitesInputData || ferror( sitesFile ))
|
||||||
wrn( "Error while reading configuration file:\n %s: %d", operation->sitesPath, ferror( sitesFile ) );
|
wrn( "Error while reading configuration file:\n %s: %d", operation->sitesPath, ferror( sitesFile ) );
|
||||||
fclose( sitesFile );
|
fclose( sitesFile );
|
||||||
|
|
||||||
|
|||||||
@@ -115,6 +115,8 @@ bool mpw_string_pushf(
|
|||||||
/** Push an integer onto a buffer. reallocs the given buffer and appends the given integer. */
|
/** Push an integer onto a buffer. reallocs the given buffer and appends the given integer. */
|
||||||
bool mpw_push_int(
|
bool mpw_push_int(
|
||||||
uint8_t **buffer, size_t *bufferSize, const uint32_t pushInt);
|
uint8_t **buffer, size_t *bufferSize, const uint32_t pushInt);
|
||||||
|
|
||||||
|
// These defines merely exist to force the void** cast (& do type-checking), since void** casts are not automatic.
|
||||||
/** Reallocate the given buffer from the given size by adding the delta size.
|
/** Reallocate the given buffer from the given size by adding the delta size.
|
||||||
* On success, the buffer size pointer will be updated to the buffer's new size
|
* On success, the buffer size pointer will be updated to the buffer's new size
|
||||||
* and the buffer pointer may be updated to a new memory address.
|
* and the buffer pointer may be updated to a new memory address.
|
||||||
@@ -124,26 +126,26 @@ bool mpw_push_int(
|
|||||||
* @param deltaSize The amount to increase the buffer's size by.
|
* @param deltaSize The amount to increase the buffer's size by.
|
||||||
* @return true if successful, false if reallocation failed.
|
* @return true if successful, false if reallocation failed.
|
||||||
*/
|
*/
|
||||||
#define mpw_realloc(buffer, bufferSize, deltaSize) \
|
#define mpw_realloc( \
|
||||||
|
/* const void** */buffer, /* size_t* */bufferSize, /* const size_t */deltaSize) \
|
||||||
({ __typeof__(buffer) _b = buffer; const void *__b = *_b; (void)__b; __mpw_realloc( (const void **)_b, bufferSize, deltaSize ); })
|
({ __typeof__(buffer) _b = buffer; const void *__b = *_b; (void)__b; __mpw_realloc( (const void **)_b, bufferSize, deltaSize ); })
|
||||||
bool __mpw_realloc(const void **buffer, size_t *bufferSize, const size_t deltaSize);
|
|
||||||
void mpw_zero(
|
|
||||||
void *buffer, size_t bufferSize);
|
|
||||||
/** Free a buffer after zero'ing its contents, then set the reference to NULL. */
|
/** Free a buffer after zero'ing its contents, then set the reference to NULL. */
|
||||||
#define mpw_free(buffer, bufferSize) \
|
#define mpw_free( \
|
||||||
|
/* void** */buffer, /* size_t */ bufferSize) \
|
||||||
({ __typeof__(buffer) _b = buffer; const void *__b = *_b; (void)__b; __mpw_free( (void **)_b, bufferSize ); })
|
({ __typeof__(buffer) _b = buffer; const void *__b = *_b; (void)__b; __mpw_free( (void **)_b, bufferSize ); })
|
||||||
bool __mpw_free(
|
|
||||||
void **buffer, size_t bufferSize);
|
|
||||||
/** Free a string after zero'ing its contents, then set the reference to NULL. */
|
/** Free a string after zero'ing its contents, then set the reference to NULL. */
|
||||||
#define mpw_free_string(string) \
|
#define mpw_free_string( \
|
||||||
|
/* char** */string) \
|
||||||
({ __typeof__(string) _s = string; const char *__s = *_s; (void)__s; __mpw_free_string( (char **)_s ); })
|
({ __typeof__(string) _s = string; const char *__s = *_s; (void)__s; __mpw_free_string( (char **)_s ); })
|
||||||
bool __mpw_free_string(
|
|
||||||
char **string);
|
|
||||||
/** Free strings after zero'ing their contents, then set the references to NULL. Terminate the va_list with NULL. */
|
/** Free strings after zero'ing their contents, then set the references to NULL. Terminate the va_list with NULL. */
|
||||||
#define mpw_free_strings(strings, ...) \
|
#define mpw_free_strings( \
|
||||||
|
/* char** */strings, ...) \
|
||||||
({ __typeof__(strings) _s = strings; const char *__s = *_s; (void)__s; __mpw_free_strings( (char **)_s, __VA_ARGS__ ); })
|
({ __typeof__(strings) _s = strings; const char *__s = *_s; (void)__s; __mpw_free_strings( (char **)_s, __VA_ARGS__ ); })
|
||||||
bool __mpw_free_strings(
|
/** Free a string after zero'ing its contents, then set the reference to the replacement string.
|
||||||
char **strings, ...);
|
* The replacement string is generated before the original is freed; it may be a derivative of the original. */
|
||||||
|
#define mpw_replace_string( \
|
||||||
|
/* char* */string, /* char* */replacement) \
|
||||||
|
do { const char *replacement_ = replacement; mpw_free_string( &string ); string = replacement_; } while (0)
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#undef mpw_realloc
|
#undef mpw_realloc
|
||||||
#define mpw_realloc(buffer, bufferSize, deltaSize) \
|
#define mpw_realloc(buffer, bufferSize, deltaSize) \
|
||||||
@@ -158,6 +160,16 @@ bool __mpw_free_strings(
|
|||||||
#define mpw_free_strings(strings, ...) \
|
#define mpw_free_strings(strings, ...) \
|
||||||
__mpw_free_strings( (char **)strings, __VA_ARGS__ )
|
__mpw_free_strings( (char **)strings, __VA_ARGS__ )
|
||||||
#endif
|
#endif
|
||||||
|
bool __mpw_realloc(
|
||||||
|
const void **buffer, size_t *bufferSize, const size_t deltaSize);
|
||||||
|
bool __mpw_free(
|
||||||
|
void **buffer, size_t bufferSize);
|
||||||
|
bool __mpw_free_string(
|
||||||
|
char **string);
|
||||||
|
bool __mpw_free_strings(
|
||||||
|
char **strings, ...);
|
||||||
|
void mpw_zero(
|
||||||
|
void *buffer, size_t bufferSize);
|
||||||
|
|
||||||
//// Cryptographic functions.
|
//// Cryptographic functions.
|
||||||
|
|
||||||
|
|||||||
@@ -147,6 +147,7 @@ public class MPMasterKey {
|
|||||||
* @return {@code null} if the result type is missing a required parameter.
|
* @return {@code null} if the result type is missing a required parameter.
|
||||||
*
|
*
|
||||||
* @throws MPKeyUnavailableException {@link #invalidate()} has been called on this object.
|
* @throws MPKeyUnavailableException {@link #invalidate()} has been called on this object.
|
||||||
|
* @throws MPAlgorithmException An internal system or algorithm error has occurred.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public String siteResult(final String siteName, final MPAlgorithm algorithm, final UnsignedInteger siteCounter,
|
public String siteResult(final String siteName, final MPAlgorithm algorithm, final UnsignedInteger siteCounter,
|
||||||
@@ -184,6 +185,7 @@ public class MPMasterKey {
|
|||||||
* {@link #siteResult(String, MPAlgorithm, UnsignedInteger, MPKeyPurpose, String, MPResultType, String)}.
|
* {@link #siteResult(String, MPAlgorithm, UnsignedInteger, MPKeyPurpose, String, MPResultType, String)}.
|
||||||
*
|
*
|
||||||
* @throws MPKeyUnavailableException {@link #invalidate()} has been called on this object.
|
* @throws MPKeyUnavailableException {@link #invalidate()} has been called on this object.
|
||||||
|
* @throws MPAlgorithmException An internal system or algorithm error has occurred.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public String siteState(final String siteName, final MPAlgorithm algorithm, final UnsignedInteger siteCounter,
|
public String siteState(final String siteName, final MPAlgorithm algorithm, final UnsignedInteger siteCounter,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.lyndir.masterpassword.gui.model;
|
package com.lyndir.masterpassword.gui.model;
|
||||||
|
|
||||||
import com.lyndir.masterpassword.model.*;
|
import com.lyndir.masterpassword.model.*;
|
||||||
import com.lyndir.masterpassword.model.impl.*;
|
import com.lyndir.masterpassword.model.impl.MPBasicSite;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
|
||||||
@@ -19,4 +19,14 @@ public class MPNewSite extends MPBasicSite<MPUser<?>, MPQuestion> {
|
|||||||
public MPQuestion addQuestion(final String keyword) {
|
public MPQuestion addQuestion(final String keyword) {
|
||||||
throw new UnsupportedOperationException( "Cannot add a question to a site that hasn't been created yet." );
|
throw new UnsupportedOperationException( "Cannot add a question to a site that hasn't been created yet." );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <S extends MPSite<?>> S addTo(final MPUser<S> user) {
|
||||||
|
S site = user.addSite( getSiteName() );
|
||||||
|
site.setAlgorithm( getAlgorithm() );
|
||||||
|
site.setCounter( getCounter() );
|
||||||
|
site.setLoginType( getLoginType() );
|
||||||
|
site.setResultType( getResultType() );
|
||||||
|
|
||||||
|
return site;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,10 +46,10 @@ public abstract class Components {
|
|||||||
|
|
||||||
private static final Logger logger = Logger.get( Components.class );
|
private static final Logger logger = Logger.get( Components.class );
|
||||||
|
|
||||||
public static final float TEXT_SIZE_HEADING = 19f;
|
public static final int TEXT_SIZE_HEADING = 19;
|
||||||
public static final float TEXT_SIZE_CONTROL = 13f;
|
public static final int TEXT_SIZE_CONTROL = 13;
|
||||||
public static final int SIZE_MARGIN = 12;
|
public static final int SIZE_MARGIN = 12;
|
||||||
public static final int SIZE_PADDING = 8;
|
public static final int SIZE_PADDING = 8;
|
||||||
|
|
||||||
public static GradientPanel panel(final Component... components) {
|
public static GradientPanel panel(final Component... components) {
|
||||||
GradientPanel panel = panel( BoxLayout.LINE_AXIS, null, components );
|
GradientPanel panel = panel( BoxLayout.LINE_AXIS, null, components );
|
||||||
@@ -426,10 +426,18 @@ public abstract class Components {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static JCheckBox checkBox(final String label) {
|
public static JCheckBox checkBox(final String label) {
|
||||||
|
return checkBox( label, false, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JCheckBox checkBox(final String label, final boolean selected, @Nullable final Consumer<Boolean> selectionConsumer) {
|
||||||
return new JCheckBox( label ) {
|
return new JCheckBox( label ) {
|
||||||
{
|
{
|
||||||
setBackground( null );
|
setBackground( null );
|
||||||
setAlignmentX( LEFT_ALIGNMENT );
|
setAlignmentX( LEFT_ALIGNMENT );
|
||||||
|
setSelected( selected );
|
||||||
|
|
||||||
|
if (selectionConsumer != null)
|
||||||
|
addItemListener( e -> selectionConsumer.accept( isSelected() ) );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,15 +20,12 @@ package com.lyndir.masterpassword.gui.util;
|
|||||||
|
|
||||||
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.io.Resources;
|
import com.google.common.io.Resources;
|
||||||
import com.google.common.util.concurrent.*;
|
import com.google.common.util.concurrent.*;
|
||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
import com.lyndir.masterpassword.MPIdenticon;
|
import com.lyndir.masterpassword.MPIdenticon;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.ref.SoftReference;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -184,88 +181,67 @@ public abstract class Res {
|
|||||||
|
|
||||||
public static final class Fonts {
|
public static final class Fonts {
|
||||||
|
|
||||||
public Font emoticonsFont(final float size) {
|
public Font emoticonsFont(final int size) {
|
||||||
return emoticonsRegular().deriveFont( size );
|
return MPFont.emoticonsRegular.get( size );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Font controlFont(final float size) {
|
public Font controlFont(final int size) {
|
||||||
return exoRegular().deriveFont( size );
|
return MPFont.exoRegular.get( size );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Font valueFont(final float size) {
|
public Font valueFont(final int size) {
|
||||||
return sourceSansProRegular().deriveFont( size );
|
return MPFont.sourceSansProRegular.get( size );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Font bigValueFont(final float size) {
|
public Font bigValueFont(final int size) {
|
||||||
return sourceSansProBlack().deriveFont( size );
|
return MPFont.sourceSansProBlack.get( size );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Font emoticonsRegular() {
|
private enum MPFont {
|
||||||
return font( "fonts/Emoticons-Regular.otf" );
|
emoticonsRegular( "Emoticons", "fonts/Emoticons-Regular.otf" ),
|
||||||
}
|
sourceCodeProRegular( "Source Code Pro", "fonts/SourceCodePro-Regular.otf" ),
|
||||||
|
sourceCodeProBlack( "Source Code Pro Bold", "fonts/SourceCodePro-Bold.otf" ),
|
||||||
|
sourceSansProRegular( "Source Sans Pro", "fonts/SourceSansPro-Regular.otf" ),
|
||||||
|
sourceSansProBlack( "Source Sans Pro Bold", "fonts/SourceSansPro-Bold.otf" ),
|
||||||
|
exoBold( "Exo 2.0 Bold", "fonts/Exo2.0-Bold.otf" ),
|
||||||
|
exoExtraBold( "Exo 2.0 Extra Bold", "fonts/Exo2.0-ExtraBold.otf" ),
|
||||||
|
exoRegular( "Exo 2.0", "fonts/Exo2.0-Regular.otf" ),
|
||||||
|
exoThin( "Exo 2.0 Thin", "fonts/Exo2.0-Thin.otf" ),
|
||||||
|
arimoBold( "Arimo Bold", "fonts/Arimo-Bold.ttf" ),
|
||||||
|
arimoBoldItalic( "Arimo Bold Italic", "fonts/Arimo-BoldItalic.ttf" ),
|
||||||
|
arimoItalic( "Arimo Italic", "fonts/Arimo-Italic.ttf" ),
|
||||||
|
arimoRegular( "Arimo", "fonts/Arimo-Regular.ttf" );
|
||||||
|
|
||||||
public Font sourceCodeProRegular() {
|
private final String fontName;
|
||||||
return font( "fonts/SourceCodePro-Regular.otf" );
|
private final String resourceName;
|
||||||
}
|
private boolean registered;
|
||||||
|
|
||||||
public Font sourceCodeProBlack() {
|
MPFont(final String fontName, final String resourceName) {
|
||||||
return font( "fonts/SourceCodePro-Bold.otf" );
|
this.fontName = fontName;
|
||||||
}
|
this.resourceName = resourceName;
|
||||||
|
}
|
||||||
|
|
||||||
public Font sourceSansProRegular() {
|
Font get(final int size) {
|
||||||
return font( "fonts/SourceSansPro-Regular.otf" );
|
return get( Font.PLAIN, size );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Font sourceSansProBlack() {
|
Font get(final int style, final int size) {
|
||||||
return font( "fonts/SourceSansPro-Bold.otf" );
|
if (!registered)
|
||||||
}
|
register();
|
||||||
|
|
||||||
public Font exoBold() {
|
return new Font( fontName, style, size );
|
||||||
return font( "fonts/Exo2.0-Bold.otf" );
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public Font exoExtraBold() {
|
private void register() {
|
||||||
return font( "fonts/Exo2.0-ExtraBold.otf" );
|
|
||||||
}
|
|
||||||
|
|
||||||
public Font exoRegular() {
|
|
||||||
return font( "fonts/Exo2.0-Regular.otf" );
|
|
||||||
}
|
|
||||||
|
|
||||||
public Font exoThin() {
|
|
||||||
return font( "fonts/Exo2.0-Thin.otf" );
|
|
||||||
}
|
|
||||||
|
|
||||||
public Font arimoBold() {
|
|
||||||
return font( "fonts/Arimo-Bold.ttf" );
|
|
||||||
}
|
|
||||||
|
|
||||||
public Font arimoBoldItalic() {
|
|
||||||
return font( "fonts/Arimo-BoldItalic.ttf" );
|
|
||||||
}
|
|
||||||
|
|
||||||
public Font arimoItalic() {
|
|
||||||
return font( "fonts/Arimo-Italic.ttf" );
|
|
||||||
}
|
|
||||||
|
|
||||||
public Font arimoRegular() {
|
|
||||||
return font( "fonts/Arimo-Regular.ttf" );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Font font(@NonNls final String fontResourceName) {
|
|
||||||
Map<String, SoftReference<Font>> fontsByResourceName = Maps.newHashMap();
|
|
||||||
SoftReference<Font> fontRef = fontsByResourceName.get( fontResourceName );
|
|
||||||
Font font = (fontRef == null)? null: fontRef.get();
|
|
||||||
if (font == null)
|
|
||||||
try {
|
try {
|
||||||
fontsByResourceName.put( fontResourceName, new SoftReference<>(
|
Font font = Font.createFont( Font.TRUETYPE_FONT, Resources.getResource( resourceName ).openStream() );
|
||||||
font = Font.createFont( Font.TRUETYPE_FONT, Resources.getResource( fontResourceName ).openStream() ) ) );
|
GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont( font );
|
||||||
|
registered = true;
|
||||||
}
|
}
|
||||||
catch (final FontFormatException | IOException e) {
|
catch (final FontFormatException | IOException e) {
|
||||||
throw logger.bug( e );
|
throw logger.bug( e );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return font;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import java.util.*;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
@@ -47,6 +48,7 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
|
|||||||
private static final Logger logger = Logger.get( UserContentPanel.class );
|
private static final Logger logger = Logger.get( UserContentPanel.class );
|
||||||
private static final JButton iconButton = Components.button( Res.icons().user(), null, null );
|
private static final JButton iconButton = Components.button( Res.icons().user(), null, null );
|
||||||
private static final KeyStroke copyLoginKeyStroke = KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, InputEvent.SHIFT_DOWN_MASK );
|
private static final KeyStroke copyLoginKeyStroke = KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, InputEvent.SHIFT_DOWN_MASK );
|
||||||
|
private static final Pattern EACH_CHARACTER = Pattern.compile( "." );
|
||||||
|
|
||||||
private final JButton addButton = Components.button( Res.icons().add(), event -> addUser(),
|
private final JButton addButton = Components.button( Res.icons().add(), event -> addUser(),
|
||||||
"Add a new user to Master Password." );
|
"Add a new user to Master Password." );
|
||||||
@@ -570,17 +572,20 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
|
|||||||
public void showUserPreferences() {
|
public void showUserPreferences() {
|
||||||
ImmutableList.Builder<Component> components = ImmutableList.builder();
|
ImmutableList.Builder<Component> components = ImmutableList.builder();
|
||||||
|
|
||||||
|
components.add( Components.label( "Default Algorithm:" ),
|
||||||
|
Components.comboBox( MPAlgorithm.Version.values(), MPAlgorithm.Version::name,
|
||||||
|
user.getAlgorithm().version(),
|
||||||
|
version -> user.setAlgorithm( version.getAlgorithm() ) ) );
|
||||||
|
|
||||||
MPFileUser fileUser = (user instanceof MPFileUser)? (MPFileUser) user: null;
|
MPFileUser fileUser = (user instanceof MPFileUser)? (MPFileUser) user: null;
|
||||||
if (fileUser != null)
|
if (fileUser != null) {
|
||||||
components.add( Components.label( "Default Password Type:" ),
|
components.add( Components.label( "Default Password Type:" ),
|
||||||
Components.comboBox( MPResultType.values(), MPResultType::getLongName,
|
Components.comboBox( MPResultType.values(), MPResultType::getLongName,
|
||||||
fileUser.getDefaultType(), fileUser::setDefaultType ),
|
fileUser.getDefaultType(), fileUser::setDefaultType ),
|
||||||
Components.strut() );
|
Components.strut() );
|
||||||
|
|
||||||
components.add( Components.label( "Default Algorithm:" ),
|
components.add( Components.checkBox( "Hide Passwords", fileUser.isHidePasswords(), fileUser::setHidePasswords ) );
|
||||||
Components.comboBox( MPAlgorithm.Version.values(), MPAlgorithm.Version::name,
|
}
|
||||||
user.getAlgorithm().version(),
|
|
||||||
version -> user.setAlgorithm( version.getAlgorithm() ) ) );
|
|
||||||
|
|
||||||
Components.showDialog( this, user.getFullName(), new JOptionPane( Components.panel(
|
Components.showDialog( this, user.getFullName(), new JOptionPane( Components.panel(
|
||||||
BoxLayout.PAGE_AXIS, components.build().toArray( new Component[0] ) ) ) );
|
BoxLayout.PAGE_AXIS, components.build().toArray( new Component[0] ) ) ) );
|
||||||
@@ -846,7 +851,7 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
|
|||||||
"New Site", JOptionPane.YES_NO_OPTION ))
|
"New Site", JOptionPane.YES_NO_OPTION ))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
site = user.addSite( site.getSiteName() );
|
site = ((MPNewSite) site).addTo( user );
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean loginResult = (copyLoginKeyStroke.getModifiers() & event.getModifiers()) != 0;
|
boolean loginResult = (copyLoginKeyStroke.getModifiers() & event.getModifiers()) != 0;
|
||||||
@@ -878,7 +883,12 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
|
|||||||
else if (showLogin && (site != null))
|
else if (showLogin && (site != null))
|
||||||
resultLabel.setText( (result != null)? strf( "Your login for %s:", site.getSiteName() ): " " );
|
resultLabel.setText( (result != null)? strf( "Your login for %s:", site.getSiteName() ): " " );
|
||||||
|
|
||||||
resultField.setText( (result != null)? result: " " );
|
if ((result == null) || result.isEmpty())
|
||||||
|
resultField.setText( " " );
|
||||||
|
else if (!showLogin && (user instanceof MPFileUser) && ((MPFileUser) user).isHidePasswords())
|
||||||
|
resultField.setText( EACH_CHARACTER.matcher( result ).replaceAll( "•" ) );
|
||||||
|
else
|
||||||
|
resultField.setText( result );
|
||||||
settingsButton.setEnabled( result != null );
|
settingsButton.setEnabled( result != null );
|
||||||
questionsButton.setEnabled( result != null );
|
questionsButton.setEnabled( result != null );
|
||||||
editButton.setEnabled( result != null );
|
editButton.setEnabled( result != null );
|
||||||
@@ -1016,8 +1026,14 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener,
|
|||||||
new LinkedList<>( user.findSites( query ) );
|
new LinkedList<>( user.findSites( query ) );
|
||||||
|
|
||||||
if (!Strings.isNullOrEmpty( queryText ))
|
if (!Strings.isNullOrEmpty( queryText ))
|
||||||
if (siteItems.stream().noneMatch( MPQuery.Result::isExact ))
|
if (siteItems.stream().noneMatch( MPQuery.Result::isExact )) {
|
||||||
siteItems.add( MPQuery.Result.allOf( new MPNewSite( user, query.getQuery() ), query.getQuery() ) );
|
MPQuery.Result<? extends MPSite<?>> selectedItem = sitesModel.getSelectedItem();
|
||||||
|
if ((selectedItem != null) && user.equals( selectedItem.getOption().getUser() ) &&
|
||||||
|
queryText.equals( selectedItem.getOption().getSiteName() ))
|
||||||
|
siteItems.add( selectedItem );
|
||||||
|
else
|
||||||
|
siteItems.add( MPQuery.Result.allOf( new MPNewSite( user, query.getQuery() ), query.getQuery() ) );
|
||||||
|
}
|
||||||
|
|
||||||
Res.ui( () -> sitesModel.set( siteItems ) );
|
Res.ui( () -> sitesModel.set( siteItems ) );
|
||||||
} );
|
} );
|
||||||
|
|||||||
@@ -80,6 +80,9 @@ public interface MPSite<Q extends MPQuestion> extends Comparable<MPSite<?>> {
|
|||||||
String getResult(MPKeyPurpose keyPurpose, @Nullable String keyContext, @Nullable String state)
|
String getResult(MPKeyPurpose keyPurpose, @Nullable String keyContext, @Nullable String state)
|
||||||
throws MPKeyUnavailableException, MPAlgorithmException;
|
throws MPKeyUnavailableException, MPAlgorithmException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see MPMasterKey#siteResult(String, MPAlgorithm, UnsignedInteger, MPKeyPurpose, String, MPResultType, String)
|
||||||
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
String getResult(MPKeyPurpose keyPurpose, @Nullable String keyContext,
|
String getResult(MPKeyPurpose keyPurpose, @Nullable String keyContext,
|
||||||
@Nullable UnsignedInteger counter, MPResultType type, @Nullable String state)
|
@Nullable UnsignedInteger counter, MPResultType type, @Nullable String state)
|
||||||
@@ -90,13 +93,13 @@ public interface MPSite<Q extends MPQuestion> extends Comparable<MPSite<?>> {
|
|||||||
@Nullable UnsignedInteger counter, MPResultType type, String state)
|
@Nullable UnsignedInteger counter, MPResultType type, String state)
|
||||||
throws MPKeyUnavailableException, MPAlgorithmException;
|
throws MPKeyUnavailableException, MPAlgorithmException;
|
||||||
|
|
||||||
@Nonnull
|
@Nullable
|
||||||
default String getLogin()
|
default String getLogin()
|
||||||
throws MPKeyUnavailableException, MPAlgorithmException {
|
throws MPKeyUnavailableException, MPAlgorithmException {
|
||||||
return getLogin( null );
|
return getLogin( null );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nullable
|
||||||
String getLogin(@Nullable String state)
|
String getLogin(@Nullable String state)
|
||||||
throws MPKeyUnavailableException, MPAlgorithmException;
|
throws MPKeyUnavailableException, MPAlgorithmException;
|
||||||
|
|
||||||
|
|||||||
@@ -62,12 +62,16 @@ public abstract class MPBasicSite<U extends MPUser<?>, Q extends MPQuestion> ext
|
|||||||
this.loginType = (loginType != null)? loginType: this.algorithm.mpw_default_login_type();
|
this.loginType = (loginType != null)? loginType: this.algorithm.mpw_default_login_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - Meta
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getSiteName() {
|
public String getSiteName() {
|
||||||
return siteName;
|
return siteName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - Algorithm
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public MPAlgorithm getAlgorithm() {
|
public MPAlgorithm getAlgorithm() {
|
||||||
@@ -158,7 +162,7 @@ public abstract class MPBasicSite<U extends MPUser<?>, Q extends MPQuestion> ext
|
|||||||
keyPurpose, keyContext, type, state );
|
keyPurpose, keyContext, type, state );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public String getLogin(@Nullable final String state)
|
public String getLogin(@Nullable final String state)
|
||||||
throws MPKeyUnavailableException, MPAlgorithmException {
|
throws MPKeyUnavailableException, MPAlgorithmException {
|
||||||
@@ -166,6 +170,14 @@ public abstract class MPBasicSite<U extends MPUser<?>, Q extends MPQuestion> ext
|
|||||||
return getResult( MPKeyPurpose.Identification, null, null, getLoginType(), state );
|
return getResult( MPKeyPurpose.Identification, null, null, getLoginType(), state );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - Relations
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public U getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Q addQuestion(final Q question) {
|
public Q addQuestion(final Q question) {
|
||||||
@@ -200,12 +212,6 @@ public abstract class MPBasicSite<U extends MPUser<?>, Q extends MPQuestion> ext
|
|||||||
return results.build();
|
return results.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public U getUser() {
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onChanged() {
|
protected void onChanged() {
|
||||||
super.onChanged();
|
super.onChanged();
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public class MPFileSite extends MPBasicSite<MPFileUser, MPFileQuestion> {
|
|||||||
return getResult( keyPurpose, keyContext, getResultState() );
|
return getResult( keyPurpose, keyContext, getResultState() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public String getLogin()
|
public String getLogin()
|
||||||
throws MPKeyUnavailableException, MPAlgorithmException {
|
throws MPKeyUnavailableException, MPAlgorithmException {
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
|
|||||||
|
|
||||||
private MPResultType defaultType;
|
private MPResultType defaultType;
|
||||||
private ReadableInstant lastUsed;
|
private ReadableInstant lastUsed;
|
||||||
|
private boolean hidePasswords;
|
||||||
private boolean complete;
|
private boolean complete;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -54,7 +55,7 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
|
|||||||
throws IOException, MPMarshalException {
|
throws IOException, MPMarshalException {
|
||||||
for (final MPMarshalFormat format : MPMarshalFormat.values())
|
for (final MPMarshalFormat format : MPMarshalFormat.values())
|
||||||
if (file.getName().endsWith( format.fileSuffix() ))
|
if (file.getName().endsWith( format.fileSuffix() ))
|
||||||
return format.unmarshaller().readUser( file );
|
return format.unmarshaller().readUser( file );
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -64,18 +65,19 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public MPFileUser(final String fullName, @Nullable final byte[] keyID, final MPAlgorithm algorithm, final File path) {
|
public MPFileUser(final String fullName, @Nullable final byte[] keyID, final MPAlgorithm algorithm, final File path) {
|
||||||
this( fullName, keyID, algorithm, 0, null, new Instant(),
|
this( fullName, keyID, algorithm, 0, null, new Instant(), false,
|
||||||
MPMarshaller.ContentMode.PROTECTED, MPMarshalFormat.DEFAULT, path );
|
MPMarshaller.ContentMode.PROTECTED, MPMarshalFormat.DEFAULT, path );
|
||||||
}
|
}
|
||||||
|
|
||||||
public MPFileUser(final String fullName, @Nullable final byte[] keyID, final MPAlgorithm algorithm,
|
public MPFileUser(final String fullName, @Nullable final byte[] keyID, final MPAlgorithm algorithm, final int avatar,
|
||||||
final int avatar, @Nullable final MPResultType defaultType, final ReadableInstant lastUsed,
|
@Nullable final MPResultType defaultType, final ReadableInstant lastUsed, final boolean hidePasswords,
|
||||||
final MPMarshaller.ContentMode contentMode, final MPMarshalFormat format, final File path) {
|
final MPMarshaller.ContentMode contentMode, final MPMarshalFormat format, final File path) {
|
||||||
super( avatar, fullName, algorithm );
|
super( avatar, fullName, algorithm );
|
||||||
|
|
||||||
this.keyID = (keyID != null)? keyID.clone(): null;
|
this.keyID = (keyID != null)? keyID.clone(): null;
|
||||||
this.defaultType = (defaultType != null)? defaultType: algorithm.mpw_default_result_type();
|
this.defaultType = (defaultType != null)? defaultType: algorithm.mpw_default_result_type();
|
||||||
this.lastUsed = lastUsed;
|
this.lastUsed = lastUsed;
|
||||||
|
this.hidePasswords = hidePasswords;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.format = format;
|
this.format = format;
|
||||||
this.contentMode = contentMode;
|
this.contentMode = contentMode;
|
||||||
@@ -157,6 +159,18 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
|
|||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isHidePasswords() {
|
||||||
|
return hidePasswords;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHidePasswords(final boolean hidePasswords) {
|
||||||
|
if (Objects.equals( this.hidePasswords, hidePasswords ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.hidePasswords = hidePasswords;
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean isComplete() {
|
protected boolean isComplete() {
|
||||||
return complete;
|
return complete;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public class MPFlatUnmarshaller implements MPUnmarshaller {
|
|||||||
else if ((fullName != null) && (keyID != null))
|
else if ((fullName != null) && (keyID != null))
|
||||||
// Ends the header.
|
// Ends the header.
|
||||||
return new MPFileUser( fullName, keyID, MPAlgorithm.Version.fromInt( mpVersion ).getAlgorithm(),
|
return new MPFileUser( fullName, keyID, MPAlgorithm.Version.fromInt( mpVersion ).getAlgorithm(),
|
||||||
avatar, defaultType, new Instant( 0 ),
|
avatar, defaultType, new Instant( 0 ), false,
|
||||||
clearContent? MPMarshaller.ContentMode.VISIBLE: MPMarshaller.ContentMode.PROTECTED,
|
clearContent? MPMarshaller.ContentMode.VISIBLE: MPMarshaller.ContentMode.PROTECTED,
|
||||||
MPMarshalFormat.Flat, file.getParentFile() );
|
MPMarshalFormat.Flat, file.getParentFile() );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||||||
import com.google.common.primitives.UnsignedInteger;
|
import com.google.common.primitives.UnsignedInteger;
|
||||||
import com.lyndir.lhunath.opal.system.CodeUtils;
|
import com.lyndir.lhunath.opal.system.CodeUtils;
|
||||||
import com.lyndir.masterpassword.*;
|
import com.lyndir.masterpassword.*;
|
||||||
import com.lyndir.masterpassword.model.MPModelConstants;
|
|
||||||
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
|
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
|
||||||
|
import com.lyndir.masterpassword.model.MPModelConstants;
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@@ -77,6 +77,7 @@ public class MPJSONFile extends MPJSONAnyObject {
|
|||||||
user.avatar = modelUser.getAvatar();
|
user.avatar = modelUser.getAvatar();
|
||||||
user.full_name = modelUser.getFullName();
|
user.full_name = modelUser.getFullName();
|
||||||
user.last_used = MPModelConstants.dateTimeFormatter.print( modelUser.getLastUsed() );
|
user.last_used = MPModelConstants.dateTimeFormatter.print( modelUser.getLastUsed() );
|
||||||
|
user.hide_passwords = modelUser.isHidePasswords();
|
||||||
user.key_id = modelUser.exportKeyID();
|
user.key_id = modelUser.exportKeyID();
|
||||||
user.algorithm = modelUser.getAlgorithm().version();
|
user.algorithm = modelUser.getAlgorithm().version();
|
||||||
user.default_type = modelUser.getDefaultType();
|
user.default_type = modelUser.getDefaultType();
|
||||||
@@ -142,7 +143,7 @@ public class MPJSONFile extends MPJSONAnyObject {
|
|||||||
user.full_name, CodeUtils.decodeHex( user.key_id ), algorithm, user.avatar,
|
user.full_name, CodeUtils.decodeHex( user.key_id ), algorithm, user.avatar,
|
||||||
(user.default_type != null)? user.default_type: algorithm.mpw_default_result_type(),
|
(user.default_type != null)? user.default_type: algorithm.mpw_default_result_type(),
|
||||||
(user.last_used != null)? MPModelConstants.dateTimeFormatter.parseDateTime( user.last_used ): new Instant(),
|
(user.last_used != null)? MPModelConstants.dateTimeFormatter.parseDateTime( user.last_used ): new Instant(),
|
||||||
export.redacted? MPMarshaller.ContentMode.PROTECTED: MPMarshaller.ContentMode.VISIBLE,
|
user.hide_passwords, export.redacted? MPMarshaller.ContentMode.PROTECTED: MPMarshaller.ContentMode.VISIBLE,
|
||||||
MPMarshalFormat.JSON, file.getParentFile()
|
MPMarshalFormat.JSON, file.getParentFile()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -202,9 +203,10 @@ public class MPJSONFile extends MPJSONAnyObject {
|
|||||||
|
|
||||||
public static class User extends MPJSONAnyObject {
|
public static class User extends MPJSONAnyObject {
|
||||||
|
|
||||||
int avatar;
|
int avatar;
|
||||||
String full_name;
|
String full_name;
|
||||||
String last_used;
|
String last_used;
|
||||||
|
boolean hide_passwords;
|
||||||
@Nullable
|
@Nullable
|
||||||
String key_id;
|
String key_id;
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
Submodule public/site updated: 914a60cd25...d8d510b6be
Reference in New Issue
Block a user