mirror of https://github.com/apache/poi.git
merge trunk
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/hemf@1849036 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
commit
abe662db86
|
@ -91,7 +91,7 @@ subprojects {
|
||||||
// See https://github.com/melix/japicmp-gradle-plugin
|
// See https://github.com/melix/japicmp-gradle-plugin
|
||||||
apply plugin: 'me.champeau.gradle.japicmp'
|
apply plugin: 'me.champeau.gradle.japicmp'
|
||||||
|
|
||||||
version = '4.0.1-SNAPSHOT'
|
version = '4.0.2-SNAPSHOT'
|
||||||
ext {
|
ext {
|
||||||
japicmpversion = '4.0.0'
|
japicmpversion = '4.0.0'
|
||||||
}
|
}
|
||||||
|
@ -233,6 +233,11 @@ project('ooxml') {
|
||||||
compile 'org.bouncycastle:bcpkix-jdk15on:1.60'
|
compile 'org.bouncycastle:bcpkix-jdk15on:1.60'
|
||||||
compile 'com.github.virtuald:curvesapi:1.05'
|
compile 'com.github.virtuald:curvesapi:1.05'
|
||||||
|
|
||||||
|
// compile only, don't add it to our dist as it blows up the size
|
||||||
|
compile 'org.apache.xmlgraphics:batik-all:1.10'
|
||||||
|
compile 'xml-apis:xml-apis-ext:1.3.04'
|
||||||
|
compile 'org.apache.xmlgraphics:xmlgraphics-commons:2.3'
|
||||||
|
|
||||||
// for ooxml-lite, should we move this somewhere else?
|
// for ooxml-lite, should we move this somewhere else?
|
||||||
compile 'junit:junit:4.12'
|
compile 'junit:junit:4.12'
|
||||||
|
|
||||||
|
|
23
build.xml
23
build.xml
|
@ -217,6 +217,14 @@ under the License.
|
||||||
<property name="dsig.sl4j-api.jar" location="${compile.lib}/slf4j-api-1.7.25.jar"/>
|
<property name="dsig.sl4j-api.jar" location="${compile.lib}/slf4j-api-1.7.25.jar"/>
|
||||||
<property name="dsig.sl4j-api.url" value="${repository.m2}/maven2/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar"/>
|
<property name="dsig.sl4j-api.url" value="${repository.m2}/maven2/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar"/>
|
||||||
|
|
||||||
|
<!-- svg/batik libs - not part of the distribution -->
|
||||||
|
<property name="svg.batik-all.url" value="${repository.m2}/maven2/org/apache/xmlgraphics/batik-all/1.10/batik-all-1.10.jar"/>
|
||||||
|
<property name="svg.batik-all.jar" value="${compile.lib}/batik-all-1.10.jar"/>
|
||||||
|
<property name="svg.xml-apis-ext.url" value="${repository.m2}/maven2/xml-apis/xml-apis-ext/1.3.04/xml-apis-ext-1.3.04.jar"/>
|
||||||
|
<property name="svg.xml-apis-ext.jar" value="${compile.lib}/xml-apis-ext-1.3.04.jar"/>
|
||||||
|
<property name="svg.xmlgraphics-commons.url" value="${repository.m2}/maven2/org/apache/xmlgraphics/xmlgraphics-commons/2.3/xmlgraphics-commons-2.3.jar"/>
|
||||||
|
<property name="svg.xmlgraphics-commons.jar" value="${compile.lib}/xmlgraphics-commons-2.3.jar"/>
|
||||||
|
|
||||||
<!-- jars in the ooxml-lib directory, see the fetch-ooxml-jars target-->
|
<!-- jars in the ooxml-lib directory, see the fetch-ooxml-jars target-->
|
||||||
<property name="ooxml.curvesapi.jar" location="${ooxml.lib}/curvesapi-1.05.jar"/>
|
<property name="ooxml.curvesapi.jar" location="${ooxml.lib}/curvesapi-1.05.jar"/>
|
||||||
<property name="ooxml.curvesapi.url"
|
<property name="ooxml.curvesapi.url"
|
||||||
|
@ -395,6 +403,12 @@ under the License.
|
||||||
<pathelement location="${scratchpad.output.dir}" unless:true="${scratchpad.ignore}"/>
|
<pathelement location="${scratchpad.output.dir}" unless:true="${scratchpad.ignore}"/>
|
||||||
</path>
|
</path>
|
||||||
|
|
||||||
|
<path id="batik.classpath">
|
||||||
|
<pathelement location="${svg.batik-all.jar}"/>
|
||||||
|
<pathelement location="${svg.xml-apis-ext.jar}"/>
|
||||||
|
<pathelement location="${svg.xmlgraphics-commons.jar}"/>
|
||||||
|
</path>
|
||||||
|
|
||||||
<path id="ooxml-lite.classpath">
|
<path id="ooxml-lite.classpath">
|
||||||
<path refid="ooxml.base.classpath"/>
|
<path refid="ooxml.base.classpath"/>
|
||||||
<!-- instead of ooxml-xsds.jar use the filtered classes-->
|
<!-- instead of ooxml-xsds.jar use the filtered classes-->
|
||||||
|
@ -402,11 +416,13 @@ under the License.
|
||||||
<pathelement location="${ooxml.output.dir}"/>
|
<pathelement location="${ooxml.output.dir}"/>
|
||||||
<pathelement location="${ooxml.output.test.dir}"/>
|
<pathelement location="${ooxml.output.test.dir}"/>
|
||||||
<pathelement location="${main.output.test.dir}"/>
|
<pathelement location="${main.output.test.dir}"/>
|
||||||
|
<path refid="batik.classpath"/>
|
||||||
</path>
|
</path>
|
||||||
|
|
||||||
<path id="ooxml.classpath">
|
<path id="ooxml.classpath">
|
||||||
<pathelement location="${ooxml.xsds.jar}"/>
|
<pathelement location="${ooxml.xsds.jar}"/>
|
||||||
<path refid="ooxml.base.classpath"/>
|
<path refid="ooxml.base.classpath"/>
|
||||||
|
<path refid="batik.classpath"/>
|
||||||
</path>
|
</path>
|
||||||
|
|
||||||
<path id="ooxml.lite.verify.classpath">
|
<path id="ooxml.lite.verify.classpath">
|
||||||
|
@ -777,6 +793,9 @@ under the License.
|
||||||
<available file="${ooxml.test.reflections.jar}"/>
|
<available file="${ooxml.test.reflections.jar}"/>
|
||||||
<available file="${ooxml.test.guava.jar}"/>
|
<available file="${ooxml.test.guava.jar}"/>
|
||||||
<available file="${ooxml.test.javassist.jar}"/>
|
<available file="${ooxml.test.javassist.jar}"/>
|
||||||
|
<available file="${svg.xml-apis-ext.jar}"/>
|
||||||
|
<available file="${svg.batik-all.jar}"/>
|
||||||
|
<available file="${svg.xmlgraphics-commons.jar}"/>
|
||||||
</and>
|
</and>
|
||||||
<isset property="disconnected"/>
|
<isset property="disconnected"/>
|
||||||
</or>
|
</or>
|
||||||
|
@ -791,6 +810,9 @@ under the License.
|
||||||
<downloadfile src="${ooxml.test.reflections.url}" dest="${ooxml.test.reflections.jar}"/>
|
<downloadfile src="${ooxml.test.reflections.url}" dest="${ooxml.test.reflections.jar}"/>
|
||||||
<downloadfile src="${ooxml.test.guava.url}" dest="${ooxml.test.guava.jar}"/>
|
<downloadfile src="${ooxml.test.guava.url}" dest="${ooxml.test.guava.jar}"/>
|
||||||
<downloadfile src="${ooxml.test.javassist.url}" dest="${ooxml.test.javassist.jar}"/>
|
<downloadfile src="${ooxml.test.javassist.url}" dest="${ooxml.test.javassist.jar}"/>
|
||||||
|
<downloadfile src="${svg.batik-all.url}" dest="${svg.batik-all.jar}"/>
|
||||||
|
<downloadfile src="${svg.xml-apis-ext.url}" dest="${svg.xml-apis-ext.jar}"/>
|
||||||
|
<downloadfile src="${svg.xmlgraphics-commons.url}" dest="${svg.xmlgraphics-commons.jar}"/>
|
||||||
</target>
|
</target>
|
||||||
<target name="check-svn-jars">
|
<target name="check-svn-jars">
|
||||||
<condition property="svn.jars.present">
|
<condition property="svn.jars.present">
|
||||||
|
@ -932,6 +954,7 @@ under the License.
|
||||||
</xmlbean>
|
</xmlbean>
|
||||||
|
|
||||||
<local name="loaderMethod"/>
|
<local name="loaderMethod"/>
|
||||||
|
<!-- the space between "public static" is on purpose to prevent double execution -->
|
||||||
<property name="loaderMethod"><![CDATA[
|
<property name="loaderMethod"><![CDATA[
|
||||||
private static java.lang.ref.SoftReference<org.apache.xmlbeans.SchemaTypeLoader> typeLoader;
|
private static java.lang.ref.SoftReference<org.apache.xmlbeans.SchemaTypeLoader> typeLoader;
|
||||||
|
|
||||||
|
|
|
@ -70,9 +70,7 @@ def poijobs = [
|
||||||
'-Djava.locale.providers=JRE,CLDR'],
|
'-Djava.locale.providers=JRE,CLDR'],
|
||||||
skipcigame: true
|
skipcigame: true
|
||||||
],
|
],
|
||||||
[ name: 'POI-DSL-IBM-JDK', jdk: 'IBMJDK', trigger: triggerSundays,
|
[ name: 'POI-DSL-IBM-JDK', jdk: 'IBMJDK', trigger: triggerSundays, skipcigame: true
|
||||||
// some OOXML tests fail with strange XML parsing errors and missing JCE unlimited strength requirements
|
|
||||||
disabled: true, skipcigame: true
|
|
||||||
],
|
],
|
||||||
[ name: 'POI-DSL-old-Xerces', trigger: triggerSundays,
|
[ name: 'POI-DSL-old-Xerces', trigger: triggerSundays,
|
||||||
shell: "test -f ${xercesLib} || wget -O ${xercesLib} ${xercesUrl}\n",
|
shell: "test -f ${xercesLib} || wget -O ${xercesLib} ${xercesUrl}\n",
|
||||||
|
|
|
@ -185,5 +185,12 @@
|
||||||
<version>1.19</version>
|
<version>1.19</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<!-- don't add it to the distribution -->
|
||||||
|
<groupId>org.apache.xmlgraphics</groupId>
|
||||||
|
<artifactId>batik-all</artifactId>
|
||||||
|
<version>1.10</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -268,9 +268,7 @@
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<target>
|
<target>
|
||||||
<property name="xmlbean.sources.dir"
|
<!-- the space between "public static" is on purpose to prevent double execution -->
|
||||||
location="${basedir}/target/generated-sources/xmlbeans"/>
|
|
||||||
|
|
||||||
<property name="loaderMethod"><![CDATA[
|
<property name="loaderMethod"><![CDATA[
|
||||||
private static java.lang.ref.SoftReference<org.apache.xmlbeans.SchemaTypeLoader> typeLoader;
|
private static java.lang.ref.SoftReference<org.apache.xmlbeans.SchemaTypeLoader> typeLoader;
|
||||||
|
|
||||||
|
@ -285,23 +283,24 @@
|
||||||
|
|
||||||
public static \2 newInstance\(\) \{]]></property>
|
public static \2 newInstance\(\) \{]]></property>
|
||||||
|
|
||||||
|
<fileset id="xsrc" dir="${basedir}/target/generated-sources/xmlbeans" includes="**/*.java" excludes="**/impl/**"/>
|
||||||
|
|
||||||
<replaceregexp byline="true"
|
<replaceregexp byline="true"
|
||||||
match="(\s*)public static ([^ ]+) newInstance\(\) \{"
|
match="(\s*)public static ([^ ]+) newInstance\(\) \{"
|
||||||
replace="${loaderMethod}">
|
replace="${loaderMethod}">
|
||||||
<fileset dir="${xmlbean.sources.dir}" includes="**/*.java"
|
<fileset refid="xsrc"/>
|
||||||
excludes="**/impl/**"/>
|
|
||||||
</replaceregexp>
|
</replaceregexp>
|
||||||
|
|
||||||
<replace dir="${xmlbean.sources.dir}" includes="**/*.java"
|
<replace>
|
||||||
excludes="**/impl/**">
|
<fileset refid="xsrc"/>
|
||||||
<replacetoken>org.apache.xmlbeans.XmlBeans.getContextTypeLoader
|
<replacetoken>org.apache.xmlbeans.XmlBeans.getContextTypeLoader
|
||||||
</replacetoken>
|
</replacetoken>
|
||||||
<replacevalue>getTypeLoader</replacevalue>
|
<replacevalue>getTypeLoader</replacevalue>
|
||||||
</replace>
|
</replace>
|
||||||
|
|
||||||
<!-- remove deprecated warnings, as we prefer the array methods - see #56854 -->
|
<!-- remove deprecated warnings, as we prefer the array methods - see #56854 -->
|
||||||
<replace dir="${xmlbean.sources.dir}" includes="**/*.java"
|
<replace>
|
||||||
excludes="**/impl/**">
|
<fileset refid="xsrc"/>
|
||||||
<replacetoken><![CDATA[ * @deprecated
|
<replacetoken><![CDATA[ * @deprecated
|
||||||
]]></replacetoken>
|
]]></replacetoken>
|
||||||
</replace>
|
</replace>
|
||||||
|
|
|
@ -212,6 +212,12 @@ public class TestAllFiles {
|
||||||
HANDLERS.put("spreadsheet/BigSSTRecordCR", new NullFileHandler());
|
HANDLERS.put("spreadsheet/BigSSTRecordCR", new NullFileHandler());
|
||||||
HANDLERS.put("spreadsheet/test_properties1", new NullFileHandler());
|
HANDLERS.put("spreadsheet/test_properties1", new NullFileHandler());
|
||||||
|
|
||||||
|
// keystore files
|
||||||
|
HANDLERS.put(".pfx", new NullFileHandler());
|
||||||
|
HANDLERS.put(".pem", new NullFileHandler());
|
||||||
|
HANDLERS.put(".jks", new NullFileHandler());
|
||||||
|
HANDLERS.put(".pkcs12", new NullFileHandler());
|
||||||
|
|
||||||
Map<String,String> passmap = new HashMap<>();
|
Map<String,String> passmap = new HashMap<>();
|
||||||
passmap.put("slideshow/Password_Protected-hello.ppt", "hello");
|
passmap.put("slideshow/Password_Protected-hello.ppt", "hello");
|
||||||
passmap.put("slideshow/Password_Protected-56-hello.ppt", "hello");
|
passmap.put("slideshow/Password_Protected-56-hello.ppt", "hello");
|
||||||
|
|
|
@ -46,7 +46,10 @@ public interface PictureData {
|
||||||
/** WordPerfect graphics (.wpg) */
|
/** WordPerfect graphics (.wpg) */
|
||||||
WPG(-1,12,"image/x-wpg",".wpg"),
|
WPG(-1,12,"image/x-wpg",".wpg"),
|
||||||
/** Microsoft Windows Media Photo image (.wdp) */
|
/** Microsoft Windows Media Photo image (.wdp) */
|
||||||
WDP(-1,13,"image/vnd.ms-photo",".wdp");
|
WDP(-1,13,"image/vnd.ms-photo",".wdp"),
|
||||||
|
/** Scalable vector graphics (.svg) - supported by Office 2016 and higher */
|
||||||
|
SVG(-1, -1, "image/svg+xml", ".svg")
|
||||||
|
;
|
||||||
|
|
||||||
public final int nativeId, ooxmlId;
|
public final int nativeId, ooxmlId;
|
||||||
public final String contentType,extension;
|
public final String contentType,extension;
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/* ====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
package org.apache.poi.poifs.crypt.dsig;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.poi.ooxml.POIXMLDocumentPart;
|
||||||
|
import org.apache.poi.ooxml.POIXMLRelation;
|
||||||
|
import org.apache.poi.openxml4j.opc.ContentTypes;
|
||||||
|
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
|
||||||
|
|
||||||
|
public class DSigRelation extends POIXMLRelation {
|
||||||
|
/**
|
||||||
|
* A map to lookup POIXMLRelation by its relation type
|
||||||
|
*/
|
||||||
|
private static final Map<String, DSigRelation> _table = new HashMap<>();
|
||||||
|
|
||||||
|
public static final DSigRelation ORIGIN_SIGS = new DSigRelation(
|
||||||
|
ContentTypes.DIGITAL_SIGNATURE_ORIGIN_PART,
|
||||||
|
PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN,
|
||||||
|
"/_xmlsignatures/origin.sigs", null
|
||||||
|
);
|
||||||
|
|
||||||
|
public static final DSigRelation SIG = new DSigRelation(
|
||||||
|
ContentTypes.DIGITAL_SIGNATURE_XML_SIGNATURE_PART,
|
||||||
|
PackageRelationshipTypes.DIGITAL_SIGNATURE,
|
||||||
|
"/_xmlsignatures/sig#.xml", null
|
||||||
|
);
|
||||||
|
|
||||||
|
private DSigRelation(String type, String rel, String defaultName, Class<? extends POIXMLDocumentPart> cls) {
|
||||||
|
super(type, rel, defaultName, cls);
|
||||||
|
_table.put(rel, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get POIXMLRelation by relation type
|
||||||
|
*
|
||||||
|
* @param rel relation type, for example,
|
||||||
|
* <code>http://schemas.openxmlformats.org/officeDocument/2006/relationships/image</code>
|
||||||
|
* @return registered POIXMLRelation or null if not found
|
||||||
|
*/
|
||||||
|
public static DSigRelation getInstance(String rel) {
|
||||||
|
return _table.get(rel);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -174,6 +174,13 @@ public class SignatureConfig {
|
||||||
*/
|
*/
|
||||||
private boolean updateConfigOnValidate = false;
|
private boolean updateConfigOnValidate = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if true, the signature is added to the existing signatures
|
||||||
|
*
|
||||||
|
* @since POI 4.0.2
|
||||||
|
*/
|
||||||
|
private boolean allowMultipleSignatures = false;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inits and checks the config object.
|
* Inits and checks the config object.
|
||||||
|
@ -1008,4 +1015,25 @@ public class SignatureConfig {
|
||||||
public void setUpdateConfigOnValidate(boolean updateConfigOnValidate) {
|
public void setUpdateConfigOnValidate(boolean updateConfigOnValidate) {
|
||||||
this.updateConfigOnValidate = updateConfigOnValidate;
|
this.updateConfigOnValidate = updateConfigOnValidate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true, if multiple signatures can be attached
|
||||||
|
*
|
||||||
|
* @since POI 4.0.2
|
||||||
|
*/
|
||||||
|
public boolean isAllowMultipleSignatures() {
|
||||||
|
return allowMultipleSignatures;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activate multiple signatures
|
||||||
|
*
|
||||||
|
* @param allowMultipleSignatures if true, the signature will be added,
|
||||||
|
* otherwise all existing signatures will be replaced by the current
|
||||||
|
*
|
||||||
|
* @since POI 4.0.2
|
||||||
|
*/
|
||||||
|
public void setAllowMultipleSignatures(boolean allowMultipleSignatures) {
|
||||||
|
this.allowMultipleSignatures = allowMultipleSignatures;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -59,7 +59,6 @@ import org.apache.jcp.xml.dsig.internal.dom.DOMSignedInfo;
|
||||||
import org.apache.jcp.xml.dsig.internal.dom.DOMSubTreeData;
|
import org.apache.jcp.xml.dsig.internal.dom.DOMSubTreeData;
|
||||||
import org.apache.poi.EncryptedDocumentException;
|
import org.apache.poi.EncryptedDocumentException;
|
||||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||||
import org.apache.poi.openxml4j.opc.ContentTypes;
|
|
||||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
import org.apache.poi.openxml4j.opc.PackagePartName;
|
import org.apache.poi.openxml4j.opc.PackagePartName;
|
||||||
|
@ -377,9 +376,8 @@ public class SignatureInfo implements SignatureConfigurable {
|
||||||
xmlSignContext.setURIDereferencer(uriDereferencer);
|
xmlSignContext.setURIDereferencer(uriDereferencer);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<String,String> me : signatureConfig.getNamespacePrefixes().entrySet()) {
|
signatureConfig.getNamespacePrefixes().forEach(xmlSignContext::putNamespacePrefix);
|
||||||
xmlSignContext.putNamespacePrefix(me.getKey(), me.getValue());
|
|
||||||
}
|
|
||||||
xmlSignContext.setDefaultNamespacePrefix("");
|
xmlSignContext.setDefaultNamespacePrefix("");
|
||||||
// signatureConfig.getNamespacePrefixes().get(XML_DIGSIG_NS));
|
// signatureConfig.getNamespacePrefixes().get(XML_DIGSIG_NS));
|
||||||
|
|
||||||
|
@ -516,9 +514,7 @@ public class SignatureInfo implements SignatureConfigurable {
|
||||||
protected void writeDocument(Document document) throws MarshalException {
|
protected void writeDocument(Document document) throws MarshalException {
|
||||||
XmlOptions xo = new XmlOptions();
|
XmlOptions xo = new XmlOptions();
|
||||||
Map<String,String> namespaceMap = new HashMap<>();
|
Map<String,String> namespaceMap = new HashMap<>();
|
||||||
for(Map.Entry<String,String> entry : signatureConfig.getNamespacePrefixes().entrySet()){
|
signatureConfig.getNamespacePrefixes().forEach((k,v) -> namespaceMap.put(v,k));
|
||||||
namespaceMap.put(entry.getValue(), entry.getKey());
|
|
||||||
}
|
|
||||||
xo.setSaveSuggestedPrefixes(namespaceMap);
|
xo.setSaveSuggestedPrefixes(namespaceMap);
|
||||||
xo.setUseDefaultNamespace();
|
xo.setUseDefaultNamespace();
|
||||||
|
|
||||||
|
@ -530,43 +526,58 @@ public class SignatureInfo implements SignatureConfigurable {
|
||||||
*/
|
*/
|
||||||
OPCPackage pkg = signatureConfig.getOpcPackage();
|
OPCPackage pkg = signatureConfig.getOpcPackage();
|
||||||
|
|
||||||
PackagePartName sigPartName, sigsPartName;
|
|
||||||
try {
|
try {
|
||||||
// <Override PartName="/_xmlsignatures/sig1.xml" ContentType="application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"/>
|
|
||||||
sigPartName = PackagingURIHelper.createPartName("/_xmlsignatures/sig1.xml");
|
|
||||||
// <Default Extension="sigs" ContentType="application/vnd.openxmlformats-package.digital-signature-origin"/>
|
// <Default Extension="sigs" ContentType="application/vnd.openxmlformats-package.digital-signature-origin"/>
|
||||||
sigsPartName = PackagingURIHelper.createPartName("/_xmlsignatures/origin.sigs");
|
final DSigRelation originDesc = DSigRelation.ORIGIN_SIGS;
|
||||||
} catch (InvalidFormatException e) {
|
PackagePartName originPartName = PackagingURIHelper.createPartName(originDesc.getFileName(0));
|
||||||
throw new MarshalException(e);
|
|
||||||
|
PackagePart originPart = pkg.getPart(originPartName);
|
||||||
|
if (originPart == null) {
|
||||||
|
// touch empty marker file
|
||||||
|
originPart = pkg.createPart(originPartName, originDesc.getContentType());
|
||||||
|
pkg.addRelationship(originPartName, TargetMode.INTERNAL, originDesc.getRelation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// <Override PartName="/_xmlsignatures/sig1.xml" ContentType="application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"/>
|
||||||
|
final DSigRelation sigDesc = DSigRelation.SIG;
|
||||||
|
int nextSigIdx = pkg.getUnusedPartIndex(sigDesc.getDefaultFileName());
|
||||||
|
|
||||||
|
if (!signatureConfig.isAllowMultipleSignatures()) {
|
||||||
|
PackageRelationshipCollection prc = originPart.getRelationshipsByType(sigDesc.getRelation());
|
||||||
|
for (int i=2; i<nextSigIdx; i++) {
|
||||||
|
PackagePartName pn = PackagingURIHelper.createPartName(sigDesc.getFileName(i));
|
||||||
|
for (PackageRelationship rel : prc) {
|
||||||
|
PackagePart pp = originPart.getRelatedPart(rel);
|
||||||
|
if (pp.getPartName().equals(pn)) {
|
||||||
|
originPart.removeRelationship(rel.getId());
|
||||||
|
prc.removeRelationship(rel.getId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pkg.removePart(pkg.getPart(pn));
|
||||||
|
}
|
||||||
|
nextSigIdx = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackagePartName sigPartName = PackagingURIHelper.createPartName(sigDesc.getFileName(nextSigIdx));
|
||||||
PackagePart sigPart = pkg.getPart(sigPartName);
|
PackagePart sigPart = pkg.getPart(sigPartName);
|
||||||
if (sigPart == null) {
|
if (sigPart == null) {
|
||||||
sigPart = pkg.createPart(sigPartName, ContentTypes.DIGITAL_SIGNATURE_XML_SIGNATURE_PART);
|
sigPart = pkg.createPart(sigPartName, sigDesc.getContentType());
|
||||||
|
originPart.addRelationship(sigPartName, TargetMode.INTERNAL, sigDesc.getRelation());
|
||||||
|
} else {
|
||||||
|
sigPart.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try (OutputStream os = sigPart.getOutputStream()) {
|
||||||
OutputStream os = sigPart.getOutputStream();
|
|
||||||
SignatureDocument sigDoc = SignatureDocument.Factory.parse(document, DEFAULT_XML_OPTIONS);
|
SignatureDocument sigDoc = SignatureDocument.Factory.parse(document, DEFAULT_XML_OPTIONS);
|
||||||
sigDoc.save(os, xo);
|
sigDoc.save(os, xo);
|
||||||
os.close();
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new MarshalException("Unable to write signature document", e);
|
throw new MarshalException("Unable to write signature document", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
PackagePart sigsPart = pkg.getPart(sigsPartName);
|
|
||||||
if (sigsPart == null) {
|
|
||||||
// touch empty marker file
|
|
||||||
sigsPart = pkg.createPart(sigsPartName, ContentTypes.DIGITAL_SIGNATURE_ORIGIN_PART);
|
|
||||||
}
|
|
||||||
|
|
||||||
PackageRelationshipCollection relCol = pkg.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN);
|
|
||||||
for (PackageRelationship pr : relCol) {
|
|
||||||
pkg.removeRelationship(pr.getId());
|
|
||||||
}
|
|
||||||
pkg.addRelationship(sigsPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN);
|
|
||||||
|
|
||||||
sigsPart.addRelationship(sigPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Element getDsigElement(final Document document, final String localName) {
|
private Element getDsigElement(final Document document, final String localName) {
|
||||||
|
|
|
@ -185,9 +185,7 @@ public class SignaturePart {
|
||||||
final Map<String,String> nsMap = new HashMap<>();
|
final Map<String,String> nsMap = new HashMap<>();
|
||||||
|
|
||||||
{
|
{
|
||||||
for (Map.Entry<String,String> me : signatureConfig.getNamespacePrefixes().entrySet()) {
|
signatureConfig.getNamespacePrefixes().forEach((k,v) -> nsMap.put(v,k));
|
||||||
nsMap.put(me.getValue(), me.getKey());
|
|
||||||
}
|
|
||||||
nsMap.put("dsss", MS_DIGSIG_NS);
|
nsMap.put("dsss", MS_DIGSIG_NS);
|
||||||
nsMap.put("ds", XML_DIGSIG_NS);
|
nsMap.put("ds", XML_DIGSIG_NS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,9 +129,7 @@ public class KeyInfoSignatureFacet extends SignatureFacet {
|
||||||
DOMSignContext domSignContext = (nextSibling == null)
|
DOMSignContext domSignContext = (nextSibling == null)
|
||||||
? new DOMSignContext(key, n)
|
? new DOMSignContext(key, n)
|
||||||
: new DOMSignContext(key, n, nextSibling);
|
: new DOMSignContext(key, n, nextSibling);
|
||||||
for (Map.Entry<String,String> me : signatureConfig.getNamespacePrefixes().entrySet()) {
|
signatureConfig.getNamespacePrefixes().forEach(domSignContext::putNamespacePrefix);
|
||||||
domSignContext.putNamespacePrefix(me.getKey(), me.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
DOMStructure domStructure = new DOMStructure(n);
|
DOMStructure domStructure = new DOMStructure(n);
|
||||||
domKeyInfo.marshal(domStructure, domSignContext);
|
domKeyInfo.marshal(domStructure, domSignContext);
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
/* ====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
package org.apache.poi.xslf.draw;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Insets;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
|
||||||
|
import org.apache.batik.bridge.BridgeContext;
|
||||||
|
import org.apache.batik.bridge.DocumentLoader;
|
||||||
|
import org.apache.batik.bridge.GVTBuilder;
|
||||||
|
import org.apache.batik.bridge.UserAgent;
|
||||||
|
import org.apache.batik.bridge.UserAgentAdapter;
|
||||||
|
import org.apache.batik.ext.awt.RenderingHintsKeyExt;
|
||||||
|
import org.apache.batik.ext.awt.image.renderable.ClipRable8Bit;
|
||||||
|
import org.apache.batik.gvt.GraphicsNode;
|
||||||
|
import org.apache.batik.util.XMLResourceDescriptor;
|
||||||
|
import org.apache.poi.sl.draw.ImageRenderer;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
|
||||||
|
public class SVGImageRenderer implements ImageRenderer {
|
||||||
|
private final GVTBuilder builder = new GVTBuilder();
|
||||||
|
private final BridgeContext context;
|
||||||
|
private final SAXSVGDocumentFactory svgFact;
|
||||||
|
private GraphicsNode svgRoot;
|
||||||
|
private double alpha = 1.0;
|
||||||
|
|
||||||
|
public SVGImageRenderer() {
|
||||||
|
String parser = XMLResourceDescriptor.getXMLParserClassName();
|
||||||
|
// TOOO: tell the batik guys to use secure parsing feature
|
||||||
|
svgFact = new SAXSVGDocumentFactory(parser);
|
||||||
|
|
||||||
|
UserAgent agent = new UserAgentAdapter();
|
||||||
|
DocumentLoader loader = new DocumentLoader(agent);
|
||||||
|
context = new BridgeContext(agent, loader);
|
||||||
|
context.setDynamic(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadImage(InputStream data, String contentType) throws IOException {
|
||||||
|
Document document = svgFact.createDocument("", data);
|
||||||
|
svgRoot = builder.build(context, document);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadImage(byte[] data, String contentType) throws IOException {
|
||||||
|
loadImage(new ByteArrayInputStream(data), contentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dimension getDimension() {
|
||||||
|
Rectangle2D r = svgRoot.getPrimitiveBounds();
|
||||||
|
return new Dimension((int)Math.ceil(r.getWidth()), (int)Math.ceil(r.getHeight()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAlpha(double alpha) {
|
||||||
|
this.alpha = alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BufferedImage getImage() {
|
||||||
|
return getImage(getDimension());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BufferedImage getImage(Dimension dim) {
|
||||||
|
BufferedImage bi = new BufferedImage((int)dim.getWidth(), (int)dim.getHeight(), BufferedImage.TYPE_INT_ARGB);
|
||||||
|
Graphics2D g2d = (Graphics2D) bi.getGraphics();
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||||
|
g2d.setRenderingHint(RenderingHintsKeyExt.KEY_BUFFERED_IMAGE, new WeakReference(bi));
|
||||||
|
Dimension dimSVG = getDimension();
|
||||||
|
|
||||||
|
double scaleX = dim.getWidth() / dimSVG.getWidth();
|
||||||
|
double scaleY = dim.getHeight() / dimSVG.getHeight();
|
||||||
|
g2d.scale(scaleX, scaleY);
|
||||||
|
|
||||||
|
svgRoot.paint(g2d);
|
||||||
|
g2d.dispose();
|
||||||
|
|
||||||
|
return bi;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean drawImage(Graphics2D graphics, Rectangle2D anchor) {
|
||||||
|
return drawImage(graphics, anchor, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean drawImage(Graphics2D graphics, Rectangle2D anchor, Insets clip) {
|
||||||
|
if (clip == null) {
|
||||||
|
svgRoot.setClip(null);
|
||||||
|
} else {
|
||||||
|
Rectangle2D clippedRect = new Rectangle2D.Double(
|
||||||
|
anchor.getX()+clip.left,
|
||||||
|
anchor.getY()+clip.top,
|
||||||
|
anchor.getWidth()-(clip.left+clip.right),
|
||||||
|
anchor.getHeight()-(clip.top+clip.bottom)
|
||||||
|
);
|
||||||
|
svgRoot.setClip(new ClipRable8Bit(null, clippedRect));
|
||||||
|
}
|
||||||
|
|
||||||
|
svgRoot.paint(graphics);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -218,6 +218,8 @@ public final class XSLFPictureData extends POIXMLDocumentPart implements Picture
|
||||||
return PictureType.WDP;
|
return PictureType.WDP;
|
||||||
} else if (XSLFRelation.IMAGE_TIFF.getContentType().equals(ct)) {
|
} else if (XSLFRelation.IMAGE_TIFF.getContentType().equals(ct)) {
|
||||||
return PictureType.TIFF;
|
return PictureType.TIFF;
|
||||||
|
} else if (XSLFRelation.IMAGE_SVG.getContentType().equals(ct)) {
|
||||||
|
return PictureType.SVG;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -237,6 +239,7 @@ public final class XSLFPictureData extends POIXMLDocumentPart implements Picture
|
||||||
case WPG: return XSLFRelation.IMAGE_WPG;
|
case WPG: return XSLFRelation.IMAGE_WPG;
|
||||||
case WDP: return XSLFRelation.IMAGE_WDP;
|
case WDP: return XSLFRelation.IMAGE_WDP;
|
||||||
case TIFF: return XSLFRelation.IMAGE_TIFF;
|
case TIFF: return XSLFRelation.IMAGE_TIFF;
|
||||||
|
case SVG: return XSLFRelation.IMAGE_SVG;
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,18 +19,31 @@
|
||||||
|
|
||||||
package org.apache.poi.xslf.usermodel;
|
package org.apache.poi.xslf.usermodel;
|
||||||
|
|
||||||
|
import static org.apache.poi.openxml4j.opc.PackageRelationshipTypes.CORE_PROPERTIES_ECMA376_NS;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
import javax.xml.namespace.QName;
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||||
|
import org.apache.poi.sl.usermodel.PictureData.PictureType;
|
||||||
import org.apache.poi.sl.usermodel.PictureShape;
|
import org.apache.poi.sl.usermodel.PictureShape;
|
||||||
import org.apache.poi.sl.usermodel.Placeholder;
|
import org.apache.poi.sl.usermodel.Placeholder;
|
||||||
import org.apache.poi.util.Beta;
|
import org.apache.poi.util.Beta;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
|
import org.apache.poi.util.Units;
|
||||||
|
import org.apache.poi.xslf.draw.SVGImageRenderer;
|
||||||
import org.apache.xmlbeans.XmlCursor;
|
import org.apache.xmlbeans.XmlCursor;
|
||||||
import org.apache.xmlbeans.XmlException;
|
import org.apache.xmlbeans.XmlException;
|
||||||
import org.apache.xmlbeans.XmlObject;
|
import org.apache.xmlbeans.XmlObject;
|
||||||
|
@ -55,6 +68,11 @@ public class XSLFPictureShape extends XSLFSimpleShape
|
||||||
implements PictureShape<XSLFShape,XSLFTextParagraph> {
|
implements PictureShape<XSLFShape,XSLFTextParagraph> {
|
||||||
private static final POILogger LOG = POILogFactory.getLogger(XSLFPictureShape.class);
|
private static final POILogger LOG = POILogFactory.getLogger(XSLFPictureShape.class);
|
||||||
|
|
||||||
|
private static final String DML_NS = "http://schemas.microsoft.com/office/drawing/2010/main";
|
||||||
|
private static final String SVG_NS = "http://schemas.microsoft.com/office/drawing/2016/SVG/main";
|
||||||
|
private static final String BITMAP_URI = "{28A0092B-C50C-407E-A947-70E740481C1C}";
|
||||||
|
private static final String SVG_URI = "{96DAC541-7B7A-43D3-8B79-37D633B846F1}";
|
||||||
|
|
||||||
private XSLFPictureData _data;
|
private XSLFPictureData _data;
|
||||||
|
|
||||||
/*package*/ XSLFPictureShape(CTPicture shape, XSLFSheet sheet) {
|
/*package*/ XSLFPictureShape(CTPicture shape, XSLFSheet sheet) {
|
||||||
|
@ -196,6 +214,97 @@ public class XSLFPictureShape extends XSLFSimpleShape
|
||||||
return (r == null) ? null : new Insets(r.getT(), r.getL(), r.getB(), r.getR());
|
return (r == null) ? null : new Insets(r.getT(), r.getL(), r.getB(), r.getR());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a SVG image reference
|
||||||
|
* @param svgPic a previously imported svg image
|
||||||
|
*/
|
||||||
|
public void setSvgImage(XSLFPictureData svgPic) {
|
||||||
|
CTBlip blip = getBlip();
|
||||||
|
CTOfficeArtExtensionList extLst = blip.isSetExtLst() ? blip.getExtLst() : blip.addNewExtLst();
|
||||||
|
|
||||||
|
final int bitmapId = getExt(extLst, BITMAP_URI);
|
||||||
|
CTOfficeArtExtension extBitmap;
|
||||||
|
if (bitmapId == -1) {
|
||||||
|
extBitmap = extLst.addNewExt();
|
||||||
|
extBitmap.setUri(BITMAP_URI);
|
||||||
|
XmlCursor cur = extBitmap.newCursor();
|
||||||
|
cur.toEndToken();
|
||||||
|
cur.beginElement(new QName(DML_NS, "useLocalDpi", "a14"));
|
||||||
|
cur.insertNamespace("a14", DML_NS);
|
||||||
|
cur.insertAttributeWithValue("val", "0");
|
||||||
|
cur.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
final int svgId = getExt(extLst, SVG_URI);;
|
||||||
|
if (svgId != -1) {
|
||||||
|
extLst.removeExt(svgId);
|
||||||
|
}
|
||||||
|
|
||||||
|
String svgRelId = getSheet().getRelationId(svgPic);
|
||||||
|
if (svgRelId == null) {
|
||||||
|
svgRelId = getSheet().addRelation(null, XSLFRelation.IMAGE_SVG, svgPic).getRelationship().getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
CTOfficeArtExtension svgBitmap = extLst.addNewExt();
|
||||||
|
svgBitmap.setUri(SVG_URI);
|
||||||
|
XmlCursor cur = svgBitmap.newCursor();
|
||||||
|
cur.toEndToken();
|
||||||
|
cur.beginElement(new QName(SVG_NS, "svgBlip", "asvg"));
|
||||||
|
cur.insertNamespace("asvg", SVG_NS);
|
||||||
|
cur.insertAttributeWithValue(new QName(CORE_PROPERTIES_ECMA376_NS, "embed", "rel"), svgRelId);
|
||||||
|
cur.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convienence method for adding SVG images, which generates the preview image
|
||||||
|
* @param sheet the sheet to add
|
||||||
|
* @param svgPic the svg picture to add
|
||||||
|
* @param previewType the preview picture type or null (defaults to PNG) - currently only JPEG,GIF,PNG are allowed
|
||||||
|
* @param anchor the image anchor (for calculating the preview image size) or
|
||||||
|
* null (the preview size is taken from the svg picture bounds)
|
||||||
|
*/
|
||||||
|
public static XSLFPictureShape addSvgImage(XSLFSheet sheet, XSLFPictureData svgPic, PictureType previewType, Rectangle2D anchor) throws IOException {
|
||||||
|
|
||||||
|
SVGImageRenderer renderer = new SVGImageRenderer();
|
||||||
|
try (InputStream is = svgPic.getInputStream()) {
|
||||||
|
renderer.loadImage(is, svgPic.getType().contentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
Dimension dim = renderer.getDimension();
|
||||||
|
Rectangle2D anc = (anchor != null) ? anchor
|
||||||
|
: new Rectangle2D.Double(0,0, Units.pixelToPoints((int)dim.getWidth()), Units.pixelToPoints((int)dim.getHeight()));
|
||||||
|
|
||||||
|
PictureType pt = (previewType != null) ? previewType : PictureType.PNG;
|
||||||
|
if (pt != PictureType.JPEG || pt != PictureType.GIF || pt != PictureType.PNG) {
|
||||||
|
pt = PictureType.PNG;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferedImage thmBI = renderer.getImage(dim);
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream(100000);
|
||||||
|
// use extension instead of enum name, because of "jpeg"
|
||||||
|
ImageIO.write(thmBI, pt.extension.substring(1), bos);
|
||||||
|
|
||||||
|
XSLFPictureData pngPic = sheet.getSlideShow().addPicture(new ByteArrayInputStream(bos.toByteArray()), pt);
|
||||||
|
|
||||||
|
XSLFPictureShape shape = sheet.createPicture(pngPic);
|
||||||
|
shape.setAnchor(anc);
|
||||||
|
shape.setSvgImage(svgPic);
|
||||||
|
return shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int getExt(CTOfficeArtExtensionList extLst, String uri) {
|
||||||
|
final int size = extLst.sizeOfExtArray();
|
||||||
|
for (int i=0; i<size; i++) {
|
||||||
|
CTOfficeArtExtension ext = extLst.getExtArray(i);
|
||||||
|
if (uri.equals(ext.getUri())) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void copy(XSLFShape sh){
|
void copy(XSLFShape sh){
|
||||||
super.copy(sh);
|
super.copy(sh);
|
||||||
|
@ -219,11 +328,11 @@ public class XSLFPictureShape extends XSLFSimpleShape
|
||||||
nvPr.unsetCustDataLst();
|
nvPr.unsetCustDataLst();
|
||||||
}
|
}
|
||||||
if(blip.isSetExtLst()) {
|
if(blip.isSetExtLst()) {
|
||||||
|
// TODO: check for SVG copying
|
||||||
CTOfficeArtExtensionList extLst = blip.getExtLst();
|
CTOfficeArtExtensionList extLst = blip.getExtLst();
|
||||||
//noinspection deprecation
|
//noinspection deprecation
|
||||||
for(CTOfficeArtExtension ext : extLst.getExtArray()){
|
for(CTOfficeArtExtension ext : extLst.getExtArray()){
|
||||||
String xpath = "declare namespace a14='http://schemas.microsoft.com/office/drawing/2010/main' $this//a14:imgProps/a14:imgLayer";
|
String xpath = "declare namespace a14='"+ DML_NS +"' $this//a14:imgProps/a14:imgLayer";
|
||||||
XmlObject[] obj = ext.selectPath(xpath);
|
XmlObject[] obj = ext.selectPath(xpath);
|
||||||
if(obj != null && obj.length == 1){
|
if(obj != null && obj.length == 1){
|
||||||
XmlCursor c = obj[0].newCursor();
|
XmlCursor c = obj[0].newCursor();
|
||||||
|
@ -234,6 +343,5 @@ public class XSLFPictureShape extends XSLFSimpleShape
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,6 +16,8 @@
|
||||||
==================================================================== */
|
==================================================================== */
|
||||||
package org.apache.poi.xslf.usermodel;
|
package org.apache.poi.xslf.usermodel;
|
||||||
|
|
||||||
|
import static org.apache.poi.openxml4j.opc.PackageRelationshipTypes.IMAGE_PART;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -159,80 +161,87 @@ public final class XSLFRelation extends POIXMLRelation {
|
||||||
|
|
||||||
public static final XSLFRelation IMAGE_EMF = new XSLFRelation(
|
public static final XSLFRelation IMAGE_EMF = new XSLFRelation(
|
||||||
PictureType.EMF.contentType,
|
PictureType.EMF.contentType,
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
IMAGE_PART,
|
||||||
"/ppt/media/image#.emf",
|
"/ppt/media/image#.emf",
|
||||||
XSLFPictureData.class
|
XSLFPictureData.class
|
||||||
);
|
);
|
||||||
public static final XSLFRelation IMAGE_WMF = new XSLFRelation(
|
public static final XSLFRelation IMAGE_WMF = new XSLFRelation(
|
||||||
PictureType.WMF.contentType,
|
PictureType.WMF.contentType,
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
IMAGE_PART,
|
||||||
"/ppt/media/image#.wmf",
|
"/ppt/media/image#.wmf",
|
||||||
XSLFPictureData.class
|
XSLFPictureData.class
|
||||||
);
|
);
|
||||||
public static final XSLFRelation IMAGE_PICT = new XSLFRelation(
|
public static final XSLFRelation IMAGE_PICT = new XSLFRelation(
|
||||||
PictureType.PICT.contentType,
|
PictureType.PICT.contentType,
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
IMAGE_PART,
|
||||||
"/ppt/media/image#.pict",
|
"/ppt/media/image#.pict",
|
||||||
XSLFPictureData.class
|
XSLFPictureData.class
|
||||||
);
|
);
|
||||||
public static final XSLFRelation IMAGE_JPEG = new XSLFRelation(
|
public static final XSLFRelation IMAGE_JPEG = new XSLFRelation(
|
||||||
PictureType.JPEG.contentType,
|
PictureType.JPEG.contentType,
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
IMAGE_PART,
|
||||||
"/ppt/media/image#.jpeg",
|
"/ppt/media/image#.jpeg",
|
||||||
XSLFPictureData.class
|
XSLFPictureData.class
|
||||||
);
|
);
|
||||||
public static final XSLFRelation IMAGE_PNG = new XSLFRelation(
|
public static final XSLFRelation IMAGE_PNG = new XSLFRelation(
|
||||||
PictureType.PNG.contentType,
|
PictureType.PNG.contentType,
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
IMAGE_PART,
|
||||||
"/ppt/media/image#.png",
|
"/ppt/media/image#.png",
|
||||||
XSLFPictureData.class
|
XSLFPictureData.class
|
||||||
);
|
);
|
||||||
public static final XSLFRelation IMAGE_DIB = new XSLFRelation(
|
public static final XSLFRelation IMAGE_DIB = new XSLFRelation(
|
||||||
PictureType.DIB.contentType,
|
PictureType.DIB.contentType,
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
IMAGE_PART,
|
||||||
"/ppt/media/image#.dib",
|
"/ppt/media/image#.dib",
|
||||||
XSLFPictureData.class
|
XSLFPictureData.class
|
||||||
);
|
);
|
||||||
public static final XSLFRelation IMAGE_GIF = new XSLFRelation(
|
public static final XSLFRelation IMAGE_GIF = new XSLFRelation(
|
||||||
PictureType.GIF.contentType,
|
PictureType.GIF.contentType,
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
IMAGE_PART,
|
||||||
"/ppt/media/image#.gif",
|
"/ppt/media/image#.gif",
|
||||||
XSLFPictureData.class
|
XSLFPictureData.class
|
||||||
);
|
);
|
||||||
public static final XSLFRelation IMAGE_TIFF = new XSLFRelation(
|
public static final XSLFRelation IMAGE_TIFF = new XSLFRelation(
|
||||||
PictureType.TIFF.contentType,
|
PictureType.TIFF.contentType,
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
IMAGE_PART,
|
||||||
"/ppt/media/image#.tiff",
|
"/ppt/media/image#.tiff",
|
||||||
XSLFPictureData.class
|
XSLFPictureData.class
|
||||||
);
|
);
|
||||||
public static final XSLFRelation IMAGE_EPS = new XSLFRelation(
|
public static final XSLFRelation IMAGE_EPS = new XSLFRelation(
|
||||||
PictureType.EPS.contentType,
|
PictureType.EPS.contentType,
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
IMAGE_PART,
|
||||||
"/ppt/media/image#.eps",
|
"/ppt/media/image#.eps",
|
||||||
XSLFPictureData.class
|
XSLFPictureData.class
|
||||||
);
|
);
|
||||||
public static final XSLFRelation IMAGE_BMP = new XSLFRelation(
|
public static final XSLFRelation IMAGE_BMP = new XSLFRelation(
|
||||||
PictureType.BMP.contentType,
|
PictureType.BMP.contentType,
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
IMAGE_PART,
|
||||||
"/ppt/media/image#.bmp",
|
"/ppt/media/image#.bmp",
|
||||||
XSLFPictureData.class
|
XSLFPictureData.class
|
||||||
);
|
);
|
||||||
public static final XSLFRelation IMAGE_WPG = new XSLFRelation(
|
public static final XSLFRelation IMAGE_WPG = new XSLFRelation(
|
||||||
PictureType.WPG.contentType,
|
PictureType.WPG.contentType,
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
IMAGE_PART,
|
||||||
"/ppt/media/image#.wpg",
|
"/ppt/media/image#.wpg",
|
||||||
XSLFPictureData.class
|
XSLFPictureData.class
|
||||||
);
|
);
|
||||||
public static final XSLFRelation IMAGE_WDP = new XSLFRelation(
|
public static final XSLFRelation IMAGE_WDP = new XSLFRelation(
|
||||||
PictureType.WDP.contentType,
|
PictureType.WDP.contentType,
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
IMAGE_PART,
|
||||||
"/ppt/media/image#.wdp",
|
"/ppt/media/image#.wdp",
|
||||||
XSLFPictureData.class
|
XSLFPictureData.class
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public static final XSLFRelation IMAGE_SVG = new XSLFRelation(
|
||||||
|
PictureType.SVG.contentType,
|
||||||
|
IMAGE_PART,
|
||||||
|
"/ppt/media/image#.svg",
|
||||||
|
XSLFPictureData.class
|
||||||
|
);
|
||||||
|
|
||||||
public static final XSLFRelation IMAGES = new XSLFRelation(
|
public static final XSLFRelation IMAGES = new XSLFRelation(
|
||||||
null,
|
null,
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
IMAGE_PART,
|
||||||
null,
|
null,
|
||||||
XSLFPictureData.class
|
XSLFPictureData.class
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,314 +0,0 @@
|
||||||
/* ====================================================================
|
|
||||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
contributor license agreements. See the NOTICE file distributed with
|
|
||||||
this work for additional information regarding copyright ownership.
|
|
||||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
(the "License"); you may not use this file except in compliance with
|
|
||||||
the License. You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
==================================================================== */
|
|
||||||
package org.apache.poi.poifs.crypt;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.security.KeyPair;
|
|
||||||
import java.security.KeyPairGenerator;
|
|
||||||
import java.security.PrivateKey;
|
|
||||||
import java.security.PublicKey;
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.security.cert.CRLException;
|
|
||||||
import java.security.cert.CertificateEncodingException;
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
import java.security.cert.X509CRL;
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
import java.security.interfaces.RSAPublicKey;
|
|
||||||
import java.security.spec.RSAKeyGenParameterSpec;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
|
||||||
import javax.xml.transform.OutputKeys;
|
|
||||||
import javax.xml.transform.Result;
|
|
||||||
import javax.xml.transform.Source;
|
|
||||||
import javax.xml.transform.Transformer;
|
|
||||||
import javax.xml.transform.TransformerException;
|
|
||||||
import javax.xml.transform.TransformerFactory;
|
|
||||||
import javax.xml.transform.dom.DOMSource;
|
|
||||||
import javax.xml.transform.stream.StreamResult;
|
|
||||||
|
|
||||||
import org.bouncycastle.asn1.DERIA5String;
|
|
||||||
import org.bouncycastle.asn1.DEROctetString;
|
|
||||||
import org.bouncycastle.asn1.DERSequence;
|
|
||||||
import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers;
|
|
||||||
import org.bouncycastle.asn1.x500.X500Name;
|
|
||||||
import org.bouncycastle.asn1.x509.AuthorityInformationAccess;
|
|
||||||
import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
|
|
||||||
import org.bouncycastle.asn1.x509.BasicConstraints;
|
|
||||||
import org.bouncycastle.asn1.x509.CRLNumber;
|
|
||||||
import org.bouncycastle.asn1.x509.CRLReason;
|
|
||||||
import org.bouncycastle.asn1.x509.DistributionPoint;
|
|
||||||
import org.bouncycastle.asn1.x509.DistributionPointName;
|
|
||||||
import org.bouncycastle.asn1.x509.Extension;
|
|
||||||
import org.bouncycastle.asn1.x509.Extensions;
|
|
||||||
import org.bouncycastle.asn1.x509.GeneralName;
|
|
||||||
import org.bouncycastle.asn1.x509.GeneralNames;
|
|
||||||
import org.bouncycastle.asn1.x509.KeyUsage;
|
|
||||||
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
|
|
||||||
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
|
|
||||||
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
|
|
||||||
import org.bouncycastle.cert.X509CRLHolder;
|
|
||||||
import org.bouncycastle.cert.X509CertificateHolder;
|
|
||||||
import org.bouncycastle.cert.X509ExtensionUtils;
|
|
||||||
import org.bouncycastle.cert.X509v2CRLBuilder;
|
|
||||||
import org.bouncycastle.cert.X509v3CertificateBuilder;
|
|
||||||
import org.bouncycastle.cert.jcajce.JcaX509CRLConverter;
|
|
||||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
|
|
||||||
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
|
|
||||||
import org.bouncycastle.cert.ocsp.BasicOCSPRespBuilder;
|
|
||||||
import org.bouncycastle.cert.ocsp.CertificateID;
|
|
||||||
import org.bouncycastle.cert.ocsp.CertificateStatus;
|
|
||||||
import org.bouncycastle.cert.ocsp.OCSPReq;
|
|
||||||
import org.bouncycastle.cert.ocsp.OCSPReqBuilder;
|
|
||||||
import org.bouncycastle.cert.ocsp.OCSPResp;
|
|
||||||
import org.bouncycastle.cert.ocsp.OCSPRespBuilder;
|
|
||||||
import org.bouncycastle.cert.ocsp.Req;
|
|
||||||
import org.bouncycastle.cert.ocsp.RevokedStatus;
|
|
||||||
import org.bouncycastle.crypto.params.RSAKeyParameters;
|
|
||||||
import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory;
|
|
||||||
import org.bouncycastle.operator.ContentSigner;
|
|
||||||
import org.bouncycastle.operator.DigestCalculator;
|
|
||||||
import org.bouncycastle.operator.OperatorCreationException;
|
|
||||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
|
||||||
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
|
|
||||||
import org.w3c.dom.Document;
|
|
||||||
import org.w3c.dom.Node;
|
|
||||||
import org.xml.sax.InputSource;
|
|
||||||
import org.xml.sax.SAXException;
|
|
||||||
|
|
||||||
public class PkiTestUtils {
|
|
||||||
|
|
||||||
private PkiTestUtils() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
static KeyPair generateKeyPair() throws Exception {
|
|
||||||
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
|
||||||
SecureRandom random = new SecureRandom();
|
|
||||||
keyPairGenerator.initialize(new RSAKeyGenParameterSpec(1024,
|
|
||||||
RSAKeyGenParameterSpec.F4), random);
|
|
||||||
return keyPairGenerator.generateKeyPair();
|
|
||||||
}
|
|
||||||
|
|
||||||
static X509Certificate generateCertificate(PublicKey subjectPublicKey,
|
|
||||||
String subjectDn, Date notBefore, Date notAfter,
|
|
||||||
X509Certificate issuerCertificate, PrivateKey issuerPrivateKey,
|
|
||||||
boolean caFlag, int pathLength, String crlUri, String ocspUri,
|
|
||||||
KeyUsage keyUsage)
|
|
||||||
throws IOException, OperatorCreationException, CertificateException
|
|
||||||
{
|
|
||||||
String signatureAlgorithm = "SHA1withRSA";
|
|
||||||
X500Name issuerName;
|
|
||||||
if (issuerCertificate != null) {
|
|
||||||
issuerName = new X509CertificateHolder(issuerCertificate.getEncoded()).getIssuer();
|
|
||||||
} else {
|
|
||||||
issuerName = new X500Name(subjectDn);
|
|
||||||
}
|
|
||||||
|
|
||||||
RSAPublicKey rsaPubKey = (RSAPublicKey)subjectPublicKey;
|
|
||||||
RSAKeyParameters rsaSpec = new RSAKeyParameters(false, rsaPubKey.getModulus(), rsaPubKey.getPublicExponent());
|
|
||||||
|
|
||||||
SubjectPublicKeyInfo subjectPublicKeyInfo =
|
|
||||||
SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(rsaSpec);
|
|
||||||
|
|
||||||
DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder()
|
|
||||||
.setProvider("BC").build().get(CertificateID.HASH_SHA1);
|
|
||||||
|
|
||||||
X509v3CertificateBuilder certificateGenerator = new X509v3CertificateBuilder(
|
|
||||||
issuerName
|
|
||||||
, new BigInteger(128, new SecureRandom())
|
|
||||||
, notBefore
|
|
||||||
, notAfter
|
|
||||||
, new X500Name(subjectDn)
|
|
||||||
, subjectPublicKeyInfo
|
|
||||||
);
|
|
||||||
|
|
||||||
X509ExtensionUtils exUtils = new X509ExtensionUtils(digestCalc);
|
|
||||||
SubjectKeyIdentifier subKeyId = exUtils.createSubjectKeyIdentifier(subjectPublicKeyInfo);
|
|
||||||
AuthorityKeyIdentifier autKeyId = (issuerCertificate != null)
|
|
||||||
? exUtils.createAuthorityKeyIdentifier(new X509CertificateHolder(issuerCertificate.getEncoded()))
|
|
||||||
: exUtils.createAuthorityKeyIdentifier(subjectPublicKeyInfo);
|
|
||||||
|
|
||||||
certificateGenerator.addExtension(Extension.subjectKeyIdentifier, false, subKeyId);
|
|
||||||
certificateGenerator.addExtension(Extension.authorityKeyIdentifier, false, autKeyId);
|
|
||||||
|
|
||||||
if (caFlag) {
|
|
||||||
BasicConstraints bc;
|
|
||||||
|
|
||||||
if (-1 == pathLength) {
|
|
||||||
bc = new BasicConstraints(true);
|
|
||||||
} else {
|
|
||||||
bc = new BasicConstraints(pathLength);
|
|
||||||
}
|
|
||||||
certificateGenerator.addExtension(Extension.basicConstraints, false, bc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null != crlUri) {
|
|
||||||
int uri = GeneralName.uniformResourceIdentifier;
|
|
||||||
DERIA5String crlUriDer = new DERIA5String(crlUri);
|
|
||||||
GeneralName gn = new GeneralName(uri, crlUriDer);
|
|
||||||
|
|
||||||
DERSequence gnDer = new DERSequence(gn);
|
|
||||||
GeneralNames gns = GeneralNames.getInstance(gnDer);
|
|
||||||
|
|
||||||
DistributionPointName dpn = new DistributionPointName(0, gns);
|
|
||||||
DistributionPoint distp = new DistributionPoint(dpn, null, null);
|
|
||||||
DERSequence distpDer = new DERSequence(distp);
|
|
||||||
certificateGenerator.addExtension(Extension.cRLDistributionPoints, false, distpDer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null != ocspUri) {
|
|
||||||
int uri = GeneralName.uniformResourceIdentifier;
|
|
||||||
GeneralName ocspName = new GeneralName(uri, ocspUri);
|
|
||||||
|
|
||||||
AuthorityInformationAccess authorityInformationAccess =
|
|
||||||
new AuthorityInformationAccess(X509ObjectIdentifiers.ocspAccessMethod, ocspName);
|
|
||||||
|
|
||||||
certificateGenerator.addExtension(Extension.authorityInfoAccess, false, authorityInformationAccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null != keyUsage) {
|
|
||||||
certificateGenerator.addExtension(Extension.keyUsage, true, keyUsage);
|
|
||||||
}
|
|
||||||
|
|
||||||
JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder(signatureAlgorithm);
|
|
||||||
signerBuilder.setProvider("BC");
|
|
||||||
|
|
||||||
X509CertificateHolder certHolder =
|
|
||||||
certificateGenerator.build(signerBuilder.build(issuerPrivateKey));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Next certificate factory trick is needed to make sure that the
|
|
||||||
* certificate delivered to the caller is provided by the default
|
|
||||||
* security provider instead of BouncyCastle. If we don't do this trick
|
|
||||||
* we might run into trouble when trying to use the CertPath validator.
|
|
||||||
*/
|
|
||||||
// CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
|
|
||||||
// certificate = (X509Certificate) certificateFactory
|
|
||||||
// .generateCertificate(new ByteArrayInputStream(certificate
|
|
||||||
// .getEncoded()));
|
|
||||||
return new JcaX509CertificateConverter().getCertificate(certHolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Document loadDocument(InputStream documentInputStream)
|
|
||||||
throws ParserConfigurationException, SAXException, IOException {
|
|
||||||
InputSource inputSource = new InputSource(documentInputStream);
|
|
||||||
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
|
|
||||||
.newInstance();
|
|
||||||
documentBuilderFactory.setNamespaceAware(true);
|
|
||||||
DocumentBuilder documentBuilder = documentBuilderFactory
|
|
||||||
.newDocumentBuilder();
|
|
||||||
return documentBuilder.parse(inputSource);
|
|
||||||
}
|
|
||||||
|
|
||||||
static String toString(Node dom) throws TransformerException {
|
|
||||||
Source source = new DOMSource(dom);
|
|
||||||
StringWriter stringWriter = new StringWriter();
|
|
||||||
Result result = new StreamResult(stringWriter);
|
|
||||||
TransformerFactory transformerFactory = TransformerFactory
|
|
||||||
.newInstance();
|
|
||||||
Transformer transformer = transformerFactory.newTransformer();
|
|
||||||
/*
|
|
||||||
* We have to omit the ?xml declaration if we want to embed the
|
|
||||||
* document.
|
|
||||||
*/
|
|
||||||
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
|
|
||||||
transformer.transform(source, result);
|
|
||||||
return stringWriter.getBuffer().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static X509CRL generateCrl(X509Certificate issuer, PrivateKey issuerPrivateKey)
|
|
||||||
throws CertificateEncodingException, IOException, CRLException, OperatorCreationException {
|
|
||||||
|
|
||||||
X509CertificateHolder holder = new X509CertificateHolder(issuer.getEncoded());
|
|
||||||
X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(holder.getIssuer(), new Date());
|
|
||||||
crlBuilder.setNextUpdate(new Date(new Date().getTime() + 100000));
|
|
||||||
JcaContentSignerBuilder contentBuilder = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC");
|
|
||||||
|
|
||||||
CRLNumber crlNumber = new CRLNumber(new BigInteger("1234"));
|
|
||||||
|
|
||||||
crlBuilder.addExtension(Extension.cRLNumber, false, crlNumber);
|
|
||||||
X509CRLHolder x509Crl = crlBuilder.build(contentBuilder.build(issuerPrivateKey));
|
|
||||||
return new JcaX509CRLConverter().setProvider("BC").getCRL(x509Crl);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static OCSPResp createOcspResp(X509Certificate certificate,
|
|
||||||
boolean revoked, X509Certificate issuerCertificate,
|
|
||||||
X509Certificate ocspResponderCertificate,
|
|
||||||
PrivateKey ocspResponderPrivateKey, String signatureAlgorithm,
|
|
||||||
long nonceTimeinMillis)
|
|
||||||
throws Exception {
|
|
||||||
DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder()
|
|
||||||
.setProvider("BC").build().get(CertificateID.HASH_SHA1);
|
|
||||||
X509CertificateHolder issuerHolder = new X509CertificateHolder(issuerCertificate.getEncoded());
|
|
||||||
CertificateID certId = new CertificateID(digestCalc, issuerHolder, certificate.getSerialNumber());
|
|
||||||
|
|
||||||
// request
|
|
||||||
//create a nonce to avoid replay attack
|
|
||||||
BigInteger nonce = BigInteger.valueOf(nonceTimeinMillis);
|
|
||||||
DEROctetString nonceDer = new DEROctetString(nonce.toByteArray());
|
|
||||||
Extension ext = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, true, nonceDer);
|
|
||||||
Extensions exts = new Extensions(ext);
|
|
||||||
|
|
||||||
OCSPReqBuilder ocspReqBuilder = new OCSPReqBuilder();
|
|
||||||
ocspReqBuilder.addRequest(certId);
|
|
||||||
ocspReqBuilder.setRequestExtensions(exts);
|
|
||||||
OCSPReq ocspReq = ocspReqBuilder.build();
|
|
||||||
|
|
||||||
|
|
||||||
SubjectPublicKeyInfo keyInfo = new SubjectPublicKeyInfo
|
|
||||||
(CertificateID.HASH_SHA1, ocspResponderCertificate.getPublicKey().getEncoded());
|
|
||||||
|
|
||||||
BasicOCSPRespBuilder basicOCSPRespBuilder = new BasicOCSPRespBuilder(keyInfo, digestCalc);
|
|
||||||
basicOCSPRespBuilder.setResponseExtensions(exts);
|
|
||||||
|
|
||||||
// request processing
|
|
||||||
Req[] requestList = ocspReq.getRequestList();
|
|
||||||
for (Req ocspRequest : requestList) {
|
|
||||||
CertificateID certificateID = ocspRequest.getCertID();
|
|
||||||
CertificateStatus certificateStatus = CertificateStatus.GOOD;
|
|
||||||
if (revoked) {
|
|
||||||
certificateStatus = new RevokedStatus(new Date(), CRLReason.privilegeWithdrawn);
|
|
||||||
}
|
|
||||||
basicOCSPRespBuilder.addResponse(certificateID, certificateStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
// basic response generation
|
|
||||||
X509CertificateHolder[] chain = null;
|
|
||||||
if (!ocspResponderCertificate.equals(issuerCertificate)) {
|
|
||||||
// TODO: HorribleProxy can't convert array input params yet
|
|
||||||
chain = new X509CertificateHolder[] {
|
|
||||||
new X509CertificateHolder(ocspResponderCertificate.getEncoded()),
|
|
||||||
issuerHolder
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
ContentSigner contentSigner = new JcaContentSignerBuilder("SHA1withRSA")
|
|
||||||
.setProvider("BC").build(ocspResponderPrivateKey);
|
|
||||||
BasicOCSPResp basicOCSPResp = basicOCSPRespBuilder.build(contentSigner, chain, new Date(nonceTimeinMillis));
|
|
||||||
|
|
||||||
|
|
||||||
OCSPRespBuilder ocspRespBuilder = new OCSPRespBuilder();
|
|
||||||
|
|
||||||
return ocspRespBuilder.build(OCSPRespBuilder.SUCCESSFUL, basicOCSPResp);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -29,6 +29,7 @@ import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assume.assumeTrue;
|
import static org.junit.Assume.assumeTrue;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -36,19 +37,30 @@ import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.net.ConnectException;
|
import java.net.ConnectException;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
|
import java.security.KeyPairGenerator;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.security.cert.CRLException;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
|
import java.security.cert.CertificateEncodingException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.X509CRL;
|
import java.security.cert.X509CRL;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.security.interfaces.RSAPublicKey;
|
||||||
|
import java.security.spec.RSAKeyGenParameterSpec;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -56,7 +68,9 @@ import java.util.Date;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.xml.crypto.MarshalException;
|
||||||
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
||||||
|
import javax.xml.crypto.dsig.XMLSignatureException;
|
||||||
import javax.xml.crypto.dsig.dom.DOMSignContext;
|
import javax.xml.crypto.dsig.dom.DOMSignContext;
|
||||||
|
|
||||||
import org.apache.jcp.xml.dsig.internal.dom.DOMSignedInfo;
|
import org.apache.jcp.xml.dsig.internal.dom.DOMSignedInfo;
|
||||||
|
@ -90,8 +104,53 @@ import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
import org.apache.xmlbeans.SystemProperties;
|
import org.apache.xmlbeans.SystemProperties;
|
||||||
import org.apache.xmlbeans.XmlObject;
|
import org.apache.xmlbeans.XmlObject;
|
||||||
|
import org.bouncycastle.asn1.DERIA5String;
|
||||||
|
import org.bouncycastle.asn1.DEROctetString;
|
||||||
|
import org.bouncycastle.asn1.DERSequence;
|
||||||
|
import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers;
|
||||||
|
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
||||||
|
import org.bouncycastle.asn1.x500.X500Name;
|
||||||
|
import org.bouncycastle.asn1.x509.AuthorityInformationAccess;
|
||||||
|
import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
|
||||||
|
import org.bouncycastle.asn1.x509.BasicConstraints;
|
||||||
|
import org.bouncycastle.asn1.x509.CRLNumber;
|
||||||
|
import org.bouncycastle.asn1.x509.CRLReason;
|
||||||
|
import org.bouncycastle.asn1.x509.DistributionPoint;
|
||||||
|
import org.bouncycastle.asn1.x509.DistributionPointName;
|
||||||
|
import org.bouncycastle.asn1.x509.Extension;
|
||||||
|
import org.bouncycastle.asn1.x509.Extensions;
|
||||||
|
import org.bouncycastle.asn1.x509.GeneralName;
|
||||||
|
import org.bouncycastle.asn1.x509.GeneralNames;
|
||||||
import org.bouncycastle.asn1.x509.KeyUsage;
|
import org.bouncycastle.asn1.x509.KeyUsage;
|
||||||
|
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
|
||||||
|
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
|
||||||
|
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
|
||||||
|
import org.bouncycastle.cert.X509CRLHolder;
|
||||||
|
import org.bouncycastle.cert.X509CertificateHolder;
|
||||||
|
import org.bouncycastle.cert.X509ExtensionUtils;
|
||||||
|
import org.bouncycastle.cert.X509v2CRLBuilder;
|
||||||
|
import org.bouncycastle.cert.X509v3CertificateBuilder;
|
||||||
|
import org.bouncycastle.cert.jcajce.JcaX509CRLConverter;
|
||||||
|
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
|
||||||
|
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
|
||||||
|
import org.bouncycastle.cert.ocsp.BasicOCSPRespBuilder;
|
||||||
|
import org.bouncycastle.cert.ocsp.CertificateID;
|
||||||
|
import org.bouncycastle.cert.ocsp.CertificateStatus;
|
||||||
|
import org.bouncycastle.cert.ocsp.OCSPReq;
|
||||||
|
import org.bouncycastle.cert.ocsp.OCSPReqBuilder;
|
||||||
import org.bouncycastle.cert.ocsp.OCSPResp;
|
import org.bouncycastle.cert.ocsp.OCSPResp;
|
||||||
|
import org.bouncycastle.cert.ocsp.OCSPRespBuilder;
|
||||||
|
import org.bouncycastle.cert.ocsp.Req;
|
||||||
|
import org.bouncycastle.cert.ocsp.RevokedStatus;
|
||||||
|
import org.bouncycastle.crypto.params.RSAKeyParameters;
|
||||||
|
import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory;
|
||||||
|
import org.bouncycastle.openssl.PEMParser;
|
||||||
|
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
|
||||||
|
import org.bouncycastle.operator.ContentSigner;
|
||||||
|
import org.bouncycastle.operator.DigestCalculator;
|
||||||
|
import org.bouncycastle.operator.OperatorCreationException;
|
||||||
|
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
||||||
|
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
|
||||||
import org.etsi.uri.x01903.v13.DigestAlgAndValueType;
|
import org.etsi.uri.x01903.v13.DigestAlgAndValueType;
|
||||||
import org.etsi.uri.x01903.v13.QualifyingPropertiesType;
|
import org.etsi.uri.x01903.v13.QualifyingPropertiesType;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
|
@ -408,7 +467,7 @@ public class TestSignatureInfo {
|
||||||
try (OPCPackage pkg = OPCPackage.open(copy(sigCopy), PackageAccess.READ_WRITE)) {
|
try (OPCPackage pkg = OPCPackage.open(copy(sigCopy), PackageAccess.READ_WRITE)) {
|
||||||
|
|
||||||
initKeyPair("Test", "CN=Test");
|
initKeyPair("Test", "CN=Test");
|
||||||
final X509CRL crl = PkiTestUtils.generateCrl(x509, keyPair.getPrivate());
|
final X509CRL crl = generateCrl(x509, keyPair.getPrivate());
|
||||||
|
|
||||||
// setup
|
// setup
|
||||||
SignatureConfig signatureConfig = new SignatureConfig();
|
SignatureConfig signatureConfig = new SignatureConfig();
|
||||||
|
@ -481,7 +540,7 @@ public class TestSignatureInfo {
|
||||||
|
|
||||||
final RevocationData revocationData = new RevocationData();
|
final RevocationData revocationData = new RevocationData();
|
||||||
revocationData.addCRL(crl);
|
revocationData.addCRL(crl);
|
||||||
OCSPResp ocspResp = PkiTestUtils.createOcspResp(x509, false,
|
OCSPResp ocspResp = createOcspResp(x509, false,
|
||||||
x509, x509, keyPair.getPrivate(), "SHA1withRSA", cal.getTimeInMillis());
|
x509, x509, keyPair.getPrivate(), "SHA1withRSA", cal.getTimeInMillis());
|
||||||
revocationData.addOCSP(ocspResp.getEncoded());
|
revocationData.addOCSP(ocspResp.getEncoded());
|
||||||
|
|
||||||
|
@ -721,18 +780,84 @@ public class TestSignatureInfo {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultiSign() throws Exception {
|
public void testMultiSign() throws Exception {
|
||||||
initKeyPair("KeyA", "CN=KeyA");
|
cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
|
||||||
//KeyPair keyPairA = keyPair;
|
cal.clear();
|
||||||
//X509Certificate x509A = x509;
|
cal.setTimeZone(LocaleUtil.TIMEZONE_UTC);
|
||||||
initKeyPair("KeyB", "CN=KeyB");
|
cal.set(2018, Calendar.DECEMBER, 14);
|
||||||
//KeyPair keyPairB = keyPair;
|
|
||||||
//X509Certificate x509B = x509;
|
|
||||||
|
|
||||||
File tpl = copy(testdata.getFile("bug58630.xlsx"));
|
// test signing with separate opened packages
|
||||||
|
File tpl = copy(testdata.getFile("hello-world-unsigned.xlsx"));
|
||||||
try (OPCPackage pkg = OPCPackage.open(tpl)) {
|
try (OPCPackage pkg = OPCPackage.open(tpl)) {
|
||||||
//SignatureConfig signatureConfig = new SignatureConfig();
|
signPkg63011(pkg, "bug63011_key1.pem", true);
|
||||||
assertNotNull(pkg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try (OPCPackage pkg = OPCPackage.open(tpl)) {
|
||||||
|
signPkg63011(pkg, "bug63011_key2.pem", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyPkg63011(tpl, true);
|
||||||
|
|
||||||
|
// test signing with single opened package
|
||||||
|
tpl = copy(testdata.getFile("hello-world-unsigned.xlsx"));
|
||||||
|
try (OPCPackage pkg = OPCPackage.open(tpl)) {
|
||||||
|
signPkg63011(pkg, "bug63011_key1.pem", true);
|
||||||
|
signPkg63011(pkg, "bug63011_key2.pem", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyPkg63011(tpl, true);
|
||||||
|
|
||||||
|
try (OPCPackage pkg = OPCPackage.open(tpl)) {
|
||||||
|
signPkg63011(pkg, "bug63011_key1.pem", true);
|
||||||
|
signPkg63011(pkg, "bug63011_key2.pem", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyPkg63011(tpl, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyPkg63011(File tpl, boolean multi) throws InvalidFormatException, IOException {
|
||||||
|
try (OPCPackage pkg = OPCPackage.open(tpl, PackageAccess.READ)) {
|
||||||
|
SignatureConfig sic = new SignatureConfig();
|
||||||
|
sic.setOpcPackage(pkg);
|
||||||
|
SignatureInfo si = new SignatureInfo();
|
||||||
|
si.setSignatureConfig(sic);
|
||||||
|
List<X509Certificate> result = new ArrayList<>();
|
||||||
|
for (SignaturePart sp : si.getSignatureParts()) {
|
||||||
|
if (sp.validate()) {
|
||||||
|
result.add(sp.getSigner());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
|
||||||
|
if (multi) {
|
||||||
|
assertEquals(2, result.size());
|
||||||
|
assertEquals("CN=Muj Klic", result.get(0).getSubjectDN().toString());
|
||||||
|
assertEquals("CN=My Second key", result.get(1).getSubjectDN().toString());
|
||||||
|
} else {
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
assertEquals("CN=My Second key", result.get(0).getSubjectDN().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(si.verifySignature());
|
||||||
|
pkg.revert();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void signPkg63011(OPCPackage pkg, String pemFile, boolean multi)
|
||||||
|
throws IOException, CertificateException, XMLSignatureException, MarshalException {
|
||||||
|
assertNotNull(pkg);
|
||||||
|
initKeyFromPEM(testdata.getFile(pemFile));
|
||||||
|
|
||||||
|
SignatureConfig config = new SignatureConfig();
|
||||||
|
config.setKey(keyPair.getPrivate());
|
||||||
|
config.setSigningCertificateChain(Collections.singletonList(x509));
|
||||||
|
config.setExecutionTime(cal.getTime());
|
||||||
|
config.setAllowMultipleSignatures(multi);
|
||||||
|
config.setOpcPackage(pkg);
|
||||||
|
|
||||||
|
SignatureInfo si = new SignatureInfo();
|
||||||
|
si.setSignatureConfig(config);
|
||||||
|
si.confirmSignature();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -829,14 +954,14 @@ public class TestSignatureInfo {
|
||||||
x509 = (X509Certificate)keystore.getCertificate(alias);
|
x509 = (X509Certificate)keystore.getCertificate(alias);
|
||||||
keyPair = new KeyPair(x509.getPublicKey(), (PrivateKey)key);
|
keyPair = new KeyPair(x509.getPublicKey(), (PrivateKey)key);
|
||||||
} else {
|
} else {
|
||||||
keyPair = PkiTestUtils.generateKeyPair();
|
keyPair = generateKeyPair();
|
||||||
Date notBefore = cal.getTime();
|
Date notBefore = cal.getTime();
|
||||||
Calendar cal2 = (Calendar)cal.clone();
|
Calendar cal2 = (Calendar)cal.clone();
|
||||||
cal2.add(Calendar.YEAR, 1);
|
cal2.add(Calendar.YEAR, 1);
|
||||||
Date notAfter = cal2.getTime();
|
Date notAfter = cal2.getTime();
|
||||||
KeyUsage keyUsage = new KeyUsage(KeyUsage.digitalSignature);
|
KeyUsage keyUsage = new KeyUsage(KeyUsage.digitalSignature);
|
||||||
|
|
||||||
x509 = PkiTestUtils.generateCertificate(keyPair.getPublic(), subjectDN
|
x509 = generateCertificate(keyPair.getPublic(), subjectDN
|
||||||
, notBefore, notAfter, null, keyPair.getPrivate(), true, 0, null, null, keyUsage);
|
, notBefore, notAfter, null, keyPair.getPrivate(), true, 0, null, null, keyUsage);
|
||||||
|
|
||||||
keystore.setKeyEntry(alias, keyPair.getPrivate(), password, new Certificate[]{x509});
|
keystore.setKeyEntry(alias, keyPair.getPrivate(), password, new Certificate[]{x509});
|
||||||
|
@ -849,6 +974,27 @@ public class TestSignatureInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initKeyFromPEM(File pemFile) throws IOException, CertificateException {
|
||||||
|
// see https://stackoverflow.com/questions/11787571/how-to-read-pem-file-to-get-private-and-public-key
|
||||||
|
PrivateKey key = null;
|
||||||
|
x509 = null;
|
||||||
|
|
||||||
|
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(pemFile), StandardCharsets.ISO_8859_1))) {
|
||||||
|
PEMParser parser = new PEMParser(br);
|
||||||
|
for (Object obj; (obj = parser.readObject()) != null; ) {
|
||||||
|
if (obj instanceof PrivateKeyInfo) {
|
||||||
|
key = new JcaPEMKeyConverter().setProvider("BC").getPrivateKey((PrivateKeyInfo)obj);
|
||||||
|
} else if (obj instanceof X509CertificateHolder) {
|
||||||
|
x509 = new JcaX509CertificateConverter().setProvider("BC").getCertificate((X509CertificateHolder)obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key != null && x509 != null) {
|
||||||
|
keyPair = new KeyPair(x509.getPublicKey(), key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static File copy(File input) throws IOException {
|
private static File copy(File input) throws IOException {
|
||||||
String extension = input.getName().replaceAll(".*?(\\.[^.]+)?$", "$1");
|
String extension = input.getName().replaceAll(".*?(\\.[^.]+)?$", "$1");
|
||||||
if (extension == null || extension.isEmpty()) {
|
if (extension == null || extension.isEmpty()) {
|
||||||
|
@ -872,4 +1018,187 @@ public class TestSignatureInfo {
|
||||||
return tmpFile;
|
return tmpFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static KeyPair generateKeyPair() throws Exception {
|
||||||
|
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
||||||
|
SecureRandom random = new SecureRandom();
|
||||||
|
keyPairGenerator.initialize(new RSAKeyGenParameterSpec(1024,
|
||||||
|
RSAKeyGenParameterSpec.F4), random);
|
||||||
|
return keyPairGenerator.generateKeyPair();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static X509Certificate generateCertificate(PublicKey subjectPublicKey,
|
||||||
|
String subjectDn, Date notBefore, Date notAfter,
|
||||||
|
X509Certificate issuerCertificate, PrivateKey issuerPrivateKey,
|
||||||
|
boolean caFlag, int pathLength, String crlUri, String ocspUri,
|
||||||
|
KeyUsage keyUsage)
|
||||||
|
throws IOException, OperatorCreationException, CertificateException
|
||||||
|
{
|
||||||
|
String signatureAlgorithm = "SHA1withRSA";
|
||||||
|
X500Name issuerName;
|
||||||
|
if (issuerCertificate != null) {
|
||||||
|
issuerName = new X509CertificateHolder(issuerCertificate.getEncoded()).getIssuer();
|
||||||
|
} else {
|
||||||
|
issuerName = new X500Name(subjectDn);
|
||||||
|
}
|
||||||
|
|
||||||
|
RSAPublicKey rsaPubKey = (RSAPublicKey)subjectPublicKey;
|
||||||
|
RSAKeyParameters rsaSpec = new RSAKeyParameters(false, rsaPubKey.getModulus(), rsaPubKey.getPublicExponent());
|
||||||
|
|
||||||
|
SubjectPublicKeyInfo subjectPublicKeyInfo =
|
||||||
|
SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(rsaSpec);
|
||||||
|
|
||||||
|
DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder()
|
||||||
|
.setProvider("BC").build().get(CertificateID.HASH_SHA1);
|
||||||
|
|
||||||
|
X509v3CertificateBuilder certificateGenerator = new X509v3CertificateBuilder(
|
||||||
|
issuerName
|
||||||
|
, new BigInteger(128, new SecureRandom())
|
||||||
|
, notBefore
|
||||||
|
, notAfter
|
||||||
|
, new X500Name(subjectDn)
|
||||||
|
, subjectPublicKeyInfo
|
||||||
|
);
|
||||||
|
|
||||||
|
X509ExtensionUtils exUtils = new X509ExtensionUtils(digestCalc);
|
||||||
|
SubjectKeyIdentifier subKeyId = exUtils.createSubjectKeyIdentifier(subjectPublicKeyInfo);
|
||||||
|
AuthorityKeyIdentifier autKeyId = (issuerCertificate != null)
|
||||||
|
? exUtils.createAuthorityKeyIdentifier(new X509CertificateHolder(issuerCertificate.getEncoded()))
|
||||||
|
: exUtils.createAuthorityKeyIdentifier(subjectPublicKeyInfo);
|
||||||
|
|
||||||
|
certificateGenerator.addExtension(Extension.subjectKeyIdentifier, false, subKeyId);
|
||||||
|
certificateGenerator.addExtension(Extension.authorityKeyIdentifier, false, autKeyId);
|
||||||
|
|
||||||
|
if (caFlag) {
|
||||||
|
BasicConstraints bc;
|
||||||
|
|
||||||
|
if (-1 == pathLength) {
|
||||||
|
bc = new BasicConstraints(true);
|
||||||
|
} else {
|
||||||
|
bc = new BasicConstraints(pathLength);
|
||||||
|
}
|
||||||
|
certificateGenerator.addExtension(Extension.basicConstraints, false, bc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null != crlUri) {
|
||||||
|
int uri = GeneralName.uniformResourceIdentifier;
|
||||||
|
DERIA5String crlUriDer = new DERIA5String(crlUri);
|
||||||
|
GeneralName gn = new GeneralName(uri, crlUriDer);
|
||||||
|
|
||||||
|
DERSequence gnDer = new DERSequence(gn);
|
||||||
|
GeneralNames gns = GeneralNames.getInstance(gnDer);
|
||||||
|
|
||||||
|
DistributionPointName dpn = new DistributionPointName(0, gns);
|
||||||
|
DistributionPoint distp = new DistributionPoint(dpn, null, null);
|
||||||
|
DERSequence distpDer = new DERSequence(distp);
|
||||||
|
certificateGenerator.addExtension(Extension.cRLDistributionPoints, false, distpDer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null != ocspUri) {
|
||||||
|
int uri = GeneralName.uniformResourceIdentifier;
|
||||||
|
GeneralName ocspName = new GeneralName(uri, ocspUri);
|
||||||
|
|
||||||
|
AuthorityInformationAccess authorityInformationAccess =
|
||||||
|
new AuthorityInformationAccess(X509ObjectIdentifiers.ocspAccessMethod, ocspName);
|
||||||
|
|
||||||
|
certificateGenerator.addExtension(Extension.authorityInfoAccess, false, authorityInformationAccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null != keyUsage) {
|
||||||
|
certificateGenerator.addExtension(Extension.keyUsage, true, keyUsage);
|
||||||
|
}
|
||||||
|
|
||||||
|
JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder(signatureAlgorithm);
|
||||||
|
signerBuilder.setProvider("BC");
|
||||||
|
|
||||||
|
X509CertificateHolder certHolder =
|
||||||
|
certificateGenerator.build(signerBuilder.build(issuerPrivateKey));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Next certificate factory trick is needed to make sure that the
|
||||||
|
* certificate delivered to the caller is provided by the default
|
||||||
|
* security provider instead of BouncyCastle. If we don't do this trick
|
||||||
|
* we might run into trouble when trying to use the CertPath validator.
|
||||||
|
*/
|
||||||
|
// CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
|
||||||
|
// certificate = (X509Certificate) certificateFactory
|
||||||
|
// .generateCertificate(new ByteArrayInputStream(certificate
|
||||||
|
// .getEncoded()));
|
||||||
|
return new JcaX509CertificateConverter().getCertificate(certHolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static X509CRL generateCrl(X509Certificate issuer, PrivateKey issuerPrivateKey)
|
||||||
|
throws CertificateEncodingException, IOException, CRLException, OperatorCreationException {
|
||||||
|
|
||||||
|
X509CertificateHolder holder = new X509CertificateHolder(issuer.getEncoded());
|
||||||
|
X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(holder.getIssuer(), new Date());
|
||||||
|
crlBuilder.setNextUpdate(new Date(new Date().getTime() + 100000));
|
||||||
|
JcaContentSignerBuilder contentBuilder = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC");
|
||||||
|
|
||||||
|
CRLNumber crlNumber = new CRLNumber(new BigInteger("1234"));
|
||||||
|
|
||||||
|
crlBuilder.addExtension(Extension.cRLNumber, false, crlNumber);
|
||||||
|
X509CRLHolder x509Crl = crlBuilder.build(contentBuilder.build(issuerPrivateKey));
|
||||||
|
return new JcaX509CRLConverter().setProvider("BC").getCRL(x509Crl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static OCSPResp createOcspResp(X509Certificate certificate,
|
||||||
|
boolean revoked, X509Certificate issuerCertificate,
|
||||||
|
X509Certificate ocspResponderCertificate,
|
||||||
|
PrivateKey ocspResponderPrivateKey, String signatureAlgorithm,
|
||||||
|
long nonceTimeinMillis)
|
||||||
|
throws Exception {
|
||||||
|
DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder()
|
||||||
|
.setProvider("BC").build().get(CertificateID.HASH_SHA1);
|
||||||
|
X509CertificateHolder issuerHolder = new X509CertificateHolder(issuerCertificate.getEncoded());
|
||||||
|
CertificateID certId = new CertificateID(digestCalc, issuerHolder, certificate.getSerialNumber());
|
||||||
|
|
||||||
|
// request
|
||||||
|
//create a nonce to avoid replay attack
|
||||||
|
BigInteger nonce = BigInteger.valueOf(nonceTimeinMillis);
|
||||||
|
DEROctetString nonceDer = new DEROctetString(nonce.toByteArray());
|
||||||
|
Extension ext = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, true, nonceDer);
|
||||||
|
Extensions exts = new Extensions(ext);
|
||||||
|
|
||||||
|
OCSPReqBuilder ocspReqBuilder = new OCSPReqBuilder();
|
||||||
|
ocspReqBuilder.addRequest(certId);
|
||||||
|
ocspReqBuilder.setRequestExtensions(exts);
|
||||||
|
OCSPReq ocspReq = ocspReqBuilder.build();
|
||||||
|
|
||||||
|
|
||||||
|
SubjectPublicKeyInfo keyInfo = new SubjectPublicKeyInfo
|
||||||
|
(CertificateID.HASH_SHA1, ocspResponderCertificate.getPublicKey().getEncoded());
|
||||||
|
|
||||||
|
BasicOCSPRespBuilder basicOCSPRespBuilder = new BasicOCSPRespBuilder(keyInfo, digestCalc);
|
||||||
|
basicOCSPRespBuilder.setResponseExtensions(exts);
|
||||||
|
|
||||||
|
// request processing
|
||||||
|
Req[] requestList = ocspReq.getRequestList();
|
||||||
|
for (Req ocspRequest : requestList) {
|
||||||
|
CertificateID certificateID = ocspRequest.getCertID();
|
||||||
|
CertificateStatus certificateStatus = CertificateStatus.GOOD;
|
||||||
|
if (revoked) {
|
||||||
|
certificateStatus = new RevokedStatus(new Date(), CRLReason.privilegeWithdrawn);
|
||||||
|
}
|
||||||
|
basicOCSPRespBuilder.addResponse(certificateID, certificateStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
// basic response generation
|
||||||
|
X509CertificateHolder[] chain = null;
|
||||||
|
if (!ocspResponderCertificate.equals(issuerCertificate)) {
|
||||||
|
// TODO: HorribleProxy can't convert array input params yet
|
||||||
|
chain = new X509CertificateHolder[] {
|
||||||
|
new X509CertificateHolder(ocspResponderCertificate.getEncoded()),
|
||||||
|
issuerHolder
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentSigner contentSigner = new JcaContentSignerBuilder("SHA1withRSA")
|
||||||
|
.setProvider("BC").build(ocspResponderPrivateKey);
|
||||||
|
BasicOCSPResp basicOCSPResp = basicOCSPRespBuilder.build(contentSigner, chain, new Date(nonceTimeinMillis));
|
||||||
|
|
||||||
|
|
||||||
|
OCSPRespBuilder ocspRespBuilder = new OCSPRespBuilder();
|
||||||
|
|
||||||
|
return ocspRespBuilder.build(OCSPRespBuilder.SUCCESSFUL, basicOCSPResp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,14 +16,17 @@
|
||||||
==================================================================== */
|
==================================================================== */
|
||||||
package org.apache.poi.xslf.usermodel;
|
package org.apache.poi.xslf.usermodel;
|
||||||
|
|
||||||
|
import static org.apache.poi.POIDataSamples.TEST_PROPERTY;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -247,4 +250,24 @@ public class TestXSLFPictureShape {
|
||||||
|
|
||||||
slideShow.close();
|
slideShow.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void renderSvgImage() throws Exception {
|
||||||
|
String dataDirName = System.getProperty(TEST_PROPERTY);
|
||||||
|
final String SVG_FILE = (dataDirName != null ? "../" : "") + "src/documentation/resources/images/project-header.svg";
|
||||||
|
XMLSlideShow ppt = new XMLSlideShow();
|
||||||
|
XSLFSlide slide = ppt.createSlide();
|
||||||
|
|
||||||
|
XSLFPictureData svgPic = ppt.addPicture(new File(dataDirName, SVG_FILE), PictureType.SVG);
|
||||||
|
XSLFPictureShape shape = XSLFPictureShape.addSvgImage(slide, svgPic, PictureType.JPEG, null);
|
||||||
|
|
||||||
|
Rectangle2D anchor = shape.getAnchor();
|
||||||
|
anchor.setRect(100, 100, anchor.getWidth(), anchor.getHeight());
|
||||||
|
shape.setAnchor(anchor);
|
||||||
|
|
||||||
|
// try (FileOutputStream fos = new FileOutputStream("svgtest.pptx")) {
|
||||||
|
// ppt.write(fos);
|
||||||
|
// }
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCr+sR6OR6R49ni
|
||||||
|
/w/jjCSOewGvOjzJelKaGoT/cYmvx6JFrFwy3PV7FZEhRPQCKvE+cCOYAwBFTC7K
|
||||||
|
uN0h/cen7tVF/idVWlzOTU/3Tdy/J7sb2KfToHvjxKkeMUl1SHvf1et+3HQHQSII
|
||||||
|
Vf8A3cu0cL91sYSd32ZZYm2TeKxbTc1GO/R9OzvSOxCQaIVbAiMQvY04EQZb0F7/
|
||||||
|
eBRj8UAdMbsTRVYuOSWrXX2DL5U3/nq/c8F0ozeyUOEbzWacZ83OcDEFC0hCrGyy
|
||||||
|
ptKtEQBWhbgSZ9BRc5nZ9q97VoDOLwrb24zBI45AsRBvwRAhf5DLV5cOw6X8MdQd
|
||||||
|
p0pKcN9HAgMBAAECggEAVcPyNe3EZAcYQw7mMplSJcgMOAG4DNY22Wk+SFGr04Cg
|
||||||
|
WVSyih8NQPupa8kCUw5tTrEH3ygn+2cZsrlsdiYkaog9zfEIVpWA0NVXesJWwvGi
|
||||||
|
aymp0G0pO5Z4rHjx5E5okGETVynDp1aBDV0tlZYGn47WvG/x7fVaClt+v9ufQMyD
|
||||||
|
snUEf2lpWhUtoUhlOnDZr791QPLUkVi0roLSD0M2vPM1cbV8EO4SdhOOyTDCNFvo
|
||||||
|
IAcysKV0UBN/TJOyB7FyDw1cJtJ9Ja/X9YoLcW+0fTZNhlYq6VrowCQyEchlb8Pz
|
||||||
|
bRhUJc6oGffpaxtrMk8pmTSScpSTV5PtB3E4t6mYYQKBgQDVPX+GdnuNyyNdvF3g
|
||||||
|
SplJZdyAjW21mZ4gdYLxyGHIsgTrz4SKJ49HZoaDdwwpQRZWnQC7gxCXbJ2IHwMF
|
||||||
|
+Qz7pp7eoRhQ3eBqQxfIypOeRSC6n3OIOYxIJlcV3O/PTGwu2eJhxck1ZG/j90DW
|
||||||
|
NDo9hQYLFpD2xGiaWd611HncsQKBgQDOdzBZF/1PbUh/zz1nwAVPT85IM1vwU85k
|
||||||
|
LIQUY/P+LFUvSa7gk3sabn6Zop5Cv0z+I1j5NW1lobLR4u02jqIb/dqeJ+XOt27n
|
||||||
|
UMiYI/6WBA6Mkrf9j10BpFuSBWYotpkr8PZcog1v+FnODcOsG6Nl7fiJjkpPD6AF
|
||||||
|
MCIHip4ZdwKBgC4fKhkMQXcOy+x3VJqxp+v/My0+6c7QlioRIKxpGfVNw9C5RsKX
|
||||||
|
Ad+ApnGC60d1A37iYIkuNQV7gasygfXlw1Ae3tfqYhcDlomFT3ynjDw8WXLkEBoT
|
||||||
|
0Gq+mDFrYxckQXX0vIlHPVjmC2l0TjrGex5ZSlBVpi8pljJkY85SUbVRAoGBAICq
|
||||||
|
BCYxbfl2aAzGEEU8g9KWMD4MS4osH92LZE/0rhPCet96MpHfNoMVQq3pimicIJXr
|
||||||
|
X0IGSoNgTjjACwXJwzpga0HOKUc2RtW+IRO2squ4IXz23dQU6GfijfIkjTJoAHJC
|
||||||
|
urSlhGw3v3dKWptBqgUWVKEcXDCC0z0Ibtx2ROonAoGAWcRq3xpkbeR4K4yd+K9w
|
||||||
|
4CBi8sdlz48tmZDSVigjq27Jk/6Ttk5K6x8M1rhUWYZ+ak1Y2NVV24oqnIdtIZrE
|
||||||
|
BdgvzJCJN3Yx3FMYzUVqONFfGyppi0E7WvSYX0qlXKeZDcjgp1ORCOhiQL3ufE1+
|
||||||
|
LdXLunLfjJzNnvX7XoTAyyE=
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICojCCAYqgAwIBAgIEXA5r3jANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAhN
|
||||||
|
dWogS2xpYzAeFw0xODEyMTAxMzM2MzBaFw0xOTEyMTAxMzM2MzBaMBMxETAPBgNV
|
||||||
|
BAMMCE11aiBLbGljMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq/rE
|
||||||
|
ejkekePZ4v8P44wkjnsBrzo8yXpSmhqE/3GJr8eiRaxcMtz1exWRIUT0AirxPnAj
|
||||||
|
mAMARUwuyrjdIf3Hp+7VRf4nVVpczk1P903cvye7G9in06B748SpHjFJdUh739Xr
|
||||||
|
ftx0B0EiCFX/AN3LtHC/dbGEnd9mWWJtk3isW03NRjv0fTs70jsQkGiFWwIjEL2N
|
||||||
|
OBEGW9Be/3gUY/FAHTG7E0VWLjklq119gy+VN/56v3PBdKM3slDhG81mnGfNznAx
|
||||||
|
BQtIQqxssqbSrREAVoW4EmfQUXOZ2fave1aAzi8K29uMwSOOQLEQb8EQIX+Qy1eX
|
||||||
|
DsOl/DHUHadKSnDfRwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAJ5hi+ZinJ4QOA
|
||||||
|
hC2sPuawdj6k+C3+CXNpRV5eMagBJZYPMsUfEPrP7ZjRiBpQVQyx6rktXqObrmTw
|
||||||
|
e12yMor5cc8kGyQ6GmYoEoCKFS/S08fK5j5bwwy8KWfyH8tRGsEHeowPw3eIZCv7
|
||||||
|
gowUhb3SOsh3osAtafSe9aS0rGNTGBdSTFnJEiew8zpWbdIFKySYxU8nmHNpIPXh
|
||||||
|
O/EuAYMwbcF3BhM20Gm5hxqrgSWe7S+q3KqSJbs+k95j0jr8xoNzwUd8NzI40Uu1
|
||||||
|
L1ejyqvGHjxhQooIej1Ea/MSp7v5ifpBWSp3yxlOjAnZPSEewCutMyHylIulS0sK
|
||||||
|
2JQfgcdd
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -0,0 +1,45 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDMcC/+xW5l/R8i
|
||||||
|
M9IKNdebiCQxkn/gfSjXD7oddrg42POCuPElhaGlHXPI+DCvNQ1+lbCTDJ7rk8F2
|
||||||
|
DbefV80uwzMkMKnn0i3GW2K8LIGrv74ACYIzueHK+Mrm3N90/Xb6IqSR430SYH9r
|
||||||
|
RbIfCqCVa0LJbVS2Pw2vBmvJHE/DVoSjKXlO73EbN4G4lJnj80NaZp6I0DDsoVup
|
||||||
|
htKJWLtYwB3CDpI0oDst8/Beq7esDyyHHWf3v0TOtH19lRWSoD9yEmg+bRMKYfnu
|
||||||
|
T5rWj8tF+cRjh+SIyBjuIn7n4qwnAs62CQKFLjp/3PjOEbaD/aCX+6xMWvAtk0UT
|
||||||
|
KIDwYsejAgMBAAECggEAX0h2hibconpMFXPTlGCt4dadD+G46hdLfpjc5Lidehlb
|
||||||
|
vXSXKCbVRRCqE2PhxPdUF8iKqK68Lw4JoA0apRCWGBJwdpCbz+k83nNfXFbeBP9z
|
||||||
|
/a5w2czr+N7mKp2NJIix+DlHPJurgnIpUQUF1MPuPlXkpd7oGZzfstCqUex5HJAU
|
||||||
|
N03lL/Z5/hgq93sLh1ZgPWhwAOYnps0rsOnFYXlXW7WVXvL1xpyBidZstOw+BdVC
|
||||||
|
7BQNvKVa4KGC/PdgW7K4327JeMjRsX1nDUzZbORM5wihLE5idIHmDbQUm4G8JZul
|
||||||
|
tLeV2Ew28L91jcc55Pbe40tBeMSqgSuU2r6/dU4uCQKBgQDlUCI8vW1Q7J92m+zU
|
||||||
|
Y8lHu5mS4nlwXJEpuUoCuD2falAZW40+sG3fqZ1tEiCEpEYSYKMP0vbFrNLQ68av
|
||||||
|
HWhjXWCQFvuUfAK8BsMusRIBQ/ZJduSa5vSgsQA+ZVl/Pnj9PyMN70nhueHcXjnM
|
||||||
|
SNo5X3BQMNERaec7Lr0mRjDGHwKBgQDkOvcbdt4gCwpAeARzCTh15uw+q8KWPz77
|
||||||
|
hPbaO4GJIMZZmRULhsrgBNZAsREasO4ZKJLI+wtukCXqgHAGzdSl6aK1fDLgFYqP
|
||||||
|
Hp8UvgvIdF5yV7oAma9gRbK47sQlyBSFvQUyAuvA7wcviQ43/TIa173iBS07WfpA
|
||||||
|
KlZu6+Ol/QKBgQDMJfglDRtKJS6eIJjKSQADzZ8eZmNoxfAyLhQWscGir7oZqSjo
|
||||||
|
+5cFvPI7DR1IGRuM9t2Uk+M//uk8N/uNIOgzNglmnh9hhLnGfVq8scVuvPuBUciZ
|
||||||
|
oy179bha1E3F+28pPlFN8Y9b1umeD4DzPpSQ6UeLDLrD/v1t8eFRNsHrTwKBgE7v
|
||||||
|
4gW6wCrfBqWznP5YoxGMVAt9BqlGqLb/jw195ViTYGce3juFXGfM5HmthFfx9/f1
|
||||||
|
o4cl5RdRffu0foqr6C+WNjOFCGeeq7TCh4z6CkNDlGMB2pBYl2K52I3D702N/SMg
|
||||||
|
dEqO3hF12stjIOrWhNzp33/sAG/1t+s3eXuV1L/VAoGAe0d/g5LcACFbl0sDRcSV
|
||||||
|
WYsKHyR2dieALKf47mhzQtKmY506zM22n52s9sUT92j4jf/4dnP5OciJniSppgfW
|
||||||
|
V64/856DuMNPoIssmNh3tQwjm8I0/t+iDGJJSHnQthG0AwD2NRe/D8Uty4P7ED64
|
||||||
|
0gEVrDJEgT60MrQt15f+1sM=
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICrDCCAZSgAwIBAgIEXA/YwjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1N
|
||||||
|
eSBTZWNvbmQga2V5MB4XDTE4MTIxMTE1MzMyMloXDTE5MTIxMTE1MzMyMlowGDEW
|
||||||
|
MBQGA1UEAwwNTXkgU2Vjb25kIGtleTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
|
||||||
|
AQoCggEBAMxwL/7FbmX9HyIz0go115uIJDGSf+B9KNcPuh12uDjY84K48SWFoaUd
|
||||||
|
c8j4MK81DX6VsJMMnuuTwXYNt59XzS7DMyQwqefSLcZbYrwsgau/vgAJgjO54cr4
|
||||||
|
yubc33T9dvoipJHjfRJgf2tFsh8KoJVrQsltVLY/Da8Ga8kcT8NWhKMpeU7vcRs3
|
||||||
|
gbiUmePzQ1pmnojQMOyhW6mG0olYu1jAHcIOkjSgOy3z8F6rt6wPLIcdZ/e/RM60
|
||||||
|
fX2VFZKgP3ISaD5tEwph+e5PmtaPy0X5xGOH5IjIGO4ifufirCcCzrYJAoUuOn/c
|
||||||
|
+M4RtoP9oJf7rExa8C2TRRMogPBix6MCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEA
|
||||||
|
n3rvm1DatfrrFdhNOfNwlYMF12ND1BIEFYYI13vIkZ5wmb+gNYZu32FqdTpX//qV
|
||||||
|
VkNLXJj/DrR+rKWH2jZwabaYyv5XmJl9Y0/LqN3ExiqijYsPgpWEKCzhfyv+Qe5B
|
||||||
|
Qzx8WCJjGh0UMQ3P8/FRYsUPf5AFMdz9jZK0uYCFFgkb4LDp23MbNYG4eRBB+/+R
|
||||||
|
Arq/poWd+eb5G79+rnrGGCtqhVuxrMP8xkPy4Rkg8zr56CxQSHX7qXehYc9x/dTj
|
||||||
|
CyHPrOUAw4W/pYShYtHsqORQivPvwnwQQ4upK6s2l5pbPwyEzV45clIPU+3tjvn7
|
||||||
|
67DLhc66Sz4/XkWeEXeeMg==
|
||||||
|
-----END CERTIFICATE-----
|
Loading…
Reference in New Issue