diff --git a/CMakeLists.txt b/CMakeLists.txt
index 770711c67..ffa18211e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,7 @@
cmake_minimum_required(VERSION 3.16)
+if(POLICY CMP0122)
+ cmake_policy(SET CMP0122 NEW)
+endif()
project(libdigidocpp VERSION 3.15.0)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)
diff --git a/README.md b/README.md
index 20372ffca..4cd2455fd 100644
--- a/README.md
+++ b/README.md
@@ -21,6 +21,9 @@
* doxygen - Optional, for API documentation
* libboost-test-dev - Optional, for unittests
+ * swig - Optional, for C#, Java and python bindings
+ * libpython3-dev, python3-distutils - Optional, for python bindings
+ * openjdk-8-jdk-headless - Optional, for Java bindings
2. Fetch the source
@@ -64,6 +67,11 @@
brew install xsd
brew unlink xerces-c
+ * doxygen - Optional, for API documentation
+ * boost - Optional, for unittests
+ * swig - Optional, for C# and Java bindings
+ * openjdk - Optional, for Java bindings
+
5. Configure, build and install (available targets: osx, ios, iossimulator, androidarm, androidarm64, androidx86)
./build-library.sh osx install
@@ -80,6 +88,8 @@
* [Swig](http://swig.org/download.html) - Optional, for C# and Java bindings
* [Doxygen](https://www.doxygen.nl/download.html) - Optional, for generationg documentation
* [Wix toolset](http://wixtoolset.org/releases/) - Optional, for creating Windows installation packages
+ * [Python](https://www.python.org/downloads/) - Optional, for Python bindings
+ * [Java](https://www.oracle.com/java/technologies/downloads/) - Optional, for Java bindings
Toolset:
* 141 - Visual Studio 2017
diff --git a/debian/control b/debian/control
index baf105b60..246111202 100644
--- a/debian/control
+++ b/debian/control
@@ -67,13 +67,46 @@ Architecture: any
Section: libdevel
Depends:
libdigidocpp1 (= ${binary:Version}),
- python3,
${misc:Depends},
${shlibs:Depends}
Description: DigiDoc digital signature library development files
This package contains files necessary for developing applications with the
DigiDoc digital signature library.
+Package: libdigidocpp-csharp
+Architecture: any
+Section: libdevel
+Depends:
+ libdigidocpp1 (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends}
+Description: DigiDoc digital signature C# bindings
+ This package contains files necessary for developing applications with the
+ DigiDoc digital signature library using C# bindings.
+
+Package: libdigidocpp-java
+Architecture: any
+Section: libdevel
+Depends:
+ libdigidocpp1 (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends}
+Description: DigiDoc digital signature java bindings
+ This package contains files necessary for developing applications with the
+ DigiDoc digital signature library using java bindings.
+
+Package: libdigidocpp-python
+Architecture: any
+Section: libdevel
+Depends:
+ libdigidocpp1 (= ${binary:Version}),
+ python3,
+ ${misc:Depends},
+ ${shlibs:Depends}
+Description: DigiDoc digital signature python bindings
+ This package contains files necessary for developing applications with the
+ DigiDoc digital signature library using python bindings.
+
Package: libdigidocpp-doc
Architecture: all
Section: doc
diff --git a/debian/libdigidocpp-csharp.install b/debian/libdigidocpp-csharp.install
new file mode 100644
index 000000000..8951eee3e
--- /dev/null
+++ b/debian/libdigidocpp-csharp.install
@@ -0,0 +1,2 @@
+usr/include/digidocpp_csharp/
+usr/lib/*/libdigidoc_csharp.so
diff --git a/debian/libdigidocpp-csharp.lintian-overrides b/debian/libdigidocpp-csharp.lintian-overrides
new file mode 100644
index 000000000..9c115fe91
--- /dev/null
+++ b/debian/libdigidocpp-csharp.lintian-overrides
@@ -0,0 +1 @@
+libdigidocpp-csharp: sharedobject-in-library-directory-missing-soname
diff --git a/debian/libdigidocpp-dev.triggers b/debian/libdigidocpp-csharp.triggers
similarity index 100%
rename from debian/libdigidocpp-dev.triggers
rename to debian/libdigidocpp-csharp.triggers
diff --git a/debian/libdigidocpp-dev.install b/debian/libdigidocpp-dev.install
index 139337ba2..15f32919e 100644
--- a/debian/libdigidocpp-dev.install
+++ b/debian/libdigidocpp-dev.install
@@ -1,4 +1,3 @@
-usr/include
-usr/lib/*/lib*.so
+usr/include/digidocpp/
+usr/lib/*/libdigidocpp.so
usr/lib/*/pkgconfig
-usr/lib/python*/dist-packages
diff --git a/debian/libdigidocpp-dev.lintian-overrides b/debian/libdigidocpp-dev.lintian-overrides
deleted file mode 100644
index 05fb4a880..000000000
--- a/debian/libdigidocpp-dev.lintian-overrides
+++ /dev/null
@@ -1 +0,0 @@
-libdigidocpp-dev: sharedobject-in-library-directory-missing-soname
diff --git a/debian/libdigidocpp-java.install b/debian/libdigidocpp-java.install
new file mode 100644
index 000000000..956814a87
--- /dev/null
+++ b/debian/libdigidocpp-java.install
@@ -0,0 +1,2 @@
+usr/include/ee/ria/libdigidocpp/
+usr/lib/*/libdigidoc_java.so
diff --git a/debian/libdigidocpp-java.lintian-overrides b/debian/libdigidocpp-java.lintian-overrides
new file mode 100644
index 000000000..7ccb60d5e
--- /dev/null
+++ b/debian/libdigidocpp-java.lintian-overrides
@@ -0,0 +1 @@
+libdigidocpp-java: sharedobject-in-library-directory-missing-soname
diff --git a/debian/libdigidocpp-java.triggers b/debian/libdigidocpp-java.triggers
new file mode 100644
index 000000000..dd8660367
--- /dev/null
+++ b/debian/libdigidocpp-java.triggers
@@ -0,0 +1 @@
+activate-noawait ldconfig
diff --git a/debian/libdigidocpp-python.install b/debian/libdigidocpp-python.install
new file mode 100644
index 000000000..2f63d6b64
--- /dev/null
+++ b/debian/libdigidocpp-python.install
@@ -0,0 +1 @@
+usr/lib/python3/dist-packages/
diff --git a/debian/libdigidocpp1.install b/debian/libdigidocpp1.install
index 3ddde5841..ed717308e 100644
--- a/debian/libdigidocpp1.install
+++ b/debian/libdigidocpp1.install
@@ -1 +1 @@
-usr/lib/*/lib*.so.*
+usr/lib/*/libdigidocpp.so.*
diff --git a/examples/DigiDocCSharp/DigiDocCSharp.csproj b/examples/DigiDocCSharp/DigiDocCSharp.csproj
index 5a6e4f4fb..9ed490dbe 100644
--- a/examples/DigiDocCSharp/DigiDocCSharp.csproj
+++ b/examples/DigiDocCSharp/DigiDocCSharp.csproj
@@ -33,6 +33,10 @@
TRACE
prompt
4
+ true
+
+
+ _WINDOWS
diff --git a/examples/DigiDocCSharp/Program.cs b/examples/DigiDocCSharp/Program.cs
index 1881511df..21f974150 100644
--- a/examples/DigiDocCSharp/Program.cs
+++ b/examples/DigiDocCSharp/Program.cs
@@ -4,36 +4,37 @@
using System;
using System.IO;
using System.Linq;
+using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using digidoc;
namespace DigiDocCSharp
{
- class Program
+ internal class Program
{
- static void Main(string[] args)
+ private static void Main(string[] args)
{
if (args.Length < 1)
{
Console.WriteLine("Missing document parameter");
- help();
+ Help();
return;
}
switch (args[0])
{
- case "add": add(args); return;
- case "extract": extract(Convert.ToInt32(args[1]), args[2]); return;
- case "sign": sign(args); return;
- case "websign": websign(args); return;
- case "verify": verify(args[1]); return;
- case "version": version(); return;
+ case "add": Add(args); return;
+ case "extract": Extract(Convert.ToInt32(args[1]), args[2]); return;
+ case "sign": Sign(args); return;
+ case "websign": Websign(args); return;
+ case "verify": Verify(args[1]); return;
+ case "version": Version(); return;
case "help":
- default: help(); return;
+ default: Help(); return;
}
}
- static void add(string[] args)
+ private static void Add(string[] args)
{
digidoc.digidoc.initialize();
try
@@ -41,7 +42,9 @@ static void add(string[] args)
Console.WriteLine("Creating file: " + args[args.Length - 1]);
Container b = Container.create(args[args.Length - 1]);
for (int i = 1; i < args.Length - 1; ++i)
+ {
b.addDataFile(args[i], "application/octet-stream");
+ }
b.save();
}
catch (Exception e)
@@ -51,7 +54,7 @@ static void add(string[] args)
digidoc.digidoc.terminate();
}
- static void extract(int index, string file)
+ private static void Extract(int index, string file)
{
digidoc.digidoc.initialize();
try
@@ -78,7 +81,7 @@ static void extract(int index, string file)
digidoc.digidoc.terminate();
}
- static void help()
+ private static void Help()
{
Console.WriteLine("DigiDocCSharp command [params]");
Console.WriteLine("Command:");
@@ -91,6 +94,9 @@ static void help()
Console.WriteLine(" datafile1 datafile2 ...");
Console.WriteLine(" file");
Console.WriteLine(" sign\t\tSigns file");
+#if !_WINDOWS
+ Console.WriteLine(" 12345");
+#endif
Console.WriteLine(" datafile1 datafile2 ...");
Console.WriteLine(" file");
Console.WriteLine(" websign\t\tSigns file");
@@ -99,20 +105,34 @@ static void help()
Console.WriteLine(" file");
Console.WriteLine(" verify\t\tVerifies document signature and shows info");
Console.WriteLine(" file");
- version();
+ Version();
}
- static void sign(string[] args)
+ private static void Sign(string[] args)
{
digidoc.digidoc.initialize();
try
{
- Console.WriteLine("Creating file: " + args[args.Length-1]);
+ Console.WriteLine("Creating file: " + args[args.Length - 1]);
Container b = Container.create(args[args.Length - 1]);
+#if _WINDOWS
for (int i = 1; i < args.Length - 1; ++i)
+#else
+ for (int i = 2; i < args.Length - 1; ++i)
+#endif
+ {
b.addDataFile(args[i], "application/octet-stream");
+ }
+#if _WINDOWS
using (WinSigner signer = new WinSigner())
+ {
+#else
+ using (PKCS11Signer signer = new PKCS11Signer())
+ {
+ signer.setPin(args[1]);
+#endif
b.sign(signer);
+ }
b.save();
}
catch (Exception e)
@@ -122,7 +142,7 @@ static void sign(string[] args)
digidoc.digidoc.terminate();
}
- static void websign(string[] args)
+ private static void Websign(string[] args)
{
digidoc.digidoc.initialize();
try
@@ -130,7 +150,9 @@ static void websign(string[] args)
Console.WriteLine("Creating file: " + args[args.Length - 1]);
Container b = Container.create(args[args.Length - 1]);
for (int i = 1; i < args.Length - 2; ++i)
+ {
b.addDataFile(args[i], "application/octet-stream");
+ }
X509Certificate cert = new X509Certificate();
cert.Import(args[args.Length - 2]);
@@ -142,7 +164,7 @@ static void websign(string[] args)
byte[] inputBuffer = new byte[1024];
Stream inputStream = Console.OpenStandardInput(inputBuffer.Length);
Console.SetIn(new StreamReader(inputStream, Console.InputEncoding, false, inputBuffer.Length));
- String hex = Console.ReadLine();
+ string hex = Console.ReadLine();
byte[] signature = Enumerable.Range(0, hex.Length / 2).Select(x => Convert.ToByte(hex.Substring(x * 2, 2), 16)).ToArray();
c.setSignatureValue(signature);
@@ -156,7 +178,7 @@ static void websign(string[] args)
digidoc.digidoc.terminate();
}
- static void verify(string file)
+ private static void Verify(string file)
{
digidoc.digidoc.initialize();
try
@@ -166,7 +188,9 @@ static void verify(string file)
Console.WriteLine("Files:");
foreach (DataFile d in b.dataFiles())
+ {
Console.WriteLine(" {0} - {1}", d.fileName(), d.mediaType());
+ }
Console.WriteLine();
Console.WriteLine("Signatures:");
@@ -175,8 +199,10 @@ static void verify(string file)
Console.WriteLine("Address: {0} {1} {2} {3}", s.city(), s.countryName(), s.stateOrProvince(), s.postalCode());
Console.Write("Role:");
- foreach (String role in s.signerRoles())
+ foreach (string role in s.signerRoles())
+ {
Console.Write(" " + role);
+ }
Console.WriteLine();
Console.WriteLine("Time: " + s.trustedSigningTime());
@@ -194,9 +220,10 @@ static void verify(string file)
digidoc.digidoc.terminate();
}
- static void version()
+ private static void Version()
{
- Console.WriteLine("DigiDocCSharp 0.3 libdigidocpp " + digidoc.digidoc.version());
+ Console.WriteLine("DigiDocCSharp " + Assembly.GetExecutingAssembly().GetName().Version +
+ " libdigidocpp " + digidoc.digidoc.version());
}
}
}
diff --git a/examples/DigiDocCSharp/Properties/AssemblyInfo.cs b/examples/DigiDocCSharp/Properties/AssemblyInfo.cs
index 2db9317f4..800b7c08a 100644
--- a/examples/DigiDocCSharp/Properties/AssemblyInfo.cs
+++ b/examples/DigiDocCSharp/Properties/AssemblyInfo.cs
@@ -1,5 +1,4 @@
using System.Reflection;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
@@ -32,5 +31,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: AssemblyVersion("0.4.0.0")]
+[assembly: AssemblyFileVersion("0.4.0.0")]
diff --git a/examples/android/app/build.gradle b/examples/android/app/build.gradle
index 674cb50f1..b6f3b899f 100644
--- a/examples/android/app/build.gradle
+++ b/examples/android/app/build.gradle
@@ -23,17 +23,13 @@ android {
}
}
compileOptions {
- targetCompatibility JavaVersion.VERSION_1_8
- sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_11
+ sourceCompatibility JavaVersion.VERSION_11
}
sourceSets.main.java.srcDirs += [libsPath + '.androidarm/include']
namespace 'ee.ria.libdigidocpp'
}
-dependencies {
- implementation 'androidx.core:core:1.9.0'
-}
-
task schemaZip(type:Zip) {
println "Create schema zip"
from (libsPath + '.androidarm/etc/digidocpp/schema/') {
diff --git a/examples/android/app/src/main/java/ee/ria/libdigidocpp/MainActivity.java b/examples/android/app/src/main/java/ee/ria/libdigidocpp/MainActivity.java
index cb6ae4b27..4265ad2c4 100644
--- a/examples/android/app/src/main/java/ee/ria/libdigidocpp/MainActivity.java
+++ b/examples/android/app/src/main/java/ee/ria/libdigidocpp/MainActivity.java
@@ -6,9 +6,6 @@
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
-import androidx.annotation.NonNull;
-import androidx.core.app.ActivityCompat;
-import androidx.core.content.ContextCompat;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.widget.EditText;
@@ -88,6 +85,7 @@ protected void onCreate(Bundle savedInstanceState) {
Container doc = Container.open(cache + "/test.bdoc");
content.append("DataFiles:\n");
+ assert doc != null;
for(DataFile file : doc.dataFiles()) {
content.append(file.fileName() + "\n");
}
@@ -105,8 +103,8 @@ protected void onCreate(Bundle savedInstanceState) {
}
// For testing
- if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
- ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_READWRITE_STORAGE);
+ if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
+ requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_READWRITE_STORAGE);
} else {
runTest(Environment.getExternalStorageDirectory());
}
@@ -142,7 +140,7 @@ public X509Certificate[] getAcceptedIssuers() {
}
@Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_READWRITE_STORAGE && grantResults.length > 0 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
runTest(Environment.getExternalStorageDirectory());
@@ -182,6 +180,7 @@ private void runTest(File path) {
try {
Log.i("VALIDATE", "Opening file " + file.getAbsolutePath());
Container doc = Container.open(file.getAbsolutePath());
+ assert doc != null;
for(DataFile dataFile : doc.dataFiles()) {
JSONObject f = new JSONObject();
f.put("f", dataFile.fileName());
diff --git a/examples/java/build.gradle b/examples/java/build.gradle
index ad564eae9..5b84adc1b 100755
--- a/examples/java/build.gradle
+++ b/examples/java/build.gradle
@@ -6,14 +6,6 @@ group 'ee.ria'
sourceCompatibility = 8
sourceSets.main.java.srcDirs += ['/Library/libdigidocpp/include', '/usr/include']
-repositories {
- mavenCentral()
-}
-
-dependencies {
- implementation 'javax.xml.bind:jaxb-api:2.3.1'
-}
-
jar {
archivesBaseName = 'libdigidocpp'
manifest {
diff --git a/examples/java/gradle/wrapper/gradle-wrapper.jar b/examples/java/gradle/wrapper/gradle-wrapper.jar
index e708b1c02..41d9927a4 100644
Binary files a/examples/java/gradle/wrapper/gradle-wrapper.jar and b/examples/java/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/examples/java/gradle/wrapper/gradle-wrapper.properties b/examples/java/gradle/wrapper/gradle-wrapper.properties
index aa991fcea..070cb702f 100644
--- a/examples/java/gradle/wrapper/gradle-wrapper.properties
+++ b/examples/java/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/examples/java/gradlew b/examples/java/gradlew
index 4f906e0c8..1b6c78733 100755
--- a/examples/java/gradlew
+++ b/examples/java/gradlew
@@ -1,7 +1,7 @@
-#!/usr/bin/env sh
+#!/bin/sh
#
-# Copyright 2015 the original author or authors.
+# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -17,67 +17,101 @@
#
##############################################################################
-##
-## Gradle start up script for UN*X
-##
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
##############################################################################
# Attempt to set APP_HOME
+
# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
+APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
+MAX_FD=maximum
warn () {
echo "$*"
-}
+} >&2
die () {
echo
echo "$*"
echo
exit 1
-}
+} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
+ JAVACMD=$JAVA_HOME/jre/sh/java
else
- JAVACMD="$JAVA_HOME/bin/java"
+ JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
- JAVACMD="java"
+ JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
@@ -106,80 +140,95 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
fi
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
-if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
# Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
fi
- i=`expr $i + 1`
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
done
- case $i in
- 0) set -- ;;
- 1) set -- "$args0" ;;
- 2) set -- "$args0" "$args1" ;;
- 3) set -- "$args0" "$args1" "$args2" ;;
- 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
- esac
fi
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=`save "$@"`
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
exec "$JAVACMD" "$@"
diff --git a/examples/java/src/main/java/ee/ria/libdigidocpp/libdigidocpp.java b/examples/java/src/main/java/ee/ria/libdigidocpp/libdigidocpp.java
index 50908a0d2..87fdfdc9d 100644
--- a/examples/java/src/main/java/ee/ria/libdigidocpp/libdigidocpp.java
+++ b/examples/java/src/main/java/ee/ria/libdigidocpp/libdigidocpp.java
@@ -8,18 +8,15 @@
import java.security.cert.X509Certificate;
import java.util.Scanner;
-import javax.xml.bind.DatatypeConverter;
-
public class libdigidocpp {
static {
System.loadLibrary("digidoc_java");
}
- public static void main(String[] args)
- {
+ public static void main(String[] args) {
if (args.length < 1)
{
- System.out.println("Missing document parameter");
+ System.out.println("Missing document parameter");
help();
return;
}
@@ -36,35 +33,27 @@ public static void main(String[] args)
}
}
- static void extract(int index, String file)
- {
+ static void extract(int index, String file) {
digidoc.initializeLib("libdigidocpp-java", "");
try
{
System.out.println("Opening file: " + file);
Container b = Container.open(file);
+ assert b != null;
DataFiles d = b.dataFiles();
String dest = FileSystems.getDefault().getPath(d.get(index).fileName()).toAbsolutePath().toString();
System.out.println("Extracting file " + d.get(index).fileName() + " to " + dest);
- try
- {
- d.get(index).saveAs(dest);
- }
- catch (Exception e)
- {
- System.out.println("Failed to copy file");
- System.out.println(e.getMessage());
- }
+ d.get(index).saveAs(dest);
}
catch (Exception e)
{
+ System.out.println("Failed to copy file");
System.out.println(e.getMessage());
}
digidoc.terminate();
}
- static void help()
- {
+ static void help() {
System.out.println("libdigidocpp-java command [params]");
System.out.println("Command:");
System.out.println(" extract\tExtracts files from document");
@@ -85,15 +74,15 @@ static void help()
version();
}
- static void sign(String[] args)
- {
- DigiDocConf conf = new DigiDocConf(null);
+ static void sign(String[] args) {
+ DigiDocConf conf = new DigiDocConf();
Conf.init(conf.transfer());
digidoc.initializeLib("libdigidocpp-java", "");
try
{
System.out.println("Creating file: " + args[args.length-1]);
Container b = Container.create(args[args.length - 1]);
+ assert b != null;
for (int i = 3; i < args.length - 1; ++i)
b.addDataFile(args[i], "application/octet-stream");
PKCS11Signer signer = new PKCS11Signer(args[1]);
@@ -108,13 +97,13 @@ static void sign(String[] args)
digidoc.terminate();
}
- static void websign(String[] args)
- {
+ static void websign(String[] args) {
digidoc.initializeLib("libdigidocpp-java", "");
try
{
System.out.println("Creating file: " + args[args.length - 1]);
Container b = Container.create(args[args.length - 1]);
+ assert b != null;
for (int i = 1; i < args.length - 2; ++i)
b.addDataFile(args[i], "application/octet-stream");
@@ -139,13 +128,13 @@ static void websign(String[] args)
digidoc.terminate();
}
- static void verify(String file)
- {
+ static void verify(String file) {
digidoc.initializeLib("libdigidocpp-java", "");
try
{
System.out.println("Opening file: " + file);
Container b = Container.open(file);
+ assert b != null;
System.out.println("Files:");
for (DataFile dataFile : b.dataFiles()) System.out.println(" " + dataFile.fileName() + " - " + dataFile.mediaType());
@@ -163,20 +152,27 @@ static void verify(String file)
System.out.println("Time: " + signature.trustedSigningTime());
System.out.println("Cert: " + toX509(signature.signingCertificateDer()).getSubjectDN().toString());
- signature.validate();
- System.out.println("Signature is valid");
+ try
+ {
+ signature.validate();
+ System.out.println("Signature is valid");
+ }
+ catch (Exception e)
+ {
+ System.out.println("Signature is invalid");
+ System.out.println(e.getMessage());
+ }
}
}
catch (Exception e)
{
- System.out.println("Signature is invalid");
System.out.println(e.getMessage());
}
digidoc.terminate();
}
static void version() {
- System.out.println("DigiDocCSharp 0.2 libdigidocpp " + digidoc.version());
+ System.out.println("DigiDocCSharp 0.3 libdigidocpp " + digidoc.version());
}
static X509Certificate toX509(byte[] der) throws CertificateException {
@@ -184,11 +180,24 @@ static X509Certificate toX509(byte[] der) throws CertificateException {
return (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(der));
}
- public static String toHex(byte[] array) {
- return DatatypeConverter.printHexBinary(array);
+ private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
+ static String toHex(byte[] bytes) {
+ char[] hex = new char[bytes.length * 2];
+ int i = 0;
+ for (byte b : bytes) {
+ hex[i++] = HEX_ARRAY[(b & 0xF0) >>> 4];
+ hex[i++] = HEX_ARRAY[b & 0x0F];
+ }
+ return new String(hex);
}
- public static byte[] fromHex(String s) {
- return DatatypeConverter.parseHexBinary(s);
+ static byte[] fromHex(String s) {
+ int len = s.length();
+ byte[] data = new byte[len / 2];
+ for (int i = 0; i < len; i += 2) {
+ data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ + Character.digit(s.charAt(i+1), 16));
+ }
+ return data;
}
}
diff --git a/libdigidocpp.i b/libdigidocpp.i
index c49f2f57c..f265c3322 100644
--- a/libdigidocpp.i
+++ b/libdigidocpp.i
@@ -207,6 +207,7 @@ extern "C"
%ignore digidoc::Conf::TSLCerts;
%ignore digidoc::ConfV2::verifyServiceCert;
%ignore digidoc::ConfV4::verifyServiceCerts;
+%ignore digidoc::ConfV5::TSCerts;
%ignore digidoc::Signer::cert;
%ignore digidoc::Signature::signingCertificate;
%ignore digidoc::Signature::OCSPCertificate;
@@ -223,7 +224,7 @@ extern "C"
%ignore digidoc::ConfV3::OCSPTMProfiles;
%ignore digidoc::Signature::Validator::warnings;
%ignore digidoc::Signature::OCSPNonce;
-// unique_ptr: There is no special smart pointer handling available for std::weak_ptr and std::unique_ptr yet.
+// std::unique_ptr is since swig 4.1
%ignore digidoc::Container::createPtr;
%ignore digidoc::Container::openPtr;
@@ -281,8 +282,7 @@ namespace std {
%include "crypto/Signer.h"
%include "crypto/PKCS12Signer.h"
%include "crypto/PKCS11Signer.h"
-#ifdef SWIGCSHARP
-// FIXME: figure out how to expose WinSigner on windows only. SWIG currently does not support this
+#ifdef SWIGWIN
%include "crypto/WinSigner.h"
#endif
%include "libdigidocpp.i.h"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index cf1d73f58..4b6ed0496 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -271,10 +271,11 @@ if(SWIG_FOUND)
if(JAVA_INCLUDE_PATH)
set(CMAKE_SWIG_FLAGS -package ee.ria.libdigidocpp)
set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/java)
- swig_add_library(digidoc_java TYPE SHARED LANGUAGE java SOURCES ../libdigidocpp.i)
+ swig_add_library(digidoc_java LANGUAGE java SOURCES ../libdigidocpp.i)
target_include_directories(digidoc_java PRIVATE ${JAVA_INCLUDE_PATH} $<$:${JAVA_INCLUDE_PATH2}>)
target_compile_definitions(digidoc_java PRIVATE TARGET_NAME="$")
target_link_libraries(digidoc_java digidocpp digidocpp_util digidocpp_ver)
+ set_property(TARGET digidoc_java PROPERTY SWIG_COMPILE_DEFINITIONS $<$:SWIGWIN>)
if(APPLE)
set_target_properties(digidoc_java PROPERTIES MACOSX_RPATH YES INSTALL_RPATH /Library/Frameworks)
install(TARGETS digidoc_java DESTINATION /Library/Java/Extensions)
@@ -289,9 +290,10 @@ if(SWIG_FOUND)
if(Python3_FOUND)
set(CMAKE_SWIG_FLAGS -py3)
set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR})
- swig_add_library(digidoc_python TYPE SHARED LANGUAGE python SOURCES ../libdigidocpp.i)
+ swig_add_library(digidoc_python LANGUAGE python SOURCES ../libdigidocpp.i)
target_compile_definitions(digidoc_python PRIVATE TARGET_NAME="$")
target_link_libraries(digidoc_python digidocpp digidocpp_util digidocpp_ver Python3::Module)
+ set_property(TARGET digidoc_python PROPERTY SWIG_COMPILE_DEFINITIONS $<$:SWIGWIN>)
#configure_file(setup.py.cmake setup.py)
#install(CODE "execute_process(COMMAND python3 ${CMAKE_CURRENT_BINARY_DIR}/setup.py install)")
if(NOT Python3_SITELIB)
@@ -308,14 +310,20 @@ if(SWIG_FOUND)
install(TARGETS digidoc_python DESTINATION ${Python3_SITELIB})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/digidoc.py DESTINATION ${Python3_SITELIB})
endif()
+
+ set(CMAKE_SWIG_FLAGS -dllimport digidoc_csharp -namespace digidoc)
+ set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/csharp)
+ swig_add_library(digidoc_csharp LANGUAGE csharp SOURCES ../libdigidocpp.i)
+ target_compile_definitions(digidoc_csharp PRIVATE TARGET_NAME="$")
+ target_link_libraries(digidoc_csharp digidocpp digidocpp_util digidocpp_ver)
+ set_target_properties(digidoc_csharp PROPERTIES
+ SWIG_COMPILE_DEFINITIONS $<$:SWIGWIN>
+ INSTALL_RPATH $<$:/Library/Frameworks>
+ PREFIX "${CMAKE_SHARED_LIBRARY_PREFIX}"
+ )
+ install(TARGETS digidoc_csharp DESTINATION ${CMAKE_INSTALL_LIBDIR})
+ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/csharp/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/digidocpp_csharp FILES_MATCHING PATTERN "*.cs")
if(WIN32)
- set(CMAKE_SWIG_FLAGS -dllimport digidoc_csharp -namespace digidoc)
- set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/csharp)
- swig_add_library(digidoc_csharp TYPE SHARED LANGUAGE csharp SOURCES ../libdigidocpp.i)
- target_compile_definitions(digidoc_csharp PRIVATE TARGET_NAME="$")
- target_link_libraries(digidoc_csharp digidocpp digidocpp_util digidocpp_ver)
- install(TARGETS digidoc_csharp DESTINATION ${CMAKE_INSTALL_BINDIR})
- install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/csharp/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/digidocpp_csharp FILES_MATCHING PATTERN "*.cs")
install(FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL)
endif()
endif()
diff --git a/src/libdigidocpp.i.h b/src/libdigidocpp.i.h
index a34698a82..7b862e1da 100644
--- a/src/libdigidocpp.i.h
+++ b/src/libdigidocpp.i.h
@@ -32,7 +32,7 @@ namespace digidoc {
class SWIGEXPORT DigiDocConf: public digidoc::XmlConfCurrent
{
public:
- DigiDocConf(std::string _cache)
+ DigiDocConf(std::string _cache = {})
: digidoc::XmlConfCurrent({}, _cache.empty() ? std::string() : util::File::path(_cache, "conf.xsd"))
, cache(std::move(_cache))
, _logFile(cache.empty() ? std::string() : cache + "/digidocpp.log") {}
@@ -54,6 +54,7 @@ class SWIGEXPORT DigiDocConf: public digidoc::XmlConfCurrent
cache + "/" + digidoc::util::File::fileName(digidoc::XmlConfCurrent::PKCS12Cert());
}
std::set OCSPTMProfiles() const final { return TMProfiles.value_or(digidoc::XmlConfCurrent::OCSPTMProfiles()); }
+ std::vector TSCerts() const final { return tsCerts.value_or(digidoc::XmlConfCurrent::TSCerts()); }
std::string TSLCache() const final { return cache.empty() ? digidoc::XmlConfCurrent::TSLCache() : cache; }
std::vector TSLCerts() const final { return tslCerts.value_or(digidoc::XmlConfCurrent::TSLCerts()); }
std::string TSLUrl() const final { return tslUrl.value_or(digidoc::XmlConfCurrent::TSLUrl()); }
@@ -68,44 +69,39 @@ class SWIGEXPORT DigiDocConf: public digidoc::XmlConfCurrent
void setLogLevel(int level) { _logLevel = level; }
void setLogFile(std::string file) { _logFile = std::move(file); }
- void setTSLCert(const std::vector &cert)
- {
- if(cert.empty()) tslCerts.emplace();
- else tslCerts = std::vector{ X509Cert(cert, X509Cert::Der) };
- }
- void addTSLCert(const std::vector &cert)
- {
- if(!tslCerts)
- setTSLCert(cert);
- else if(!cert.empty())
- tslCerts->emplace_back(cert, X509Cert::Der);
- }
+ void setTSCert(const std::vector &cert) { setCert(tsCerts, cert); }
+ void addTSCert(const std::vector &cert) { addCert(tsCerts, cert); }
+ void setTSLCert(const std::vector &cert) { setCert(tslCerts, cert); }
+ void addTSLCert(const std::vector &cert) { addCert(tslCerts, cert); }
void setTSLUrl(std::string url) { tslUrl = std::move(url); }
void setOCSPUrls(std::map urls) { OCSPUrls = std::move(urls); }
void setOCSPTMProfiles(const std::vector &_TMProfiles)
{
TMProfiles = {_TMProfiles.cbegin(), _TMProfiles.cend()};
}
- void setVerifyServiceCert(const std::vector &cert)
+ void setVerifyServiceCert(const std::vector &cert) { setCert(serviceCerts, cert); }
+ void addVerifyServiceCert(const std::vector &cert) { addCert(serviceCerts, cert); }
+
+private:
+ DISABLE_COPY(DigiDocConf);
+
+ static void setCert(std::optional> &certs, const std::vector &cert)
{
- if(cert.empty()) serviceCerts.emplace();
- else serviceCerts = std::vector{ X509Cert(cert, X509Cert::Der) };
+ if(cert.empty()) certs.emplace();
+ else certs = std::vector{ X509Cert(cert, X509Cert::Der) };
}
- void addVerifyServiceCert(const std::vector &cert)
+ static void addCert(std::optional> &certs, const std::vector &cert)
{
- if(!serviceCerts)
- setVerifyServiceCert(cert);
+ if(!certs)
+ setCert(certs, cert);
else if(!cert.empty())
- serviceCerts->emplace_back(cert, X509Cert::Der);
+ certs->emplace_back(cert, X509Cert::Der);
}
-private:
- DISABLE_COPY(DigiDocConf);
-
std::string cache;
std::optional _logLevel;
std::optional _logFile, serviceUrl, tslUrl;
- std::optional> tslCerts, serviceCerts;
+ std::optional> tslCerts, serviceCerts, tsCerts;
std::optional> TMProfiles;
std::optional> OCSPUrls;
};