diff --git a/core/c/build.gradle b/core/c/build.gradle new file mode 100644 index 00000000..2fd63e6b --- /dev/null +++ b/core/c/build.gradle @@ -0,0 +1,44 @@ +import org.gradle.internal.jvm.Jvm + + +plugins { + id 'cpp-library' + id 'xcode' + id 'visual-studio' +} + +description = 'Master Password Algorithm Implementation' + +library { + linkage.set( [Linkage.STATIC, Linkage.SHARED] ) + + binaries.configureEach { + // Reconfigure the toolchain from C++ to C. + compileTask.get().source.setFrom( fileTree( dir: "src", include: "**/*.c" ) ) + if (toolChain instanceof VisualCpp) { + compileTask.get().compilerArgs = ["/TC"] + } else if (toolChain instanceof GccCompatibleToolChain) { + compileTask.get().compilerArgs = ["-x", "c", "-std=c11"] + //linkTask.get().linkerArgs = ["-nodefaultlibs", "-lc"] + } + + // Resolve our standard naming for OS platforms. + def platform = System.getProperty( "os.name" ).toLowerCase( Locale.ROOT ) + if (platform.startsWith( "mac" )) + platform = "macos" + + project.dependencies { + // Depend on JDK for JNI support. + add( includePathConfiguration.name, + files( new File( Jvm.current().javaHome, "include" ) ) { first().eachDir { from it } } ) + + // Depend on libsodium from `lib`; run `lib/bin/build_libsodium-${os}` first. + add( includePathConfiguration.name, + files( "../../lib/libsodium/build-${platform}~/out/include" ) ) + add( linkLibraries.name, + fileTree( "../../lib/libsodium/build-${platform}~/out/lib" ) ) + } + + compileTask.get().compilerArgs.add "-DMPW_SODIUM=1" + } +} diff --git a/core/c/aes.c b/core/c/src/aes.c similarity index 100% rename from core/c/aes.c rename to core/c/src/aes.c diff --git a/core/c/aes.h b/core/c/src/aes.h similarity index 100% rename from core/c/aes.h rename to core/c/src/aes.h diff --git a/core/c/base64.c b/core/c/src/base64.c similarity index 100% rename from core/c/base64.c rename to core/c/src/base64.c diff --git a/core/c/base64.h b/core/c/src/base64.h similarity index 100% rename from core/c/base64.h rename to core/c/src/base64.h diff --git a/core/c/mpw-algorithm.c b/core/c/src/mpw-algorithm.c similarity index 100% rename from core/c/mpw-algorithm.c rename to core/c/src/mpw-algorithm.c diff --git a/core/c/mpw-algorithm.h b/core/c/src/mpw-algorithm.h similarity index 100% rename from core/c/mpw-algorithm.h rename to core/c/src/mpw-algorithm.h diff --git a/core/c/mpw-algorithm_v0.c b/core/c/src/mpw-algorithm_v0.c similarity index 100% rename from core/c/mpw-algorithm_v0.c rename to core/c/src/mpw-algorithm_v0.c diff --git a/core/c/mpw-algorithm_v1.c b/core/c/src/mpw-algorithm_v1.c similarity index 100% rename from core/c/mpw-algorithm_v1.c rename to core/c/src/mpw-algorithm_v1.c diff --git a/core/c/mpw-algorithm_v2.c b/core/c/src/mpw-algorithm_v2.c similarity index 100% rename from core/c/mpw-algorithm_v2.c rename to core/c/src/mpw-algorithm_v2.c diff --git a/core/c/mpw-algorithm_v3.c b/core/c/src/mpw-algorithm_v3.c similarity index 100% rename from core/c/mpw-algorithm_v3.c rename to core/c/src/mpw-algorithm_v3.c diff --git a/core/java/algorithm/src/mpw/c/jni_mpw.c b/core/c/src/mpw-jni.c similarity index 94% rename from core/java/algorithm/src/mpw/c/jni_mpw.c rename to core/c/src/mpw-jni.c index c4532d7c..720c6df2 100644 --- a/core/java/algorithm/src/mpw/c/jni_mpw.c +++ b/core/c/src/mpw-jni.c @@ -1,4 +1,4 @@ -#include "jni_mpw.h" +#include "mpw-jni.h" /** native int _scrypt(byte[] passwd, int passwdlen, byte[] salt, int saltlen, int N, int r, int p, byte[] buf, int buflen); */ JNIEXPORT jint JNICALL Java_com_lyndir_masterpassword_impl_MPAlgorithmV0__1scrypt(JNIEnv *env, jobject obj, diff --git a/core/java/algorithm/src/mpw/c/jni_mpw.h b/core/c/src/mpw-jni.h similarity index 100% rename from core/java/algorithm/src/mpw/c/jni_mpw.h rename to core/c/src/mpw-jni.h diff --git a/core/c/mpw-marshal-util.c b/core/c/src/mpw-marshal-util.c similarity index 100% rename from core/c/mpw-marshal-util.c rename to core/c/src/mpw-marshal-util.c diff --git a/core/c/mpw-marshal-util.h b/core/c/src/mpw-marshal-util.h similarity index 100% rename from core/c/mpw-marshal-util.h rename to core/c/src/mpw-marshal-util.h diff --git a/core/c/mpw-marshal.c b/core/c/src/mpw-marshal.c similarity index 100% rename from core/c/mpw-marshal.c rename to core/c/src/mpw-marshal.c diff --git a/core/c/mpw-marshal.h b/core/c/src/mpw-marshal.h similarity index 100% rename from core/c/mpw-marshal.h rename to core/c/src/mpw-marshal.h diff --git a/core/c/mpw-types.c b/core/c/src/mpw-types.c similarity index 100% rename from core/c/mpw-types.c rename to core/c/src/mpw-types.c diff --git a/core/c/mpw-types.h b/core/c/src/mpw-types.h similarity index 100% rename from core/c/mpw-types.h rename to core/c/src/mpw-types.h diff --git a/core/c/mpw-util.c b/core/c/src/mpw-util.c similarity index 100% rename from core/c/mpw-util.c rename to core/c/src/mpw-util.c diff --git a/core/c/mpw-util.h b/core/c/src/mpw-util.h similarity index 100% rename from core/c/mpw-util.h rename to core/c/src/mpw-util.h diff --git a/core/java/algorithm/build.gradle b/core/java/algorithm/build.gradle index 7d2a00fa..caaeea01 100644 --- a/core/java/algorithm/build.gradle +++ b/core/java/algorithm/build.gradle @@ -1,78 +1,27 @@ plugins { - id 'java' - id 'c' + id 'java-library' } + description = 'Master Password Algorithm Implementation' +configurations { + resource +} + dependencies { - compile( group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: '1.7-p1' ) { - exclude( module: 'joda-time' ) - } + implementation group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: '1.7-p1' - compile 'com.fasterxml.jackson.core:jackson-annotations:2.9.5' - compile group: 'org.jetbrains', name: 'annotations', version: '13.0' - compile group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.1' + api( group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.9.5' ) + api group: 'org.jetbrains', name: 'annotations', version: '13.0' + api group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.1' + + resource project( path: ':masterpassword-core', configuration: 'releaseSharedRuntimeElements' ) } -processResources { - dependsOn 'mpwSharedLibrary' -} - -// TODO: nativeGenHeaders should run prior to mpwSharedLibrary -// TODO: but that creates a cyclic dependency since processResources runs before compileJava which nativeGenHeaders depends on. -//task mpwSharedLibrary { -// dependsOn processResources -//} -build { -// dependsOn 'mpwSharedLibrary' - dependsOn 'nativeGenHeaders' -} - -task nativeGenHeaders { - description "Uses javah to regenerate the JNI header files" - inputs.file sourceSets.main.output.asFileTree.matching { - include 'com/lyndir/masterpassword/impl/MPAlgorithmV0.class' - } - outputs.file 'src/mpw/c/jni_mpw.h' - def classpath = files( sourceSets.main.compileClasspath, sourceSets.main.output ) - doLast { - ant.javah( class: 'com.lyndir.masterpassword.impl.MPAlgorithmV0', - outputFile: 'src/mpw/c/jni_mpw.h', - classpath: classpath.asPath ) - } -} - -model { - components { - mpw( NativeLibrarySpec ) { - binaries.all { - if (targetPlatform.operatingSystem.macOsX) { - cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include" - cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include/darwin" - cCompiler.args '-mmacosx-version-min=10.4' - linker.args '-mmacosx-version-min=10.4' - } else if (targetPlatform.operatingSystem.linux) { - cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include" - cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include/linux" - cCompiler.args '-D_FILE_OFFSET_BITS=64' - } else if (targetPlatform.operatingSystem.windows) { - cCompiler.args "-I${org.gradle.internal.jvm.Jvm.current().javaHome}/include" - cCompiler.args "-I${org.gradle.internal.jvm.Jvm.current().javaHome}/include/win32" - linker.args "Shlwapi.lib", "Advapi32.lib" - } else if (targetPlatform.operatingSystem.freeBSD) { - cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include" - cCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include/freebsd" - } - } - // TODO: Can't we add the sharedLibraryFile to the resources through some kind of task dependency instead? - binaries.withType( SharedLibraryBinarySpec ) { - sourceSets.main.resources.srcDirs it.sharedLibraryFile.parent -// copy { -// from sharedLibraryFile -// to sourceSets.main.resources.outputDir -// } - } - } +jar { + dependsOn task( type: Sync, 'copyResources' ) { + from files( configurations.resource ) + into processResources.outputs.files.singleFile } } diff --git a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/impl/Native.java b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/impl/Native.java index 9852ea48..66f0c7b2 100644 --- a/core/java/algorithm/src/main/java/com/lyndir/masterpassword/impl/Native.java +++ b/core/java/algorithm/src/main/java/com/lyndir/masterpassword/impl/Native.java @@ -18,42 +18,67 @@ package com.lyndir.masterpassword.impl; +import com.google.common.base.Joiner; import com.google.common.io.ByteStreams; import com.lyndir.lhunath.opal.system.logging.Logger; import java.io.*; +import java.util.Locale; +import javax.annotation.Nonnull; /** * @author lhunath, 2018-05-22 */ public final class Native { + private static final Logger logger = Logger.get( Native.class ); - private static final char FILE_DOT = '.'; - private static final String NATIVES_PATH = ""; + @SuppressWarnings("HardcodedFileSeparator") + private static final char RESOURCE_SEPARATOR = '/'; + private static final char EXTENSION_SEPARATOR = '.'; + private static final String NATIVES_PATH = "lib"; @SuppressWarnings({ "HardcodedFileSeparator", "LoadLibraryWithNonConstantString" }) public static void load(final Class context, final String name) { try { + // Find and open a stream to the packaged library resource. String library = System.mapLibraryName( name ); - int libraryDot = library.lastIndexOf( FILE_DOT ); + int libraryDot = library.lastIndexOf( EXTENSION_SEPARATOR ); String libraryName = (libraryDot > 0)? library.substring( 0, libraryDot ): library; - String libraryExtension = (libraryDot > 0)? library.substring( libraryDot ): "lib"; - String libraryResource = String.format( "%s/%s", NATIVES_PATH, library ); + String libraryExtension = (libraryDot > 0)? library.substring( libraryDot ): ".lib"; + String libraryResource = getLibraryResource( library ); InputStream libraryStream = context.getResourceAsStream( libraryResource ); if (libraryStream == null) throw new IllegalStateException( "Library: " + name + " (" + libraryResource + "), not found in class loader for: " + context ); - File libraryFile = File.createTempFile( "libmpw", ".dylib" ); - ByteStreams.copy( libraryStream, new FileOutputStream( libraryFile ) ); + // Write the library resource to a temporary file. + File libraryFile = File.createTempFile( libraryName, libraryExtension ); + FileOutputStream libraryFileStream = new FileOutputStream( libraryFile ); + try { + libraryFile.deleteOnExit(); + ByteStreams.copy( libraryStream, libraryFileStream ); + } + finally { + libraryFileStream.close(); + libraryStream.close(); + } + + // Load the library from the temporary file. System.load( libraryFile.getAbsolutePath() ); - libraryFile.deleteOnExit(); - if (!libraryFile.delete()) - logger.wrn( "Couldn't clean up library after loading: " + libraryFile ); } catch (final IOException e) { - throw new IllegalStateException( "Couldn't load library: " + name, e ); + throw new IllegalStateException( "Couldn't extract library: " + name, e ); } } + + @Nonnull + private static String getLibraryResource(final String library) { + String system = System.getProperty( "os.name" ).toLowerCase( Locale.ROOT ); + String architecture = System.getProperty( "os.arch" ).toLowerCase( Locale.ROOT ); + if ("Mac OS X".equalsIgnoreCase( system )) + system = "macos"; + + return Joiner.on( RESOURCE_SEPARATOR ).join( NATIVES_PATH, system, architecture, library ); + } } diff --git a/core/java/model/build.gradle b/core/java/model/build.gradle index 039b4fbd..ca26b226 100644 --- a/core/java/model/build.gradle +++ b/core/java/model/build.gradle @@ -1,19 +1,22 @@ plugins { - id 'java' + id 'java-library' id 'net.ltgt.apt' version '0.9' } description = 'Master Password Site Model' dependencies { - compile project( ':masterpassword-algorithm' ) - compile 'joda-time:joda-time:2.4' - compile 'com.fasterxml.jackson.core:jackson-core:2.9.5' - compile 'com.fasterxml.jackson.core:jackson-annotations:2.9.5' - compile 'com.fasterxml.jackson.core:jackson-databind:2.9.5' - //compile group: 'com.google.code.gson', name: 'gson', version: '2.8.2' + implementation group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: '1.7-p1' + implementation 'com.fasterxml.jackson.core:jackson-core:2.9.5' + + api project( ':masterpassword-algorithm' ) + api 'joda-time:joda-time:2.4' + api 'com.fasterxml.jackson.core:jackson-annotations:2.9.5' + api 'com.fasterxml.jackson.core:jackson-databind:2.9.5' + compileOnly 'com.google.auto.value:auto-value:1.2' apt group: 'com.google.auto.value', name: 'auto-value', version: '1.2' + testCompile 'org.testng:testng:6.8.5' testCompile 'ch.qos.logback:logback-classic:1.1.2' } diff --git a/core/java/tests/build.gradle b/core/java/tests/build.gradle index 56242948..6fb07175 100644 --- a/core/java/tests/build.gradle +++ b/core/java/tests/build.gradle @@ -5,6 +5,8 @@ plugins { description = 'Master Password Test Suite' dependencies { + implementation group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: '1.7-p1' + compile project( ':masterpassword-algorithm' ) compile project( ':masterpassword-model' ) diff --git a/gradle/gradle/wrapper/gradle-wrapper.jar b/gradle/gradle/wrapper/gradle-wrapper.jar index 27768f1b..91ca28c8 100644 Binary files a/gradle/gradle/wrapper/gradle-wrapper.jar and b/gradle/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/gradle/wrapper/gradle-wrapper.properties b/gradle/gradle/wrapper/gradle-wrapper.properties index a277a67e..16d28051 100644 --- a/gradle/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Thu Apr 26 12:52:02 EDT 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.3-all.zip diff --git a/gradle/settings.gradle b/gradle/settings.gradle index 669df3c9..bfa45923 100644 --- a/gradle/settings.gradle +++ b/gradle/settings.gradle @@ -6,6 +6,9 @@ try { } catch (FileNotFoundException ignored) { } +include 'masterpassword-core' +project(':masterpassword-core').projectDir = new File( '../core/c' ) + include 'masterpassword-algorithm' project(':masterpassword-algorithm').projectDir = new File( '../core/java/algorithm' ) @@ -18,9 +21,10 @@ project(':masterpassword-tests').projectDir = new File( '../core/java/tests' ) include 'masterpassword-gui' project(':masterpassword-gui').projectDir = new File( '../platform-independent/gui-java' ) +/* if (local.containsKey('sdk.dir')) { include 'masterpassword-android' project(':masterpassword-android').projectDir = new File( '../platform-android' ) } else { logger.warn( "Skipping masterpassword-android since sdk.dir is not defined in local.properties." ) -} +}*/