From fffec56d4e27d983661cda7027b2a0417cd9c346 Mon Sep 17 00:00:00 2001 From: Maarten Billemont Date: Sun, 24 Jun 2018 16:20:42 -0400 Subject: [PATCH] Build support for Microsoft Windows. --- gradle/.idea/codeStyleSettings.xml | 9 --- gradle/.idea/copyright/GPLv3.xml | 7 -- gradle/.idea/copyright/profiles_settings.xml | 13 ---- .../inspectionProfiles/profiles_settings.xml | 9 --- gradle/.idea/misc.xml | 44 +---------- gradle/.idea/runConfigurations/Android.xml | 28 ------- gradle/.idea/scopes/masterpassword.xml | 3 - .../gradle/wrapper/gradle-wrapper.properties | 3 +- gradle/settings.gradle | 8 +- lib/bin/build_lib | 45 +++++++++-- lib/bin/build_libjson-c-windows | 8 ++ lib/bin/build_libsodium-windows | 4 + platform-independent/c/core/build.gradle | 9 ++- platform-independent/c/core/src/mpw-marshal.c | 17 ++-- platform-independent/c/core/src/mpw-types.c | 78 ++++++++----------- platform-independent/c/core/src/mpw-util.c | 41 ++++++++-- platform-independent/c/core/src/mpw-util.h | 44 +++++++---- 17 files changed, 169 insertions(+), 201 deletions(-) delete mode 100644 gradle/.idea/codeStyleSettings.xml delete mode 100644 gradle/.idea/copyright/GPLv3.xml delete mode 100644 gradle/.idea/copyright/profiles_settings.xml delete mode 100644 gradle/.idea/inspectionProfiles/profiles_settings.xml delete mode 100644 gradle/.idea/runConfigurations/Android.xml delete mode 100644 gradle/.idea/scopes/masterpassword.xml create mode 100644 lib/bin/build_libjson-c-windows create mode 100644 lib/bin/build_libsodium-windows diff --git a/gradle/.idea/codeStyleSettings.xml b/gradle/.idea/codeStyleSettings.xml deleted file mode 100644 index 6411f7cf..00000000 --- a/gradle/.idea/codeStyleSettings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/gradle/.idea/copyright/GPLv3.xml b/gradle/.idea/copyright/GPLv3.xml deleted file mode 100644 index 7621717c..00000000 --- a/gradle/.idea/copyright/GPLv3.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/gradle/.idea/copyright/profiles_settings.xml b/gradle/.idea/copyright/profiles_settings.xml deleted file mode 100644 index d516e023..00000000 --- a/gradle/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/gradle/.idea/inspectionProfiles/profiles_settings.xml b/gradle/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 59059c7a..00000000 --- a/gradle/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - \ No newline at end of file diff --git a/gradle/.idea/misc.xml b/gradle/.idea/misc.xml index 2e7d1a63..7bfef59d 100644 --- a/gradle/.idea/misc.xml +++ b/gradle/.idea/misc.xml @@ -1,45 +1,9 @@ - - - + + - - - - - - - - - - - - + + \ No newline at end of file diff --git a/gradle/.idea/runConfigurations/Android.xml b/gradle/.idea/runConfigurations/Android.xml deleted file mode 100644 index 10cabad7..00000000 --- a/gradle/.idea/runConfigurations/Android.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - \ No newline at end of file diff --git a/gradle/.idea/scopes/masterpassword.xml b/gradle/.idea/scopes/masterpassword.xml deleted file mode 100644 index 42d84ba4..00000000 --- a/gradle/.idea/scopes/masterpassword.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/gradle/gradle/wrapper/gradle-wrapper.properties b/gradle/gradle/wrapper/gradle-wrapper.properties index 16d28051..49df2ab4 100644 --- a/gradle/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Fri Jun 22 01:12:28 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.7-all.zip diff --git a/gradle/settings.gradle b/gradle/settings.gradle index 9b1008b8..6086dddb 100644 --- a/gradle/settings.gradle +++ b/gradle/settings.gradle @@ -21,9 +21,9 @@ project(':masterpassword-tests').projectDir = new File( '../platform-independent include 'masterpassword-gui' project(':masterpassword-gui').projectDir = new File( '../platform-independent/java/gui' ) -if (local.containsKey('sdk.dir')) { +//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." ) -} +//} else { +// logger.warn( "Skipping masterpassword-android since sdk.dir is not defined in local.properties." ) +//} diff --git a/lib/bin/build_lib b/lib/bin/build_lib index 062f3b40..efb89206 100755 --- a/lib/bin/build_lib +++ b/lib/bin/build_lib @@ -53,7 +53,13 @@ _initialize() { # By default, this will check for `automake` and `autoreconf`. initialize_needs() { _initialize_needs "$@"; } _initialize_needs() { - needs automake autoreconf + if [[ $platform = windows ]]; then + needs cmd + export VSINSTALLDIR="${VSINSTALLDIR:-$(cd "$(cygpath -F 0x002a)/Microsoft Visual Studio"/*/*/Common7/.. && pwd)}" + [[ -e "$VSINSTALLDIR/Common7/Tools/VsMSBuildCmd.bat" ]] || { echo >&2 "Missing: msbuild. Please install 'Build Tools for Visual Studio'."; return 1; } + else + needs automake autoreconf + fi } # clean @@ -64,6 +70,13 @@ _initialize_needs() { clean() { _clean "$@"; } _clean() { rm -rf "$prefix" + + if [[ $platform = windows ]]; then + printf '"%%VSINSTALLDIR%%\Common7\Tools\VsMSBuildCmd.bat" && msbuild /t:Clean' > .clean.bat + cmd //c .clean.bat + rm -f .clean.bat + fi + [[ ! -e Makefile ]] || make -s distclean [[ ! -e .git ]] || git clean -fdx } @@ -103,6 +116,8 @@ prepare_config() { _prepare_config "$@"; } _prepare_config() { local prefix=$1 platform=$2; shift 2 + [[ $platform = windows ]] && return + [[ -e configure ]] || autoreconf --verbose --install --symlink 2> >(sed 's/^\([^:]*\):[0-9]\{1,\}: /\1: /') } @@ -127,6 +142,8 @@ target_prepare() { _target_prepare "$@"; } _target_prepare() { local prefix=$1 platform=$2 arch=$3; shift 3 + [[ $platform = windows ]] && return + [[ ! -e Makefile ]] || make -s clean } @@ -140,6 +157,9 @@ _target_configure() { local prefix=$1 platform=$2 arch=$3; shift 3 case "$platform" in + 'windows') + return + ;; 'android') host=( "$SDKROOT"/*-android* ) host=${host##*/} @@ -164,10 +184,16 @@ _target_configure() { target_build() { _target_build "$@"; } _target_build() { local prefix=$1 platform=$2 arch=$3; shift 3 - #make -j3 check - cores=$(getconf NPROCESSORS_ONLN 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null ||:) - make -j"${cores:-3}" install + if [[ $platform = windows ]]; then + # I cannot for the life of me figure out how to pass this command directly into cmd. + printf '"%%VSINSTALLDIR%%\Common7\Tools\VsMSBuildCmd.bat" && msbuild /t:Rebuild /p:Configuration=ReleaseDLL;Platform=%s;OutDir=%s' "$arch" "$(cygpath -w "${prefix##$PWD/}/$arch/")" > .build.bat + cmd //c .build.bat + rm -f .build.bat + else + local cores=$(getconf NPROCESSORS_ONLN 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null ||:) + make -j"${cores:-3}" install + fi } # finalize [ ... ] @@ -189,10 +215,16 @@ finalize_merge() { _finalize_merge "$@"; } _finalize_merge() { local prefix=$1 platform=$2; shift 2 - mv -f -- "$prefix/$1/include" "$prefix/out/" + [[ -e "$prefix/$1/include" ]] && mv -f -- "$prefix/$1/include" "$prefix/out/" mkdir -p "$prefix/out/lib" case "$platform" in + 'windows') + for arch; do + install -d "$prefix/out/lib/$arch" + install -p "$prefix/Win32/"*.lib "$prefix/out/lib/" + done + ;; 'macos'|'ios') for lib in "$prefix/$1/lib/"*; do if lipo -info "$lib" >/dev/null 2>&1; then @@ -247,6 +279,7 @@ _build() { 'macos') archs=( 'x86_64' ) ;; 'ios') archs=( 'i386' 'x86_64' 'armv7' 'armv7s' 'arm64' ) ;; 'android') archs=( 'arm' 'arm64' 'x86' 'x86_64' ) ;; + 'windows') archs=( 'Win32' 'x64' ) ;; esac fi @@ -270,6 +303,8 @@ _build() { # Set up a base environment for the platform. case "$platform" in + 'windows') + ;; 'macos') SDKROOT="$(xcrun --show-sdk-path --sdk macosx)" export PATH="$(xcrun --show-sdk-platform-path --sdk macosx)/usr/bin:$PATH" diff --git a/lib/bin/build_libjson-c-windows b/lib/bin/build_libjson-c-windows new file mode 100644 index 00000000..31368936 --- /dev/null +++ b/lib/bin/build_libjson-c-windows @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +source "${BASH_SOURCE%/*}/build_lib" + +autoreconf() { + command autoreconf -Iautoconf-archive/m4 "$@" +} + +build libjson-c windows diff --git a/lib/bin/build_libsodium-windows b/lib/bin/build_libsodium-windows new file mode 100644 index 00000000..4f3a51b1 --- /dev/null +++ b/lib/bin/build_libsodium-windows @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +source "${BASH_SOURCE%/*}/build_lib" + +build libsodium windows diff --git a/platform-independent/c/core/build.gradle b/platform-independent/c/core/build.gradle index a4bfca76..c67a8b45 100644 --- a/platform-independent/c/core/build.gradle +++ b/platform-independent/c/core/build.gradle @@ -21,10 +21,15 @@ artifacts { } library { - linkage.set( [Linkage.STATIC, Linkage.SHARED] ) + linkage.set( [ Linkage.SHARED ] ) // Reconfigure the toolchain from C++ to C. toolChains { + withType( VisualCpp ) { + eachPlatform { + cppCompiler.withArguments { addAll( ["/TC", "/DMPW_SODIUM=1"] ) } + } + } withType( GccCompatibleToolChain ) { eachPlatform { cppCompiler.withArguments { addAll( ["-x", "c", "-std=c11", "-Werror", "-DMPW_SODIUM=1"] ) } @@ -52,7 +57,7 @@ library { // Depend on libsodium from `lib`; run `lib/bin/build_libsodium-${platform}` first. add( includePathConfiguration.name, - files( "../../../lib/libsodium/build-${platform}~/out/include" ) ) + files( "../../../lib/libsodium/src/libsodium/include" ) ) add( linkLibraries.name, fileTree( "../../../lib/libsodium/build-${platform}~/out/lib" ) ) } diff --git a/platform-independent/c/core/src/mpw-marshal.c b/platform-independent/c/core/src/mpw-marshal.c index fd17669e..1f7b2b40 100644 --- a/platform-independent/c/core/src/mpw-marshal.c +++ b/platform-independent/c/core/src/mpw-marshal.c @@ -206,7 +206,7 @@ static bool mpw_marshal_write_flat( if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &site->lastUsed ) )) mpw_string_pushf( out, "%s %8ld %lu:%lu:%lu %25s\t%25s\t%s\n", dateString, (long)site->uses, (long)site->type, (long)site->algorithm, (long)site->counter, - loginContent?: "", site->name, content?: "" ); + loginContent? loginContent: "", site->name, content? content: "" ); mpw_free_strings( &content, &loginContent, NULL ); } mpw_free( &masterKey, MPMasterKeySize ); @@ -871,21 +871,14 @@ const MPMarshalFormat mpw_formatWithName( if (!formatName || !strlen( formatName )) return MPMarshalFormatNone; - // Lower-case to standardize it. - size_t stdFormatNameSize = strlen( formatName ); - char stdFormatName[stdFormatNameSize + 1]; - for (size_t c = 0; c < stdFormatNameSize; ++c) - stdFormatName[c] = (char)tolower( formatName[c] ); - stdFormatName[stdFormatNameSize] = '\0'; - - if (strncmp( mpw_nameForFormat( MPMarshalFormatNone ), stdFormatName, strlen( stdFormatName ) ) == 0) + if (mpw_strncasecmp( mpw_nameForFormat( MPMarshalFormatNone ), formatName, strlen( formatName ) ) == 0) return MPMarshalFormatNone; - if (strncmp( mpw_nameForFormat( MPMarshalFormatFlat ), stdFormatName, strlen( stdFormatName ) ) == 0) + if (mpw_strncasecmp( mpw_nameForFormat( MPMarshalFormatFlat ), formatName, strlen( formatName ) ) == 0) return MPMarshalFormatFlat; - if (strncmp( mpw_nameForFormat( MPMarshalFormatJSON ), stdFormatName, strlen( stdFormatName ) ) == 0) + if (mpw_strncasecmp( mpw_nameForFormat( MPMarshalFormatJSON ), formatName, strlen( formatName ) ) == 0) return MPMarshalFormatJSON; - dbg( "Not a format name: %s", stdFormatName ); + dbg( "Not a format name: %s", formatName ); return (MPMarshalFormat)ERR; } diff --git a/platform-independent/c/core/src/mpw-types.c b/platform-independent/c/core/src/mpw-types.c index 2343aa90..5aa1b9c4 100644 --- a/platform-independent/c/core/src/mpw-types.c +++ b/platform-independent/c/core/src/mpw-types.c @@ -53,38 +53,31 @@ const MPResultType mpw_typeWithName(const char *typeName) { return MPResultTypeDeriveKey; } - // Lower-case typeName to standardize it. - size_t stdTypeNameSize = strlen( typeName ); - char stdTypeName[stdTypeNameSize + 1]; - for (size_t c = 0; c < stdTypeNameSize; ++c) - stdTypeName[c] = (char)tolower( typeName[c] ); - stdTypeName[stdTypeNameSize] = '\0'; - // Find what password type is represented by the type name. - if (strncmp( mpw_nameForType( MPResultTypeTemplateMaximum ), stdTypeName, strlen( stdTypeName ) ) == 0) + if (mpw_strncasecmp( mpw_nameForType( MPResultTypeTemplateMaximum ), typeName, strlen( typeName ) ) == 0) return MPResultTypeTemplateMaximum; - if (strncmp( mpw_nameForType( MPResultTypeTemplateLong ), stdTypeName, strlen( stdTypeName ) ) == 0) + if (mpw_strncasecmp( mpw_nameForType( MPResultTypeTemplateLong ), typeName, strlen( typeName ) ) == 0) return MPResultTypeTemplateLong; - if (strncmp( mpw_nameForType( MPResultTypeTemplateMedium ), stdTypeName, strlen( stdTypeName ) ) == 0) + if (mpw_strncasecmp( mpw_nameForType( MPResultTypeTemplateMedium ), typeName, strlen( typeName ) ) == 0) return MPResultTypeTemplateMedium; - if (strncmp( mpw_nameForType( MPResultTypeTemplateBasic ), stdTypeName, strlen( stdTypeName ) ) == 0) + if (mpw_strncasecmp( mpw_nameForType( MPResultTypeTemplateBasic ), typeName, strlen( typeName ) ) == 0) return MPResultTypeTemplateBasic; - if (strncmp( mpw_nameForType( MPResultTypeTemplateShort ), stdTypeName, strlen( stdTypeName ) ) == 0) + if (mpw_strncasecmp( mpw_nameForType( MPResultTypeTemplateShort ), typeName, strlen( typeName ) ) == 0) return MPResultTypeTemplateShort; - if (strncmp( mpw_nameForType( MPResultTypeTemplatePIN ), stdTypeName, strlen( stdTypeName ) ) == 0) + if (mpw_strncasecmp( mpw_nameForType( MPResultTypeTemplatePIN ), typeName, strlen( typeName ) ) == 0) return MPResultTypeTemplatePIN; - if (strncmp( mpw_nameForType( MPResultTypeTemplateName ), stdTypeName, strlen( stdTypeName ) ) == 0) + if (mpw_strncasecmp( mpw_nameForType( MPResultTypeTemplateName ), typeName, strlen( typeName ) ) == 0) return MPResultTypeTemplateName; - if (strncmp( mpw_nameForType( MPResultTypeTemplatePhrase ), stdTypeName, strlen( stdTypeName ) ) == 0) + if (mpw_strncasecmp( mpw_nameForType( MPResultTypeTemplatePhrase ), typeName, strlen( typeName ) ) == 0) return MPResultTypeTemplatePhrase; - if (strncmp( mpw_nameForType( MPResultTypeStatefulPersonal ), stdTypeName, strlen( stdTypeName ) ) == 0) + if (mpw_strncasecmp( mpw_nameForType( MPResultTypeStatefulPersonal ), typeName, strlen( typeName ) ) == 0) return MPResultTypeStatefulPersonal; - if (strncmp( mpw_nameForType( MPResultTypeStatefulDevice ), stdTypeName, strlen( stdTypeName ) ) == 0) + if (mpw_strncasecmp( mpw_nameForType( MPResultTypeStatefulDevice ), typeName, strlen( typeName ) ) == 0) return MPResultTypeStatefulDevice; - if (strncmp( mpw_nameForType( MPResultTypeDeriveKey ), stdTypeName, strlen( stdTypeName ) ) == 0) + if (mpw_strncasecmp( mpw_nameForType( MPResultTypeDeriveKey ), typeName, strlen( typeName ) ) == 0) return MPResultTypeDeriveKey; - dbg( "Not a generated type name: %s", stdTypeName ); + dbg( "Not a generated type name: %s", typeName ); return (MPResultType)ERR; } @@ -129,35 +122,35 @@ const char **mpw_templatesForType(MPResultType type, size_t *count) { switch (type) { case MPResultTypeTemplateMaximum: - return mpw_alloc_array( count, const char *, - "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" ); + return mpw_strings( count, + "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno", NULL ); case MPResultTypeTemplateLong: - return mpw_alloc_array( count, const char *, + return mpw_strings( count, "CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno", "CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno", "CvcvnoCvccCvcv", "CvcvCvccnoCvcv", "CvcvCvccCvcvno", "CvcvnoCvcvCvcc", "CvcvCvcvnoCvcc", "CvcvCvcvCvccno", "CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno", "CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno", - "CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno" ); + "CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno", NULL ); case MPResultTypeTemplateMedium: - return mpw_alloc_array( count, const char *, - "CvcnoCvc", "CvcCvcno" ); + return mpw_strings( count, + "CvcnoCvc", "CvcCvcno", NULL ); case MPResultTypeTemplateShort: - return mpw_alloc_array( count, const char *, - "Cvcn" ); + return mpw_strings( count, + "Cvcn", NULL ); case MPResultTypeTemplateBasic: - return mpw_alloc_array( count, const char *, - "aaanaaan", "aannaaan", "aaannaaa" ); + return mpw_strings( count, + "aaanaaan", "aannaaan", "aaannaaa", NULL ); case MPResultTypeTemplatePIN: - return mpw_alloc_array( count, const char *, - "nnnn" ); + return mpw_strings( count, + "nnnn", NULL ); case MPResultTypeTemplateName: - return mpw_alloc_array( count, const char *, - "cvccvcvcv" ); + return mpw_strings( count, + "cvccvcvcv", NULL ); case MPResultTypeTemplatePhrase: - return mpw_alloc_array( count, const char *, - "cvcc cvc cvccvcv cvc", "cvc cvccvcvcv cvcv", "cv cvccv cvc cvcvccv" ); + return mpw_strings( count, + "cvcc cvc cvccvcv cvc", "cvc cvccvcvcv cvcv", "cv cvccv cvc cvcvccv", NULL ); default: { dbg( "Unknown generated type: %d", type ); return NULL; @@ -177,21 +170,14 @@ const char *mpw_templateForType(MPResultType type, uint8_t templateIndex) { const MPKeyPurpose mpw_purposeWithName(const char *purposeName) { - // Lower-case and trim optionally leading "generated" string from typeName to standardize it. - size_t stdPurposeNameSize = strlen( purposeName ); - char stdPurposeName[stdPurposeNameSize + 1]; - for (size_t c = 0; c < stdPurposeNameSize; ++c) - stdPurposeName[c] = (char)tolower( purposeName[c] ); - stdPurposeName[stdPurposeNameSize] = '\0'; - - if (strncmp( mpw_nameForPurpose( MPKeyPurposeAuthentication ), stdPurposeName, strlen( stdPurposeName ) ) == 0) + if (mpw_strncasecmp( mpw_nameForPurpose( MPKeyPurposeAuthentication ), purposeName, strlen( purposeName ) ) == 0) return MPKeyPurposeAuthentication; - if (strncmp( mpw_nameForPurpose( MPKeyPurposeIdentification ), stdPurposeName, strlen( stdPurposeName ) ) == 0) + if (mpw_strncasecmp( mpw_nameForPurpose( MPKeyPurposeIdentification ), purposeName, strlen( purposeName ) ) == 0) return MPKeyPurposeIdentification; - if (strncmp( mpw_nameForPurpose( MPKeyPurposeRecovery ), stdPurposeName, strlen( stdPurposeName ) ) == 0) + if (mpw_strncasecmp( mpw_nameForPurpose( MPKeyPurposeRecovery ), purposeName, strlen( purposeName ) ) == 0) return MPKeyPurposeRecovery; - dbg( "Not a purpose name: %s", stdPurposeName ); + dbg( "Not a purpose name: %s", purposeName ); return (MPKeyPurpose)ERR; } diff --git a/platform-independent/c/core/src/mpw-util.c b/platform-independent/c/core/src/mpw-util.c index 07bd5a47..96cf284e 100644 --- a/platform-independent/c/core/src/mpw-util.c +++ b/platform-independent/c/core/src/mpw-util.c @@ -62,6 +62,25 @@ void mpw_uint64(const uint64_t number, uint8_t buf[8]) { buf[7] = (uint8_t)((number >> 0L) & UINT8_MAX); } +const char **mpw_strings(size_t *count, const char *strings, ...) { + + va_list args; + va_start( args, strings ); + char **array = NULL; + size_t arraySize = 0; + for (const char *string; string = va_arg( args, const char * );) { + size_t cursor = arraySize; + if (!mpw_realloc( &array, &arraySize, sizeof(string) )) { + mpw_free( &array, arraySize ); + return NULL; + } + array[cursor] = string; + } + va_end( args ); + + return array; +} + bool mpw_push_buf(uint8_t **buffer, size_t *bufferSize, const void *pushBuffer, const size_t pushSize) { if (!buffer || !bufferSize || !pushBuffer || !pushSize) @@ -275,14 +294,15 @@ static uint8_t const *mpw_aes(bool encrypt, const uint8_t *key, const size_t key return NULL; // IV = zero - uint8_t iv[AES_BLOCKLEN]; - mpw_zero( iv, sizeof iv ); + static uint8_t *iv = NULL; + if (!iv) + iv = calloc( AES_BLOCKLEN, sizeof( uint8_t ) ); // Add PKCS#7 padding uint32_t aesSize = ((uint32_t)*bufSize + AES_BLOCKLEN - 1) & -AES_BLOCKLEN; // round up to block size. if (encrypt && !(*bufSize % AES_BLOCKLEN)) // add pad block if plain text fits block size. encrypt += AES_BLOCKLEN; - uint8_t aesBuf[aesSize]; + uint8_t *aesBuf = malloc( aesSize ); memcpy( aesBuf, buf, *bufSize ); memset( aesBuf + *bufSize, aesSize - *bufSize, aesSize - *bufSize ); uint8_t *resultBuf = malloc( aesSize ); @@ -291,8 +311,7 @@ static uint8_t const *mpw_aes(bool encrypt, const uint8_t *key, const size_t key AES_CBC_encrypt_buffer( resultBuf, aesBuf, aesSize, key, iv ); else AES_CBC_decrypt_buffer( resultBuf, aesBuf, aesSize, key, iv ); - mpw_zero( aesBuf, aesSize ); - mpw_zero( iv, AES_BLOCKLEN ); + mpw_free( aesBuf, aesSize ); // Truncate PKCS#7 padding if (encrypt) @@ -496,3 +515,15 @@ char *mpw_strndup(const char *src, size_t max) { return dst; } + +int *mpw_strncasecmp(const char *s1, const char *s2, size_t max) { + + if (s1 && s2 && max) + for (; --max > 0; ++s1, ++s2) { + int cmp = tolower( *(unsigned char *)s1 ) - tolower( *(unsigned char *)s2 ); + if (!cmp || *s1 == '\0') + return cmp; + } + + return 0; +} \ No newline at end of file diff --git a/platform-independent/c/core/src/mpw-util.h b/platform-independent/c/core/src/mpw-util.h index 15b0422c..a2d19baf 100644 --- a/platform-independent/c/core/src/mpw-util.h +++ b/platform-independent/c/core/src/mpw-util.h @@ -33,36 +33,36 @@ extern int mpw_verbosity; #endif #ifndef mpw_log -#define mpw_log(level, ...) ({ \ +#define mpw_log(level, format, ...) do { \ if (mpw_verbosity >= level) { \ - mpw_log_do( level, ##__VA_ARGS__ ); \ - }; }) + mpw_log_do( level, format, ##__VA_ARGS__ ); \ + }; } while (0) #endif #ifndef trc /** Logging internal state. */ #define trc_level 3 -#define trc(...) mpw_log( trc_level, ##__VA_ARGS__ ) +#define trc(format, ...) mpw_log( trc_level, format, ##__VA_ARGS__ ) /** Logging state and events interesting when investigating issues. */ #define dbg_level 2 -#define dbg(...) mpw_log( dbg_level, ##__VA_ARGS__ ) +#define dbg(format, ...) mpw_log( dbg_level, format, ##__VA_ARGS__ ) /** User messages. */ #define inf_level 1 -#define inf(...) mpw_log( inf_level, ##__VA_ARGS__ ) +#define inf(format, ...) mpw_log( inf_level, format, ##__VA_ARGS__ ) /** Recoverable issues and user suggestions. */ #define wrn_level 0 -#define wrn(...) mpw_log( wrn_level, ##__VA_ARGS__ ) +#define wrn(format, ...) mpw_log( wrn_level, format, ##__VA_ARGS__ ) /** Unrecoverable issues. */ #define err_level -1 -#define err(...) mpw_log( err_level, ##__VA_ARGS__ ) +#define err(format, ...) mpw_log( err_level, format, ##__VA_ARGS__ ) /** Issues that lead to abortion. */ #define ftl_level -2 -#define ftl(...) mpw_log( ftl_level, ##__VA_ARGS__ ) +#define ftl(format, ...) mpw_log( ftl_level, format, ##__VA_ARGS__ ) #endif #ifndef min @@ -98,14 +98,8 @@ void mpw_uint32(const uint32_t number, uint8_t buf[4]); void mpw_uint64(const uint64_t number, uint8_t buf[8]); /** Allocate a new array of _type, assign its element count to _count if not NULL and populate it with the varargs. */ -#define mpw_alloc_array(_count, _type, ...) ({ \ - _type stackElements[] = { __VA_ARGS__ }; \ - if (_count) \ - *_count = sizeof( stackElements ) / sizeof( _type ); \ - _type *allocElements = malloc( sizeof( stackElements ) ); \ - memcpy( allocElements, stackElements, sizeof( stackElements ) ); \ - allocElements; \ - }) +const char **mpw_strings( + size_t *count, const char *strings, ...); /** Push a buffer onto a buffer. reallocs the given buffer and appends the given buffer. */ bool mpw_push_buf( @@ -150,6 +144,20 @@ bool __mpw_free_string( ({ __typeof__(strings) _s = strings; const char *__s = *_s; (void)__s; __mpw_free_strings( (char **)_s, __VA_ARGS__ ); }) bool __mpw_free_strings( char **strings, ...); +#ifdef _MSC_VER +#undef mpw_realloc +#define mpw_realloc(buffer, bufferSize, deltaSize) \ + __mpw_realloc( (const void **)buffer, bufferSize, deltaSize ) +#undef mpw_free +#define mpw_free(buffer, bufferSize) \ + __mpw_free( (void **)buffer, bufferSize ) +#undef mpw_free_string +#define mpw_free_string(string) \ + __mpw_free_string( (char **)string ) +#undef mpw_free_strings +#define mpw_free_strings(strings, ...) \ + __mpw_free_strings( (char **)strings, __VA_ARGS__ ) +#endif //// Cryptographic functions. @@ -207,5 +215,7 @@ const size_t mpw_utf8_strlen(const char *utf8String); char *mpw_strdup(const char *src); /** Drop-in for POSIX strndup(3). */ char *mpw_strndup(const char *src, size_t max); +/** Drop-in for POSIX strncasecmp(3). */ +int *mpw_strncasecmp(const char *s1, const char *s2, size_t max); #endif // _MPW_UTIL_H