diff --git a/.gitignore b/.gitignore index 560b024..a6578c1 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.lo *.o *.obj +*.pyc # Precompiled Headers *.gch @@ -43,6 +44,14 @@ bld/ ipch/ .vs/ +dist/ +.externalNativeBuild/ +.gradle/ +.classpath + +# cross-platform +platform/cross-platform/out +platform/cross-platform/vendor # Windows Thumbs.db @@ -68,5 +77,8 @@ storage.json result.epub *.iml +.settings/ +.project +local.properties -platform/android/lcp/libs/ \ No newline at end of file +platform/android/lcp/libs/ diff --git a/README.md b/README.md index cb11841..816287d 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,10 @@ readium-lcp-client ================== -This repository is for the Readium Lightweight Content Protection (LCP) client side implementation work. +This repository is for the Readium Licensed Content Protection (LCP) client side implementation work. Created by Artem Brazhnikov, Mickaƫl Menu. +Maintained by Cyrille Lebeaupin, Daniel Weck. ## Overview diff --git a/platform/android/README.md b/platform/android/README.md new file mode 100644 index 0000000..433d130 --- /dev/null +++ b/platform/android/README.md @@ -0,0 +1,26 @@ +# Android + +## Properties + +You can define some properties in local.properties file: + +* ndk.dir: Path to the Ndk +* sdk.dir: Path to the Sdk +* readium.ndk_skipX86: If true, skip X86 compilation +* readium.ndk_skipARM: If true, skip ARM compilation +* readium.ndk_clang: If true, compile with clang +* readium.sdk_lib_dir: Path to readium sdk lib (*.so files) directory +* readium.sdk_include_dir: Path to readium include directory +* readium.extra_cmake: Path to an extra cmake that can modify lib compilation + +## Clean + +``` +./gradlew clean +``` + +## Build + +``` +./gradlew build +``` diff --git a/platform/android/build.gradle b/platform/android/build.gradle index 0685574..10e11e7 100644 --- a/platform/android/build.gradle +++ b/platform/android/build.gradle @@ -1,10 +1,41 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { - jcenter() + jcenter() } dependencies { - classpath 'com.android.tools.build:gradle-experimental:0.6.0-alpha5' + Properties properties = new Properties() + properties.load(rootProject.file('local.properties').newDataInputStream()) + + def ndkClang = properties.getProperty('readium.ndk_clang', "false") + ndkClang = (ndkClang == "true") ? true : false; + rootProject.ext.set('readium_ndk_clang', ndkClang) + + def ndkSkipX86 = properties.getProperty('readium.ndk_skipX86', "false") + ndkSkipX86 = (ndkSkipX86 == "true") ? true : false; + rootProject.ext.set('readium_ndk_skipX86', ndkSkipX86) + + def ndkSkipARM = properties.getProperty('readium.ndk_skipARM', "false") + ndkSkipARM = (ndkSkipARM == "true") ? true : false; + rootProject.ext.set('readium_ndk_skipARM', ndkSkipARM) + + def extraCmake = properties.getProperty('readium.extra_cmake', null) + rootProject.ext.set('readium_extra_cmake', extraCmake) + + def readiumSdkLibDir = properties.getProperty('readium.sdk_lib_dir', null) + rootProject.ext.set('readium_sdk_lib_dir', readiumSdkLibDir) + + def readiumSdkIncludeDir = properties.getProperty('readium.sdk_include_dir', null) + rootProject.ext.set('readium_sdk_include_dir', readiumSdkIncludeDir) + + if (readiumSdkLibDir != null && readiumSdkIncludeDir != null) { + rootProject.ext.set('readium_lcp_build_content_filter', true) + } else { + rootProject.ext.set('readium_lcp_build_content_filter', false) + } + + //https://bintray.com/android/android-tools/com.android.tools.build.gradle/view + classpath "com.android.tools.build:gradle:2.3.3" } } @@ -12,4 +43,4 @@ allprojects { repositories { jcenter() } -} \ No newline at end of file +} diff --git a/platform/android/clean.sh b/platform/android/clean.sh new file mode 100644 index 0000000..e155c5b --- /dev/null +++ b/platform/android/clean.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +rm -rf build + +rm -rf lib/build +rm -rf lib/.externalNativeBuild diff --git a/platform/android/gradle/wrapper/gradle-wrapper.properties b/platform/android/gradle/wrapper/gradle-wrapper.properties index 60e4196..a1347d8 100644 --- a/platform/android/gradle/wrapper/gradle-wrapper.properties +++ b/platform/android/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,9 @@ -#Wed Aug 17 23:29:31 BST 2016 +#Wed Apr 12 13:19:28 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists #https://services.gradle.org/distributions -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip +# GRADLE EXPERIMENTAL requires 3.3 +# GRADLE STABLE works with latest (4.4) +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip diff --git a/platform/android/lcp/Application.mk b/platform/android/lcp/Application.mk deleted file mode 100644 index 04fad3f..0000000 --- a/platform/android/lcp/Application.mk +++ /dev/null @@ -1,25 +0,0 @@ -APP_PLATFORM := android-25 - -ifneq ($(READIUM_SKIPARM),true) - -APP_ABI := armeabi-v7a - -ifneq ($(READIUM_SKIPX86),true) -APP_ABI += x86 -endif - -else - -APP_ABI := x86 - -endif - -ifeq ($(READIUM_CLANG),true) -#NDK_TOOLCHAIN := clang -NDK_TOOLCHAIN_VERSION := clang -APP_STL := c++_shared -else -#NDK_TOOLCHAIN := gcc -NDK_TOOLCHAIN_VERSION := 4.9 -APP_STL := gnustl_shared -endif \ No newline at end of file diff --git a/platform/android/lcp/Experimental.mk b/platform/android/lcp/Experimental.mk deleted file mode 100644 index 6595ff4..0000000 --- a/platform/android/lcp/Experimental.mk +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright (c) 2014 Readium Foundation and/or its licensees. All rights reserved. -# -# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# -# Licensed under Gnu Affero General Public License Version 3 (provided, notwithstanding this -# notice, Readium Foundation reserves the right to license this material under a different -# separate license, and if you have done so, the terms of that separate license control and -# the following references to GPL do not apply). -# -# This program is free software: you can redistribute it and/or modify it under the terms -# of the GNU Affero General Public License as published by the Free Software Foundation, -# either version 3 of the License, or (at your option) any later version. You should have -# received a copy of the GNU Affero General Public License along with this program. If not, -# see . - -#LOCAL_PATH := $(call my-dir) -#THIRD_PARTY_PATH := $(LOCAL_PATH)/../../../src/third-parties -# -########################################################### -# cryptopp -#include $(CLEAR_VARS) -#LOCAL_MODULE := cryptopp -# -#ifeq ($(READIUM_CLANG),true) -#LOCAL_CPPFLAGS := -std=c++11 -fpermissive -#LOCAL_CXXFLAGS := -std=c++11 -fpermissive -#LOCAL_CFLAGS := -std=c11 -#else -#LOCAL_CPPFLAGS := -std=gnu++11 -fpermissive -#LOCAL_CXXFLAGS := -std=gnu++11 -fpermissive -#LOCAL_CFLAGS := -std=gnu11 -#endif -# -#LOCAL_CPP_FEATURES += exceptions rtti -# -#ifeq ($(TARGET_ARCH_ABI),x86) -# LOCAL_CFLAGS += -mtune=atom -mssse3 -mfpmath=sse -#endif -# -#LOCAL_C_INCLUDES := $(THIRD_PARTY_PATH)/cryptopp -#LOCAL_SRC_FILES := $(wildcard $(THIRD_PARTY_PATH)/cryptopp/*.cpp) -# -#include $(BUILD_STATIC_LIBRARY) -# -########################################################### -# ZipLib -#include $(CLEAR_VARS) -#LOCAL_MODULE := ziplib -# -#ifeq ($(READIUM_CLANG),true) -#LOCAL_CPPFLAGS := -std=c++11 -fpermissive -#LOCAL_CXXFLAGS := -std=c++11 -fpermissive -#LOCAL_CFLAGS := -std=c11 -#else -#LOCAL_CPPFLAGS := -std=gnu++11 -fpermissive -#LOCAL_CXXFLAGS := -std=gnu++11 -fpermissive -#LOCAL_CFLAGS := -std=gnu11 -#endif -# -#LOCAL_CPP_FEATURES += exceptions rtti -# -#ifeq ($(TARGET_ARCH_ABI),x86) -# LOCAL_CFLAGS += -mtune=atom -mssse3 -mfpmath=sse -#endif -# -#LOCAL_C_INCLUDES := $(THIRD_PARTY_PATH)/Source/ZipLib -#LOCAL_SRC_FILES := \ -# $(wildcard $(THIRD_PARTY_PATH)/ziplib/Source/ZipLib/extlibs/zlib/*.c) \ -# $(wildcard $(THIRD_PARTY_PATH)/ziplib/Source/ZipLib/extlibs/lzma/unix/*.c) \ -# $(wildcard $(THIRD_PARTY_PATH)/ziplib/Source/ZipLib/extlibs/bzip2/*.c) \ -# $(wildcard $(THIRD_PARTY_PATH)/ziplib/Source/ZipLib/detail/*.cpp) \ -# $(wildcard $(THIRD_PARTY_PATH)/ziplib/Source/ZipLib/*.cpp) -# -#include $(BUILD_STATIC_LIBRARY) -# \ No newline at end of file diff --git a/platform/android/lcp/Stable.mk b/platform/android/lcp/Stable.mk deleted file mode 100644 index 4a13f05..0000000 --- a/platform/android/lcp/Stable.mk +++ /dev/null @@ -1,128 +0,0 @@ -# Copyright (c) 2014 Readium Foundation and/or its licensees. All rights reserved. -# -# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# -# Licensed under Gnu Affero General Public License Version 3 (provided, notwithstanding this -# notice, Readium Foundation reserves the right to license this material under a different -# separate license, and if you have done so, the terms of that separate license control and -# the following references to GPL do not apply). -# -# This program is free software: you can redistribute it and/or modify it under the terms -# of the GNU Affero General Public License as published by the Free Software Foundation, -# either version 3 of the License, or (at your option) any later version. You should have -# received a copy of the GNU Affero General Public License along with this program. If not, -# see . - -LOCAL_PATH := $(call my-dir) -SRC_PATH := $(LOCAL_PATH)/../../../src -LCP_CLIENT_LIB_PATH := $(SRC_PATH)/lcp-client-lib -LCP_CONTENT_FILTER_PATH := $(SRC_PATH)/lcp-content-filter -THIRD_PARTY_PATH := $(SRC_PATH)/third-parties - -########################################################### -# cryptopp -include $(CLEAR_VARS) -LOCAL_MODULE := cryptopp - -ifeq ($(READIUM_CLANG),true) -LOCAL_CPPFLAGS := -std=c++11 -fpermissive -LOCAL_CXXFLAGS := -std=c++11 -fpermissive -LOCAL_CFLAGS := -std=c11 -else -LOCAL_CPPFLAGS := -std=gnu++11 -fpermissive -LOCAL_CXXFLAGS := -std=gnu++11 -fpermissive -LOCAL_CFLAGS := -std=gnu11 -endif - -LOCAL_CPP_FEATURES += exceptions rtti - -ifeq ($(TARGET_ARCH_ABI),x86) - LOCAL_CFLAGS += -mtune=atom -mssse3 -mfpmath=sse -endif - -LOCAL_C_INCLUDES := $(THIRD_PARTY_PATH)/cryptopp -LOCAL_SRC_FILES := $(wildcard $(THIRD_PARTY_PATH)/cryptopp/*.cpp) - -include $(BUILD_STATIC_LIBRARY) - -########################################################### -# ZipLib -include $(CLEAR_VARS) -LOCAL_MODULE := ziplib - -ifeq ($(READIUM_CLANG),true) -LOCAL_CPPFLAGS := -std=c++11 -fpermissive -DZLIB_ONLY -LOCAL_CXXFLAGS := -std=c++11 -fpermissive -DZLIB_ONLY -LOCAL_CFLAGS := -std=c11 -DZLIB_ONLY -else -LOCAL_CPPFLAGS := -std=gnu++11 -fpermissive -DZLIB_ONLY -LOCAL_CXXFLAGS := -std=gnu++11 -fpermissive -DZLIB_ONLY -LOCAL_CFLAGS := -std=gnu11 -DZLIB_ONLY -endif - -LOCAL_CPP_FEATURES += exceptions rtti - -ifeq ($(TARGET_ARCH_ABI),x86) - LOCAL_CFLAGS += -mtune=atom -mssse3 -mfpmath=sse -endif - -LOCAL_C_INCLUDES := $(THIRD_PARTY_PATH)/Source/ZipLib -LOCAL_SRC_FILES := \ - $(wildcard $(THIRD_PARTY_PATH)/ziplib/Source/ZipLib/extlibs/zlib/*.c) \ - $(wildcard $(THIRD_PARTY_PATH)/ziplib/Source/ZipLib/extlibs/lzma/unix/*.c) \ - $(wildcard $(THIRD_PARTY_PATH)/ziplib/Source/ZipLib/extlibs/bzip2/*.c) \ - $(wildcard $(THIRD_PARTY_PATH)/ziplib/Source/ZipLib/detail/*.cpp) \ - $(wildcard $(THIRD_PARTY_PATH)/ziplib/Source/ZipLib/*.cpp) - -include $(BUILD_STATIC_LIBRARY) - -########################################################### -# Epub3 -include $(CLEAR_VARS) -LOCAL_MODULE := epub3 - -LOCAL_SRC_FILES := $(EPUB3_PATH)/libs/$(TARGET_ARCH_ABI)/libepub3.so - -include $(PREBUILT_SHARED_LIBRARY) - -########################################################### -# Lcp -include $(CLEAR_VARS) -LOCAL_MODULE := lcp - -ifeq ($(READIUM_CLANG),true) -LOCAL_CPPFLAGS := -std=c++11 -fpermissive -LOCAL_CXXFLAGS := -std=c++11 -fpermissive -DFEATURES_READIUM -LOCAL_CFLAGS := -std=c11 -else -LOCAL_CPPFLAGS := -std=gnu++11 -fpermissive -LOCAL_CXXFLAGS := -std=gnu++11 -fpermissive -DFEATURES_READIUM -LOCAL_CFLAGS := -std=gnu11 -endif - -LOCAL_CPP_FEATURES += exceptions rtti - -ifeq ($(TARGET_ARCH_ABI),x86) - LOCAL_CFLAGS += -mtune=atom -mssse3 -mfpmath=sse -endif - -LOCAL_STATIC_LIBRARIES := cryptopp ziplib -LOCAL_SHARED_LIBRARIES := epub3 -LOCAL_LDLIBS := -lz -landroid -llog - -LOCAL_C_INCLUDES += \ - $(EPUB3_PATH)/include \ - $(LCP_CLIENT_LIB_PATH) \ - $(LCP_CLIENT_LIB_PATH)/public \ - $(LCP_CONTENT_FILTER_PATH) \ - $(LCP_CONTENT_FILTER_PATH)/public \ - $(THIRD_PARTY_PATH) - -LOCAL_SRC_FILES := \ - $(wildcard $(THIRD_PARTY_PATH)/time64/*.c) \ - $(wildcard $(LCP_CLIENT_LIB_PATH)/*.cpp) \ - $(wildcard $(LCP_CONTENT_FILTER_PATH)/*.cpp) \ - $(wildcard $(LOCAL_PATH)/src/main/jni/*.cpp) - -include $(BUILD_SHARED_LIBRARY) diff --git a/platform/android/lcp/build.gradle b/platform/android/lcp/build.gradle deleted file mode 100644 index 7faa8a2..0000000 --- a/platform/android/lcp/build.gradle +++ /dev/null @@ -1,53 +0,0 @@ -import org.apache.tools.ant.taskdefs.condition.Os - -def ndk_skipX86 = (rootProject.hasProperty("readium_ndk_skipX86") && rootProject.readium_ndk_skipX86) -def ndk_skipARM = (rootProject.hasProperty("readium_ndk_skipARM") && rootProject.readium_ndk_skipARM) -def ndk_clang = (rootProject.hasProperty("readium_ndk_clang") && rootProject.readium_ndk_clang) -def ndk_experimental = (rootProject.hasProperty("readium_ndk_experimental") && rootProject.readium_ndk_experimental) - -if (ndk_experimental) { - println "${project.name}: Using Gradle EXPERIMENTAL to build LCP lib" - apply from: 'build_experimental.gradle' -} else { - println "${project.name}: Using Gradle STABLE to build LCP lib" -} - -task buildMk(type: Exec) { - // Retrieve ndk dir - Properties properties = new Properties() - properties.load(project.rootProject.file('local.properties').newDataInputStream()) - def ndkDir = properties.getProperty('ndk.dir', null) - - // Call ndk build - def ndkBuildExt = Os.isFamily(Os.FAMILY_WINDOWS) ? ".cmd" : "" - def projectPath = file('.').absolutePath - def buildScript = (ndk_experimental) ? "Experimental.mk" : "Stable.mk" - - environment 'EPUB3_PATH', project(':epub3').projectDir - - if (ndk_skipX86) environment 'READIUM_SKIPX86', 'true' - if (ndk_skipARM) environment 'READIUM_SKIPARM', 'true' - if (ndk_clang) environment 'READIUM_CLANG', 'true' - if (ndk_experimental) environment 'READIUM_DEBUG', 'true' - - commandLine "$ndkDir/ndk-build${ndkBuildExt}", - "-j", "4", //Runtime.runtime.availableProcessors() - '-C', projectPath, - 'NDK_APPLICATION_MK=Application.mk', - "APP_BUILD_SCRIPT=${buildScript}", - "NDK_PROJECT_PATH=${projectPath}", - "NDK_DEBUG=1" -} - -tasks.whenTaskAdded { task -> - def taskName = task.name - - if (taskName.startsWith("compile")) { - - if (ndk_experimental) { - println "${project.name} - ${taskName}: Using Gradle EXPERIMENTAL, no need to invoke external NDK / Makefile to build LCP lib" - } else { - task.dependsOn "buildMk" - } - } -} diff --git a/platform/android/lcp/build_experimental.gradle b/platform/android/lcp/build_experimental.gradle deleted file mode 100644 index a726d27..0000000 --- a/platform/android/lcp/build_experimental.gradle +++ /dev/null @@ -1,124 +0,0 @@ -apply plugin: 'com.android.model.native' - -def ndk_skipX86 = (rootProject.hasProperty("readium_ndk_skipX86") && rootProject.readium_ndk_skipX86) -def ndk_skipARM = (rootProject.hasProperty("readium_ndk_skipARM") && rootProject.readium_ndk_skipARM) -def ndk_clang = (rootProject.hasProperty("readium_ndk_clang") && rootProject.readium_ndk_clang) -def ndk_experimental = (rootProject.hasProperty("readium_ndk_experimental") && rootProject.readium_ndk_experimental) - -model { - android { - compileSdkVersion = 25 - sources { - main { - jni { - source { - srcDirs = [ - './src/main/jni', - '../../../src/lcp-client-lib', - '../../../src/lcp-content-filter', - '../../../src/third-parties' - ] - - excludes.add('curl/**/*.*') - excludes.add('gtest/**/*.*') - excludes.add('rapidjson/**/*.*') - excludes.add('utf8-cpp/**/*.*') - excludes.add('cryptopp/*test.cpp') - excludes.add('cryptopp/TestScripts/*.*') - excludes.add('cryptopp/bench*.cpp') - excludes.add('cryptopp/validat*.cpp') - excludes.add('cryptopp/adhoc.cpp') - excludes.add('ziplib/Source/Sample/*.*') - excludes.add('ziplib/Source/ZipLib/extlibs/lzma/*.c') - excludes.add('ziplib/Source/ZipLib/extlibs/lzma/**/*.c') - } //source - - exportedHeaders { - srcDir "./src/main/jni" - } - - dependencies { - project ":epub3" linkage "shared" - } - } - } - } //sources - - ndk { - moduleName = "lcp" - - //arguments "-j 4" //Runtime.runtime.availableProcessors() - - toolchain = ndk_clang ? "clang" : "gcc" - toolchainVersion = ndk_clang ? "" : "4.9" //https://github.com/android-ndk/ndk/issues/229 - - def clangWithGnuStl = false - - if (!ndk_clang || clangWithGnuStl) - stl = "gnustl_shared" - else - stl = "c++_shared" - - def arrayFlags = [ - "-fexceptions", - "-fpic", - "-DFEATURES_READIUM", - "-DZLIB_ONLY", - ndk_clang ? "-D_LIBCPP_INLINE_VISIBILITY_EXCEPT_GCC49=_LIBCPP_INLINE_VISIBILITY" : "-DREADIUM_GCC", - "-I" + project(':epub3').projectDir + "/include", - "-I${file("../../../src/lcp-client-lib")}".toString(), - "-I${file("../../../src/lcp-client-lib/public")}".toString(), - "-I${file("../../../src/lcp-content-filter")}".toString(), - "-I${file("../../../src/lcp-content-filter/public")}".toString(), - "-I${file("../../../src/third-parties")}".toString() - ] - - def arrayFlagsCPP = [ - "-fpermissive", - "-frtti" - ] - - cppFlags.addAll(arrayFlags) - cppFlags.addAll(arrayFlagsCPP) - cppFlags.add((!ndk_clang || clangWithGnuStl) ? "-std=gnu++11" : "-std=c++11") - - CFlags.addAll(arrayFlags) - CFlags.add((!ndk_clang || clangWithGnuStl) ? "-std=gnu11" : "-std=c11") - - ldLibs.addAll(['z', 'android', 'log']) - if (ndk_clang) ldLibs.addAll(['atomic']) - } //ndk - - buildTypes { - release { - - } - debug { - ndk.with { - debuggable = true //"NDK_DEBUG=1" - } - } - } //buildTypes - - productFlavors { - if (!ndk_skipARM) - create("arm") { - ndk.with { - abiFilters.add("armeabi-v7a") - ldFlags.addAll([ - "-L${file("./obj/local/armeabi-v7a")}".toString() - ]) - } - } - if (!ndk_skipX86) - create("x86") { - ndk.with { - abiFilters.add("x86") - ldFlags.addAll([ - "-L${file("./obj/local/x86")}".toString() - ]) - } - } - } //productFlavors - } //android -} //model \ No newline at end of file diff --git a/platform/android/lib/CMakeLists.txt b/platform/android/lib/CMakeLists.txt new file mode 100644 index 0000000..f85414c --- /dev/null +++ b/platform/android/lib/CMakeLists.txt @@ -0,0 +1,74 @@ +# Global options +cmake_minimum_required(VERSION 3.6.0) +set(CMAKE_VERBOSE_MAKEFILE od) + +set(MODULE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(PROJECT_DIR ${MODULE_DIR}/..) +set(ROOT_DIR ${PROJECT_DIR}/../..) +set(DISTRIBUTION_DIR ${PROJECT_DIR}/dist/${CMAKE_BUILD_TYPE}/${ANDROID_ABI}) +set("ndk-stl_DIR" "${CMAKE_CURRENT_SOURCE_DIR}") + +include(${PROJECT_DIR}/lib/clientlib.cmake) +# Android Studio 2.x with CMake support does not pack stl shared libraries, +# so app needs to pack the right shared lib into APK. This sample uses solution +# from https://github.com/jomof/ndk-stl to find the right stl shared lib to use +# and copy it to the right place for Android Studio to pack +# Usage: download ndk-stl-config.cmake into app's directory hosting CMakeLists.txt +# and just use it with the following line +include(${PROJECT_DIR}/lib/ndk-stl-config.cmake) + +if("${FEATURES_READIUM}") + add_definitions("-DFEATURES_READIUM") +endif() + +# Compiler options +add_definitions("-DZLIB_ONLY") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -fpic -frtti -fexceptions -fpermissive -Wall") + +#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11") +#set(CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS} -std=gnu11") +#set(CMAKE_REQUIRED_FLAGS ${CMAKE_ANSI_CFLAGS}) + +include_directories( + ${CLIENTLIB_DIR} + ${CLIENTLIB_DIR}/public + ${THIRDPARTY_DIR} + ${MODULE_DIR}/src/clientlib/cpp/) + +# Client lib JNI files +file(GLOB CLIENTLIB_JNI_SOURCES ${MODULE_DIR}/src/clientlib/cpp/*.cpp) + +# LCP with content filter +add_definitions("-DREADIUM_GCC") +include(${PROJECT_DIR}/lib/contentfilter.cmake) +file(GLOB CONTENTFILTER_JNI_SOURCES ${MODULE_DIR}/src/contentfilter/cpp/*.cpp) +include_directories( + ${CONTENTFILTER_DIR} + ${CONTENTFILTER_DIR}/public + ${RSDK_INCLUDE_DIR} + ${MODULE_DIR}/src/contentfilter/cpp/) + +# Link libraries used by LCP shared library +SET ( + LCP_LINK_LIBRARIES + "clientlib" + "contentfilter" + "${RSDK_LIB_DIR}/${CMAKE_BUILD_TYPE}/${ANDROID_ABI}/libepub3.so" +) + +# Extra cmake called before build +if(EXISTS "${EXTRA_CMAKE}") + include(${EXTRA_CMAKE}) +endif() + +# Targets to build +add_library("clientlib" STATIC ${CLIENTLIB_ALL_SOURCES}) +add_library("lcp-min" SHARED ${CLIENTLIB_JNI_SOURCES}) +add_library("contentfilter" STATIC ${CONTENTFILTER_SOURCES}) +add_library("lcp" SHARED + ${CLIENTLIB_JNI_SOURCES} + ${CONTENTFILTER_JNI_SOURCES}) + +# Target links +target_link_libraries("lcp" ${LCP_LINK_LIBRARIES}) +target_link_libraries("lcp-min" "clientlib") diff --git a/platform/android/lib/build.gradle b/platform/android/lib/build.gradle index b8d0fa9..02af41a 100644 --- a/platform/android/lib/build.gradle +++ b/platform/android/lib/build.gradle @@ -1,55 +1,244 @@ -apply plugin: 'com.android.model.library' +apply plugin: 'com.android.library' -model { - android { - compileSdkVersion = 23 - buildToolsVersion = "23.0.2" +repositories { + mavenCentral() + jcenter() +} - defaultConfig.with { - minSdkVersion.apiLevel = 19 - targetSdkVersion.apiLevel = 23 +dependencies { + compile 'com.android.support:support-v4:25.+' + compile 'commons-io:commons-io:2.4' + compile 'com.koushikdutta.ion:ion:2.+' +} + +def ndk_skipX86 = (rootProject.hasProperty("readium_ndk_skipX86") && rootProject.readium_ndk_skipX86) +def ndk_skipARM = (rootProject.hasProperty("readium_ndk_skipARM") && rootProject.readium_ndk_skipARM) +def ndk_clang = (rootProject.hasProperty("readium_ndk_clang") && rootProject.readium_ndk_clang) +def readiumSdkLibDir = null +def readiumSdkIncludeDir = null +def lcpBuildContentFilter = false +def extraCmake = null + +if (rootProject.hasProperty("readium_extra_cmake")) { + extraCmake = rootProject.readium_extra_cmake +} + +if (rootProject.hasProperty("readium_sdk_lib_dir")) { + readiumSdkLibDir = rootProject.readium_sdk_lib_dir +} + +if (rootProject.hasProperty("readium_sdk_include_dir")) { + readiumSdkIncludeDir = rootProject.readium_sdk_include_dir +} + +if (rootProject.hasProperty("readium_lcp_build_content_filter")) { + lcpBuildContentFilter = rootProject.readium_lcp_build_content_filter +} +println("extraCmake ${extraCmake}") +def toolchain = ndk_clang ? "clang" : "gcc" +def stl = ndk_clang ? "c++_shared" : "gnustl_shared" + +if (!lcpBuildContentFilter) { + try { + def epub3Dir = project(':epub3').projectDir + readiumSdkLibDir = "${epub3Dir}/libs" + readiumSdkIncludeDir = "${epub3Dir}/include" + lcpBuildContentFilter = true + println("Build with rsdk *") + } catch (UnknownProjectException e) { + // No epub3 project is defined + println("Build without rsdk") + } +} else { + println("Build with rsdk") +} +println "${lcpBuildContentFilter}" +println "${readiumSdkLibDir}" +println "${readiumSdkIncludeDir}" +android { + compileSdkVersion 26 + buildToolsVersion "27.0.3" + + defaultConfig { + minSdkVersion 19 + targetSdkVersion 26 + versionCode 1 + versionName "1.0" + + externalNativeBuild { + cmake { + if (lcpBuildContentFilter) { + targets "clientlib", "contentfilter", "lcp" + + arguments "-DFEATURES_READIUM=1", + "-DANDROID_PLATFORM=android-19", + "-DANDROID_TOOLCHAIN=${toolchain}", + "-DANDROID_STL=${stl}", + "-DRSDK_INCLUDE_DIR=${readiumSdkIncludeDir}", + "-DRSDK_LIB_DIR=${readiumSdkLibDir}", + "-DEXTRA_CMAKE=${extraCmake}" + } else { + targets "clientlib", "lcp-min" + + arguments "-DANDROID_PLATFORM=android-19", + "-DANDROID_TOOLCHAIN=${toolchain}", + "-DANDROID_STL=${stl}", + "-DRSDK_INCLUDE_DIR=${readiumSdkIncludeDir}", + "-DRSDK_LIB_DIR=${readiumSdkLibDir}", + "-DEXTRA_CMAKE=${extraCmake}" + } + } } + } - sources { + sourceSets { + if (lcpBuildContentFilter) { main { - jniLibs { - dependencies { - project ":lcp" - } + java { + srcDirs = [ + './src/clientlib/java', + './src/contentfilter/java' + ] } } + } else { main { java { - source { - srcDirs = [ - './src/main/java' - ] - } + srcDirs = [ + './src/clientlib/java' + ] } } } + } - buildTypes { - debug { - minifyEnabled = false + buildTypes { + release { + externalNativeBuild { + cmake { + arguments '-DCMAKE_BUILD_TYPE=RELEASE' + } } - release { - minifyEnabled = false - proguardFiles.add(file('proguard-rules.txt')) + } + + debug { + externalNativeBuild { + cmake { + arguments '-DCMAKE_BUILD_TYPE=DEBUG' + } } } + } + + externalNativeBuild { + cmake { + path "CMakeLists.txt" + } + } - productFlavors { - create ("arm") { - ndk.with { - abiFilters.add("armeabi-v7a") + productFlavors { + if (!ndk_skipARM) { + arm7 { + ndk { + abiFilter 'armeabi-v7a' } } - create ("x86") { - ndk.with { - abiFilters.add("x86") + } + if (!ndk_skipX86) { + x86 { + ndk { + abiFilter 'x86' } } } + /*arm8 { + ndk { + abiFilters 'arm64-v8a' + } + } + arm { + ndk { + abiFilter 'armeabi' + } + } + x86_64 { + ndk { + abiFilter 'x86_64' + } + }*/ + } +} + +build.doLast { + println("Copy libs to dist directory") + android.productFlavors.all { flavor -> + android.buildTypes.all { buildType -> + def abiFilter = flavor.ndk.abiFilters.first() + def dstDirPath = "${project.projectDir}/../dist/${buildType.name.toLowerCase()}/${abiFilter}" + + // Copy static libs + def srcDirPath = "${project.projectDir}/.externalNativeBuild/cmake/${flavor.name}${buildType.name.capitalize()}/${abiFilter}" + + copy { + from("${srcDirPath}") { + include("*.a") + } + into("${dstDirPath}") + } + + // Copy shared libs + srcDirPath = "${project.projectDir}/build/intermediates/cmake/${flavor.name}/${buildType.name}/obj/${abiFilter}" + + copy { + from("${srcDirPath}") { + include("*.so") + } + into("${dstDirPath}") + } + + // Copy aar + srcDirPath = "${project.projectDir}/build/outputs/aar" + def srcFilename = "lib-${flavor.name}-${buildType.name}.aar" + + copy { + from("${srcDirPath}") { + include(srcFilename) + } + into("${dstDirPath}") + rename(srcFilename, "liblcp.aar") + } + } + } +} + +clean.doFirst { + println("Clean dist directory") + def dstDirPath = "${project.projectDir}/../dist/" + delete dstDirPath +} + +task copyLibs { + doLast { + println ("Copy shared library to libs") + android.productFlavors.all { flavor -> + android.buildTypes.all { buildType -> + def abiFilter = flavor.ndk.abiFilters.first() + def srcDirPath = "${project.projectDir}/build/intermediates/cmake/${flavor.name}/${buildType.name}/obj/${abiFilter}" + def dstDirPath = "${project.projectDir}/libs/${abiFilter}" + + copy { + from("${srcDirPath}") { + include("liblcp.so") + } + into("${dstDirPath}") + } + } + } + } +} + +tasks.whenTaskAdded { task -> + if (task.name.startsWith('assemble')) { + task.dependsOn copyLibs } -} \ No newline at end of file +} diff --git a/platform/android/lib/clientlib.cmake b/platform/android/lib/clientlib.cmake new file mode 100644 index 0000000..6497178 --- /dev/null +++ b/platform/android/lib/clientlib.cmake @@ -0,0 +1,33 @@ +# Path definitions +set(CLIENTLIB_DIR ${ROOT_DIR}/src/lcp-client-lib) +set(THIRDPARTY_DIR ${ROOT_DIR}/src/third-parties) + +# CryptoPP +file(GLOB_RECURSE CRYPTOPP_SOURCES ${THIRDPARTY_DIR}/cryptopp/*.cpp) +list(FILTER CRYPTOPP_SOURCES EXCLUDE REGEX "TestScripts/.*\.cpp") +list(FILTER CRYPTOPP_SOURCES EXCLUDE REGEX "bench.*\.cpp") +list(FILTER CRYPTOPP_SOURCES EXCLUDE REGEX ".*test\.cpp") +list(FILTER CRYPTOPP_SOURCES EXCLUDE REGEX "validat.*\.cpp") +list(FILTER CRYPTOPP_SOURCES EXCLUDE REGEX "adhoc\.cpp") + +# ZipLib +file(GLOB ZIPLIB_SOURCES + ${THIRDPARTY_DIR}/ziplib/Source/ZipLib/extlibs/zlib/*\.c + ${THIRDPARTY_DIR}/ziplib/Source/ZipLib/extlibs/lzma/unix/*\.c + ${THIRDPARTY_DIR}/ziplib/Source/ZipLib/extlibs/bzip2/*\.c + ${THIRDPARTY_DIR}/ziplib/Source/ZipLib/detail/*\.cpp + ${THIRDPARTY_DIR}/ziplib/Source/ZipLib//*\.cpp + ) + +# Time64 +file(GLOB_RECURSE TIME64_SOURCES ${THIRDPARTY_DIR}/time64/*.c) + +# Client lib +file(GLOB CLIENTLIB_SOURCES ${CLIENTLIB_DIR}/*.cpp) + +set(CLIENTLIB_ALL_SOURCES + ${CRYPTOPP_SOURCES} + ${ZIPLIB_SOURCES} + ${TIME64_SOURCES} + ${CLIENTLIB_SOURCES} +) diff --git a/platform/android/lib/contentfilter.cmake b/platform/android/lib/contentfilter.cmake new file mode 100644 index 0000000..72c53cc --- /dev/null +++ b/platform/android/lib/contentfilter.cmake @@ -0,0 +1,5 @@ +# Path definitions +set(CONTENTFILTER_DIR ${ROOT_DIR}/src/lcp-content-filter) + +# Content filter +file(GLOB CONTENTFILTER_SOURCES ${CONTENTFILTER_DIR}/*.cpp) \ No newline at end of file diff --git a/platform/android/lib/ndk-stl-config.cmake b/platform/android/lib/ndk-stl-config.cmake new file mode 100644 index 0000000..3133faf --- /dev/null +++ b/platform/android/lib/ndk-stl-config.cmake @@ -0,0 +1,39 @@ +# Copy shared STL files to Android Studio output directory so they can be +# packaged in the APK. +# Usage: +# +# find_package(ndk-stl REQUIRED) +# +# or +# +# find_package(ndk-stl REQUIRED PATHS ".") + +if(NOT ${ANDROID_STL} MATCHES "_shared") + return() +endif() + +function(configure_shared_stl lib_path so_base) + message("Configuring STL ${so_base} for ${ANDROID_ABI}") + configure_file( + "${ANDROID_NDK}/sources/cxx-stl/${lib_path}/libs/${ANDROID_ABI}/lib${so_base}.so" + "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${so_base}.so" + COPYONLY) +endfunction() + +if("${ANDROID_STL}" STREQUAL "libstdc++") + # The default minimal system C++ runtime library. +elseif("${ANDROID_STL}" STREQUAL "gabi++_shared") + # The GAbi++ runtime (shared). + message(FATAL_ERROR "gabi++_shared was not configured by ndk-stl package") +elseif("${ANDROID_STL}" STREQUAL "stlport_shared") + # The STLport runtime (shared). + configure_shared_stl("stlport" "stlport_shared") +elseif("${ANDROID_STL}" STREQUAL "gnustl_shared") + # The GNU STL (shared). + configure_shared_stl("gnu-libstdc++/4.9" "gnustl_shared") +elseif("${ANDROID_STL}" STREQUAL "c++_shared") + # The LLVM libc++ runtime (shared). + configure_shared_stl("llvm-libc++" "c++_shared") +else() + message(FATAL_ERROR "STL configuration ANDROID_STL=${ANDROID_STL} is not supported") +endif() diff --git a/platform/android/lcp/src/main/jni/Acquisition.cpp b/platform/android/lib/src/clientlib/cpp/Acquisition.cpp similarity index 100% rename from platform/android/lcp/src/main/jni/Acquisition.cpp rename to platform/android/lib/src/clientlib/cpp/Acquisition.cpp diff --git a/platform/android/lcp/src/main/jni/Acquisition.h b/platform/android/lib/src/clientlib/cpp/Acquisition.h similarity index 100% rename from platform/android/lcp/src/main/jni/Acquisition.h rename to platform/android/lib/src/clientlib/cpp/Acquisition.h diff --git a/platform/android/lcp/src/main/jni/AcquisitionCallback.cpp b/platform/android/lib/src/clientlib/cpp/AcquisitionCallback.cpp similarity index 100% rename from platform/android/lcp/src/main/jni/AcquisitionCallback.cpp rename to platform/android/lib/src/clientlib/cpp/AcquisitionCallback.cpp diff --git a/platform/android/lcp/src/main/jni/AcquisitionCallback.h b/platform/android/lib/src/clientlib/cpp/AcquisitionCallback.h similarity index 100% rename from platform/android/lcp/src/main/jni/AcquisitionCallback.h rename to platform/android/lib/src/clientlib/cpp/AcquisitionCallback.h diff --git a/platform/android/lcp/src/main/jni/License.cpp b/platform/android/lib/src/clientlib/cpp/License.cpp similarity index 94% rename from platform/android/lcp/src/main/jni/License.cpp rename to platform/android/lib/src/clientlib/cpp/License.cpp index 02ba883..702cf74 100644 --- a/platform/android/lcp/src/main/jni/License.cpp +++ b/platform/android/lib/src/clientlib/cpp/License.cpp @@ -49,6 +49,14 @@ JNIEXPORT jstring JNICALL Java_org_readium_sdk_lcp_License_nativeGetOriginalCont return res; } +JNIEXPORT jstring JNICALL Java_org_readium_sdk_lcp_License_nativeGetPassphraseHint( + JNIEnv *env, jobject obj, jlong licensePtr) { + lcp::ILicense * license = (lcp::ILicense *) licensePtr; + std::string hint = license->Crypto()->UserKeyHint(); + jstring res = env->NewStringUTF(hint.c_str()); + return res; +} + JNIEXPORT jstring JNICALL Java_org_readium_sdk_lcp_License_nativeGetLinkPublication( JNIEnv *env, jobject obj, jlong licensePtr) { lcp::ILicense * license = (lcp::ILicense *) licensePtr; diff --git a/platform/android/lcp/src/main/jni/License.h b/platform/android/lib/src/clientlib/cpp/License.h similarity index 95% rename from platform/android/lcp/src/main/jni/License.h rename to platform/android/lib/src/clientlib/cpp/License.h index 5faf05c..22a7ed9 100644 --- a/platform/android/lcp/src/main/jni/License.h +++ b/platform/android/lib/src/clientlib/cpp/License.h @@ -45,6 +45,9 @@ JNIEXPORT jboolean JNICALL Java_org_readium_sdk_lcp_License_nativeIsDecrypted( JNIEXPORT jstring JNICALL Java_org_readium_sdk_lcp_License_nativeGetOriginalContent( JNIEnv *env, jobject obj, jlong licensePtr); +JNIEXPORT jstring JNICALL Java_org_readium_sdk_lcp_License_nativeGetPassphraseHint( + JNIEnv *env, jobject obj, jlong licensePtr); + JNIEXPORT jstring JNICALL Java_org_readium_sdk_lcp_License_nativeGetLinkPublication( JNIEnv *env, jobject obj, jlong licensePtr); diff --git a/platform/android/lcp/src/main/jni/NetProvider.cpp b/platform/android/lib/src/clientlib/cpp/NetProvider.cpp similarity index 88% rename from platform/android/lcp/src/main/jni/NetProvider.cpp rename to platform/android/lib/src/clientlib/cpp/NetProvider.cpp index 5247cf2..01887f6 100644 --- a/platform/android/lcp/src/main/jni/NetProvider.cpp +++ b/platform/android/lib/src/clientlib/cpp/NetProvider.cpp @@ -27,6 +27,8 @@ #if !DISABLE_NET_PROVIDER #include "NetProvider.h" +#include "BaseDownloadRequest.h" + #include "Util.h" namespace lcp { @@ -49,6 +51,12 @@ namespace lcp { ) { JNIEnv * env = getJNIEnv(); jstring jUrl = env->NewStringUTF(request->Url().c_str()); + + if (!request->HasDestinationPath()) { + // TODO: write to STREAM instead!! + // request->DestinationStream() + } + jstring jDstPath = env->NewStringUTF(request->DestinationPath().c_str()); env->CallVoidMethod(this->jNetProvider, this->jDownloadMethodId, jUrl, jDstPath, (jlong) request, (jlong) callback); @@ -70,9 +78,18 @@ JNIEXPORT void JNICALL Java_org_readium_sdk_lcp_NetProviderCallback_nativeOnRequ } JNIEXPORT void JNICALL Java_org_readium_sdk_lcp_NetProviderCallback_nativeOnRequestEnded( - JNIEnv *env, jobject obj, jlong callbackPtr, jlong requestPtr) { + JNIEnv *env, jobject obj, jlong callbackPtr, jlong requestPtr, jstring path) { lcp::INetProviderCallback * callback = (lcp::INetProviderCallback *) callbackPtr; lcp::IDownloadRequest * request = (lcp::IDownloadRequest *) requestPtr; + + // This is a hack, see TODO above in StartDownloadRequest() (Java/JNI NetProvider only supports download-to-file, not memory stream!) + lcp::BaseDownloadRequest* request_ = dynamic_cast(request); + if (request_) { + const char *path_ = env->GetStringUTFChars(path, 0); + request_->SetSuggestedFileName(std::string(path_)); + } + + lcp::Status status(lcp::StatusCode::ErrorCommonSuccess); callback->OnRequestEnded(request, status); } @@ -91,4 +108,4 @@ JNIEXPORT void JNICALL Java_org_readium_sdk_lcp_NetProviderCallback_nativeOnRequ callback->OnRequestProgressed(request, progress); } -#endif //!DISABLE_NET_PROVIDER \ No newline at end of file +#endif //!DISABLE_NET_PROVIDER diff --git a/platform/android/lcp/src/main/jni/NetProvider.h b/platform/android/lib/src/clientlib/cpp/NetProvider.h similarity index 99% rename from platform/android/lcp/src/main/jni/NetProvider.h rename to platform/android/lib/src/clientlib/cpp/NetProvider.h index 50ad522..e9f6414 100644 --- a/platform/android/lcp/src/main/jni/NetProvider.h +++ b/platform/android/lib/src/clientlib/cpp/NetProvider.h @@ -61,7 +61,7 @@ namespace lcp { JNIEXPORT void JNICALL Java_org_readium_sdk_lcp_NetProviderCallback_nativeOnRequestStarted( JNIEnv *env, jobject obj, jlong callbackPtr, jlong requestPtr); JNIEXPORT void JNICALL Java_org_readium_sdk_lcp_NetProviderCallback_nativeOnRequestEnded( - JNIEnv *env, jobject obj, jlong callbackPtr, jlong requestPtr); + JNIEnv *env, jobject obj, jlong callbackPtr, jlong requestPtr, jstring path); JNIEXPORT void JNICALL Java_org_readium_sdk_lcp_NetProviderCallback_nativeOnRequestCanceled( JNIEnv *env, jobject obj, jlong callbackPtr, jlong requestPtr); JNIEXPORT void JNICALL Java_org_readium_sdk_lcp_NetProviderCallback_nativeOnRequestProgressed( diff --git a/platform/android/lcp/src/main/jni/Service.cpp b/platform/android/lib/src/clientlib/cpp/Service.cpp similarity index 98% rename from platform/android/lcp/src/main/jni/Service.cpp rename to platform/android/lib/src/clientlib/cpp/Service.cpp index f6b625a..d49d78f 100644 --- a/platform/android/lcp/src/main/jni/Service.cpp +++ b/platform/android/lib/src/clientlib/cpp/Service.cpp @@ -30,10 +30,9 @@ #include #include -#include - -//#include +#if FEATURES_READIUM extern "C" jboolean javaEPub3_handleSdkError(JNIEnv *env, jstring message, jboolean isSevereEpubError); +#endif //extern "C" jstring toJstring(JNIEnv *env, const char* str, bool freeNative = false); @@ -90,18 +89,22 @@ JNIEXPORT jobject JNICALL Java_org_readium_sdk_lcp_Service_nativeOpenLicense( if (!lcp::Status::IsSuccess(status)) { +#if FEATURES_READIUM //jstring test = toJstring(env, "test", false); jstring jmessage = env->NewStringUTF(lcp::Status::ToString(status).c_str()); jboolean b = javaEPub3_handleSdkError(env, jmessage, (jboolean)true); env->DeleteLocalRef(jmessage); +#endif return nullptr; } } catch (lcp::StatusException &ex) { +#if FEATURES_READIUM jstring jmessage = env->NewStringUTF(ex.what()); jboolean b = javaEPub3_handleSdkError(env, jmessage, (jboolean)true); env->DeleteLocalRef(jmessage); +#endif return nullptr; } diff --git a/platform/android/lcp/src/main/jni/Service.h b/platform/android/lib/src/clientlib/cpp/Service.h similarity index 100% rename from platform/android/lcp/src/main/jni/Service.h rename to platform/android/lib/src/clientlib/cpp/Service.h diff --git a/platform/android/lcp/src/main/jni/StorageProvider.cpp b/platform/android/lib/src/clientlib/cpp/StorageProvider.cpp similarity index 100% rename from platform/android/lcp/src/main/jni/StorageProvider.cpp rename to platform/android/lib/src/clientlib/cpp/StorageProvider.cpp diff --git a/platform/android/lcp/src/main/jni/StorageProvider.h b/platform/android/lib/src/clientlib/cpp/StorageProvider.h similarity index 100% rename from platform/android/lcp/src/main/jni/StorageProvider.h rename to platform/android/lib/src/clientlib/cpp/StorageProvider.h diff --git a/platform/android/lcp/src/main/jni/Util.cpp b/platform/android/lib/src/clientlib/cpp/Util.cpp similarity index 100% rename from platform/android/lcp/src/main/jni/Util.cpp rename to platform/android/lib/src/clientlib/cpp/Util.cpp diff --git a/platform/android/lcp/src/main/jni/Util.h b/platform/android/lib/src/clientlib/cpp/Util.h similarity index 100% rename from platform/android/lcp/src/main/jni/Util.h rename to platform/android/lib/src/clientlib/cpp/Util.h diff --git a/platform/android/lib/src/main/java/org/readium/sdk/lcp/Acquisition.java b/platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/Acquisition.java similarity index 100% rename from platform/android/lib/src/main/java/org/readium/sdk/lcp/Acquisition.java rename to platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/Acquisition.java diff --git a/platform/android/lib/src/main/java/org/readium/sdk/lcp/DoneCallback.java b/platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/DoneCallback.java similarity index 100% rename from platform/android/lib/src/main/java/org/readium/sdk/lcp/DoneCallback.java rename to platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/DoneCallback.java diff --git a/platform/android/lib/src/main/java/org/readium/sdk/lcp/Lcp.java b/platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/Lcp.java similarity index 100% rename from platform/android/lib/src/main/java/org/readium/sdk/lcp/Lcp.java rename to platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/Lcp.java diff --git a/platform/android/lib/src/main/java/org/readium/sdk/lcp/License.java b/platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/License.java similarity index 95% rename from platform/android/lib/src/main/java/org/readium/sdk/lcp/License.java rename to platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/License.java index 4588a32..8163fe0 100644 --- a/platform/android/lib/src/main/java/org/readium/sdk/lcp/License.java +++ b/platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/License.java @@ -43,6 +43,10 @@ public String getOriginalContent() { return this.nativeGetOriginalContent(this.nativePtr); } + public String getPassphraseHint() { + return this.nativeGetPassphraseHint(this.nativePtr); + } + public void decrypt(String passphrase) { this.nativeDecrypt(this.nativePtr, this.servicePtr, passphrase); } @@ -86,6 +90,8 @@ private long getNativePtr() { private native String nativeGetOriginalContent(long nativePtr); + private native String nativeGetPassphraseHint(long nativePtr); + private native String nativeGetLinkPublication(long nativePtr); private native String nativeGetLinkStatus(long nativePtr); diff --git a/platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/NetProvider.java b/platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/NetProvider.java new file mode 100644 index 0000000..94e53dd --- /dev/null +++ b/platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/NetProvider.java @@ -0,0 +1,208 @@ +// Licensed to the Readium Foundation under one or more contributor license agreements. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation and/or +// other materials provided with the distribution. +// 3. Neither the name of the organization nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +package org.readium.sdk.lcp; + +import android.app.Activity; +import android.content.Context; +import android.net.Uri; +import android.os.AsyncTask; +import android.util.Log; + +import com.koushikdutta.async.future.Future; +import com.koushikdutta.async.future.FutureCallback; +import com.koushikdutta.async.http.AsyncHttpRequest; +import com.koushikdutta.async.http.Headers; +import com.koushikdutta.ion.Ion; +import com.koushikdutta.ion.Response; +import com.koushikdutta.ion.loader.AsyncHttpRequestFactory; + +import org.apache.commons.io.IOUtils; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; + +public class NetProvider { +//#if !DISABLE_NET_PROVIDER + + private Context context; + private Activity activity; + private Map>> requests; + + /** + * Cancel request asynchronously + */ + private class CancelRequest extends AsyncTask { + @Override + protected Void doInBackground(Long... requestPtrs) { + for (Long requestPtr: requestPtrs) { + Future> request = NetProvider.this.requests.get(requestPtr); + request.cancel(); + } + + return null; + } + } + + public NetProvider(Context context, Activity activity) { + this.context = context; + this.activity = activity; + + this.requests = new HashMap<>(); + } + + public void download(final String url, String dstPath, final long requestPtr, long callbackPtr) { + + final NetProviderCallback callback = new NetProviderCallback(callbackPtr, requestPtr); + + if (dstPath == null || dstPath.isEmpty()) { + File outputDir = this.context.getCacheDir(); + File outputFile = null; + try { + outputFile = File.createTempFile("readium_TEMP_download", ".tmp", outputDir); + dstPath = outputFile.getAbsolutePath(); + } catch (IOException e) { + e.printStackTrace(); + } + } + final String destPath = dstPath; + +// Timer timer = new Timer(); +// timer.schedule(new TimerTask() { +// @Override +// public void run() { +// +// } +// }, 500); + +// runOnUiThread(new Runnable() { +// @Override +// public void run() { +// +// new AsyncTask() { +// @Override +// protected Void doInBackground(Void... params) { + +// final AsyncHttpRequestFactory current = Ion.getDefault(context).configure().getAsyncHttpRequestFactory(); +// Ion.getDefault(context).configure().setAsyncHttpRequestFactory(new AsyncHttpRequestFactory() { +// @Override +// public AsyncHttpRequest createAsyncHttpRequest(Uri uri, String method, Headers headers) { +// AsyncHttpRequest ret = current.createAsyncHttpRequest(uri, method, headers); +// ret.setTimeout(1000); +// return ret; +// } +// }); + +// this.activity.runOnUiThread(new Runnable() { +// @Override +// public void run() { + + Future> request = Ion.with(NetProvider.this.context) + .load("GET", url) + .setLogging("Readium Ion", Log.VERBOSE) + + //.setTimeout(AsyncHttpRequest.DEFAULT_TIMEOUT) //30000 + .setTimeout(6000) + + // TODO: comment this in production! (this is only for testing a local HTTP server) + //.setHeader("X-Add-Delay", "2s") + + .progress(callback) // not UI thread + //.progressHandler(callback) // UI thread + + .asInputStream() + .withResponse() + + // UI thread + .setCallback(new FutureCallback>() { + @Override + public void onCompleted(Exception e, Response response) { + + InputStream inputStream = response != null ? response.getResult() : null; + int httpResponseCode = response != null ? response.getHeaders().code() : 0; + if (e != null || inputStream == null + || httpResponseCode < 200 || httpResponseCode >= 300) { + + callback.onCompleted(e, null); + return; + } + + File destFile = new File(destPath); + try { + FileOutputStream outputStream = new FileOutputStream(destFile); + //inputStream.transferTo(outputStream); + + byte[] buf = new byte[4096]; + int n; + int total = 0; + while ((n = inputStream.read(buf)) > 0) { + total += n; + outputStream.write(buf, 0, n); + } + outputStream.close(); +// inputStream.close(); + callback.onCompleted(null, destFile); + + } catch (Exception ex) { + ex.printStackTrace(); + callback.onCompleted(ex, null); + } finally { + try { + inputStream.close(); + } catch (IOException ex) { + ex.printStackTrace(); + // ignore + } + } + } + }); + + NetProvider.this.requests.put(requestPtr, request); + +//// ASYNC TASK +// return null; + +// } +// }); + } + + public void cancel(long requestPtr) { + // Cancel ion request + if (!this.requests.containsKey(requestPtr)) { + return; + } + + new CancelRequest().execute(requestPtr); + } +} diff --git a/platform/android/lib/src/main/java/org/readium/sdk/lcp/NetProviderCallback.java b/platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/NetProviderCallback.java similarity index 98% rename from platform/android/lib/src/main/java/org/readium/sdk/lcp/NetProviderCallback.java rename to platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/NetProviderCallback.java index 6de0f6c..75ad832 100644 --- a/platform/android/lib/src/main/java/org/readium/sdk/lcp/NetProviderCallback.java +++ b/platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/NetProviderCallback.java @@ -77,7 +77,7 @@ public void onCompleted(Exception e, File result) { // Request timeout this.nativeOnRequestCanceled(this.nativePtr, this.requestPtr); } else if (e == null && result != null) { - this.nativeOnRequestEnded(this.nativePtr, this.requestPtr); + this.nativeOnRequestEnded(this.nativePtr, this.requestPtr, result.getAbsolutePath()); } else { // Other errors this.nativeOnRequestCanceled(this.nativePtr, this.requestPtr); @@ -104,6 +104,6 @@ public void onProgress(long downloaded, long total) { private native void nativeOnRequestStarted(long nativePtr, long requestPtr); private native void nativeOnRequestProgressed(long nativePtr, long requestPtr, float progress); - private native void nativeOnRequestEnded(long nativePtr, long requestPtr); + private native void nativeOnRequestEnded(long nativePtr, long requestPtr, String path); private native void nativeOnRequestCanceled(long nativePtr, long requestPtr); } diff --git a/platform/android/lib/src/main/java/org/readium/sdk/lcp/Service.java b/platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/Service.java similarity index 100% rename from platform/android/lib/src/main/java/org/readium/sdk/lcp/Service.java rename to platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/Service.java diff --git a/platform/android/lib/src/main/java/org/readium/sdk/lcp/StatusDocumentProcessing.java b/platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/StatusDocumentProcessing.java similarity index 100% rename from platform/android/lib/src/main/java/org/readium/sdk/lcp/StatusDocumentProcessing.java rename to platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/StatusDocumentProcessing.java diff --git a/platform/android/lib/src/main/java/org/readium/sdk/lcp/StorageProvider.java b/platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/StorageProvider.java similarity index 100% rename from platform/android/lib/src/main/java/org/readium/sdk/lcp/StorageProvider.java rename to platform/android/lib/src/clientlib/java/org/readium/sdk/lcp/StorageProvider.java diff --git a/platform/android/lcp/src/main/jni/CredentialHandler.cpp b/platform/android/lib/src/contentfilter/cpp/CredentialHandler.cpp similarity index 100% rename from platform/android/lcp/src/main/jni/CredentialHandler.cpp rename to platform/android/lib/src/contentfilter/cpp/CredentialHandler.cpp diff --git a/platform/android/lcp/src/main/jni/CredentialHandler.h b/platform/android/lib/src/contentfilter/cpp/CredentialHandler.h similarity index 100% rename from platform/android/lcp/src/main/jni/CredentialHandler.h rename to platform/android/lib/src/contentfilter/cpp/CredentialHandler.h diff --git a/platform/android/lcp/src/main/jni/ServiceFactory.cpp b/platform/android/lib/src/contentfilter/cpp/ServiceFactory.cpp similarity index 99% rename from platform/android/lcp/src/main/jni/ServiceFactory.cpp rename to platform/android/lib/src/contentfilter/cpp/ServiceFactory.cpp index 5999fb1..9f48b98 100644 --- a/platform/android/lcp/src/main/jni/ServiceFactory.cpp +++ b/platform/android/lib/src/contentfilter/cpp/ServiceFactory.cpp @@ -87,4 +87,4 @@ JNIEXPORT jobject JNICALL Java_org_readium_sdk_lcp_ServiceFactory_nativeBuild( jclass cls = env->FindClass("org/readium/sdk/lcp/Service"); jmethodID methodId = env->GetMethodID(cls, "", "(J)V"); return env->NewObject(cls, methodId, (jlong) service); -} \ No newline at end of file +} diff --git a/platform/android/lcp/src/main/jni/ServiceFactory.h b/platform/android/lib/src/contentfilter/cpp/ServiceFactory.h similarity index 100% rename from platform/android/lcp/src/main/jni/ServiceFactory.h rename to platform/android/lib/src/contentfilter/cpp/ServiceFactory.h diff --git a/platform/android/lcp/src/main/jni/StatusDocumentHandler.cpp b/platform/android/lib/src/contentfilter/cpp/StatusDocumentHandler.cpp similarity index 100% rename from platform/android/lcp/src/main/jni/StatusDocumentHandler.cpp rename to platform/android/lib/src/contentfilter/cpp/StatusDocumentHandler.cpp diff --git a/platform/android/lcp/src/main/jni/StatusDocumentHandler.h b/platform/android/lib/src/contentfilter/cpp/StatusDocumentHandler.h similarity index 100% rename from platform/android/lcp/src/main/jni/StatusDocumentHandler.h rename to platform/android/lib/src/contentfilter/cpp/StatusDocumentHandler.h diff --git a/platform/android/lib/src/main/java/org/readium/sdk/lcp/CredentialHandler.java b/platform/android/lib/src/contentfilter/java/org/readium/sdk/lcp/CredentialHandler.java similarity index 100% rename from platform/android/lib/src/main/java/org/readium/sdk/lcp/CredentialHandler.java rename to platform/android/lib/src/contentfilter/java/org/readium/sdk/lcp/CredentialHandler.java diff --git a/platform/android/lib/src/main/java/org/readium/sdk/lcp/ServiceFactory.java b/platform/android/lib/src/contentfilter/java/org/readium/sdk/lcp/ServiceFactory.java similarity index 100% rename from platform/android/lib/src/main/java/org/readium/sdk/lcp/ServiceFactory.java rename to platform/android/lib/src/contentfilter/java/org/readium/sdk/lcp/ServiceFactory.java diff --git a/platform/android/lib/src/main/java/org/readium/sdk/lcp/StatusDocumentHandler.java b/platform/android/lib/src/contentfilter/java/org/readium/sdk/lcp/StatusDocumentHandler.java similarity index 100% rename from platform/android/lib/src/main/java/org/readium/sdk/lcp/StatusDocumentHandler.java rename to platform/android/lib/src/contentfilter/java/org/readium/sdk/lcp/StatusDocumentHandler.java diff --git a/platform/android/lib/src/main/AndroidManifest.xml b/platform/android/lib/src/main/AndroidManifest.xml index a340258..156d6aa 100644 --- a/platform/android/lib/src/main/AndroidManifest.xml +++ b/platform/android/lib/src/main/AndroidManifest.xml @@ -20,6 +20,8 @@ android:versionCode="1" android:versionName="0.1" > - + diff --git a/platform/android/lib/src/main/java/org/readium/sdk/lcp/NetProvider.java b/platform/android/lib/src/main/java/org/readium/sdk/lcp/NetProvider.java deleted file mode 100644 index 0e6c8c1..0000000 --- a/platform/android/lib/src/main/java/org/readium/sdk/lcp/NetProvider.java +++ /dev/null @@ -1,158 +0,0 @@ -// Licensed to the Readium Foundation under one or more contributor license agreements. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation and/or -// other materials provided with the distribution. -// 3. Neither the name of the organization nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -package org.readium.sdk.lcp; - -import android.content.Context; -import android.net.Uri; -import android.os.AsyncTask; -import android.util.Log; - -import com.koushikdutta.async.future.Future; -import com.koushikdutta.async.future.FutureCallback; -import com.koushikdutta.async.http.AsyncHttpRequest; -import com.koushikdutta.async.http.Headers; -import com.koushikdutta.ion.Ion; -import com.koushikdutta.ion.loader.AsyncHttpRequestFactory; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.util.HashMap; -import java.util.Map; - -public class NetProvider { -//#if !DISABLE_NET_PROVIDER - - private Context context; - private Map> requests; - - /** - * Cancel request asynchronously - */ - private class CancelRequest extends AsyncTask { - @Override - protected Void doInBackground(Long... requestPtrs) { - for (Long requestPtr: requestPtrs) { - Future request = NetProvider.this.requests.get(requestPtr); - request.cancel(); - } - - return null; - } - } - - public NetProvider(Context context) { - this.context = context; - this.requests = new HashMap<>(); - } - - public void download(String url, String dstPath, long requestPtr, long callbackPtr) { - - final NetProviderCallback callback = new NetProviderCallback(callbackPtr, requestPtr); - final String destPath = dstPath; - - if (dstPath == null || dstPath.isEmpty()) { - File outputDir = this.context.getCacheDir(); - File outputFile = null; - try { - outputFile = File.createTempFile("readium_lcp_download", ".tmp", outputDir); - dstPath = outputFile.getAbsolutePath(); - } catch (IOException e) { - e.printStackTrace(); - } - } -// final AsyncHttpRequestFactory current = Ion.getDefault(context).configure().getAsyncHttpRequestFactory(); -// Ion.getDefault(context).configure().setAsyncHttpRequestFactory(new AsyncHttpRequestFactory() { -// @Override -// public AsyncHttpRequest createAsyncHttpRequest(Uri uri, String method, Headers headers) { -// AsyncHttpRequest ret = current.createAsyncHttpRequest(uri, method, headers); -// ret.setTimeout(1000); -// return ret; -// } -// }); - - - Future request = Ion.with(this.context) - .load("GET", url) - .setLogging("Ion", Log.VERBOSE) - .progress(callback) // not UI thread - //.progressHandler(callback) // UI thread - //.setTimeout(AsyncHttpRequest.DEFAULT_TIMEOUT) //30000 - .setTimeout(6000) - //.setHeader(name, value) - - // UI thread - .asInputStream().setCallback(new FutureCallback() { - @Override - public void onCompleted(Exception e, InputStream inputStream) { - if (e != null) { - callback.onCompleted(e, null); - return; - } - if (inputStream == null) { - callback.onCompleted(null, null); - return; - } - File destFile = new File(destPath); - try { - FileOutputStream outputStream = new FileOutputStream(destFile); - //inputStream.transferTo(outputStream); - - byte[] buf = new byte[4096]; - int n; - int total = 0; - while((n = inputStream.read(buf))>0){ - total += n; - outputStream.write(buf, 0, n); - } - outputStream.close(); - inputStream.close(); - callback.onCompleted(null, destFile); - } catch (Exception ex) { - ex.printStackTrace(); - callback.onCompleted(ex, null); - } - } - }) -// .write(new File(dstPath)) -// .setCallback(callback) - ; - - this.requests.put(requestPtr, request); - } - - public void cancel(long requestPtr) { - // Cancel ion request - if (!this.requests.containsKey(requestPtr)) { - return; - } - - new CancelRequest().execute(requestPtr); - } -} diff --git a/platform/android/settings.gradle b/platform/android/settings.gradle new file mode 100644 index 0000000..8c2a2e0 --- /dev/null +++ b/platform/android/settings.gradle @@ -0,0 +1 @@ +include ':lib' diff --git a/platform/apple/LCP Client (iOS).xcconfig b/platform/apple/LCP Client (iOS).xcconfig index cd380af..64e6b2a 100644 --- a/platform/apple/LCP Client (iOS).xcconfig +++ b/platform/apple/LCP Client (iOS).xcconfig @@ -26,4 +26,4 @@ PRODUCT_NAME = LCP-client-iOS -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) ENABLE_NET_PROVIDER_ACQUISITION=1 CRYPTOPP_DISABLE_SSE2=1 CRYPTOPP_DISABLE_ASM=1 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) DISABLE_CRL_=1 ENABLE_NET_PROVIDER_ACQUISITION=1 CRYPTOPP_DISABLE_SSE2=1 CRYPTOPP_DISABLE_ASM=1 diff --git a/platform/apple/LCP Client.xcodeproj/project.pbxproj b/platform/apple/LCP Client.xcodeproj/project.pbxproj index 1219045..f6c011e 100644 --- a/platform/apple/LCP Client.xcodeproj/project.pbxproj +++ b/platform/apple/LCP Client.xcodeproj/project.pbxproj @@ -707,7 +707,7 @@ 5ACE2E031BF21D7900AC0585 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0800; + LastUpgradeCheck = 1010; ORGANIZATIONNAME = Readium; TargetAttributes = { 5ACE2E1A1BF21D8C00AC0585 = { @@ -888,14 +888,22 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -934,14 +942,22 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; diff --git a/platform/apple/src/LCPError.h b/platform/apple/src/LCPError.h index 7fd2aaf..f5ff5d4 100644 --- a/platform/apple/src/LCPError.h +++ b/platform/apple/src/LCPError.h @@ -34,7 +34,9 @@ extern NSString *const LCPErrorExtensionKey; // @see LcpStatus.h for documentation extern NSInteger const LCPErrorCommonNoNetProvider; extern NSInteger const LCPErrorCommonNoStorageProvider; +#if ENABLE_PROFILE_NAMES extern NSInteger const LCPErrorCommonEncryptionProfileNotFound; +#endif //ENABLE_PROFILE_NAMES extern NSInteger const LCPErrorCommonAlgorithmMismatch; extern NSInteger const LCPErrorOpeningLicenseNotValid; extern NSInteger const LCPErrorOpeningLicenseNotStarted; diff --git a/platform/apple/src/LCPLicense.h b/platform/apple/src/LCPLicense.h index b5a4470..b6a7d11 100644 --- a/platform/apple/src/LCPLicense.h +++ b/platform/apple/src/LCPLicense.h @@ -32,15 +32,21 @@ namespace lcp { } #endif - @interface LCPLicense : NSObject @property (readonly, nonatomic) NSString *identifier; @property (readonly, nonatomic) NSString *linkPublication; @property (readonly, nonatomic) BOOL isDecrypted; +@property (readonly, nonatomic) NSString *username; @property (readonly, nonatomic) NSString *userHint; +- (NSString *)originalJSON; +- (NSString *)canonicalJSON; + +- (NSDate *)rightsStart; +- (NSDate *)rightsEnd; + #ifdef __cplusplus @property (readonly, nonatomic) lcp::ILicense *nativeLicense; - (instancetype)initWithLicense:(lcp::ILicense *)nativeLicense NS_DESIGNATED_INITIALIZER; diff --git a/platform/apple/src/LCPLicense.mm b/platform/apple/src/LCPLicense.mm index 8b218bb..a3bb0f4 100644 --- a/platform/apple/src/LCPLicense.mm +++ b/platform/apple/src/LCPLicense.mm @@ -25,11 +25,11 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #import "LCPLicense.h" - #import "ICrypto.h" #import "ILicense.h" - #import "ILinks.h" +#import "IRights.h" +#import "IUser.h" @interface LCPLicense () @property (nonatomic) lcp::ILicense *nativeLicense; @@ -77,9 +77,89 @@ - (BOOL)isDecrypted return _nativeLicense->Decrypted(); } +- (NSString *)username +{ + if (_nativeLicense->User() != NULL) { // _nativeLicense->User()->Name() can be std::string.empty(), but not nil + return [NSString stringWithUTF8String:_nativeLicense->User()->Name().c_str()]; + } + return @""; // no nil return to be consistent with the above potential missing Name() JSON value (empty std::string) +} + - (NSString *)userHint { return [NSString stringWithUTF8String:_nativeLicense->Crypto()->UserKeyHint().c_str()]; } +- (NSString *)originalJSON +{ + return [NSString stringWithUTF8String:_nativeLicense->OriginalContent().c_str()]; +} + +- (NSString *)canonicalJSON +{ + return [NSString stringWithUTF8String:_nativeLicense->CanonicalContent().c_str()]; +} + +- (NSDate *)rightsStart { + std::string start; + // _nativeLicense->Rights()->HasRightValue(lcp::StartRight) + if (_nativeLicense->Rights() != NULL && _nativeLicense->Rights()->GetRightValue(lcp::StartRight, start)) { + NSString *startDateString = [NSString stringWithUTF8String:start.c_str()]; + + NSISO8601DateFormatter *dateFormatter = [[NSISO8601DateFormatter alloc] init]; + NSDate *startDate = [dateFormatter dateFromString:startDateString]; // may be nil + return startDate; + } + return nil; + +// NSData *data = [[self canonicalJSON] dataUsingEncoding:NSUTF8StringEncoding]; +// +// NSError *error; +// NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; +// if (!jsonDictionary) { +// NSLog(@"Failed to parse license JSON: %@", error); +// return nil; +// } +// +// NSDictionary *rights = [jsonDictionary objectForKey:@"rights"]; +// if (rights == nil) { // no need to check for (id)[NSNull null] here (because source data is LCP license JSON) +// return nil; +// } +// NSString *startDateString = [rights objectForKey:@"start"]; +// if (startDateString == nil || [startDateString length] == 0) { // early exit +// return nil; +// } +} + +- (NSDate *)rightsEnd { + std::string end; + // _nativeLicense->Rights()->HasRightValue(lcp::StartRight) + if (_nativeLicense->Rights() != NULL && _nativeLicense->Rights()->GetRightValue(lcp::EndRight, end)) { + NSString *endDateString = [NSString stringWithUTF8String:end.c_str()]; + + NSISO8601DateFormatter *dateFormatter = [[NSISO8601DateFormatter alloc] init]; + NSDate *endDate = [dateFormatter dateFromString:endDateString]; // may be nil + return endDate; + } + return nil; + +// NSData *data = [[self canonicalJSON] dataUsingEncoding:NSUTF8StringEncoding]; +// +// NSError *error; +// NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; +// if (!jsonDictionary) { +// NSLog(@"Failed to parse license JSON: %@", error); +// return nil; +// } +// +// NSDictionary *rights = [jsonDictionary objectForKey:@"rights"]; +// if (rights == nil) { // no need to check for (id)[NSNull null] here (because source data is LCP license JSON) +// return nil; +// } +// NSString *endDateString = [rights objectForKey:@"end"]; +// if (endDateString == nil || [endDateString length] == 0) { // early exit +// return nil; +// } +} + @end diff --git a/platform/apple/src/LCPStatusDocumentProcessing.h b/platform/apple/src/LCPStatusDocumentProcessing.h index 669cc53..8b19b53 100644 --- a/platform/apple/src/LCPStatusDocumentProcessing.h +++ b/platform/apple/src/LCPStatusDocumentProcessing.h @@ -25,6 +25,25 @@ #import +@interface StatusDocumentLink : NSObject { + NSString* rel; + NSString* href; + NSString* type; + BOOL templated; + NSString* title; + NSString* profile; +} + +- (instancetype)init_:(NSString*) rel href:(NSString*) href type:(NSString*) type templated:(BOOL) templated title:(NSString*) title profile:(NSString*) profile; + +@property (nonatomic, readonly) NSString* rel; +@property (nonatomic, readonly) NSString* href; +@property (nonatomic, readonly) NSString* type; +@property (nonatomic, readonly) BOOL templated; +@property (nonatomic, readonly) NSString* title; +@property (nonatomic, readonly) NSString* profile; + +@end @protocol DeviceIdManager @@ -61,11 +80,29 @@ typedef void (^DoneCallback)(bool); -(bool)isInitialized; -(bool)hasLicenseUpdatePending; + +- (NSString *)identifier; +- (NSString *)message; + +-(NSString *)status; -(bool)isActive; --(bool)hasRenewLink; --(bool)hasReturnLink; +-(StatusDocumentLink *)licenseLink; + +-(bool)hasRegisterLink; +-(StatusDocumentLink *)registerLink; + +-(bool)hasRenewLink; +-(StatusDocumentLink *)renewLink; -(void)doRenew:(DoneCallback)doneCallback_doRenew; //void(^)(bool) + +-(bool)hasReturnLink; +-(StatusDocumentLink *)returnLink; -(void)doReturn:(DoneCallback)doneCallback_doReturn; //void(^)(bool) +-(NSDate *)potentialRightsEnd; + +- (NSDate *)statusUpdated; +- (NSDate *)licenseUpdated; + @end diff --git a/platform/apple/src/LCPStatusDocumentProcessing.mm b/platform/apple/src/LCPStatusDocumentProcessing.mm index 3994ce0..4c26757 100644 --- a/platform/apple/src/LCPStatusDocumentProcessing.mm +++ b/platform/apple/src/LCPStatusDocumentProcessing.mm @@ -41,29 +41,6 @@ using namespace lcp; - -@interface StatusDocumentLink : NSObject { - - NSString* rel; - NSString* href; - NSString* type; - BOOL templated; - NSString* title; - NSString* profile; -} - -- (instancetype)init_:(NSString*) rel href:(NSString*) href type:(NSString*) type templated:(BOOL) templated title:(NSString*) title profile:(NSString*) profile; - -@property (nonatomic, readonly) NSString* rel; -@property (nonatomic, readonly) NSString* href; -@property (nonatomic, readonly) NSString* type; -@property (nonatomic, readonly) BOOL templated; -@property (nonatomic, readonly) NSString* title; -@property (nonatomic, readonly) NSString* profile; - -@end - - @interface StatusDocumentLink() @end @@ -111,7 +88,7 @@ @implementation LCPStatusDocumentProcessing { id _deviceIDManager; bool _wasCancelled; - id _statusDocumentProcessingListener; + __weak id _statusDocumentProcessingListener; NSString * _statusDocument_ID; NSString * _statusDocument_STATUS; // ready, active, revoked, returned, cancelled, expired @@ -354,7 +331,6 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task if ([task.taskDescription isEqualToString:TASK_DESCRIPTION_LCP_LSD_FETCH]) { if (error) { - _data_TASK_DESCRIPTION_LCP_LSD_FETCH = nil; NSLog(@"%@", [NSString stringWithFormat:@"HTTP error (TASK_DESCRIPTION_LCP_LSD_FETCH) [%@] => (%li) ... %@ [%li]", [(NSHTTPURLResponse *)task.originalRequest URL], code, error.domain, error.code]); @@ -365,10 +341,19 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task } else if (code < 200 || code >= 300) { + if (_data_TASK_DESCRIPTION_LCP_LSD_FETCH != nil) { + try { + NSString *msg = [[NSString alloc] initWithData:_data_TASK_DESCRIPTION_LCP_LSD_FETCH encoding:NSUTF8StringEncoding]; + NSLog(@"%@", msg); + } + catch (NSException *e) { + NSLog(@"%@", [e reason]); + } + } _data_TASK_DESCRIPTION_LCP_LSD_FETCH = nil; NSLog(@"%@", [NSString stringWithFormat:@"HTTP fail (TASK_DESCRIPTION_LCP_LSD_FETCH) [%@] => (%li)", [(NSHTTPURLResponse *)task.response URL], code]); - + if (!_wasCancelled) { [_statusDocumentProcessingListener onStatusDocumentProcessingComplete:self]; } @@ -427,6 +412,15 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task } else if (code < 200 || code >= 300) { + if (_data_TASK_DESCRIPTION_LCP_LSD_REGISTER != nil) { + try { + NSString *msg = [[NSString alloc] initWithData:_data_TASK_DESCRIPTION_LCP_LSD_REGISTER encoding:NSUTF8StringEncoding]; + NSLog(@"%@", msg); + } + catch (NSException *e) { + NSLog(@"%@", [e reason]); + } + } _data_TASK_DESCRIPTION_LCP_LSD_REGISTER = nil; NSLog(@"%@", [NSString stringWithFormat:@"HTTP fail (TASK_DESCRIPTION_LCP_LSD_REGISTER) [%@] => (%li)", [(NSHTTPURLResponse *)task.response URL], code]); @@ -473,15 +467,24 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task _data_TASK_DESCRIPTION_LCP_FETCH = nil; - NSLog(@"%@", [NSString stringWithFormat:@"HTTP error (TASK_DESCRIPTION_LCP_LSD_FETCH) [%@] => (%li) ... %@ [%li]", [(NSHTTPURLResponse *)task.originalRequest URL], code, error.domain, error.code]); + NSLog(@"%@", [NSString stringWithFormat:@"HTTP error (TASK_DESCRIPTION_LCP_FETCH) [%@] => (%li) ... %@ [%li]", [(NSHTTPURLResponse *)task.originalRequest URL], code, error.domain, error.code]); _doneCallback_fetchAndInjectUpdatedLicense(false); } else if (code < 200 || code >= 300) { + if (_data_TASK_DESCRIPTION_LCP_FETCH != nil) { + try { + NSString *msg = [[NSString alloc] initWithData:_data_TASK_DESCRIPTION_LCP_FETCH encoding:NSUTF8StringEncoding]; + NSLog(@"%@", msg); + } + catch (NSException *e) { + NSLog(@"%@", [e reason]); + } + } _data_TASK_DESCRIPTION_LCP_FETCH = nil; - NSLog(@"%@", [NSString stringWithFormat:@"HTTP fail (TASK_DESCRIPTION_LCP_LSD_FETCH) [%@] => (%li)", [(NSHTTPURLResponse *)task.response URL], code]); + NSLog(@"%@", [NSString stringWithFormat:@"HTTP fail (TASK_DESCRIPTION_LCP_FETCH) [%@] => (%li)", [(NSHTTPURLResponse *)task.response URL], code]); _doneCallback_fetchAndInjectUpdatedLicense(false); @@ -533,6 +536,15 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task } else if (code < 200 || code >= 300) { + if (_data_TASK_DESCRIPTION_LCP_LSD_RENEW != nil) { + try { + NSString *msg = [[NSString alloc] initWithData:_data_TASK_DESCRIPTION_LCP_LSD_RENEW encoding:NSUTF8StringEncoding]; + NSLog(@"%@", msg); + } + catch (NSException *e) { + NSLog(@"%@", [e reason]); + } + } _data_TASK_DESCRIPTION_LCP_LSD_RENEW = nil; NSLog(@"%@", [NSString stringWithFormat:@"HTTP fail (TASK_DESCRIPTION_LCP_LSD_RENEW) [%@] => (%li)", [(NSHTTPURLResponse *)task.response URL], code]); @@ -540,8 +552,16 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task _doneCallback_doRenew(false); } else { - try { + if (_data_TASK_DESCRIPTION_LCP_LSD_RENEW != nil) { + try { + NSString *msg = [[NSString alloc] initWithData:_data_TASK_DESCRIPTION_LCP_LSD_RENEW encoding:NSUTF8StringEncoding]; + NSLog(@"%@", msg); + } + catch (NSException *e) { + NSLog(@"%@", [e reason]); + } + } _data_TASK_DESCRIPTION_LCP_LSD_RENEW = nil; // forces re-check of LSD, now with updated LCP timestamp @@ -583,6 +603,15 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task } else if (code < 200 || code >= 300) { + if (_data_TASK_DESCRIPTION_LCP_LSD_RETURN != nil) { + try { + NSString *msg = [[NSString alloc] initWithData:_data_TASK_DESCRIPTION_LCP_LSD_RETURN encoding:NSUTF8StringEncoding]; + NSLog(@"%@", msg); + } + catch (NSException *e) { + NSLog(@"%@", [e reason]); + } + } _data_TASK_DESCRIPTION_LCP_LSD_RETURN = nil; NSLog(@"%@", [NSString stringWithFormat:@"HTTP fail (TASK_DESCRIPTION_LCP_LSD_RETURN) [%@] => (%li)", [(NSHTTPURLResponse *)task.response URL], code]); @@ -592,6 +621,15 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task } else { try { + if (_data_TASK_DESCRIPTION_LCP_LSD_RETURN != nil) { + try { + NSString *msg = [[NSString alloc] initWithData:_data_TASK_DESCRIPTION_LCP_LSD_RETURN encoding:NSUTF8StringEncoding]; + NSLog(@"%@", msg); + } + catch (NSException *e) { + NSLog(@"%@", [e reason]); + } + } _data_TASK_DESCRIPTION_LCP_LSD_RETURN = nil; // forces re-check of LSD, now with updated LCP timestamp @@ -676,7 +714,6 @@ - (bool)parseStatusDocumentJson:(NSString*)json } NSDictionary *updatedJsonDict = [rootJsonDict valueForKey:@"updated"]; - strTemp = [updatedJsonDict valueForKey:@"license"]; if (strTemp != nil) { _statusDocument_UPDATED_LICENSE = strTemp; @@ -706,7 +743,7 @@ - (bool)parseStatusDocumentJson:(NSString*)json templated = YES; } } else if ([templated_ isKindOfClass:[NSNumber class]]) { - if (((NSNumber*)templated_) > 0) { + if ([((NSNumber*)templated_) integerValue] > 0) { templated = YES; } } @@ -778,7 +815,7 @@ -(bool)isInitialized { } -(bool)hasLicenseUpdatePending { - if (_statusDocument_UPDATED_LICENSE == nil) { + if (_statusDocument_UPDATED_LICENSE == nil || [_statusDocument_UPDATED_LICENSE length] == 0) { return false; } @@ -961,7 +998,6 @@ -(void)fetchAndInjectUpdatedLicense:(DoneCallback)doneCallback_fetchAndInjectUpd [task resume]; } - -(void)doRenew:(DoneCallback)doneCallback_doRenew //void(^)(bool) { if (_statusDocument_LINK_RENEW == nil) { @@ -988,7 +1024,6 @@ -(void)doRenew:(DoneCallback)doneCallback_doRenew //void(^)(bool) NSURL *url = [NSURL URLWithString:urlString]; - NSURLSessionConfiguration *config = [NSURLSessionConfiguration ephemeralSessionConfiguration]; NSString * locale = [[NSLocale preferredLanguages] objectAtIndex:0]; @@ -1073,18 +1108,67 @@ -(void)doReturn:(DoneCallback)doneCallback_doReturn //void(^)(bool) [task resume]; } +- (NSString *)identifier { + return _statusDocument_ID; +} +- (NSString *)message { + return _statusDocument_MESSAGE; +} + +- (NSString *)status { + return _statusDocument_STATUS; +} -(bool)isActive { return (_statusDocument_STATUS != nil && [_statusDocument_STATUS isEqualToString:@"active"]); } --(bool)hasRenewLink { +- (NSDate *)statusUpdated { + if (_statusDocument_UPDATED_STATUS != nil && [_statusDocument_UPDATED_STATUS length] > 0) { + NSISO8601DateFormatter *dateFormatter = [[NSISO8601DateFormatter alloc] init]; + return [dateFormatter dateFromString:_statusDocument_UPDATED_STATUS]; // can be nil + } + return nil; +} +- (NSDate *)licenseUpdated { + if (_statusDocument_UPDATED_LICENSE != nil && [_statusDocument_UPDATED_LICENSE length] > 0) { + NSISO8601DateFormatter *dateFormatter = [[NSISO8601DateFormatter alloc] init]; + return [dateFormatter dateFromString:_statusDocument_UPDATED_LICENSE]; // can be nil + } + return nil; +} +- (NSDate *)potentialRightsEnd { + if (_statusDocument_POTENTIAL_RIGHTS_END != nil && [_statusDocument_POTENTIAL_RIGHTS_END length] > 0) { + NSISO8601DateFormatter *dateFormatter = [[NSISO8601DateFormatter alloc] init]; + return [dateFormatter dateFromString:_statusDocument_POTENTIAL_RIGHTS_END]; // can be nil + } + return nil; +} + +- (StatusDocumentLink *)licenseLink { + return _statusDocument_LINK_LICENSE; +} + +- (bool)hasRegisterLink { + return (_statusDocument_LINK_REGISTER != nil); +} +- (StatusDocumentLink *)registerLink { + return _statusDocument_LINK_REGISTER; +} + +- (bool)hasRenewLink { return (_statusDocument_LINK_RENEW != nil); } +- (StatusDocumentLink *)renewLink { + return _statusDocument_LINK_RENEW; +} --(bool)hasReturnLink { +- (bool)hasReturnLink { return (_statusDocument_LINK_RETURN != nil); } +- (StatusDocumentLink *)returnLink { + return _statusDocument_LINK_RETURN; +} @end @@ -1102,3 +1186,4 @@ -(bool)hasReturnLink { // }); // }); +// NSLog(@"%s", __PRETTY_FUNCTION__); diff --git a/platform/cross-platform/README.md b/platform/cross-platform/README.md new file mode 100644 index 0000000..74de9d3 --- /dev/null +++ b/platform/cross-platform/README.md @@ -0,0 +1,22 @@ +# Cross platform compilation + +## Bootstrap + +``` +python bootstrap.py +``` + +## Compile + +``` +python build.py +``` + +This build generates static libraries in out/Default/obj directory: + +* liblcp_client.a +* liblcp_content_filter.a +* libbzip2.a +* libzlib.a +* libcryptopp.a +* libtime64.a diff --git a/platform/cross-platform/bootstrap.py b/platform/cross-platform/bootstrap.py new file mode 100644 index 0000000..06b4ce8 --- /dev/null +++ b/platform/cross-platform/bootstrap.py @@ -0,0 +1,76 @@ +#!/usr/bin/python +import os +import shutil +import platform +import utils +import urllib +import zipfile +import tarfile +import tempfile +import subprocess + +# Other variables +SYSTEM = platform.system().lower() + +if SYSTEM == "darwin": + SYSTEM = "mac" + +# Install gyp +def install_gyp(): + if os.path.exists(os.path.join("vendor", "gyp")): + return + + print "Clone gyp" + utils.execute_command(["git", "clone", "https://chromium.googlesource.com/external/gyp.git", "vendor/gyp"]) + +# Install ninja +def install_ninja(): + if not os.path.exists(os.path.join("vendor", "ninja")): + print "Clone ninja" + utils.execute_command(["git", "clone", "https://github.com/ninja-build/ninja.git", "vendor/ninja"]) + + # Configure and build ninja + if SYSTEM == "windows": + cmd_path = (os.path.join("vendor", "ninja", "ninja.exe")) + else: + cmd_path = (os.path.join("vendor", "ninja", "ninja")) + + if not os.path.exists(cmd_path): + print "Build and install ninja" + + # Initialize visual studio environment variables + cmd = ["python", "configure.py", "--bootstrap"] + + if SYSTEM == "windows": + cmd = ["vcvarsall.bat", "&&"] + cmd + + utils.execute_command(cmd, os.path.join("vendor", "ninja")) + +# Apply patches +def apply_patches(): + patch_file_path = os.path.abspath(os.path.join("patches", "%s.diff" % SYSTEM)) + + if not os.path.exists(patch_file_path): + return + + print "Apply patches" + cmd = ["git", "apply"] + + # Add options for windows to manage spaces + if SYSTEM == "windows": + cmd += ["--ignore-space-change", "--ignore-whitespace"] + + cmd += [patch_file_path] + + utils.execute_command(cmd, os.path.join("..", "..")) + +# Download and install vendors +if not os.path.exists("vendor"): + os.mkdir("vendor") + +install_gyp() +install_ninja() + +# Apply patches +apply_patches() + diff --git a/platform/cross-platform/build.py b/platform/cross-platform/build.py new file mode 100644 index 0000000..9316a49 --- /dev/null +++ b/platform/cross-platform/build.py @@ -0,0 +1,45 @@ +#!/usr/bin/python +import os +import subprocess +import platform +import utils + +SYSTEM = platform.system().lower() + +if SYSTEM == "linux": + # Use clang on linux + # print "Use clang compiler" + # os.environ["CC"] = "clang" + # os.environ["CXX"] = "clang++" + # os.environ["GYP_DEFINES"] = "clang=1" + GYP_OS = "linux" +elif SYSTEM == "windows": + # Use msvs version 2015 + print "Use msvs version 2015" + os.environ["GYP_MSVS_VERSION"] = "2015" + GYP_OS = "win" +elif SYSTEM == "darwin": + GYP_OS = "mac" + +# Directories variables +PPAPI_PATH = os.path.abspath(os.getcwd()) +GYP_CMD = os.path.join(PPAPI_PATH, "vendor", "gyp", "gyp_main.py") +NINJA_PATH = os.path.join(PPAPI_PATH, "vendor", "ninja") + +if SYSTEM == "windows": + NINJA_CMD = os.path.join(NINJA_PATH, "ninja.exe") +else: + NINJA_CMD = os.path.join(NINJA_PATH, "ninja") + +# Create ninja build file +print "Create ninja project" +utils.execute_command(["python", GYP_CMD, "--depth=.", "-f", "ninja", "-DOS=%s" % GYP_OS, "lcp.gyp"]) + +# Build ninja project +print "Build ninja project" +cmd = [NINJA_CMD, "-C", os.path.join("out", "Default"), "-f", "build.ninja"] + +if SYSTEM == "windows": + cmd = ["vcvarsall.bat", "&&"] + cmd + +utils.execute_command(cmd) \ No newline at end of file diff --git a/platform/cross-platform/filenames.gypi b/platform/cross-platform/filenames.gypi new file mode 100644 index 0000000..0298447 --- /dev/null +++ b/platform/cross-platform/filenames.gypi @@ -0,0 +1,219 @@ +{ + 'variables': { + 'root_dir': '../../src', + 'third_party_dir': '<(root_dir)/third-parties', + 'lcp_content_filter_dir': '<(root_dir)/lcp-content-filter', + 'lcp_client_lib_dir': '<(root_dir)/lcp-client-lib', + 'cryptopp_dir': '<(third_party_dir)/cryptopp', + 'zip_lib_dir': '<(third_party_dir)/ziplib/Source/ZipLib', + 'zlib_dir': '<(zip_lib_dir)/extlibs/zlib', + 'bzip2_dir': '<(zip_lib_dir)/extlibs/bzip2', + 'time64_dir': '<(third_party_dir)/time64', + 'zlib_sources': [ + '<(zlib_dir)/compress.c', + '<(zlib_dir)/zutil.c', + '<(zlib_dir)/trees.c', + '<(zlib_dir)/inftrees.c', + '<(zlib_dir)/inffast.c', + '<(zlib_dir)/crc32.c', + '<(zlib_dir)/inflate.c', + '<(zlib_dir)/uncompr.c', + '<(zlib_dir)/adler32.c', + '<(zlib_dir)/infback.c', + '<(zlib_dir)/deflate.c' + ], + 'bzip2_sources': [ + '<(bzip2_dir)/blocksort.c', + '<(bzip2_dir)/bzerror.c', + '<(bzip2_dir)/bzlib.c', + '<(bzip2_dir)/compress.c', + '<(bzip2_dir)/crctable.c', + '<(bzip2_dir)/decompress.c', + '<(bzip2_dir)/huffman.c', + '<(bzip2_dir)/randtable.c', + ], + 'zip_lib_sources': [ + '<(zip_lib_dir)/detail/EndOfCentralDirectoryBlock.cpp', + '<(zip_lib_dir)/detail/ZipCentralDirectoryFileHeader.cpp', + '<(zip_lib_dir)/detail/ZipGenericExtraField.cpp', + '<(zip_lib_dir)/detail/ZipLocalFileHeader.cpp', + '<(zip_lib_dir)/ZipArchive.cpp', + '<(zip_lib_dir)/ZipArchiveEntry.cpp', + '<(zip_lib_dir)/ZipFile.cpp' + ], + 'time64_sources': [ + '<(time64_dir)/time64.c' + ], + 'cryptopp_sources': [ + '<(cryptopp_dir)/3way.cpp', + '<(cryptopp_dir)/adhoc.cpp', + '<(cryptopp_dir)/adler32.cpp', + '<(cryptopp_dir)/algebra.cpp', + '<(cryptopp_dir)/algparam.cpp', + '<(cryptopp_dir)/arc4.cpp', + '<(cryptopp_dir)/asn.cpp', + '<(cryptopp_dir)/authenc.cpp', + '<(cryptopp_dir)/base32.cpp', + '<(cryptopp_dir)/base64.cpp', + '<(cryptopp_dir)/basecode.cpp', + '<(cryptopp_dir)/bench2.cpp', + '<(cryptopp_dir)/bench.cpp', + '<(cryptopp_dir)/bfinit.cpp', + '<(cryptopp_dir)/blowfish.cpp', + '<(cryptopp_dir)/blumshub.cpp', + '<(cryptopp_dir)/camellia.cpp', + '<(cryptopp_dir)/cast.cpp', + '<(cryptopp_dir)/casts.cpp', + '<(cryptopp_dir)/cbcmac.cpp', + '<(cryptopp_dir)/ccm.cpp', + '<(cryptopp_dir)/channels.cpp', + '<(cryptopp_dir)/cmac.cpp', + '<(cryptopp_dir)/cpu.cpp', + '<(cryptopp_dir)/crc.cpp', + '<(cryptopp_dir)/cryptlib_bds.cpp', + '<(cryptopp_dir)/cryptlib.cpp', + '<(cryptopp_dir)/datatest.cpp', + '<(cryptopp_dir)/default.cpp', + '<(cryptopp_dir)/des.cpp', + '<(cryptopp_dir)/dessp.cpp', + '<(cryptopp_dir)/dh2.cpp', + '<(cryptopp_dir)/dh.cpp', + '<(cryptopp_dir)/dll.cpp', + '<(cryptopp_dir)/dlltest.cpp', + '<(cryptopp_dir)/dsa.cpp', + '<(cryptopp_dir)/eax.cpp', + '<(cryptopp_dir)/ec2n.cpp', + '<(cryptopp_dir)/eccrypto.cpp', + '<(cryptopp_dir)/ecp.cpp', + '<(cryptopp_dir)/elgamal.cpp', + '<(cryptopp_dir)/emsa2.cpp', + '<(cryptopp_dir)/eprecomp.cpp', + '<(cryptopp_dir)/esign.cpp', + '<(cryptopp_dir)/files.cpp', + '<(cryptopp_dir)/filters.cpp', + '<(cryptopp_dir)/fips140.cpp', + '<(cryptopp_dir)/fipsalgt.cpp', + '<(cryptopp_dir)/fipstest.cpp', + '<(cryptopp_dir)/gcm.cpp', + '<(cryptopp_dir)/gf2_32.cpp', + '<(cryptopp_dir)/gf256.cpp', + '<(cryptopp_dir)/gf2n.cpp', + '<(cryptopp_dir)/gfpcrypt.cpp', + '<(cryptopp_dir)/gost.cpp', + '<(cryptopp_dir)/gzip.cpp', + '<(cryptopp_dir)/hex.cpp', + '<(cryptopp_dir)/hmac.cpp', + '<(cryptopp_dir)/hrtimer.cpp', + '<(cryptopp_dir)/ida.cpp', + '<(cryptopp_dir)/idea.cpp', + '<(cryptopp_dir)/integer.cpp', + '<(cryptopp_dir)/iterhash.cpp', + '<(cryptopp_dir)/luc.cpp', + '<(cryptopp_dir)/mars.cpp', + '<(cryptopp_dir)/marss.cpp', + '<(cryptopp_dir)/md2.cpp', + '<(cryptopp_dir)/md4.cpp', + '<(cryptopp_dir)/md5.cpp', + '<(cryptopp_dir)/misc.cpp', + '<(cryptopp_dir)/modes.cpp', + '<(cryptopp_dir)/mqueue.cpp', + '<(cryptopp_dir)/mqv.cpp', + '<(cryptopp_dir)/nbtheory.cpp', + '<(cryptopp_dir)/network.cpp', + '<(cryptopp_dir)/oaep.cpp', + '<(cryptopp_dir)/osrng.cpp', + '<(cryptopp_dir)/panama.cpp', + '<(cryptopp_dir)/pch.cpp', + '<(cryptopp_dir)/pkcspad.cpp', + '<(cryptopp_dir)/polynomi.cpp', + '<(cryptopp_dir)/pssr.cpp', + '<(cryptopp_dir)/pubkey.cpp', + '<(cryptopp_dir)/queue.cpp', + '<(cryptopp_dir)/rabin.cpp', + '<(cryptopp_dir)/randpool.cpp', + '<(cryptopp_dir)/rc2.cpp', + '<(cryptopp_dir)/rc5.cpp', + '<(cryptopp_dir)/rc6.cpp', + '<(cryptopp_dir)/rdtables.cpp', + '<(cryptopp_dir)/regtest.cpp', + '<(cryptopp_dir)/rijndael.cpp', + '<(cryptopp_dir)/ripemd.cpp', + '<(cryptopp_dir)/rng.cpp', + '<(cryptopp_dir)/rsa.cpp', + '<(cryptopp_dir)/rw.cpp', + '<(cryptopp_dir)/safer.cpp', + '<(cryptopp_dir)/salsa.cpp', + '<(cryptopp_dir)/seal.cpp', + '<(cryptopp_dir)/seed.cpp', + '<(cryptopp_dir)/serpent.cpp', + '<(cryptopp_dir)/sha3.cpp', + '<(cryptopp_dir)/shacal2.cpp', + '<(cryptopp_dir)/sha.cpp', + '<(cryptopp_dir)/sharkbox.cpp', + '<(cryptopp_dir)/shark.cpp', + '<(cryptopp_dir)/simple.cpp', + '<(cryptopp_dir)/skipjack.cpp', + '<(cryptopp_dir)/socketft.cpp', + '<(cryptopp_dir)/sosemanuk.cpp', + '<(cryptopp_dir)/square.cpp', + '<(cryptopp_dir)/squaretb.cpp', + '<(cryptopp_dir)/strciphr.cpp', + '<(cryptopp_dir)/tea.cpp', + '<(cryptopp_dir)/test.cpp', + '<(cryptopp_dir)/tftables.cpp', + '<(cryptopp_dir)/tiger.cpp', + '<(cryptopp_dir)/tigertab.cpp', + '<(cryptopp_dir)/trdlocal.cpp', + '<(cryptopp_dir)/ttmac.cpp', + '<(cryptopp_dir)/twofish.cpp', + '<(cryptopp_dir)/validat1.cpp', + '<(cryptopp_dir)/validat2.cpp', + '<(cryptopp_dir)/validat3.cpp', + '<(cryptopp_dir)/vmac.cpp', + '<(cryptopp_dir)/wait.cpp', + '<(cryptopp_dir)/wake.cpp', + '<(cryptopp_dir)/whrlpool.cpp', + '<(cryptopp_dir)/winpipes.cpp', + '<(cryptopp_dir)/xtr.cpp', + '<(cryptopp_dir)/xtrcrypt.cpp', + '<(cryptopp_dir)/zdeflate.cpp', + '<(cryptopp_dir)/zinflate.cpp', + '<(cryptopp_dir)/zlib.cpp' + ], + 'lcp_client_lib_sources': [ + '<(lcp_client_lib_dir)/Acquisition.cpp', + '<(lcp_client_lib_dir)/AesCbcSymmetricAlgorithm.cpp', + '<(lcp_client_lib_dir)/AlgorithmNames.cpp', + '<(lcp_client_lib_dir)/Certificate.cpp', + '<(lcp_client_lib_dir)/CertificateExtension.cpp', + '<(lcp_client_lib_dir)/CertificateRevocationList.cpp', + '<(lcp_client_lib_dir)/CrlDistributionPoints.cpp', + '<(lcp_client_lib_dir)/CrlUpdater.cpp', + '<(lcp_client_lib_dir)/CryptoLcpNode.cpp', + '<(lcp_client_lib_dir)/CryptoppCryptoProvider.cpp', + '<(lcp_client_lib_dir)/CryptoppUtils.cpp', + '<(lcp_client_lib_dir)/DateTime.cpp', + '<(lcp_client_lib_dir)/EncryptionProfileNames.cpp', + '<(lcp_client_lib_dir)/EncryptionProfilesManager.cpp', + '<(lcp_client_lib_dir)/JsonCanonicalizer.cpp', + '<(lcp_client_lib_dir)/JsonValueReader.cpp', + '<(lcp_client_lib_dir)/Lcp1dot0EncryptionProfile.cpp', + '<(lcp_client_lib_dir)/LcpService.cpp', + '<(lcp_client_lib_dir)/LcpServiceCreator.cpp', + '<(lcp_client_lib_dir)/LcpUtils.cpp', + '<(lcp_client_lib_dir)/LinksLcpNode.cpp', + '<(lcp_client_lib_dir)/RightsLcpNode.cpp', + '<(lcp_client_lib_dir)/RightsService.cpp', + '<(lcp_client_lib_dir)/RootLcpNode.cpp', + '<(lcp_client_lib_dir)/RsaSha256SignatureAlgorithm.cpp', + '<(lcp_client_lib_dir)/Sha256HashAlgorithm.cpp', + '<(lcp_client_lib_dir)/SymmetricAlgorithmEncryptedStream.cpp', + '<(lcp_client_lib_dir)/ThreadTimer.cpp', + '<(lcp_client_lib_dir)/UserLcpNode.cpp' + ], + 'lcp_content_filter_sources': [ + '<(lcp_content_filter_dir)/LcpContentFilter.cpp', + '<(lcp_content_filter_dir)/LcpContentModule.cpp' + ] + } +} diff --git a/platform/cross-platform/lcp.gyp b/platform/cross-platform/lcp.gyp new file mode 100644 index 0000000..13aba20 --- /dev/null +++ b/platform/cross-platform/lcp.gyp @@ -0,0 +1,215 @@ +{ + 'includes': [ + 'filenames.gypi' + ], + 'variables': { + + }, + 'target_defaults': { + 'include_dirs': [ + + ], + 'cflags': [ + '-w', + '-fPIC', + '-fvisibility=hidden', + '-g', # Debug mode + ], + 'defines': [ + 'BUILDING_EPUB3' + ] + }, + 'targets': [ + { + 'target_name': 'lcp_content_filter', + 'type': 'static_library', + 'cflags_cc': [ + '-std=c++11' + ], + 'sources': [ + '<@(lcp_content_filter_sources)' + ] + }, + { + 'target_name': 'lcp_client_lib', + 'type': 'static_library', + 'dependencies': [ + 'cryptopp', + 'zip_lib', + 'time64' + ], + 'include_dirs': [ + '<(third_party_dir)' + ], + 'cflags_cc': [ + '-std=c++11', + '-frtti', + '-fexceptions', + ], + 'sources': [ + '<@(lcp_client_lib_sources)' + ] + }, + { + 'target_name': 'cryptopp', + 'type': 'static_library', + 'cflags_cc': [ + '-std=c++11', + '-fpermissive', + '-frtti', + '-fexceptions', + ], + 'sources': [ + '<@(cryptopp_sources)' + ] + }, + { + 'target_name': 'zip_lib', + 'type': 'static_library', + 'dependencies': [ + 'zlib', + 'bzip2' + ], + 'cflags_cc': [ + '-std=c++11', + '-fpermissive', + '-frtti', + '-fexceptions', + ], + 'sources': [ + '<@(zip_lib_sources)' + ] + }, + { + 'target_name': 'zlib', + 'type': 'static_library', + 'sources': [ + '<@(zlib_sources)' + ] + }, + { + 'target_name': 'bzip2', + 'type': 'static_library', + 'sources': [ + '<@(bzip2_sources)' + ] + }, + { + 'target_name': 'time64', + 'type': 'static_library', + 'sources': [ + '<@(time64_sources)' + ] + } + ], + 'conditions': [ + ['OS=="mac"', { + 'target_defaults': { + 'defines': [ + 'LIBXML_THREAD_ENABLED', + 'CRYPTOPP_DISABLE_ASM', + 'ZLIB_ONLY' + ], + 'cflags_cc': [ + #'-std=c++0x', + #'-stdlib=libc++', + #'-Wtautological-pointer-compare', + #'-Wc++11-extensions' + ], + 'xcode_settings': { + 'GCC_TREAT_WARNINGS_AS_ERRORS': 'NO', + #'MACOSX_DEPLOYMENT_TARGET': '10.8', + 'CLANG_CXX_LANGUAGE_STANDARD': 'gnu++0x', + 'CLANG_CXX_LIBRARY': 'libc++', + 'WARNING_CFLAGS': [ + '-Wno-unknown-warning-option', + '-Wno-parentheses-equality', + '-Wno-unused-function', + '-Wno-sometimes-uninitialized', + '-Wno-pointer-sign', + '-Wno-sign-compare', + '-Wno-string-plus-int', + '-Wno-unused-variable', + '-Wno-deprecated-declarations', + '-Wno-return-type', + '-Wno-gnu-folding-constant', + '-Wno-shift-negative-value', + '-Wno-tautological-pointer-compare', + '-Wno-inconsistent-missing-override', + '-Wno-empty-body', + '-Wno-uninitialized', + '-Wno-potentially-evaluated-expression' + ] + }, + 'ldflags': [ + + ], + 'link_settings': { + 'libraries': [ + + ] + } + } + }], + ['OS=="linux"', { + 'target_defaults': { + 'defines': [ + #'LIBXML_THREAD_ENABLED', + #'_GLIBCXX_USE_CXX11_ABI=0' # to avoid std::locale issue + ], + 'cflags': [ + '-m64', + '-march=x86-64', + ], + 'cflags_cc': [ + ], + 'ldflags': [ + '-m64', + ], + 'link_settings': { + 'libraries': [ + + ] + } + } + }], + ['OS=="win"', { + 'variables': { + }, + 'target_defaults': { + 'defines': [ + 'MSVS_VERSION_2015', + 'NDEBUG', + 'NOMINMAX', + 'WIN32' + ], + 'msvs_disabled_warnings': [ + 4530, + 4577, + 4028, + 4090 + ], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'WarnAsError': 'false', + }, + }, + 'cflags': [ + '/EHsc' + ], + 'cflags_cc': [ + # '-std=c++11', + # '-fpermissive' + ], + 'include_dirs': [ + ], + 'link_settings': { + 'library_dirs': [ + ], + 'libraries': [ + ] + } + } + }], + ] +} diff --git a/platform/cross-platform/utils.py b/platform/cross-platform/utils.py new file mode 100644 index 0000000..b8e87da --- /dev/null +++ b/platform/cross-platform/utils.py @@ -0,0 +1,12 @@ +import subprocess +import os.path + +# Helper to execute command +def execute_command(cmd, cwd=None): + cwd_abs_path = None + + if cwd is not None: + cwd_abs_path = os.path.abspath(cwd) + + p = subprocess.Popen(cmd, cwd=cwd_abs_path) + p.wait() \ No newline at end of file diff --git a/src/lcp-client-lib/Certificate.cpp b/src/lcp-client-lib/Certificate.cpp index 8af23da..f9b2a07 100644 --- a/src/lcp-client-lib/Certificate.cpp +++ b/src/lcp-client-lib/Certificate.cpp @@ -58,7 +58,6 @@ DEFINE_OID(ASN1::joint_iso_ccitt() + 5, joint_iso_ccitt_ds); DEFINE_OID(joint_iso_ccitt_ds() + 29, id_ce); DEFINE_OID(id_ce() + 31, id_ce_CRLDistributionPoints); - namespace lcp { Certificate::Certificate( @@ -74,7 +73,7 @@ namespace lcp certData.Put(rawDecodedCert.data(), rawDecodedCert.size()); certData.MessageEnd(); - ByteQueue subjectPublicKey; + ByteQueue subjectPublicKey; //CryptoPP::BufferedTransformation BERSequenceDecoder cert(certData); { @@ -98,13 +97,21 @@ namespace lcp // subject CryptoppUtils::Cert::SkipNextSequence(toBeSignedCert); + //subjectPublicKey (RSA or ECDSA) //CryptoppUtils::Cert::ReadSubjectPublicKey(toBeSignedCert, m_publicKeyRSA); - BERSequenceDecoder subjPublicInfoFrom(toBeSignedCert); - DERSequenceEncoder subjPublicInfoOut(subjectPublicKey); - subjPublicInfoFrom.TransferTo(subjPublicInfoOut, subjPublicInfoFrom.RemainingLength()); - subjPublicInfoOut.MessageEnd(); - subjPublicInfoFrom.MessageEnd(); + // subjectPublicKeyInfo + BERSequenceDecoder spki(toBeSignedCert); + DERSequenceEncoder spkiEncoder(subjectPublicKey); + spki.CopyTo(spkiEncoder); + spkiEncoder.MessageEnd(); + spki.SkipAll(); + // ----- EQUIVALENT: +// BERSequenceDecoder subjPublicInfoFrom(toBeSignedCert); +// DERSequenceEncoder subjPublicInfoOut(subjectPublicKey); +// subjPublicInfoFrom.TransferTo(subjPublicInfoOut, subjPublicInfoFrom.RemainingLength()); +// subjPublicInfoOut.MessageEnd(); +// subjPublicInfoFrom.MessageEnd(); while (!toBeSignedCert.EndReached()) @@ -157,60 +164,67 @@ namespace lcp algo = AlgorithmNames::RsaMd5Id; } - if (algo == AlgorithmNames::EcdsaSha256Id) { - m_publicKeyECDSA.BERDecode(subjectPublicKey); - } else { - m_publicKeyRSA.BERDecode(subjectPublicKey); - } +// m_publicKeyQueue = subjectPublicKey; - //this->PublicKey() - ByteQueue publicKeyQueue; - if (algo == AlgorithmNames::EcdsaSha256Id) { - m_publicKeyECDSA.DEREncode(publicKeyQueue); - } else { - m_publicKeyRSA.DEREncode(publicKeyQueue); - } - size_t size = static_cast(publicKeyQueue.MaxRetrievable()); +// if (algo == AlgorithmNames::EcdsaSha256Id) { +// m_publicKeyECDSA.BERDecode(subjectPublicKey); +// } else { +// m_publicKeyRSA.BERDecode(subjectPublicKey); +// } +// +// //this->PublicKey() +// ByteQueue publicKeyQueue; +// if (algo == AlgorithmNames::EcdsaSha256Id) { +// m_publicKeyECDSA.DEREncode(publicKeyQueue); +// } else { +// m_publicKeyRSA.DEREncode(publicKeyQueue); +// } + + size_t size = static_cast(subjectPublicKey.MaxRetrievable()); KeyType outKey(size); - publicKeyQueue.Get(&outKey.at(0), outKey.size()); + subjectPublicKey.Get(&outKey.at(0), outKey.size()); + m_publicKeyType = outKey; - m_signatureAlgorithm.reset(m_encryptionProfile->CreateSignatureAlgorithm(outKey, algo)); + m_signatureAlgorithm.reset(m_encryptionProfile->CreateSignatureAlgorithm(m_publicKeyType, algo)); } KeyType Certificate::PublicKey() const { - ByteQueue publicKeyQueue; - if (m_signatureAlgorithm->Name() == AlgorithmNames::EcdsaSha256Id) { - m_publicKeyECDSA.DEREncode(publicKeyQueue); - } else { - m_publicKeyRSA.DEREncode(publicKeyQueue); - } - - size_t size = static_cast(publicKeyQueue.MaxRetrievable()); - KeyType outKey(size); - publicKeyQueue.Get(&outKey.at(0), outKey.size()); - return outKey; - } - - bool Certificate::VerifyMessage(const std::string & message, const std::string & hashBase64) - { - return m_signatureAlgorithm->VerifySignature(message, hashBase64); + return m_publicKeyType; + +// ByteQueue publicKeyQueue; +// if (m_signatureAlgorithm->Name() == AlgorithmNames::EcdsaSha256Id) { +// m_publicKeyECDSA.DEREncode(publicKeyQueue); +// } else { +// m_publicKeyRSA.DEREncode(publicKeyQueue); +// } +// +// ByteQueue publicKeyQueue = m_publicKeyQueue; +// size_t size = static_cast(publicKeyQueue.MaxRetrievable()); +// KeyType outKey(size); +// publicKeyQueue.Get(&outKey.at(0), outKey.size()); +// return outKey; } - bool Certificate::VerifyMessage( - const unsigned char * message, - size_t messageLength, - const unsigned char * signature, - size_t signatureLength - ) - { - return m_signatureAlgorithm->VerifySignature( - message, - messageLength, - signature, - signatureLength - ); - } +// bool Certificate::VerifyMessage(const std::string & message, const std::string & hashBase64) +// { +// return m_signatureAlgorithm->VerifySignature(message, hashBase64); +// } +// +// bool Certificate::VerifyMessage( +// const unsigned char * message, +// size_t messageLength, +// const unsigned char * signature, +// size_t signatureLength +// ) +// { +// return m_signatureAlgorithm->VerifySignature( +// message, +// messageLength, +// signature, +// signatureLength +// ); +// } bool Certificate::VerifyCertificate(ICertificate * rootCertificate) { @@ -218,32 +232,32 @@ namespace lcp KeyType rawPublicKey = rootCertificate->PublicKey(); publicKeyQueue.Put(&rawPublicKey.at(0), rawPublicKey.size()); publicKeyQueue.MessageEnd(); - - CryptoPP::ECDSA::PublicKey publicKeyECDSA; - CryptoPP::RSA::PublicKey publicKeyRSA; - - if (m_signatureAlgorithm->Name() == AlgorithmNames::EcdsaSha256Id) { - publicKeyECDSA.BERDecode(publicKeyQueue); - } else { - publicKeyRSA.BERDecode(publicKeyQueue); - } +// +// CryptoPP::ECDSA::PublicKey publicKeyECDSA; +// CryptoPP::RSA::PublicKey publicKeyRSA; +// +// if (m_signatureAlgorithm->Name() == AlgorithmNames::EcdsaSha256Id) { +// publicKeyECDSA.BERDecode(publicKeyQueue); +// } else { +// publicKeyRSA.BERDecode(publicKeyQueue); +// } std::unique_ptr rootVerifierPtr; if (m_signatureAlgorithm->Name() == AlgorithmNames::EcdsaSha256Id) { - rootVerifierPtr.reset(new ECDSA::Verifier(publicKeyECDSA)); + rootVerifierPtr.reset(new ECDSA::Verifier(publicKeyQueue)); } else if (m_signatureAlgorithmId == sha256withRSAEncryption()) { - rootVerifierPtr.reset(new RSASS::Verifier(publicKeyRSA)); + rootVerifierPtr.reset(new RSASS::Verifier(publicKeyQueue)); } else if (m_signatureAlgorithmId == sha1withRSAEncryption()) { - rootVerifierPtr.reset(new RSASS::Verifier(publicKeyRSA)); + rootVerifierPtr.reset(new RSASS::Verifier(publicKeyQueue)); } else if (m_signatureAlgorithmId == md5withRSAEncryption()) { - rootVerifierPtr.reset(new RSASS::Verifier(publicKeyRSA)); + rootVerifierPtr.reset(new RSASS::Verifier(publicKeyQueue)); } else { diff --git a/src/lcp-client-lib/Certificate.h b/src/lcp-client-lib/Certificate.h index 448621b..f656edc 100644 --- a/src/lcp-client-lib/Certificate.h +++ b/src/lcp-client-lib/Certificate.h @@ -63,13 +63,13 @@ namespace lcp KeyType PublicKey() const; bool VerifyCertificate(ICertificate * rootCertificate); - bool VerifyMessage(const std::string & message, const std::string & hashBase64); - bool VerifyMessage( - const unsigned char * message, - size_t messageLength, - const unsigned char * signature, - size_t signatureLength - ); +// bool VerifyMessage(const std::string & message, const std::string & hashBase64); +// bool VerifyMessage( +// const unsigned char * message, +// size_t messageLength, +// const unsigned char * signature, +// size_t signatureLength +// ); ICrlDistributionPoints * DistributionPoints() const; @@ -78,8 +78,11 @@ namespace lcp std::string m_notBeforeDate; std::string m_notAfterDate; - CryptoPP::ECDSA::PublicKey m_publicKeyECDSA; - CryptoPP::RSA::PublicKey m_publicKeyRSA; +// CryptoPP::ECDSA::PublicKey m_publicKeyECDSA; +//// CryptoPP::DL_PublicKey_EC m_publicKeyECDSA; +// CryptoPP::RSA::PublicKey m_publicKeyRSA; +// ByteQueue m_publicKeyQueue; + KeyType m_publicKeyType; SecByteBlock m_toBeSignedData; SecByteBlock m_rootSignature; diff --git a/src/lcp-client-lib/CertificateRevocationList.cpp b/src/lcp-client-lib/CertificateRevocationList.cpp index 482f415..a4499bd 100644 --- a/src/lcp-client-lib/CertificateRevocationList.cpp +++ b/src/lcp-client-lib/CertificateRevocationList.cpp @@ -39,63 +39,66 @@ using namespace CryptoPP; namespace lcp { - CertificateRevocationList::CertificateRevocationList(const Buffer & crlRaw) - { - this->UpdateRevocationList(crlRaw); - } +// CertificateRevocationList::CertificateRevocationList(const Buffer & crlRaw) +// { +// this->UpdateRevocationList(crlRaw); +// } void CertificateRevocationList::UpdateRevocationList(const Buffer & crlRaw) { - std::unique_lock locker(m_sync); + try { + std::unique_lock locker(m_sync); - ByteQueue crlData; - crlData.Put(crlRaw.data(), crlRaw.size()); - crlData.MessageEnd(); + ByteQueue crlData; + crlData.Put(crlRaw.data(), crlRaw.size()); + crlData.MessageEnd(); - BERSequenceDecoder crl(crlData); - { - BERSequenceDecoder toBeSignedCertList(crl); + BERSequenceDecoder crl(crlData); { - word32 version = CryptoppUtils::Cert::ReadVersion(toBeSignedCertList, CertificateVersion::Certificatev2); - if (version != CertificateVersion::Certificatev2) + BERSequenceDecoder toBeSignedCertList(crl); { - throw BERDecodeErr("Wrong version of the crl"); - } + word32 version = CryptoppUtils::Cert::ReadVersion(toBeSignedCertList, + CertificateVersion::Certificatev2); + if (version != CertificateVersion::Certificatev2) { + throw BERDecodeErr("Wrong version of the crl"); + } - // algorithmId - CryptoppUtils::Cert::SkipNextSequence(toBeSignedCertList); - // issuer - CryptoppUtils::Cert::SkipNextSequence(toBeSignedCertList); - // this update - CryptoppUtils::Cert::BERDecodeTime(toBeSignedCertList, m_thisUpdate); - // next update - if (!toBeSignedCertList.EndReached()) - { - byte nextId = toBeSignedCertList.PeekByte(); - if (nextId == UTC_TIME || nextId == GENERALIZED_TIME) - { - CryptoppUtils::Cert::BERDecodeTime(toBeSignedCertList, m_nextUpdate); + // algorithmId + CryptoppUtils::Cert::SkipNextSequence(toBeSignedCertList); + // issuer + CryptoppUtils::Cert::SkipNextSequence(toBeSignedCertList); + // this update + CryptoppUtils::Cert::BERDecodeTime(toBeSignedCertList, m_thisUpdate); + // next update + if (!toBeSignedCertList.EndReached()) { + byte nextId = toBeSignedCertList.PeekByte(); + if (nextId == UTC_TIME || nextId == GENERALIZED_TIME) { + CryptoppUtils::Cert::BERDecodeTime(toBeSignedCertList, m_nextUpdate); + } } - } - if (!toBeSignedCertList.EndReached()) - { - BERSequenceDecoder revokedCertificates(toBeSignedCertList); - { - while (!revokedCertificates.EndReached()) + if (!toBeSignedCertList.EndReached()) { + BERSequenceDecoder revokedCertificates(toBeSignedCertList); { - BERSequenceDecoder nextRevokedCertificate(revokedCertificates); - { - std::string serial = CryptoppUtils::Cert::ReadIntegerAsString(nextRevokedCertificate); - m_revokedSerialNumbers.insert(serial); + while (!revokedCertificates.EndReached()) { + BERSequenceDecoder nextRevokedCertificate(revokedCertificates); + { + std::string serial = CryptoppUtils::Cert::ReadIntegerAsString( + nextRevokedCertificate); + m_revokedSerialNumbers.insert(serial); + } + nextRevokedCertificate.SkipAll(); } - nextRevokedCertificate.SkipAll(); } } + toBeSignedCertList.SkipAll(); } - toBeSignedCertList.SkipAll(); } } + catch (const std::exception & ex) + { + throw; + } } std::string CertificateRevocationList::ThisUpdateDate() const @@ -133,6 +136,12 @@ namespace lcp std::unique_lock locker(m_sync); return m_revokedSerialNumbers; } + + const void CertificateRevocationList::InsertRevokedSerialNumber(std::string serial) + { + std::unique_lock locker(m_sync); + m_revokedSerialNumbers.insert(serial); + } } #endif //!DISABLE_CRL diff --git a/src/lcp-client-lib/CertificateRevocationList.h b/src/lcp-client-lib/CertificateRevocationList.h index fadcc62..3afbf7b 100644 --- a/src/lcp-client-lib/CertificateRevocationList.h +++ b/src/lcp-client-lib/CertificateRevocationList.h @@ -40,7 +40,7 @@ namespace lcp { public: CertificateRevocationList() = default; - explicit CertificateRevocationList(const Buffer & crlRaw); +// explicit CertificateRevocationList(const Buffer & crlRaw); // ICertificateRevocationList virtual void UpdateRevocationList(const Buffer & crlRaw); @@ -50,6 +50,8 @@ namespace lcp virtual std::string NextUpdateDate() const; virtual bool SerialNumberRevoked(const std::string & serialNumber) const; virtual const StringsSet & RevokedSerialNumbers() const; + virtual const void InsertRevokedSerialNumber(std::string serial); + private: mutable std::mutex m_sync; diff --git a/src/lcp-client-lib/CrlUpdater.cpp b/src/lcp-client-lib/CrlUpdater.cpp index 9d24649..c9347b8 100644 --- a/src/lcp-client-lib/CrlUpdater.cpp +++ b/src/lcp-client-lib/CrlUpdater.cpp @@ -33,8 +33,13 @@ #include "CrlUpdater.h" #if !DISABLE_NET_PROVIDER +#if !DISABLE_CRL_DOWNLOAD_IN_MEMORY #include "SimpleMemoryWritableStream.h" #include "DownloadInMemoryRequest.h" +#else // !DISABLE_CRL_DOWNLOAD_IN_MEMORY +#include "DownloadInFileRequest.h" +#endif // !DISABLE_CRL_DOWNLOAD_IN_MEMORY + #endif //!DISABLE_NET_PROVIDER #include "DateTime.h" @@ -48,16 +53,26 @@ namespace lcp #if !DISABLE_NET_PROVIDER INetProvider * netProvider, #endif //!DISABLE_NET_PROVIDER + + IFileSystemProvider * fileSystemProvider, + ICertificateRevocationList * revocationList, +#if !DISABLE_CRL_BACKGROUND_POLL ThreadTimer * threadTimer, +#endif //!DISABLE_CRL_BACKGROUND_POLL const std::string & defaultCrlUrl ) : m_requestRunning(false) #if !DISABLE_NET_PROVIDER , m_netProvider(netProvider) #endif //!DISABLE_NET_PROVIDER + + , m_fileSystemProvider(fileSystemProvider) + , m_revocationList(revocationList) - , m_threadTimer(threadTimer) +#if !DISABLE_CRL_BACKGROUND_POLL + , m_threadTimer(threadTimer) +#endif //!DISABLE_CRL_BACKGROUND_POLL , m_currentRequestStatus(Status(StatusCode::ErrorCommonSuccess)) { if (!defaultCrlUrl.empty()) @@ -136,10 +151,17 @@ namespace lcp void CrlUpdater::Download(const std::string & url) { #if !DISABLE_NET_PROVIDER - m_crlStream.reset(new SimpleMemoryWritableStream()); + m_requestRunning = true; + +#if !DISABLE_CRL_DOWNLOAD_IN_MEMORY + m_crlStream.reset(new SimpleMemoryWritableStream()); // not actually used with NetProvider Java which operates on File only :( m_downloadRequest.reset(new DownloadInMemoryRequest(url, m_crlStream.get())); +#else // !DISABLE_CRL_DOWNLOAD_IN_MEMORY + m_crlFile.reset(m_fileSystemProvider->GetFile(PATH_TO_DOWNLOAD)); + m_downloadRequest.reset(new DownloadInFileRequest(url, m_crlFile.get())); +#endif // !DISABLE_CRL_DOWNLOAD_IN_MEMORY + m_netProvider->StartDownloadRequest(m_downloadRequest.get(), this); - m_requestRunning = true; #else m_currentRequestStatus = Status(StatusCode::ErrorCommonSuccess); m_requestRunning = false; @@ -150,10 +172,12 @@ namespace lcp #if !DISABLE_NET_PROVIDER void CrlUpdater::OnRequestStarted(INetRequest * request) { + bool breakpoint = true; } void CrlUpdater::OnRequestProgressed(INetRequest * request, float progress) { + bool breakpoint = true; } void CrlUpdater::OnRequestCanceled(INetRequest * request) @@ -170,7 +194,52 @@ namespace lcp std::unique_lock locker(m_downloadSync); if (Status::IsSuccess(result)) { - m_revocationList->UpdateRevocationList(m_crlStream->Buffer()); +#if !DISABLE_CRL_DOWNLOAD_IN_MEMORY + lcp::BaseDownloadRequest* request_ = dynamic_cast(request); + if (request_) { + std::string path = request_->SuggestedFileName(); + if (path.length() && path.at(0) == '/') { // SUPER HACKY!! (because Android NetProvider only handles file download) + IFile* file = m_fileSystemProvider->GetFile(path, IFileSystemProvider::ReadOnly); + + size_t bufferSize = 1024 * 1024; + std::vector buffer(bufferSize); + + size_t read = 0; + size_t sizeToRead = bufferSize; + size_t fileSize = static_cast(file->Size()); + while (read != fileSize) + { + sizeToRead = (fileSize - read > bufferSize) ? bufferSize : fileSize - read; + file->Read(buffer.data(), sizeToRead); + read += sizeToRead; + } + + delete file; + + m_revocationList->UpdateRevocationList(buffer); //std::vector + } else { + m_revocationList->UpdateRevocationList(m_crlStream->Buffer()); //std::vector + } + } + +#else // !DISABLE_CRL_DOWNLOAD_IN_MEMORY + // IFile == IReadableStream + size_t bufferSize = 1024 * 1024; + std::vector buffer(bufferSize); + + size_t read = 0; + size_t sizeToRead = bufferSize; + size_t fileSize = static_cast(m_crlFile->Size()); + while (read != fileSize) + { + sizeToRead = (fileSize - read > bufferSize) ? bufferSize : fileSize - read; + m_crlFile->Read(buffer.data(), sizeToRead); + read += sizeToRead; + } + + m_revocationList->UpdateRevocationList(buffer); //std::vector +#endif // !DISABLE_CRL_DOWNLOAD_IN_MEMORY + this->ResetNextUpdate(); } m_currentRequestStatus = result; @@ -180,12 +249,15 @@ namespace lcp catch (const std::exception & ex) { m_currentRequestStatus = Status(StatusCode::ErrorNetworkingRequestFailed, "ErrorNetworkingRequestFailed: " + std::string(ex.what())); + m_requestRunning = false; + m_conditionDownload.notify_one(); } } #endif //!DISABLE_NET_PROVIDER void CrlUpdater::ResetNextUpdate() { +#if !DISABLE_CRL_BACKGROUND_POLL if (m_revocationList->HasNextUpdateDate()) { DateTime nextUpdate(m_revocationList->NextUpdateDate()); @@ -205,8 +277,14 @@ namespace lcp m_threadTimer->SetUsage(ThreadTimer::DurationUsage); m_threadTimer->SetDuration(ThreadTimer::DurationType(TenMinutesPeriod)); } +// +//// TODO: remove this, for testing async update only! +// m_threadTimer->SetUsage(ThreadTimer::DurationUsage); +// m_threadTimer->SetDuration(ThreadTimer::DurationType(2000)); //TenMinutesPeriod == 1000 * 60 * 10 + m_threadTimer->SetAutoReset(true); +#endif //!DISABLE_CRL_BACKGROUND_POLL } } -#endif //!DISABLE_CRL \ No newline at end of file +#endif //!DISABLE_CRL diff --git a/src/lcp-client-lib/CrlUpdater.h b/src/lcp-client-lib/CrlUpdater.h index 8b897b5..e403978 100644 --- a/src/lcp-client-lib/CrlUpdater.h +++ b/src/lcp-client-lib/CrlUpdater.h @@ -37,12 +37,17 @@ #include "ICertificate.h" #if !DISABLE_NET_PROVIDER -#include "SimpleMemoryWritableStream.h" #include "public/INetProvider.h" #endif //!DISABLE_NET_PROVIDER #include "NonCopyable.h" +#if !DISABLE_CRL_DOWNLOAD_IN_MEMORY +#include "SimpleMemoryWritableStream.h" +#endif // !DISABLE_CRL_DOWNLOAD_IN_MEMORY + +#include "public/IFileSystemProvider.h" + namespace lcp { class ThreadTimer; @@ -62,8 +67,13 @@ namespace lcp #if !DISABLE_NET_PROVIDER INetProvider * netProvider, #endif //!DISABLE_NET_PROVIDER + + IFileSystemProvider * fileSystemProvider, + ICertificateRevocationList * revocationList, +#if !DISABLE_CRL_BACKGROUND_POLL ThreadTimer * threadTimer, +#endif //!DISABLE_CRL_BACKGROUND_POLL const std::string & defaultCrlUrl ); @@ -95,10 +105,20 @@ namespace lcp INetProvider * m_netProvider; #endif //!DISABLE_NET_PROVIDER ICertificateRevocationList * m_revocationList; +#if !DISABLE_CRL_BACKGROUND_POLL ThreadTimer * m_threadTimer; +#endif //!DISABLE_CRL_BACKGROUND_POLL #if !DISABLE_NET_PROVIDER + + IFileSystemProvider * m_fileSystemProvider; + +#if !DISABLE_CRL_DOWNLOAD_IN_MEMORY std::unique_ptr m_crlStream; +#else // !DISABLE_CRL_DOWNLOAD_IN_MEMORY + std::unique_ptr m_crlFile; +#endif // !DISABLE_CRL_DOWNLOAD_IN_MEMORY + std::unique_ptr m_downloadRequest; #endif //!DISABLE_NET_PROVIDER diff --git a/src/lcp-client-lib/CryptoLcpNode.cpp b/src/lcp-client-lib/CryptoLcpNode.cpp index 10dda22..839856d 100644 --- a/src/lcp-client-lib/CryptoLcpNode.cpp +++ b/src/lcp-client-lib/CryptoLcpNode.cpp @@ -96,11 +96,15 @@ namespace lcp Status CryptoLcpNode::VerifyNode(ILicense * license, IClientProvider * clientProvider, ICryptoProvider * cryptoProvider) { +#if ENABLE_PROFILE_NAMES m_encryptionProfile = m_encryptionProfilesManager->GetProfile(m_cryptoInfo.encryptionProfile); if (m_encryptionProfile == nullptr) { return Status(StatusCode::ErrorCommonEncryptionProfileNotFound, "ErrorCommonEncryptionProfileNotFound"); } +#else + m_encryptionProfile = m_encryptionProfilesManager->GetProfile(); +#endif //ENABLE_PROFILE_NAMES if (m_encryptionProfile->ContentKeyAlgorithmCBC() != m_cryptoInfo.contentKeyAlgorithm && m_encryptionProfile->ContentKeyAlgorithmGCM() != m_cryptoInfo.contentKeyAlgorithm) { diff --git a/src/lcp-client-lib/CryptoppCryptoProvider.cpp b/src/lcp-client-lib/CryptoppCryptoProvider.cpp index 360f1b8..5db7485 100644 --- a/src/lcp-client-lib/CryptoppCryptoProvider.cpp +++ b/src/lcp-client-lib/CryptoppCryptoProvider.cpp @@ -55,22 +55,41 @@ namespace lcp , INetProvider * netProvider #endif //!DISABLE_NET_PROVIDER + , IFileSystemProvider * fileSystemProvider + #if !DISABLE_CRL , const std::string & defaultCrlUrl #endif //!DISABLE_CRL ) - : m_encryptionProfilesManager(encryptionProfilesManager) + : + m_encryptionProfilesManager(encryptionProfilesManager) + + , m_fileSystemProvider(fileSystemProvider) + { #if !DISABLE_CRL m_revocationList.reset(new CertificateRevocationList()); + +#if !DISABLE_CRL_BACKGROUND_POLL m_threadTimer.reset(new ThreadTimer()); +#endif //!DISABLE_CRL_BACKGROUND_POLL m_crlUpdater.reset(new CrlUpdater( #if !DISABLE_NET_PROVIDER netProvider, #endif //!DISABLE_NET_PROVIDER - m_revocationList.get(), m_threadTimer.get(), defaultCrlUrl)); + m_fileSystemProvider, + + m_revocationList.get(), + +#if !DISABLE_CRL_BACKGROUND_POLL + m_threadTimer.get(), +#endif //!DISABLE_CRL_BACKGROUND_POLL + + defaultCrlUrl)); + +#if !DISABLE_CRL_BACKGROUND_POLL m_threadTimer->SetHandler(std::bind(&CrlUpdater::Update, m_crlUpdater.get())); m_threadTimer->SetAutoReset(false); @@ -80,6 +99,8 @@ namespace lcp m_threadTimer->SetDuration(ThreadTimer::DurationType(ThreadTimer::DurationType::zero())); m_threadTimer->Start(); } +#endif //!DISABLE_CRL_BACKGROUND_POLL + #endif //!DISABLE_CRL } @@ -89,7 +110,10 @@ namespace lcp try { m_crlUpdater->Cancel(); + +#if !DISABLE_CRL_BACKGROUND_POLL m_threadTimer->Stop(); +#endif //!DISABLE_CRL_BACKGROUND_POLL } catch (...) { @@ -104,11 +128,15 @@ namespace lcp { try { +#if ENABLE_PROFILE_NAMES IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(license->Crypto()->EncryptionProfile()); if (profile == nullptr) { return Status(StatusCode::ErrorCommonEncryptionProfileNotFound, "ErrorCommonEncryptionProfileNotFound"); } +#else + IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(); +#endif //ENABLE_PROFILE_NAMES if (rootCertificateBase64.empty()) { @@ -148,7 +176,9 @@ namespace lcp } #endif //!DISABLE_CRL - if (!providerCertificate->VerifyMessage(license->CanonicalContent(), license->Crypto()->Signature())) + //providerCertificate->VerifyMessage + lcp::ISignatureAlgorithm* signatureAlgorithm = profile->CreateSignatureAlgorithm(providerCertificate->PublicKey(), license->Crypto()->SignatureAlgorithm()); + if (!signatureAlgorithm->VerifySignature(license->CanonicalContent(), license->Crypto()->Signature())) { return Status(StatusCode::ErrorOpeningLicenseSignatureNotValid, "ErrorOpeningLicenseSignatureNotValid"); } @@ -182,29 +212,56 @@ namespace lcp } } + Status CryptoppCryptoProvider::LegacyPassphraseUserKey( + const KeyType & userKey1, + KeyType & userKey2 + ) + { + try + { + userKey2.assign(userKey1.begin(), userKey1.end()); + + return Status(StatusCode::ErrorCommonSuccess); + } + catch (const std::exception & ex) + { + return Status(StatusCode::ErrorDecryptionUserPassphraseNotValid, "ErrorDecryptionUserPassphraseNotValid: " + std::string(ex.what())); + } + } + Status CryptoppCryptoProvider::DecryptUserKey( const std::string & userPassphrase, ILicense * license, - KeyType & userKey + KeyType & userKey1, + KeyType & userKey2 ) { try { +#if ENABLE_PROFILE_NAMES IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(license->Crypto()->EncryptionProfile()); if (profile == nullptr) { return Status(StatusCode::ErrorCommonEncryptionProfileNotFound, "ErrorCommonEncryptionProfileNotFound"); } +#else + IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(); +#endif //ENABLE_PROFILE_NAMES std::unique_ptr hashAlgorithm(profile->CreateUserKeyAlgorithm()); hashAlgorithm->UpdateHash(userPassphrase); - userKey = hashAlgorithm->Hash(); + userKey1 = hashAlgorithm->Hash(); + + Status resx = this->LegacyPassphraseUserKey(userKey1, userKey2); + if (!Status::IsSuccess(resx)) { + return resx; + } //http://www.w3.org/2009/xmlenc11#aes256-gcm //http://www.w3.org/2001/04/xmlenc#aes256-cbc const std::string algorithm = license->Crypto()->ContentKeyAlgorithm(); - std::unique_ptr contentKeyAlgorithm(profile->CreateContentKeyAlgorithm(userKey, algorithm)); + std::unique_ptr contentKeyAlgorithm(profile->CreateContentKeyAlgorithm(userKey2, algorithm)); std::string id = contentKeyAlgorithm->Decrypt(license->Crypto()->UserKeyCheck()); if (!EqualsUtf8(id, license->Id())) { @@ -226,11 +283,15 @@ namespace lcp { try { +#if ENABLE_PROFILE_NAMES IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(license->Crypto()->EncryptionProfile()); if (profile == nullptr) { return Status(StatusCode::ErrorCommonEncryptionProfileNotFound, "ErrorCommonEncryptionProfileNotFound"); } +#else + IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(); +#endif //ENABLE_PROFILE_NAMES //http://www.w3.org/2009/xmlenc11#aes256-gcm //http://www.w3.org/2001/04/xmlenc#aes256-cbc @@ -333,11 +394,15 @@ namespace lcp { try { +#if ENABLE_PROFILE_NAMES IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(license->Crypto()->EncryptionProfile()); if (profile == nullptr) { return Status(StatusCode::ErrorCommonEncryptionProfileNotFound, "ErrorCommonEncryptionProfileNotFound"); } +#else + IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(); +#endif //ENABLE_PROFILE_NAMES //http://www.w3.org/2009/xmlenc11#aes256-gcm //http://www.w3.org/2001/04/xmlenc#aes256-cbc @@ -365,11 +430,15 @@ namespace lcp { try { +#if ENABLE_PROFILE_NAMES IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(license->Crypto()->EncryptionProfile()); if (profile == nullptr) { return Status(StatusCode::ErrorCommonEncryptionProfileNotFound, "ErrorCommonEncryptionProfileNotFound"); } +#else + IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(); +#endif //ENABLE_PROFILE_NAMES std::unique_ptr algo(profile->CreatePublicationAlgorithm(keyProvider->ContentKey(), algorithm)); *decryptedDataLength = algo->Decrypt( @@ -394,11 +463,15 @@ namespace lcp { try { +#if ENABLE_PROFILE_NAMES IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(license->Crypto()->EncryptionProfile()); if (profile == nullptr) { return Status(StatusCode::ErrorCommonEncryptionProfileNotFound, "ErrorCommonEncryptionProfileNotFound"); } +#else + IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(); +#endif //ENABLE_PROFILE_NAMES Status res(StatusCode::ErrorCommonSuccess); std::unique_ptr algo(profile->CreatePublicationAlgorithm(keyProvider->ContentKey(), algorithm)); @@ -412,6 +485,43 @@ namespace lcp } #if !DISABLE_CRL + + Status CryptoppCryptoProvider::CheckRevokation(ILicense* license) { + +#if ENABLE_PROFILE_NAMES + IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(license->Crypto()->EncryptionProfile()); + if (profile == nullptr) + { + return Status(StatusCode::ErrorCommonEncryptionProfileNotFound, "ErrorCommonEncryptionProfileNotFound"); + } +#else + IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(); +#endif //ENABLE_PROFILE_NAMES + + std::unique_ptr providerCertificate; + try { + providerCertificate.reset( + new lcp::Certificate(license->Crypto()->SignatureCertificate(), profile)); + } + catch (std::exception &ex) { + return Status(StatusCode::ErrorOpeningContentProviderCertificateNotValid, + "ErrorOpeningContentProviderCertificateNotValid: " + + std::string(ex.what())); + } + + return this->CheckRevokation(providerCertificate.get()); + } + + Status CryptoppCryptoProvider::CheckRevokation(ICertificate * providerCertificate) { + + if (m_revocationList->SerialNumberRevoked(providerCertificate->SerialNumber())) { + return Status(StatusCode::ErrorOpeningContentProviderCertificateRevoked, + "ErrorOpeningContentProviderCertificateRevoked"); + } + + return StatusCode::ErrorCommonSuccess; + } + Status CryptoppCryptoProvider::ProcessRevokation(ICertificate * rootCertificate, ICertificate * providerCertificate) { m_crlUpdater->UpdateCrlUrls(rootCertificate->DistributionPoints()); @@ -421,34 +531,53 @@ namespace lcp std::unique_lock locker(m_processRevocationSync); if (m_crlUpdater->ContainsAnyUrl() && !m_revocationList->HasThisUpdateDate()) { +#if !DISABLE_CRL_BACKGROUND_POLL if (m_threadTimer->IsRunning()) { m_threadTimer->Stop(); } +#endif //!DISABLE_CRL_BACKGROUND_POLL - // Check once more, the CRL state could've been changed during the stop process - if (!m_revocationList->HasThisUpdateDate()) - { - // If CRL is absent, update it right before certificate verification - m_crlUpdater->Update(); - } +// // Check once more, the CRL state could've been changed during the stop process +// if (!m_revocationList->HasThisUpdateDate()) +// { +// // If CRL is absent, update it right before certificate verification +// m_crlUpdater->Update(); +// } +#if !DISABLE_CRL_BACKGROUND_POLL // Start timer which will check CRL for updates periodically or by time point m_threadTimer->SetAutoReset(true); m_threadTimer->SetUsage(ThreadTimer::DurationUsage); + + //std::function + m_threadTimer->SetHandler([&]{ + m_crlUpdater->Update(); + }); // std::bind(&CrlUpdater::Update, &m_crlUpdater); + m_threadTimer->SetDuration(ThreadTimer::DurationType(CrlUpdater::TenMinutesPeriod)); m_threadTimer->Start(); +#endif //!DISABLE_CRL_BACKGROUND_POLL } locker.unlock(); +#if !DISABLE_CRL_BACKGROUND_POLL // If exception occurred in the timer thread, re-throw it m_threadTimer->RethrowExceptionIfAny(); +#endif //!DISABLE_CRL_BACKGROUND_POLL - if (m_revocationList->SerialNumberRevoked(providerCertificate->SerialNumber())) + + Status resx = this->CheckRevokation(providerCertificate); + if (!Status::IsSuccess(resx)) { - return Status(StatusCode::ErrorOpeningContentProviderCertificateRevoked, "ErrorOpeningContentProviderCertificateRevoked"); + return resx; } +// +// // TODO: only for testing fake mock revocation!! +// // TODO: REMOVE ! +// m_revocationList->InsertRevokedSerialNumber(providerCertificate->SerialNumber()); + return Status(StatusCode::ErrorCommonSuccess); } #endif //!DISABLE_CRL -} \ No newline at end of file +} diff --git a/src/lcp-client-lib/CryptoppCryptoProvider.h b/src/lcp-client-lib/CryptoppCryptoProvider.h index 63074ef..1c45e27 100644 --- a/src/lcp-client-lib/CryptoppCryptoProvider.h +++ b/src/lcp-client-lib/CryptoppCryptoProvider.h @@ -30,6 +30,7 @@ #include #include +#include "public/IFileSystemProvider.h" #include "ICryptoProvider.h" #include "NonCopyable.h" @@ -60,6 +61,9 @@ class ICertificateRevocationList; , INetProvider * netProvider #endif //!DISABLE_NET_PROVIDER + , IFileSystemProvider * fileSystemProvider + + #if !DISABLE_CRL , const std::string & defaultCrlUrl #endif //!DISABLE_CRL @@ -72,10 +76,16 @@ class ICertificateRevocationList; ); virtual Status DecryptUserKey( - const std::string & userPassphrase, - ILicense * license, - KeyType & userKey - ); + const std::string & userPassphrase, + ILicense * license, + KeyType & userKey1, + KeyType & userKey2 + ); + + virtual Status LegacyPassphraseUserKey( + const KeyType & userKey1, + KeyType & userKey2 + ); virtual Status DecryptContentKey( const KeyType & userKey, @@ -125,16 +135,27 @@ class ICertificateRevocationList; const std::string & algorithm ); +#if !DISABLE_CRL + public: + Status CheckRevokation(ILicense* license); + private: + Status CheckRevokation(ICertificate * providerCertificate); Status ProcessRevokation(ICertificate * rootCertificate, ICertificate * providerCertificate); - private: -#if !DISABLE_CRL + std::unique_ptr m_revocationList; + +#if !DISABLE_CRL_BACKGROUND_POLL std::unique_ptr m_threadTimer; +#endif //!DISABLE_CRL_BACKGROUND_POLL + std::unique_ptr m_crlUpdater; -#endif //!DISABLE_CRL std::mutex m_processRevocationSync; +#endif //!DISABLE_CRL + + IFileSystemProvider * m_fileSystemProvider; + EncryptionProfilesManager * m_encryptionProfilesManager; }; } diff --git a/src/lcp-client-lib/EcdsaSha256SignatureAlgorithm.cpp b/src/lcp-client-lib/EcdsaSha256SignatureAlgorithm.cpp index 9768e88..beedbcf 100644 --- a/src/lcp-client-lib/EcdsaSha256SignatureAlgorithm.cpp +++ b/src/lcp-client-lib/EcdsaSha256SignatureAlgorithm.cpp @@ -33,11 +33,7 @@ namespace lcp { EcdsaSha256SignatureAlgorithm::EcdsaSha256SignatureAlgorithm(const KeyType & publicKey) { - ByteQueue publicKeyQueue; - KeyType rawPublicKey = publicKey; - publicKeyQueue.Put(&rawPublicKey.at(0), rawPublicKey.size()); - publicKeyQueue.MessageEnd(); - m_publicKey.BERDecode(publicKeyQueue); + m_publicKeyType = publicKey; } std::string EcdsaSha256SignatureAlgorithm::Name() const @@ -68,7 +64,13 @@ namespace lcp size_t signatureLength ) { - ThisVerifier verifier(m_publicKey); + ByteQueue publicKeyQueue; + publicKeyQueue.Put(&m_publicKeyType.at(0), m_publicKeyType.size()); + publicKeyQueue.MessageEnd(); +// m_publicKey.BERDecode(publicKeyQueue); +// m_publicKeyQueue = publicKeyQueue; + + ThisVerifier verifier(publicKeyQueue); return verifier.VerifyMessage( message, messageLength, diff --git a/src/lcp-client-lib/EcdsaSha256SignatureAlgorithm.h b/src/lcp-client-lib/EcdsaSha256SignatureAlgorithm.h index 6d9c42b..a3a3539 100644 --- a/src/lcp-client-lib/EcdsaSha256SignatureAlgorithm.h +++ b/src/lcp-client-lib/EcdsaSha256SignatureAlgorithm.h @@ -59,7 +59,10 @@ namespace lcp private: typedef CryptoPP::ECDSA::Verifier ThisVerifier; - CryptoPP::ECDSA::PublicKey m_publicKey; + +// CryptoPP::ECDSA::PublicKey m_publicKey; +// CryptoPP::ByteQueue m_publicKeyQueue; + KeyType m_publicKeyType; }; } diff --git a/src/lcp-client-lib/EncryptionProfileNames.cpp b/src/lcp-client-lib/EncryptionProfileNames.cpp index 441cd72..a407a1a 100644 --- a/src/lcp-client-lib/EncryptionProfileNames.cpp +++ b/src/lcp-client-lib/EncryptionProfileNames.cpp @@ -27,7 +27,12 @@ #include "EncryptionProfileNames.h" +#if ENABLE_PROFILE_NAMES + namespace lcp { /*static*/ std::string EncryptionProfileNames::Lcp1dot0ProfileId = "http://readium.org/lcp/profile-1.0"; -} \ No newline at end of file + /*static*/ std::string EncryptionProfileNames::LcpBasicProfileId = "http://readium.org/lcp/basic-profile"; +} + +#endif //ENABLE_PROFILE_NAMES diff --git a/src/lcp-client-lib/EncryptionProfileNames.h b/src/lcp-client-lib/EncryptionProfileNames.h index f816e48..2b099ed 100644 --- a/src/lcp-client-lib/EncryptionProfileNames.h +++ b/src/lcp-client-lib/EncryptionProfileNames.h @@ -28,6 +28,8 @@ #ifndef __ENCRYPTION_PROFILE_NAMES_H__ #define __ENCRYPTION_PROFILE_NAMES_H__ +#if ENABLE_PROFILE_NAMES + #include namespace lcp @@ -36,7 +38,10 @@ namespace lcp { public: static std::string Lcp1dot0ProfileId; + static std::string LcpBasicProfileId; }; } +#endif //ENABLE_PROFILE_NAMES + #endif //__ENCRYPTION_PROFILE_NAMES_H__ diff --git a/src/lcp-client-lib/EncryptionProfilesManager.cpp b/src/lcp-client-lib/EncryptionProfilesManager.cpp index 9787a09..635fa33 100644 --- a/src/lcp-client-lib/EncryptionProfilesManager.cpp +++ b/src/lcp-client-lib/EncryptionProfilesManager.cpp @@ -32,10 +32,15 @@ namespace lcp { EncryptionProfilesManager::EncryptionProfilesManager() { +#if ENABLE_PROFILE_NAMES std::unique_ptr lcp1dot0(new Lcp1dot0EncryptionProfile()); m_profilesMap.insert(std::make_pair(lcp1dot0->Name(), std::move(lcp1dot0))); +#else + m_profile.reset(new Lcp1dot0EncryptionProfile()); +#endif //ENABLE_PROFILE_NAMES } +#if ENABLE_PROFILE_NAMES bool EncryptionProfilesManager::RegisterProfile(std::unique_ptr profile) { std::unique_lock locker(m_profilesSync); @@ -53,4 +58,10 @@ namespace lcp } return nullptr; } -} \ No newline at end of file +#else + IEncryptionProfile * EncryptionProfilesManager::GetProfile() const + { + return m_profile.get(); + } +#endif //ENABLE_PROFILE_NAMES +} diff --git a/src/lcp-client-lib/EncryptionProfilesManager.h b/src/lcp-client-lib/EncryptionProfilesManager.h index 09e6d6e..87d7862 100644 --- a/src/lcp-client-lib/EncryptionProfilesManager.h +++ b/src/lcp-client-lib/EncryptionProfilesManager.h @@ -28,9 +28,13 @@ #ifndef __ENCRYPTION_PROFILES_MANAGER_H__ #define __ENCRYPTION_PROFILES_MANAGER_H__ +#if ENABLE_PROFILE_NAMES #include -#include #include +#endif //ENABLE_PROFILE_NAMES + +#include + #include "IEncryptionProfile.h" #include "NonCopyable.h" @@ -40,13 +44,21 @@ namespace lcp { public: EncryptionProfilesManager(); +#if ENABLE_PROFILE_NAMES bool RegisterProfile(std::unique_ptr profile); IEncryptionProfile * GetProfile(const std::string & name) const; +#else + IEncryptionProfile * GetProfile() const; +#endif //ENABLE_PROFILE_NAMES private: +#if ENABLE_PROFILE_NAMES typedef std::map > ProfilesMap; ProfilesMap m_profilesMap; mutable std::mutex m_profilesSync; +#else + std::unique_ptr m_profile; +#endif //ENABLE_PROFILE_NAMES }; } diff --git a/src/lcp-client-lib/ICertificate.h b/src/lcp-client-lib/ICertificate.h index 33ca53b..675525d 100644 --- a/src/lcp-client-lib/ICertificate.h +++ b/src/lcp-client-lib/ICertificate.h @@ -48,7 +48,7 @@ namespace lcp virtual std::string NotAfterDate() const = 0; virtual KeyType PublicKey() const = 0; virtual bool VerifyCertificate(ICertificate * rootCertificate) = 0; - virtual bool VerifyMessage(const std::string & message, const std::string & hashBase64) = 0; +// virtual bool VerifyMessage(const std::string & message, const std::string & hashBase64) = 0; virtual ICrlDistributionPoints * DistributionPoints() const = 0; virtual ~ICertificate() {} }; @@ -74,6 +74,7 @@ namespace lcp virtual std::string NextUpdateDate() const = 0; virtual bool SerialNumberRevoked(const std::string & serialNumber) const = 0; virtual const StringsSet & RevokedSerialNumbers() const = 0; + virtual const void InsertRevokedSerialNumber(std::string serial) = 0; virtual ~ICertificateRevocationList() {} }; diff --git a/src/lcp-client-lib/ICryptoProvider.h b/src/lcp-client-lib/ICryptoProvider.h index f18bb34..c5bc02c 100644 --- a/src/lcp-client-lib/ICryptoProvider.h +++ b/src/lcp-client-lib/ICryptoProvider.h @@ -46,11 +46,21 @@ namespace lcp ILicense * license ) = 0; +#if !DISABLE_CRL + virtual Status CheckRevokation(ILicense* license) = 0; +#endif //!DISABLE_CRL + virtual Status DecryptUserKey( - const std::string & userPassphrase, - ILicense * license, - KeyType & userKey - ) = 0; + const std::string & userPassphrase, + ILicense * license, + KeyType & userKey1, + KeyType & userKey2 + ) = 0; + + virtual Status LegacyPassphraseUserKey( + const KeyType & userKey1, + KeyType & userKey2 + ) = 0; virtual Status DecryptContentKey( const KeyType & userKey, @@ -104,4 +114,4 @@ namespace lcp }; } -#endif //__I_CRYPTO_PROVIDER_H__ \ No newline at end of file +#endif //__I_CRYPTO_PROVIDER_H__ diff --git a/src/lcp-client-lib/IEncryptionProfile.h b/src/lcp-client-lib/IEncryptionProfile.h index 4d0546c..3f89595 100644 --- a/src/lcp-client-lib/IEncryptionProfile.h +++ b/src/lcp-client-lib/IEncryptionProfile.h @@ -41,7 +41,9 @@ namespace lcp class IEncryptionProfile { public: +#if ENABLE_PROFILE_NAMES virtual std::string Name() const = 0; +#endif //ENABLE_PROFILE_NAMES virtual std::string UserKeyAlgorithm() const = 0; virtual std::string PublicationAlgorithmGCM() const = 0; virtual std::string PublicationAlgorithmCBC() const = 0; diff --git a/src/lcp-client-lib/Lcp1dot0EncryptionProfile.cpp b/src/lcp-client-lib/Lcp1dot0EncryptionProfile.cpp index 1b4a7a8..bbd482f 100644 --- a/src/lcp-client-lib/Lcp1dot0EncryptionProfile.cpp +++ b/src/lcp-client-lib/Lcp1dot0EncryptionProfile.cpp @@ -26,7 +26,11 @@ #include "Lcp1dot0EncryptionProfile.h" + +#if ENABLE_PROFILE_NAMES #include "EncryptionProfileNames.h" +#endif //ENABLE_PROFILE_NAMES + #include "AlgorithmNames.h" #include "LcpUtils.h" @@ -96,11 +100,18 @@ namespace lcp throw StatusException(Status(StatusCode::ErrorCommonAlgorithmMismatch, "ErrorCommonAlgorithmMismatch")); } +#if ENABLE_PROFILE_NAMES std::string Lcp1dot0EncryptionProfile::Name() const { //http://readium.org/lcp/profile-1.0 return EncryptionProfileNames::Lcp1dot0ProfileId; + + ...OR? + + //http://readium.org/lcp/basic-profile + return EncryptionProfileNames::LcpBasicProfileId } +#endif //ENABLE_PROFILE_NAMES std::string Lcp1dot0EncryptionProfile::UserKeyAlgorithm() const { @@ -143,4 +154,4 @@ namespace lcp //http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256 return AlgorithmNames::EcdsaSha256Id; } -} \ No newline at end of file +} diff --git a/src/lcp-client-lib/Lcp1dot0EncryptionProfile.h b/src/lcp-client-lib/Lcp1dot0EncryptionProfile.h index 2d3a0fb..257dcf5 100644 --- a/src/lcp-client-lib/Lcp1dot0EncryptionProfile.h +++ b/src/lcp-client-lib/Lcp1dot0EncryptionProfile.h @@ -36,7 +36,9 @@ namespace lcp class Lcp1dot0EncryptionProfile : public IEncryptionProfile { public: +#if ENABLE_PROFILE_NAMES virtual std::string Name() const; +#endif //ENABLE_PROFILE_NAMES virtual std::string UserKeyAlgorithm() const; virtual std::string PublicationAlgorithmGCM() const; virtual std::string PublicationAlgorithmCBC() const; diff --git a/src/lcp-client-lib/LcpService.cpp b/src/lcp-client-lib/LcpService.cpp index 20b7402..8befc60 100644 --- a/src/lcp-client-lib/LcpService.cpp +++ b/src/lcp-client-lib/LcpService.cpp @@ -84,6 +84,8 @@ namespace lcp , m_netProvider #endif //!DISABLE_NET_PROVIDER + , fileSystemProvider + #if !DISABLE_CRL , defaultCrlUrl #endif //!DISABLE_CRL @@ -153,6 +155,14 @@ namespace lcp res = this->CheckDecrypted((*licensePTR)); } +#if !DISABLE_CRL + Status resx = m_cryptoProvider->CheckRevokation((*licensePTR)); + if (!Status::IsSuccess(resx)) + { + return resx; + } +#endif //!DISABLE_CRL + res = this->CheckLicenseStatusDocument((*licensePTR)); return res; @@ -213,9 +223,7 @@ namespace lcp Status result = Status(StatusCode::ErrorCommonSuccess); - if ( - false && // TODO comment this! => skips the decryption attempt (from stored passphrase) at first-time load, to test the user prompt - !license->Decrypted()) + if (!license->Decrypted()) // false && // TODO comment this! => skips the decryption attempt (from stored passphrase) at first-time load, to test the user prompt { result = this->DecryptLicenseOnOpening(license); @@ -328,16 +336,17 @@ namespace lcp throw std::invalid_argument("license is nullptr"); } - KeyType userKey; - Status res = m_cryptoProvider->DecryptUserKey(userPassphrase, license, userKey); + KeyType userKey1; + KeyType userKey2; + Status res = m_cryptoProvider->DecryptUserKey(userPassphrase, license, userKey1, userKey2); if (!Status::IsSuccess(res)) return res; - res = this->DecryptLicenseByUserKey(license, userKey); + res = this->DecryptLicenseByUserKey(license, userKey2); if (!Status::IsSuccess(res)) return res; - return this->AddDecryptedUserKey(license, userKey); + return this->AddDecryptedUserKey(license, userKey1); } catch (const StatusException & ex) { @@ -361,15 +370,15 @@ namespace lcp rootNode->SetKeyProvider(std::unique_ptr(new SimpleKeyProvider(userKey, contentKey))); return rootNode->DecryptNode(license, rootNode, m_cryptoProvider.get()); } - - Status LcpService::DecryptLicenseByHexUserKey(ILicense * license, const std::string & hexUserKey) - { - KeyType userKey; - Status res = m_cryptoProvider->ConvertHexToRaw(hexUserKey, userKey); - if (!Status::IsSuccess(res)) - return res; - return this->DecryptLicenseByUserKey(license, userKey); - } +// +// Status LcpService::DecryptLicenseByHexUserKey(ILicense * license, const std::string & hexUserKey) +// { +// KeyType userKey; +// Status res = m_cryptoProvider->ConvertHexToRaw(hexUserKey, userKey); +// if (!Status::IsSuccess(res)) +// return res; +// return this->DecryptLicenseByUserKey(license, userKey); +// } Status LcpService::DecryptLicenseOnOpening(ILicense * license) { @@ -411,7 +420,17 @@ namespace lcp ); if (!userKeyHex.empty()) { - Status res = this->DecryptLicenseByHexUserKey(license, userKeyHex); + KeyType userKey1; + Status res = m_cryptoProvider->ConvertHexToRaw(userKeyHex, userKey1); + if (!Status::IsSuccess(res)) + return res; + + KeyType userKey2; + res = m_cryptoProvider->LegacyPassphraseUserKey(userKey1, userKey2); + if (!Status::IsSuccess(res)) + return res; + + res = this->DecryptLicenseByUserKey(license, userKey2); if (Status::IsSuccess(res)) { return res; } @@ -420,7 +439,19 @@ namespace lcp std::unique_ptr it(m_storageProvider->EnumerateVault(UserKeysVaultId)); for (it->First(); !it->IsDone(); it->Next()) { - Status res = this->DecryptLicenseByHexUserKey(license, it->Current()); + std::string userKeyHex = it->Current(); + + KeyType userKey1; + Status res = m_cryptoProvider->ConvertHexToRaw(userKeyHex, userKey1); + if (!Status::IsSuccess(res)) + continue; + + KeyType userKey2; + res = m_cryptoProvider->LegacyPassphraseUserKey(userKey1, userKey2); + if (!Status::IsSuccess(res)) + continue; + + res = this->DecryptLicenseByUserKey(license, userKey2); if (Status::IsSuccess(res)) return res; } @@ -448,11 +479,16 @@ namespace lcp return Status(StatusCode::ErrorDecryptionLicenseEncrypted, "ErrorDecryptionLicenseEncrypted"); } +#if ENABLE_PROFILE_NAMES IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(license->Crypto()->EncryptionProfile()); if (profile == nullptr) { return Status(StatusCode::ErrorCommonEncryptionProfileNotFound, "ErrorCommonEncryptionProfileNotFound"); } +#else + IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(); +#endif //ENABLE_PROFILE_NAMES + if (algorithm != profile->PublicationAlgorithmGCM() && algorithm != profile->PublicationAlgorithmCBC()) { return Status(StatusCode::ErrorCommonAlgorithmMismatch, "ErrorCommonAlgorithmMismatch"); @@ -499,11 +535,15 @@ namespace lcp return Status(StatusCode::ErrorDecryptionLicenseEncrypted, "ErrorDecryptionLicenseEncrypted"); } +#if ENABLE_PROFILE_NAMES IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(license->Crypto()->EncryptionProfile()); if (profile == nullptr) { return Status(StatusCode::ErrorCommonEncryptionProfileNotFound, "ErrorCommonEncryptionProfileNotFound"); } +#else + IEncryptionProfile * profile = m_encryptionProfilesManager->GetProfile(); +#endif //ENABLE_PROFILE_NAMES if (algorithm != profile->PublicationAlgorithmGCM() && algorithm != profile->PublicationAlgorithmCBC()) { diff --git a/src/lcp-client-lib/LcpService.h b/src/lcp-client-lib/LcpService.h index b3219fa..af01a15 100644 --- a/src/lcp-client-lib/LcpService.h +++ b/src/lcp-client-lib/LcpService.h @@ -131,7 +131,7 @@ namespace lcp Status DecryptLicenseOnOpening(ILicense * license); Status DecryptLicenseByUserKey(ILicense * license, const KeyType & userKey); - Status DecryptLicenseByHexUserKey(ILicense * license, const std::string & hexUserKey); +// Status DecryptLicenseByHexUserKey(ILicense * license, const std::string & hexUserKey); Status DecryptLicenseByStorage(ILicense * license); Status AddDecryptedUserKey(ILicense * license, const KeyType & userKey); diff --git a/src/lcp-client-lib/LinksLcpNode.cpp b/src/lcp-client-lib/LinksLcpNode.cpp index f153bfc..e303366 100644 --- a/src/lcp-client-lib/LinksLcpNode.cpp +++ b/src/lcp-client-lib/LinksLcpNode.cpp @@ -79,18 +79,20 @@ namespace lcp rapidjson::Type type = linksMember->value.GetType(); + bool checkHref = name != Hint; + if (type == rapidjson::kObjectType) { const rapidjson::Value & linkObject = linksMember->value; - Link link = this->ParseLinkValues(linkObject, reader); + Link link = this->ParseLinkValues(linkObject, reader, checkHref); m_linksMultiMap.insert(std::make_pair(name, link)); } else if (type == rapidjson::kArrayType) { for (auto linkObject = linksMember->value.Begin(); linkObject != linksMember->value.End(); ++linkObject) { - Link link = this->ParseLinkValues(*linkObject, reader); + Link link = this->ParseLinkValues(*linkObject, reader, checkHref); m_linksMultiMap.insert(std::make_pair(name, link)); } } @@ -134,12 +136,14 @@ namespace lcp { throw StatusException(Status(StatusCode::ErrorOpeningLicenseNotValid, "ErrorOpeningLicenseNotValid: links object is not valid")); } + + bool checkHref = true; if (name == Hint) { hintFound = true; + checkHref = false; } - - Link link = this->ParseLinkValues(*linkObject, reader); + Link link = this->ParseLinkValues(*linkObject, reader, checkHref); m_linksMultiMap.insert(std::make_pair(name, link)); } @@ -217,10 +221,14 @@ namespace lcp return new MultiMapIterator(m_linksMultiMap); } - Link LinksLcpNode::ParseLinkValues(const rapidjson::Value & linkObject, JsonValueReader * reader) + Link LinksLcpNode::ParseLinkValues(const rapidjson::Value & linkObject, JsonValueReader * reader, bool checkHref) { Link link; - link.href = reader->ReadStringCheck("href", linkObject); + if (checkHref) { + link.href = reader->ReadStringCheck("href", linkObject); + } else { + link.href = reader->ReadString("href", linkObject); + } link.title = reader->ReadString("title", linkObject); link.type = reader->ReadString("type", linkObject); link.templated = reader->ReadBoolean("templated", linkObject); diff --git a/src/lcp-client-lib/LinksLcpNode.h b/src/lcp-client-lib/LinksLcpNode.h index a3a679d..c8f8802 100644 --- a/src/lcp-client-lib/LinksLcpNode.h +++ b/src/lcp-client-lib/LinksLcpNode.h @@ -52,7 +52,7 @@ namespace lcp virtual bool GetLinks(const std::string & name, std::vector & links) const; private: - Link ParseLinkValues(const rapidjson::Value & linkObject, JsonValueReader * reader); + Link ParseLinkValues(const rapidjson::Value & linkObject, JsonValueReader * reader, bool checkHref); private: typedef std::multimap LinksMap; diff --git a/src/lcp-client-lib/RsaSha256SignatureAlgorithm.cpp b/src/lcp-client-lib/RsaSha256SignatureAlgorithm.cpp index b6a66cf..a9ec206 100644 --- a/src/lcp-client-lib/RsaSha256SignatureAlgorithm.cpp +++ b/src/lcp-client-lib/RsaSha256SignatureAlgorithm.cpp @@ -33,11 +33,7 @@ namespace lcp { RsaSha256SignatureAlgorithm::RsaSha256SignatureAlgorithm(const KeyType & publicKey) { - ByteQueue publicKeyQueue; - KeyType rawPublicKey = publicKey; - publicKeyQueue.Put(&rawPublicKey.at(0), rawPublicKey.size()); - publicKeyQueue.MessageEnd(); - m_publicKey.BERDecode(publicKeyQueue); + m_publicKeyType = publicKey; } std::string RsaSha256SignatureAlgorithm::Name() const @@ -68,7 +64,13 @@ namespace lcp size_t signatureLength ) { - ThisVerifier verifier(m_publicKey); + ByteQueue publicKeyQueue; + publicKeyQueue.Put(&m_publicKeyType.at(0), m_publicKeyType.size()); + publicKeyQueue.MessageEnd(); +// m_publicKey.BERDecode(publicKeyQueue); +// m_publicKeyQueue = publicKeyQueue; + + ThisVerifier verifier(publicKeyQueue); return verifier.VerifyMessage( message, messageLength, diff --git a/src/lcp-client-lib/RsaSha256SignatureAlgorithm.h b/src/lcp-client-lib/RsaSha256SignatureAlgorithm.h index 1ae3dd2..f154913 100644 --- a/src/lcp-client-lib/RsaSha256SignatureAlgorithm.h +++ b/src/lcp-client-lib/RsaSha256SignatureAlgorithm.h @@ -59,7 +59,10 @@ namespace lcp private: typedef CryptoPP::RSASS::Verifier ThisVerifier; - CryptoPP::RSA::PublicKey m_publicKey; + +// CryptoPP::RSA::PublicKey m_publicKey; +// CryptoPP::ByteQueue m_publicKeyQueue; + KeyType m_publicKeyType; }; } diff --git a/src/lcp-client-lib/ThreadTimer.cpp b/src/lcp-client-lib/ThreadTimer.cpp index 5265e62..2120207 100644 --- a/src/lcp-client-lib/ThreadTimer.cpp +++ b/src/lcp-client-lib/ThreadTimer.cpp @@ -26,6 +26,8 @@ #if !DISABLE_CRL +#if !DISABLE_CRL_BACKGROUND_POLL + #include "ThreadTimer.h" namespace lcp @@ -139,6 +141,13 @@ namespace lcp std::unique_lock locker(m_sync); do { + locker.unlock(); + if (m_handler) + { + m_handler(); + } + locker.lock(); + if (m_usageType == UsageTypeEnum::TimePointUsage) { m_conditionRunning.wait_until(locker, m_runTimePoint, [&]() { return !m_isRunning; }); @@ -151,13 +160,6 @@ namespace lcp { throw std::logic_error("Unknown timer usage type"); } - - locker.unlock(); - if (m_handler) - { - m_handler(); - } - locker.lock(); } while (m_isAutoReset && m_isRunning); @@ -184,4 +186,6 @@ namespace lcp } } +#endif //!DISABLE_CRL_BACKGROUND_POLL + #endif //!DISABLE_CRL \ No newline at end of file diff --git a/src/lcp-client-lib/ThreadTimer.h b/src/lcp-client-lib/ThreadTimer.h index 4cb59ac..f91d93b 100644 --- a/src/lcp-client-lib/ThreadTimer.h +++ b/src/lcp-client-lib/ThreadTimer.h @@ -29,6 +29,8 @@ #if !DISABLE_CRL +#if !DISABLE_CRL_BACKGROUND_POLL + #include #include #include @@ -97,6 +99,8 @@ namespace lcp }; } +#endif //!DISABLE_CRL_BACKGROUND_POLL + #endif //!DISABLE_CRL #endif //__THREAD_TIMER_H__ \ No newline at end of file diff --git a/src/lcp-client-lib/public/DefaultFileSystemProvider.h b/src/lcp-client-lib/public/DefaultFileSystemProvider.h index 94fa300..fd66688 100644 --- a/src/lcp-client-lib/public/DefaultFileSystemProvider.h +++ b/src/lcp-client-lib/public/DefaultFileSystemProvider.h @@ -45,13 +45,13 @@ namespace lcp , m_readPosition(0) , m_writePosition(0) { - int mode = 0; - if (openMode == IFileSystemProvider::CreateNew) - mode = std::ios::in | std::ios::out | std::fstream::trunc | std::ios::binary; - else if (openMode == IFileSystemProvider::ReadOnly) - mode = std::ios::in | std::ios::binary; + m_fstream.open(path.c_str(), (openMode == IFileSystemProvider::CreateNew) ? + (std::ios::in | std::ios::out | std::fstream::trunc | std::ios::binary) : + ((openMode == IFileSystemProvider::ReadOnly) ? + (std::ios::in | std::ios::binary) : + std::ios::binary) + ); - m_fstream.open(path, mode); if (!m_fstream.is_open()) { this->ThrowError("Can not open file: "); diff --git a/src/third-parties/cryptopp/cryptopp.xcodeproj/project.pbxproj b/src/third-parties/cryptopp/cryptopp.xcodeproj/project.pbxproj index 63785d6..9481b65 100644 --- a/src/third-parties/cryptopp/cryptopp.xcodeproj/project.pbxproj +++ b/src/third-parties/cryptopp/cryptopp.xcodeproj/project.pbxproj @@ -930,7 +930,7 @@ 5A5C5FA41C04BAD700185159 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0710; + LastUpgradeCheck = 1010; ORGANIZATIONNAME = "Crypto++"; TargetAttributes = { 5A5C5FAB1C04BAD700185159 = { @@ -1245,8 +1245,24 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; @@ -1261,7 +1277,12 @@ "DEBUG=1", "$(inherited)", ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.3; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; @@ -1278,8 +1299,24 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; @@ -1289,7 +1326,12 @@ GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = "${inherited}"; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.3; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; diff --git a/src/third-parties/cryptopp/filters.cpp b/src/third-parties/cryptopp/filters.cpp index b848d99..1cd9d9a 100644 --- a/src/third-parties/cryptopp/filters.cpp +++ b/src/third-parties/cryptopp/filters.cpp @@ -618,8 +618,14 @@ void StreamTransformationFilter::InitializeDerivedAndReturnNewSizes(const NameVa else m_padding = padding; - if (!isBlockCipher && (m_padding == PKCS_PADDING || m_padding == ONE_AND_ZEROS_PADDING)) - throw InvalidArgument("StreamTransformationFilter: PKCS_PADDING and ONE_AND_ZEROS_PADDING cannot be used with " + m_cipher.AlgorithmName()); + if (!isBlockCipher && (m_padding == PKCS_PADDING)) + throw InvalidArgument("StreamTransformationFilter: PKCS_PADDING cannot be used with " + m_cipher.AlgorithmName()); + + if (!isBlockCipher && (m_padding == W3C_PADDING)) + throw InvalidArgument("StreamTransformationFilter: W3C_PADDING cannot be used with " + m_cipher.AlgorithmName()); + + if (!isBlockCipher && (m_padding == ONE_AND_ZEROS_PADDING)) + throw InvalidArgument("StreamTransformationFilter: ONE_AND_ZEROS_PADDING cannot be used with " + m_cipher.AlgorithmName()); firstSize = 0; blockSize = m_cipher.MandatoryBlockSize(); diff --git a/src/third-parties/ziplib/Source/ZipLib/streams/compression_decoder_stream.h b/src/third-parties/ziplib/Source/ZipLib/streams/compression_decoder_stream.h index 401b750..3420c5c 100644 --- a/src/third-parties/ziplib/Source/ZipLib/streams/compression_decoder_stream.h +++ b/src/third-parties/ziplib/Source/ZipLib/streams/compression_decoder_stream.h @@ -1,6 +1,111 @@ #pragma once #include -#include "streambuffs/compression_decoder_streambuf.h" +// #include "streambuffs/compression_decoder_streambuf.h" + +#include +#include +#include +#include + +#include "../compression/compression_interface.h" + +template +class compression_decoder_streambuf + : public std::basic_streambuf +{ + public: + typedef std::basic_streambuf base_type; + typedef typename std::basic_streambuf::traits_type traits_type; + + typedef typename base_type::char_type char_type; + typedef typename base_type::int_type int_type; + typedef typename base_type::pos_type pos_type; + typedef typename base_type::off_type off_type; + + typedef std::basic_istream istream_type; + typedef std::basic_ostream ostream_type; + + typedef compression_decoder_interface_basic icompression_decoder_type; + typedef std::shared_ptr icompression_decoder_ptr_type; + + compression_decoder_streambuf() + { + + } + + compression_decoder_streambuf(icompression_decoder_ptr_type compressionDecoder, istream_type& stream) + { + init(compressionDecoder, stream); + } + + compression_decoder_streambuf(icompression_decoder_ptr_type compressionDecoder, compression_decoder_properties_interface& props, istream_type& stream) + { + init(compressionDecoder, stream); + } + + void init(icompression_decoder_ptr_type compressionDecoder, istream_type& stream) + { + _compressionDecoder = compressionDecoder; + + // compression decoder init + _compressionDecoder->init(stream); + + // set stream buffer + this->setg(_compressionDecoder->get_buffer_end(), _compressionDecoder->get_buffer_end(), _compressionDecoder->get_buffer_end()); + } + + void init(icompression_decoder_ptr_type compressionDecoder, compression_decoder_properties_interface& props, istream_type& stream) + { + _compressionDecoder = compressionDecoder; + + // compression decoder init + _compressionDecoder->init(stream, props); + + // set stream buffer + this->setg(_compressionDecoder->get_buffer_end(), _compressionDecoder->get_buffer_end(), _compressionDecoder->get_buffer_end()); + } + + bool is_init() const + { + return _compressionDecoder->is_init(); + } + + size_t get_bytes_read() const + { + return _compressionDecoder->get_bytes_read(); + } + + size_t get_bytes_written() const + { + return _compressionDecoder->get_bytes_written(); + } + + protected: + int_type underflow() override + { + // buffer exhausted + if (this->gptr() >= this->egptr()) + { + ELEM_TYPE* base = _compressionDecoder->get_buffer_begin(); + + // how many bytes has been read + size_t n = _compressionDecoder->decode_next(); + + if (n == 0) + { + return traits_type::eof(); + } + + // set buffer pointers + this->setg(base, base, base + n); + } + + return traits_type::to_int_type(*this->gptr()); + } + + private: + icompression_decoder_ptr_type _compressionDecoder; +}; /** * \brief Basic generic compression decoder stream. diff --git a/src/third-parties/ziplib/Source/ZipLib/streams/compression_encoder_stream.h b/src/third-parties/ziplib/Source/ZipLib/streams/compression_encoder_stream.h index 078a6b0..241844e 100644 --- a/src/third-parties/ziplib/Source/ZipLib/streams/compression_encoder_stream.h +++ b/src/third-parties/ziplib/Source/ZipLib/streams/compression_encoder_stream.h @@ -1,6 +1,136 @@ #pragma once #include -#include "streambuffs/compression_encoder_streambuf.h" +// #include "streambuffs/compression_encoder_streambuf.h" + +#include +#include +#include +#include +#include +#include + +#include "../compression/compression_interface.h" + +template +class compression_encoder_streambuf + : public std::basic_streambuf +{ + public: + typedef std::basic_streambuf base_type; + typedef typename std::basic_streambuf::traits_type traits_type; + + typedef typename base_type::char_type char_type; + typedef typename base_type::int_type int_type; + typedef typename base_type::pos_type pos_type; + typedef typename base_type::off_type off_type; + + typedef std::basic_istream istream_type; + typedef std::basic_ostream ostream_type; + + typedef compression_encoder_interface_basic icompression_encoder_type; + typedef std::shared_ptr icompression_encoder_ptr_type; + + compression_encoder_streambuf() + { + + } + + compression_encoder_streambuf(icompression_encoder_ptr_type compressionEncoder, ostream_type& stream) + { + init(compressionEncoder, stream); + } + + compression_encoder_streambuf(icompression_encoder_ptr_type compressionEncoder, compression_encoder_properties_interface& props, ostream_type& stream) + { + init(compressionEncoder, props, stream); + } + + virtual ~compression_encoder_streambuf() + { + sync(); + } + + void init(icompression_encoder_ptr_type compressionEncoder, ostream_type& stream) + { + _compressionEncoder = compressionEncoder; + + // compression encoder init + _compressionEncoder->init(stream); + + // set stream buffer + this->setp(_compressionEncoder->get_buffer_begin(), _compressionEncoder->get_buffer_end() - 1); + } + + void init(icompression_encoder_ptr_type compressionEncoder, compression_encoder_properties_interface& props, ostream_type& stream) + { + _compressionEncoder = compressionEncoder; + + // compression encoder init + _compressionEncoder->init(stream, props); + + // set stream buffer + this->setp(_compressionEncoder->get_buffer_begin(), _compressionEncoder->get_buffer_end() - 1); + } + + bool is_init() const + { + return _compressionEncoder->is_init(); + } + + size_t get_bytes_read() const + { + return _compressionEncoder->get_bytes_read(); + } + + size_t get_bytes_written() const + { + return _compressionEncoder->get_bytes_written(); + } + + protected: + int_type overflow(int_type c = traits_type::eof()) override + { + bool is_eof = traits_type::eq_int_type(c, traits_type::eof()); + + // if the input is not EOF, just put it into the buffer + // and increment current pointer + if (!is_eof) + { + *this->pptr() = c; + this->pbump(1); + } + + // if input buffer is full or input is EOF, + // compress the buffer + if (this->pptr() >= this->epptr() || is_eof) + { + process(); + } + + // not eof + return ~traits_type::eof(); + } + + int sync() override + { + process(); + _compressionEncoder->sync(); + + return 0; + } + + private: + void process() + { + std::ptrdiff_t inputLength = this->pptr() - this->pbase(); + _compressionEncoder->encode_next(inputLength); + + // set pointers for new buffer + this->setp(_compressionEncoder->get_buffer_begin(), _compressionEncoder->get_buffer_end() - 1); + } + + icompression_encoder_ptr_type _compressionEncoder; +}; /** * \brief Basic generic compression encoder stream. diff --git a/src/third-parties/ziplib/Source/ZipLib/streams/crc32stream.h b/src/third-parties/ziplib/Source/ZipLib/streams/crc32stream.h index cffaa7c..61ce88a 100644 --- a/src/third-parties/ziplib/Source/ZipLib/streams/crc32stream.h +++ b/src/third-parties/ziplib/Source/ZipLib/streams/crc32stream.h @@ -1,6 +1,111 @@ #pragma once #include -#include "streambuffs/crc32_streambuf.h" +// #include "streambuffs/crc32_streambuf.h" + +#include +#include + +#include "substream.h" +#include "../extlibs/zlib/zlib.h" + +template +class crc32_streambuf + : public std::basic_streambuf +{ + public: + typedef std::basic_streambuf base_type; + typedef typename std::basic_streambuf::traits_type traits_type; + + typedef typename base_type::char_type char_type; + typedef typename base_type::int_type int_type; + typedef typename base_type::pos_type pos_type; + typedef typename base_type::off_type off_type; + + crc32_streambuf() + : _inputStream(nullptr) + , _internalBufferPosition(_internalBuffer + INTERNAL_BUFFER_SIZE) + , _internalBufferEnd(_internalBuffer + INTERNAL_BUFFER_SIZE) + , _bytesRead(0) + , _crc32(0) + { + + } + + crc32_streambuf(std::basic_istream& input) + : crc32_streambuf() + { + init(input); + } + + void init(std::basic_istream& input) + { + _inputStream = &input; + + ELEM_TYPE* endOfBuffer = _internalBuffer + INTERNAL_BUFFER_SIZE; + this->setg(endOfBuffer, endOfBuffer, endOfBuffer); + } + + bool is_init() const + { + return (_inputStream != nullptr); + } + + size_t get_bytes_read() const + { + return _bytesRead; + } + + uint32_t get_crc32() const + { + return _crc32; + } + + protected: + int_type underflow() override + { + // buffer exhausted + if (this->gptr() >= _internalBufferEnd) + { + _inputStream->read(_internalBuffer, static_cast(INTERNAL_BUFFER_SIZE)); + size_t n = static_cast(_inputStream->gcount()); + + _bytesRead += n; + + _internalBufferPosition = _internalBuffer; + _internalBufferEnd = _internalBuffer + n; + + if (n == 0) + { + return traits_type::eof(); + } + } + + // set buffer pointers, increment current position + ELEM_TYPE* base = _internalBufferPosition++; + + // setting all pointers to the same position forces calling of this method each time, + // so crc32 really represents the checksum of what really has been read + this->setg(base, base, base + 1); + + _crc32 = crc32(_crc32, reinterpret_cast(this->gptr()), static_cast(sizeof(ELEM_TYPE))); + + return traits_type::to_int_type(*this->gptr()); + } + + private: + enum : size_t + { + INTERNAL_BUFFER_SIZE = 1 << 15 + }; + + ELEM_TYPE _internalBuffer[INTERNAL_BUFFER_SIZE]; + ELEM_TYPE* _internalBufferPosition; + ELEM_TYPE* _internalBufferEnd; + + std::basic_istream* _inputStream; + size_t _bytesRead; + uint32_t _crc32; +}; /** * \brief Basic CRC32 output stream. Computes CRC32 of input data. diff --git a/src/third-parties/ziplib/Source/ZipLib/streams/memstream.h b/src/third-parties/ziplib/Source/ZipLib/streams/memstream.h index 641291e..b774794 100644 --- a/src/third-parties/ziplib/Source/ZipLib/streams/memstream.h +++ b/src/third-parties/ziplib/Source/ZipLib/streams/memstream.h @@ -1,7 +1,208 @@ #pragma once #include #include -#include "streambuffs/mem_streambuf.h" +// #include "streambuffs/mem_streambuf.h" + +#include +#include +#include + +template +class mem_streambuf + : public std::basic_streambuf +{ + public: + typedef std::basic_streambuf base_type; + typedef typename std::basic_streambuf::traits_type traits_type; + + typedef typename base_type::char_type char_type; + typedef typename base_type::int_type int_type; + typedef typename base_type::pos_type pos_type; + typedef typename base_type::off_type off_type; + + mem_streambuf(ELEM_TYPE* buffer, size_t length) + { + // set stream buffer + ELEM_TYPE* endOfBuffer = buffer + length; + this->setg(buffer, buffer, endOfBuffer); + this->setp(buffer, buffer, endOfBuffer); + } + + protected: + int_type underflow() override + { + // buffer not exhausted + if (this->gptr() < this->egptr()) + { + return traits_type::to_int_type(*this->gptr()); + } + + return traits_type::eof(); + } + + int_type overflow(int_type c = traits_type::eof()) override + { + assert(this->pptr() != nullptr); + + // check if incoming character is not EOF + // also, we might not overflow the buffer + if (!traits_type::eq_int_type(c, traits_type::eof()) && + this->pptr() < this->epptr()) + { + *this->pptr() = c; + this->pbump(1); // shift pptr() by 1 + return c; // return value must not be EOF + } + + return traits_type::eof(); + } + + pos_type seekpos(pos_type pos, std::ios::openmode which = std::ios::in | std::ios::out) override + { + static const off_type BAD_OFFSET(-1); + + // depending on which pointer we move, it must be set + assert(which & std::ios::in ? this->gptr() != nullptr : true); + assert(which & std::ios::out ? this->pptr() != nullptr : true); + + // do not seek over the length of buffer + if (pos <= pos_type(this->egptr() - this->eback())) + { + // position of read buffer + if (which & std::ios::in) + { + // move gptr to the right position + this->gbump(static_cast(this->eback() - this->gptr() + pos)); + + if (which & std::ios::out) + { + // change write position to match + this->setp(this->pbase(), this->gptr(), this->epptr()); + } + } + + // position of write buffer + else if (which & std::ios::out) + { + // move pptr to the right position + this->pbump(static_cast(this->eback() - this->pptr() + pos)); + } + + return pos; + } + + // something went wrong + return pos_type(BAD_OFFSET); + } + + pos_type seekoff(off_type off, std::ios::seekdir dir, std::ios::openmode which = std::ios::in | std::ios::out) override + { + static const off_type BAD_OFFSET(-1); + + // depending on which pointer we move, it must be set + assert(which & std::ios::in ? this->gptr() != nullptr : true); + assert(which & std::ios::out ? this->pptr() != nullptr : true); + + if (which & std::ios::in) + { + // position within read buffer + if (dir == std::ios::end) + { + off += off_type(this->egptr() - this->eback()); + } + else if (dir == std::ios::cur && (which & std::ios::out) == 0) + { + off += off_type(this->gptr() - this->eback()); + } + else if (dir != std::ios::beg) + { + off = BAD_OFFSET; + } + + if (off >= 0 && off <= off_type(this->egptr() - this->eback())) + { + // move gptr to the right position + this->gbump(static_cast(this->eback() - this->gptr() + off)); + if (which & std::ios::out) + { + // change write position to match + this->setp(this->pbase(), this->gptr(), this->epptr()); + } + } + else + { + off = BAD_OFFSET; + } + } + else if (which & std::ios::out) + { + // position within write buffer + if (dir == std::ios::end) + { + off += off_type(this->egptr() - this->eback()); + } + else if (dir == std::ios::cur) + { + off += off_type(this->pptr() - this->eback()); + } + else if (dir != std::ios::beg) + { + // if dir is ios::beg, just leave the offset set as is + // if dir is not neither of the valid directions, set bad offset + off = BAD_OFFSET; + } + + if (off >= 0 && off <= off_type(this->egptr() - this->eback())) + { + // change write position + this->pbump(static_cast(this->eback() - this->pptr() + off)); + } + else + { + off = BAD_OFFSET; + } + } + else + { + // neither read nor write buffer selected, fail + off = BAD_OFFSET; + } + return (pos_type(off)); + } + + int_type pbackfail(int_type c = traits_type::eof()) override + { + assert(this->gptr() != nullptr); + + // put an element back to stream + if (this->gptr() <= this->eback() || // do not underflow + (!traits_type::eq_int_type(traits_type::eof(), c) && + !traits_type::eq(traits_type::to_char_type(c), this->gptr()[-1]))) + { + // can't put back, fail + return (traits_type::eof()); + } + else + { + // back up one position and store put-back character + this->gbump(-1); + + if (!traits_type::eq_int_type(traits_type::eof(), c)) + { + *this->gptr() = traits_type::to_char_type(c); + } + + return (traits_type::not_eof(c)); + } + } + + private: + void setp(ELEM_TYPE* first, ELEM_TYPE* next, ELEM_TYPE* last) + { + this->std::basic_streambuf::setp(first, last); + this->pbump(static_cast(next - first)); + } +}; /** * \brief Basic input memory stream. diff --git a/src/third-parties/ziplib/Source/ZipLib/streams/nullstream.h b/src/third-parties/ziplib/Source/ZipLib/streams/nullstream.h index ad238cb..5444e4c 100644 --- a/src/third-parties/ziplib/Source/ZipLib/streams/nullstream.h +++ b/src/third-parties/ziplib/Source/ZipLib/streams/nullstream.h @@ -1,7 +1,39 @@ #pragma once #include #include -#include "streambuffs/null_streambuf.h" +// #include "streambuffs/null_streambuf.h" + +#include + +template +class null_streambuf + : public std::basic_streambuf +{ + public: + typedef std::basic_streambuf base_type; + typedef typename std::basic_streambuf::traits_type traits_type; + + typedef typename base_type::char_type char_type; + typedef typename base_type::int_type int_type; + typedef typename base_type::pos_type pos_type; + typedef typename base_type::off_type off_type; + + null_streambuf() + { + + } + + protected: + std::streamsize xsgetn(char_type* s, std::streamsize count) override + { + return 0; + } + + std::streamsize xsputn(const ELEM_TYPE* ptr, std::streamsize count) override + { + return count; + } +}; /** * \brief Basic null stream. diff --git a/src/third-parties/ziplib/Source/ZipLib/streams/substream.h b/src/third-parties/ziplib/Source/ZipLib/streams/substream.h index c1fe45e..366fe70 100644 --- a/src/third-parties/ziplib/Source/ZipLib/streams/substream.h +++ b/src/third-parties/ziplib/Source/ZipLib/streams/substream.h @@ -1,6 +1,104 @@ #pragma once #include -#include "streambuffs/sub_streambuf.h" +// #include "streambuffs/sub_streambuf.h" + +#include +#include +#include + +template +class sub_streambuf : + public std::basic_streambuf +{ + public: + typedef std::basic_streambuf base_type; + typedef typename std::basic_streambuf::traits_type traits_type; + + typedef typename base_type::char_type char_type; + typedef typename base_type::int_type int_type; + typedef typename base_type::pos_type pos_type; + typedef typename base_type::off_type off_type; + + sub_streambuf() + : _inputStream(nullptr) + , _startPosition(0) + , _currentPosition(0) + , _endPosition(0) + { + + } + + sub_streambuf(std::basic_istream& input, pos_type startOffset, size_t length) + : sub_streambuf() + { + init(input, startOffset, length); + } + + void init(std::basic_istream& input, pos_type startOffset, size_t length) + { + _inputStream = &input; + _startPosition = startOffset; + _currentPosition = startOffset; + _endPosition = startOffset + static_cast(length); + _internalBuffer = new ELEM_TYPE[INTERNAL_BUFFER_SIZE]; + + // set stream buffer + ELEM_TYPE* endOfOutputBuffer = _internalBuffer + INTERNAL_BUFFER_SIZE; + this->setg(endOfOutputBuffer, endOfOutputBuffer, endOfOutputBuffer); + } + + bool is_init() const + { + return (_inputStream != nullptr && _internalBuffer != nullptr); + } + + virtual ~sub_streambuf() + { + if (_internalBuffer != nullptr) + { + delete[] _internalBuffer; + } + } + + protected: + int_type underflow() override + { + // buffer exhausted + if (this->gptr() >= this->egptr()) + { + ELEM_TYPE* base = _internalBuffer; + + _inputStream->seekg(_currentPosition, std::ios::beg); + _inputStream->read(_internalBuffer, std::min(static_cast(INTERNAL_BUFFER_SIZE), static_cast(_endPosition - _currentPosition))); + size_t n = static_cast(_inputStream->gcount()); + + _currentPosition += n; + + if (n == 0) + { + return traits_type::eof(); + } + + // set buffer pointers + this->setg(base, base, base + n); + } + + return traits_type::to_int_type(*this->gptr()); + } + + private: + enum : size_t + { + INTERNAL_BUFFER_SIZE = 1 << 15 + }; + + ELEM_TYPE* _internalBuffer; + + std::basic_istream* _inputStream; + pos_type _startPosition; + pos_type _currentPosition; + pos_type _endPosition; +}; /** * \brief Basic input substream. Creates a virtual stream over an existing input stream. diff --git a/src/third-parties/ziplib/Source/ZipLib/streams/teestream.h b/src/third-parties/ziplib/Source/ZipLib/streams/teestream.h index c70b9b2..d89fbf3 100644 --- a/src/third-parties/ziplib/Source/ZipLib/streams/teestream.h +++ b/src/third-parties/ziplib/Source/ZipLib/streams/teestream.h @@ -1,7 +1,70 @@ #pragma once #include #include -#include "streambuffs/tee_streambuff.h" +// #include "streambuffs/tee_streambuff.h" + +#include +#include + +template +class tee_streambuf: + public std::basic_streambuf +{ + public: + typedef std::basic_streambuf base_type; + typedef typename std::basic_streambuf::traits_type traits_type; + + typedef typename base_type::char_type char_type; + typedef typename base_type::int_type int_type; + typedef typename base_type::pos_type pos_type; + typedef typename base_type::off_type off_type; + + tee_streambuf& bind(base_type* sb) + { + _sbCollection.push_back(sb); + return *this; + } + + tee_streambuf& bind(std::basic_ostream& stream) + { + _sbCollection.push_back(stream.rdbuf()); + return *this; + } + + protected: + int_type overflow(int_type c = traits_type::eof()) override + { + bool failed = false; + + for (auto* sb : _sbCollection) + { + if (sb->sputc(c) == traits_type::eof()) + { + failed = true; + } + } + + return failed ? traits_type::eof() : c; + } + + int sync() override + { + bool failed = false; + + for (auto* sb : _sbCollection) + { + if (sb->pubsync() == -1) + { + failed = true; + } + } + + return failed ? -1 : 0; + } + + private: + std::vector _sbCollection; +}; /** * \brief Basic teestream. Distributes the input data into every bound output stream. diff --git a/src/third-parties/ziplib/Source/ZipLib/streams/zip_cryptostream.h b/src/third-parties/ziplib/Source/ZipLib/streams/zip_cryptostream.h index c50396c..891cfa6 100644 --- a/src/third-parties/ziplib/Source/ZipLib/streams/zip_cryptostream.h +++ b/src/third-parties/ziplib/Source/ZipLib/streams/zip_cryptostream.h @@ -1,6 +1,291 @@ #pragma once #include -#include "streambuffs/zip_crypto_streambuf.h" +// #include "streambuffs/zip_crypto_streambuf.h" + +#include +#include +#include +#include +#include +#include + +#include "../extlibs/zlib/zlib.h" + +template +class zip_crypto_streambuf + : public std::basic_streambuf +{ + public: + typedef std::basic_streambuf base_type; + typedef typename std::basic_streambuf::traits_type traits_type; + + typedef typename base_type::char_type char_type; + typedef typename base_type::int_type int_type; + typedef typename base_type::pos_type pos_type; + typedef typename base_type::off_type off_type; + + zip_crypto_streambuf() + : _internalBuffer(nullptr) + , _inputStream(nullptr) + , _outputStream(nullptr) + , _finalByte(-1) + , _encryptionHeaderRead(false) + , _encryptionHeaderWritten(false) + { + static_assert(sizeof(ELEM_TYPE) == 1, "size of ELEM_TYPE must be 1"); + } + + zip_crypto_streambuf(std::basic_ostream& stream, const ELEM_TYPE* password) + : zip_crypto_streambuf() + { + static_assert(sizeof(ELEM_TYPE) == 1, "size of ELEM_TYPE must be 1"); + init(stream, password); + } + + zip_crypto_streambuf(std::basic_istream& stream, const ELEM_TYPE* password) + : zip_crypto_streambuf() + { + static_assert(sizeof(ELEM_TYPE) == 1, "size of ELEM_TYPE must be 1"); + init(stream, password); + } + + ~zip_crypto_streambuf() + { + if (_internalBuffer != nullptr) + { + delete[] _internalBuffer; + } + } + + void init(std::basic_ostream& stream, const ELEM_TYPE* password) + { + _inputStream = nullptr; + _outputStream = &stream; + _finalByte = -1; + _encryptionHeaderRead = false; + _encryptionHeaderWritten = false; + + init_internal(password); + } + + void init(std::basic_istream& stream, const ELEM_TYPE* password) + { + _inputStream = &stream; + _outputStream = nullptr; + _finalByte = -1; + _encryptionHeaderRead = false; + _encryptionHeaderWritten = false; + + init_internal(password); + } + + bool is_init() const + { + return (_inputStream != nullptr || _outputStream != nullptr); + } + + void set_final_byte(uint8_t c) + { + _finalByte = int(c); + } + + bool has_correct_password() const + { + return (uint8_t(_finalByte) == _encryptionHeader.u8[11]); + } + + bool prepare_for_decryption() + { + if (_inputStream == nullptr) + { + return false; + } + + _inputStream->read(reinterpret_cast(&_encryptionHeader), sizeof(_encryptionHeader)); + finish_decryption_header(); + _encryptionHeaderRead = true; + + return has_correct_password(); + } + + protected: + int_type overflow(int_type c = traits_type::eof()) override + { + bool is_eof = traits_type::eq_int_type(c, traits_type::eof()); + + // buffering would be great, maybe? + if (!is_eof) + { + if (!_encryptionHeaderWritten) + { + finish_encryption_header(); + _outputStream->write(reinterpret_cast(&_encryptionHeader), sizeof(_encryptionHeader)); + _encryptionHeaderWritten = true; + } + + uint8_t encryptedByte = encrypt_byte(uint8_t(c)); + _outputStream->write(reinterpret_cast(&encryptedByte), sizeof(encryptedByte)); + + return encryptedByte; + } + + return traits_type::eof(); + } + + int_type underflow() override + { + // if we're going to decrypt, + // the call to prepare_for_decryption() is needed + if (!_encryptionHeaderRead) + { + return traits_type::eof(); + } + + // buffer exhausted + if (this->gptr() >= this->egptr()) + { + ELEM_TYPE* base = _internalBuffer; + _inputStream->read(_internalBuffer, INTERNAL_BUFFER_SIZE); + + size_t n = static_cast(_inputStream->gcount()); + + if (n == 0) + { + return traits_type::eof(); + } + + decrypt_internal_buffer(n); + + // set buffer pointers + this->setg(base, base, base + n); + } + + return traits_type::to_int_type(*this->gptr()); + } + + int sync() override + { + return _outputStream->rdbuf()->pubsync(); + } + + private: + static uint32_t crc32_byte(uint32_t prevCrc32, uint8_t c) + { + return uint32_t(get_crc_table()[(prevCrc32 ^ c) & 0xff] ^ (prevCrc32 >> 8)); + } + + bool init_internal(const ELEM_TYPE* password) + { + assert(password != nullptr); + + _keys.u32[0] = 0x12345678; + _keys.u32[1] = 0x23456789; + _keys.u32[2] = 0x34567890; + + do + { + update_keys(uint8_t(*password++)); + } while (*password != '\0'); + + // make encryption header + auto seed = std::chrono::system_clock::now().time_since_epoch().count(); + std::mt19937 generator(static_cast(seed)); + + _encryptionHeader.u32[0] = generator(); + _encryptionHeader.u32[1] = generator(); + _encryptionHeader.u32[2] = generator(); + + // set stream buffer + _internalBuffer = new ELEM_TYPE[INTERNAL_BUFFER_SIZE]; + ELEM_TYPE* endOfInternalBuffer = _internalBuffer + INTERNAL_BUFFER_SIZE; + this->setg(endOfInternalBuffer, endOfInternalBuffer, endOfInternalBuffer); + + return true; + } + + void finish_encryption_header() + { + assert(_finalByte != -1); + + _encryptionHeader.u8[11] = uint8_t(_finalByte); + + for (uint8_t& c : _encryptionHeader.u8) + { + c = encrypt_byte(c); + } + } + + void finish_decryption_header() + { + for (uint8_t& c : _encryptionHeader.u8) + { + c = decrypt_byte(c); + } + } + + uint8_t encrypt_byte(uint8_t c) + { + uint8_t result = uint8_t(c ^ get_magic_byte()); + + update_keys(c); + + return result; + } + + uint8_t decrypt_byte(uint8_t c) + { + uint8_t result = uint8_t(c ^ get_magic_byte()); + + update_keys(result); + + return result; + } + + void decrypt_internal_buffer(size_t length) + { + for (size_t i = 0; i < length; ++i) + { + _internalBuffer[i] = decrypt_byte(_internalBuffer[i]); + } + } + + void update_keys(uint8_t c) + { + _keys.u32[0] = crc32_byte(_keys.u32[0], c); + _keys.u32[1] = _keys.u32[1] + uint8_t(_keys.u32[0] & 0x000000ff); + _keys.u32[1] = _keys.u32[1] * 0x08088405 + 1; + _keys.u32[2] = crc32_byte(_keys.u32[2], _keys.u32[1] >> 24); + } + + uint8_t get_magic_byte() const + { + uint16_t t = uint16_t(uint16_t(_keys.u32[2] & 0xFFFF) | 2); + return uint8_t((t * (t ^ 1)) >> 8); + } + + union encryption_header + { + uint8_t u8[12]; + uint32_t u32[3]; + }; + + ////////////////////////////////////////////////////////////////////////// + + enum : size_t + { + INTERNAL_BUFFER_SIZE = 1 << 15 + }; + + ELEM_TYPE* _internalBuffer; + + std::basic_istream* _inputStream; + std::basic_ostream* _outputStream; + encryption_header _keys; + encryption_header _encryptionHeader; + int _finalByte; + bool _encryptionHeaderRead; + bool _encryptionHeaderWritten; +}; template class basic_zip_cryptostream diff --git a/src/third-parties/ziplib/ziplib.xcodeproj/project.pbxproj b/src/third-parties/ziplib/ziplib.xcodeproj/project.pbxproj index 14b3b82..bb8e6c4 100644 --- a/src/third-parties/ziplib/ziplib.xcodeproj/project.pbxproj +++ b/src/third-parties/ziplib/ziplib.xcodeproj/project.pbxproj @@ -432,7 +432,7 @@ 5AA9E0D01C119EB6006470DD /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0710; + LastUpgradeCheck = 1010; ORGANIZATIONNAME = Readium; TargetAttributes = { 5AA9E0E81C119F19006470DD = { @@ -524,13 +524,23 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -568,13 +578,23 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -600,7 +620,7 @@ 5AA9E0F01C119F19006470DD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -610,7 +630,7 @@ 5AA9E0F11C119F19006470DD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; diff --git a/test/lcp-client-lib/tests/CertificateTest.cpp b/test/lcp-client-lib/tests/CertificateTest.cpp index 4e10330..ca0339f 100644 --- a/test/lcp-client-lib/tests/CertificateTest.cpp +++ b/test/lcp-client-lib/tests/CertificateTest.cpp @@ -40,7 +40,12 @@ namespace lcptest TEST(CertificateTest, CertificateDistributionPoints) { lcp::EncryptionProfilesManager profilesManager; + +#if ENABLE_PROFILE_NAMES lcp::IEncryptionProfile * profile = profilesManager.GetProfile("http://readium.org/lcp/profile-1.0"); +#else + lcp::IEncryptionProfile * profile = profilesManager.GetProfile(); +#endif //ENABLE_PROFILE_NAMES ASSERT_NE(profile, nullptr); @@ -55,7 +60,12 @@ namespace lcptest TEST(CertificateTest, CertificateRevocationList_) { lcp::EncryptionProfilesManager profilesManager; + +#if ENABLE_PROFILE_NAMES lcp::IEncryptionProfile * profile = profilesManager.GetProfile("http://readium.org/lcp/profile-1.0"); +#else + lcp::IEncryptionProfile * profile = profilesManager.GetProfile(); +#endif //ENABLE_PROFILE_NAMES ASSERT_NE(profile, nullptr); @@ -84,7 +94,12 @@ namespace lcptest TEST(CertificateTest, CertificateParse) { lcp::EncryptionProfilesManager profilesManager; + +#if ENABLE_PROFILE_NAMES lcp::IEncryptionProfile * profile = profilesManager.GetProfile("http://readium.org/lcp/profile-1.0"); +#else + lcp::IEncryptionProfile * profile = profilesManager.GetProfile(); +#endif //ENABLE_PROFILE_NAMES ASSERT_NE(profile, nullptr); @@ -98,7 +113,12 @@ namespace lcptest TEST(CertificateTest, CertificateVerifyByRoot) { lcp::EncryptionProfilesManager profilesManager; + +#if ENABLE_PROFILE_NAMES lcp::IEncryptionProfile * profile = profilesManager.GetProfile("http://readium.org/lcp/profile-1.0"); +#else + lcp::IEncryptionProfile * profile = profilesManager.GetProfile(); +#endif //ENABLE_PROFILE_NAMES ASSERT_NE(profile, nullptr); @@ -111,7 +131,12 @@ namespace lcptest TEST(CertificateTest, CertificateVerifySignature) { lcp::EncryptionProfilesManager profilesManager; + +#if ENABLE_PROFILE_NAMES lcp::IEncryptionProfile * profile = profilesManager.GetProfile("http://readium.org/lcp/profile-1.0"); +#else + lcp::IEncryptionProfile * profile = profilesManager.GetProfile(); +#endif //ENABLE_PROFILE_NAMES ASSERT_NE(profile, nullptr); diff --git a/test/lcp-client-lib/tests/CryptoppCryptoProviderTest.cpp b/test/lcp-client-lib/tests/CryptoppCryptoProviderTest.cpp index ec64cca..e5d65a5 100644 --- a/test/lcp-client-lib/tests/CryptoppCryptoProviderTest.cpp +++ b/test/lcp-client-lib/tests/CryptoppCryptoProviderTest.cpp @@ -60,6 +60,7 @@ namespace lcptest ASSERT_EQ(lcp::StatusCode::ErrorCommonSuccess, res.Code); } +#if ENABLE_PROFILE_NAMES TEST_F(CryptoppCryptoProviderTest, VerifyLicense_Return_ErrorCommonEncryptionProfileNotFound) { FakeCryptoImpl crypto; @@ -69,6 +70,7 @@ namespace lcptest lcp::Status res = m_cryptoProvider->VerifyLicense(TestCertificate, &license); ASSERT_EQ(lcp::StatusCode::ErrorCommonEncryptionProfileNotFound, res.Code); } +#endif //ENABLE_PROFILE_NAMES TEST_F(CryptoppCryptoProviderTest, VerifyLicense_Return_ErrorOpeningNoRootCertificate) {