summaryrefslogtreecommitdiffstats
path: root/xmlsecurity
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /xmlsecurity
parentInitial commit. (diff)
downloadlibreoffice-upstream.tar.xz
libreoffice-upstream.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xmlsecurity')
-rw-r--r--xmlsecurity/AllLangMoTarget_xsc.mk13
-rw-r--r--xmlsecurity/CppunitTest_qa_certext.mk27
-rw-r--r--xmlsecurity/CppunitTest_xmlsecurity_dialogs_test.mk68
-rw-r--r--xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk70
-rw-r--r--xmlsecurity/CppunitTest_xmlsecurity_signing.mk94
-rw-r--r--xmlsecurity/Executable_pdfverify.mk35
-rw-r--r--xmlsecurity/IwyuFilter_xmlsecurity.yaml134
-rw-r--r--xmlsecurity/Library_xmlsecurity.mk112
-rw-r--r--xmlsecurity/Library_xsec_xmlsec.mk188
-rw-r--r--xmlsecurity/Makefile14
-rw-r--r--xmlsecurity/Module_xmlsecurity.mk48
-rw-r--r--xmlsecurity/README.md32
-rw-r--r--xmlsecurity/UIConfig_xmlsec.mk24
-rw-r--r--xmlsecurity/doc/OpenDocumentSignatures-TestIntegration.sxwbin0 -> 14189 bytes
-rw-r--r--xmlsecurity/doc/OpenDocumentSignatures-Workflow.sxdbin0 -> 10310 bytes
-rw-r--r--xmlsecurity/doc/OpenDocumentSignatures.sxwbin0 -> 16195 bytes
-rw-r--r--xmlsecurity/doc/XMLSecurityFramework.sxwbin0 -> 187975 bytes
-rw-r--r--xmlsecurity/inc/UriBindingHelper.hxx51
-rw-r--r--xmlsecurity/inc/biginteger.hxx51
-rw-r--r--xmlsecurity/inc/bitmaps.hlst21
-rw-r--r--xmlsecurity/inc/certificate.hxx43
-rw-r--r--xmlsecurity/inc/certificatechooser.hxx96
-rw-r--r--xmlsecurity/inc/certificateviewer.hxx158
-rw-r--r--xmlsecurity/inc/digitalsignaturesdialog.hxx126
-rw-r--r--xmlsecurity/inc/documentsignaturehelper.hxx104
-rw-r--r--xmlsecurity/inc/documentsignaturemanager.hxx135
-rw-r--r--xmlsecurity/inc/framework/saxeventkeeperimpl.hxx290
-rw-r--r--xmlsecurity/inc/framework/securityengine.hxx142
-rw-r--r--xmlsecurity/inc/framework/signaturecreatorimpl.hxx96
-rw-r--r--xmlsecurity/inc/framework/signatureengine.hxx116
-rw-r--r--xmlsecurity/inc/framework/signatureverifierimpl.hxx88
-rw-r--r--xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx95
-rw-r--r--xmlsecurity/inc/gpg/SEInitializer.hxx47
-rw-r--r--xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx77
-rw-r--r--xmlsecurity/inc/macrosecurity.hxx126
-rw-r--r--xmlsecurity/inc/pch/precompiled_xmlsecurity.cxx12
-rw-r--r--xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx201
-rw-r--r--xmlsecurity/inc/pch/precompiled_xsec_xmlsec.cxx12
-rw-r--r--xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx149
-rw-r--r--xmlsecurity/inc/pdfsignaturehelper.hxx73
-rw-r--r--xmlsecurity/inc/resourcemanager.hxx26
-rw-r--r--xmlsecurity/inc/strings.hrc67
-rw-r--r--xmlsecurity/inc/xmlsec-wrapper.h47
-rw-r--r--xmlsecurity/inc/xmlsec/errorcallback.hxx30
-rw-r--r--xmlsecurity/inc/xmlsec/saxhelper.hxx85
-rw-r--r--xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx208
-rw-r--r--xmlsecurity/inc/xmlsec/xmlsec_init.hxx17
-rw-r--r--xmlsecurity/inc/xmlsec/xmlstreamio.hxx39
-rw-r--r--xmlsecurity/inc/xmlsecuritydllapi.h20
-rw-r--r--xmlsecurity/inc/xmlsignaturehelper.hxx176
-rw-r--r--xmlsecurity/inc/xsecctl.hxx408
-rw-r--r--xmlsecurity/inc/xsecxmlsecdllapi.h20
-rw-r--r--xmlsecurity/qa/certext/SanCertExt.cxx260
-rw-r--r--xmlsecurity/qa/certext/User_35_Root_11.crt64
-rwxr-xr-xxmlsecurity/qa/create-certs/create-certs.sh187
-rw-r--r--xmlsecurity/qa/create-certs/templates/intermediate.cnf132
-rw-r--r--xmlsecurity/qa/create-certs/templates/root.cnf132
-rw-r--r--xmlsecurity/qa/unit/data/xmlsecurity-dialogs-test.txt45
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/2good.pdfbin0 -> 109682 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p1.pdfbin0 -> 29646 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p3-stamp.pdfbin0 -> 22023 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/cr-comment.pdf4480
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/dict-bool.pdfbin0 -> 145552 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/forcepoint16.pdfbin0 -> 51200 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/good-custom-magic.pdfbin0 -> 57404 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/good-non-detached.pdfbin0 -> 29815 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/good-pades.pdfbin0 -> 58008 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/good.pdfbin0 -> 58796 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/name-bracket.pdf2241
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/no-eof.pdfbin0 -> 174879 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/no.pdfbin0 -> 6865 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/noeol.pdfbin0 -> 83693 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/partial-in-between.pdfbin0 -> 104501 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/partial.pdfbin0 -> 52004 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/pdf14adobe.pdfbin0 -> 141054 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/pdf14lowin.pdfbin0 -> 58575 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/pdf16adobe.pdfbin0 -> 81882 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/small.pdfbin0 -> 834 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/tdf107149.pdf97
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/tdf107782.pdfbin0 -> 157668 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/tdf114460.pdfbin0 -> 12669 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/data/tdf145312.pdfbin0 -> 148303 bytes
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx646
-rw-r--r--xmlsecurity/qa/unit/signing/data/02_doc_macros_signed_by_attacker_manipulated.odtbin0 -> 14045 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated.odtbin0 -> 13139 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated2.odtbin0 -> 13160 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated_triple.odtbin0 -> 13237 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/02_doc_signed_by_trusted_person_manipulated.odtbin0 -> 14003 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/add-visible-signature.pdfbin0 -> 2235 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/bad.docxbin0 -> 17962 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/bad.odtbin0 -> 10920 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/bad.pdfbin0 -> 57587 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/badDsigGPG.odtbin0 -> 13047 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/badStreamGPG.odtbin0 -> 13046 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/encryptedGPG.odtbin0 -> 13081 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/encryptedGPG_odf13.odtbin0 -> 12982 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/good-xades.odtbin0 -> 13918 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/good.odtbin0 -> 10878 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/good.pdfbin0 -> 57587 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/goodGPG.odtbin0 -> 11587 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/hide-and-replace-shadow-file-signed-2.pdfbin0 -> 17896 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/multi.docxbin0 -> 23767 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/no.odtbin0 -> 8345 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/no.pdfbin0 -> 6865 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/notype-xades.odtbin0 -> 13918 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/odb_signed_macros.odbbin0 -> 8823 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/partial.docxbin0 -> 17918 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/signatureline.docxbin0 -> 22877 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/signatureline.odtbin0 -> 27142 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odtbin0 -> 13585 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/tdf42316.ottbin0 -> 10242 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/tdf42316_odt12.ottbin0 -> 14625 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/tdf96097.odsbin0 -> 13767 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/tdf96097.odtbin0 -> 11791 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/data/untrustedGoodGPG.odtbin0 -> 12274 bytes
-rw-r--r--xmlsecurity/qa/unit/signing/signing.cxx1696
-rw-r--r--xmlsecurity/qa/unit/signing/signing2.cxx127
-rw-r--r--xmlsecurity/qa/unit/xmlsecurity-dialogs-test.cxx61
-rw-r--r--xmlsecurity/source/component/certificatecontainer.cxx152
-rw-r--r--xmlsecurity/source/component/documentdigitalsignatures.cxx900
-rw-r--r--xmlsecurity/source/dialogs/certificatechooser.cxx332
-rw-r--r--xmlsecurity/source/dialogs/certificateviewer.cxx377
-rw-r--r--xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx801
-rw-r--r--xmlsecurity/source/dialogs/macrosecurity.cxx446
-rw-r--r--xmlsecurity/source/framework/buffernode.cxx886
-rw-r--r--xmlsecurity/source/framework/buffernode.hxx119
-rw-r--r--xmlsecurity/source/framework/elementcollector.cxx137
-rw-r--r--xmlsecurity/source/framework/elementcollector.hxx80
-rw-r--r--xmlsecurity/source/framework/elementmark.cxx64
-rw-r--r--xmlsecurity/source/framework/elementmark.hxx67
-rw-r--r--xmlsecurity/source/framework/saxeventkeeperimpl.cxx1152
-rw-r--r--xmlsecurity/source/framework/securityengine.cxx67
-rw-r--r--xmlsecurity/source/framework/signaturecreatorimpl.cxx175
-rw-r--r--xmlsecurity/source/framework/signatureengine.cxx197
-rw-r--r--xmlsecurity/source/framework/signatureverifierimpl.cxx130
-rw-r--r--xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx113
-rw-r--r--xmlsecurity/source/gpg/CertificateImpl.cxx261
-rw-r--r--xmlsecurity/source/gpg/CertificateImpl.hxx100
-rw-r--r--xmlsecurity/source/gpg/CipherContext.cxx27
-rw-r--r--xmlsecurity/source/gpg/CipherContext.hxx26
-rw-r--r--xmlsecurity/source/gpg/DigestContext.cxx23
-rw-r--r--xmlsecurity/source/gpg/DigestContext.hxx24
-rw-r--r--xmlsecurity/source/gpg/SEInitializer.cxx80
-rw-r--r--xmlsecurity/source/gpg/SecurityEnvironment.cxx232
-rw-r--r--xmlsecurity/source/gpg/SecurityEnvironment.hxx72
-rw-r--r--xmlsecurity/source/gpg/XMLEncryption.cxx37
-rw-r--r--xmlsecurity/source/gpg/XMLEncryption.hxx37
-rw-r--r--xmlsecurity/source/gpg/XMLSecurityContext.cxx87
-rw-r--r--xmlsecurity/source/gpg/XMLSecurityContext.hxx58
-rw-r--r--xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx527
-rw-r--r--xmlsecurity/source/helper/UriBindingHelper.cxx113
-rw-r--r--xmlsecurity/source/helper/documentsignaturehelper.cxx650
-rw-r--r--xmlsecurity/source/helper/documentsignaturemanager.cxx705
-rw-r--r--xmlsecurity/source/helper/ooxmlsecexporter.cxx558
-rw-r--r--xmlsecurity/source/helper/ooxmlsecexporter.hxx47
-rw-r--r--xmlsecurity/source/helper/ooxmlsecparser.cxx1352
-rw-r--r--xmlsecurity/source/helper/ooxmlsecparser.hxx110
-rw-r--r--xmlsecurity/source/helper/pdfsignaturehelper.cxx626
-rw-r--r--xmlsecurity/source/helper/xmlsignaturehelper.cxx714
-rw-r--r--xmlsecurity/source/helper/xsecctl.cxx1004
-rw-r--r--xmlsecurity/source/helper/xsecparser.cxx1632
-rw-r--r--xmlsecurity/source/helper/xsecparser.hxx159
-rw-r--r--xmlsecurity/source/helper/xsecsign.cxx460
-rw-r--r--xmlsecurity/source/helper/xsecverify.cxx630
-rw-r--r--xmlsecurity/source/xmlsec/biginteger.cxx106
-rw-r--r--xmlsecurity/source/xmlsec/certificateextension_certextn.cxx47
-rw-r--r--xmlsecurity/source/xmlsec/certificateextension_certextn.hxx36
-rw-r--r--xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.hxx56
-rw-r--r--xmlsecurity/source/xmlsec/errorcallback.cxx68
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx229
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx56
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/oid.hxx153
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx131
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx66
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx1118
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.hxx173
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx173
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.hxx71
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx786
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx96
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx155
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx312
-rw-r--r--xmlsecurity/source/xmlsec/nss/certerrors.h385
-rw-r--r--xmlsecurity/source/xmlsec/nss/ciphercontext.cxx265
-rw-r--r--xmlsecurity/source/xmlsec/nss/ciphercontext.hxx80
-rw-r--r--xmlsecurity/source/xmlsec/nss/digestcontext.cxx94
-rw-r--r--xmlsecurity/source/xmlsec/nss/digestcontext.hxx59
-rw-r--r--xmlsecurity/source/xmlsec/nss/nssinitializer.cxx638
-rw-r--r--xmlsecurity/source/xmlsec/nss/nssinitializer.hxx68
-rw-r--r--xmlsecurity/source/xmlsec/nss/nssrenam.h41
-rw-r--r--xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.cxx164
-rw-r--r--xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.hxx65
-rw-r--r--xmlsecurity/source/xmlsec/nss/secerror.cxx152
-rw-r--r--xmlsecurity/source/xmlsec/nss/secerror.hxx31
-rw-r--r--xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx890
-rw-r--r--xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx146
-rw-r--r--xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx144
-rw-r--r--xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx55
-rw-r--r--xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx614
-rw-r--r--xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx104
-rw-r--r--xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx150
-rw-r--r--xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx325
-rw-r--r--xmlsecurity/source/xmlsec/saxhelper.cxx364
-rw-r--r--xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.cxx902
-rw-r--r--xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.cxx70
-rw-r--r--xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx79
-rw-r--r--xmlsecurity/source/xmlsec/xmlsec_init.cxx73
-rw-r--r--xmlsecurity/source/xmlsec/xmlstreamio.cxx251
-rw-r--r--xmlsecurity/test_docs/CAs/README.txt383
-rw-r--r--xmlsecurity/test_docs/CAs/Root_1/demoCA/cacert.pem19
-rw-r--r--xmlsecurity/test_docs/CAs/Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL0
-rw-r--r--xmlsecurity/test_docs/CAs/Root_1/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_1/demoCA/newcerts/1000.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Root_1/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Root_1/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_1/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Root_10/demoCA/cacert.pem19
-rw-r--r--xmlsecurity/test_docs/CAs/Root_10/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_10/demoCA/newcerts/1000.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Root_10/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Root_10/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_10/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/cacert.pem19
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt35
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1000.pem57
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1002.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1003.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1004.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1005.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1006.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1007.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1008.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1009.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100A.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100B.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100C.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100D.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100E.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100F.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1010.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1011.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1012.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1013.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1014.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1015.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1016.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1017.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1018.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1019.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101A.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101B.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101C.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101D.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101E.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101F.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1020.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1021.pem61
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1022.pem64
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_11/openssl.cfg298
-rw-r--r--xmlsecurity/test_docs/CAs/Root_2/demoCA/cacert.pem19
-rw-r--r--xmlsecurity/test_docs/CAs/Root_2/demoCA/crl/DO_NOT_CREATE_A_CRL0
-rw-r--r--xmlsecurity/test_docs/CAs/Root_2/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_2/demoCA/newcerts/1000.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Root_2/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Root_2/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_2/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Root_3/demoCA/cacert.pem19
-rw-r--r--xmlsecurity/test_docs/CAs/Root_3/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_3/demoCA/newcerts/1000.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Root_3/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Root_3/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_3/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Root_4/README.txt4
-rw-r--r--xmlsecurity/test_docs/CAs/Root_4/demoCA/cacert.pem19
-rw-r--r--xmlsecurity/test_docs/CAs/Root_4/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt2
-rw-r--r--xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1000.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1001.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Root_4/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Root_4/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_4/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Root_5/demoCA/cacert.pem19
-rw-r--r--xmlsecurity/test_docs/CAs/Root_5/demoCA/crl/DO_NOT_CREATE_A_CRL0
-rw-r--r--xmlsecurity/test_docs/CAs/Root_5/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_5/demoCA/newcerts/1001.pem66
-rw-r--r--xmlsecurity/test_docs/CAs/Root_5/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Root_5/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_5/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Root_6/README.txt5
-rw-r--r--xmlsecurity/test_docs/CAs/Root_6/demoCA/cacert.pem19
-rw-r--r--xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/DO_NOT_INSTALL_THIS_CRL0
-rw-r--r--xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/Root_6.crlbin0 -> 316 bytes
-rw-r--r--xmlsecurity/test_docs/CAs/Root_6/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_6/demoCA/newcerts/1001.pem66
-rw-r--r--xmlsecurity/test_docs/CAs/Root_6/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Root_6/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_6/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Root_7/README.txt10
-rw-r--r--xmlsecurity/test_docs/CAs/Root_7/demoCA/cacert.pem19
-rw-r--r--xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL0
-rw-r--r--xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/Root_7.crlbin0 -> 353 bytes
-rw-r--r--xmlsecurity/test_docs/CAs/Root_7/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt2
-rw-r--r--xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1000.pem66
-rw-r--r--xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1001.pem66
-rw-r--r--xmlsecurity/test_docs/CAs/Root_7/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Root_7/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_7/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Root_8/README.txt9
-rw-r--r--xmlsecurity/test_docs/CAs/Root_8/demoCA/cacert.pem19
-rw-r--r--xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL0
-rw-r--r--xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/Root_8.crlbin0 -> 353 bytes
-rw-r--r--xmlsecurity/test_docs/CAs/Root_8/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt2
-rw-r--r--xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1000.pem66
-rw-r--r--xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1001.pem66
-rw-r--r--xmlsecurity/test_docs/CAs/Root_8/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Root_8/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_8/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Root_9/DO_NOT_INSTALL_THIS_ROOT_CERT.txt1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_9/demoCA/DO_NO_INSTALL_THIS_ROOT_CERTIFICATE0
-rw-r--r--xmlsecurity/test_docs/CAs/Root_9/demoCA/Root_9.crtbin0 -> 776 bytes
-rw-r--r--xmlsecurity/test_docs/CAs/Root_9/demoCA/cacert.pem19
-rw-r--r--xmlsecurity/test_docs/CAs/Root_9/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_9/demoCA/newcerts/1000.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Root_9/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Root_9/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Root_9/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/cacert.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL0
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/newcerts/1000.pem58
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/DO_NOT_INSTALL_THIS_CERTIFICATE0
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/README.txt19
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/DO_NOT_INSTALL_THIS_CERTIFICATE0
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/Sub_CA_1_Root_10.crtbin0 -> 781 bytes
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/cacert.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/DO_NOT_INSTALL_THIS_CRL0
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/Sub_CA_1_Root_10.crlbin0 -> 326 bytes
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/newcerts/1000.pem67
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/openssl.cfg293
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/cacert.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/newcerts/1000.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/req.pem11
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/cacert.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crl/DO_NOT_CREATE_A_CRL0
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/newcerts/1000.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/req.pem11
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/README.txt4
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/cacert.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt2
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1000.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1001.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/README.txt5
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/cacert.pem66
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/DO_NOT_INSTALL_THIS_CRL0
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/Sub_CA_1_Root_5.crlbin0 -> 325 bytes
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/newcerts/1002.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/cacert.pem66
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crl/DO_NOT_CREATE_A_CRL0
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/newcerts/1000.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/README.txt3
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/cacert.pem66
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL0
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/Sub_CA_1_Root_7.crlbin0 -> 362 bytes
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt2
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1000.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1001.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/README.txt13
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/cacert.pem66
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL0
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/Sub_CA_1_Root_8.crlbin0 -> 362 bytes
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt2
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1000.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1001.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/cacert.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/newcerts/1000.pem58
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/README.txt4
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/cacert.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt2
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1001.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1002.pem60
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/README.txt12
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/cacert.pem66
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL0
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/Sub_CA_2_Root_7.crlbin0 -> 362 bytes
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt2
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1000.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1001.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/README.txt13
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/cacert.pem66
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL0
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/Sub_CA_2_Root_8.crlbin0 -> 362 bytes
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crlnumber1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt2
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt.attr1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1002.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1003.pem62
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/private/cakey.pem18
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/serial1
-rw-r--r--xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/openssl.cfg292
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Root_1.crtbin0 -> 776 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Root_10.crtbin0 -> 779 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Root_11.crtbin0 -> 779 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Root_2.crtbin0 -> 776 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Root_3.crtbin0 -> 776 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Root_4.crtbin0 -> 776 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Root_5.crtbin0 -> 776 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Root_6.crtbin0 -> 776 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Root_7.crtbin0 -> 776 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Root_8.crtbin0 -> 776 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_1.crtbin0 -> 778 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_2.crtbin0 -> 778 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_3.crtbin0 -> 778 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_4.crtbin0 -> 778 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_5.crtbin0 -> 842 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_6.crtbin0 -> 842 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_7.crtbin0 -> 842 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_8.crtbin0 -> 829 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_9.crtbin0 -> 778 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_4.crtbin0 -> 778 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_7.crtbin0 -> 842 bytes
-rw-r--r--xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_8.crtbin0 -> 829 bytes
-rw-r--r--xmlsecurity/test_docs/certs/crl/Root_10.crlbin0 -> 317 bytes
-rw-r--r--xmlsecurity/test_docs/certs/crl/Root_11.crlbin0 -> 317 bytes
-rw-r--r--xmlsecurity/test_docs/certs/crl/Root_3.crlbin0 -> 316 bytes
-rw-r--r--xmlsecurity/test_docs/certs/crl/Root_4.crlbin0 -> 353 bytes
-rw-r--r--xmlsecurity/test_docs/certs/crl/Root_9.crlbin0 -> 316 bytes
-rw-r--r--xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_2.crlbin0 -> 325 bytes
-rw-r--r--xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_4.crlbin0 -> 362 bytes
-rw-r--r--xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_9.crlbin0 -> 325 bytes
-rw-r--r--xmlsecurity/test_docs/certs/crl/Sub_CA_2_Root_4.crlbin0 -> 362 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_10_Root_11.crtbin0 -> 739 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_11_Root_11.crtbin0 -> 733 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_12_Root_11.crtbin0 -> 729 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_13_Root_11.crtbin0 -> 739 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_14_Root_11.crtbin0 -> 729 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_15_Root_11.crtbin0 -> 720 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_16_Root_11.crtbin0 -> 739 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_17_Root_11.crtbin0 -> 749 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_18_Root_11.crtbin0 -> 714 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_19_Root_11.crtbin0 -> 710 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_1_Root_11.crtbin0 -> 699 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_1.crtbin0 -> 706 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_10.crtbin0 -> 828 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_2.crtbin0 -> 719 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_3.crtbin0 -> 719 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_4.crtbin0 -> 719 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_5.crtbin0 -> 746 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_6.crtbin0 -> 746 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_7.crtbin0 -> 746 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_8.crtbin0 -> 726 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_9.crtbin0 -> 673 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_4.crtbin0 -> 719 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_7.crtbin0 -> 746 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_8.crtbin0 -> 726 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_20_Root_11.crtbin0 -> 710 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_21_Root_11.crtbin0 -> 727 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_22_Root_11.crtbin0 -> 739 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_23_Root_11.crtbin0 -> 733 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_24_Root_11.crtbin0 -> 729 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_25_Root_11.crtbin0 -> 737 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_26_Root_11.crtbin0 -> 729 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_27_Root_11.crtbin0 -> 705 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_28_Root_11.crtbin0 -> 700 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_29_Root_11.crtbin0 -> 698 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_2_Root_11.crtbin0 -> 695 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_4.crtbin0 -> 719 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_7.crtbin0 -> 746 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_8.crtbin0 -> 726 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_4.crtbin0 -> 719 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_7.crtbin0 -> 746 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_8.crtbin0 -> 726 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_30_Root_11.crtbin0 -> 716 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_31_Root_11.crtbin0 -> 745 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_32_Root_11.crtbin0 -> 591 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_33_Root_11.crtbin0 -> 620 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_34_Root_11.crtbin0 -> 637 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_35_Root_11.crt64
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_3_Root_11.crtbin0 -> 719 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_4_Root_11.crtbin0 -> 738 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_5_Root_11.crtbin0 -> 748 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_6_Root_11.crtbin0 -> 713 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_7_Root_11.crtbin0 -> 709 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_8_Root_11.crtbin0 -> 709 bytes
-rw-r--r--xmlsecurity/test_docs/certs/end_certs/User_9_Root_11.crtbin0 -> 726 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/Root_11.p12bin0 -> 1797 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_10_Root_11.p12bin0 -> 1757 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_11_Root_11.p12bin0 -> 1749 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_12_Root_11.p12bin0 -> 1749 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_13_Root_11.p12bin0 -> 1757 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_14_Root_11.p12bin0 -> 1749 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_15_Root_11.p12bin0 -> 1741 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_16_Root_11.p12bin0 -> 1757 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_17_Root_11.p12bin0 -> 1765 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_18_Root_11.p12bin0 -> 1733 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_19_Root_11.p12bin0 -> 1725 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_1_Root_11.p12bin0 -> 1717 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_1.p12bin0 -> 1725 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_10.p12bin0 -> 1845 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_2.p12bin0 -> 1733 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_3.p12bin0 -> 1733 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_4.p12bin0 -> 1733 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_5.p12bin0 -> 1765 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_6.p12bin0 -> 1765 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_7.p12bin0 -> 1765 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_8.p12bin0 -> 1741 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_9.p12bin0 -> 1693 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_4.p12bin0 -> 1733 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_7.p12bin0 -> 1765 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_8.p12bin0 -> 1741 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_20_Root_11.p12bin0 -> 1725 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_21_Root_11.p12bin0 -> 1741 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_22_Root_11.p12bin0 -> 1757 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_23_Root_11.p12bin0 -> 1749 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_24_Root_11.p12bin0 -> 1749 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_25_Root_11.p12bin0 -> 1757 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_26_Root_11.p12bin0 -> 1749 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_27_Root_11.p12bin0 -> 1725 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_28_Root_11.p12bin0 -> 1717 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_29_Root_11.p12bin0 -> 1717 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_2_Root_11.p12bin0 -> 1709 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_4.p12bin0 -> 1733 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_7.p12bin0 -> 1765 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_8.p12bin0 -> 1741 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_4.p12bin0 -> 1733 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_7.p12bin0 -> 1765 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_8.p12bin0 -> 1741 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_30_Root_11.p12bin0 -> 1733 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_31_Root_11.p12bin0 -> 1765 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_32_Root_11.p12bin0 -> 1605 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_33_Root_11.p12bin0 -> 1732 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_34_Root_11.p12bin0 -> 1714 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_3_Root_11.p12bin0 -> 1733 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_4_Root_11.p12bin0 -> 1757 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_5_Root_11.p12bin0 -> 1765 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_6_Root_11.p12bin0 -> 1733 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_7_Root_11.p12bin0 -> 1725 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_8_Root_11.p12bin0 -> 1725 bytes
-rw-r--r--xmlsecurity/test_docs/certs/p12/User_9_Root_11.p12bin0 -> 1741 bytes
-rw-r--r--xmlsecurity/test_docs/documents/aia_ca_issuers.odtbin0 -> 9511 bytes
-rw-r--r--xmlsecurity/test_docs/documents/aia_ocsp.odtbin0 -> 9376 bytes
-rw-r--r--xmlsecurity/test_docs/documents/aia_ocsp_revoked_chain.odtbin0 -> 9370 bytes
-rw-r--r--xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf.odtbin0 -> 9379 bytes
-rw-r--r--xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf_chain.odtbin0 -> 9378 bytes
-rw-r--r--xmlsecurity/test_docs/documents/crl.odtbin0 -> 9354 bytes
-rw-r--r--xmlsecurity/test_docs/documents/crl_revoked_chain.odtbin0 -> 9352 bytes
-rw-r--r--xmlsecurity/test_docs/documents/crl_revoked_leaf.odtbin0 -> 9363 bytes
-rw-r--r--xmlsecurity/test_docs/documents/crl_revoked_leaf_chain.odtbin0 -> 9351 bytes
-rw-r--r--xmlsecurity/test_docs/documents/crldp.odtbin0 -> 9379 bytes
-rw-r--r--xmlsecurity/test_docs/documents/crldp_no_intermediate_ca_revocation_info.odtbin0 -> 9382 bytes
-rw-r--r--xmlsecurity/test_docs/documents/crldp_no_root_revocation_info.odtbin0 -> 9379 bytes
-rw-r--r--xmlsecurity/test_docs/documents/crldp_revoked_chain.odtbin0 -> 9381 bytes
-rw-r--r--xmlsecurity/test_docs/documents/crldp_revoked_leaf.odtbin0 -> 9380 bytes
-rw-r--r--xmlsecurity/test_docs/documents/crldp_revoked_leaf_chain.odtbin0 -> 9383 bytes
-rw-r--r--xmlsecurity/test_docs/documents/dn_cyrillic_bmpstring.odtbin0 -> 9392 bytes
-rw-r--r--xmlsecurity/test_docs/documents/dn_latin_ext_greak_bmpstring.odtbin0 -> 9388 bytes
-rw-r--r--xmlsecurity/test_docs/documents/dn_multivalue_rdn.odtbin0 -> 9272 bytes
-rw-r--r--xmlsecurity/test_docs/documents/dn_quoting.odtbin0 -> 28429 bytes
-rw-r--r--xmlsecurity/test_docs/documents/dn_single_multivalue_rdn.odtbin0 -> 9299 bytes
-rw-r--r--xmlsecurity/test_docs/documents/dn_single_multivalue_rdn_with_quoting.odtbin0 -> 9313 bytes
-rw-r--r--xmlsecurity/test_docs/documents/incomplete_path.odtbin0 -> 9308 bytes
-rw-r--r--xmlsecurity/test_docs/documents/invalid_ooo2_x_doc1.odtbin0 -> 9550 bytes
-rw-r--r--xmlsecurity/test_docs/documents/invalid_ooo2_x_doc2.odtbin0 -> 6989 bytes
-rw-r--r--xmlsecurity/test_docs/documents/invalid_ooo2_x_macro1.odtbin0 -> 12911 bytes
-rw-r--r--xmlsecurity/test_docs/documents/invalid_ooo2_x_macro2.odtbin0 -> 12929 bytes
-rw-r--r--xmlsecurity/test_docs/documents/invalid_ooo2_x_macro3.odtbin0 -> 13043 bytes
-rw-r--r--xmlsecurity/test_docs/documents/invalid_ooo2_x_macro4.odtbin0 -> 13079 bytes
-rw-r--r--xmlsecurity/test_docs/documents/invalid_ooo2_x_macro5.odtbin0 -> 20336 bytes
-rw-r--r--xmlsecurity/test_docs/documents/invalid_ooo3_2_doc1.odtbin0 -> 9200 bytes
-rw-r--r--xmlsecurity/test_docs/documents/invalid_ooo3_2_doc3.odtbin0 -> 8908 bytes
-rw-r--r--xmlsecurity/test_docs/documents/invalid_ooo3_2_doc4.odtbin0 -> 8997 bytes
-rw-r--r--xmlsecurity/test_docs/documents/invalid_ooo_3_2_doc2.odtbin0 -> 9199 bytes
-rw-r--r--xmlsecurity/test_docs/documents/ocsp_crl.odtbin0 -> 9444 bytes
-rw-r--r--xmlsecurity/test_docs/documents/ocsp_crl_revoked_leaf.odtbin0 -> 9447 bytes
-rw-r--r--xmlsecurity/test_docs/documents/stateOrProvinceName.odtbin0 -> 10534 bytes
-rw-r--r--xmlsecurity/test_docs/documents/valid_no_revocation.odtbin0 -> 9341 bytes
-rw-r--r--xmlsecurity/test_docs/documents/valid_no_root_revocation_info.odtbin0 -> 9349 bytes
-rw-r--r--xmlsecurity/test_docs/documents/valid_no_sub_ca_revocation_info.odtbin0 -> 9352 bytes
-rw-r--r--xmlsecurity/test_docs/documents/valid_ooo2_x_doc1.odtbin0 -> 9880 bytes
-rw-r--r--xmlsecurity/test_docs/documents/valid_ooo2_x_doc_macro.odtbin0 -> 12425 bytes
-rw-r--r--xmlsecurity/test_docs/documents/valid_ooo2_x_doc_unsigned_macro.odtbin0 -> 10821 bytes
-rw-r--r--xmlsecurity/test_docs/documents/valid_ooo3_0_doc1.odtbin0 -> 12565 bytes
-rw-r--r--xmlsecurity/test_docs/documents/valid_ooo3_0_doc_macro.odtbin0 -> 15656 bytes
-rw-r--r--xmlsecurity/test_docs/documents/valid_ooo3_0_doc_unsigned_macro.odtbin0 -> 13975 bytes
-rw-r--r--xmlsecurity/test_docs/documents/valid_ooo3_2_doc1.odtbin0 -> 12514 bytes
-rw-r--r--xmlsecurity/test_docs/documents/valid_ooo3_2_doc_macro.odtbin0 -> 15579 bytes
-rw-r--r--xmlsecurity/test_docs/documents/valid_ooo3_2_doc_unsigned_macro.odtbin0 -> 13929 bytes
-rw-r--r--xmlsecurity/test_docs/test_description.odtbin0 -> 25782 bytes
-rw-r--r--xmlsecurity/test_docs/tools/README.txt24
-rw-r--r--xmlsecurity/test_docs/tools/httpserv/build.xml79
-rw-r--r--xmlsecurity/test_docs/tools/httpserv/manifest.mf3
-rw-r--r--xmlsecurity/test_docs/tools/httpserv/nbproject/build-impl.xml700
-rw-r--r--xmlsecurity/test_docs/tools/httpserv/nbproject/genfiles.properties9
-rw-r--r--xmlsecurity/test_docs/tools/httpserv/nbproject/project.properties65
-rw-r--r--xmlsecurity/test_docs/tools/httpserv/nbproject/project.xml15
-rw-r--r--xmlsecurity/test_docs/tools/httpserv/src/httpserv/Main.java190
-rw-r--r--xmlsecurity/uiconfig/ui/certdetails.ui119
-rw-r--r--xmlsecurity/uiconfig/ui/certgeneral.ui254
-rw-r--r--xmlsecurity/uiconfig/ui/certpage.ui196
-rw-r--r--xmlsecurity/uiconfig/ui/digitalsignaturesdialog.ui528
-rw-r--r--xmlsecurity/uiconfig/ui/macrosecuritydialog.ui208
-rw-r--r--xmlsecurity/uiconfig/ui/securitylevelpage.ui160
-rw-r--r--xmlsecurity/uiconfig/ui/securitytrustpage.ui392
-rw-r--r--xmlsecurity/uiconfig/ui/selectcertificatedialog.ui301
-rw-r--r--xmlsecurity/uiconfig/ui/viewcertdialog.ui227
-rw-r--r--xmlsecurity/util/xmlsecurity.component31
-rw-r--r--xmlsecurity/util/xmlsecurity.component.dds7
-rw-r--r--xmlsecurity/util/xsec_xmlsec.component60
-rw-r--r--xmlsecurity/util/xsec_xmlsec.component.gpg7
-rw-r--r--xmlsecurity/util/xsec_xmlsec.component.nss7
-rw-r--r--xmlsecurity/util/xsec_xmlsec.component.nss_mscrypt10
-rw-r--r--xmlsecurity/workben/pdfverify.cxx216
699 files changed, 58122 insertions, 0 deletions
diff --git a/xmlsecurity/AllLangMoTarget_xsc.mk b/xmlsecurity/AllLangMoTarget_xsc.mk
new file mode 100644
index 000000000..90b80207c
--- /dev/null
+++ b/xmlsecurity/AllLangMoTarget_xsc.mk
@@ -0,0 +1,13 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+$(eval $(call gb_AllLangMoTarget_AllLangMoTarget,xsc))
+
+$(eval $(call gb_AllLangMoTarget_set_polocation,xsc,xmlsecurity))
+
+# vim: set noet sw=4 ts=4:
diff --git a/xmlsecurity/CppunitTest_qa_certext.mk b/xmlsecurity/CppunitTest_qa_certext.mk
new file mode 100644
index 000000000..faa5459d3
--- /dev/null
+++ b/xmlsecurity/CppunitTest_qa_certext.mk
@@ -0,0 +1,27 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,xmlsecurity_qa_certext))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_qa_certext))
+
+$(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_qa_certext,\
+ cppu \
+ neon \
+ sal \
+ svl \
+ test \
+ tl \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,xmlsecurity_qa_certext,\
+ xmlsecurity/qa/certext/SanCertExt \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/xmlsecurity/CppunitTest_xmlsecurity_dialogs_test.mk b/xmlsecurity/CppunitTest_xmlsecurity_dialogs_test.mk
new file mode 100644
index 000000000..945c33af7
--- /dev/null
+++ b/xmlsecurity/CppunitTest_xmlsecurity_dialogs_test.mk
@@ -0,0 +1,68 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitScreenShot,xmlsecurity_dialogs_test))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,xmlsecurity_dialogs_test, \
+ xmlsecurity/qa/unit/xmlsecurity-dialogs-test \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_dialogs_test))
+
+$(eval $(call gb_CppunitTest_set_include,desktop_dialogs_test,\
+ -I$(SRCDIR)/xmlsecurity/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_dialogs_test, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ drawinglayer \
+ editeng \
+ i18nlangtag \
+ i18nutil \
+ msfilter \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sfx \
+ sot \
+ svl \
+ svt \
+ test \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_use_external,xmlsecurity_dialogs_test,boost_headers))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_dialogs_test))
+
+$(eval $(call gb_CppunitTest_use_ure,xmlsecurity_dialogs_test))
+$(eval $(call gb_CppunitTest_use_vcl_non_headless_with_windows,xmlsecurity_dialogs_test))
+
+$(eval $(call gb_CppunitTest_use_rdb,xmlsecurity_dialogs_test,services))
+
+$(eval $(call gb_CppunitTest_use_configuration,xmlsecurity_dialogs_test))
+
+$(eval $(call gb_CppunitTest_use_uiconfigs,xmlsecurity_dialogs_test,\
+ xmlsec \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk b/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk
new file mode 100644
index 000000000..667acc97e
--- /dev/null
+++ b/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk
@@ -0,0 +1,70 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,xmlsecurity_pdfsigning))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,xmlsecurity_pdfsigning, \
+ xmlsecurity/qa/unit/pdfsigning/pdfsigning \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_pdfsigning, \
+ comphelper \
+ cppuhelper \
+ cppu \
+ sal \
+ sax \
+ sfx \
+ test \
+ tl \
+ unotest \
+ utl \
+ xmlsecurity \
+ vcl \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_pdfsigning,\
+ boost_headers \
+))
+
+ifneq ($(OS),WNT)
+ifneq (,$(ENABLE_NSS))
+$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_pdfsigning,\
+ nssutil3 \
+))
+endif
+endif
+
+$(eval $(call gb_CppunitTest_set_include,xmlsecurity_pdfsigning,\
+ -I$(SRCDIR)/xmlsecurity/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_pdfsigning))
+
+$(eval $(call gb_CppunitTest_use_ure,xmlsecurity_pdfsigning))
+$(eval $(call gb_CppunitTest_use_vcl,xmlsecurity_pdfsigning))
+
+$(eval $(call gb_CppunitTest_use_rdb,xmlsecurity_pdfsigning,services))
+
+$(eval $(call gb_CppunitTest_use_configuration,xmlsecurity_pdfsigning))
+
+ifeq ($(ENABLE_POPPLER),TRUE)
+$(eval $(call gb_CppunitTest_use_executable,xmlsecurity_pdfsigning,xpdfimport))
+endif
+
+ifeq ($(OS),WNT)
+# Initializing DocumentSignatureManager will require gpgme-w32spawn.exe in workdir/LinkTarget/Executable
+$(eval $(call gb_CppunitTest_use_packages,xmlsecurity_pdfsigning,\
+ $(call gb_Helper_optional,GPGMEPP,gpgmepp)\
+))
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
new file mode 100644
index 000000000..91b4ae39f
--- /dev/null
+++ b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
@@ -0,0 +1,94 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,xmlsecurity_signing))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,xmlsecurity_signing, \
+ xmlsecurity/qa/unit/signing/signing \
+ xmlsecurity/qa/unit/signing/signing2 \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_signing, \
+ comphelper \
+ cppuhelper \
+ cppu \
+ sal \
+ sax \
+ sfx \
+ svx \
+ test \
+ tl \
+ unotest \
+ utl \
+ vcl \
+ xmlsecurity \
+ xsec_xmlsec \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_signing,\
+ boost_headers \
+ libxml2 \
+))
+
+ifneq ($(OS),WNT)
+ifneq (,$(ENABLE_NSS))
+$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_signing,\
+ nssutil3 \
+))
+endif
+endif
+
+$(eval $(call gb_CppunitTest_set_include,xmlsecurity_signing,\
+ -I$(SRCDIR)/xmlsecurity/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_signing))
+
+$(eval $(call gb_CppunitTest_use_ure,xmlsecurity_signing))
+$(eval $(call gb_CppunitTest_use_vcl,xmlsecurity_signing))
+
+$(eval $(call gb_CppunitTest_use_uiconfigs,xmlsecurity_signing, \
+ svt \
+))
+
+$(eval $(call gb_CppunitTest_use_rdb,xmlsecurity_signing,services))
+
+$(eval $(call gb_CppunitTest_use_configuration,xmlsecurity_signing))
+
+ifeq ($(ENABLE_POPPLER),TRUE)
+$(eval $(call gb_CppunitTest_use_executable,xmlsecurity_signing,xpdfimport))
+endif
+
+# various hacks to make unit test work on Linux more often
+ifeq ($(OS),LINUX)
+# reset the LD_LIBRARY_PATH for spawned GPG processes
+$(call gb_CppunitTest_get_target,xmlsecurity_signing): \
+ EXTRA_ENV_VARS := \
+ LIBO_LD_PATH=$$LD_LIBRARY_PATH
+endif
+
+$(eval $(call gb_CppunitTest_use_custom_headers,xmlsecurity_signing,\
+ officecfg/registry \
+))
+
+ifeq ($(OS),WNT)
+# Initializing DocumentSignatureManager will require gpgme-w32spawn.exe in workdir/LinkTarget/Executable
+$(eval $(call gb_CppunitTest_use_packages,xmlsecurity_signing,\
+ $(call gb_Helper_optional,GPGMEPP,gpgmepp)\
+))
+endif
+
+$(eval $(call gb_CppunitTest_add_arguments,xmlsecurity_signing, \
+ -env:arg-env=$(gb_Helper_LIBRARY_PATH_VAR)"$$$${$(gb_Helper_LIBRARY_PATH_VAR)+=$$$$$(gb_Helper_LIBRARY_PATH_VAR)}" \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/xmlsecurity/Executable_pdfverify.mk b/xmlsecurity/Executable_pdfverify.mk
new file mode 100644
index 000000000..ed8e9559f
--- /dev/null
+++ b/xmlsecurity/Executable_pdfverify.mk
@@ -0,0 +1,35 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Executable_Executable,pdfverify))
+
+$(eval $(call gb_Executable_use_sdk_api,pdfverify))
+
+$(eval $(call gb_Executable_use_external,pdfverify,boost_headers))
+
+$(eval $(call gb_Executable_set_include,pdfverify,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/xmlsecurity/inc \
+))
+
+$(eval $(call gb_Executable_use_libraries,pdfverify,\
+ comphelper \
+ cppu \
+ cppuhelper \
+ sal \
+ tl \
+ vcl \
+ xmlsecurity \
+))
+
+$(eval $(call gb_Executable_add_exception_objects,pdfverify,\
+ xmlsecurity/workben/pdfverify \
+))
+
+# vim:set noet sw=4 ts=4:
diff --git a/xmlsecurity/IwyuFilter_xmlsecurity.yaml b/xmlsecurity/IwyuFilter_xmlsecurity.yaml
new file mode 100644
index 000000000..b3ea0f00e
--- /dev/null
+++ b/xmlsecurity/IwyuFilter_xmlsecurity.yaml
@@ -0,0 +1,134 @@
+---
+assumeFilename: xmlsecurity/source/xmlsec/xmlsec_init.cxx
+excludelist:
+ xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx:
+ # complete type is needed
+ - com/sun/star/security/DocumentSignatureInformation.hpp
+ xmlsecurity/inc/UriBindingHelper.hxx:
+ # Base class needs complete type
+ - com/sun/star/xml/crypto/XUriBinding.hpp
+ xmlsecurity/inc/xsecctl.hxx:
+ # Base class needs complete type
+ - com/sun/star/xml/crypto/sax/XSAXEventKeeperStatusChangeListener.hpp
+ - com/sun/star/xml/crypto/sax/XSignatureCreationResultListener.hpp
+ - com/sun/star/xml/crypto/sax/XSignatureVerifyResultListener.hpp
+ # Needed on WIN32 for rtl::Reference<UriBindingHelper> to compile
+ - UriBindingHelper.hxx
+ xmlsecurity/inc/framework/securityengine.hxx:
+ # Base class needs complete type
+ - com/sun/star/xml/crypto/XXMLSignature.hpp
+ - com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp
+ - com/sun/star/xml/crypto/sax/XSAXEventKeeper.hpp
+ xmlsecurity/inc/framework/signaturecreatorimpl.hxx:
+ # Base class needs complete type
+ - framework/signatureengine.hxx
+ - com/sun/star/xml/crypto/sax/XBlockerMonitor.hpp
+ - com/sun/star/xml/crypto/sax/XSignatureCreationResultBroadcaster.hpp
+ - com/sun/star/lang/XInitialization.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ xmlsecurity/inc/framework/saxeventkeeperimpl.hxx:
+ # Base class needs complete type
+ - com/sun/star/xml/crypto/sax/XSecuritySAXEventKeeper.hpp
+ - com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp
+ - com/sun/star/xml/crypto/sax/XSAXEventKeeperStatusChangeBroadcaster.hpp
+ - com/sun/star/xml/sax/XDocumentHandler.hpp
+ - com/sun/star/lang/XInitialization.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ xmlsecurity/inc/framework/signatureverifierimpl.hxx:
+ # Base class needs complete type
+ - framework/signatureengine.hxx
+ - com/sun/star/xml/crypto/sax/XSignatureVerifyResultBroadcaster.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/lang/XInitialization.hpp
+ xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx:
+ # Base class needs complete type
+ - com/sun/star/xml/crypto/XXMLSignatureTemplate.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ xmlsecurity/inc/gpg/SEInitializer.hxx:
+ # Base class needs complete type
+ - com/sun/star/xml/crypto/XSEInitializer.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx:
+ # Base class needs complete type
+ - com/sun/star/xml/crypto/XXMLSignature.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx:
+ # Base class needs complete type
+ - com/sun/star/xml/wrapper/XXMLDocumentWrapper.hpp
+ - com/sun/star/xml/csax/XCompressedDocumentHandler.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ xmlsecurity/source/gpg/CipherContext.hxx:
+ # Base class needs complete type
+ - com/sun/star/xml/crypto/XCipherContext.hpp
+ xmlsecurity/source/gpg/DigestContext.hxx:
+ # Base class needs complete type
+ - com/sun/star/xml/crypto/XDigestContext.hpp
+ xmlsecurity/source/gpg/CertificateImpl.hxx:
+ # Base class needs complete type
+ - com/sun/star/security/XCertificate.hpp
+ - com/sun/star/lang/XUnoTunnel.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ xmlsecurity/source/gpg/GpgComponentFactory.cxx:
+ # Silence warning due to incorrect include path
+ - com/sun/star/lang/XSingleServiceFactory.hpp
+ xmlsecurity/source/gpg/SecurityEnvironment.hxx:
+ # Base class needs complete type
+ - com/sun/star/xml/crypto/XSecurityEnvironment.hpp
+ - com/sun/star/lang/XUnoTunnel.hpp
+ xmlsecurity/source/gpg/XMLSecurityContext.hxx:
+ # Base class needs complete type
+ - com/sun/star/xml/crypto/XXMLSecurityContext.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ xmlsecurity/source/gpg/XMLEncryption.hxx:
+ # Base class needs complete type
+ - com/sun/star/xml/crypto/XXMLEncryption.hpp
+ xmlsecurity/source/helper/ooxmlsecparser.hxx:
+ # Base class needs complete type
+ - com/sun/star/xml/sax/XDocumentHandler.hpp
+ - com/sun/star/lang/XInitialization.hpp
+ xmlsecurity/source/helper/xsecparser.hxx:
+ # Base class needs complete type
+ - com/sun/star/xml/sax/XDocumentHandler.hpp
+ - com/sun/star/lang/XInitialization.hpp
+ xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.hxx:
+ # Base class needs complete type
+ - com/sun/star/security/XCertificateExtension.hpp
+ xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx:
+ # Base class needs complete type
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/lang/XUnoTunnel.hpp
+ - com/sun/star/xml/wrapper/XXMLElementWrapper.hpp
+ xmlsecurity/source/xmlsec/errorcallback.cxx:
+ # Needed for xmlsec/errors.h
+ - xmlsec-wrapper.h
+ xmlsecurity/source/xmlsec/xmlstreamio.cxx:
+ # comphelper::ScopeGuard is in use but not noticed by IWYU
+ - comphelper/scopeguard.hxx
+ xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.hxx:
+ # Base class needs complete type
+ - com/sun/star/security/XSanExtension.hpp
+ xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx:
+ # Base class needs complete type
+ - com/sun/star/security/XCertificate.hpp
+ - com/sun/star/lang/XUnoTunnel.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx:
+ # Base class needs complete type
+ - nssinitializer.hxx
+ - com/sun/star/xml/crypto/XSEInitializer.hpp
+ xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx:
+ # Base class needs complete type
+ - com/sun/star/xml/crypto/XSecurityEnvironment.hpp
+ - com/sun/star/xml/crypto/XCertificateCreator.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/lang/XUnoTunnel.hpp
+ xmlsecurity/source/xmlsec/nss/secerror.cxx:
+ # Used as array initializer
+ - certerrors.h
+ # Needed for macros used by certerrors.h
+ - nss.h
+ xmlsecurity/qa/unit/signing/signing.cxx:
+ # Don't replace URE header with impl. detail
+ - osl/thread.hxx
+ xmlsecurity/workben/pdfverify.cxx:
+ - comphelper/scopeguard.hxx
diff --git a/xmlsecurity/Library_xmlsecurity.mk b/xmlsecurity/Library_xmlsecurity.mk
new file mode 100644
index 000000000..8507b4bab
--- /dev/null
+++ b/xmlsecurity/Library_xmlsecurity.mk
@@ -0,0 +1,112 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Library_Library,xmlsecurity))
+
+$(eval $(call gb_Library_set_componentfile,xmlsecurity,xmlsecurity/util/xmlsecurity,services))
+
+$(eval $(call gb_Library_set_include,xmlsecurity,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/xmlsecurity/inc \
+))
+
+$(eval $(call gb_Library_add_defs,xmlsecurity,\
+ -DXMLSECURITY_DLLIMPLEMENTATION \
+))
+
+$(eval $(call gb_Library_use_externals,xmlsecurity,\
+ boost_headers \
+))
+
+$(eval $(call gb_Library_set_precompiled_header,xmlsecurity,xmlsecurity/inc/pch/precompiled_xmlsecurity))
+
+$(eval $(call gb_Library_use_sdk_api,xmlsecurity))
+
+$(eval $(call gb_Library_use_libraries,xmlsecurity,\
+ comphelper \
+ cppu \
+ cppuhelper \
+ sal \
+ sax \
+ svl \
+ sfx \
+ svt \
+ svxcore \
+ tl \
+ ucbhelper \
+ utl \
+ vcl \
+ xo \
+ i18nlangtag \
+ xsec_xmlsec \
+))
+
+$(eval $(call gb_Library_add_exception_objects,xmlsecurity,\
+ xmlsecurity/source/component/certificatecontainer \
+ xmlsecurity/source/dialogs/certificatechooser \
+ xmlsecurity/source/dialogs/certificateviewer \
+ xmlsecurity/source/dialogs/digitalsignaturesdialog \
+ xmlsecurity/source/dialogs/macrosecurity \
+ xmlsecurity/source/framework/buffernode \
+ xmlsecurity/source/framework/elementcollector \
+ xmlsecurity/source/framework/elementmark \
+ xmlsecurity/source/framework/saxeventkeeperimpl \
+ xmlsecurity/source/framework/securityengine \
+ xmlsecurity/source/framework/signaturecreatorimpl \
+ xmlsecurity/source/framework/signatureengine \
+ xmlsecurity/source/framework/signatureverifierimpl \
+ xmlsecurity/source/framework/xmlsignaturetemplateimpl \
+ xmlsecurity/source/helper/documentsignaturehelper \
+ xmlsecurity/source/helper/documentsignaturemanager \
+ xmlsecurity/source/helper/ooxmlsecparser \
+ xmlsecurity/source/helper/ooxmlsecexporter \
+ xmlsecurity/source/helper/pdfsignaturehelper \
+ xmlsecurity/source/helper/UriBindingHelper \
+ xmlsecurity/source/helper/xsecctl \
+ xmlsecurity/source/helper/xsecparser \
+ xmlsecurity/source/helper/xsecsign \
+))
+
+ifneq (,$(or $(ENABLE_NSS),$(filter WNT,$(OS))))
+$(eval $(call gb_Library_add_exception_objects,xmlsecurity,\
+ xmlsecurity/source/component/documentdigitalsignatures \
+ xmlsecurity/source/helper/xmlsignaturehelper \
+ xmlsecurity/source/helper/xsecverify \
+))
+
+$(eval $(call gb_Library_add_componentimpl,xmlsecurity,dds))
+endif
+
+$(eval $(call gb_Library_use_externals,xmlsecurity,\
+ libxml2 \
+))
+ifeq ($(OS),WNT)
+$(eval $(call gb_Library_add_defs,xmlsecurity,\
+ -DXMLSEC_CRYPTO_MSCRYPTO \
+))
+$(eval $(call gb_Library_use_system_win32_libs,xmlsecurity,\
+ crypt32 \
+ Ole32 \
+ Shell32 \
+))
+else
+ifneq (,$(filter DESKTOP,$(BUILD_TYPE))$(filter ANDROID,$(OS)))
+ifeq (TRUE,$(ENABLE_NSS))
+$(eval $(call gb_Library_add_defs,xmlsecurity,\
+ -DXMLSEC_CRYPTO_NSS \
+))
+$(eval $(call gb_Library_use_externals,xmlsecurity,\
+ nss3 \
+ plc4 \
+))
+endif
+endif # BUILD_TYPE=DESKTOP
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/xmlsecurity/Library_xsec_xmlsec.mk b/xmlsecurity/Library_xsec_xmlsec.mk
new file mode 100644
index 000000000..615c3eba0
--- /dev/null
+++ b/xmlsecurity/Library_xsec_xmlsec.mk
@@ -0,0 +1,188 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Library_Library,xsec_xmlsec))
+
+$(eval $(call gb_Library_set_componentfile,xsec_xmlsec,xmlsecurity/util/xsec_xmlsec,services))
+
+$(eval $(call gb_Library_add_componentimpls,xsec_xmlsec, \
+ $(if $(ENABLE_GPGMEPP),gpg) \
+ $(if $(or $(ENABLE_NSS),$(filter WNT,$(OS))),nss_mscrypt) \
+ $(if $(ENABLE_NSS),nss) \
+))
+
+$(eval $(call gb_Library_set_include,xsec_xmlsec,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/xmlsecurity/inc \
+ -I$(SRCDIR)/xmlsecurity/source/gpg \
+ -I$(SRCDIR)/xmlsecurity/source/xmlsec \
+ -I$(call gb_UnpackedTarball_get_dir,xmlsec/include) \
+))
+
+$(eval $(call gb_Library_use_custom_headers,xsec_xmlsec,\
+ officecfg/registry \
+))
+
+$(eval $(call gb_Library_use_sdk_api,xsec_xmlsec))
+
+$(eval $(call gb_Library_add_defs,xsec_xmlsec,\
+ -DXMLSEC_NO_XSLT \
+ -DXSECXMLSEC_DLLIMPLEMENTATION \
+))
+
+$(eval $(call gb_Library_set_precompiled_header,xsec_xmlsec,xmlsecurity/inc/pch/precompiled_xsec_xmlsec))
+
+$(eval $(call gb_Library_use_libraries,xsec_xmlsec,\
+ comphelper \
+ cppu \
+ cppuhelper \
+ sal \
+ svl \
+ tl \
+ xo \
+ utl \
+))
+
+ifeq ($(SYSTEM_XMLSEC),)
+$(eval $(call gb_Library_use_packages,xsec_xmlsec,\
+ xmlsec \
+))
+endif
+
+$(eval $(call gb_Library_use_externals,xsec_xmlsec,\
+ boost_headers \
+ $(if $(ENABLE_GPGMEPP),gpgmepp) \
+ libxml2 \
+ xmlsec \
+))
+
+$(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\
+ xmlsecurity/source/xmlsec/biginteger \
+ xmlsecurity/source/xmlsec/certificateextension_certextn \
+ xmlsecurity/source/xmlsec/errorcallback \
+ xmlsecurity/source/xmlsec/saxhelper \
+ xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl \
+ xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl \
+ xmlsecurity/source/xmlsec/xmlsec_init \
+ xmlsecurity/source/xmlsec/xmlstreamio \
+))
+
+ifeq ($(ENABLE_GPGMEPP),TRUE)
+$(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\
+ xmlsecurity/source/gpg/CertificateImpl \
+ xmlsecurity/source/gpg/CipherContext \
+ xmlsecurity/source/gpg/DigestContext \
+ xmlsecurity/source/gpg/SecurityEnvironment \
+ xmlsecurity/source/gpg/SEInitializer \
+ xmlsecurity/source/gpg/XMLEncryption \
+ xmlsecurity/source/gpg/XMLSecurityContext \
+ xmlsecurity/source/gpg/xmlsignature_gpgimpl \
+))
+endif
+
+ifeq ($(OS),WNT)
+
+$(eval $(call gb_Library_add_defs,xsec_xmlsec,\
+ -DXMLSEC_CRYPTO_MSCRYPTO \
+))
+
+$(eval $(call gb_Library_add_libs,xsec_xmlsec,\
+ $(call gb_UnpackedTarball_get_dir,xmlsec)/win32/binaries/libxmlsec-mscng.lib \
+ $(call gb_UnpackedTarball_get_dir,xmlsec)/win32/binaries/libxmlsec.lib \
+))
+
+$(eval $(call gb_Library_use_system_win32_libs,xsec_xmlsec,\
+ crypt32 \
+ advapi32 \
+ ncrypt \
+))
+
+$(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\
+ xmlsecurity/source/xmlsec/mscrypt/akmngr \
+ xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl \
+ xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl \
+ xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl \
+ xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl \
+ xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl \
+ xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl \
+))
+
+ifeq ($(ENABLE_NSS),TRUE)
+
+$(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\
+ xmlsecurity/source/xmlsec/nss/ciphercontext \
+ xmlsecurity/source/xmlsec/nss/digestcontext \
+ xmlsecurity/source/xmlsec/nss/nssinitializer \
+))
+
+# nss3 after static libs to appease --as-needed linkers
+$(eval $(call gb_Library_use_externals,xsec_xmlsec,\
+ nss3 \
+))
+
+endif
+
+else # !$(OS),WNT
+
+ifeq ($(SYSTEM_XMLSEC),)
+$(eval $(call gb_Library_add_libs,xsec_xmlsec,\
+ $(call gb_UnpackedTarball_get_dir,xmlsec)/src/.libs/libxmlsec1.a \
+))
+endif
+
+ifeq ($(ENABLE_NSS),TRUE)
+
+ifeq ($(SYSTEM_XMLSEC),)
+$(eval $(call gb_Library_add_libs,xsec_xmlsec,\
+ $(call gb_UnpackedTarball_get_dir,xmlsec)/src/nss/.libs/libxmlsec1-nss.a \
+))
+endif
+
+$(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\
+ xmlsecurity/source/xmlsec/nss/ciphercontext \
+ xmlsecurity/source/xmlsec/nss/digestcontext \
+ xmlsecurity/source/xmlsec/nss/nssinitializer \
+ xmlsecurity/source/xmlsec/nss/sanextension_nssimpl \
+ xmlsecurity/source/xmlsec/nss/secerror \
+ xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl \
+ xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl \
+ xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl \
+ xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl \
+ xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl \
+))
+
+$(eval $(call gb_Library_add_defs,xsec_xmlsec,\
+ -DXMLSEC_CRYPTO_NSS \
+))
+
+$(eval $(call gb_Library_use_externals,xsec_xmlsec,\
+ plc4 \
+))
+# nss3 after static libs to appease --as-needed linkers
+$(eval $(call gb_Library_use_externals,xsec_xmlsec,\
+ nss3 \
+))
+
+else # ! $(ENABLE_NSS)
+
+ifeq ($(ENABLE_OPENSSL),TRUE)
+$(eval $(call gb_Library_use_external,xsec_xmlsec,openssl))
+endif
+
+endif # !$(ENABLE_NSS)
+
+ifeq ($(OS),SOLARIS)
+$(eval $(call gb_Library_add_libs,xsec_xmlsec,\
+ -ldl \
+))
+endif
+
+endif # !$(OS),WNT
+
+# vim: set noet sw=4 ts=4:
diff --git a/xmlsecurity/Makefile b/xmlsecurity/Makefile
new file mode 100644
index 000000000..0997e6284
--- /dev/null
+++ b/xmlsecurity/Makefile
@@ -0,0 +1,14 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
+
+include $(module_directory)/../solenv/gbuild/partial_build.mk
+
+# vim: set noet sw=4 ts=4:
diff --git a/xmlsecurity/Module_xmlsecurity.mk b/xmlsecurity/Module_xmlsecurity.mk
new file mode 100644
index 000000000..62852c0a4
--- /dev/null
+++ b/xmlsecurity/Module_xmlsecurity.mk
@@ -0,0 +1,48 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Module_Module,xmlsecurity))
+
+$(eval $(call gb_Module_add_targets,xmlsecurity,\
+ Library_xmlsecurity \
+ $(if $(ENABLE_NSS)$(ENABLE_OPENSSL),Library_xsec_xmlsec) \
+ UIConfig_xmlsec \
+))
+
+$(eval $(call gb_Module_add_slowcheck_targets,xmlsecurity,\
+ CppunitTest_xmlsecurity_pdfsigning \
+))
+
+$(eval $(call gb_Module_add_subsequentcheck_targets,xmlsecurity,\
+ CppunitTest_xmlsecurity_signing \
+))
+
+$(eval $(call gb_Module_add_l10n_targets,xmlsecurity,\
+ AllLangMoTarget_xsc \
+))
+
+# failing
+#$(eval $(call gb_Module_add_check_targets,xmlsecurity,\
+ CppunitTest_qa_certext \
+))
+
+# screenshots
+$(eval $(call gb_Module_add_screenshot_targets,xmlsecurity,\
+ CppunitTest_xmlsecurity_dialogs_test \
+))
+
+ifneq (,$(filter DESKTOP,$(BUILD_TYPE)))
+ifneq (,$(or $(ENABLE_NSS),$(filter WNT,$(OS))))
+$(eval $(call gb_Module_add_targets,xmlsecurity,\
+ $(if $(DISABLE_DYNLOADING),,Executable_pdfverify) \
+))
+endif
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/xmlsecurity/README.md b/xmlsecurity/README.md
new file mode 100644
index 000000000..b983f5dc5
--- /dev/null
+++ b/xmlsecurity/README.md
@@ -0,0 +1,32 @@
+# Stuff for Document Signing
+
+This code provides dialogs, and infrastructure wrapping `libxmlsec` and
+`gpgme` that implements document signing.
+
+For signing a document, a personal key pair is used, which consists of a
+private key and a public key, which is added to the document in addition
+to the digital signature of the document, when signing it.
+
+The document signing can be done both for the source ODF/OOXML files and
+the exported PDF files. It is also possible to sign existing PDF files.
+
+To test the signed PDFs, one can use the `pdfverify` in this way:
+
+ ./bin/run pdfverify $PWD/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf
+
+The file parameter should be an absolute path.
+
+This is the output of `pdfverify` for `2good.pdf`:
+
+```
+verifying signatures
+found 2 signatures
+signature #0: digest match? 1
+signature #0: partial? 0
+signature #1: digest match? 1
+signature #1: partial? 0
+```
+
+## References
+* [Adobe: Digital Signatures in a PDF](https://www.adobe.com/devnet-docs/etk_deprecated/tools/DigSig/Acrobat\_DigitalSignatures_in_PDF.pdf)
+* [Adobe: Acrobat DC Digital Signatures - Supported Standards](https://www.adobe.com/devnet-docs/acrobatetk/tools/DigSigDC/standards.html)
diff --git a/xmlsecurity/UIConfig_xmlsec.mk b/xmlsecurity/UIConfig_xmlsec.mk
new file mode 100644
index 000000000..06482e2a2
--- /dev/null
+++ b/xmlsecurity/UIConfig_xmlsec.mk
@@ -0,0 +1,24 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_UIConfig_UIConfig,xmlsec))
+
+$(eval $(call gb_UIConfig_add_uifiles,xmlsec,\
+ xmlsecurity/uiconfig/ui/certpage \
+ xmlsecurity/uiconfig/ui/certdetails \
+ xmlsecurity/uiconfig/ui/certgeneral \
+ xmlsecurity/uiconfig/ui/digitalsignaturesdialog \
+ xmlsecurity/uiconfig/ui/securitylevelpage \
+ xmlsecurity/uiconfig/ui/securitytrustpage \
+ xmlsecurity/uiconfig/ui/selectcertificatedialog \
+ xmlsecurity/uiconfig/ui/macrosecuritydialog \
+ xmlsecurity/uiconfig/ui/viewcertdialog \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/xmlsecurity/doc/OpenDocumentSignatures-TestIntegration.sxw b/xmlsecurity/doc/OpenDocumentSignatures-TestIntegration.sxw
new file mode 100644
index 000000000..2973f08c8
--- /dev/null
+++ b/xmlsecurity/doc/OpenDocumentSignatures-TestIntegration.sxw
Binary files differ
diff --git a/xmlsecurity/doc/OpenDocumentSignatures-Workflow.sxd b/xmlsecurity/doc/OpenDocumentSignatures-Workflow.sxd
new file mode 100644
index 000000000..abc5f32c6
--- /dev/null
+++ b/xmlsecurity/doc/OpenDocumentSignatures-Workflow.sxd
Binary files differ
diff --git a/xmlsecurity/doc/OpenDocumentSignatures.sxw b/xmlsecurity/doc/OpenDocumentSignatures.sxw
new file mode 100644
index 000000000..9b453e0d8
--- /dev/null
+++ b/xmlsecurity/doc/OpenDocumentSignatures.sxw
Binary files differ
diff --git a/xmlsecurity/doc/XMLSecurityFramework.sxw b/xmlsecurity/doc/XMLSecurityFramework.sxw
new file mode 100644
index 000000000..c778e1c1e
--- /dev/null
+++ b/xmlsecurity/doc/XMLSecurityFramework.sxw
Binary files differ
diff --git a/xmlsecurity/inc/UriBindingHelper.hxx b/xmlsecurity/inc/UriBindingHelper.hxx
new file mode 100644
index 000000000..67c9ae69f
--- /dev/null
+++ b/xmlsecurity/inc/UriBindingHelper.hxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/xml/crypto/XUriBinding.hpp>
+
+namespace com::sun::star {
+ namespace io { class XInputStream; }
+ namespace embed { class XStorage; }
+}
+
+// XUriBinding
+
+class UriBindingHelper final : public cppu::WeakImplHelper< css::xml::crypto::XUriBinding >
+{
+private:
+ css::uno::Reference < css::embed::XStorage > mxStorage;
+
+public:
+ UriBindingHelper();
+ explicit UriBindingHelper( const css::uno::Reference < css::embed::XStorage >& rxStorage );
+
+ void SAL_CALL setUriBinding( const OUString& uri, const css::uno::Reference< css::io::XInputStream >& aInputStream ) override;
+
+ css::uno::Reference< css::io::XInputStream > SAL_CALL getUriBinding( const OUString& uri ) override;
+
+ static css::uno::Reference < css::io::XInputStream > OpenInputStream( const css::uno::Reference < css::embed::XStorage >& rxStore, const OUString& rURI );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/biginteger.hxx b/xmlsecurity/inc/biginteger.hxx
new file mode 100644
index 000000000..fc99320c7
--- /dev/null
+++ b/xmlsecurity/inc/biginteger.hxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <rtl/ustring.hxx>
+
+#include <com/sun/star/uno/Sequence.h>
+
+#include "xsecxmlsecdllapi.h"
+
+namespace xmlsecurity
+{
+XSECXMLSEC_DLLPUBLIC OUString bigIntegerToNumericString(const css::uno::Sequence<sal_Int8>& serial);
+XSECXMLSEC_DLLPUBLIC css::uno::Sequence<sal_Int8>
+numericStringToBigInteger(std::u16string_view serialNumber);
+
+// DNs read as strings from XML files may need to be mangled for compatibility
+// as NSS and MS CryptoAPI have different string serialisations; if the DN is
+// from an XCertificate it's "native" already and doesn't need to be mangled.
+enum EqualMode
+{
+ NOCOMPAT,
+ COMPAT_2ND,
+ COMPAT_BOTH
+};
+XSECXMLSEC_DLLPUBLIC bool EqualDistinguishedNames(std::u16string_view rName1,
+ std::u16string_view rName2, EqualMode eMode);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/bitmaps.hlst b/xmlsecurity/inc/bitmaps.hlst
new file mode 100644
index 000000000..2d4ccd0c4
--- /dev/null
+++ b/xmlsecurity/inc/bitmaps.hlst
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+inline constexpr OUStringLiteral BMP_STATE_NOT_VALIDATED = u"xmlecurity/res/notcertificate_40x56.png";
+
+#define BMP_CERT_OK "xmlsecurity/res/certificate_16.png"
+#define BMP_CERT_NOT_OK "xmlsecurity/res/notcertificate_16.png"
+
+inline constexpr OUStringLiteral BMP_SIG_VALID = u"xmlsecurity/res/signet_11x16.png";
+inline constexpr OUStringLiteral BMP_SIG_INVALID = u"svx/res/caution_11x16.png";
+inline constexpr OUStringLiteral BMP_SIG_NOT_VALIDATED = u"xmlsecurity/res/notcertificate_16.png";
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/xmlsecurity/inc/certificate.hxx b/xmlsecurity/inc/certificate.hxx
new file mode 100644
index 000000000..bd24bcd72
--- /dev/null
+++ b/xmlsecurity/inc/certificate.hxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sal/types.h>
+
+#include <com/sun/star/uno/Sequence.hxx>
+
+namespace svl
+{
+namespace crypto
+{
+enum class SignatureMethodAlgorithm;
+}
+}
+
+namespace xmlsecurity
+{
+/// Extension of css::security::XCertificate for module-internal purposes.
+class SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI Certificate
+{
+public:
+ /// Returns the SHA-256 thumbprint.
+ ///
+ /// @throws css::uno::RuntimeException
+ virtual css::uno::Sequence<sal_Int8> getSHA256Thumbprint() = 0;
+
+ /// Same as getSubjectPublicKeyAlgorithm(), but returns an ID, not a string.
+ virtual svl::crypto::SignatureMethodAlgorithm getSignatureMethodAlgorithm() = 0;
+
+protected:
+ ~Certificate() noexcept = default;
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/certificatechooser.hxx b/xmlsecurity/inc/certificatechooser.hxx
new file mode 100644
index 000000000..8ad4c3190
--- /dev/null
+++ b/xmlsecurity/inc/certificatechooser.hxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <vcl/weld.hxx>
+#include <unotools/resmgr.hxx>
+
+namespace com::sun::star {
+ namespace security { class XCertificate; }
+ namespace xml::crypto {
+ class XSecurityEnvironment;
+ }
+}
+
+namespace com::sun::star::xml::crypto { class XXMLSecurityContext; }
+
+struct UserData
+{
+ css::uno::Reference<css::security::XCertificate> xCertificate;
+ css::uno::Reference<css::xml::crypto::XXMLSecurityContext> xSecurityContext;
+ css::uno::Reference<css::xml::crypto::XSecurityEnvironment> xSecurityEnvironment;
+};
+
+enum class UserAction
+{
+ Sign,
+ SelectSign, // Select signing certificate
+ Encrypt
+};
+
+class CertificateChooser final : public weld::GenericDialogController
+{
+private:
+ std::vector< css::uno::Reference< css::xml::crypto::XXMLSecurityContext > > mxSecurityContexts;
+ std::vector<std::shared_ptr<UserData>> mvUserData;
+
+ bool mbInitialized;
+ UserAction const meAction;
+ OUString msPreferredKey;
+ css::uno::Reference<css::security::XCertificate> mxEncryptToSelf;
+
+ std::unique_ptr<weld::Label> m_xFTSign;
+ std::unique_ptr<weld::Label> m_xFTEncrypt;
+ std::unique_ptr<weld::TreeView> m_xCertLB;
+ std::unique_ptr<weld::Button> m_xViewBtn;
+ std::unique_ptr<weld::Button> m_xOKBtn;
+ std::unique_ptr<weld::Label> m_xFTDescription;
+ std::unique_ptr<weld::Entry> m_xDescriptionED;
+
+ DECL_LINK(ViewButtonHdl, weld::Button&, void);
+ DECL_LINK(CertificateHighlightHdl, weld::TreeView&, void);
+ DECL_LINK(CertificateSelectHdl, weld::TreeView&, bool);
+
+ void ImplShowCertificateDetails();
+ void ImplInitialize();
+
+ static void HandleOneUsageBit(OUString& string, int& bits, int bit, TranslateId name);
+
+public:
+ CertificateChooser(weld::Window* pParent,
+ std::vector< css::uno::Reference< css::xml::crypto::XXMLSecurityContext > > && rxSecurityContexts,
+ UserAction eAction);
+ virtual ~CertificateChooser() override;
+
+ short run() override;
+
+ css::uno::Sequence<css::uno::Reference< css::security::XCertificate > > GetSelectedCertificates();
+ css::uno::Reference< css::xml::crypto::XXMLSecurityContext > GetSelectedSecurityContext() const;
+ /// Gets the description string provided when selecting the certificate.
+ OUString GetDescription() const;
+
+ /// Returns the usage string of the selected certificate, if any.
+ OUString GetUsageText();
+
+ static OUString UsageInClearText(int bits);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/certificateviewer.hxx b/xmlsecurity/inc/certificateviewer.hxx
new file mode 100644
index 000000000..ea47c4102
--- /dev/null
+++ b/xmlsecurity/inc/certificateviewer.hxx
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <vcl/weld.hxx>
+
+namespace com::sun::star {
+ namespace security { class XCertificate; }
+ namespace xml::crypto { class XSecurityEnvironment; }
+}
+
+class CertificateViewerGeneralTP;
+class CertificateViewerDetailsTP;
+class CertificateViewerCertPathTP;
+class CertificateChooser;
+
+class CertificateViewer final : public weld::GenericDialogController
+{
+private:
+ friend class CertificateViewerGeneralTP;
+ friend class CertificateViewerDetailsTP;
+ friend class CertificateViewerCertPathTP;
+
+ bool const mbCheckForPrivateKey;
+
+ css::uno::Reference< css::xml::crypto::XSecurityEnvironment > mxSecurityEnvironment;
+ css::uno::Reference< css::security::XCertificate > mxCert;
+
+ CertificateChooser* mpParentChooser;
+
+ std::unique_ptr<weld::Notebook> mxTabCtrl;
+
+ std::unique_ptr<CertificateViewerGeneralTP> mxGeneralPage;
+ std::unique_ptr<CertificateViewerDetailsTP> mxDetailsPage;
+ std::unique_ptr<CertificateViewerCertPathTP> mxPathId;
+
+ DECL_LINK(ActivatePageHdl, const OString&, void);
+
+public:
+ CertificateViewer(weld::Window* pParent, const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& rxSecurityEnvironment, const css::uno::Reference< css::security::XCertificate >& rXCert, bool bCheckForPrivateKey, CertificateChooser* pParentChooser);
+ CertificateChooser* GetParentChooser() { return mpParentChooser; }
+};
+
+class CertificateViewerTP
+{
+protected:
+ std::unique_ptr<weld::Builder> mxBuilder;
+ std::unique_ptr<weld::Container> mxContainer;
+ CertificateViewer* mpDlg;
+
+public:
+ CertificateViewerTP(weld::Container* pParent, const OUString& rUIXMLDescription,
+ const OString& rID, CertificateViewer* pDlg);
+};
+
+class CertificateViewerGeneralTP : public CertificateViewerTP
+{
+private:
+ std::unique_ptr<weld::Image> m_xCertImg;
+ std::unique_ptr<weld::Label> m_xHintNotTrustedFT;
+ std::unique_ptr<weld::Label> m_xIssuedToLabelFT;
+ std::unique_ptr<weld::Label> m_xIssuedToFT;
+ std::unique_ptr<weld::Label> m_xIssuedByLabelFT;
+ std::unique_ptr<weld::Label> m_xIssuedByFT;
+ std::unique_ptr<weld::Label> m_xValidFromDateFT;
+ std::unique_ptr<weld::Label> m_xValidToDateFT;
+ std::unique_ptr<weld::Image> m_xKeyImg;
+ std::unique_ptr<weld::Label> m_xHintCorrespPrivKeyFT;
+
+public:
+ CertificateViewerGeneralTP(weld::Container* pParent, CertificateViewer* pDlg);
+};
+
+struct Details_UserDatat
+{
+ OUString const maTxt;
+ bool const mbFixedWidthFont;
+
+ Details_UserDatat(const OUString& rTxt, bool bFixedWidthFont)
+ : maTxt(rTxt)
+ , mbFixedWidthFont(bFixedWidthFont)
+ {
+ }
+};
+
+class CertificateViewerDetailsTP : public CertificateViewerTP
+{
+private:
+ std::vector<std::unique_ptr<Details_UserDatat>> m_aUserData;
+
+ std::unique_ptr<weld::TreeView> m_xElementsLB;
+ std::unique_ptr<weld::TextView> m_xValueDetails;
+
+ DECL_LINK(ElementSelectHdl, weld::TreeView&, void);
+ void InsertElement(const OUString& rField, const OUString& rValue,
+ const OUString& rDetails, bool bFixedWidthFont = false);
+public:
+ CertificateViewerDetailsTP(weld::Container* pParent, CertificateViewer* pDlg);
+};
+
+struct CertPath_UserData
+{
+ css::uno::Reference< css::security::XCertificate > mxCert;
+ bool const mbValid;
+
+ CertPath_UserData(css::uno::Reference<css::security::XCertificate> const & xCert, bool bValid)
+ : mxCert(xCert)
+ , mbValid(bValid)
+ {
+ }
+};
+
+class CertificateViewerCertPathTP : public CertificateViewerTP
+{
+private:
+ CertificateViewer* mpParent;
+ bool mbFirstActivateDone;
+
+ std::vector<std::unique_ptr<CertPath_UserData>> maUserData;
+ std::shared_ptr<CertificateViewer> mxCertificateViewer;
+
+ std::unique_ptr<weld::TreeView> mxCertPathLB;
+ std::unique_ptr<weld::TreeIter> mxScratchIter;
+ std::unique_ptr<weld::Button> mxViewCertPB;
+ std::unique_ptr<weld::TextView> mxCertStatusML;
+ std::unique_ptr<weld::Label> mxCertOK;
+ std::unique_ptr<weld::Label> mxCertNotValidated;
+
+ DECL_LINK(ViewCertHdl, weld::Button&, void);
+ DECL_LINK(CertSelectHdl, weld::TreeView&, void);
+ void InsertCert(const weld::TreeIter* pParent, const OUString& _rName,
+ const css::uno::Reference< css::security::XCertificate >& rxCert,
+ bool bValid);
+
+public:
+ CertificateViewerCertPathTP(weld::Container* pParent, CertificateViewer* pDlg);
+ ~CertificateViewerCertPathTP();
+ void ActivatePage();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/digitalsignaturesdialog.hxx b/xmlsecurity/inc/digitalsignaturesdialog.hxx
new file mode 100644
index 000000000..28ed32ccb
--- /dev/null
+++ b/xmlsecurity/inc/digitalsignaturesdialog.hxx
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <vcl/weld.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include "documentsignaturehelper.hxx"
+#include "xmlsignaturehelper.hxx"
+#include "documentsignaturemanager.hxx"
+
+#include <vector>
+
+namespace com::sun::star {
+ namespace lang { class XMultiServiceFactory; }
+ namespace io { class XStream; }
+ namespace embed { class XStorage; }
+ namespace xml::dom { class XDocumentBuilder; }
+}
+
+
+class HeaderBar;
+class CertificateViewer;
+
+class DigitalSignaturesDialog final : public weld::GenericDialogController
+{
+private:
+ DocumentSignatureManager maSignatureManager;
+ bool mbVerifySignatures;
+ bool mbSignaturesChanged;
+
+ OUString const m_sODFVersion;
+ //Signals if the document contains already a document signature. This is only
+ //important when we are signing macros and if the value is true.
+ bool const m_bHasDocumentSignature;
+ bool m_bWarningShowSignMacro;
+
+ bool m_bAdESCompliant;
+
+ std::unique_ptr<weld::Label> m_xHintDocFT;
+ std::unique_ptr<weld::Label> m_xHintBasicFT;
+ std::unique_ptr<weld::Label> m_xHintPackageFT;
+ std::unique_ptr<weld::TreeView> m_xSignaturesLB;
+ std::unique_ptr<weld::Image> m_xSigsValidImg;
+ std::unique_ptr<weld::Label> m_xSigsValidFI;
+ std::unique_ptr<weld::Image> m_xSigsInvalidImg;
+ std::unique_ptr<weld::Label> m_xSigsInvalidFI;
+ std::unique_ptr<weld::Image> m_xSigsNotvalidatedImg;
+ std::unique_ptr<weld::Label> m_xSigsNotvalidatedFI;
+ std::unique_ptr<weld::Image> m_xSigsOldSignatureImg;
+ std::unique_ptr<weld::Label> m_xSigsOldSignatureFI;
+ std::unique_ptr<weld::CheckButton> m_xAdESCompliantCB;
+ std::unique_ptr<weld::Button> m_xViewBtn;
+ std::unique_ptr<weld::Button> m_xAddBtn;
+ std::unique_ptr<weld::Button> m_xRemoveBtn;
+ std::unique_ptr<weld::Button> m_xStartCertMgrBtn;
+ std::unique_ptr<weld::Button> m_xCloseBtn;
+
+ std::shared_ptr<CertificateViewer> m_xViewer;
+ std::shared_ptr<weld::MessageDialog> m_xInfoBox;
+
+ DECL_LINK(AdESCompliantCheckBoxHdl, weld::Toggleable&, void);
+ DECL_LINK(ViewButtonHdl, weld::Button&, void);
+ DECL_LINK(AddButtonHdl, weld::Button&, void);
+ DECL_LINK(RemoveButtonHdl, weld::Button&, void);
+ DECL_LINK(SignatureHighlightHdl, weld::TreeView&, void);
+ DECL_LINK(SignatureSelectHdl, weld::TreeView&, bool);
+ DECL_LINK(StartVerifySignatureHdl, LinkParamNone*, bool);
+ DECL_LINK(OKButtonHdl, weld::Button&, void);
+ DECL_LINK(CertMgrButtonHdl, weld::Button&, void);
+
+ void ImplGetSignatureInformations(bool bUseTempStream, bool bCacheLastSignature);
+ void ImplFillSignaturesBox();
+ void ImplShowSignaturesDetails();
+
+ css::uno::Reference<css::security::XCertificate> getCertificate(const SignatureInformation& rInfo);
+ css::uno::Reference<css::xml::crypto::XSecurityEnvironment> getSecurityEnvironmentForCertificate(
+ const css::uno::Reference<css::security::XCertificate>& xCert);
+
+ //Checks if adding is allowed.
+ //See the spec at specs/www/appwide/security/Electronic_Signatures_and_Security.sxw
+ //(6.6.2)Behaviour with regard to ODF 1.2
+ bool canAdd();
+ bool canRemove();
+
+ bool canAddRemove();
+
+public:
+ DigitalSignaturesDialog(weld::Window* pParent, const css::uno::Reference<
+ css::uno::XComponentContext >& rxCtx, DocumentSignatureMode eMode,
+ bool bReadOnly, const OUString& sODFVersion, bool bHasDocumentSignature);
+ virtual ~DigitalSignaturesDialog() override;
+
+ // Initialize the dialog and the security environment, returns TRUE on success
+ bool Init();
+
+ // Set the storage which should be signed or verified
+ void SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStore );
+ void SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream );
+
+ // Execute the dialog...
+ void beforeRun();
+ short run() override;
+
+ // Did signatures change?
+ bool SignaturesChanged() const { return mbSignaturesChanged; }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/documentsignaturehelper.hxx b/xmlsecurity/inc/documentsignaturehelper.hxx
new file mode 100644
index 000000000..b18ccf103
--- /dev/null
+++ b/xmlsecurity/inc/documentsignaturehelper.hxx
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/uno/Reference.h>
+#include <rtl/ustring.hxx>
+#include <svl/sigstruct.hxx>
+
+#include <vector>
+
+namespace com::sun::star {
+ namespace io { class XStream; }
+ namespace embed { class XStorage; }
+}
+
+namespace com::sun::star::xml::sax { class XDocumentHandler; }
+
+enum class DocumentSignatureMode
+{
+ Content,
+ Macros,
+ Package
+};
+
+enum class DocumentSignatureAlgorithm
+{
+ OOo2,
+ OOo3_0,
+ OOo3_2
+};
+
+struct SignatureStreamHelper
+{
+ css::uno::Reference < css::embed::XStorage > xSignatureStorage;
+ css::uno::Reference < css::io::XStream > xSignatureStream;
+ /// If this is embed::StorageFormats::OFOPXML, then it's expected that xSignatureStream is an empty reference.
+ sal_Int32 nStorageFormat;
+
+ SignatureStreamHelper()
+ : nStorageFormat(0)
+ {
+ }
+};
+
+namespace DocumentSignatureHelper
+{
+ SignatureStreamHelper OpenSignatureStream(
+ const css::uno::Reference < css::embed::XStorage >& rxStore, sal_Int32 nOpenMode,
+ DocumentSignatureMode eDocSigMode );
+
+ std::vector< OUString > CreateElementList(
+ const css::uno::Reference < css::embed::XStorage >& rxStore,
+ DocumentSignatureMode eMode,
+ const DocumentSignatureAlgorithm mode);
+
+ bool isODFPre_1_2(const OUString & sODFVersion);
+ bool isOOo3_2_Signature(const SignatureInformation & sigInfo);
+
+ DocumentSignatureAlgorithm getDocumentAlgorithm(
+ const OUString & sODFVersion, const SignatureInformation & sigInfo);
+
+ bool CanSignWithGPG(const css::uno::Reference < css::embed::XStorage >& rxStore,
+ const OUString& sOdfVersion);
+
+ bool checkIfAllFilesAreSigned( const ::std::vector< OUString > & sElementList,
+ const SignatureInformation & sigInfo, const DocumentSignatureAlgorithm alg);
+
+ bool equalsReferenceUriManifestPath(
+ std::u16string_view rUri, std::u16string_view rPath);
+
+ OUString GetDocumentContentSignatureDefaultStreamName();
+ OUString GetScriptingContentSignatureDefaultStreamName();
+ OUString GetPackageSignatureDefaultStreamName();
+
+ /// In case the storage is OOXML, prepend a leading '/' and append content type to the element URIs.
+ void AppendContentTypes(const css::uno::Reference<css::embed::XStorage>& xStorage, std::vector<OUString>& rElements);
+
+ void writeDigestMethod(
+ const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler);
+ void writeSignedProperties(
+ const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler,
+ const SignatureInformation& signatureInfo,
+ const OUString& sDate,
+ const bool bWriteSignatureLineData);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/documentsignaturemanager.hxx b/xmlsecurity/inc/documentsignaturemanager.hxx
new file mode 100644
index 000000000..06dd200de
--- /dev/null
+++ b/xmlsecurity/inc/documentsignaturemanager.hxx
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include "xmlsecuritydllapi.h"
+
+#include <memory>
+
+#include <svl/sigstruct.hxx>
+#include "xmlsignaturehelper.hxx"
+#include "documentsignaturehelper.hxx"
+
+#include <com/sun/star/xml/crypto/XSEInitializer.hpp>
+
+namespace com::sun::star
+{
+namespace beans
+{
+struct PropertyValue;
+}
+namespace embed
+{
+class XStorage;
+}
+namespace frame
+{
+class XModel;
+}
+namespace graphic
+{
+class XGraphic;
+}
+namespace uno
+{
+class XComponentContext;
+}
+}
+class PDFSignatureHelper;
+
+/// Manages signatures (addition, removal), used by DigitalSignaturesDialog.
+class XMLSECURITY_DLLPUBLIC DocumentSignatureManager
+{
+private:
+ css::uno::Reference<css::uno::XComponentContext> mxContext;
+ css::uno::Reference<css::embed::XStorage> mxStore;
+ XMLSignatureHelper maSignatureHelper;
+ std::unique_ptr<PDFSignatureHelper> mpPDFSignatureHelper;
+ SignatureInformations maCurrentSignatureInformations;
+ DocumentSignatureMode const meSignatureMode;
+ css::uno::Sequence<css::uno::Sequence<css::beans::PropertyValue>> m_manifest;
+ css::uno::Reference<css::io::XStream> mxSignatureStream;
+ css::uno::Reference<css::frame::XModel> mxModel;
+ css::uno::Reference<css::io::XStream> mxTempSignatureStream;
+ /// Storage containing all OOXML signatures, unused for ODF.
+ css::uno::Reference<css::embed::XStorage> mxTempSignatureStorage;
+ css::uno::Reference<css::xml::crypto::XSEInitializer> mxSEInitializer;
+ css::uno::Reference<css::xml::crypto::XXMLSecurityContext> mxSecurityContext;
+ css::uno::Reference<css::xml::crypto::XSEInitializer> mxGpgSEInitializer;
+ css::uno::Reference<css::xml::crypto::XXMLSecurityContext> mxGpgSecurityContext;
+
+public:
+ DocumentSignatureManager(const css::uno::Reference<css::uno::XComponentContext>& xContext,
+ DocumentSignatureMode eMode);
+ ~DocumentSignatureManager();
+
+ /**
+ * Checks if a particular stream is a valid xml stream. Those are treated
+ * differently when they are signed (c14n transformation)
+ */
+ bool isXML(std::u16string_view rURI);
+ bool readManifest();
+
+ SignatureStreamHelper ImplOpenSignatureStream(sal_Int32 nStreamOpenMode, bool bTempStream);
+ /// Add a new signature, using xCert as a signing certificate, and rDescription as description.
+ bool add(const css::uno::Reference<css::security::XCertificate>& xCert,
+ const css::uno::Reference<css::xml::crypto::XXMLSecurityContext>& xSecurityContext,
+ const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant,
+ const OUString& rSignatureLineId = OUString(),
+ const css::uno::Reference<css::graphic::XGraphic>& xValidGraphic
+ = css::uno::Reference<css::graphic::XGraphic>(),
+ const css::uno::Reference<css::graphic::XGraphic>& xInvalidGraphic
+ = css::uno::Reference<css::graphic::XGraphic>());
+ /// Remove signature at nPosition.
+ void remove(sal_uInt16 nPosition);
+ /// Read signatures from either a temp stream or the real storage.
+ void read(bool bUseTempStream, bool bCacheLastSignature = true);
+ /// Write signatures back to the persistent storage.
+ void write(bool bXAdESCompliantIfODF);
+ /// Lazy creation of PDF helper.
+ PDFSignatureHelper& getPDFSignatureHelper();
+#if 0
+ // Checks if the document is a kind where it is relevant to distinguish between using XAdES or not
+ bool IsXAdESRelevant();
+#endif
+ /// Attempts to initialize the platform-specific crypto.
+ bool init();
+ /// Get the security environment.
+ css::uno::Reference<css::xml::crypto::XSecurityEnvironment> getSecurityEnvironment();
+ css::uno::Reference<css::xml::crypto::XSecurityEnvironment> getGpgSecurityEnvironment();
+ css::uno::Reference<css::xml::crypto::XXMLSecurityContext> const& getSecurityContext() const;
+ css::uno::Reference<css::xml::crypto::XXMLSecurityContext> const& getGpgSecurityContext() const;
+ void setStore(const css::uno::Reference<css::embed::XStorage>& xStore) { mxStore = xStore; }
+ XMLSignatureHelper& getSignatureHelper() { return maSignatureHelper; }
+ bool hasPDFSignatureHelper() const { return bool(mpPDFSignatureHelper); }
+ void setSignatureStream(const css::uno::Reference<css::io::XStream>& xSignatureStream)
+ {
+ mxSignatureStream = xSignatureStream;
+ }
+ void setModel(const css::uno::Reference<css::frame::XModel>& xModel);
+ const css::uno::Reference<css::embed::XStorage>& getStore() const { return mxStore; }
+ DocumentSignatureMode getSignatureMode() const { return meSignatureMode; }
+ SignatureInformations& getCurrentSignatureInformations()
+ {
+ return maCurrentSignatureInformations;
+ }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/framework/saxeventkeeperimpl.hxx b/xmlsecurity/inc/framework/saxeventkeeperimpl.hxx
new file mode 100644
index 000000000..161b9a936
--- /dev/null
+++ b/xmlsecurity/inc/framework/saxeventkeeperimpl.hxx
@@ -0,0 +1,290 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/crypto/sax/XSecuritySAXEventKeeper.hpp>
+#include <com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp>
+#include <com/sun/star/xml/crypto/sax/XSAXEventKeeperStatusChangeBroadcaster.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <xmlsecuritydllapi.h>
+#include <cppuhelper/implbase.hxx>
+#include <vector>
+#include <memory>
+
+class BufferNode;
+class ElementMark;
+class ElementCollector;
+namespace com::sun::star::xml::crypto::sax { class XSAXEventKeeperStatusChangeListener; }
+namespace com::sun::star::xml::csax { class XCompressedDocumentHandler; }
+namespace com::sun::star::xml::wrapper { class XXMLDocumentWrapper; }
+
+
+class SAXEventKeeperImpl final : public cppu::WeakImplHelper
+<
+ css::xml::crypto::sax::XSecuritySAXEventKeeper,
+ css::xml::crypto::sax::XReferenceResolvedBroadcaster,
+ css::xml::crypto::sax::XSAXEventKeeperStatusChangeBroadcaster,
+ css::xml::sax::XDocumentHandler,
+ css::lang::XInitialization,
+ css::lang::XServiceInfo
+>
+/****** SAXEventKeeperImpl.hxx/CLASS SAXEventKeeperImpl ***********************
+ *
+ * NAME
+ * SAXEventKeeperImpl -- SAX events buffer controller
+ *
+ * FUNCTION
+ * Controls SAX events to be buffered, and controls buffered SAX events
+ * to be released.
+ ******************************************************************************/
+{
+private:
+ /*
+ * the XMLDocumentWrapper component which maintains all buffered SAX
+ * in DOM format.
+ */
+ css::uno::Reference< css::xml::wrapper::XXMLDocumentWrapper >
+ m_xXMLDocument;
+
+ /*
+ * the document handler provided by the XMLDocumentWrapper component.
+ */
+ css::uno::Reference< css::xml::sax::XDocumentHandler > m_xDocumentHandler;
+
+ /*
+ * the compressed document handler provided by the XMLDocumentWrapper
+ * component, the handler has more efficient method definition that the
+ * normal document handler.
+ */
+ css::uno::Reference< css::xml::csax::XCompressedDocumentHandler >
+ m_xCompressedDocumentHandler;
+
+ /*
+ * a listener which receives this SAXEventKeeper's status change
+ * notification.
+ * Based on the status changes, the listener can decide whether the
+ * SAXEventKeeper should chain on/chain off the SAX chain, or whether
+ * the SAXEventKeeper is useless any long.
+ */
+ css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >
+ m_xSAXEventKeeperStatusChangeListener;
+
+ /*
+ * the root node of the BufferNode tree.
+ * the BufferNode tree is used to keep track of all buffered elements,
+ * it has the same structure with the document which maintains those
+ * elements physically.
+ */
+ std::unique_ptr<BufferNode> m_pRootBufferNode;
+
+ /*
+ * the current active BufferNode.
+ * this is used to keep track the current location in the BufferNode tree,
+ * the next generated BufferNode will become a child BufferNode of it.
+ */
+ BufferNode* m_pCurrentBufferNode;
+
+ /*
+ * the next Id for a coming ElementMark.
+ * the variable is increased by 1 when a new ElementMark is generated,
+ * in this way, we can promise the Id of any ElementMark is unique.
+ */
+ sal_Int32 m_nNextElementMarkId;
+
+ /*
+ * maintains a collection of all ElementMarks.
+ */
+ std::vector<std::unique_ptr<const ElementMark>> m_vElementMarkBuffers;
+
+ /*
+ * maintains a list of new ElementCollectors that will be created
+ * on the element represented by the next incoming startElement SAX
+ * event.
+ * The reason that such the m_vNewElementCollectors is necessary
+ * is: when an ElementCollector is asked to create, it can't be
+ * created completely at once, because the BufferNode it will be
+ * working on has not been created until the next startElement
+ * SAX event comes.
+ */
+ std::vector< const ElementCollector* > m_vNewElementCollectors;
+
+ /*
+ * maintains the new Blocker that will be created
+ * on the element represented by the next incoming startElement SAX
+ * event.
+ */
+ ElementMark* m_pNewBlocker;
+
+ /*
+ * the document handler to which all received SAX events will be
+ * forwarded.
+ */
+ css::uno::Reference< css::xml::sax::XDocumentHandler > m_xNextHandler;
+
+ /*
+ * the current BufferNode which prevents the SAX events to be
+ * forwarded to the m_xNextHandler.
+ */
+ BufferNode* m_pCurrentBlockingBufferNode;
+
+ /*
+ * maintains a list of ElementMark that has been asked to release.
+ * Because during processing a request of releasing an ElementMark,
+ * another releasing ElementMark request can be invoked. To avoid
+ * reentering the same method, a such request only add that ElementMark
+ * into this ElementMark list, then all ElementMarks will be processed in
+ * order.
+ */
+ std::vector< sal_Int32 > m_vReleasedElementMarkBuffers;
+
+ /*
+ * a flag to indicate whether the ElementMark releasing process is running.
+ * When a releasing request comes, the assigned ElementMark is added to
+ * the m_vReleasedElementMarkBuffers first, then this flag is checked.
+ * If the ElementMark releasing process is not running, then call that
+ * method.
+ */
+ bool m_bIsReleasing;
+
+ /*
+ * a flag to indicate whether it is the "Forwarding" mode now.
+ * A "Forwarding" mode means that all received SAX events are from the
+ * XMLDocumentWrapper component, instead of up-stream component in the
+ * SAX chain.
+ * The difference between "Forwarding" mode and normal mode is that:
+ * no SAX events need to be transferred to the XMLDocumentWrapper component
+ * again even if a buffer request happens.
+ */
+ bool m_bIsForwarding;
+
+ void setCurrentBufferNode(BufferNode* pBufferNode);
+
+ BufferNode* addNewElementMarkBuffers();
+
+ ElementMark* findElementMarkBuffer(sal_Int32 nId) const;
+
+ void removeElementMarkBuffer(sal_Int32 nId);
+
+ OUString printBufferNode(
+ BufferNode const * pBufferNode, sal_Int32 nIndent) const;
+
+ static css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > >
+ collectChildWorkingElement(BufferNode const * pBufferNode);
+
+ void smashBufferNode(
+ BufferNode* pBufferNode, bool bClearRoot) const;
+
+ static BufferNode* findNextBlockingBufferNode(
+ BufferNode* pStartBufferNode);
+
+ static void diffuse(BufferNode* pBufferNode);
+
+ void releaseElementMarkBuffer();
+
+ void markElementMarkBuffer(sal_Int32 nId);
+
+ sal_Int32 createElementCollector(
+ css::xml::crypto::sax::ElementMarkPriority nPriority,
+ bool bModifyElement,
+ const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener>& xReferenceResolvedListener);
+
+ sal_Int32 createBlocker();
+
+public:
+ SAXEventKeeperImpl();
+ virtual ~SAXEventKeeperImpl() override;
+
+ SAXEventKeeperImpl(const SAXEventKeeperImpl&) = delete;
+ SAXEventKeeperImpl& operator=(const SAXEventKeeperImpl&) = delete;
+
+ /* XSAXEventKeeper */
+ virtual sal_Int32 SAL_CALL addElementCollector( ) override;
+ virtual void SAL_CALL removeElementCollector( sal_Int32 id ) override;
+ virtual sal_Int32 SAL_CALL addBlocker( ) override;
+ virtual void SAL_CALL removeBlocker( sal_Int32 id ) override;
+ virtual sal_Bool SAL_CALL isBlocking( ) override;
+ virtual css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL
+ getElement( sal_Int32 id ) override;
+ virtual void SAL_CALL setElement(
+ sal_Int32 id,
+ const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aElement ) override;
+ virtual css::uno::Reference<
+ css::xml::sax::XDocumentHandler > SAL_CALL
+ setNextHandler( const css::uno::Reference<
+ css::xml::sax::XDocumentHandler >& xNewHandler ) override;
+ virtual OUString SAL_CALL printBufferNodeTree() override;
+ virtual css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL
+ getCurrentBlockingNode() override;
+
+ /* XSecuritySAXEventKeeper */
+ virtual sal_Int32 SAL_CALL addSecurityElementCollector(
+ css::xml::crypto::sax::ElementMarkPriority priority,
+ sal_Bool modifyElement ) override;
+ virtual void SAL_CALL setSecurityId( sal_Int32 id, sal_Int32 securityId ) override;
+
+ /* XReferenceResolvedBroadcaster */
+ virtual void SAL_CALL addReferenceResolvedListener(
+ sal_Int32 referenceId,
+ const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& listener ) override;
+ virtual void SAL_CALL removeReferenceResolvedListener(
+ sal_Int32 referenceId,
+ const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& listener ) override;
+
+ /* XSAXEventKeeperStatusChangeBroadcaster */
+ virtual void SAL_CALL addSAXEventKeeperStatusChangeListener(
+ const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >& listener ) override;
+ virtual void SAL_CALL removeSAXEventKeeperStatusChangeListener(
+ const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >& listener ) override;
+
+ /* XDocumentHandler */
+ virtual void SAL_CALL startDocument( ) override;
+ virtual void SAL_CALL endDocument( ) override;
+ virtual void SAL_CALL startElement(
+ const OUString& aName,
+ const css::uno::Reference< css::xml::sax::XAttributeList >&
+ xAttribs ) override;
+ virtual void SAL_CALL endElement( const OUString& aName ) override;
+ virtual void SAL_CALL characters( const OUString& aChars ) override;
+ virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) override;
+ virtual void SAL_CALL processingInstruction(
+ const OUString& aTarget, const OUString& aData ) override;
+ virtual void SAL_CALL setDocumentLocator(
+ const css::uno::Reference< css::xml::sax::XLocator >& xLocator ) override;
+
+ /* XInitialization */
+ virtual void SAL_CALL initialize(
+ const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+ /* XServiceInfo */
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+};
+
+/// @throws css::uno::RuntimeException
+OUString SAXEventKeeperImpl_getImplementationName();
+
+/// @throws css::uno::RuntimeException
+css::uno::Sequence< OUString > SAXEventKeeperImpl_getSupportedServiceNames( );
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/framework/securityengine.hxx b/xmlsecurity/inc/framework/securityengine.hxx
new file mode 100644
index 000000000..bebf07306
--- /dev/null
+++ b/xmlsecurity/inc/framework/securityengine.hxx
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/crypto/sax/XReferenceResolvedListener.hpp>
+#include <com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp>
+#include <com/sun/star/xml/crypto/sax/XKeyCollector.hpp>
+#include <com/sun/star/xml/crypto/sax/XMissionTaker.hpp>
+#include <com/sun/star/xml/crypto/sax/XSAXEventKeeper.hpp>
+#include <com/sun/star/xml/crypto/XXMLSignature.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <xmlsecuritydllapi.h>
+
+class SAL_DLLPUBLIC_RTTI SecurityEngine : public cppu::WeakImplHelper
+<
+ css::xml::crypto::sax::XReferenceResolvedListener,
+ css::xml::crypto::sax::XKeyCollector,
+ css::xml::crypto::sax::XMissionTaker
+>
+/****** securityengine.hxx/CLASS SecurityEngine *******************************
+ *
+ * NAME
+ * SecurityEngine -- Base class of SignatureEngine and EncryptionEngine
+ *
+ * FUNCTION
+ * Maintains common members and methods related with security engine
+ * operation.
+ ******************************************************************************/
+{
+protected:
+
+ /*
+ * A SAXEventKeeper internally maintains all resources that a security
+ * operation needs. The m_xSAXEventKeeper member is used to release
+ * those resources when the security operation finishes.
+ */
+ css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeper > m_xSAXEventKeeper;
+
+ /*
+ * the id of ElementCollector of the template element.
+ * For a signature, the template element is the Signature element,
+ * for an encryption, the EncryptedData/EncryptedKey element is.
+ */
+ sal_Int32 m_nIdOfTemplateEC;
+
+ /*
+ * remembers how many referenced elements have been buffered completely,
+ * including the key element, template element, and referenced element of
+ * signature.
+ */
+ sal_Int32 m_nNumOfResolvedReferences;
+
+ /*
+ * the id of ElementCollector of the key element.
+ * If a Signature element or EncryptedData/EncryptedKey element has
+ * an internal key sub-element, then this member should be -1
+ */
+ sal_Int32 m_nIdOfKeyEC;
+
+ /*
+ * remembers whether the current operation has finished.
+ */
+ bool m_bMissionDone;
+
+ /*
+ * the Id of the security entity, a signature or encryption, which is used for
+ * the result listener to identify the entity.
+ */
+ sal_Int32 m_nSecurityId;
+
+ /*
+ * the status of the operation
+ */
+ css::xml::crypto::SecurityOperationStatus m_nStatus;
+
+ /*
+ * the result listener, which will receives the security operation result.
+ */
+ css::uno::Reference< css::uno::XInterface > m_xResultListener;
+
+protected:
+ explicit SecurityEngine();
+ virtual ~SecurityEngine() override {};
+
+ /*
+ * perform the security operation.
+ * Any derived class will implement this method respectively.
+ */
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ virtual void tryToPerform( ){};
+
+ /*
+ * clear up all resources used by this operation.
+ * This method is called after the operation finishes, or a End-Your-Mission
+ * message is received.
+ * Any derived class will implement this method respectively.
+ */
+ virtual void clearUp( ) const {};
+
+ /*
+ * notifies any possible result listener.
+ * When verify a signature or conduct a decryption, the operation result will
+ * be transferred to a listener by this method.
+ * Any derived class will implement this method respectively.
+ */
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ virtual void notifyResultListener() const
+ {};
+
+public:
+ /* XReferenceResolvedListener */
+ virtual void SAL_CALL referenceResolved( sal_Int32 referenceId ) override;
+
+ /* XKeyCollector */
+ virtual void SAL_CALL setKeyId( sal_Int32 id ) override;
+
+ /* XMissionTaker */
+ virtual sal_Bool SAL_CALL endMission( ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/framework/signaturecreatorimpl.hxx b/xmlsecurity/inc/framework/signaturecreatorimpl.hxx
new file mode 100644
index 000000000..d0fc1dc33
--- /dev/null
+++ b/xmlsecurity/inc/framework/signaturecreatorimpl.hxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/crypto/sax/XBlockerMonitor.hpp>
+#include <com/sun/star/xml/crypto/sax/XSignatureCreationResultBroadcaster.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase.hxx>
+
+#include <framework/signatureengine.hxx>
+
+namespace com::sun::star::xml::crypto { class XSecurityEnvironment; }
+namespace com::sun::star::xml::crypto::sax { class XSignatureCreationResultListener;}
+
+typedef cppu::ImplInheritanceHelper
+<
+ SignatureEngine,
+ css::xml::crypto::sax::XBlockerMonitor,
+ css::xml::crypto::sax::XSignatureCreationResultBroadcaster,
+ css::lang::XInitialization,
+ css::lang::XServiceInfo
+> SignatureCreatorImpl_Base;
+
+class SignatureCreatorImpl final : public SignatureCreatorImpl_Base
+/****** SignatureCreatorImpl.hxx/CLASS SignatureCreatorImpl *******************
+ *
+ * NAME
+ * SignatureCreatorImpl -- generates a signature
+ *
+ * FUNCTION
+ * Collects all resources for a signature generation, then generates the
+ * signature by invoking a xmlsec-based signature bridge component.
+ ******************************************************************************/
+{
+private:
+ /*
+ * the Id of template blocker.
+ */
+ sal_Int32 m_nIdOfBlocker;
+
+ css::uno::Reference< css::xml::crypto::XSecurityEnvironment > m_xSecurityEnvironment;
+
+ virtual void notifyResultListener() const override;
+ virtual void clearUp( ) const override;
+ virtual void startEngine( const rtl::Reference<XMLSignatureTemplateImpl>& xSignatureTemplate) override;
+
+public:
+ explicit SignatureCreatorImpl();
+ virtual ~SignatureCreatorImpl() override;
+
+ /* XBlockerMonitor */
+ virtual void SAL_CALL setBlockerId( sal_Int32 id ) override;
+
+ /* XSignatureCreationResultBroadcaster */
+ void SAL_CALL addSignatureCreationResultListener(
+ const css::uno::Reference< css::xml::crypto::sax::XSignatureCreationResultListener >& listener ) override;
+
+ void SAL_CALL removeSignatureCreationResultListener(
+ const css::uno::Reference< css::xml::crypto::sax::XSignatureCreationResultListener >& listener ) override;
+
+ /* XInitialization */
+ virtual void SAL_CALL initialize(
+ const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+ /* XServiceInfo */
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+};
+
+/// @throws css::uno::RuntimeException
+OUString SignatureCreatorImpl_getImplementationName();
+
+/// @throws css::uno::RuntimeException
+css::uno::Sequence< OUString > SignatureCreatorImpl_getSupportedServiceNames( );
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/framework/signatureengine.hxx b/xmlsecurity/inc/framework/signatureengine.hxx
new file mode 100644
index 000000000..6446c2f36
--- /dev/null
+++ b/xmlsecurity/inc/framework/signatureengine.hxx
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/crypto/sax/XReferenceResolvedListener.hpp>
+#include <com/sun/star/xml/crypto/sax/XReferenceCollector.hpp>
+#include <com/sun/star/xml/crypto/sax/XKeyCollector.hpp>
+#include <com/sun/star/xml/crypto/sax/XMissionTaker.hpp>
+#include <com/sun/star/xml/crypto/XUriBinding.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <xmlsecuritydllapi.h>
+#include <framework/securityengine.hxx>
+
+#include <vector>
+
+namespace com::sun::star::io { class XInputStream; }
+namespace com::sun::star::xml::crypto { class XXMLSignature; }
+namespace rtl { template <class reference_type> class Reference; }
+
+class XMLSignatureTemplateImpl;
+
+class SignatureEngine : public cppu::ImplInheritanceHelper
+<
+ SecurityEngine,
+ css::xml::crypto::sax::XReferenceCollector,
+ css::xml::crypto::XUriBinding
+>
+/****** signatureengine.hxx/CLASS SignatureEngine *****************************
+ *
+ * NAME
+ * SignatureEngine -- Base class of SignatureCreator and SignatureVerifier
+ *
+ * FUNCTION
+ * Maintains common members and methods related with signature operation.
+ ******************************************************************************/
+{
+protected:
+
+ /*
+ * the Signature bridge component, which performs signature generation
+ * and verification based on xmlsec library.
+ */
+ css::uno::Reference< css::xml::crypto::XXMLSignature > m_xXMLSignature;
+
+ /*
+ * a collection of ElementCollector's ids. Each ElementCollector
+ * represents one element signed by this signature.
+ */
+ std::vector< sal_Int32 > m_vReferenceIds;
+
+ /*
+ * remembers how many references this signature has.
+ */
+ sal_Int32 m_nTotalReferenceNumber;
+
+ /*
+ * a collection of Uri binding.
+ *
+ * the m_vUris is used to hold the Uri strings, and the m_vXInputStreams is used
+ * to hold corresponding bound XInputStream interface.
+ */
+ std::vector< OUString > m_vUris;
+ std::vector< css::uno::Reference< css::io::XInputStream > > m_vXInputStreams;
+
+protected:
+ explicit SignatureEngine();
+ virtual ~SignatureEngine() override {};
+
+ virtual void tryToPerform( ) override;
+ virtual void clearUp( ) const override;
+ bool checkReady() const;
+
+ /*
+ * starts the main function. This method will be implemented by any sub-class.
+ * For a SignatureCreator, it performs signing operation;
+ * for a SignatureVerifier, verification operation is performed.
+ */
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ virtual void startEngine( const rtl::Reference<XMLSignatureTemplateImpl>&)
+ {};
+
+public:
+ /* XReferenceCollector */
+ virtual void SAL_CALL setReferenceCount( sal_Int32 count ) override;
+
+ virtual void SAL_CALL setReferenceId( sal_Int32 id ) override;
+
+ /* XUriBinding */
+ virtual void SAL_CALL setUriBinding(
+ const OUString& uri,
+ const css::uno::Reference< css::io::XInputStream >& aInputStream ) override;
+ virtual css::uno::Reference< css::io::XInputStream >
+ SAL_CALL getUriBinding( const OUString& uri ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/framework/signatureverifierimpl.hxx b/xmlsecurity/inc/framework/signatureverifierimpl.hxx
new file mode 100644
index 000000000..15c79643e
--- /dev/null
+++ b/xmlsecurity/inc/framework/signatureverifierimpl.hxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultBroadcaster.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase.hxx>
+
+#include <xmlsecuritydllapi.h>
+#include <framework/signatureengine.hxx>
+
+namespace com::sun::star::xml::crypto::sax { class XSignatureVerifyResultListener; }
+namespace com::sun::star::xml::crypto { class XXMLSecurityContext; }
+
+typedef cppu::ImplInheritanceHelper
+<
+ SignatureEngine,
+ css::xml::crypto::sax::XSignatureVerifyResultBroadcaster,
+ css::lang::XInitialization,
+ css::lang::XServiceInfo
+> SignatureVerifierImpl_Base;
+
+class SignatureVerifierImpl final : public SignatureVerifierImpl_Base
+/****** SignatureVerifier.hxx/CLASS SignatureVerifierImpl *********************
+ *
+ * NAME
+ * SignatureVerifierImpl -- verifies a signature
+ *
+ * FUNCTION
+ * Collects all resources for a signature verification, then verifies the
+ * signature by invoking a xmlsec-based signature bridge component.
+ ******************************************************************************/
+{
+private:
+ css::uno::Reference< css::xml::crypto::XXMLSecurityContext > m_xXMLSecurityContext;
+
+ virtual void notifyResultListener() const override;
+ virtual void startEngine( const rtl::Reference<XMLSignatureTemplateImpl>& xSignatureTemplate) override;
+
+public:
+ explicit SignatureVerifierImpl();
+ virtual ~SignatureVerifierImpl() override;
+
+ /* XSignatureVerifyResultBroadcaster */
+ virtual void SAL_CALL addSignatureVerifyResultListener(
+ const css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultListener >& listener ) override;
+ virtual void SAL_CALL removeSignatureVerifyResultListener(
+ const css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultListener >& listener ) override;
+
+ /* XInitialization */
+ virtual void SAL_CALL initialize(
+ const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+ /* XServiceInfo */
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ void updateSignature( const css::uno::Reference< css::xml::crypto::XXMLSignature >& xSignature,
+ const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& xContext ) { m_xXMLSignature = xSignature; m_xXMLSecurityContext = xContext; }
+};
+
+/// @throws css::uno::RuntimeException
+OUString SignatureVerifierImpl_getImplementationName();
+
+/// @throws css::uno::RuntimeException
+css::uno::Sequence< OUString > SignatureVerifierImpl_getSupportedServiceNames( );
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx b/xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx
new file mode 100644
index 000000000..c0dee1173
--- /dev/null
+++ b/xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+#include <rtl/ustring.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/xml/crypto/XXMLSignatureTemplate.hpp>
+
+#include <vector>
+
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+namespace com::sun::star::xml::wrapper { class XXMLElementWrapper; }
+
+class XMLSignatureTemplateImpl final : public ::cppu::WeakImplHelper<
+ css::xml::crypto::XXMLSignatureTemplate ,
+ css::lang::XServiceInfo >
+{
+ private:
+ css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > m_xTemplate ;
+ std::vector< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > targets;
+ css::uno::Reference< css::xml::crypto::XUriBinding > m_xUriBinding;
+ css::xml::crypto::SecurityOperationStatus m_nStatus;
+
+ public:
+ explicit XMLSignatureTemplateImpl();
+ virtual ~XMLSignatureTemplateImpl() override;
+
+ //Methods from XXMLSignatureTemplate
+ virtual void SAL_CALL setTemplate(
+ const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aXmlElement
+ ) override;
+
+ virtual css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL getTemplate(
+ ) override;
+
+ virtual void SAL_CALL setTarget(
+ const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aXmlElement
+ ) override;
+
+ virtual css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > SAL_CALL getTargets(
+ ) override;
+
+ virtual void SAL_CALL setBinding(
+ const css::uno::Reference< css::xml::crypto::XUriBinding >& aUriBinding ) override;
+ virtual css::uno::Reference< css::xml::crypto::XUriBinding >
+ SAL_CALL getBinding( ) override;
+
+ virtual void SAL_CALL setStatus(
+ css::xml::crypto::SecurityOperationStatus status ) override;
+ virtual css::xml::crypto::SecurityOperationStatus
+ SAL_CALL getStatus( ) override;
+
+ //Methods from XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override ;
+
+ virtual sal_Bool SAL_CALL supportsService(
+ const OUString& ServiceName
+ ) override ;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override ;
+
+ //Helper for XServiceInfo
+ static css::uno::Sequence< OUString > impl_getSupportedServiceNames() ;
+
+ /// @throws css::uno::RuntimeException
+ static OUString impl_getImplementationName() ;
+
+ //Helper for registry
+ /// @throws css::uno::RuntimeException
+ static css::uno::Reference< css::uno::XInterface > impl_createInstance( const css::uno::Reference< css::lang::XMultiServiceFactory >& aServiceManager ) ;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/gpg/SEInitializer.hxx b/xmlsecurity/inc/gpg/SEInitializer.hxx
new file mode 100644
index 000000000..e4da22029
--- /dev/null
+++ b/xmlsecurity/inc/gpg/SEInitializer.hxx
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/xml/crypto/XSEInitializer.hpp>
+
+#include <xsecxmlsecdllapi.h>
+#include <cppuhelper/implbase.hxx>
+
+namespace com::sun::star::xml::crypto { class XXMLSecurityContext; }
+
+class XSECXMLSEC_DLLPUBLIC SEInitializerGpg final : public cppu::WeakImplHelper
+<
+ css::xml::crypto::XSEInitializer,
+ css::lang::XServiceInfo
+>
+{
+public:
+ SEInitializerGpg();
+ virtual ~SEInitializerGpg() override;
+
+ /* XSEInitializer */
+ virtual css::uno::Reference< css::xml::crypto::XXMLSecurityContext >
+ SAL_CALL createSecurityContext( const OUString& ) override;
+
+ virtual void SAL_CALL freeSecurityContext( const css::uno::Reference<
+ css::xml::crypto::XXMLSecurityContext >& securityContext ) override;
+
+ /* XServiceInfo */
+ virtual OUString SAL_CALL getImplementationName( ) override;
+
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx b/xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx
new file mode 100644
index 000000000..906a51d19
--- /dev/null
+++ b/xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+#include <rtl/ustring.hxx>
+#include <xsecxmlsecdllapi.h>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/xml/crypto/XXMLSignature.hpp>
+
+namespace com::sun::star::xml::crypto { class XXMLSignatureTemplate; }
+namespace com::sun::star::xml::crypto { class XXMLSecurityContext; }
+namespace com::sun::star::lang { class XMultiServiceFactory; }
+
+
+class XSECXMLSEC_DLLPUBLIC XMLSignature_GpgImpl final : public ::cppu::WeakImplHelper<
+ css::xml::crypto::XXMLSignature ,
+ css::lang::XServiceInfo >
+{
+ public:
+ explicit XMLSignature_GpgImpl();
+ virtual ~XMLSignature_GpgImpl() override ;
+
+ //Methods from XXMLSignature
+ virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL generate(
+ const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate ,
+ const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aEnvironment
+ ) override ;
+
+ virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL validate(
+ const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate ,
+ const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& aContext
+ ) override;
+
+ //Methods from XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override ;
+
+ virtual sal_Bool SAL_CALL supportsService(
+ const OUString& ServiceName
+ ) override ;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override ;
+
+ //Helper for XServiceInfo
+ static css::uno::Sequence< OUString > impl_getSupportedServiceNames() ;
+
+ /// @throws css::uno::RuntimeException
+ static OUString impl_getImplementationName() ;
+
+ //Helper for registry
+ /// @throws css::uno::RuntimeException
+ static css::uno::Reference< css::uno::XInterface > impl_createInstance( const css::uno::Reference< css::lang::XMultiServiceFactory >& aServiceManager ) ;
+} ;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/macrosecurity.hxx b/xmlsecurity/inc/macrosecurity.hxx
new file mode 100644
index 000000000..233ef2c1d
--- /dev/null
+++ b/xmlsecurity/inc/macrosecurity.hxx
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <vcl/weld.hxx>
+#include <unotools/securityoptions.hxx>
+
+namespace com::sun::star::xml::crypto { class XSecurityEnvironment; }
+class MacroSecurityTP;
+
+class MacroSecurity final : public weld::GenericDialogController
+{
+private:
+ friend class MacroSecurityLevelTP;
+ friend class MacroSecurityTrustedSourcesTP;
+
+ css::uno::Reference<css::xml::crypto::XSecurityEnvironment> m_xSecurityEnvironment;
+
+ std::unique_ptr<weld::Notebook> m_xTabCtrl;
+ std::unique_ptr<weld::Button> m_xOkBtn;
+ std::unique_ptr<weld::Button> m_xResetBtn;
+
+ std::unique_ptr<MacroSecurityTP> m_xLevelTP;
+ std::unique_ptr<MacroSecurityTP> m_xTrustSrcTP;
+
+ DECL_LINK(ActivatePageHdl, const OString&, void);
+ DECL_LINK(OkBtnHdl, weld::Button&, void);
+public:
+ MacroSecurity(weld::Window* pParent,
+ const css::uno::Reference<css::xml::crypto::XSecurityEnvironment>& rxSecurityEnvironment);
+
+ void EnableReset(bool bEnable = true)
+ {
+ m_xResetBtn->set_sensitive(bEnable);
+ }
+};
+
+class MacroSecurityTP
+{
+protected:
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Container> m_xContainer;
+
+ MacroSecurity* m_pDlg;
+public:
+ MacroSecurityTP(weld::Container* pParent, const OUString& rUIXMLDescription,
+ const OString& rID, MacroSecurity* pDlg);
+ virtual ~MacroSecurityTP();
+
+ virtual void ActivatePage();
+ virtual void ClosePage() = 0;
+};
+
+class MacroSecurityLevelTP : public MacroSecurityTP
+{
+private:
+ sal_uInt16 mnCurLevel;
+
+ std::unique_ptr<weld::RadioButton> m_xVeryHighRB;
+ std::unique_ptr<weld::RadioButton> m_xHighRB;
+ std::unique_ptr<weld::RadioButton> m_xMediumRB;
+ std::unique_ptr<weld::RadioButton> m_xLowRB;
+ std::unique_ptr<weld::Widget> m_xVHighImg;
+ std::unique_ptr<weld::Widget> m_xHighImg;
+ std::unique_ptr<weld::Widget> m_xMedImg;
+ std::unique_ptr<weld::Widget> m_xLowImg;
+
+ DECL_LINK(RadioButtonHdl, weld::Toggleable&, void);
+public:
+ MacroSecurityLevelTP(weld::Container* pParent, MacroSecurity* pDlg);
+ virtual void ClosePage() override;
+};
+
+class MacroSecurityTrustedSourcesTP : public MacroSecurityTP
+{
+private:
+ std::vector< SvtSecurityOptions::Certificate > m_aTrustedAuthors;
+
+ bool mbAuthorsReadonly;
+ bool mbURLsReadonly;
+
+ std::unique_ptr<weld::Image> m_xTrustCertROFI;
+ std::unique_ptr<weld::TreeView> m_xTrustCertLB;
+ std::unique_ptr<weld::Button> m_xViewCertPB;
+ std::unique_ptr<weld::Button> m_xRemoveCertPB;
+ std::unique_ptr<weld::Image> m_xTrustFileROFI;
+ std::unique_ptr<weld::TreeView> m_xTrustFileLocLB;
+ std::unique_ptr<weld::Button> m_xAddLocPB;
+ std::unique_ptr<weld::Button> m_xRemoveLocPB;
+
+ DECL_LINK(ViewCertPBHdl, weld::Button&, void);
+ DECL_LINK(RemoveCertPBHdl, weld::Button&, void);
+ DECL_LINK(AddLocPBHdl, weld::Button&, void);
+ DECL_LINK(RemoveLocPBHdl, weld::Button&, void);
+ DECL_LINK(TrustCertLBSelectHdl, weld::TreeView&, void);
+ DECL_LINK(TrustFileLocLBSelectHdl, weld::TreeView&, void);
+
+ void FillCertLB(const bool bShowWarnings = false);
+ void ImplCheckButtons();
+ void ShowBrokenCertificateError(std::u16string_view rData);
+
+public:
+ MacroSecurityTrustedSourcesTP(weld::Container* pParent, MacroSecurity* pDlg);
+
+ virtual void ActivatePage() override;
+ virtual void ClosePage() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/pch/precompiled_xmlsecurity.cxx b/xmlsecurity/inc/pch/precompiled_xmlsecurity.cxx
new file mode 100644
index 000000000..16ace305f
--- /dev/null
+++ b/xmlsecurity/inc/pch/precompiled_xmlsecurity.cxx
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "precompiled_xmlsecurity.hxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx b/xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx
new file mode 100644
index 000000000..21e6b93a9
--- /dev/null
+++ b/xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/*
+ This file has been autogenerated by update_pch.sh. It is possible to edit it
+ manually (such as when an include file has been moved/renamed/removed). All such
+ manual changes will be rewritten by the next run of update_pch.sh (which presumably
+ also fixes all possible problems, so it's usually better to use it).
+
+ Generated on 2021-04-11 19:48:55 using:
+ ./bin/update_pch xmlsecurity xmlsecurity --cutoff=6 --exclude:system --include:module --include:local
+
+ If after updating build fails, use the following command to locate conflicting headers:
+ ./bin/update_pch_bisect ./xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx "make xmlsecurity.build" --find-conflicts
+*/
+
+#include <sal/config.h>
+#if PCH_LEVEL >= 1
+#include <algorithm>
+#include <assert.h>
+#include <cassert>
+#include <chrono>
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <float.h>
+#include <functional>
+#include <initializer_list>
+#include <iomanip>
+#include <limits.h>
+#include <limits>
+#include <math.h>
+#include <memory>
+#include <new>
+#include <ostream>
+#include <set>
+#include <stddef.h>
+#include <string.h>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+#endif // PCH_LEVEL >= 1
+#if PCH_LEVEL >= 2
+#include <osl/diagnose.h>
+#include <osl/doublecheckedlocking.h>
+#include <osl/endian.h>
+#include <osl/file.hxx>
+#include <osl/getglobalmutex.hxx>
+#include <osl/interlck.h>
+#include <osl/mutex.h>
+#include <osl/mutex.hxx>
+#include <osl/thread.h>
+#include <osl/time.h>
+#include <rtl/alloc.h>
+#include <rtl/instance.hxx>
+#include <rtl/locale.h>
+#include <rtl/math.h>
+#include <rtl/ref.hxx>
+#include <rtl/strbuf.hxx>
+#include <rtl/string.h>
+#include <rtl/string.hxx>
+#include <rtl/stringconcat.hxx>
+#include <rtl/stringutils.hxx>
+#include <rtl/textcvt.h>
+#include <rtl/textenc.h>
+#include <rtl/uri.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.h>
+#include <rtl/ustring.hxx>
+#include <rtl/uuid.h>
+#include <sal/log.hxx>
+#include <sal/macros.h>
+#include <sal/saldllapi.h>
+#include <sal/types.h>
+#include <sal/typesizes.h>
+#include <vcl/BinaryDataContainer.hxx>
+#include <vcl/Scanline.hxx>
+#include <vcl/alpha.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/bitmap/BitmapTypes.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/checksum.hxx>
+#include <vcl/dllapi.h>
+#include <vcl/errcode.hxx>
+#include <vcl/fntstyle.hxx>
+#include <vcl/font.hxx>
+#include <vcl/mapmod.hxx>
+#include <vcl/region.hxx>
+#include <vcl/scopedbitmapaccess.hxx>
+#include <vcl/task.hxx>
+#include <vcl/uitest/factory.hxx>
+#include <vcl/vclenum.hxx>
+#include <vcl/vclptr.hxx>
+#endif // PCH_LEVEL >= 2
+#if PCH_LEVEL >= 3
+#include <basegfx/basegfxdllapi.h>
+#include <basegfx/color/bcolor.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/point/b2ipoint.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2irange.hxx>
+#include <basegfx/range/basicrange.hxx>
+#include <basegfx/tuple/b2dtuple.hxx>
+#include <basegfx/tuple/b2i64tuple.hxx>
+#include <basegfx/tuple/b2ituple.hxx>
+#include <basegfx/tuple/b3dtuple.hxx>
+#include <basegfx/utils/common.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/vector/b2enums.hxx>
+#include <basegfx/vector/b2ivector.hxx>
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/StorageFormats.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XTypeProvider.hpp>
+#include <com/sun/star/uno/Any.h>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Type.h>
+#include <com/sun/star/uno/Type.hxx>
+#include <com/sun/star/uno/TypeClass.hdl>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/uno/XWeak.hpp>
+#include <com/sun/star/uno/genfunc.h>
+#include <com/sun/star/uno/genfunc.hxx>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/xml/crypto/DigestID.hpp>
+#include <com/sun/star/xml/crypto/SecurityOperationStatus.hpp>
+#include <com/sun/star/xml/crypto/XXMLSignature.hpp>
+#include <com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp>
+#include <com/sun/star/xml/sax/XFastAttributeList.hpp>
+#include <com/sun/star/xml/sax/XFastTokenHandler.hpp>
+#include <comphelper/comphelperdllapi.h>
+#include <cppu/cppudllapi.h>
+#include <cppu/unotype.hxx>
+#include <cppuhelper/cppuhelperdllapi.h>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/implbase_ex.hxx>
+#include <cppuhelper/implbase_ex_post.hxx>
+#include <cppuhelper/implbase_ex_pre.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/weak.hxx>
+#include <i18nlangtag/lang.h>
+#include <o3tl/cow_wrapper.hxx>
+#include <o3tl/strong_int.hxx>
+#include <o3tl/typed_flags_set.hxx>
+#include <o3tl/underlyingenumvalue.hxx>
+#include <salhelper/salhelperdllapi.h>
+#include <salhelper/simplereferenceobject.hxx>
+#include <sax/saxdllapi.h>
+#include <svl/sigstruct.hxx>
+#include <tools/color.hxx>
+#include <tools/date.hxx>
+#include <tools/degree.hxx>
+#include <tools/fldunit.hxx>
+#include <tools/fontenum.hxx>
+#include <tools/gen.hxx>
+#include <tools/link.hxx>
+#include <tools/long.hxx>
+#include <tools/mapunit.hxx>
+#include <tools/solar.h>
+#include <tools/toolsdllapi.h>
+#include <typelib/typeclass.h>
+#include <typelib/typedescription.h>
+#include <typelib/uik.h>
+#include <uno/any2.h>
+#include <uno/data.h>
+#include <uno/sequence2.h>
+#include <unotools/datetime.hxx>
+#include <unotools/options.hxx>
+#include <unotools/unotoolsdllapi.h>
+#include <xmloff/dllapi.h>
+#endif // PCH_LEVEL >= 3
+#if PCH_LEVEL >= 4
+#include <biginteger.hxx>
+#include <xmlsecuritydllapi.h>
+#include <xsecctl.hxx>
+#endif // PCH_LEVEL >= 4
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.cxx b/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.cxx
new file mode 100644
index 000000000..74123c2f1
--- /dev/null
+++ b/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.cxx
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "precompiled_xsec_xmlsec.hxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx b/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx
new file mode 100644
index 000000000..3ed774968
--- /dev/null
+++ b/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/*
+ This file has been autogenerated by update_pch.sh. It is possible to edit it
+ manually (such as when an include file has been moved/renamed/removed). All such
+ manual changes will be rewritten by the next run of update_pch.sh (which presumably
+ also fixes all possible problems, so it's usually better to use it).
+
+ Generated on 2021-04-08 13:57:49 using:
+ ./bin/update_pch xmlsecurity xsec_xmlsec --cutoff=2 --exclude:system --include:module --include:local
+
+ If after updating build fails, use the following command to locate conflicting headers:
+ ./bin/update_pch_bisect ./xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx "make xmlsecurity.build" --find-conflicts
+*/
+
+#include <sal/config.h>
+#if PCH_LEVEL >= 1
+#include <algorithm>
+#include <cassert>
+#include <chrono>
+#include <cstddef>
+#include <cstdlib>
+#include <initializer_list>
+#include <iomanip>
+#include <limits>
+#include <memory>
+#include <new>
+#include <ostream>
+#ifdef XMLSEC_CRYPTO_NSS
+#include <pk11pub.h>
+#endif
+#include <stddef.h>
+#include <string.h>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+#endif // PCH_LEVEL >= 1
+#if PCH_LEVEL >= 2
+#include <osl/diagnose.h>
+#include <osl/doublecheckedlocking.h>
+#include <osl/file.h>
+#include <osl/file.hxx>
+#include <osl/getglobalmutex.hxx>
+#include <osl/interlck.h>
+#include <osl/mutex.h>
+#include <osl/mutex.hxx>
+#include <osl/thread.h>
+#include <osl/time.h>
+#include <rtl/alloc.h>
+#include <rtl/bootstrap.h>
+#include <rtl/bootstrap.hxx>
+#include <rtl/instance.hxx>
+#include <rtl/malformeduriexception.hxx>
+#include <rtl/random.h>
+#include <rtl/ref.hxx>
+#include <rtl/string.h>
+#include <rtl/string.hxx>
+#include <rtl/stringconcat.hxx>
+#include <rtl/stringutils.hxx>
+#include <rtl/textcvt.h>
+#include <rtl/textenc.h>
+#include <rtl/uri.h>
+#include <rtl/uri.hxx>
+#include <rtl/ustring.h>
+#include <rtl/ustring.hxx>
+#include <rtl/uuid.h>
+#include <sal/log.hxx>
+#include <sal/macros.h>
+#include <sal/saldllapi.h>
+#include <sal/types.h>
+#include <sal/typesizes.h>
+#include <vcl/dllapi.h>
+#include <vcl/errcode.hxx>
+#endif // PCH_LEVEL >= 2
+#if PCH_LEVEL >= 3
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XTypeProvider.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/uno/Any.h>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Type.h>
+#include <com/sun/star/uno/Type.hxx>
+#include <com/sun/star/uno/TypeClass.hdl>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/uno/XWeak.hpp>
+#include <com/sun/star/uno/genfunc.h>
+#include <com/sun/star/uno/genfunc.hxx>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/xml/csax/XCompressedDocumentHandler.hpp>
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+#include <com/sun/star/xml/wrapper/XXMLDocumentWrapper.hpp>
+#include <comphelper/servicehelper.hxx>
+#include <cppu/cppudllapi.h>
+#include <cppu/unotype.hxx>
+#include <cppuhelper/cppuhelperdllapi.h>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/implbase_ex.hxx>
+#include <cppuhelper/implbase_ex_post.hxx>
+#include <cppuhelper/implbase_ex_pre.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/weak.hxx>
+#include <libxml/tree.h>
+#include <o3tl/typed_flags_set.hxx>
+#include <o3tl/underlyingenumvalue.hxx>
+#include <salhelper/singletonref.hxx>
+#include <tools/lineend.hxx>
+#include <tools/long.hxx>
+#include <tools/ref.hxx>
+#include <tools/stream.hxx>
+#include <tools/toolsdllapi.h>
+#include <typelib/typeclass.h>
+#include <typelib/typedescription.h>
+#include <typelib/uik.h>
+#include <uno/any2.h>
+#include <uno/data.h>
+#include <uno/sequence2.h>
+#include <unotools/unotoolsdllapi.h>
+#include <xmloff/dllapi.h>
+#endif // PCH_LEVEL >= 3
+#if PCH_LEVEL >= 4
+#include <xmlsec-wrapper.h>
+#include <xsecxmlsecdllapi.h>
+#endif // PCH_LEVEL >= 4
+
+// Cleanup windows header macro pollution.
+#if defined(_WIN32) && defined(WINAPI)
+#include <postwin.h>
+#undef RGB
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/pdfsignaturehelper.hxx b/xmlsecurity/inc/pdfsignaturehelper.hxx
new file mode 100644
index 000000000..ea24685d2
--- /dev/null
+++ b/xmlsecurity/inc/pdfsignaturehelper.hxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+#include "xmlsecuritydllapi.h"
+
+#include <svl/sigstruct.hxx>
+
+namespace com::sun::star
+{
+namespace frame
+{
+class XModel;
+}
+namespace io
+{
+class XInputStream;
+}
+namespace security
+{
+class XCertificate;
+}
+namespace security
+{
+struct DocumentSignatureInformation;
+}
+namespace xml::crypto
+{
+class XSecurityEnvironment;
+}
+}
+class SvStream;
+
+/// Handles signatures of a PDF file.
+class XMLSECURITY_DLLPUBLIC PDFSignatureHelper
+{
+ SignatureInformations m_aSignatureInfos;
+
+ css::uno::Reference<css::security::XCertificate> m_xCertificate;
+ OUString m_aDescription;
+
+public:
+ PDFSignatureHelper();
+ bool ReadAndVerifySignature(const css::uno::Reference<css::io::XInputStream>& xInputStream);
+ bool ReadAndVerifySignatureSvStream(SvStream& rStream);
+ css::uno::Sequence<css::security::DocumentSignatureInformation>
+ GetDocumentSignatureInformations(
+ const css::uno::Reference<css::xml::crypto::XSecurityEnvironment>& xSecEnv) const;
+ SignatureInformations const& GetSignatureInformations() const;
+
+ /// Return the ID of the next created signature.
+ sal_Int32 GetNewSecurityId() const;
+ /// Certificate to be used next time signing is performed.
+ void SetX509Certificate(const css::uno::Reference<css::security::XCertificate>& xCertificate);
+ /// Comment / reason to be used next time signing is performed.
+ void SetDescription(const OUString& rDescription);
+ /// Append a new signature at the end of xInputStream.
+ bool Sign(const css::uno::Reference<css::frame::XModel>& xModel,
+ const css::uno::Reference<css::io::XInputStream>& xInputStream, bool bAdES);
+ /// Remove the signature at nPosition (and all dependent signatures) from xInputStream.
+ static bool RemoveSignature(const css::uno::Reference<css::io::XInputStream>& xInputStream,
+ sal_uInt16 nPosition);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/resourcemanager.hxx b/xmlsecurity/inc/resourcemanager.hxx
new file mode 100644
index 000000000..1dc5b2987
--- /dev/null
+++ b/xmlsecurity/inc/resourcemanager.hxx
@@ -0,0 +1,26 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <unotools/resmgr.hxx>
+
+inline OUString XsResId(TranslateId aId) { return Translate::get(aId, Translate::Create("xsc")); }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/strings.hrc b/xmlsecurity/inc/strings.hrc
new file mode 100644
index 000000000..8cf89b211
--- /dev/null
+++ b/xmlsecurity/inc/strings.hrc
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#define NC_(Context, String) TranslateId(Context, reinterpret_cast<char const *>(u8##String))
+
+#define STR_CERTIFICATE_NOT_VALIDATED NC_("STR_CERTIFICATE_NOT_VALIDATED", "The certificate could not be validated.")
+#define STR_VERSION NC_("STR_VERSION", "Version")
+#define STR_SERIALNUM NC_("STR_SERIALNUM", "Serial Number")
+#define STR_ISSUER NC_("STR_ISSUER", "Issuer")
+#define STR_VALIDFROM NC_("STR_VALIDFROM", "Valid From")
+#define STR_VALIDTO NC_("STR_VALIDTO", "Valid to")
+#define STR_SUBJECT NC_("STR_SUBJECT", "Subject")
+#define STR_SUBJECT_PUBKEY_ALGO NC_("STR_SUBJECT_PUBKEY_ALGO", "Subject Algorithm")
+#define STR_SUBJECT_PUBKEY_VAL NC_("STR_SUBJECT_PUBKEY_VAL", "Public Key")
+#define STR_SIGNATURE_ALGO NC_("STR_SIGNATURE_ALGO", "Signature Algorithm")
+#define STR_USE NC_("STR_USE", "Certificate Use")
+#define STR_THUMBPRINT_SHA1 NC_("STR_THUMBPRINT_SHA1", "Thumbprint SHA1")
+#define STR_THUMBPRINT_MD5 NC_("STR_THUMBPRINT_MD5", "Thumbprint MD5")
+
+#define STR_XMLSECDLG_OLD_ODF_FORMAT NC_("STR_XMLSECDLG_OLD_ODF_FORMAT", "This document contains signatures in ODF 1.1 (OpenOffice.org 2.x) format. " \
+ "Signing documents in %PRODUCTNAME %PRODUCTVERSION requires ODF 1.2 format version. " \
+ "Thus no signatures can be added or removed to this document.\n\n" \
+ "Save document in ODF 1.2 format and add all desired signatures again.")
+#define STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN NC_("STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN", "Adding or removing a macro signature will remove all document signatures.\n" \
+ "Do you really want to continue?")
+#define STR_XMLSECDLG_QUERY_REALLYREMOVE NC_("STR_XMLSECDLG_QUERY_REALLYREMOVE", "Document signature cannot be restored, once removed.\n" \
+ "Do you really want to remove selected signature?")
+
+#define STR_XMLSECDLG_SIGNING_FAILED NC_("STR_XMLSECDLG_SIGNING_FAILED", "An error occurred while adding the signature.")
+#define STR_XMLSECDLG_NO_CERT_MANAGER NC_("STR_XMLSECDLG_NO_CERT_MANAGER", "Could not find any certificate manager.")
+#define STR_XMLSECDLG_NO_CERT_FOUND NC_("STR_XMLSECDLG_NO_CERT_FOUND", "Could not find the certificate.")
+
+#define RID_XMLSECWB_NO_MOZILLA_PROFILE NC_("RID_XMLSECWB_NO_MOZILLA_PROFILE", "Digital signatures functionality could not be used, because no Mozilla user profile was found. Please check the Mozilla installation.")
+
+#define STR_DIGITAL_SIGNATURE NC_("selectcertificatedialog|STR_DIGITAL_SIGNATURE", "Digital signature")
+#define STR_NON_REPUDIATION NC_("selectcertificatedialog|STR_NON_REPUDIATION", "Non-repudiation")
+#define STR_KEY_ENCIPHERMENT NC_("selectcertificatedialog|STR_KEY_ENCIPHERMENT", "Key encipherment")
+#define STR_DATA_ENCIPHERMENT NC_("selectcertificatedialog|STR_DATA_ENCIPHERMENT", "Data encipherment")
+#define STR_KEY_AGREEMENT NC_("selectcertificatedialog|STR_KEY_AGREEMENT", "Key Agreement")
+#define STR_KEY_CERT_SIGN NC_("selectcertificatedialog|STR_KEY_CERT_SIGN", "Certificate signature verification")
+#define STR_CRL_SIGN NC_("selectcertificatedialog|STR_CRL_SIGN", "CRL signature verification")
+#define STR_ENCIPHER_ONLY NC_("selectcertificatedialog|STR_ENCIPHER_ONLY", "Only for encipherment")
+#define STR_SIGN NC_("selectcertificatedialog|str_sign", "Sign")
+#define STR_SELECTSIGN NC_("selectcertificatedialog|str_selectsign", "Select")
+#define STR_ENCRYPT NC_("selectcertificatedialog|str_encrypt", "Encrypt")
+
+#define STR_BROKEN_MACRO_CERTIFICATE_DATA NC_("STR_BROKEN_MACRO_CERTIFICATE_DATA", "Macro security problem!\n\nBroken certificate data: %{data}")
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/xmlsec-wrapper.h b/xmlsecurity/inc/xmlsec-wrapper.h
new file mode 100644
index 000000000..e4048de94
--- /dev/null
+++ b/xmlsecurity/inc/xmlsec-wrapper.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <sal/types.h>
+
+// Cf. xmlsec's configure.in:
+#if SAL_TYPES_SIZEOFPOINTER != 4 && !defined SYSTEM_XMLSEC
+#define XMLSEC_NO_SIZE_T
+#endif
+
+#include <xmlsec/base64.h>
+#include <xmlsec/bn.h>
+#include <xmlsec/errors.h>
+#include <xmlsec/io.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/strings.h>
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/xmlenc.h>
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#ifdef XMLSEC_CRYPTO_NSS
+#include <xmlsec/nss/app.h>
+#include <xmlsec/nss/crypto.h>
+#include <xmlsec/nss/pkikeys.h>
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/xmlsec/errorcallback.hxx b/xmlsecurity/inc/xmlsec/errorcallback.hxx
new file mode 100644
index 000000000..80ba564e9
--- /dev/null
+++ b/xmlsecurity/inc/xmlsec/errorcallback.hxx
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <xsecxmlsecdllapi.h>
+
+// Only used for logging
+void setErrorRecorder();
+//ToDo
+//void setErrorRecorder(const css::uno::Reference< css::xml::crypto::XXMLEncryptionTemplate >& xTemplate);
+void clearErrorRecorder();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/xmlsec/saxhelper.hxx b/xmlsecurity/inc/xmlsec/saxhelper.hxx
new file mode 100644
index 000000000..a49ccef18
--- /dev/null
+++ b/xmlsecurity/inc/xmlsec/saxhelper.hxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <libxml/tree.h>
+
+#include <rtl/ustring.hxx>
+
+namespace com::sun::star::xml::csax { struct XMLAttribute; }
+namespace com::sun::star::uno { template <typename > class Sequence; }
+
+/** This class represents a SAX handler which simply forwards to
+ the corresponding libxml API and translates parameter if necessary.
+*/
+class SAXHelper final
+{
+ private:
+ xmlParserCtxtPtr m_pParserCtxt ;
+ xmlSAXHandlerPtr m_pSaxHandler ;
+
+ public:
+ SAXHelper( ) ;
+ ~SAXHelper() ;
+
+ xmlNodePtr getCurrentNode() { return m_pParserCtxt->node;}
+ void setCurrentNode(const xmlNodePtr pNode);
+ xmlDocPtr getDocument() { return m_pParserCtxt->myDoc;}
+
+ /// @throws css::xml::sax::SAXException
+ /// @throws css::uno::RuntimeException
+ void startDocument() ;
+
+ /// @throws css::xml::sax::SAXException
+ /// @throws css::uno::RuntimeException
+ void endDocument() ;
+
+ /// @throws css::xml::sax::SAXException
+ /// @throws css::uno::RuntimeException
+ void startElement(
+ std::u16string_view aName ,
+ const css::uno::Sequence<
+ css::xml::csax::XMLAttribute >& aAttributes ) ;
+
+ /// @throws css::xml::sax::SAXException
+ /// @throws css::uno::RuntimeException
+ void endElement( std::u16string_view aName ) ;
+
+ /// @throws css::xml::sax::SAXException
+ /// @throws css::uno::RuntimeException
+ void characters( std::u16string_view aChars ) ;
+
+ /// @throws css::xml::sax::SAXException
+ /// @throws css::uno::RuntimeException
+ void ignorableWhitespace( std::u16string_view aWhitespaces ) ;
+
+ /// @throws css::xml::sax::SAXException
+ /// @throws css::uno::RuntimeException
+ void processingInstruction(
+ std::u16string_view aTarget ,
+ std::u16string_view aData ) ;
+
+} ;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx b/xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx
new file mode 100644
index 000000000..8f5695d10
--- /dev/null
+++ b/xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx
@@ -0,0 +1,208 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/wrapper/XXMLDocumentWrapper.hpp>
+#include <com/sun/star/xml/csax/XCompressedDocumentHandler.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase.hxx>
+
+#include <xmlsec/saxhelper.hxx>
+#include <xsecxmlsecdllapi.h>
+
+#define NODEPOSITION_NORMAL 1
+#define NODEPOSITION_STARTELEMENT 2
+#define NODEPOSITION_ENDELEMENT 3
+
+#include <libxml/tree.h>
+
+class XSECXMLSEC_DLLPUBLIC XMLDocumentWrapper_XmlSecImpl final : public cppu::WeakImplHelper
+<
+ css::xml::wrapper::XXMLDocumentWrapper,
+ css::xml::sax::XDocumentHandler,
+ css::xml::csax::XCompressedDocumentHandler,
+ css::lang::XServiceInfo
+>
+/**
+ * NAME
+ * XMLDocumentWrapper_XmlSecImpl -- Class to manipulate a libxml2
+ * document
+ *
+ * FUNCTION
+ * Converts SAX events into a libxml2 document, converts the document back
+ * into SAX event stream, and manipulate nodes in the document.
+ ******************************************************************************/
+{
+private:
+ /* the sax helper */
+ SAXHelper saxHelper;
+
+ /* the document used to convert SAX events to */
+ xmlDocPtr m_pDocument;
+
+ /* the root element */
+ xmlNodePtr m_pRootElement;
+
+ /*
+ * the current active element. The next incoming SAX event will be
+ * appended to this element
+ */
+ xmlNodePtr m_pCurrentElement;
+
+ /*
+ * This variable is used when converting the document or part of it into
+ * SAX events. See getNextSAXEvent method.
+ */
+ sal_Int32 m_nCurrentPosition;
+
+ /*
+ * used for recursive deletion. See recursiveDelete method
+ */
+ xmlNodePtr m_pStopAtNode;
+ xmlNodePtr m_pCurrentReservedNode;
+ css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > m_aReservedNodes;
+ sal_Int32 m_nReservedNodeIndex;
+
+private:
+ void getNextSAXEvent();
+
+ /// @throws css::xml::sax::SAXException
+ static void sendStartElement(
+ const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler,
+ const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler2,
+ const xmlNodePtr pNode);
+
+ /// @throws css::xml::sax::SAXException
+ static void sendEndElement(
+ const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler,
+ const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler2,
+ const xmlNodePtr pNode);
+
+ /// @throws css::xml::sax::SAXException
+ static void sendNode(
+ const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler,
+ const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler2,
+ const xmlNodePtr pNode);
+
+ static OString getNodeQName(const xmlNodePtr pNode);
+
+ sal_Int32 recursiveDelete( const xmlNodePtr pNode);
+
+ void getNextReservedNode();
+
+ void removeNode( const xmlNodePtr pNode) const;
+
+ static xmlNodePtr checkElement(
+ const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& xXMLElement);
+
+ void buildIDAttr( xmlNodePtr pNode ) const;
+ void rebuildIDLink( xmlNodePtr pNode ) const;
+
+public:
+ XMLDocumentWrapper_XmlSecImpl();
+ virtual ~XMLDocumentWrapper_XmlSecImpl() override;
+
+ /* css::xml::wrapper::XXMLDocumentWrapper */
+ virtual css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL getCurrentElement( ) override;
+
+ virtual void SAL_CALL setCurrentElement( const css::uno::Reference<
+ css::xml::wrapper::XXMLElementWrapper >& element ) override;
+
+ virtual void SAL_CALL removeCurrentElement( ) override;
+
+ virtual sal_Bool SAL_CALL isCurrent( const css::uno::Reference<
+ css::xml::wrapper::XXMLElementWrapper >& node ) override;
+
+ virtual sal_Bool SAL_CALL isCurrentElementEmpty( ) override;
+
+ virtual OUString SAL_CALL getNodeName( const css::uno::Reference<
+ css::xml::wrapper::XXMLElementWrapper >& node ) override;
+
+ virtual void SAL_CALL clearUselessData(
+ const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& node,
+ const css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > >& reservedDescendants,
+ const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& stopAtNode ) override;
+
+ virtual void SAL_CALL collapse( const css::uno::Reference<
+ css::xml::wrapper::XXMLElementWrapper >& node ) override;
+
+ virtual void SAL_CALL generateSAXEvents(
+ const css::uno::Reference< css::xml::sax::XDocumentHandler >& handler,
+ const css::uno::Reference< css::xml::sax::XDocumentHandler >& xEventKeeperHandler,
+ const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& startNode,
+ const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& endNode ) override;
+
+ virtual void SAL_CALL getTree(
+ const css::uno::Reference< css::xml::sax::XDocumentHandler >& handler ) override;
+
+ virtual void SAL_CALL rebuildIDLink(
+ const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& node ) override;
+
+ /* css::xml::sax::XDocumentHandler */
+ virtual void SAL_CALL startDocument( ) override;
+
+ virtual void SAL_CALL endDocument( ) override;
+
+ virtual void SAL_CALL startElement(
+ const OUString& aName,
+ const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) override;
+
+ virtual void SAL_CALL endElement( const OUString& aName ) override;
+
+ virtual void SAL_CALL characters( const OUString& aChars ) override;
+
+ virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) override;
+
+ virtual void SAL_CALL processingInstruction( const OUString& aTarget, const OUString& aData ) override;
+
+ virtual void SAL_CALL setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >& xLocator ) override;
+
+ /* css::xml::csax::XCompressedDocumentHandler */
+ virtual void SAL_CALL compressedStartDocument( ) override;
+
+ virtual void SAL_CALL compressedEndDocument( ) override;
+
+ virtual void SAL_CALL compressedStartElement(
+ const OUString& aName,
+ const css::uno::Sequence< css::xml::csax::XMLAttribute >& aAttributes ) override;
+
+ virtual void SAL_CALL compressedEndElement( const OUString& aName ) override;
+
+ virtual void SAL_CALL compressedCharacters( const OUString& aChars ) override;
+
+ virtual void SAL_CALL compressedIgnorableWhitespace( const OUString& aWhitespaces ) override;
+
+ virtual void SAL_CALL compressedProcessingInstruction( const OUString& aTarget, const OUString& aData ) override;
+
+ virtual void SAL_CALL compressedSetDocumentLocator(
+ sal_Int32 columnNumber,
+ sal_Int32 lineNumber,
+ const OUString& publicId,
+ const OUString& systemId ) override;
+
+ /* css::lang::XServiceInfo */
+ virtual OUString SAL_CALL getImplementationName( ) override;
+
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/xmlsec/xmlsec_init.hxx b/xmlsecurity/inc/xmlsec/xmlsec_init.hxx
new file mode 100644
index 000000000..417acd288
--- /dev/null
+++ b/xmlsecurity/inc/xmlsec/xmlsec_init.hxx
@@ -0,0 +1,17 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <xsecxmlsecdllapi.h>
+
+XSECXMLSEC_DLLPUBLIC void initXmlSec();
+XSECXMLSEC_DLLPUBLIC void deInitXmlSec();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/xmlsec/xmlstreamio.hxx b/xmlsecurity/inc/xmlsec/xmlstreamio.hxx
new file mode 100644
index 000000000..6e3d506a4
--- /dev/null
+++ b/xmlsecurity/inc/xmlsec/xmlstreamio.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <xsecxmlsecdllapi.h>
+
+namespace com::sun::star::xml::crypto
+{
+class XUriBinding;
+}
+namespace com::sun::star::uno
+{
+template <typename> class Reference;
+}
+
+int xmlEnableStreamInputCallbacks();
+void xmlDisableStreamInputCallbacks();
+int xmlRegisterStreamInputCallbacks(
+ css::uno::Reference<css::xml::crypto::XUriBinding> const& aUriBinding);
+int xmlUnregisterStreamInputCallbacks();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/xmlsecuritydllapi.h b/xmlsecurity/inc/xmlsecuritydllapi.h
new file mode 100644
index 000000000..7f31e6f8f
--- /dev/null
+++ b/xmlsecurity/inc/xmlsecuritydllapi.h
@@ -0,0 +1,20 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sal/types.h>
+
+#if defined(XMLSECURITY_DLLIMPLEMENTATION)
+#define XMLSECURITY_DLLPUBLIC SAL_DLLPUBLIC_EXPORT
+#else
+#define XMLSECURITY_DLLPUBLIC SAL_DLLPUBLIC_IMPORT
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/xmlsignaturehelper.hxx b/xmlsecurity/inc/xmlsignaturehelper.hxx
new file mode 100644
index 000000000..de7de9908
--- /dev/null
+++ b/xmlsecurity/inc/xmlsignaturehelper.hxx
@@ -0,0 +1,176 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <tools/link.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/ref.hxx>
+#include <svl/sigstruct.hxx>
+#include "xmlsecuritydllapi.h"
+#include "xmlsignaturehelper.hxx"
+#include "xsecctl.hxx"
+
+#include <com/sun/star/security/XCertificate.hpp>
+#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
+
+class DateTime;
+class UriBindingHelper;
+
+namespace com::sun::star {
+ namespace io {
+ class XOutputStream;
+ class XInputStream;
+ }
+ namespace embed { class XStorage; }
+}
+
+namespace com::sun::star::graphic { class XGraphic; }
+namespace com::sun::star::uno { class XComponentContext; }
+namespace com::sun::star::xml::crypto { class XXMLSecurityContext; }
+namespace com::sun::star::xml::sax { class XDocumentHandler; }
+namespace com::sun::star::xml::sax { class XWriter; }
+
+/**********************************************************
+ XMLSignatureHelper
+
+ Helper class for the XML Security framework
+
+ Functions:
+ 1. help to create a security context;
+ 2. help to listen signature creation result;
+ 3. help to listen signature verify result;
+ 4. help to indicate which signature to verify.
+
+ **********************************************************/
+
+class XMLSECURITY_DLLPUBLIC XMLSignatureHelper
+{
+private:
+ css::uno::Reference< css::uno::XComponentContext > mxCtx;
+ rtl::Reference<UriBindingHelper> mxUriBinding;
+
+ rtl::Reference<XSecController> mpXSecController;
+ bool mbError;
+ bool mbODFPre1_2;
+ Link<LinkParamNone*,bool> maStartVerifySignatureHdl;
+
+private:
+ XMLSignatureHelper(const XMLSignatureHelper&) = delete;
+
+public:
+ XMLSignatureHelper(const css::uno::Reference< css::uno::XComponentContext >& mrCtx );
+ ~XMLSignatureHelper();
+
+ void StartVerifySignatureElement();
+
+ // Set the storage which should be used by the default UriBinding
+ // Must be set before StartMission().
+ //sODFVersion indicates the ODF version
+ void SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStorage, const OUString& sODFVersion );
+
+ // Argument for the Link is a uno::Reference< xml::sax::XAttributeList >*
+ // Return 1 to verify, 0 to skip.
+ // Default handler will verify all.
+ void SetStartVerifySignatureHdl( const Link<LinkParamNone*,bool>& rLink );
+
+ // After signing/verifying, get information about signatures
+ SignatureInformation GetSignatureInformation( sal_Int32 nSecurityId ) const;
+ SignatureInformations GetSignatureInformations() const;
+ /// ImplVerifySignature calls this to figure out which X509Data is the
+ /// signing certificate and update the internal state with the result.
+ /// @return
+ /// A sequence with the signing certificate at the back on success.
+ /// An empty sequence on failure.
+ std::vector<css::uno::Reference<css::security::XCertificate>>
+ CheckAndUpdateSignatureInformation(
+ css::uno::Reference<css::xml::crypto::XSecurityEnvironment> const& xSecEnv,
+ SignatureInformation const& rInfo);
+
+ // See XSecController for documentation
+ void StartMission(const css::uno::Reference<css::xml::crypto::XXMLSecurityContext>& xSecurityContext);
+ void EndMission();
+ sal_Int32 GetNewSecurityId();
+ /** sets data that describes the certificate.
+
+ It is absolutely necessary that the parameter ouX509IssuerName is set. It contains
+ the base64 encoded certificate, which is DER encoded. The XMLSec needs it to find
+ the private key. Although issuer name and certificate should be sufficient to identify
+ the certificate the implementation in XMLSec is broken, both for Windows and mozilla.
+ The reason is that they use functions to find the certificate which take as parameter
+ the DER encoded ASN.1 issuer name. The issuer name is a DName, where most attributes
+ are of type DirectoryName, which is a choice of 5 string types. This information is
+ not contained in the issuer string and while it is converted to the ASN.1 name the
+ conversion function must assume a particular type, which is often wrong. For example,
+ the Windows function CertStrToName will use a T.61 string if the string does not contain
+ special characters. So if the certificate uses simple characters but encodes the
+ issuer attributes in Utf8, then CertStrToName will use T.61. The resulting DER encoded
+ ASN.1 name now contains different bytes which indicate the string type. The functions
+ for finding the certificate apparently use memcmp - hence they fail to find the
+ certificate.
+ */
+ void SetX509Certificate(sal_Int32 nSecurityId, const OUString& ouX509IssuerName,
+ const OUString& ouX509SerialNumber, const OUString& ouX509Cert, const OUString& ouX509CertDigest,
+ svl::crypto::SignatureMethodAlgorithm eAlgorithmID);
+
+ void AddEncapsulatedX509Certificate(const OUString& ouEncapsulatedX509Certificate);
+
+ void SetGpgCertificate(sal_Int32 nSecurityId, const OUString& ouGpgCertDigest,
+ const OUString& ouGpgCert, const OUString& ouGpgOwner);
+
+ void SetDateTime( sal_Int32 nSecurityId, const DateTime& rDateTime );
+ void SetDescription(sal_Int32 nSecurityId, const OUString& rDescription);
+ void SetSignatureLineId(sal_Int32 nSecurityId, const OUString& rSignatureLineId);
+ void
+ SetSignatureLineValidGraphic(sal_Int32 nSecurityId,
+ const css::uno::Reference<css::graphic::XGraphic>& xValidGraphic);
+ void SetSignatureLineInvalidGraphic(
+ sal_Int32 nSecurityId, const css::uno::Reference<css::graphic::XGraphic>& xInvalidGraphic);
+
+ void AddForSigning( sal_Int32 securityId, const OUString& uri, bool bBinary, bool bXAdESCompliantIfODF );
+ void CreateAndWriteSignature( const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler, bool bXAdESCompliantIfODF );
+ bool ReadAndVerifySignature( const css::uno::Reference< css::io::XInputStream >& xInputStream );
+
+ // MT: ??? I think only for adding/removing, not for new signatures...
+ // MM: Yes, but if you want to insert a new signature into an existing signature file, those function
+ // will be very useful, see Mission 3 in the new "multisigdemo" program :-)
+ css::uno::Reference< css::xml::sax::XWriter> CreateDocumentHandlerWithHeader( const css::uno::Reference< css::io::XOutputStream >& xOutputStream );
+ static void CloseDocumentHandler( const css::uno::Reference< css::xml::sax::XDocumentHandler>& xDocumentHandler );
+ static void ExportSignature(
+ const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler,
+ const SignatureInformation& signatureInfo,
+ bool bXAdESCompliantIfODF );
+
+ /// Read and verify OOXML signatures.
+ bool ReadAndVerifySignatureStorage(const css::uno::Reference<css::embed::XStorage>& xStorage, bool bCacheLastSignature = true);
+ /// Read and verify a single OOXML signature.
+ bool ReadAndVerifySignatureStorageStream(const css::uno::Reference<css::io::XInputStream>& xInputStream);
+ /// Adds or removes an OOXML digital signature relation to _rels/.rels if there wasn't any before.
+ void EnsureSignaturesRelation(const css::uno::Reference<css::embed::XStorage>& xStorage, bool bAdd);
+ /// Given that xStorage is an OOXML _xmlsignatures storage, create origin.sigs and its relations.
+ void ExportSignatureRelations(const css::uno::Reference<css::embed::XStorage>& xStorage, int nSignatureCount);
+ /// Given that xSignatureStorage is an OOXML _xmlsignatures storage, create and write a new signature.
+ void CreateAndWriteOOXMLSignature(const css::uno::Reference<css::embed::XStorage>& xRootStorage, const css::uno::Reference<css::embed::XStorage>& xSignatureStorage, int nSignatureIndex);
+ /// Similar to CreateAndWriteOOXMLSignature(), but used to write the signature to the persistent storage, not the temporary one.
+ void ExportOOXMLSignature(const css::uno::Reference<css::embed::XStorage>& xRootStorage, const css::uno::Reference<css::embed::XStorage>& xSignatureStorage, const SignatureInformation& rInformation, int nSignatureIndex);
+ /// Given that xStorage is an OOXML root storage, advertise signatures in its [Content_Types].xml stream.
+ void ExportSignatureContentTypes(const css::uno::Reference<css::embed::XStorage>& xStorage, int nSignatureCount);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/xsecctl.hxx b/xmlsecurity/inc/xsecctl.hxx
new file mode 100644
index 000000000..adfd251b1
--- /dev/null
+++ b/xmlsecurity/inc/xsecctl.hxx
@@ -0,0 +1,408 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <svl/sigstruct.hxx>
+
+#include <com/sun/star/xml/crypto/sax/XSAXEventKeeperStatusChangeListener.hpp>
+#include <com/sun/star/xml/crypto/sax/XSignatureCreationResultListener.hpp>
+#include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultListener.hpp>
+
+#include <rtl/ref.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#include <vector>
+
+#include "UriBindingHelper.hxx"
+
+namespace com::sun::star::embed { class XStorage; }
+namespace com::sun::star::graphic { class XGraphic; }
+namespace com::sun::star::io { class XInputStream; }
+namespace com::sun::star::lang { class XInitialization; }
+namespace com::sun::star::uno { class XComponentContext; }
+namespace com::sun::star::xml::crypto { class XXMLSecurityContext; }
+namespace com::sun::star::xml::crypto { class XXMLSignature; }
+namespace com::sun::star::xml::crypto:: sax { class XReferenceResolvedListener; }
+namespace com::sun::star::xml::sax { class XDocumentHandler; }
+
+inline constexpr OUStringLiteral NS_XMLDSIG = u"http://www.w3.org/2000/09/xmldsig#";
+inline constexpr OUStringLiteral NS_DC = u"http://purl.org/dc/elements/1.1/";
+inline constexpr OUStringLiteral NS_XD = u"http://uri.etsi.org/01903/v1.3.2#";
+inline constexpr OUStringLiteral NS_MDSSI = u"http://schemas.openxmlformats.org/package/2006/digital-signature";
+inline constexpr OUStringLiteral NS_LOEXT = u"urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0";
+
+inline constexpr OUStringLiteral ALGO_C14N = u"http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
+inline constexpr OUStringLiteral ALGO_RSASHA1 = u"http://www.w3.org/2000/09/xmldsig#rsa-sha1";
+inline constexpr OUStringLiteral ALGO_RSASHA256 = u"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
+inline constexpr OUStringLiteral ALGO_RSASHA512 = u"http://www.w3.org/2001/04/xmldsig-more#rsa-sha512";
+inline constexpr OUStringLiteral ALGO_ECDSASHA1 = u"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1";
+inline constexpr OUStringLiteral ALGO_ECDSASHA256 = u"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256";
+inline constexpr OUStringLiteral ALGO_ECDSASHA512 = u"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512";
+inline constexpr OUStringLiteral ALGO_XMLDSIGSHA1 = u"http://www.w3.org/2000/09/xmldsig#sha1";
+inline constexpr OUStringLiteral ALGO_XMLDSIGSHA256 = u"http://www.w3.org/2001/04/xmlenc#sha256";
+inline constexpr OUStringLiteral ALGO_XMLDSIGSHA512 = u"http://www.w3.org/2001/04/xmlenc#sha512";
+inline constexpr OUStringLiteral ALGO_RELATIONSHIP = u"http://schemas.openxmlformats.org/package/2006/RelationshipTransform";
+
+class XMLDocumentWrapper_XmlSecImpl;
+class SAXEventKeeperImpl;
+class XMLSignatureHelper;
+namespace svl::crypto { enum class SignatureMethodAlgorithm; }
+
+class InternalSignatureInformation
+{
+public:
+ SignatureInformation signatureInfor;
+
+ css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener;
+
+ ::std::vector< sal_Int32 > vKeeperIds;
+
+ InternalSignatureInformation(
+ sal_Int32 nId,
+ css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > const & xListener)
+ :signatureInfor(nId)
+ {
+ xReferenceResolvedListener = xListener;
+ }
+
+ void addReference( SignatureReferenceType type, sal_Int32 digestID, const OUString& uri, sal_Int32 keeperId, const OUString& rType )
+ {
+ signatureInfor.vSignatureReferenceInfors.push_back(
+ SignatureReferenceInformation(type, digestID, uri, rType));
+ vKeeperIds.push_back( keeperId );
+ }
+};
+
+class XSecController final : public cppu::WeakImplHelper
+<
+ css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener,
+ css::xml::crypto::sax::XSignatureCreationResultListener,
+ css::xml::crypto::sax::XSignatureVerifyResultListener
+>
+/****** XSecController.hxx/CLASS XSecController *******************************
+ *
+ * NAME
+ * XSecController -- the xml security framework controller
+ *
+ * FUNCTION
+ * Controls the whole xml security framework to create signatures or to
+ * verify signatures.
+ *
+ ******************************************************************************/
+{
+ friend class XSecParser;
+ friend class OOXMLSecParser;
+
+private:
+ css::uno::Reference< css::uno::XComponentContext> mxCtx;
+
+ /*
+ * used to buffer SAX events
+ */
+ rtl::Reference<XMLDocumentWrapper_XmlSecImpl> m_xXMLDocumentWrapper;
+
+ /*
+ * the SAX events keeper
+ */
+ rtl::Reference<SAXEventKeeperImpl> m_xSAXEventKeeper;
+
+ /*
+ * the bridge component which creates/verifies signature
+ */
+ css::uno::Reference< css::xml::crypto::XXMLSignature > m_xXMLSignature;
+
+ /*
+ * the Security Context
+ */
+ css::uno::Reference< css::xml::crypto::XXMLSecurityContext > m_xSecurityContext;
+
+ /*
+ * the security id incrementer, in order to make any security id unique
+ * to the SAXEventKeeper.
+ * Because each XSecController has its own SAXEventKeeper, so this variable
+ * is not necessary to be static.
+ */
+ sal_Int32 m_nNextSecurityId;
+
+ /*
+ * Signature information
+ */
+ std::vector< InternalSignatureInformation > m_vInternalSignatureInformations;
+
+ /*
+ * the previous node on the SAX chain.
+ * The reason that use a Reference<XInterface> type variable
+ * is that the previous components are different when exporting
+ * and importing, and there is no other common interface they
+ * can provided.
+ */
+ css::uno::Reference< css::uno::XInterface > m_xPreviousNodeOnSAXChain;
+ /*
+ * whether the previous node can provide an XInitialize interface,
+ * use this variable in order to typecast the XInterface to the
+ * correct interface type.
+ */
+ bool m_bIsPreviousNodeInitializable;
+
+ /*
+ * a flag representing whether the SAXEventKeeper is now on the
+ * SAX chain.
+ */
+ bool m_bIsSAXEventKeeperConnected;
+
+ /*
+ * a flag representing whether it is collecting some element,
+ * which means that the SAXEventKeeper can't be chained off the
+ * SAX chain.
+ */
+ bool m_bIsCollectingElement;
+
+ /*
+ * a flag representing whether the SAX event stream is blocking,
+ * which also means that the SAXEventKeeper can't be chained off
+ * the SAX chain.
+ */
+ bool m_bIsBlocking;
+
+ /*
+ * a flag representing the current status of security related
+ * components.
+ */
+
+ /*
+ * status of security related components
+ */
+ enum class InitializationState { UNINITIALIZED, INITIALIZED, FAILTOINITIALIZED } m_eStatusOfSecurityComponents;
+
+ /*
+ * a flag representing whether the SAXEventKeeper need to be
+ * on the SAX chain all the time.
+ * This flag is used to the situation when creating signature.
+ */
+ bool m_bIsSAXEventKeeperSticky;
+
+ /*
+ * the XSecParser which is used to parse the signature stream
+ */
+ css::uno::Reference<css::xml::sax::XDocumentHandler> m_xSecParser;
+
+ /*
+ * the caller assigned signature id for the next signature in the
+ * signature stream
+ */
+ sal_Int32 m_nReservedSignatureId;
+
+ /*
+ * representing whether to verify the current signature
+ */
+ bool m_bVerifyCurrentSignature;
+
+ /*
+ * An xUriBinding is provided to map Uris to XInputStream interfaces.
+ */
+ rtl::Reference<UriBindingHelper> m_xUriBinding;
+
+private:
+
+ /*
+ * Common methods
+ */
+ void createXSecComponent( );
+ int findSignatureInfor( sal_Int32 nSecurityId ) const;
+ bool chainOn();
+ void chainOff();
+ void checkChainingStatus();
+ void initializeSAXChain();
+
+ css::uno::Reference< css::io::XInputStream > getObjectInputStream( const OUString& objectURL );
+
+ //sal_Int32 getFastPropertyIndex(sal_Int32 nHandle) const;
+
+ /*
+ * For signature generation
+ */
+ static OUString createId();
+ css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > prepareSignatureToWrite(
+ InternalSignatureInformation& signatureInfo,
+ sal_Int32 nStorageFormat,
+ bool bXAdESCompliantIfODF );
+
+ /*
+ * For signature verification
+ */
+ void addSignature();
+ /// Sets algorithm from <SignatureMethod Algorithm="...">.
+ void setSignatureMethod(svl::crypto::SignatureMethodAlgorithm eAlgorithmID);
+ void switchGpgSignature();
+ bool haveReferenceForId(std::u16string_view rId) const;
+ void addReference(
+ const OUString& ouUri,
+ sal_Int32 nDigestID,
+ const OUString& ouType );
+ void addStreamReference(
+ const OUString& ouUri,
+ bool isBinary,
+ sal_Int32 nDigestID );
+ void setReferenceCount() const;
+
+ void setX509Data(
+ std::vector<std::pair<OUString, OUString>> & rX509IssuerSerials,
+ std::vector<OUString> const& rX509Certificates);
+ void setX509CertDigest(
+ OUString const& rCertDigest, sal_Int32 const nReferenceDigestID,
+ std::u16string_view const& rX509IssuerName, std::u16string_view const& rX509SerialNumber);
+
+ void setSignatureValue( OUString const & ouSignatureValue );
+ void setDigestValue( sal_Int32 nDigestID, OUString const & ouDigestValue );
+ void setGpgKeyID( OUString const & ouKeyID );
+ void setGpgCertificate( OUString const & ouGpgCert );
+ void setGpgOwner( OUString const & ouGpgOwner );
+
+ void setDate(OUString const& rId, OUString const& ouDate);
+ void setDescription(OUString const& rId, OUString const& rDescription);
+ void setValidSignatureImage(std::u16string_view rValidSigImg);
+ void setInvalidSignatureImage(std::u16string_view rInvalidSigImg);
+ void setSignatureLineId(const OUString& rSignatureLineId);
+
+public:
+ void setSignatureBytes(const css::uno::Sequence<sal_Int8>& rBytes);
+
+private:
+ void setId( OUString const & ouId );
+
+ css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > prepareSignatureToRead(
+ sal_Int32 nSecurityId );
+
+public:
+ explicit XSecController(const css::uno::Reference<css::uno::XComponentContext>& rxCtx);
+ virtual ~XSecController() override;
+
+ sal_Int32 getNewSecurityId( );
+
+ void startMission(const rtl::Reference<UriBindingHelper>& xUriBinding, const css::uno::Reference<css::xml::crypto::XXMLSecurityContext>& xSecurityContext);
+
+ void setSAXChainConnector(const css::uno::Reference< css::lang::XInitialization >& xInitialization);
+
+ void clearSAXChainConnector();
+ void endMission();
+
+ SignatureInformation getSignatureInformation( sal_Int32 nSecurityId ) const;
+ SignatureInformations getSignatureInformations() const;
+ /// only verify can figure out which X509Data is the signing certificate
+ void UpdateSignatureInformation(sal_Int32 nSecurityId,
+ std::vector<SignatureInformation::X509Data> && rDatas);
+
+ static void exportSignature(
+ const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler,
+ const SignatureInformation& signatureInfo,
+ bool bXAdESCompliantIfODF );
+
+
+ /*
+ * For signature generation
+ */
+ void signAStream( sal_Int32 securityId, const OUString& uri, bool isBinary, bool bXAdESCompliantIfODF);
+
+
+ /** sets data that describes the certificate.
+
+ It is absolutely necessary that the parameter ouX509IssuerName is set. It contains
+ the base64 encoded certificate, which is DER encoded. The XMLSec needs it to find
+ the private key. Although issuer name and certificate should be sufficient to identify
+ the certificate the implementation in XMLSec is broken, both for Windows and mozilla.
+ The reason is that they use functions to find the certificate which take as parameter
+ the DER encoded ASN.1 issuer name. The issuer name is a DName, where most attributes
+ are of type DirectoryName, which is a choice of 5 string types. This information is
+ not contained in the issuer string and while it is converted to the ASN.1 name the
+ conversion function must assume a particular type, which is often wrong. For example,
+ the Windows function CertStrToName will use a T.61 string if the string does not contain
+ special characters. So if the certificate uses simple characters but encodes the
+ issuer attributes in Utf8, then CertStrToName will use T.61. The resulting DER encoded
+ ASN.1 name now contains different bytes which indicate the string type. The functions
+ for finding the certificate apparently use memcmp - hence they fail to find the
+ certificate.
+ */
+ void setX509Certificate(
+ sal_Int32 nSecurityId,
+ const OUString& ouX509IssuerName,
+ const OUString& ouX509SerialNumber,
+ const OUString& ouX509Cert,
+ const OUString& ouX509CertDigest,
+ svl::crypto::SignatureMethodAlgorithm eAlgorithmID);
+
+ void addEncapsulatedX509Certificate(const OUString& rEncapsulatedX509Certificate);
+
+ void setGpgCertificate(
+ sal_Int32 nSecurityId,
+ const OUString& ouCertDigest,
+ const OUString& ouCert,
+ const OUString& ouOwner);
+
+ void setDate(
+ sal_Int32 nSecurityId,
+ const css::util::DateTime& rDateTime );
+ void setDescription(sal_Int32 nSecurityId, const OUString& rDescription);
+ void setSignatureLineId(sal_Int32 nSecurityId, const OUString& rSignatureLineId);
+ void
+ setSignatureLineValidGraphic(sal_Int32 nSecurityId,
+ const css::uno::Reference<css::graphic::XGraphic>& xValidGraphic);
+ void setSignatureLineInvalidGraphic(
+ sal_Int32 nSecurityId, const css::uno::Reference<css::graphic::XGraphic>& xInvalidGraphic);
+
+ bool WriteSignature(
+ const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler,
+ bool bXAdESCompliantIfODF);
+
+ /*
+ * For signature verification
+ */
+ void collectToVerify( std::u16string_view referenceId );
+ void addSignature( sal_Int32 nSignatureId );
+ css::uno::Reference< css::xml::sax::XDocumentHandler > const & createSignatureReader(XMLSignatureHelper& rXMLSignatureHelper, sal_Int32 nType = 0);
+ void releaseSignatureReader();
+
+public:
+ /* Interface methods */
+
+ /*
+ * XSAXEventKeeperStatusChangeListener
+ */
+ virtual void SAL_CALL blockingStatusChanged( sal_Bool isBlocking ) override;
+ virtual void SAL_CALL collectionStatusChanged(
+ sal_Bool isInsideCollectedElement ) override;
+ virtual void SAL_CALL bufferStatusChanged( sal_Bool isBufferEmpty ) override;
+
+ /*
+ * XSignatureCreationResultListener
+ */
+ virtual void SAL_CALL signatureCreated( sal_Int32 securityId, css::xml::crypto::SecurityOperationStatus nResult ) override;
+
+ /*
+ * XSignatureVerifyResultListener
+ */
+ virtual void SAL_CALL signatureVerified( sal_Int32 securityId, css::xml::crypto::SecurityOperationStatus nResult ) override;
+
+ /// Writes XML elements inside a single OOXML signature's <Signature> element.
+ bool WriteOOXMLSignature(const css::uno::Reference<css::embed::XStorage>& xRootStorage, const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler);
+ /// Exports an OOXML signature, called by WriteOOXMLSignature().
+ void exportOOXMLSignature(const css::uno::Reference<css::embed::XStorage>& xRootStorage, const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler, const SignatureInformation& rInformation);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/inc/xsecxmlsecdllapi.h b/xmlsecurity/inc/xsecxmlsecdllapi.h
new file mode 100644
index 000000000..36f8ad52a
--- /dev/null
+++ b/xmlsecurity/inc/xsecxmlsecdllapi.h
@@ -0,0 +1,20 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sal/types.h>
+
+#if defined(XSECXMLSEC_DLLIMPLEMENTATION)
+#define XSECXMLSEC_DLLPUBLIC SAL_DLLPUBLIC_EXPORT
+#else
+#define XSECXMLSEC_DLLPUBLIC SAL_DLLPUBLIC_IMPORT
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/qa/certext/SanCertExt.cxx b/xmlsecurity/qa/certext/SanCertExt.cxx
new file mode 100644
index 000000000..c117f4c00
--- /dev/null
+++ b/xmlsecurity/qa/certext/SanCertExt.cxx
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <test/officeconnection.hxx>
+
+#include <com/sun/star/security/XSanExtension.hpp>
+#include <com/sun/star/security/ExtAltNameType.hpp>
+#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
+#include <com/sun/star/xml/crypto/SEInitializer.hpp>
+#include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp>
+#include <com/sun/star/security/XCertificate.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <cppuhelper/bootstrap.hxx>
+#include "cppunit/TestAssert.h"
+#include "cppunit/TestFixture.h"
+#include "cppunit/extensions/HelperMacros.h"
+#include "cppunit/plugin/TestPlugIn.h"
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+
+#include <neon/ne_ssl.h>
+
+using namespace com::sun::star;
+
+#define OID_SUBJECT_ALTERNATIVE_NAME "2.5.29.17"
+
+
+namespace {
+
+ class Test: public CppUnit::TestFixture {
+
+ private:
+ static uno::Sequence< security::CertAltNameEntry > altNames;
+ static bool runOnce;
+
+ uno::Reference< xml::crypto::XSecurityEnvironment > initUno();
+ void init();
+ OString getB64CertFromFile(const char filename[]);
+ test::OfficeConnection connection_;
+
+ public:
+
+ Test();
+
+ ~Test();
+
+ void test_Others();
+
+ void test_RFC822();
+
+ void test_DNS();
+
+ void test_Directory();
+
+ void test_URI();
+
+ void test_IP();
+
+ void test_RID();
+
+ void test_EDI();
+
+ void test_X400();
+
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(test_Others);
+ CPPUNIT_TEST(test_RFC822);
+ CPPUNIT_TEST(test_DNS);
+ CPPUNIT_TEST(test_Directory);
+ CPPUNIT_TEST(test_URI);
+ CPPUNIT_TEST(test_IP);
+ CPPUNIT_TEST(test_RID);
+ CPPUNIT_TEST(test_EDI);
+ CPPUNIT_TEST(test_X400);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ uno::Sequence< security::CertAltNameEntry > Test::altNames;
+ bool Test::runOnce = false;
+
+ CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+ Test::Test()
+ {
+ if (runOnce)
+ return;
+ runOnce = true;
+ connection_.setUp();
+ init();
+ }
+
+ Test::~Test()
+ {
+ if (runOnce)
+ {
+ connection_.tearDown();
+ runOnce = false;
+ }
+ }
+
+
+ uno::Reference< xml::crypto::XSecurityEnvironment > Test::initUno()
+ {
+ uno::Reference< uno::XComponentContext > context(connection_.getComponentContext(), uno::UNO_QUERY_THROW);
+ uno::Reference< lang::XMultiServiceFactory > factory(context->getServiceManager(), uno::UNO_QUERY_THROW);
+ uno::Reference< xml::crypto::XSEInitializer > xSEInitializer = xml::crypto::SEInitializer::create(context);
+ uno::Reference< xml::crypto::XXMLSecurityContext > xSecurityContext(
+ xSEInitializer->createSecurityContext(OUString()));
+ return xSecurityContext->getSecurityEnvironment();
+ }
+
+
+ void Test::init()
+ {
+ uno::Reference< xml::crypto::XSecurityEnvironment > xSecurityEnv = initUno();
+ OString b64Cert(getB64CertFromFile("User_35_Root_11.crt"));
+ uno::Reference< security::XCertificate > xCert = xSecurityEnv->createCertificateFromAscii(
+ OStringToOUString( b64Cert, RTL_TEXTENCODING_ASCII_US ) );
+ uno::Sequence< uno::Reference< security::XCertificateExtension > > extensions = xCert->getExtensions();
+ for (sal_Int32 i = 0 ; i < extensions.getLength(); i++)
+ {
+ uno::Reference< security::XCertificateExtension >element = extensions[i];
+ OString aId ( (const char *)element->getExtensionId().getArray(), element->getExtensionId().getLength());
+ if (aId.equals(OID_SUBJECT_ALTERNATIVE_NAME))
+ {
+ uno::Reference< security::XSanExtension > sanExtension ( element, uno::UNO_QUERY );
+ altNames = sanExtension->getAlternativeNames();
+ break;
+ }
+ }
+ }
+
+ OString Test::getB64CertFromFile(const char filename[])
+ {
+ ne_ssl_certificate* cert = ne_ssl_cert_read(filename);
+ char* certExportB64 = ne_ssl_cert_export(cert);
+ OString certB64( certExportB64 );
+ return certB64;
+ }
+
+
+ void Test::test_Others() {
+ CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) );
+ for(int n = 1; n < altNames.getLength(); n++)
+ {
+ if (altNames[n].Type == security::ExtAltNameType_OTHER_NAME)
+ {
+ css::beans::NamedValue otherNameProp;
+ if (altNames[n].Value >>= otherNameProp)
+ {
+ CPPUNIT_ASSERT_EQUAL( OUString("1.2.3.4"), otherNameProp.Name);
+ uno::Sequence< sal_Int8 > ipAddress;
+ otherNameProp.Value >>= ipAddress;
+ CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( ipAddress.getLength() > 0 ) );
+ }
+ }
+ }
+ }
+
+ void Test::test_RFC822() {
+ CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) );
+ for(int n = 1; n < altNames.getLength(); n++)
+ {
+ if (altNames[n].Type == security::ExtAltNameType_RFC822_NAME)
+ {
+ OUString value;
+ altNames[n].Value >>= value;
+ CPPUNIT_ASSERT_EQUAL( OUString("my@other.address"), value);
+ }
+ }
+ }
+
+ void Test::test_DNS() {
+ CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) );
+ for(int n = 1; n < altNames.getLength(); n++)
+ {
+ if (altNames[n].Type == security::ExtAltNameType_DNS_NAME)
+ {
+ OUString value;
+ altNames[n].Value >>= value;
+ CPPUNIT_ASSERT_EQUAL( OUString("alt.openoffice.org"), value);
+ }
+ }
+ }
+
+ void Test::test_Directory() {
+ // Not implemented
+ }
+
+ void Test::test_URI() {
+ CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) );
+ for(int n = 1; n < altNames.getLength(); n++)
+ {
+ if (altNames[n].Type == security::ExtAltNameType_URL)
+ {
+ OUString value;
+ altNames[n].Value >>= value;
+ CPPUNIT_ASSERT_EQUAL( OUString("http://my.url.here/"), value);
+ }
+ }
+ }
+
+ void Test::test_IP() {
+ CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) );
+ for(int n = 1; n < altNames.getLength(); n++)
+ {
+ if (altNames[n].Type == security::ExtAltNameType_IP_ADDRESS)
+ {
+ uno::Sequence< sal_Int8 > ipAddress;
+ altNames[n].Value >>= ipAddress;
+ CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( ipAddress.getLength() > 0 ) );
+ }
+ }
+
+ }
+
+ void Test::test_RID() {
+ CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) );
+ for(int n = 1; n < altNames.getLength(); n++)
+ {
+ if (altNames[n].Type == security::ExtAltNameType_REGISTERED_ID)
+ {
+ OUString value;
+ altNames[n].Value >>= value;
+ CPPUNIT_ASSERT( OUString("1.2.3.4").equals(value));
+ }
+ }
+ }
+
+ void Test::test_EDI() {
+ // Not implemented
+ }
+
+ void Test::test_X400() {
+ // Not implemented
+ }
+}
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/qa/certext/User_35_Root_11.crt b/xmlsecurity/qa/certext/User_35_Root_11.crt
new file mode 100644
index 000000000..0092d16c7
--- /dev/null
+++ b/xmlsecurity/qa/certext/User_35_Root_11.crt
@@ -0,0 +1,64 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4130 (0x1022)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Nov 8 10:51:39 2010 GMT
+ Not After : Nov 8 10:51:39 2011 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 35
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:9b:36:00:64:f3:ce:93:97:62:19:fa:78:d9:6f:
+ 92:6a:b9:d2:9a:4e:06:2c:02:52:cd:93:50:84:28:
+ 19:42:a2:4a:34:e2:cd:e6:b0:39:7a:c8:4d:84:bc:
+ 71:51:ed:5d:6c:7e:f9:cc:01:5a:4b:73:50:a9:3b:
+ 5d:ad:cc:89:f7:dc:e0:dd:0a:ff:48:01:a9:34:19:
+ c0:6a:ee:4b:20:f4:cf:3c:94:c1:ae:88:0f:c9:42:
+ 1a:a6:47:31:fe:37:04:00:bb:ec:07:5f:cb:ee:70:
+ c4:c7:7c:6f:ee:03:19:76:de:0b:df:d0:48:91:67:
+ 55:9b:90:91:f4:ce:56:04:d5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 91:47:AC:29:95:5D:EF:72:14:8F:82:45:07:E2:94:49:75:C6:7D:73
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DNS:alt.openoffice.org, IP Address:192.168.7.1, IP Address:13:0:0:0:0:0:0:17, email:my@other.address, Registered ID:1.2.3.4, othername:<unsupported>, DirName:/C=DE/O=OpenOffice.org/OU=Development/CN=User 32 Root 11, URI:http://my.url.here/
+ Signature Algorithm: sha1WithRSAEncryption
+ 6e:80:e6:1e:86:3d:d2:65:a6:17:fa:80:2d:2e:dc:85:32:05:
+ a1:69:82:e1:79:d1:dc:de:69:cd:9e:f0:cc:90:75:a9:45:ee:
+ 73:46:fe:29:69:c0:99:bb:fc:3a:db:c0:5f:69:c6:b7:ea:9a:
+ 63:b2:8e:29:2c:a5:5a:88:88:94:75:4b:ab:0a:72:f6:3a:aa:
+ 5d:6b:3a:5c:b6:9b:57:f5:c1:51:af:df:3c:a6:8a:a3:da:70:
+ 66:61:49:12:06:78:98:9f:bc:78:3c:43:6d:08:94:aa:32:b6:
+ f3:cc:af:0d:29:fe:96:47:7d:fe:4a:61:48:90:11:0b:bd:0f:
+ a0:fd
+-----BEGIN CERTIFICATE-----
+MIIDajCCAtOgAwIBAgICECIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDExMDgxMDUx
+MzlaFw0xMTExMDgxMDUxMzlaMGAxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxEDAOBgNVBAMTB1VzZXIgMzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
+AJs2AGTzzpOXYhn6eNlvkmq50ppOBiwCUs2TUIQoGUKiSjTizeawOXrITYS8cVHt
+XWx++cwBWktzUKk7Xa3Miffc4N0K/0gBqTQZwGruSyD0zzyUwa6ID8lCGqZHMf43
+BAC77Adfy+5wxMd8b+4DGXbeC9/QSJFnVZuQkfTOVgTVAgMBAAGjggExMIIBLTAL
+BgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJFHrCmVXe9yFI+CRQfilEl1xn1zMB8GA1Ud
+IwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMIHdBgNVHREEgdUwgdKCEmFsdC5v
+cGVub2ZmaWNlLm9yZ4cEwKgHAYcQABMAAAAAAAAAAAAAAAAAF4EQbXlAb3RoZXIu
+YWRkcmVzc4gDKgMEoB4GAyoDBKAXDBVzb21lIG90aGVyIGlkZW50aWZpZXKkWDBW
+MQswCQYDVQQGEwJERTEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT
+C0RldmVsb3BtZW50MRgwFgYDVQQDEw9Vc2VyIDMyIFJvb3QgMTGGE2h0dHA6Ly9t
+eS51cmwuaGVyZS8wDQYJKoZIhvcNAQEFBQADgYEAboDmHoY90mWmF/qALS7chTIF
+oWmC4XnR3N5pzZ7wzJB1qUXuc0b+KWnAmbv8OtvAX2nGt+qaY7KOKSylWoiIlHVL
+qwpy9jqqXWs6XLabV/XBUa/fPKaKo9pwZmFJEgZ4mJ+8eDxDbQiUqjK288yvDSn+
+lkd9/kphSJARC70PoP0=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/qa/create-certs/create-certs.sh b/xmlsecurity/qa/create-certs/create-certs.sh
new file mode 100755
index 000000000..5a4c244c6
--- /dev/null
+++ b/xmlsecurity/qa/create-certs/create-certs.sh
@@ -0,0 +1,187 @@
+#!/usr/bin/env bash
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# The purpose of this script is to create certificates to be able to test ODF signing code.
+#
+# What it does:
+#
+# 1) Create a test root CA.
+#
+# 2) Create an intermediate CA, as signing certificates with a root CA is
+# considered unsafe.
+#
+# 3) Create two client certificates that can be used to sign ODF documents in
+# LibreOffice.
+#
+# References:
+#
+# <https://jamielinux.com/docs/openssl-certificate-authority/> for most of the
+# commands.
+#
+# <https://www.sslshopper.com/article-most-common-openssl-commands.html> for
+# the PKCS#12 export of self-signed certificates
+#
+
+set -e
+
+root="$PWD"
+algo="RSA"
+
+if [ -n "$1" ]; then
+ algo="$1"
+fi
+
+if [ -d "$root/ca" ]; then
+ echo "'ca' directory already exists in $root, please remove it before running this script."
+ exit 1
+fi
+
+if [ -z "$SSLPASS" ]; then
+ # Unless specified otherwise, we'll use this as a password everywhere.
+ export SSLPASS="xmlsecurity"
+fi
+
+# 1) Create the root pair.
+
+mkdir "$root/ca"
+
+cd "$root/ca"
+mkdir certs crl newcerts private
+chmod 700 private
+touch index.txt
+echo 1000 > serial
+
+sed "s|@ROOT@|$root|g" "$root/templates/root.cnf" > "$root/ca/openssl.cnf"
+
+# Create the root key.
+cd "$root/ca"
+openssl genrsa -aes256 -out private/ca.key.pem -passout env:SSLPASS 4096
+chmod 400 private/ca.key.pem
+
+# Create the root certificate.
+cd "$root/ca"
+openssl req -config openssl.cnf \
+ -key private/ca.key.pem \
+ -new -x509 -days 36500 -sha256 -extensions v3_ca \
+ -out certs/ca.cert.pem \
+ -passin env:SSLPASS \
+ -subj "/C=UK/ST=England/O=Xmlsecurity ${algo} Test/CN=Xmlsecurity ${algo} Test Root CA"
+chmod 444 certs/ca.cert.pem
+
+# 2) Create the intermediate pair.
+
+# Prepare the directory.
+mkdir "$root/ca/intermediate"
+cd "$root/ca/intermediate"
+mkdir certs crl csr newcerts private
+chmod 700 private
+touch index.txt
+echo 1000 > serial
+
+# crlnumber is used to keep track of certificate revocation lists.
+echo 1000 > "$root/ca/intermediate/crlnumber"
+
+# Copy the intermediate CA configuration file.
+sed "s|@ROOT@|$root|g" "$root/templates/intermediate.cnf" > "$root/ca/intermediate/openssl.cnf"
+
+# Create the intermediate key.
+
+cd "$root/ca"
+openssl genrsa -aes256 \
+ -out intermediate/private/intermediate.key.pem \
+ -passout env:SSLPASS 4096
+chmod 400 intermediate/private/intermediate.key.pem
+
+# Create the intermediate certificate.
+
+# Intermediate key.
+cd "$root/ca"
+openssl req -config intermediate/openssl.cnf -new -sha256 \
+ -key intermediate/private/intermediate.key.pem \
+ -out intermediate/csr/intermediate.csr.pem \
+ -passin env:SSLPASS \
+ -subj "/C=UK/ST=England/O=Xmlsecurity ${algo} Test/CN=Xmlsecurity Intermediate Root CA"
+
+# The certificate itself.
+openssl ca -batch -config openssl.cnf -extensions v3_intermediate_ca \
+ -days 36500 -notext -md sha256 \
+ -in intermediate/csr/intermediate.csr.pem \
+ -passin env:SSLPASS \
+ -out intermediate/certs/intermediate.cert.pem
+chmod 444 intermediate/certs/intermediate.cert.pem
+
+# Create the certificate chain file.
+cat intermediate/certs/intermediate.cert.pem \
+ certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem
+chmod 444 intermediate/certs/ca-chain.cert.pem
+
+# 3) Create the real certificate.
+
+for i in Alice Bob
+do
+ # Create a key.
+ cd "$root/ca"
+ if [ "$algo" == "ECDSA" ]; then
+ openssl ecparam -name secp256r1 -genkey \
+ -out intermediate/private/example-xmlsecurity-${i}.key.pem
+ else
+ openssl genrsa -aes256 \
+ -out intermediate/private/example-xmlsecurity-${i}.key.pem \
+ -passout env:SSLPASS 2048
+ fi
+ chmod 400 intermediate/private/example-xmlsecurity-${i}.key.pem
+
+ # Create a certificate signing request (CSR).
+
+ cd "$root/ca"
+ openssl req -config intermediate/openssl.cnf \
+ -key intermediate/private/example-xmlsecurity-${i}.key.pem \
+ -new -sha256 -out intermediate/csr/example-xmlsecurity-${i}.csr.pem \
+ -passin env:SSLPASS \
+ -subj "/C=UK/ST=England/O=Xmlsecurity ${algo} Test/CN=Xmlsecurity ${algo} Test example ${i}"
+
+ # To create a certificate, use the intermediate CA to sign the CSR.
+ cd "$root/ca"
+ # usr_cert: the cert will be used for signing.
+ openssl ca -batch -config intermediate/openssl.cnf \
+ -extensions usr_cert -days 36500 -notext -md sha256 \
+ -in intermediate/csr/example-xmlsecurity-${i}.csr.pem \
+ -passin env:SSLPASS \
+ -out intermediate/certs/example-xmlsecurity-${i}.cert.pem
+ chmod 444 intermediate/certs/example-xmlsecurity-${i}.cert.pem
+
+ # Export it in PKCS#12 format.
+ if [ "$algo" == "ECDSA" ]; then
+ openssl pkcs12 -export \
+ -out ./intermediate/private/example-xmlsecurity-${i}.cert.p12 \
+ -passout env:SSLPASS \
+ -inkey intermediate/private/example-xmlsecurity-${i}.key.pem \
+ -passin env:SSLPASS \
+ -in intermediate/certs/example-xmlsecurity-${i}.cert.pem \
+ -certfile intermediate/certs/ca-chain.cert.pem
+ else
+ openssl pkcs12 -export \
+ -out ./intermediate/private/example-xmlsecurity-${i}.cert.p12 \
+ -passout env:SSLPASS \
+ -inkey intermediate/private/example-xmlsecurity-${i}.key.pem \
+ -passin env:SSLPASS \
+ -in intermediate/certs/example-xmlsecurity-${i}.cert.pem \
+ -certfile intermediate/certs/ca-chain.cert.pem \
+ -CSP "Microsoft Enhanced RSA and AES Cryptographic Provider"
+ fi
+done
+
+echo
+echo "Authority certificate is at: <$root/ca/intermediate/certs/ca-chain.cert.pem>."
+echo "To be able to import it in Windows, rename the '.pem' extension to '.cer'."
+for i in Alice Bob
+do
+ echo "Signing certificate is at <$root/ca/intermediate/private/example-xmlsecurity-${i}.cert.p12>."
+done
+
+# vim:set shiftwidth=4 expandtab:
diff --git a/xmlsecurity/qa/create-certs/templates/intermediate.cnf b/xmlsecurity/qa/create-certs/templates/intermediate.cnf
new file mode 100644
index 000000000..c6fd12d0a
--- /dev/null
+++ b/xmlsecurity/qa/create-certs/templates/intermediate.cnf
@@ -0,0 +1,132 @@
+# OpenSSL intermediate CA configuration file.
+# Copy to `$root/ca/intermediate/openssl.cnf`.
+
+[ ca ]
+# `man ca`
+default_ca = CA_default
+
+[ CA_default ]
+# Directory and file locations.
+dir = @ROOT@/ca/intermediate
+certs = $dir/certs
+crl_dir = $dir/crl
+new_certs_dir = $dir/newcerts
+database = $dir/index.txt
+serial = $dir/serial
+RANDFILE = $dir/private/.rand
+
+# The root key and root certificate.
+private_key = $dir/private/intermediate.key.pem
+certificate = $dir/certs/intermediate.cert.pem
+
+# For certificate revocation lists.
+crlnumber = $dir/crlnumber
+crl = $dir/crl/intermediate.crl.pem
+crl_extensions = crl_ext
+default_crl_days = 30
+
+# SHA-1 is deprecated, so use SHA-2 instead.
+default_md = sha256
+
+name_opt = ca_default
+cert_opt = ca_default
+default_days = 375
+preserve = no
+policy = policy_loose
+
+[ policy_strict ]
+# The root CA should only sign intermediate certificates that match.
+# See the POLICY FORMAT section of `man ca`.
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+[ policy_loose ]
+# Allow the intermediate CA to sign a more diverse range of certificates.
+# See the POLICY FORMAT section of the `ca` man page.
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+[ req ]
+# Options for the `req` tool (`man req`).
+default_bits = 2048
+distinguished_name = req_distinguished_name
+string_mask = utf8only
+
+# SHA-1 is deprecated, so use SHA-2 instead.
+default_md = sha256
+
+# Extension to add when the -x509 option is used.
+x509_extensions = v3_ca
+
+[ req_distinguished_name ]
+# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
+countryName = Country Name (2 letter code)
+stateOrProvinceName = State or Province Name
+localityName = Locality Name
+0.organizationName = Organization Name
+organizationalUnitName = Organizational Unit Name
+commonName = Common Name
+emailAddress = Email Address
+
+# Optionally, specify some defaults.
+countryName_default = GB
+stateOrProvinceName_default = England
+localityName_default =
+0.organizationName_default = Xmlsecurity Test
+organizationalUnitName_default =
+emailAddress_default =
+
+[ v3_ca ]
+# Extensions for a typical CA (`man x509v3_config`).
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer
+basicConstraints = critical, CA:true
+keyUsage = critical, digitalSignature, cRLSign, keyCertSign
+
+[ v3_intermediate_ca ]
+# Extensions for a typical intermediate CA (`man x509v3_config`).
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer
+basicConstraints = critical, CA:true, pathlen:0
+keyUsage = critical, digitalSignature, cRLSign, keyCertSign
+
+[ usr_cert ]
+# Extensions for client certificates (`man x509v3_config`).
+basicConstraints = CA:FALSE
+nsCertType = client, email
+nsComment = "OpenSSL Generated Client Certificate"
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid,issuer
+keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
+extendedKeyUsage = clientAuth, emailProtection
+
+[ server_cert ]
+# Extensions for server certificates (`man x509v3_config`).
+basicConstraints = CA:FALSE
+nsCertType = server
+nsComment = "OpenSSL Generated Server Certificate"
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid,issuer:always
+keyUsage = critical, digitalSignature, keyEncipherment
+extendedKeyUsage = serverAuth
+
+[ crl_ext ]
+# Extension for CRLs (`man x509v3_config`).
+authorityKeyIdentifier=keyid:always
+
+[ ocsp ]
+# Extension for OCSP signing certificates (`man ocsp`).
+basicConstraints = CA:FALSE
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid,issuer
+keyUsage = critical, digitalSignature
+extendedKeyUsage = critical, OCSPSigning
diff --git a/xmlsecurity/qa/create-certs/templates/root.cnf b/xmlsecurity/qa/create-certs/templates/root.cnf
new file mode 100644
index 000000000..1298d74d3
--- /dev/null
+++ b/xmlsecurity/qa/create-certs/templates/root.cnf
@@ -0,0 +1,132 @@
+# OpenSSL root CA configuration file.
+# Copy to `$root/ca/openssl.cnf`.
+
+[ ca ]
+# `man ca`
+default_ca = CA_default
+
+[ CA_default ]
+# Directory and file locations.
+dir = @ROOT@/ca
+certs = $dir/certs
+crl_dir = $dir/crl
+new_certs_dir = $dir/newcerts
+database = $dir/index.txt
+serial = $dir/serial
+RANDFILE = $dir/private/.rand
+
+# The root key and root certificate.
+private_key = $dir/private/ca.key.pem
+certificate = $dir/certs/ca.cert.pem
+
+# For certificate revocation lists.
+crlnumber = $dir/crlnumber
+crl = $dir/crl/ca.crl.pem
+crl_extensions = crl_ext
+default_crl_days = 30
+
+# SHA-1 is deprecated, so use SHA-2 instead.
+default_md = sha256
+
+name_opt = ca_default
+cert_opt = ca_default
+default_days = 375
+preserve = no
+policy = policy_strict
+
+[ policy_strict ]
+# The root CA should only sign intermediate certificates that match.
+# See the POLICY FORMAT section of `man ca`.
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+[ policy_loose ]
+# Allow the intermediate CA to sign a more diverse range of certificates.
+# See the POLICY FORMAT section of the `ca` man page.
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+[ req ]
+# Options for the `req` tool (`man req`).
+default_bits = 2048
+distinguished_name = req_distinguished_name
+string_mask = utf8only
+
+# SHA-1 is deprecated, so use SHA-2 instead.
+default_md = sha256
+
+# Extension to add when the -x509 option is used.
+x509_extensions = v3_ca
+
+[ req_distinguished_name ]
+# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
+countryName = Country Name (2 letter code)
+stateOrProvinceName = State or Province Name
+localityName = Locality Name
+0.organizationName = Organization Name
+organizationalUnitName = Organizational Unit Name
+commonName = Common Name
+emailAddress = Email Address
+
+# Optionally, specify some defaults.
+countryName_default = GB
+stateOrProvinceName_default = England
+localityName_default =
+0.organizationName_default = Xmlsecurity Test
+organizationalUnitName_default =
+emailAddress_default =
+
+[ v3_ca ]
+# Extensions for a typical CA (`man x509v3_config`).
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer
+basicConstraints = critical, CA:true
+keyUsage = critical, digitalSignature, cRLSign, keyCertSign
+
+[ v3_intermediate_ca ]
+# Extensions for a typical intermediate CA (`man x509v3_config`).
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer
+basicConstraints = critical, CA:true, pathlen:0
+keyUsage = critical, digitalSignature, cRLSign, keyCertSign
+
+[ usr_cert ]
+# Extensions for client certificates (`man x509v3_config`).
+basicConstraints = CA:FALSE
+nsCertType = client, email
+nsComment = "OpenSSL Generated Client Certificate"
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid,issuer
+keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
+extendedKeyUsage = clientAuth, emailProtection
+
+[ server_cert ]
+# Extensions for server certificates (`man x509v3_config`).
+basicConstraints = CA:FALSE
+nsCertType = server
+nsComment = "OpenSSL Generated Server Certificate"
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid,issuer:always
+keyUsage = critical, digitalSignature, keyEncipherment
+extendedKeyUsage = serverAuth
+
+[ crl_ext ]
+# Extension for CRLs (`man x509v3_config`).
+authorityKeyIdentifier=keyid:always
+
+[ ocsp ]
+# Extension for OCSP signing certificates (`man ocsp`).
+basicConstraints = CA:FALSE
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid,issuer
+keyUsage = critical, digitalSignature
+extendedKeyUsage = critical, OCSPSigning
diff --git a/xmlsecurity/qa/unit/data/xmlsecurity-dialogs-test.txt b/xmlsecurity/qa/unit/data/xmlsecurity-dialogs-test.txt
new file mode 100644
index 000000000..1f8ee2b62
--- /dev/null
+++ b/xmlsecurity/qa/unit/data/xmlsecurity-dialogs-test.txt
@@ -0,0 +1,45 @@
+# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+# This file contains all dialogs that the unit tests in the module
+# will work on if it is in script mode. It will read one-by-one,
+# try to open it and create a screenshot that will be saved in
+# workdir/screenshots using the pattern of the ui-file name.
+#
+# Syntax:
+# - empty lines are allowed
+# - lines starting with '#' are treated as comment
+# - all other lines should contain a *.ui filename in the same
+# notation as in the dialog constructors (see code)
+
+#
+# The 'known' dialogs which have a hard-coded representation
+# in registerKnownDialogsByID/createDialogByID
+#
+
+# No known dialogs in xmlsecurity for now
+
+#
+# Dialogs without a hard-coded representation. These will
+# be visualized using a fallback based on weld::Builder
+#
+
+# currently deactivated, leads to problems and the test to not work
+# This is typically a hint that these should be hard-coded in the
+# test case since they need some document and model data to work
+
+xmlsec/ui/viewcertdialog.ui
+xmlsec/ui/macrosecuritydialog.ui
+xmlsec/ui/certgeneral.ui
+xmlsec/ui/certdetails.ui
+xmlsec/ui/certpage.ui
+xmlsec/ui/securitylevelpage.ui
+xmlsec/ui/securitytrustpage.ui
+xmlsec/ui/selectcertificatedialog.ui
+xmlsec/ui/digitalsignaturesdialog.ui
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf b/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf
new file mode 100644
index 000000000..10528c57f
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p1.pdf b/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p1.pdf
new file mode 100644
index 000000000..04d995058
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p1.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p3-stamp.pdf b/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p3-stamp.pdf
new file mode 100644
index 000000000..b30f5b038
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p3-stamp.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/cr-comment.pdf b/xmlsecurity/qa/unit/pdfsigning/data/cr-comment.pdf
new file mode 100644
index 000000000..b1aae07a2
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/cr-comment.pdf
@@ -0,0 +1,4480 @@
+%PDF-1.4 %âãÏÓ
+1 0 obj <</Metadata 2 0 R/Pages 3 0 R/Type/Catalog/ViewerPreferences<</Direction/L2R>>>> endobj 2 0 obj <</Length 45779/Subtype/XML/Type/Metadata>>stream
+<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
+<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.2-c063 53.352624, 2008/07/30-18:05:41 ">
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description rdf:about=""
+ xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"
+ xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#"
+ xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#"
+ xmlns:stMfs="http://ns.adobe.com/xap/1.0/sType/ManifestItem#">
+ <xmpMM:InstanceID>uuid:e7f483a2-dbf7-4046-8848-508b776dd738</xmpMM:InstanceID>
+ <xmpMM:DocumentID>xmp.did:89321C534E266811A613EDAC20FB34D2</xmpMM:DocumentID>
+ <xmpMM:OriginalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</xmpMM:OriginalDocumentID>
+ <xmpMM:RenditionClass>proof:pdf</xmpMM:RenditionClass>
+ <xmpMM:DerivedFrom rdf:parseType="Resource">
+ <stRef:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stRef:instanceID>
+ <stRef:documentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:documentID>
+ <stRef:originalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:originalDocumentID>
+ <stRef:renditionClass>default</stRef:renditionClass>
+ </xmpMM:DerivedFrom>
+ <xmpMM:History>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E4B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E5B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/metadata</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E6B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:44:22-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:80321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:46:03-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:81321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:48-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:82321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:49:01-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:83321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:52:39-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:84321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:58:06-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:85321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:59:50-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/metadata</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:89321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4A27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:48:01-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4B27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:50:54-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4C27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:54-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4D27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:55:16-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4E27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:56:27-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4F27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:58:44-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5027385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:05:30-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5127385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:07:25-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5227385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:12:43-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5327385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:13:56-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5427385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:16:22-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:DE855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:19:25-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:DF855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:27:07-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E0855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:29:58-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E1855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:32:34-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E2855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:33:46-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E3855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:40:42-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E4855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:41:28-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E5855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:42:42-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E6855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:44:36-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E7855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:47:08-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E8855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:51:29-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:80C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:49:23-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:81C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:50:43-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:82C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:52:12-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:00CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:53:23-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:01CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:53:56-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:02CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:56:41-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:03CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:03:21-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:04CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:06:47-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:05CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:09:26-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:06CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:11:53-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:07CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:13:29-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:999093B2AD2068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T14:21:34-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:9A9093B2AD2068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T14:27:38-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:9B9093B2AD2068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T14:30:31-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:371C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:20:55-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:381C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:26:33-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:391C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:29:07-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:3A1C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:31:19-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:7A0142B9242368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:41:33-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:7B0142B9242368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:44:10-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ </rdf:Seq>
+ </xmpMM:History>
+ <xmpMM:Manifest>
+ <rdf:Bag>
+ <rdf:li rdf:parseType="Resource">
+ <stMfs:linkForm>ReferenceStream</stMfs:linkForm>
+ <xmpMM:placedXResolution>72.00</xmpMM:placedXResolution>
+ <xmpMM:placedYResolution>72.00</xmpMM:placedYResolution>
+ <xmpMM:placedResolutionUnit>Inches</xmpMM:placedResolutionUnit>
+ <stMfs:reference rdf:parseType="Resource">
+ <stRef:instanceID>uuid:288c3c69-7dd6-7c4f-984d-b085b3307748</stRef:instanceID>
+ <stRef:documentID>uuid:93F9F49755C5DE1185BCB9A8461E73D9</stRef:documentID>
+ </stMfs:reference>
+ </rdf:li>
+ </rdf:Bag>
+ </xmpMM:Manifest>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:xmp="http://ns.adobe.com/xap/1.0/"
+ xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/">
+ <xmp:CreateDate>2010-07-02T15:32:26-07:00</xmp:CreateDate>
+ <xmp:ModifyDate>2010-07-02T15:32:26-07:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2010-07-02T15:32:26-07:00</xmp:MetadataDate>
+ <xmp:CreatorTool>Adobe InDesign CS4 (6.0.5)</xmp:CreatorTool>
+ <xmp:Thumbnails>
+ <rdf:Alt>
+ <rdf:li rdf:parseType="Resource">
+ <xmpGImg:format>JPEG</xmpGImg:format>
+ <xmpGImg:width>256</xmpGImg:width>
+ <xmpGImg:height>256</xmpGImg:height>
+ <xmpGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA&#xA;AQBIAAAAAQAB/+4AE0Fkb2JlAGQAAAAAAQUAAjSA/9sAhAAKBwcHBwcKBwcKDgkJCQ4RDAsLDBEU&#xA;EBAQEBAUEQ8RERERDxERFxoaGhcRHyEhISEfKy0tLSsyMjIyMjIyMjIyAQsJCQ4MDh8XFx8rIx0j&#xA;KzIrKysrMjIyMjIyMjIyMjIyMjIyMjI+Pj4+PjJAQEBAQEBAQEBAQEBAQEBAQEBAQED/wAARCAC1&#xA;AQADAREAAhEBAxEB/8QBogAAAAcBAQEBAQAAAAAAAAAABAUDAgYBAAcICQoLAQACAgMBAQEBAQAA&#xA;AAAAAAABAAIDBAUGBwgJCgsQAAIBAwMCBAIGBwMEAgYCcwECAxEEAAUhEjFBUQYTYSJxgRQykaEH&#xA;FbFCI8FS0eEzFmLwJHKC8SVDNFOSorJjc8I1RCeTo7M2F1RkdMPS4ggmgwkKGBmElEVGpLRW01Uo&#xA;GvLj88TU5PRldYWVpbXF1eX1ZnaGlqa2xtbm9jdHV2d3h5ent8fX5/c4SFhoeIiYqLjI2Oj4KTlJ&#xA;WWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+hEAAgIBAgMFBQQFBgQIAwNtAQACEQMEIRIxQQVRE2Ei&#xA;BnGBkTKhsfAUwdHhI0IVUmJy8TMkNEOCFpJTJaJjssIHc9I14kSDF1STCAkKGBkmNkUaJ2R0VTfy&#xA;o7PDKCnT4/OElKS0xNTk9GV1hZWltcXV5fVGVmZ2hpamtsbW5vZHV2d3h5ent8fX5/c4SFhoeIiY&#xA;qLjI2Oj4OUlZaXmJmam5ydnp+So6SlpqeoqaqrrK2ur6/9oADAMBAAIRAxEAPwCReWvLfleTyzo9&#xA;zd6VYPJNY2zySy28JZ3aJGZmZkqSTlgApgSbTL/Dfk3/AKtOmf8ASNB/zRhoIsrk8reUZKlNH01q&#xA;deNrAf1JjQWymEXlLyYIk9TRdLDU35WsFfxjys82Y5L18peSmPFdE0tiewtLcn/k3gSubyd5OUcm&#xA;0LTFA7m0gA/5N4qt/wAKeSf+rLpX/SLb/wDVPFXf4U8k/wDVl0r/AKRbf/qnirX+FPJP/Vl0r/pF&#xA;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&#xA;xV2KuxV2KpL5z/5Q/Xv+2bef8mJMVf/Z</xmpGImg:image>
+ </rdf:li>
+ </rdf:Alt>
+ </xmp:Thumbnails>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:idPriv="http://ns.adobe.com/xmp/InDesign/private">
+ <idPriv:DocChangeCount>244</idPriv:DocChangeCount>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <dc:format>application/pdf</dc:format>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
+ <pdf:Producer>Adobe PDF Library 9.0</pdf:Producer>
+ <pdf:Trapped>False</pdf:Trapped>
+ </rdf:Description>
+ </rdf:RDF>
+</x:xmpmeta>
+<?xpacket end="r"?> endstream endobj 3 0 obj <</Count 1/Kids[5 0 R]/Type/Pages>> endobj 5 0 obj <</ArtBox[0.0 0.0 841.89 595.276]/BleedBox[0.0 0.0 841.89 595.276]/Contents 6 0 R/CropBox[0.0 0.0 841.89 595.276]/Group 7 0 R/MediaBox[0.0 0.0 841.89 595.276]/Parent 3 0 R/Resources<</ColorSpace<</CS0 8 0 R>>/ExtGState<</GS0 9 0 R/GS1 10 0 R/GS2 11 0 R>>/Font<</C2_0 12 0 R/C2_1 13 0 R/C2_2 14 0 R>>/ProcSet[/PDF/Text]/Properties<</MC0<</Metadata 15 0 R>>>>/Shading<</Sh0 16 0 R>>/XObject<</Fm0 17 0 R/Fm1 18 0 R/Fm2 19 0 R/Fm3 20 0 R>>>>/TrimBox[0.0 0.0 841.89 595.276]/Type/Page>> endobj 6 0 obj <</Filter/FlateDecode/Length 7843>>stream
+H‰ÌWm‹¹þ>¿¢?¶W*½ƒYðŽ½†ÀÁ/ÜA!¬Ï6‰7áb8È¿ÏSU’Z­™ñÝÚ¾#,lOI¥z}ªJ2«]Ìj<ÿï埇ëWoÌòþÓ²Y£ÃR¶k*n %¬”ÂòŸŸï×ßüûÃOo¿q·\w4Ëí‹ãrøùR]­9„%Ù•lX¬]‹I|ð‡å_³Èß ëçÅ
+e—èÓ•%âLŽ~yxÎÇÕY §ÍòQ~Ƹð§D¥­ÍmÚO¬§4…˜°Î-‡NhSjoÇ;;P/zAfïX8¢ä7rÓÍÜj[‰;Ú•²ã>íhG±ðQU«‰LP°•ªlõËZ}S=qÐ[Éc÷áA¬”äº4–Ae‚dSrZ6¿²˜ÇVËÁJg/ùÜ•]mé,´Rb ›¦$@“Û±ö[E
+¥ÚšïÕŒÍÄn1¤9ÕäH¶ÑøÇ‹¡ªF+Ý3…J¨&ÄâR*S­k@߃ŕde5ŸÕŽ•¢¹1ÈÏV»Õ¥N#Û~µÇÒ—”&Ôh) d/8bÂf¡Ràà‚6‰ˆ«IPÂÊžw‹ËEàt•Po¢G]e`'ð¡‰wCrË/ÐÀíH?.2Sæ¥Õp6 ÀH,ãj9{ݨ ?Ðe%@Œ— øÊŠ= ¾1à`£6A“ yïëOiG[x‰öá*ÈBY $e&Ñš¢D?#
+´¸Õ'‰òäP%CXHêEbÒS
+Sö^ö¥é#ãT¤é÷Þ
+½¡*Šƒ
+ïW†õÉv»½œ¶ÞÊbFá‰SYÌþÍåÜíh03§ò„~y¡ ·*xZ<¿m7ëá™7·Ü%³;ʼ@0î_RýÜ MåÏ"ê8E2žï3¿Úéólù½3û[u)Ã}Ì)q³?ƒÇ“X< ]½šæ]³-=çsuN3ä$W ~vöí†Ü µ¡~î¢Á{ïׯÞØåý§ÃõÝ£Y^ü-˜¯'!òw±Oà—Œ«n¼ÞÞ*v/€¯È>e~Òî{—ÊŒÛæø{ãˆ-ݹlqq¶¸••èrÆ=ýáñpûãrýæƒY>}X^þ¸¼þ•[Ò‰ñ¶Û!&†áÇ
+p½uèm†Á }I{‹ü­9¨ ¦™`ëÔäWž NþñZˆ/ŽÀ?¢éÃ3š*쨖8U¸É— ¬]*Ì©– UØ*_¥C¥¹<Ü §kßvåp~ÝOt9/·}_Ó¸³Q“¯5“^ûy=-.ÁìùhŠÊ™âhWÓO“]?LS"Ú6%¨±|aHirÍ×}Û\½»‚)ÜÉÜ
+bÑN¶—ß]º±î Dº|7É>í§ý¹­)eÍŸ“mPÖÎŒ” bíäÞ—#¿gîþOZÄ_˜¨¾ž§ónoÙIàg9愧¿óMî‰"cë9;'l®½²—Ó=yoÏY µšœk¯Ë÷{»C>oG˜Þ€'y¹gŽ%i£œË¯ÁrøÆQúŒ“Pú€¾T¶ä?ƒ;•éÜql¥Ý$oÆmïtqŠZœä´(O7LQoÌ·sQ/Ns6z<Ž{ûÛ9ò_«Gs¶ûÍ ifí jE
+y
+”'6¿ïÄ’Ä.˜—õ[iÞ7²/stÊtÁc,h¦Yfª—ª¨6w[ëËI~mð~°ó ÎûÞ~>€jgu0¾Z*‰ºÓ ùç*͆ÝnÞ‡çÕòc5î¶òWMó5ouŠ‹u¾FàXyíÅK › CwS#f¸áb@5ÐYgéPӈˡ21›M˜ê®‡o‡Ì5ûì·E÷¢ÍM¬²hÎľtÚ¡!zÆMÑ*ݵ¾Ö¡1Èʬk»éTÓ¾_–5eOˆíM¤­]ìšCÁ;É~]s šQvì2-ææQ]£š±1Älµ}¶×êóïÕŽTs8œfD‚£.GaîW¨ßþ¿öŠçK-b‚µ? [N¢2XÜÒ!kµÈ7lBÒ³æÁùŽkYnbó/}Û%4PÅjÕÝåþ7Éli0j)$Sß”O àßX]\KH½ÖÐ#ɺ¸¡ùÔWK®ë¸÷*¼;üK ¶ßu̲€ ‚Œ² YU,II¾×~ q[Ïúë{Ωk &¹¥Í<ˆI{"Xµÿ8 ±Y*øò7q››íur |å6 ~tN.ÔøíÈp
+i¦b{.+…ÆÞÓ Ñ ¹ÍpNøë«Çñù4k\W>!þuô(\ [rNŠaO@÷!ò\VÈÏ“ç^j¢#Û á¤Ê„üÉJ»Ðˆ,¸ñš¿«g¤˜ ŽöÂΘtF+Ó£0dÉ{û˜gå+'§AÌß ¢Û^åÕ
+k!ìq&Cú(x(ŽÖ:VALär¼ Yâ?28x}ñÃhWpˆ9ÖÐOYÞè_ä%Ël|ù1šc¹Ú@†LÖñ/° ñ1ÊÇ oÙý‚op­å˜=¨&~GeÁJµrJ«òvÊX»Å)¾4¨ÓY_Œ^²ð‹PG…CTF
+Fçæ°¸X l¢™çH\v˜µ²,]=‘·•:¿sé¢+ ¯’ÑØÃ<)Ì)âSèæËÑ$&þ9j•ÞØäßúàH*Ó_ow'¶1àÈRÁ<‰® žè{*%AÚ+à´ìmê
+à>€A©M^ó¾ÛôÝ×ê--ÞBjúÂàoqÎÅH“ös{m‡tm=ÚñmòÌf§<ü»öÀíNŽmš&DOkƒ–ÛÁǯ0'ï©n-3­:6}Å‚ÙDž·ŒÜn–ÈÛî*RL<èëÙ#ê(FÄä}«ÏÞ‹á°-Ž¸Ðå{ïj+¢‰¯ 4k
+â¸çÈÔ¢BkL}ÔÜ!:+—™ÂÅ©N>,ªÙZ¹
+Ƶ„ñÀŒÀ‹&×åÔtµpÿ W÷Å{
+Þóhçבž‹(Üeô9€†Çl(u$"07±47‰†ßà¼Í“‹)ÜD`ǼOÑœ‡‹õk£³eѽ+‘‹€ù{^¸÷vÇŽ=qßCñ=™¶…-ÒCçxºËýÒ¥=%ó"Ë6–˜S :Ò@Š¦Ž+¦ ±rÙ‰£†×BÆ’Ê]'ÅUh·£)ç~3n¦zûÎzZ OŸÎ Òi—± N!sÓúgC"ßH.QàÂWo@«jÖZ¡ƒ(U-8ä;‚­¡we4I"lF$Œçè?
+Ÿá»MµT‡{çµáé•‘2¤2Ê‚¥8*ϬeˬÁ¡Sz'‚ö{ÆmT%[V›B[ù8lÚ^jdÏûZ¾¿gÙ‰GikÖÏæÕ:Ä…Ž9AåûŽ±yüŽ±ÙÆ•Á|ob ì4(cYÖ\¾GÑ!ýµä©ƒ‰÷šéhno‚Á=r5JNÑ­nxÂ$1üYH¹Ìôwªÿüpõ¯{¾¿\ì6aó<–þƒÂßø«´÷¹cG<J¹‚<#m2}¤o5Ô
+”7ÊÕmoõBûb/‘ûç„ÝG¹7T«Ÿô[ì¸êõýÝ
+†¡íl¹ÝP÷V>a߯R)V<YR\Ýpu$T%‚zDï9²l4÷=¶ÛK,-¿DÅ9ZdÎÞÚ~Ê Ë á}ãK?è\ˆ'1R‘µ½îªçöÉ ºùÀ¿ÿÚ®a·Gð}YãPúGþ*Q)1Vtέ´Oã,âòbf¼~¥‡4÷ä
+Ðnàˆ8碩ÎÂÅÀïÎ@òž¿ñV1/ìegDM"HÖPOø‚qÓ±{C }Z,¨5:³# ?YMN-ŠžC^cêUÁzdü&çP.>Ñrr–äYqKÜq6Ó5ŸÍI1&I§ñXÒ‡H†9ôÅÖ
+k˜´aöiK¾.¶ûS‡>“Qﻄ_m”P+{›Ê¸:
+€u¥,¼ãXÄÖ×̸BñxDX”ì_Ðj,2’'3K~“,€ª.)¢ˆðÙÓ4c 5]Qõ£¶_u•Ú‘¢HÁcEI~b ” $
+îf@q½Ákš\Í­üØœŸŠ;Žòò9ø
+Ç †ª pK*þ{£»þ›8hØa®ìz¸òÈS)Ö"µ±È6»¿¥ªŠ¾¹š†m½ÊæŠ^s™-.N@e¥TÝVí*gÜë•ãM“Q¿WY2ÿ(0—W¯Q<¿™Ÿ¸úñb¦Óà.“÷„B#ƒu¶ø#£.ÆÒ[‰>Ïéæ¹€GÜu†»ÈÆ°u²Ð\å’SMi¥®Ðv€–ñ¨[FØT²…áξEðóL°.? ¼Ðþd/nt]ájá¨/¸Âoó5Ÿm¡f‡Zͪ‘ó…W¤ºpΩs&HdÈ nà¿P»"NJ¼Ë;©qíÔ€ó"ÆVhËc6.A $kt>¶“bòÅËU¨
+·Qõ
+u¢³v’ˆ:xgÛSÓ¤E|ë&âûïmy¾O€í&m«á -nÍÄÖÅÅ€5ý³*€‘vÏ|‹gçŒÐymÔ65Âû¥•ݵ‡ô’cšl/é’㊠Ñ{®jB¨•.wx}_Ì\uVÙ®´
+edñ` ¹ú
+ÂâE¥÷J(IÅš1¬ÐÃxk3²’a2Vˆb…#¿ç–îrƒ6#Hì†E£â#¶<ìXxÙIÉ#ñ?÷º$¡¬™ø^ÿ¥WOÜé—Ÿïõú}íî;é–”ÒAyʵù~Á fx'oÇä®12wium
+ܤó
+ ÃÁõ C=hŠ¢[Eû˜Á#ݨ¼ìLÏÔ$ÜÒ$ê¸%ã[n#6 ÜyKxå´ÔVrÚ˜äs#Nüúh+,f“þ–¥QÜßQV1‹¬1ùe¨[÷ô<Ë»ïd½Ç²G*ûø%¹@ØyÄk9bsÅ«½`°§Ösjúø§é¦¿Þw‡¿o?~þ2‡?ÿ
+xfd`¦âŧ?íê`Þ)bÜú‚O9Œ2þºC†*Ϻ ™ÀŸBŸàð
+H‰LŒ1
+Ã@ {½b?`ùN:ét­!¤6.â>„¸‰Áöÿ!&nÂÃÀ°™g‡ÕÂ!DbWt¹²jÁþ¢VÚ(áMý}:qÐIkYéÜ¿ÿ­…x…Yå-<Ï 3úiI8ÜfŒ4ÒW€
+H‰LŒ±
+ƒ@DûùŠù×½½œ·Û
+’Z,bBl"¨ÿ‘Ø„)³Á‹ŠÍ:IflÌCºÌ&UÉêÜ_xpÅåí}:qàŠ,"åL=÷ï¿CZµÐÔÅÓM­Ÿô3ÛiQ ‡™#F|
+H‰LŒ±
+Ã0Cw}…~ ÎùìØwk¡tš½„fi ÉÿCÝv)žíP“P³Õ VÙ©ùÇ»XC®‰Ç‚;7ì>Ñߦ†¿‘ºÇ”(-ÿþ=l]­0³èà|¼p™ÙO«ð\y9bÄ[€
+H‰LŒ±
+ƒP E÷|Åýc|y1É*”ÎâP÷RêRAý¨Ô¥Üápàp7
+Ž„yå(M‰ä^ÑtΪû‹Xi#Á›Úûtâ +*™*äÜ¿ÿ#ÝÅ`æ\#£‚燆í´Ž·#ô`
+H‰ª6RÈÌKI­P0Ô3
+¹PTšÁTš0Òn¹ •p‡äÀq-@€
+<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
+<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.2-c063 53.352624, 2008/07/30-18:05:41 ">
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description rdf:about=""
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <dc:format>application/pdf</dc:format>
+ <dc:title>
+ <rdf:Alt>
+ <rdf:li xml:lang="x-default">MS_Logo_70%</rdf:li>
+ </rdf:Alt>
+ </dc:title>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:xmp="http://ns.adobe.com/xap/1.0/"
+ xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/">
+ <xmp:CreatorTool>Adobe Illustrator CS3</xmp:CreatorTool>
+ <xmp:CreateDate>2009-10-28T13:10:30-07:00</xmp:CreateDate>
+ <xmp:ModifyDate>2009-10-28T14:10:20-07:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2009-10-28T14:10:20-07:00</xmp:MetadataDate>
+ <xmp:Thumbnails>
+ <rdf:Alt>
+ <rdf:li rdf:parseType="Resource">
+ <xmpGImg:width>256</xmpGImg:width>
+ <xmpGImg:height>44</xmpGImg:height>
+ <xmpGImg:format>JPEG</xmpGImg:format>
+ <xmpGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA&#xA;AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK&#xA;DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f&#xA;Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgALAEAAwER&#xA;AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA&#xA;AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB&#xA;UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE&#xA;1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ&#xA;qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy&#xA;obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp&#xA;0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo&#xA;+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9SXlzHa2k9zJ/dwRtK/y&#xA;QFj+rFXzFcTyTzyTyGskrM7nxZjU5JCzFX0V5IYN5R0kg1H1aMfSBQ5EpeT/AJpeYhqvmJraFuVp&#xA;pwMKUOxkr+9b7xx+jJBDDcVZz5H0+9PlPzJe2cDz3U8aWNvHEpZiJD+9oB/kuDgVj/8AgzzZ/wBW&#xA;i7/5FP8A0wq9u8i6VLpflTT7SaMxz8DJMjCjBpGLkMPEcqZEpT7FXYq7FXYq7FXYq7FXYq7FXYq7&#xA;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</xmpGImg:image>
+ </rdf:li>
+ </rdf:Alt>
+ </xmp:Thumbnails>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/">
+ <xmpMM:DocumentID>uuid:93F9F49755C5DE1185BCB9A8461E73D9</xmpMM:DocumentID>
+ <xmpMM:InstanceID>uuid:288c3c69-7dd6-7c4f-984d-b085b3307748</xmpMM:InstanceID>
+ <xmpMM:DerivedFrom rdf:parseType="Resource"/>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:xmpTPg="http://ns.adobe.com/xap/1.0/t/pg/"
+ xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#"
+ xmlns:xmpG="http://ns.adobe.com/xap/1.0/g/">
+ <xmpTPg:NPages>1</xmpTPg:NPages>
+ <xmpTPg:HasVisibleTransparency>False</xmpTPg:HasVisibleTransparency>
+ <xmpTPg:HasVisibleOverprint>False</xmpTPg:HasVisibleOverprint>
+ <xmpTPg:MaxPageSize rdf:parseType="Resource">
+ <stDim:w>6.000000</stDim:w>
+ <stDim:h>2.000000</stDim:h>
+ <stDim:unit>Inches</stDim:unit>
+ </xmpTPg:MaxPageSize>
+ <xmpTPg:PlateNames>
+ <rdf:Seq>
+ <rdf:li>Black</rdf:li>
+ </rdf:Seq>
+ </xmpTPg:PlateNames>
+ <xmpTPg:SwatchGroups>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:groupName>Default Swatch Group</xmpG:groupName>
+ <xmpG:groupType>0</xmpG:groupType>
+ <xmpG:Colorants>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>K=100</xmpG:swatchName>
+ <xmpG:mode>GRAY</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:gray>255</xmpG:gray>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=0 Y=0 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>K=100</xmpG:swatchName>
+ <xmpG:mode>GRAY</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:gray>255</xmpG:gray>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=0 Y=0 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ </rdf:Seq>
+ </xmpG:Colorants>
+ </rdf:li>
+ </rdf:Seq>
+ </xmpTPg:SwatchGroups>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:illustrator="http://ns.adobe.com/illustrator/1.0/">
+ <illustrator:Type>Document</illustrator:Type>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
+ <pdf:Producer>Adobe PDF library 8.00</pdf:Producer>
+ </rdf:Description>
+ </rdf:RDF>
+</x:xmpmeta>
+<?xpacket end="r"?> endstream endobj 12 0 obj <</BaseFont/UZUFLT+Segoe-Semibold/DescendantFonts 34 0 R/Encoding/Identity-H/Subtype/Type0/ToUnicode 35 0 R/Type/Font>> endobj 13 0 obj <</BaseFont/SJATJX+Segoe/DescendantFonts 36 0 R/Encoding/Identity-H/Subtype/Type0/ToUnicode 37 0 R/Type/Font>> endobj 14 0 obj <</BaseFont/QTGHHB+Segoe-Bold/DescendantFonts 38 0 R/Encoding/Identity-H/Subtype/Type0/ToUnicode 39 0 R/Type/Font>> endobj 38 0 obj [40 0 R] endobj 39 0 obj <</Filter/FlateDecode/Length 531>>stream
+H‰\”Íjã0F÷~
+-ÛE±-Ý+µmÒ@óÃdæ[I mg‘·Å't`-låûιùj»ÞvídòŸc_ïâdm׌ñÜ_Æ:š}<¶]VZÓ´õt§ù}ª†,O‡w×óOÛîÐg‹…É¥‡çi¼š‡×¦ßÇÇ,ÿ16ql»£yø³Ú=š|w†ÏxŠÝd
+³\š&Ò}«†ïÕ)š|>ö´mÒóvº>¥3ÿÞø}¢±3—”©û&ž‡ªŽcÕc¶(Ògi›ôYf±kþ{
+ŽíõG5ί»ôzQØb9“‡ô=C+èz‡Þ  ´š©, 5TBï…6éŽôR RÈBèRèò==Ë5ô:“%AH°$ wÁÝ’'äYò„<Kžg™’0%KºnI—{:3ff™™03ÇÌ„™9f&ÌÌ13afŽ™)3s)F#ÅÈa¤9Œ#‡‘bä0RŒÒ°f
+~ŠŸÃAqZ+­…žJO¡§§§ÐÓÓSèéé)ôôôzzz
+===…žžžBOOO¡§§§pž{îÁs‚ƒ¿;pž{PŒ<FÊ=xîAñóø)~?Å(`¤Œ£€‘b0RŒFŠQÀH1
+)F#¥u õêÞÚcœ~ø÷_øm¤Me¾öK}Ç´Zæu6ï”Û6i»øµñ†~0éÔí/û+À
+H‰j
+H‰dV TT×½ç¾÷f
+Ú,UÚ àâ/ýãџУºŒ!O"1o­ÆàgÒù˜CFa$¿Nœò˜ዶû~_üN4ÞZ¼G¦vG…?Þü.ÜjÛ¾ L‰œv[/ˆu5›Ö ”鮚xÁ›‰.:Š:XhôÓhÍߊ(‡f÷`G`9Ÿ¶?{OõI<5ûוdMÆÕÓ+3ñFã|Ëø`Kê\stÜÁ‡U_»Wßb—“þóåÍ…w;£&¦¦ÅÎŽ‰Ñ(z¤#z è8s¥n5¹èduEt†sr$žÆ»§6çV=šÅjÖìÛuïVÉï°iåÜ$‹uÕ¼Ù™’‹qÎ/@Ž»ÿW¾ûÝ÷®=ݹmßÉÓ¹Ož²jͦŠìà®ÜŸ¸6DäMá\äÕ½ÁäLAä-eÅ.\BŒNµwüÈmN]fJ)õHË~&8$ÑI
+4Q«%¥+3/ÇO¹éËõ7WƒHlRÊí‡áQDlôFÂÅŽkÚÉž cþ™l¤;X¨Õhù ö0£QGu𢢈jG;vþWmç/Š7¦Ä¯=”:×?+Ü“–±yÍ©/r£&AÍ¥ï”ò…óÙÌ%{-]G°f™ú<yn³XÄ~‰£NT¹v
+9O.{#—–ìʈ'–¾}GI“¡óG±¨ÇÕ3ÔsOèG{!GÝÈ7Híçñ$Iñ´Rèw‚SÄ·Iß&PPûp¤BÐPY£t÷d;‡Íœ“ =èHß´/]ç3‰¾Sóɇ—k#9½´/±Ë»ôŠì®ëƸ–^ ùÛÕÕu†ÿsï¹wq‹ºPЬë–P»1Æè²"áQå±ìE¤D”‘¢âsàÂ`5¨PÂXÃJ†ZL­5Ç*t¨EkÔ µˆË0Žµ‰cvÏö?wwR™ù<ë½çœÿõý+Ó@BIê¿'ª)õ¹Ê/k—¦eÄØ7¢¥ïç&®ÿh4椬ÿŒ²p´BQ–¿+ºnQ£2°P„²’ï'j¨Wà dJK'ݾÔ[ÿld ·âô‹Ù<¡[èf–¥o§G·¢§Í¶W>öGšml6¹Óƒ³©üÏ®—í|W,îÒzv™Œ>A8j™áömÒËÎwI ]¸X¯hq&xfFÑbo-¬·ˆŸ¥ ‚UTÞ½``WI mÀÒ‰ì s~+öÑ@ìBze rõbMp0Ÿ?L8—gúHžIÀ$ö±;4çzí* YO¦œ=ו·3‹œe½çëÌ‹Öl…êÖÕÖƒÄ07¸9odf –Åø™b÷¤sY6är›4ŒYΧ€’‚ü]×5sÌRˆì:Ú^ötdRv…Dл=›3ØãÂœŒ}©y;­Øõ#EÒ°c÷™š²ÝËVVýrÓúÍÜÞ8´¨-
+PúªbÌèpåi¬beî‘êà õ„œMúÅî²D˯ì(Žª®ê'ꚣï±ç愤Êòz3j÷Ñ|ÔÚwœ‡xUA¥qÌ'¦Oþ)YžÏ®ÐÍ=_–––ܼš@I»¾m]îöè…™é‘QPÙ´³‚u'ª„õvyåG¥Í•UËcÌ nIZÔÜOáµ~Š~~¨ÿ¨Ê\¬EVQ­#[C&4—T üPQÖtøÆÐÞ­ì^{bXÈOHSÒÇ*ž“Iµ¥GKïFÞ_•Š^™ƒ=J/SÎb‚êúûýy™
+2Ý#Ÿ¨^Pûä ëlmÝ\Ø•C_|‘7d§·äøqý˜Ž ~Zx=¡[¯n=&î”Y¯¼²€T7±³7wüü7«“éæÛW(þë…4Má›v.Ûµk;ûÏgmáD¶6åPr+ñ{L¼êŽ)r '§/^Þx|Ÿ9¡-±aeJSâ¡ôR%¨î¶T¥i¬³ñÃy.Þ|MÒ@ˆ}°8*çˆaÇÞß3ü?ä£îIßbå™<~y·¼—mIþ('1iÃ4~‡»l]ÆÒ¸5k_n£Èaç¦sŸ üÑY?eê0¡¹¦q·|˜?´$eQÈñ±w•]+ýíŒÁO¨ n‹ÊÑ"o¥o»g,ˆ´Ëן\)€mµˆbgT¶‡“>¦s$—ð¤g"ºÄ÷>p½“û1Z:Ÿ7yV½¿q,î4¹–Å®|ž¼^‘öNbFÁÝÄíi×_–í¸,$ôíßâ¸FáTüüˆ‹Y¶[ï,”à3N¿™"‹u¶¤lR®ÛÚG¬ „ìÏpœ£ÐðKu³½OOr} ›f‚B ìÕ’F +ÿ
+ãh—zëÎÔ”ÿ‹Lút·%·¬Ùeµ¨§¾
+w~6ÖfžCa+6*×Å_ž§t5³©:þæÍ#’Ž•)5 rÙëžQ±|`+w±hª?ÏMw'ãòvÞo(¯ûäDÜ®}aK_-..*ݤK?øA< ;–šB`Ý:CÈ»s#—ï¬>cx»êÝ7~:/ÚŒ² 8?•B•Y¿.|”LöáYï‡+<]vˆµ75‘ðGŠç›¼ƒÉZrgè›TÖ5IJNqÇÁvŒ9ïã©zJs÷ã]
+LãxJü~nš=— &ìAج¹FÂýç´cµäðãvzWi ëŠÌìÖ–Ähóî÷°L’~ñ T=õ…ÚXÁ4{pa±ÈG£ÍñB׶kO·¬sur¬Ýv”áÅ¿a hÇ0Vw^Ñ‚ÿ¿¦¿¶âÓá씤 9‰É¦³Nν¿°êñcv¹µ5·àÚÚÆU¾o~‘?h§ºšŸ98tëÚžeLŽø/LG=ðïüߧQeý¦(Àirt¨5^6Ü7óÒ}ÂËæè
+Ô’Ï00ãÕHch”NƒYÆçB4Š‡A/ÍÃçS¡QÕ ²¡3r­>§f”ytRTK«@í¥_)dzcw hGŸˆ €+·å†hÁߥ8½%@ýlb/ÄÑç+ĉ˜£üî› ùB¬sÝ¥ü¶©¬`£½ˆ|çø>q.ž·Aº¨¾ÛNW•3ACsÁ‹&8íâD¹¹˜=¸ZQþeÅn·›Û챉ë¯èô(:ZÇuZ†ú "þ‚hÕíÇàz ‘¢
+1>-ˆÃâ(3áVÞ4I›Ì TÁlX!äA¨Ø«¤Qíq2®§\ìâÆwè Êþ5Ì‘‚À$[1†h_=4‰qè£&ˆ•g‚E>…¶ J@ǹ§Üa„Tμ‡ûå-Ú&Õ
+(áõøŠËUÙÙhr˜çr7Q X QÀï£gð=úÇ^¸é4q~
+—ÀÄÜ0ppû^Z ϧª½‘÷< ÏÊüÛ"T8"n ¾WlwCášœÈ"Hh£Ð ¾‚Œ1GÞ“s`DyzAYø^<{ZÎYäMç§Âäæ
+H‰\”ÝŠÛ0FïýºÜ½Xü#´ Áu6‹þдàØJjhl£8yû*:a 5$p°Gg¾q&y³ÛìÆaQù÷0u{¿¨ã0öÁ_¦kè¼:øÓ0fe¥ú¡[”¾»s;gy,Þß.‹?ïÆã”­V*ÿo^–pSOë~:øç,ÿz†ñ¤ž~5ûg•ï¯óüÇŸý¸¨BÕµêý1ô¥¿¶g¯òTö²ëãýa¹½ÄšOü¼Í^U‰Kšé¦Þ_æ¶ó¡O>[ñªÕj¯:ócÿß}Ñ”ŽÝï6¤Çu|¼(ª¢Nd! ½C¯P½A[¨ITÐ*¡ƒÆP¾BqŠæ”Š:M]%‰LÑ™¡³ÊAâLÙ}ú¬0 š> }j::ÓøŸÆ'ø4>Á§ß ­!13afš^„^b»w²%„Ïâ3ø,>ƒÏâ3ä³ä3Ø-vƒÝb7Ø-vƒÝ>ìh }@ïS²LI˜’eJÂ[±¼•8žD[ˆ :&(äsäò9ò ùù„|Ž|B>G>!Ÿ#ŸÏ‘OÈçÈ'äsäò9ò5 –üq¿ùûRÄÝUŸ×]CˆË–<mÙ}¿†ÑþÌÓ¬bÕý“ý`
+H‰j
+H‰\V T”×~÷ýo–ÄmF˜AÔÃ8Vq”a­ (j­5Š8"¨ "à‚ˆâ†TÃ*ˆ„¨5#x)µV\ÚºÅå ±ÖX·$.1GKmVþgï›AbÊœÇ?oûîò}÷þC€¢&9D"dÖSàÆØcp¥GÜÒ•›’^V</ÇïO éçX–¸8áŽê¶!š
+\ ^† š#êE8ÿ
+ç.KY—þùû“8o'ä=õÊÔ%‹‰Wb<!žÿÅyï”Åé«¥4rŒ#ÅóÞ«§$ö‰¹òç>„H"±E°“(SÔ(ÌxÂázÒ$‰&©)í¥ ŒJÑW’OÞùûhÖÌY$”ôé¤JƽÈ!õv:É›OÄ#Šja Å8‰”CÛ1Z!V­AëkÐr$"çPÂñ@»Ü?ÚÅIÉ`ÅŠ2ˆx*ƒdÀat3â0X Îa–Ì8TFÉÌŠõ¼+<ñö¨ìÈÛfïpõþDî¶l[Wd†­¬kgêüz2_ Åb$ðPÎW‰ëh†ò4­¾‡#ÑjÀŒÿ¨­Œ £wñ‹üÄSUC*Ïå*Þ oxàÚwÝ74oïÀw¼¥ ¬üâ.°R£üšï… ð^C&/Ã;þüŒ%÷羌ݷ~ý}®ƒ'¸W
+´‰fˆ=0X ´I¾CбEx·æÍN.‘^xÏ]iôñ³›õ>É4"4t„iÒüaaøÃüE¾ùAêR4‘>D'<Sáq?­Ælö–4o-©«(ëÆ¥õÛ 2ïÀ9¿Ã[!
+ógÍíMÛ*øB–½–
+õgBŸû“ÄØí7*½Ô¹+U:=zd0j1 7×ÓÌLo»Àc¡êlJ¶uås£^ñö3õŸNãugTGÌ€ÚSi«5ñÑÅ›Žú3íüXJ®òQÛåG\îúÍÌSì›X!fÞ£Q½]YG“:?£J©Õx`Ö¬¬pï?ùåæ?~Ó
+Á­Û«Oþ§j_eÉÃojÇÚ¾<!°èï—Æ6Eî«ãøóÚÝqÈ'F¢‘¨‰ÆŧãT¢×Þ¸ué¯âÛ¡ˆ¾h”ÿôíu £é=ÞÜÒ¦¨‘'RÿÎJ¾!ŠtQ„‚ NÊœC:*«é ù*UÊ4œ(jª¸±
+åíº xChMA‚ÃûÝ;’¿*œXfD±Ë4·;¸k_¹ÖYÁâfÕ¨TüüzV é=ÌÁV0+×:ú²nÜ#‚ëuz¦>pŽöS g®é\š=nXg›:"1òlWˆ¢¦kÀš±~)= ®œ°¡h¡·Sã‚[#" vUš·lÝRòú´
+gg6òÆ HíçrŠd,Ú´Õ×àùèì™ÝX¢òÝ„¾}’_V·R¤ ±„Ja‘-§f—; þoëRŽ”…Of•Åîn¯#ÐØ$ïUÔ¤$úäª\BҶʯªE®6aíT¡&†¾­?,‚·¨?,d«¨—Dtîzñ‘ªR³þ~Þ–k÷©>ÿ}ɦì¶3Ñkš²¦O þmãÌ(Xñ»¥ë½/ŽûÐp#fZH\ÂñÍ“Sͧ¢BÇÅ$„Ž^<?­£UÖc5cQY ¬7_âàñÒ}íà
+Z…§ú㩇.m
+GÈ­¿²ÇAÙš ù?©zo]±Ü¶'=2:yÕ¥C—Ï ÿë°ƒ¿rêGth]Û-o­ôÊÞ¾q¶ Ųñ&Ì't&„DÇì’O¡DVœã±è{)‚$)nbÇè'ô÷Ó/Iô÷¤€á!!ÃBÛíŠÔ€ ãLãÇw$0ŒúÍîÕ}Óóÿnjz~Yh†±<±ùìW}PUÇ?wwï{€ˆ€F4ƼAƒJ©eT‹–*ZúüBÊ ?FÑØ–P !V,c‰˜c¨UòBˆAƒŒI‹d:ÖIˆ5‘Xjk¬–Á:F[c©Â}ý}}MÚÿ:SßÌoξý8»çì7eêÌïœõSUnyKKÞ1ÚX.¯øY¬óÂpŸ!aÙùWksÞØwÒŠ"ã’5À¼Ô•d´Yá¾UÆ ¬ê©o3<Â_߈c.nf˜¯~ùHæï§|aÁÞrÌõLŒÏÏ­ðt¬œ–‚ÍVÏMKúô_ 7‰Ôý3§½ÿ³îF‘mŒNÿaEw£¢ê_OJ\Ô/ÚçÆ>·nÁOùÀø
+wCáº3oî'‘bLkÜÂ
+öþÓGdGS
+V÷õ½Ëè6kÈéÏRŠuébû¦ç+Ë:.FíÂù¯¾’¹ø`Uõ¼9B}iýñÅò‹FŸŠRë¼÷ÈŠ'–®ümã'O.çcE«¹út~9ÆÏøÿ.ÇÜÜñZ]w¥yòÀWr GB´Ž„0½öðÏ wÀíÄ°ò‡~T`ˆ¶OaClò¼Œì´‚Ó¿oE‹M-Ïÿüï†0ñ½T8?#gõÑ÷—Í{r±Ïç¢I…³Ïþ÷é Û¦÷ÒäY0á‘™Ó<)3"3–5t_WtbÍä !XŸímœ[¹ã-?ngÍdo•rÑ–µ¢¡â©g*Ï/*ÿøG¿úéâe%î%ÑQ?.Iœi„¯Ÿ“1¥~Iù¤Ù &}÷égß|ôõï¥%%ãY8»Åx;D±«+^”a:ÃŒOÐo7}·¢81ÛºV_?{¾!,kº{òè HcŒÈ*»1ø!«µ¬»yÅ‚Hþ¶@F<‡ø ëÉ»PÊ•y÷œG-o³¶z:ó_õ€ŸÆ;xù¿kÚ[!fcmXzk{½äQ+§Ú*zÇPCœf`„¦¨ Ÿ|݃ÓKM:Žáf=Vú^Rl ýµ†þ=Ò¬·Ží9ÑÇT2ü‚Ç:Zw¯ ú·Ê6HÒÊzÅ™Qã‡OìŽDÛ5.&NRWWTÂÈx©ìwÜŠ¼(nïsk#¹Õª5ÜÍ-¡C•Š9ÖddZ Í„VòÛPÞ}Ãr©Ž œf0®‹ «Ú5Öœip|†X.Ô¢|~a_uÂígl³¢×Ÿ,&>¦hŠÛZóž1  ¯Ãìg Wt3Ó:¼-|Ûaiu]8aPœŒà“¢îɵÐÈߌ.1ž¿ôäÚîÝ"½ë=‘Õ}ZFÈÖ®ƒeqrjÅ ÎÈÔγQwÉ´w­=²Ã/ÿZ'î,DþéØøJU2HãêôÃ[õ›ô% þüýƒJË3ùdµt7f¸‰­=+6v7£cŸÕbÕfé^¿Ÿ˜ŠåÏêWαÀt:€ËkP)»jG¥™5”o´Q­È¥2 BΧT³€Ú&)ã¨r­ty?Ç|~ÖÙ@ x€<{l)Åóy­Y`„²–²’Jœª3£)BUR“ºFYfd05Évj2‹ð5‰Hà4 Pô¡&g,ƺ¨É@YªÐ–;0vƒ
+ÔXŠ67ÐÕIá΢U®Ê)v´È
+÷Óäò}È$ò`¹*ƒjœ.ªf8b)UL¥M2ŠÌBjwœ£ >§c3¹õ]ú
+{§ÐlõÅaN“©(Tý€šåpœ}ÍvÑÇvز‹¢±_sO눣Bæ ô´š£(þÈ2Ì3à8Úã+Þ׹Ȅ=à0ÇlÈòÀ×\ õ©·hûïÞXbµ@÷r±‰2j-î`û5/Û(ëÓ÷÷||¶d€ψHopí!Úv|W=`nˆNìÑ@ÃE!MyeTÑ*1™Ü†‡âð}—dp'-#aWs–yÃüdŽ0?CUìÃÙµ à8óÌŽ›`ñ m—á»ËT _lp&;©˜ã’9­mb›×ÑRÌÕ¶€;½%óNóé’cÑLÖr¨Žö‡ë›%Ç-Ï¿§DL3G!‡Bºà×ãàm#|Û’ýlA¶ãÿø4r¯BlÀåœ8u.@<j '`Þ6[nf)2}ýb#öé²÷ë%Õ)ïÉž¶Î!ˆ‘Þ’ó
+Çv/ùrϽõ–œt€”3|’ÿë˜FÌý§’sç[°ùq‹'—a‡}:Sö™£{ÎÂùVÄÒÇ"Ö{
+s2/Ô Þ#Ž±Þ#â5Èo«9ßÛà¨ò¶ŠaÞý<yøü€!Ç©:Äû™oÓ!Ö-†á¿c4È9ò&þ DÐ."iŒŠ£Q*ÂÑŸš2ÈO¥ˆû¥?:_¤LY þí ç ó õKªä>µí‘d‚ë y\n¦Tž£vÓB=o,½!»¼–Ú‰v<õ‘å4‹ÇcÂT-í–oÓUŠµhë4Kq³)ØA´Ý‘Où°ñ’Þ‹ï’ût¬¿Ÿ5‚WÁ{øŽÏé<E¡Î³û¢™kê9Š3ß²óÂ6üG½â5f%î:_x;ÔÊ6-ô¼Æ\\«öÙyëu,s¾/T1tG5ʼ‚y3s_F};‰öëíHÆ\®‡ˆõ€ºíÒq»µ5ü³áOŽ¹NRr+¥©ôò:d…š;!wÚõ€¥]çd
+¹˜Wæ*´Q£Ô1Œm„Ÿ–#¶£½Ÿ\æ^HÒóÝŽH y“ãü%¼Âl=Ì3Ô‡›B+1¿ cØ[þœÅ~ò7ð“ vÙ|î-{ø­ó8ç®6ÇK·È“x— µc5ÞC¹Fœƒ/WS¥¨ÄšÁ'Çhž3ù/¹0q3œªUmÐÁ@»rœa À9N#g®f)öƒè[÷À®»àSœÐáþFšäÚhú*ÄÀ¯ÁTkzá<¬NðN“ ½ð;?ài†ßƨ˜?ªlül"ÇN೯‡zœ¨¬¸ú€§€ñ–Äs4ð
+y€<@ ¥y—Ty†<AºTùß²&a˜ßÌÎ×]·UÄŸ×ÀÏëà—ÀÔ£WdFµKxßô8¢Fô¸B×Ñgà*â_kÔ¨\®ƒï_à=q?Ö¹vú gÊ)>rw8´zNŸã|®xj6Æí·Â#c·Æ*§Í¦ÍñjÅVç W°•BìN²6'’yc]°bgU&ke—læœ.äï>É$N'³¦/<Égw¥1iÊ¡z ¡Œªà+ÐÚ¥!d@-üÖ¤XŒš¹Ï˜’¡ ÔÑž¶¨gÁ³àòT¾o™ÑöU+#^Î\à®ðžÀ
+ìÎÏ/3PŽ:¹¹…§}^9Íùžn×°––ˆl”¢ŸœµOBl”âœQów"=xzĦå„SYçÇÿý‹~
+H‰\”ÙŠÛ0†ïýºœ¹¼HGÊ@0d™@.ºÐ´àØJjhl£8yû*úÂj°áCË¿Àq¾Ùo÷C?«ü{ÛƒŸÕ©ºà¯ã-´^ý¹²²R]ßÎOJßöÒLYî×Ù_öÃiÌ–K•ÿˆ‹×9ÜÕ˪þ5Ë¿…·~8«—_›Ã«Ê·iúã/~˜U¡êZuþ/úÒL_›‹Wy:ö¶ïâz?ßßâ™;~Þ'¯ªÄ%fÚ±óשi}h†³Ï–E|jµÜŧÎüÐý·.±ã©ýÝ„´]ÇíEQu"•…4´ƒ6‰ÊÚB%ôq§æÎR 
+Ú@ï‰*ô z; ;+Ô ê•ƒ ´€z‡,´†zæ©GCMCMC†h7Ñ"‘HãZp­q-¸Ö¸\k\ ®5>Ÿz9h ­,
+‹‚AÁ¢`P°(z±ôbгèô,z†–,-Z²´dðbŸ^> 5Dƒ–…-
+ Z´4(4èhPHäH$$r$9 ‰‰„DŽDB"G"!‘#‘È‘hÁÚ
+Z?YÇ1yÎÃc`â\«Ïilo!ÄALß&ð1{ýà?ÿÓ8©xêñf
+H‰j
+H‰dV XTÇž3wî.‚
+»°¬HX®@­MU–e°Uëã«FD@>šP?EEŸŒ/4¾¨5
+–‹FIâƒúˆøâ3ZãcµECˆZe•š­¨A²ì=sªùºûÍ;3çüçœÿœ³!^d%‘ŸÜ?jñk¥ðMŽŒé³ó³^y?&Ä/jÆ´ÉSo}s÷ !º7ð]Ì |¡“´óq‚ë>3ræõoyç>®ó‘îÎÎÍœÜ$ß‹'ÄF<Í™œ7—Þ!Ç1ŽÁó¡s&çLË<0×Ùx~;‘X*M#2ar™lÆ{=3 &Y4Ë‹R-e”PŠXÞ—ŸqãÆ“¡$´j!Õ^kèðPT)ö‘wm¤sÝõðÿkJvu<†ÓrJ÷ÅmE2Ka–èsT !@Å'ƒŸ.’”?$1vImΤ$kìø$ë  ân0ÉgÛäí8‡xîjIñW‡Õ¬³¤'–ßlå&gÊŸ“I»õ~lm r&î÷CJeb³;kpK¬TÈŸoà«a™ {ðbñçб‡óV˜Š‘AOø+þfÛÞ¬|ÓŠ;ÅPOÒêŽÅd(¦
+ÔWW {'uØaqôù+–9âSRãã“'%[ã'ÄVíIè°³¾r ñ&„ÈaTçGÌ¡øð÷£
+Φ(íowB·ÐÈ É+à?‚ƹKá}·Â·òeô6„€Þ}Öý˜š„þ8Ž2„˜-c‰ŽP´ ªƒÉ0ö®]¾|ñéC5¯<¬ÜÃÏÓ§¡bõñ…3—íúgÁcÅü§rÞÀ.11Q^/NˆÕhŽÒ[”0‹FÆsA¼¦0Z4†
+úh'úÈ@H¸F U]e4 Kˆ!
+#n¬+?q›7üíµÊ!©°†ÃDø"îéÛü»vož¦zqËóTûýTÔ‚&’ Óå ‰ð‰¼òlŒÜÑ.—¹GòžËl.½Z[
+>¡
+žòžÉ‹ÙxšÍÕÂF<gåÉ(O¢|l¸{ŠÃA+þCsÜ"¤ÝôgVçy¨Rs‘˜uG"J¤sGªÇÙ³ƒè%·›»ôh.àîkBO´ÕŠÑE° Ð àA Ñc“Nnì&1C
+‹a”T²}ö€9Qí,¸Wé’o]År™ëÝ‚‘y‰ÒzDá±Fpĵü\x„EX5ÉÛ×[Û£Þ¤ùýţ™…ýÍnW:â|6:dÌŸ¤"Õ*x Føˆì“=<PŸF z‘:~”ºø5¾–Áï ,â¼þbKË™KŽ¦ (A.¤A%ÏåµüS>µñ†?á·@ÿPèÕÉ &xá-ЂÀ…†“—†*œh/þÕ;¶ìÙù!en—\ö°þ*Amn×ÚUù«R^¡"íIz#g1·úü,} 6šJËOó&„¼Þƒ1‹Zù[[žž¾ä¸ïÍ·ÀïµP
+±èð*žÃOòfþÛŒ°Ÿñ»»‚»PW"j=Vn¤q„¢¨È;3Ñè]è¥5ûG/Ÿã€oî½Øµ#}T£›Õ.,]»*öºk岿)½þ ZÊû±¿ó¸õÙ™s1zÙvé<Z†ÕIˆõåDF`mêcö¤ ¨JFOº‡E佚Ñ4ß'ƒïÍc+W™µ"eÏ©=¼µ5íJ°!‰5c—¼=±nCÍ«3kj⸙i™-8ÞhF=ØqØ(5#=~ǪO«Ÿ`"™­ÝÌl6•±¢n;3C”,CÍRÿSÐÀtƒVî泜ȺaC¬,^ÍÌríA¼¬ÞSë¼r¿kÖDr;ê§eÝ|ùsþ/>øôÔh˜Lô¸Áü€:%{Ü'ź‚PI‹%+6“õh·Ç'N`‚4B[ãÉôpLt [ Wòj¯’Ý‘ìM›m
+›eK‘Þ­dAXÙ°zš,ŠZöýÂã՞ƒÝJš®ºo¡'Ù¬sí‡ñÐïìñò؆?@6=yÒ[Ó×ïÙ]¿ìÛ÷Úü+Ê >×½ê{ŒM:acvºÐS´@~Œ~xQ)QRÌسôس”0©SÚd`³ÛY~ã×ß»NælÌ~¿t}^Þ¶¼íž{Š?²wðËtÔºœ­çŽmÙ§vä$´ažjƒ¨ÎaÄ‚]ö%5°:Kó¸ÏBçæ¬Üe›¶åÝ%ýF€éH00º1©n×ÇÇRJ”Ä,](=Þ j4Šâ%½Ú¥6çÞ™G@êÏObö%³VmÞ˜—»£ò8è`ÞNg9hêì²3vî?´Ñ#[jC”:Q;@oŠ²T°B¼Þ`ˆD#'~«eoá¦ïuxãb}sSCz¡?œä÷¦|•
+Æ6Drçýûëç Ë­ºQÃÄ¿ @lƒÙ 2O±˜Õÿ%FÚ8(¦òÁƒæÏ?¿úIr´Ü?è̆ZW­4ªv[Õ%½ÀÄC˜1õ&‘è;Ñç#-žH{L÷Ó Ó-æŸYÎ,üTWZ]U}˜-¸U÷ßü*]°9{uIñ¢Ee`¨Öqü‹Ìp¼ zû
+ž’S~æh顃Åw2´/úYÿ_Þ«>(ªëŠŸ{ß}o¤¸ Htx€: ˆfY?bÀ-Ä©Q]» ¬kaýÀªã0Äâ˜:¶A³ÍPG u0µtM6Ö–qŒu¬“8 elµN§P©c‰%Ôt/=÷í[‚ÔÎ$DÎü¸çí»çÜsî9÷žóĽoª£B —³´ä››0ê{ÚÏR+ù®×ðað=ö] 4k÷p*i“‡ðŠs\†×d‰Yh³-\d³ígw ²®´d|™À°gCÙÑrž¨ËÆ?-;Ed¢îT昖ù7..]‘g^ë¯-g˜?œvå…cG¤á?ùèO„¨0)A_D?#%ðZ‘ÌX fò<ÒGyŒ<øŸlÒÃã÷tIÒ(†*§·_|úå(Æ&Q«³ôMÛ¬Xm³â´*w¾Z·nwÿ•ò\ËÝ[ñŽºõï¤æj>µ-ÐMK‰âÝèfà=·¹ü
+ßh
+Ùœªåãøµ¨Q²^«lFe[n’Rº„L§!àgpâ·¼L€8)n”žSEg<s¢’‚y¢¢ÉtÍ?x?I<"‘üöý¦cÇ_#ñ?'Óþ‰ÍËL~÷ñ¿ùŸ¤­´Ÿè"åï‹;‚¿Àö£NýŽó2:Öôì;bÇÍÿÊoø¿º#°éC#ïŒÿ#µØrD\¿ zKY´–/³žÚÃ8:h)pìAuyç«RbÊé×\¾)v© O- MªÞ‡ŠÏK‹ž—²×ZN®Ø{dÃεµû–ÍÛ÷“ú?_x3ñÖ†ÚÌìy¯4;žI½¾üåô¹‹æ-|³¢åWBÆh?õãZL°³ŒÒή9Jœcíê¢þÜjÞÓÑ1ðŹß)=<…Xi‚p9¿æç&û*ñ™01 ´HŠƒ‹Z2£LÁ4Ž’RÙ¦«üðýÞªý÷ZMNcëö>|d-Ç!Xј¥EEK!™S´J4%“îáüÖ4›<õ.îGÀVZT–KÏj2xnŠ2¢š¥HÁ®}œlhd½ÃçÃŒ,lÒ•!ÞóȦ(JDÏ­nŨÂ;oÓv5/gV u§ÍxååÙô“@jÜJk2í+Œré!® îJ"—Ÿ„$Yø3RÂ??k˜ÁÂ"¾æÃo§õÜG";ã#YxÒ9Ni
+Œ±Gê„Ü“6\£µ¡Ÿ Ð* ¤A!u@Ô
+;1‡µü»"OE®Ú¡ÞÐ
+ò§tÞ
+À µ4À”Wa)>Õ!/þÛ5½bÆMªIÅßÅšUø®^{râèÄq›¶¾˜YŒ\%Ê9“’ñɥͫy4|[ƒclÆßÜh‰
+%¨ÏùìY k¹˜Ÿ%úÕŠèg±¦ßñ¹W³iï¶"/ÖüúrßÆÌç°3ÿ`
+0000000016 00000 n
+0000000112 00000 n
+0000045968 00000 n
+0000000000 00000 f
+0000046019 00000 n
+0000046517 00000 n
+0000054429 00000 n
+0000056144 00000 n
+0000056814 00000 n
+0000089522 00000 n
+0000089637 00000 n
+0000069062 00000 n
+0000069198 00000 n
+0000069325 00000 n
+0000057522 00000 n
+0000057173 00000 n
+0000054485 00000 n
+0000054847 00000 n
+0000055208 00000 n
+0000055569 00000 n
+0000056926 00000 n
+0000057100 00000 n
+0000056002 00000 n
+0000057027 00000 n
+0000056954 00000 n
+0000055929 00000 n
+0000056217 00000 n
+0000056424 00000 n
+0000056679 00000 n
+0000056312 00000 n
+0000056732 00000 n
+0000057315 00000 n
+0000057410 00000 n
+0000083527 00000 n
+0000083552 00000 n
+0000077005 00000 n
+0000077030 00000 n
+0000069457 00000 n
+0000069482 00000 n
+0000070082 00000 n
+0000070556 00000 n
+0000070625 00000 n
+0000070888 00000 n
+0000070967 00000 n
+0000077563 00000 n
+0000077976 00000 n
+0000078045 00000 n
+0000078303 00000 n
+0000078382 00000 n
+0000084090 00000 n
+0000084519 00000 n
+0000084588 00000 n
+0000084863 00000 n
+0000084942 00000 n
+0000089748 00000 n
+trailer <</Size 56/Root 1 0 R/Info 55 0 R/ID[<9ACF01BAB32244F184A6B6A3D6DB10C2><BD2963D24D474598BA7FB4CC0AD67B3F>]>> startxref 89924 %%EOF 2 0 obj <</Length 47827/Subtype/XML/Type/Metadata>>stream
+<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
+<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:56:37 ">
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description rdf:about=""
+ xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"
+ xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#"
+ xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#"
+ xmlns:stMfs="http://ns.adobe.com/xap/1.0/sType/ManifestItem#">
+ <xmpMM:InstanceID>uuid:7e7b597d-426f-3642-8dca-bcbf37236e1d</xmpMM:InstanceID>
+ <xmpMM:DocumentID>xmp.did:89321C534E266811A613EDAC20FB34D2</xmpMM:DocumentID>
+ <xmpMM:OriginalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</xmpMM:OriginalDocumentID>
+ <xmpMM:RenditionClass>proof:pdf</xmpMM:RenditionClass>
+ <xmpMM:DerivedFrom rdf:parseType="Resource">
+ <stRef:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stRef:instanceID>
+ <stRef:documentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:documentID>
+ <stRef:originalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:originalDocumentID>
+ <stRef:renditionClass>default</stRef:renditionClass>
+ </xmpMM:DerivedFrom>
+ <xmpMM:History>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E4B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E5B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/metadata</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E6B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:44:22-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:80321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:46:03-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:81321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:48-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:82321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:49:01-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:83321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:52:39-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:84321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:58:06-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:85321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:59:50-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/metadata</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:89321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4A27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:48:01-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4B27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:50:54-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4C27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:54-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4D27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:55:16-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4E27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:56:27-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4F27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:58:44-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5027385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:05:30-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5127385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:07:25-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5227385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:12:43-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5327385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:13:56-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5427385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:16:22-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:DE855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:19:25-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:DF855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:27:07-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E0855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:29:58-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E1855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:32:34-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E2855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:33:46-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E3855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:40:42-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E4855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:41:28-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E5855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:42:42-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E6855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:44:36-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E7855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:47:08-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E8855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:51:29-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:80C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:49:23-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:81C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:50:43-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:82C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:52:12-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:00CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:53:23-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:01CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:53:56-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:02CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:56:41-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:03CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:03:21-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:04CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:06:47-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:05CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:09:26-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:06CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:11:53-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:07CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:13:29-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:999093B2AD2068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T14:21:34-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:9A9093B2AD2068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T14:27:38-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:9B9093B2AD2068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T14:30:31-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:371C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:20:55-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:381C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:26:33-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:391C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:29:07-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:3A1C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:31:19-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:7A0142B9242368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:41:33-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:7B0142B9242368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:44:10-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ </rdf:Seq>
+ </xmpMM:History>
+ <xmpMM:Manifest>
+ <rdf:Bag>
+ <rdf:li rdf:parseType="Resource">
+ <stMfs:linkForm>ReferenceStream</stMfs:linkForm>
+ <xmpMM:placedXResolution>72.00</xmpMM:placedXResolution>
+ <xmpMM:placedYResolution>72.00</xmpMM:placedYResolution>
+ <xmpMM:placedResolutionUnit>Inches</xmpMM:placedResolutionUnit>
+ <stMfs:reference rdf:parseType="Resource">
+ <stRef:instanceID>uuid:288c3c69-7dd6-7c4f-984d-b085b3307748</stRef:instanceID>
+ <stRef:documentID>uuid:93F9F49755C5DE1185BCB9A8461E73D9</stRef:documentID>
+ </stMfs:reference>
+ </rdf:li>
+ </rdf:Bag>
+ </xmpMM:Manifest>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:xmp="http://ns.adobe.com/xap/1.0/"
+ xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/">
+ <xmp:CreateDate>2010-07-02T15:32:26-07:00</xmp:CreateDate>
+ <xmp:ModifyDate>2010-07-02T15:32:59-07:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2010-07-02T15:32:59-07:00</xmp:MetadataDate>
+ <xmp:CreatorTool>Adobe InDesign CS4 (6.0.5)</xmp:CreatorTool>
+ <xmp:Thumbnails>
+ <rdf:Alt>
+ <rdf:li rdf:parseType="Resource">
+ <xmpGImg:format>JPEG</xmpGImg:format>
+ <xmpGImg:width>256</xmpGImg:width>
+ <xmpGImg:height>256</xmpGImg:height>
+ <xmpGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA&#xA;AQBIAAAAAQAB/+4AE0Fkb2JlAGQAAAAAAQUAAjSA/9sAhAAKBwcHBwcKBwcKDgkJCQ4RDAsLDBEU&#xA;EBAQEBAUEQ8RERERDxERFxoaGhcRHyEhISEfKy0tLSsyMjIyMjIyMjIyAQsJCQ4MDh8XFx8rIx0j&#xA;KzIrKysrMjIyMjIyMjIyMjIyMjIyMjI+Pj4+PjJAQEBAQEBAQEBAQEBAQEBAQEBAQED/wAARCAC1&#xA;AQADAREAAhEBAxEB/8QBogAAAAcBAQEBAQAAAAAAAAAABAUDAgYBAAcICQoLAQACAgMBAQEBAQAA&#xA;AAAAAAABAAIDBAUGBwgJCgsQAAIBAwMCBAIGBwMEAgYCcwECAxEEAAUhEjFBUQYTYSJxgRQykaEH&#xA;FbFCI8FS0eEzFmLwJHKC8SVDNFOSorJjc8I1RCeTo7M2F1RkdMPS4ggmgwkKGBmElEVGpLRW01Uo&#xA;GvLj88TU5PRldYWVpbXF1eX1ZnaGlqa2xtbm9jdHV2d3h5ent8fX5/c4SFhoeIiYqLjI2Oj4KTlJ&#xA;WWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+hEAAgIBAgMFBQQFBgQIAwNtAQACEQMEIRIxQQVRE2Ei&#xA;BnGBkTKhsfAUwdHhI0IVUmJy8TMkNEOCFpJTJaJjssIHc9I14kSDF1STCAkKGBkmNkUaJ2R0VTfy&#xA;o7PDKCnT4/OElKS0xNTk9GV1hZWltcXV5fVGVmZ2hpamtsbW5vZHV2d3h5ent8fX5/c4SFhoeIiY&#xA;qLjI2Oj4OUlZaXmJmam5ydnp+So6SlpqeoqaqrrK2ur6/9oADAMBAAIRAxEAPwCReWvLfleTyzo9&#xA;zd6VYPJNY2zySy28JZ3aJGZmZkqSTlgApgSbTL/Dfk3/AKtOmf8ASNB/zRhoIsrk8reUZKlNH01q&#xA;deNrAf1JjQWymEXlLyYIk9TRdLDU35WsFfxjys82Y5L18peSmPFdE0tiewtLcn/k3gSubyd5OUcm&#xA;0LTFA7m0gA/5N4qt/wAKeSf+rLpX/SLb/wDVPFXf4U8k/wDVl0r/AKRbf/qnirX+FPJP/Vl0r/pF&#xA;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&#xA;xV2KuxV2KpL5z/5Q/Xv+2bef8mJMVf/Z</xmpGImg:image>
+ </rdf:li>
+ </rdf:Alt>
+ </xmp:Thumbnails>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:idPriv="http://ns.adobe.com/xmp/InDesign/private">
+ <idPriv:DocChangeCount>244</idPriv:DocChangeCount>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <dc:format>application/pdf</dc:format>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
+ <pdf:Producer>Adobe PDF Library 9.0</pdf:Producer>
+ <pdf:Trapped>False</pdf:Trapped>
+ </rdf:Description>
+ </rdf:RDF>
+</x:xmpmeta>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<?xpacket end="w"?> endstream endobj 3 0 obj <</Count 2/Kids[59 0 R 5 0 R]/Type/Pages>> endobj 40 0 obj <</BaseFont/QTGHHB+Segoe-Bold/CIDSystemInfo 41 0 R/CIDToGIDMap/Identity/DW 1000/FontDescriptor 42 0 R/Subtype/CIDFontType2/Type/Font/W[3[276]6[592]11[369 369]14[707 271 404 271 443 575 575 575 575 575 575 575 575 575 575 271]31[707]33[707]36[703 641 624 737 532 520 711 766 317 445 649 511 957 790 758 614 758 636 536 586 723 667 1005 655 607]62[369]64[369]66[415 314 538 620 480 619 541 383 619 602 284 284 559 284 916 605 611 620]85[398 440 389 605 542 797 552 538]95[326]138[874]192[667]]>> endobj 42 0 obj <</Ascent 1065/CIDSet 43 0 R/CapHeight 700/Descent -282/Flags 4/FontBBox[-99 -282 1258 1065]/FontFamily(Segoe)/FontFile2 60 0 R/FontName/QTGHHB+Segoe-Bold/FontStretch/Normal/FontWeight 700/ItalicAngle 0/StemV 156/Type/FontDescriptor/XHeight 500>> endobj 45 0 obj <</BaseFont/SJATJX+Segoe/CIDSystemInfo 46 0 R/CIDToGIDMap/Identity/DW 1000/FontDescriptor 47 0 R/Subtype/CIDFontType2/Type/Font/W[3[274]6[591]11[302 302]15[217 400 217 390 539]24[539]31[684]33[684]36[645 573 619 701 506 488 686]44[266]47[471 898 748]51[560 754 575 497 524 687 621 934 590 553]68[505 584 458 585 515 313 585 566 242 242 497 242 861 566 578 584 585 348 390 339 566 479 723 459 484 452]138[890]192[555]]>> endobj 47 0 obj <</Ascent 1040/CIDSet 48 0 R/CapHeight 700/Descent -282/Flags 4/FontBBox[-152 -282 1171 1040]/FontFamily(Segoe)/FontFile2 61 0 R/FontName/SJATJX+Segoe/FontStretch/Normal/FontWeight 400/ItalicAngle 0/StemV 80/Type/FontDescriptor/XHeight 500>> endobj 50 0 obj <</BaseFont/UZUFLT+Segoe-Semibold/CIDSystemInfo 51 0 R/CIDToGIDMap/Identity/DW 1000/FontDescriptor 52 0 R/Subtype/CIDFontType2/Type/Font/W[3[275 298]6[588]15[234 402 234]19[558]21[558]28[558]31[702]33[702]36[668 604 621 721 517 505 700 738 294]47[489 935 774 753 583 753 601 510 549 710 641 969]61[582]68[505 603 470 603 527 347 603 584 266 266 533 266 889 585 594 603]85[370 407 368 585 507 760 500 511 458]139[888]190[613]]>> endobj 52 0 obj <</Ascent 924/CIDSet 53 0 R/CapHeight 700/Descent -236/Flags 4/FontBBox[-130 -236 1190 924]/FontFamily(Segoe Semibold)/FontFile2 62 0 R/FontName/UZUFLT+Segoe-Semibold/FontStretch/Normal/FontWeight 600/ItalicAngle 0/StemV 112/Type/FontDescriptor/XHeight 500>> endobj 55 0 obj <</CreationDate(D:20100702153226-07'00')/Creator(Adobe InDesign CS4 \(6.0.5\))/ModDate(D:20100702153259-07'00')/Producer(Adobe PDF Library 9.0)/Trapped/False>> endobj 56 0 obj <</BaseFont/LZSDPL+Segoe-Bold/DescendantFonts 197 0 R/Encoding/Identity-H/Subtype/Type0/ToUnicode 198 0 R/Type/Font>> endobj 57 0 obj <</BaseFont/JJYRNP+Segoe-Semibold/DescendantFonts 195 0 R/Encoding/Identity-H/Subtype/Type0/ToUnicode 196 0 R/Type/Font>> endobj 58 0 obj <</BaseFont/HTEFLT+Segoe/DescendantFonts 193 0 R/Encoding/Identity-H/Subtype/Type0/ToUnicode 194 0 R/Type/Font>> endobj 59 0 obj <</ArtBox[0.0 0.0 841.89 595.276]/BleedBox[0.0 0.0 841.89 595.276]/Contents 63 0 R/CropBox[0.0 0.0 841.89 595.276]/Group 64 0 R/MediaBox[0.0 0.0 841.89 595.276]/Parent 3 0 R/Resources<</ColorSpace<</CS0 85 0 R/CS1 100 0 R>>/ExtGState<</GS0 91 0 R/GS1 199 0 R/GS10 200 0 R/GS11 201 0 R/GS12 202 0 R/GS13 203 0 R/GS14 204 0 R/GS15 205 0 R/GS16 206 0 R/GS2 207 0 R/GS3 208 0 R/GS4 209 0 R/GS5 210 0 R/GS6 211 0 R/GS7 212 0 R/GS8 213 0 R/GS9 214 0 R>>/Font<</C2_0 56 0 R/C2_1 57 0 R/C2_2 58 0 R>>/ProcSet[/PDF/Text]/Properties<</MC0<</Metadata 192 0 R>>>>/Shading<</Sh0 139 0 R/Sh1 140 0 R/Sh10 141 0 R/Sh11 142 0 R/Sh12 143 0 R/Sh13 144 0 R/Sh14 145 0 R/Sh2 146 0 R/Sh3 147 0 R/Sh4 148 0 R/Sh5 149 0 R/Sh6 150 0 R/Sh7 151 0 R/Sh8 152 0 R/Sh9 153 0 R>>/XObject<</Fm0 65 0 R/Fm1 66 0 R/Fm10 67 0 R/Fm11 68 0 R/Fm12 69 0 R/Fm13 70 0 R/Fm14 71 0 R/Fm15 72 0 R/Fm16 73 0 R/Fm17 74 0 R/Fm2 75 0 R/Fm3 76 0 R/Fm4 77 0 R/Fm5 78 0 R/Fm6 79 0 R/Fm7 80 0 R/Fm8 81 0 R/Fm9 82 0 R>>>>/TrimBox[0.0 0.0 841.89 595.276]/Type/Page>> endobj 60 0 obj <</Filter/FlateDecode/Length 6532/Length1 11712>>stream
+H‰dV PTçþÏ}ìâ³ì‚à#*˲lª–ek}‰ ¥ê "
+øFÅê
+T!_AÒ¨ˆ–¨1Ô2¨”±JЊo4„cðE•Ä±ôEQqï¡ç¿»;™;wç¿{Ïã;ç|çœË€1æÅò˜ÈØô™¡áÙÛŠ³3¶Ð¿)éËsÒ|zV}IçíŒù}—±x¡ãnpËÆ‚ÆÓ‘ô‡®¡ÏçôL:,(cEVvyi]÷2ÖÇkùªÔ…lÌ’ÓŒù;è¹ÿŠ…Ù™âVÎØè2’X¹pÅâ=•÷Úè˜É˜¸œ „ƒ‰yB¡Ñ2fÓt&ƒÎ'2%O`ȘСèó ƒÌÄÖJ{å"6Œd ´F­Ek>êm³Øèö±ˆü毤½æ3¶ÆÑW§]‹}wíS­õz`C\CÜ#û¸}ok—FW?¯Æ£Èo:‚Kù]ýœŒ³ƒX#´É%¬=˜Î[ýÚñ,¼ ›° è„|\#péèIgŽGÇ»WK˜ƒ5= Âñk`²`R\¸
+à1<€O0—´:˜Cª•,¬÷¤3ê VƒÎ¢3Hµ˜{°å:äÃ#Ì…ü°›¹G€ÌÅëg¢ØáDqWš 5ÐMïvAµP%ñw@–„*¥U0Bu+×Kêi‡FcýIÏWc 4[#"-á~иdÖô˲øøŒ±óÃC§ÄΛOò==zñÅÃmÄ#Ê|,œ–K^dk> zLíi—ä*BîÃ#ÖjŒ:o[¤!
+Vœ«‚c0£©¨èÏ7n}råì‹ýëó0á˜ëÖçÝÿë³$žŠD.U3¢w³†â
+ÑÂXlÛWj†Ð(ˆgyPØIË›["§ŠÂi£±$Û1 "s/rÿ7`;}ôgÂ*ßqJ4Jf‘û–{c»]Ç(Âör¹¹Vãžå¦ÞM úóÄåÁÏ_õ©Õ`]¯!¾xŸã±#û ÀVh“Ñ[3t$˜ ‰‰ïWŒu…‰—ÍŸÕÿÑEÙpU¦§eÍã=ÑT’ŸÞh~´l¥ÜVbr2ÜOò¢u“$Œ"yÑ·ƒX`™¾Ïõ”Lí ‰‹(‡p¶r\% `ÃÝl ðlˆ
+"›(KEœ(‚$„XêQA „Ã1ÔPk9Øq_jÝ©‰h —C qÁPŽÇzRÎüô¿ïÍ $ÎÇ;̼{ÿåþÿ÷—‘蛺k]ð û÷ŠóÑ}Éû"C‰§+°~fÞ«Œ%x›héTÛ
+çyŽ·HøuÍGÑÜ÷›ÅÑvîa,EuÙëܨû|ð9Ðáç⤶À¨\¡Üf¸½£‡ 8²Y\ì—Zäï‡õVÿùæFß¹Á>ûáqìÞ{àtRîü9;.jÖ‘ª¶Í{bÈâƒóÜýCüf/û”˜_ê÷…;1KBæÎZ”´*‡U,êqZ%²Õ(_ CdÂ9Ȧ[iÕ«\ZE’Æ’©M}‡Aã‹ÒC¦64Ná™+É8ì…\C_ èÿGHŒ‰+Ù„ˆ’@TÆ&E {’Df9P¹Âž Þ€Õ9960$Jøžy‡ ª2j#+ÒTÁ=&IzNP Á.¨´‘QsÕKØ å$­ËJ.§„’Ä­,(U]c› u!I)KõYh$äÝœèá¤~‘WfÜJá<ÚB•"óE[vÒéMÚ@¢ð…ÿµRR3‡!¬”NH&»o8ØPKçHh8rÛ>Ìy,àoð7@ã23Ž3ø±(ð‡>0æŽ`âF÷¤`œ?¢}"ŸB­l~DÇ2€'CB“¡ß*k…;/*lÞNZ_Ÿ‘–ß
+³Èn¼ËÈ¿ënco…â[Ž¦·Ô^*¼C8‚ÇíÛ¤ÎtÊ¢:™'Ð#hF¢Lw A£o4ÐSÀÖûÒ&>^öHüÎ…8óñ}p8Ð&¤^¬~¿‘'‚Ž:àœt•»‹¤C”®®L;ªQÇ{MWÉL*H-èàÍìª{OCÒÈħŽæ¦“Ðs¦>|IÂf®ªeuüâ1ÏõhîàtGˆ(±·-P‡~ÌlíÂ^h• K°Û¢’GK.vaKzËMl£àjî¾Já
+  [îvoLs^ 3SŠµ‰¹ÛxǺöÈ Eíµe}EËWV¾Ÿ¶ó(‹7 #ªÀˆìÅÉ/3fø±ö*r¾¬ú¤©1ëŠÊ¢5¿ß¹MëXUÙK,j̇—áQ1å áè5îGóÐk›1b¬„N㵨½Mý+²D\¡»;¶”–îøæZ%еumN~ÐÂÔäE\EsánBW_Sɧéå+×—­¨\±4<ÊhÉ=·ûÂy¢³§¯Ýh¢XE® Ž† %1?º£²ïÕî²æO¾êÿp3Ük‹öóGš{c~ˆÜ·û%±®+=PzwÑýàÀDÌÊœqÎrʺ€ »vv^vŒæðe”»‚sOݳgpµ¥eã–Îä¥tØþóÜ~}¿0©¿äXŽÖ–ùNT‹þ9r³1Ê7ÙLÌ
+oôÓKÍ’âö:+>T[Õ '¾ÙÞøÙWÇÒ·¯<ÞYòõ¹$–œ/Õþ)Ù…>~Ò·çÃ>mõ'IkâöŶۧĬ¾za 6yÙŠ#‡ŠÃ£j1’]ØuIâyˆ³X<TãØÇR¥IpõÈ*ïRÝ|I’8>ôá²ÀdÔ!†ÿ
+ø?—‡9¸'{‚Ì5~¬
+Ø´½—¡‰]Ÿ³a2ÛCº|mJHXšá­kxäp2®uøÙZ[Qµ¨1\õ˜]VåõÇ-ñ>ôæ^e×Kÿ4mÈõï¹,¢rŒÈRœûF ƒ„JË‘þNK-€c¹
+¦SÅÂY/SŠÇªôò¤ U5¨Gà~cÍ1«*ƒ r— öñÖúêZâôö﩯ì'Ná+÷ƒŽ± xÐVÑ+ÇQ–1¹å)mýšc ·Î˜8æÛ[¹ipîVꇛ׌2Œ¡MÖSß^[þ=±>X¤É);*E-8S±vf¼3ë!¿È¬-âv—8ò}Nµ¿…I”»pÓ’H22Szæ"ÅkÔ¸H(¤*šdÇzÓ¨„°ÜÂûMåõ{k¶û?½VRRPZì┼gqñ«NÌð&ÜÚµÞsç-ZQXÕîñ2ô½¹Síµ (my ž~.óµ$ÞTb§»ªX×ÛbÇòϗæfâÿøq‰§ÚÒ•¬!wú$Bg?¤f‰ãòñ|4Xó*ë‰âÀ–MÔ¸*ÛzˆK\ñç¾ ÇùC›n[&ÏìãBLêÀ4ã¡êàÑ´M“QÅ´xéÁw »³W.Ïæ‹™]Ôòò\ùvm0Áô”Ç€:j­¹Âª NA/YZa.—ˬþBæ4*
+j¹‹íͯ^ée8‚62f†{òu†Œ) øfËL¬`Ž±¢9ÿq€EÜJb ºÚn"?ùúgɦƒŽ–T9åå@ixNlÝÕ³æA?ž‡‡~nó¼Ë߈Ù’eÀ–ÅÁ;KÔàëûf*RkàÖ¦è ð¢ù>J’/N0§“.QîU+h'ë]·”`8Ák™·ÝÈ=7äNÒ$G†¸¡G,®t䉼U¦%7™›Åy?Çî¼ØM{(ä*変ø¡ÂE¼²ºH×(pí¼<åÅg¡âÈIA‚{ì‚ZxÏ:ŽŸî –DN´Ï!Ò=4ü6YLÞ×%¨ë'æíEMtV‘FŠþ¤õÝÐATdýÉvø þÝ~œ¬oZB= Ÿ÷¥¶mÞclÎÀiÄØõ—ìúÖ E2âb6dFÇn˜W‰?,ywaåÓ§p¹¥%G{}Íâ1L=4õó¼GúG”GÒðý™ùPótI"OËi‚‰kva=ƒÃ
+›Þ'þQmäõÍOùNG
+Â9ÚIlæã˜ÿù|ÇGÚü
+r¤`0*ƾj´Š
+×û°ÕùVÚ?C\-GºƒD¡Õ*û(n«É˜dÍB'å*«Ã¿@û*âÑLì!&ÝD’¨#j‰±—¾öÑ’qDZ;wa—}»˜}ú±À¥è¶aÃzµÝV'Ší鬇n÷(ºZ¢
+Pfô‹È©*¤U•¿U·=çÆ‘ÓWˆwØÎ~bgMeÿÖXãQʶz´S‡ýºƿo]ÆÓœ÷µ)ãœÿŒÙ7!û–=ìIÖoÖô˜5Æÿ\Ó|®¯—ø!Ñ3¸¶¡u=볘cEÐÊóé!:­h·êpPb•í çô£Ý`2ªfÌ°Žc¿xo»[ý~Y§³=Ï ©pŒRÝ˹»PfOD…çîæþöãˆÅxµŽ ÊñPëä^Þ!v *Ü3c”c¥ð„ãˆ_žÑGP!pb‡ptÀW2¯›#’Ü9,QAîÖT-êˆ 2ž~ƒíô»œ½ºàW?ÕP! 7J²ÃËZ¬dÿ•‘‘作Ïb@
+È¿µÛ—8GüÕì=€áZ
+ï ŸÞGJ,Ú{„=Šõâøã¥Ä­ÄÄûI‰i‰+JèÛ(¢O¯“·ß£Ÿ£”ý,ß¡¼Äò!{Œçiöé@Zò€Ä¢ÉŒGƾØr»‘·òõÖfÎø’˜*í­þ™Á:É%Œ‘¡RòŠÄöYœÛš’Ì?&ˆ<H–ML3æþU)¹ËäüäI’k ÎÑÄ#c*Xó¤µïè»ï[•þ û—ˆ°¼ÚžãŸw?柷vùœùW9þ ç–^uѧ‡c%ùkÿ”üó¼†R9/g ¨ÖÓïvžp{X·”í͘-mN”úˆ—ð ý:¢ú:Ÿ—;ñœýæÁWè_ƽÄìÇ~
+ÏZobž~—<íÂ>ýGl“:ýÏŒqÆúji·¾‹˜ØHÙØu²= [ߤlñg]Âç¤Íä˜>ì°nb>ÛªiS"c:Šz‹ßË<Ôæ¼*sùoK½É…ÒÎ:“wGp½r< ÿè;Ygøó^öï“éfo㜠ù¼ >2÷û8åô7ÇpÿìßÓ_&o–æýbütãÌ]ååóº3ž}nåï9á…ó-æPÞQηhaŽþ:íG#êN£í}³®åáv¶G1ÒÄí¯Q£3×TÓwQ(1ç¼0cv±m“v—Pà|Š²7¸D÷œu˜ó“WN¹ü%¾bÄî<ýD—º=EÎ×òão Ý1Ô_ÂDçA‘ÌmÆžñÎqÎõ[Ú0žÍÜÂY™~²¶ 7Àç¡r€ß&Kîbþæ»CÞ#t7%ëóÍ|@î¨H}Ó‡Võ2Fè¢oøN19ð„É…;Ýz¬Ð—ñMÅ|( ~œrƒFˆo„ÐMæÈÌŸ+(×ÈËHÅøæsñi>½1_àBÎÊã¡¿ 0
+H‰tV{XTÇŸ3wöá{ØE#Ëò¨µBda×(h‰µºÁ ‚D|"
+>   ‚Zå!"ˆ+¢U¢[>‚”
+¨_+>ªUC‰6ñm4úÅ›SîØswÁ˜?úí7{ïÌœ9çwÎù3—
+ Ã¡wÖãЙtöa 8zÁÀòµ¼'܆󎨬È.ËF ïråDþ­\,Y–žÈ KQÏΔËyû
+ùÒX£—þJ¸ŽfÈ.ÞD#Ñj?œè‰Zü£–"~ ÆóÞñTA•Ìs¸‚À®¸ö ÷„ªï <à­E`â-Å`¢zñ5¯€õð^C&/Â3¾ü“GRN¼Ñ>´nÝ#®oq¯ºhÍö@¤£u⪇®Íº5ož™\&ðœ‹\ïéh4hÁ<Åß/$ÄÏÊ\¿ÐP|„xóè“0qIz@ÂÑl¥52ëë4ù)¾‘o¾zdudÑHȨÎ×G­2 ‚Jç¡Æ!ôämºyy]îÎÌ;pÎÆïð«0FÑ6žÓ\SÙ+¡ðü QMÄ"ñ¢«D­hÑõ¹Øõi Æ @_}€B­ÓèÔˆÖU+´nÜù²%¾¸¬¼>jaƒì ­ŸL6ý';ê/nÚ5¾&¦f×öY¤×öòù,+á«HKb3$ÎxChðÇ’zŽ
+ ÄLš“µÁð°”—3~ñç²€²ÒO’¥[ÅÂêÏÍ%0N ¥ü=)
+®„Èœ³‚ AÝz)gÁÇW/W2§¦}â¡Â&êUsøA¿Á¬ß {Šx²ÌÚSHãÝÂ'x‰_¬ æ:œÈ0¢ïõYžj\ä
+=ÔéÕ
+gÇÓddþØzÇ@YsRÂÖµ{>ŽzÅ;ÎVï<ÎýzÄ (?²JfÎO?éËÔsc(¹ÁÇæŠO¸ØóÛ©ë˜7ß°]˜=7D-×{82‡&5>zO…\­rÅțخŠïø•ÆÏn]ãÕÜý§~(;TZðøVy°åÒy˜ ¿¸\yèÂ;ËKb1è‰lz¢$*'tè‡DDí[—ÛxÏ…<ú²Vüëývp‡qôol½&³Š“©ow)ø!6Ô"œD-Kuö´Û‡pRTÒ›â *»¨™È¬e\_†%Ô{¢¸·†Òz”/vÈÚèMåª}b.J8<Žž<×ýÏÕX9ìù-þŠ_?s¶ýLyv¸¦ãÅþòÒ‚ïmü"<ŒÏ8׬/Úf4%rŸ–ï ƒ¢2HpTŽ7: 6¢íÃY‰¯2»gÄX)µÑÜîâŽ}yª½gI'MH",=$“V£–4i] F䩶Ál¨3wàZ–)Ü…†€!ŠÑÃàlÎ¥TÆŽî®cÓüG6÷LB² ]¼þ×Â×½d¸Dœ% ?×ì¤6È&]݇9Ë•¶/é?Gaý¶aÔX¿}Ý2k÷ÐK„ˆ#Ólêh¯~‰±z)æÈY…ª££6¼>cƒO³2kyí…Úšùó„ŽsÙy"¶»”Õm0B<ùÑLÔÃ˪0#*{§VÉg¯Þ¼xA…åïIzc”UñÎaæS$]{ýg5§a6J¯¬Ý±õñþ8oÇí§Ûó‘R·x¦‰WÂoèåK3¯Üæ«ùqy°”7`ª:T”èó"Ò w{õú¼õ¢·ò„@i +E¶žž™¿ÇÕÿZ›t¢ÈÆJóŸÜÍ=F ¶N¬Y“«ÜðdîtLÊñÕ~)ÖéØÏÊЯQ}ýÌzá!u4_l¾&©Ÿ9ˆ§qqÕJ?¡,yÓ÷æóþ¡‹c,à2mâŸþ\žuílôšºMÓ§…ÿX;3
+–_².À£e¼—îæ‚ðI± ?Y‘l82~ABè¸è¸¹‹Ñ:ZeíIª ½Ñù"Éh—Q‰«UX í(5HŠ<vm$¥ãÁÚÅ{â6X‰6&¥Ó„¤žƒ<ª„5xÎ µ?vÔ¨t;ôQ“=;Äÿž‚|çþLé%HìDdN¡ñà a,YŠ
+r[ëà88Èm'ù[r÷>±|Åþog)\øÍs|AŒu–36 &•’1Wð–´3·°ßMŸÚ`ºO†ÍšÇftWO7D2s¯5fEkš>¾Û½cY¯òú!N¬¿¯¾÷øÔkàýž†y …±ç õvóú¾ø½A[¹2pì_è? ½ˆí`|ŠA,÷µqÃß`ò` àf¬À4±ƒòÄ4ÉÓHí÷g²#ƒ¹á ¢—°éíhÊÛ[…|2J©Z¡KÔ°_ƒBF%[q½|Îlˆ
+·5__µ{xèÿدö ¨®3þsï]ä¹QIÊ"!† Š""EðŠˆ‘Pdu—§º« >‚#1(&$>Æ*]dÇ$”¬8-u:h­5„ZÇc”§C“8Êú»X_™ñüÑÖÝùÝóÝ{Î÷8ïqÊLuO‘‹M­…{Wn}‹H?¾ÿvÕëWCßJxùÈ6¾*¡¸é‡TTŽ—(ÇÓ3Ä“¿Ð%ÐCÁ³šúûÍÍÍyéñR†÷¥ƒUUºªú£YÉ~fÒ˜¨F+Çsïöw÷•+$­ÇðªÈrBB‡–eèèˆjëö· eâºoOšJ^Ûxù¼^^œò÷–¤Ù¾ãX’õÜKæ,²{íéÊ7¿&ÂÞƒõ;­çß{5uYÁš³îàö×cîº-Ÿž›ÜeéÊñÑz·Íÿ,y9KÉ%’4D-ûÕ«H~ËDÛ«QH¶t #†?#Õ§ÀóOvTФ¨¨IAQO›Í’1hvä” Y³îèEœõ`8óQ8ÇÝÇé>\%zÜ##Ïð»Ø˜…s¯Ú‰ªfƒÛ+~±/ˆd ýv³q–ã‚Ÿm"èÂÂí°H~æIóEæä&-݈"ÝLcã"qÈ5”ÙãÌfÀW[*wf‚-sÛ¥‡ý:yÚÜÌ‹¯–*ÅZ’_cî+˜‹ÊVÿ5?1þ™¢¯HÐøÎ?µÍÚJ³HPÚ+5ÖVê>‰ŒXÞ«¨Øz†wÁNøO¾ e‡Q`ñ•£
+ÚíðúÌÄvÈ«J@4a¥spÀBØ¿;ü@Œ@Õg~ŽÔãØà”†hC0tè ¤GÝpFûœ7"Þ^ƒ ® ÚëªF˜'
+-ÂX:J¡UHû)´èé‹óòròLy z­^gÒij§†‡‡M ÑFçdë´‹ŒkŒ¦ÒBƒv®±¨ÐX¤3å×LÖF¯Z¥-ÊËÉ5k‹ ņ¢õýdm²!ÇhhÔækuZS‘NoX­+*гµ)¹†‡ËIŽ‹N‰K ”I?¶T˜yƒ0!6€ô Eèð]‡ÔQÄTÇ–ðÓ ÿ!ø-y²å‹Àk&(…Bä×Â\|+Bš?u²\>b²Ìµ
+ÿZüÎuæb_±üfÀÖ€ízY?™ŒTò|'à[ž<Žk3É2õØ»Û"(ÀoF´D )(ÏðXö$CZ”‚Ï4ÑI2µ-å5êñ¿ÿü3âþ!.'»@QÚ'…à{ƒ­¥ã!›f«)%Q‘¥öU‚ÝoÑâ„Å0\îR•È| QýÑì·9š´­â…ˆ-èعÜ-ò{ðVËÜmŸåöJ °Nk»c¦šû0÷3›OâSý†ïŽÍ¬“µ8fû¶ò£1(`³LáÍ‹NE,€‚ÇÅ6ð¡NU‰R=”nh ùP…ðR!^*…^b‰BTc»Vð¼ŽãS ˆ,DÂaF•>="“ç¼R)qçrx+ÔB…ƒš¤
+Ò&hoƒÆ¡¼ÅVÄjЈÕà‹óèÔƒ=؆¢ =®õ‡$Ñ ÑõB#¤‰ÍH£[ T¦+¡žôã|ûÃQ>§ëUסža?òñq´ù} ‹~ØW-tƒ«Ô ã„&ð®‚+Þê¸þ ÒMØÆ þ |ÞòÜqÞ|ÎCs’íwR캲>÷mZ‰öýˆøÑ5lÛý@»ìGsîûjÜŸVD>ß!
+̨#EL‡z¨ãPMx•B"”KeЫºNÜNÕ/ƒÐ¸ª( ÿsß}o¢IjÑ‚Ä! ÚfÓP¦Aj7Y„`ƒFj[™Å$„J:JUBR)&ˆÔPL£Ä`µZ¡´¥ÁEFpQlµÍ"„ b»(¥"©ÝHÄ0¯ß¹yÓÅ@ÑÅá¿sß}çÞsîÿŸófB}á.GÖ ]~†½»Õëï©Èšb¯Fÿš~ŒÚ8û°z“ÇÕŸLË—jg¿Aã^ðQÔˆñ? ñVÉG {3þ þÁÑZ®lßü0V"8ܤÈÙ½*ðõ
+Ø´`ù(ü7šnmý#MGÁf°@^oÀÛKäö)Ðò\ïð{”œ‚ç<Ú Ç­˜C-@Á¨ ¬;‘á„¡+­Ï»cì³–íW‡~9]ªC A#õhuÅ´]‡'k÷VVB
+:øžña¬EÛ|Q[}E™/ÓS6'G÷o™~B-þC¥h þ}®£ø<ã¿Ð”Íù~Æ[Ãõýö<šÐ+¶ÆŸÒþ°n»ÎDkiÕÏ2îÔÑqí¶gÔ˜&ÿNE´×óîmµšÏxœûëÕ†DšNé1þö²{m.hý3rv ܇÷äÎΙ_Vcþwž]Q»qÍU1>›Õ…ü¦_Ù;ñw„ä^z׿®r\e³wâ~|X¯:ŸÕuÞZ¶z/ü>o0¦Gű®‡š{’þ¶Äøµ']¬µ~ˆÖ^ãBÐí$½µ~7ÁÇ2ù4Í­ÊG“zÕËý ¾¨ÆxœÍúaÖç¢nŒWñcz”¿Æ³cäi
+H‰lV XTÇž3wvñ»°,DSX®@MMX–UÀÔX£©FD@>‰Ÿ"">
+¾>{~NêH§ôþ/&D;>mÖŒ”«ßÝxˆã§ð]x¾Ð
+šEøìÄçÁiéYÙÃÚ¦Þ"Ä7€áÆüÌ™3½ã‹k¯íé3²Ðëd?!ƒp: Ș‘>‹íŠÆ¿^çpþv"cùå‡0þ÷™’êîûpTUŽh=pXLB`°9,Üê£÷VCÉáíËFÆÆEŒ‰†j¡Ók‰˜k>Y^;ä°mªíØû»ÖjDAôRšÅ¤4“ 4v,§ÕÂŽø¿ÄÚc«cî½pßÒé爩øS|UL«”:¢-B(â7ð5'· Я
+x¾ÜŠùcè‡Øƒx¤û²g½D/“µ>µßtàH 4Ñ=4_1õ%T„¦†™ï´nä'é‹>}Ž™=*>!**n²_œ%2frÄ…Ot· Q5wâMˆ*j=‰)
+ÖÙ«·­CáèH2+añDƒfÐ+—NÈ•òiÕÍæ¯ø!Æ›¿"®¹)87Qžd³2_G ¤|!7å$ˆ Þ<ÁCÒd.nèåÔžFÖžQÀ Œ
+¿ŠYŸÃD{mÃÓfþ#×6Ìá—©or.ˆ…ú7ŸdðKí~/⬲Jp#^Äè±±ÑR²ÝN+Ðté}$\K§:R{æC’§§I»Ï.k ×’Є#*×r·S´Üe²öŒªÏàè yŸ0‹µ¢¬1½L| ¦p µª–>Ó{óè
+>ÁÝ_í~â!=¬¿ú7° Æ
+[¶Ï%#´«… ô-]~ÅY¢*w.-x#;FX(\ldzá.ÿm<Ø,³š&eq×ôo…—iÎP-ëÛÊ‚F¼VëLBœÆùÿ³P¬°¡Š×¿@¯÷•3†ÊåuåTï­“»'¥N~¯ƒ<ø= …%¼€7mk;öýŽlA¥%BÏäùG|ëäÍÿ~ȯ‚îg àÛ£:&«Î]F 2ÎP$Nž¨±Ã¡Npãÿ|Ú°ckÝÎ÷)“œªò»MçùSj•œ…«sÖÈHy¥‚t
+¼Ö{¼úƒý 2J´Ä̽(]Þ JÁ7ÈIOx¾Þ Ñ,ãæ±{@šNOc¶Û[æ­Þ¼1;sGÕÐÙ»Á´ÎsxÓ„ùåÇ>ݹû³.ÛB'¢ÔÊ9tÆP‹^+›×éõ!èqÔÄï´ Ömúá^7_mj½ÓœTä‡ùÍä“ `ètBwÜZ¼Û±~‘ÌÜ‚ [ÔLþ’Ħכôò‰Í&åÌ@[†‡WݾÝúÉ'ç?Œ S óûïUÕuÅϽᄋ‹XD)E†‡ˆe0 ’uýˆ¢ˆÄ-¥Áîò¡ÀX?ðc4Ã0Äb±ŽQ4Û %F©%ÆPÔÕªŒc¬µ6q¤tbiµ ‡C¬º—žûö-kg’?âžùí=ï½{Î=çÜ{î¹÷ÜN×S—”ìÚÛô§@ag hÓà%Œ8Ó¼”à™iëþÂõ„øž³~ß9¿»¹©¹•UÜ8ßË».äa~¹¦ª¾nýúwòpoéLìÎ;õ»_œ&Aÿ F2cßvžYzà\ÛîŽÕ »¸B§`œE½ðª¼ 7uiÞ×Öà¨è8|œ&‘:î6œ|Ç©®«îZmÿ®A%òÌBqžvâÄí5€ͶXfϱXŽ÷°Ûi3g¥/5ÏL{Ê@œöé`.×eCFÊŽ+Q÷? ~HKB÷……KRLÙ¶áÚ ðû.O9°Gðú“ŠþŒ•)Òã‹8eI¡¼L,f,"Q<…t‘>$÷=M$<Ø}G—$ÕrŸ·â:{ä¾ÇA QöâÜ„k5u²¤¡`Ó‚¬e¨ÜòÓòŸmí¹œ[‰cÙ; ÞU×ÿ“¤Ó»j?Øàn§+‰âÜîngà<±6÷2Ïs×xmŽÖÖãð9jQ£”tµ°•­ûœ¬¤óHØ»•nƒ¦?ð}D¦ØQÚÆ‹S¼'çÄ‘Eò¬M¦Y_ð2ÑÝOüøÍ»5¾ABÞ !þGª(~ûáøuiýÉÃM­$·ù˜Ø#øö:êÔ÷ˆ!/Çù?Øôù'çÝ®oö<Vu¡‘w{ÿ™&U­Û#6‰ßz¼¥},P[/“GÄ0˜ö™Ó¬ÛP]Ê™¹ªyôM÷C—ºýD”r0kmRõ{€·h½òlÑÂ|Éy£îÐ’í{òº[6••íX”1cǯ*þvöíðyeñ‰3æ×Zw~}mñ«±Óç̘ývAÝGBÜ`uÉñ"ƒÅy7@Ë]S€Ècm뢮äÞÑÜÜûõ×É?~%vT$I¢¡®¾Åüª‹ûç/WB¨Â¹b Í¤H\O5ó,ã
+´i`‡2„*aÊ«°ŸÊ‘ÿùš^Ñcš&U‚¤â{1f~«ÐžlØÚ°Ý /z.G®ålñ©Xë'Fsh:­øµÛrX‹ïìh‰
+™¨ÏöìYÙˆdHEÙèoFD?—kú‹a5>—àhíÛzäŘß^îûèù""#±•4 d`ržP
+´ÀH©¯2
+”JZ®û¥-M_
+óA}BÆáÙXM¨zV3÷c£êYŽH›\ß»jÌœ¯ÀרI»:~2S´§WÏ3óæSm°‚¨ªTW2Æj÷Y|Õ…ßoùTíÞß#£ÎÐx«¡QZÇY+„²°Wi‹ìB?Œpˆ6A"HÚ©²úÉMˆ’LP‡m®d¼ýÓGEˆ:D â¢
+Úä|î6š mR4Úö
+ç{§Œ
+H‰ìWIŽ$Ǽ÷+òS«GÄU$¨“
+M³õ¹j^’MyuMLÍÞ·?S±›—P¶§jî;tã ;½ûúÚ7%–eò°Oõ3Ž §BU1ØÇa–BM¿c/ÿ­Ã‘KLÝKIÔ§w©yGaÌçXÌ¢%t{“«¬ÏØbèä'ÀÔUR½#Zç©Æù©…ʈQôoV]mÎ1Š&éHf X£æÓÌäiN1äÍB«ÚÒ¥‹·tHº³hNÜžêy/^äÄáÄ.1åÔ íÎh6:¸®ueñêÅneK”iU—,;òuœH·ëà°çèhÍ …VÙ».{ùËIC»—dÃ{¾¡2v06>}’Tì¥z[IKÛ‚!+»3²«,b‡KÙ
+¹nÄc” kéî\Òv]Ð-¬êÃî2ùßù¾þáÆvà’8úˆÇʼéIv´†õëRàg…÷âÛ² äú˜®;æTSÚ¿ÈC¯›\·\ŒQ+×éõT#)? *rùà"Çè³áV“bŒ á
+¬Áú¦ž ÀŒ§ €pÓeG¹ËÚë™Ø2Ú”º—r¼˜œÏÏö˜°O»^°<ɈȆ %f.‹oT'ê„YPF + ¨hMEAÂ4-be¿-™Ûµ±Ya¤u®¯ŸÞØoì Æ™¦<ˆÎ‡á5Ùà2Ü›ëÛˆ%S‚Æs3¤5¡¹†?€2øC‰àøÀÙ‚ˆ6`ÀÒjzoµïÕÚ½FÛ»O/kÿ°dLéÞ®Í~‡4ÝÓ÷ôþmõqß}¶æéçé ±¸Ù¶Àm7Û 5}¼ŽŸ7ß«OÏ\»ŸžÛ§ŸnݶÝÝÎJ|ÖáÈì;Ø{ t—úZˆ%Dv9D@}˜Êšªo™‰Ä<­ŽkvU÷=¦{ÙŒXÚÚ‰WI)ªd%S¬qæÚžHXÄ@\‡à/bV
+€%0 3uœѪ1ÄÄÁ »òh%Þ«È7)³Ö¾ ô²ïo(yÀȳ\³h?DÁÈö½4õ±Z@é[µ±iñ‚;ºT$Þ«IS¼Òô »
+{¸þ½§ƒÀ;¬‚Ü«ZÙßnåj{hÖâöÀ²šÊkçPv?mÖ¥‰ÙÑ”O@_ì¦Xœî“2`õ/0égu±øÁšÏøfÉK˜Â}XÛ´]²ÕÍ„ÚÑ4§ÎÇ–Ž[XÝÍÛXC¤
+ÕÔ)žÕ |£EDžO5`à¤é·±Q˜i’#È´Z´awfz`„;CŸêúqÞ)7OÜxòe"mãìmáˆï‚Ýz(‹-عX¸NtÚ¹‘ýÜâÅîYÅRД´ÆVÒiùÚ-ü\¡<9Ÿ+R|@ý²â&)ãd =É5íÜÕ+
+çgK•ØX6´­éRãEñŽq­DµzÛû‚\Fßþ`Ö:ZLÏ'Ju»uÓ¥Ð0ÌJÑ%õJVë6]¨×‡IªÏ'_¤X˜zœcÌú®U*Y03 ´Écô^ Þë~œžü\ÔM>j¦zÉç>—®ôK"[Òw „ê#•'CÑ/~Ì°ù–³%N w÷9oƒÓbU'_vò™™/LQ¤
+çFù¡µûÐ^·(?ÓoÖkðJœ:î(õ=w{fʱ~•f‹Õa)>¶úž~‡†‹bI™ûÁSÄ}— Žyh½?}ÝÉýÖÜ5ÊdaB6]^yPùB8Aà]dGÎ%6%¡?«¼{Ñ#Ô7ö¨ýÊèl‡ŽÛÔšH»â¢<‡êà<½L˜VÜ®d™%JiµZjÜ%uWU³Íœ¸%”|Že=$°jº”‹§ö˜Ü|eÇ’)¬vp‚èõ¼aw‰·%/M3Pb”³‘×"Íë,s⌜ÖÓg%-+jÿ,‡9—©¦‚Šºó:© ´áãI¼ôYáQ0{ûƒúÿ þÿ7êÜkíëô.I:Xåg„®”–¾I€·,Ùcû‘ûý¹ug†0â0Ì'¹Î¯À¨ïÙ¯¸¡·à£Äý_óI9_>ìšüÉþå—ZOÖ¢+l½TéÕVË⯳ô]WûÓyYŸ–à×Aˆ¿>דs¢g4êÉ°˜ M=e)ѬƒÝ’uËxXûļVžzJŒ'`Ó6¿dòôjÛ[ùT°íÖáœølç7•Þ`Tsó;ªeÁ
+áÆ̳é´Ü’!£€°Q™"
+*®5°˜‰n]MV©q¡¤®~SÝ¥hN°xáÑÞŠ&ùU¶î©î“²qXVÁRÞ‹:²*ž7,’¨î3sQ(×®ÊÁ!XZ†¯hÀp}¸F$PË'hŠ£ý
+¢¯t ,Ìï{ŒŽ!PŸm¡ñ˜`ó ¡ìKs3IËJJœñþÆ¢ªgŸGà›Ls™£B‹ ƒáÞí( ²L‡›‘œãùÝÝ+O˜»Ær£ŸHÝÜoữâc#Øpø2¡ 0³dYëì 3íîæGˆõfÒÛÅ]0þÇ~µcIrANÑØ%øû|Òx„1HcöÉ¡§Û+>@u×ÌÒ¥#:Ý…O!™‘‘‹wTfH%ÅRš€ÇOeübÔC/ŠîækòlæKv]“ôn§ü1ê.Jm”ÇråRõUS¼“ìgtÀÉY Ëà+JCñ®ŠÛ°; Žþ„Ô²ÁëYâSîæ =ËÃ¥Ì=Â0ž‘Êî¨j5Ǧƒ¡\-ûiy‘æÜ *âÞß^Kkø~ø\3s‚µ5³¢tDÏr¹™å]B–ÉÔ¨F!Ÿ¬ç™üªÕå+) ·ðrµôÜ/dÑÔ;£Žñ¨¬ONþmÅ‚¨¸yÀ”a¨c4e »‘¬Ÿµ_£<ˆæÖ醪hÉ:ÁXE;53
+¿)HÓÓš?ÞìJ2ìqû‘~ÕÅ…PbGö‚G²ù½$ц”зØ)m$ÃV×(ŠÕÒÂ1Ç&6:¦•-(êe(åIR ~=(”öŠçäkiI4°¤µšŸÙÈÆSµ91ñd±7w£ÖHÝwGº60 !úöYƒâ3šØ•anFÔa“è…!ùñ&‹2…©È»”¼yX±D‰ÚU>iNe$OG
+øYÊj¯¤f‰N* Øx¡Œ§Lm‚Ìæ'唫ê´ÓkÍÎy Ý@xèÒP]æ¼í]ìÈ(ª‘sXW¹¾*0aVWàVÕyeÀŠ~ BaŒéºWu£Sc¥ïíËÛ²RJ Ý>£g`[Uÿé[Ú˜ÊRÕø.áiAºf/ôæ
+9”¯súÚT7ØŸé¦FQÄäé’ûA*Ý[—hÔ…Zν
+’Òâ
+öHªè³¸r¥a]]2½¬~‚{ƒQÙËyvH›–ƒϵX#ƒ>Ã%÷q&‚ϾŠeÀ‹•(Ô)dZa™hˆqçñÙ*½<]÷”O0ÎÇÌdÚPwÁ¤¢—H=rm6*lQN9„”\mèŠ:´À5ƒéšÀ§éá‹}ÿ*-J!E®ÿGõ¶þ"õVC-Å[¬{â·]ÑÕ±QçPŽOëñ!­O­ò¾I‡i+©Bï°'°®Zk+°r†PÁ;U€ös·D[ÂTRƒ ^M3}é†s>àÊEC&¬›3yé3lÙåÎÒë•íVK×kÖa÷áÂœÛaùR\eV(@FUIð  ³îËsóÏ¥ü
+TÂV~|”ò—=…ßn…¶Âú (\ZU‰(¹dõ;û5j¯©w“šË^«:¾çÔg*¹ f“iÑûA°$Šœ$¸ÏÔ=¥iÁˆX\w¡Uá:•g°B«nàp\ùŒ% ?¬*¢rc“…¤Ÿ³ÌàÈó
+ß\‘¸Ù»S„C‡ALÂ
+ŒŽ*Žüq{Ó5h~"¦ðãvÈkÂê¾Å(Õˆø®¢3"á`®èûÏ ¤ºw(Â-{ÇÈgE •yF0C‡„({ÅKãù^Ï^áš„Íó,ºs¯ð)šŠ÷ó”M‘ü´ÃØ–ÛÒç {âìp|õüÆqæ9Åqö9åý:ÞïB¹á{Ê8*éàF@átcKj¢îä ±6í˜B(ãIõäè‘ÝÐŒ¬uâsÁE…)Sš
+ßܽEFÎÒ¸¡f ìpU6 ïQ¬ëÍÕQ4T¦Šôõy%’·5÷ºêYúnUG>ÈÌÓû5
+½N´3âê¦}„óÕVd=lÚEá¬÷±<w™StRjdâg+)9L6¯4º<‡Êl#ÙD}|F!ýZœ…ˆÃùº+”qÚîPÓ1³%>Yn#umæ!Þ'¶Ì•X–׈‡ûV«ÒFiËÒ9„nÑ­+šžÍ< `%vN•!Ç
+ÒÙvv©a:¯©¶ÕÇQšêÅ‘_ÔdW GŸÔ×àMê>Þàç˜ê2XK‹$_ RŠ²­Xêb¡KR_©ªñdoŽ,„zŒ±ÉÌ¡IF“d<
+åzѤ2©ãéiNJ&©3Üéî…zF3—Þ‡ò„r¨ –ÃU‹Ú5$yZ]”…+t7ÜœìŒM¥‚H
+¨éàp>³ç’6|ž|™µ!R¤°Mé* ¼Ê‰û™_4‹ˆM+ÊâcÒeN¯Ší®¢ –ì’øÊKK
+…=( è“—Î2ôñD·ÒÜ8ÜÑÏÔ’Ø\dGnÂî¯íyRiX²²µ Õ¦áÞ%—ÝÙ5}IA”jˆu!–òê©ÂÍ2€ '“€M!·mJ¥ýðàãÛD‚K§M>Ï]]ÙcÉ |kˆCñ\¥@WÛ:RW:¬)±DŽlÞp6e0b;BþÔ‹Íü“L%j—hVŠ]½«±¸eðÛk¹Ã(:sž¶|È8ê6fó’îÏnò‰í$aF´&$@{ÖÊH[©;©^3ËEZ”}çLﺟe{ZŠXÍâH11õ†]Ì‚–ÏgŽÎòÁrªˆ\¦êëƒçÝ^¸ùè ½ fDÉB/ÖP¿zGKrýã\ˆ!npÕ®¹XØ9_èìrYõ3úYBL’rë'Äß ñ$DÇ0m ?÷„ŒÂ_È" ÇDŽÏî@ð Lɲ5OV¸HnkÑh^-kÃ9
+îãjö^0ëËÆjþX¶}åÉ·ˆðƒ¨Â!q¶ :“4I;é9ª%ŠUoÕäÒüý ÷—S•v?åµuÏå æô C·|ÁÌà ârS ¾a5¥ÅEÖä–å@¾ËSÎÌýz¦ÂÖ,û#uMkwLvšë+^.ÈÉn&a,¡lO‘9|wGÞNo6_û¦$PeDöi¥£þ`‚Ÿ&¢è6äç’¤¡ýNz’‡¤î}ý×îR
+Ó»”ØÀ·0æs¬OÉíU>”¾b²¤¡ÏdgÎtñŠx:O5nYiË»`¾†c9sÎ}H¥{NݬšÏ17’§S;–9ë’Ñá-}%Íñ:‚·§Z›9qxb€^<¡ÝÉö•›t®«€%©ÆË'Q¤ûæË8Ȉ Ãu›°©jz×e¯ål^s…‰äƒ·ü‚bìËØøøDÔQž XÓ>ÁÐ)›#²) ú¾.EO×E$ñ¸?£%K¦3êN z…Iý°·°*?n~Üt.ûýÍ úŸÇÛ/ÿü-¿ÿûí—ü¨_ÿ… œY¢A¯5‹æ ‰N¦ü¾ØôŒö½T>‡r ô{ÃÂ]8--­Å
+wå …†èñŽ½-_ÐhAW\ÿ ,ºªO/¼ý@ŒΟðDë0’ÑÇL¶W0cÄ?½ø ÝçA'Öqž Ïá4]">7Mz0'Uçû Èž‚«ä h‹ñìÖ"bh”ÏFù%üôËéÊýß ThúÎzíhžzÖvL}¬¿¿ÀúbÛ/°ÿ”y¡ÖEÇY‚µjýýÖãe>Ì@nÃüUîaƒ”—ŽAoJFܱœG­°±F»TÐß>½ÐüQèÝ)éAXù5´Ž ˆ åÝdüýjÙ‘ä6‚÷þŠù“L>¯ü>X÷†\#@6 ïWD$«›ÅÝÁÚÐÂ'aÛ™C²È|DFès›ã ƒD‚•F¢ÀØ7¦¢ŠÁÃãœFõÖ=Ú«û‘lV¤ÂÅä…k(A+½Í¯#*´9:`ˆ2¤×L Âã Ea„îÒê,ô‹©o·¢þJ51³¤Í4I™WS7’ùxž_¶Ê¤.‡8Ty¯2Ê‚H7Í“¼:T£¹¦§9/½È$©Û àqûûÛ/D’€¨ ²"Ù{fþ.¿—5h®˜Z#9pTë)JtüôóÛ_þö%¼ýçËÛ_~sB«“ NÖ È{×Ixê¿ÿ±Üc3›`V^`f½›½)ÇI&'ð6h¨˜#{×€6ƒµbºy“òÁ›zÅwvUFä,È‚ÅrɨŠà=„ó›ÛžÃž/ˈsñeœ«u¶ÿæ8nHØš“¦ Ø³?Æ@¦Š!]ŽPQ¶9°Uª®Ì˜T¼×»„«Bô²TÔeÔö«ã £é{ø³º Y<èÙNhóʬlmÛÕöݳŻJX<Š‡%F´
+Róé>Pi0³
+fš-Ü…ƒ›ã`ÉF½›8ÐXÒ¥wáhcôN3Š¨ÂWÇñt Hâ‹óUÙˆ:§_F­Ì0uõ×ÅF’º€‚v%sÀÈö Õ¾[!{Im÷ý
+EI›yI³=YðÞm4õGÞ¥ÎY‡i8aÁTSM“9™}æ‘©úþÅ¡ýF8a´+Aê½—ê€;øš¬Ì"Õ~ý«CÏoæÅ
+Ò°ü|ý)Jà-;̳È6Îþ·ëx#Õd,¨?5Þ)¦“±âŠ(Ý&ÀD@ªÚ*TATUÆ6j G™ÓÈ!¤ÂúðÄ,hMê]f¬ñíHh„ƒ ¢˜¢IàÆHïæ! URU«2‰Ìk²ˆ.MëøÆ4%Q[Ò`yÜ6Ç!Gs™Ôš64e
+HŠ†©a ¼&¼ÚÚݤ°¼d.çW]sušÙ­4Šï^líÎ.©8êii¸QÞNS–K¤«­ÍF¼Ä¬Ë~ñÚ‰vt äE“‰x+q›Cú²¨f
+Ç¢çäg7}ŸY ø|2‘.&$‚À*4'F“+‡qBÍâÔäì41)¢ïçywb€º4M¤\Zþ`ŸÇ®am Ý¥t€ž€*P(“•®I‡&sàë„ ]"é0Î2ÍÇmshÊH œXÅÍ"sŨQ´qXl(•$b`øúy_W°9A‡È49
+Rˆ Îó`Fe2£æÌèëu.èŸ-hsÁølAŸ bx±/"Ídº±úÕ9jPI€Å¤Ù‰(³sV¢„pðê˜Ú•
+€OÑq4p“~ÐŒ)ÙÇM
+}Uï'‡™~\®â Ú¿:´?dß?pR­ŽÄ!Ê,Ý9O”lŽƒ“©߀–g©¶äÑL•£™Á‹íc؃F(ÝGnð™
+¦ôßÌï,E–¤2xXôlY#xm²ÇÀ âv'£@¡jן¯)QšÄÂù‚Géb •ÿ†P"H¤:.àß¿n¿¾EýeODÏâŽ8Šñ/7Ü B?Á.3š&‚AR‰HÝYé5wUwTd¥—
+ïGe`?ÑžÐÄB¸PÐÅx6æ+¿yý±‹±Õd!' Ï5Ì{Ô
+Šäq—ÙÜ Õƒ†.Ö¸²º0Y‘!œO@áC·NÄŠ”½¢œÚtŒQ5ª­Âÿ˜]NåàŠÙ%ßÒT[ÇíÜ€4EÔŽKyt¬ƒæŒÒ™ªPt±iR‰P( ùL]´_ÓiS£P–Œ§¹^gu/@8ë9i¾.£:q:Kœ¯a’”Õqܾ¬‹x’XZBÛ,?§7f°`ÉSdzžõY/õI©;†Ï 0†2«œœ™E\–‚uiÅ#)GKyšÛæpÁÚâÕaÖÖjœGavf~àê8(qD‰8ºÒ 1›÷Ü’ôøF֪ʜr›Ê踅®ýí¶9´>TwÃáó!»Ìïë“`´2¯û²õZ¿<ûAO÷·²é—Ð8‹ÞÕ[6…´·•VSán¹z\
+b ÈR½«©î/S»0»'µ¤a‰Có¬‡v­à®x%éÂiy•DOPNrÀ9Mm
+. {i¢\uRBôV™|²¥I¹‡ö×ä
+rt‰
+ÔçIO”ïE³·‰™ë&+lÝÍWž¢·ˆx¼nÂaÔÔ´L­»9°=‰˜Ó)q"fdWúðNs\êl%ɺÃ`Ãæ߇R.™§LÛ¢Uµ¹#áÿœ§êã„OT'ˆjÂÝ6ö»\¡£ƒZƒèªQ¼%ô© ùö«}t¶0gO¯É¿³_-»m,GtϯÐ:
+^oœà}Bü|V† à±TAðl™•ŒŠ3+¬XO bVHÄH«¢‹²¾WÈz'ÓíþÈ<x˱ˆ„Ë<ÿyÉ›êŠD¢W,”éGôÙ§]Üâ4"³Ñ+»%Š6)¸ø#»»ŸFg±Â–Š@ŒEy#Ó¤IÁ¥îƒ(aÆA¯Ë9§kÖ½+>)ÎTTÄ}8íÐþP’®j,*‹Þ8n µrMŠóª
+þNüÉRé9-)‹‰öôˆšŠ—A²ãî†GN˜C(B H@pŒ´Ò3ëÃ+Obæ3kâ]1²Eðü!±7o “;ˆ"%:?ʖ쟗ÝÇFe
+kåQýªðù49 cê̘hn ƒ ¡½çJ"‘¹…[Ì%ñe7)¸ÙTŠ†*È!–%‹ sÌÄ~Ø°¸¸EjS{C^€½Qf.¿öÝ{O<²I¢J  N\È@Ä©ìrDª0Ö"òE9Ê„F•³à"Ž’û;PMÀXaÿxFâ—ݤ8“" rðhHÔ©i*@:ä¥×•eu¯àվʘ@/½çÒDóÊlŠ52KÖDîžgR/ÉO ÄB„¦Xàn–«Ð”¬³i'ód›™Ÿ&Nkx&3žR´" yÆ ›vœ}“‚gË…Q:Ôf[¼|‚Q4ÙXϦ½âL}P¦zjSÄ»)ªp‚·<(‘/0hŒ
+îz¥Xõ6A3’ª˜Fïþ»› 2óD Y ¶Zª6ÙJ=·r`1!y&…£âLMÚ$i7VÚ¨©|< —£É‰t®rÛ^õÈç"Š…£QN¼#‹&(.ºªÞîgJÜĽ5‰àE³“B›«FÞj¬;R¥HÞ“½”› èD9xb ”j¾HEAIªõ
+NÕê%:€Oy/4/Îû6_&F&…ÔI’6‚IŽ6KRF¶H¢—È"á¦$z§àD”º
+ š>BìAؼï wèPÙ(ƒëÙO,<4²Òî ›3Ä™¬§8b’AæÏ"qÊÌbtù•¸~\GÁðpññ3èêj,ŠF€˜ø$r¨§ž›ön?­±Ê ÑPãô:ð r“ÂÇ*ºŒ?MÌ$mæežÞ¯fY–°™œªÜoO}E>R P…õÈ¿½Ð8ÚرPìj‰aµDú23ƒ&šˆK^…’uI²Â7käg‹Ê^6]Dà‡#†ï«o¦³èø¶‰Ù?• œ}ηë6I–y"ü=™
+ÊS0æcʽ,7ž¿óDܸ—N¶ÕѶņ¢ú Ï§es~:ýΤÁ8Œ5
+¦DˆÁÛüC¬KtþÐÜ»:S2›G}ª ãŒá÷øçwº¶±ÍXݦ׮GOÚ(è%B꾋úœ.ÃßGÝWßõ{!—ŠzL“öùl Öë[´;Y¬‡óÆAŸúî^~Ó¹lTé öª#–­èõ½êÜÑÎýf—n[ÃúP²…™R],Ü4¶Y·2úÞˆ+øw<îó¡[sZÝ5-ß°Êê‘.š†·§îþÖ¶lÒÚƒ•™B4ý(Pì/eûÃèqŸV7¶ðáÞÌÛ.½Ž‘ªU"Ï(O÷$OÜEž£ `yúîK÷sïU©¥ LÑ"Îkð®;m£Öšj¢eAÖ ®-ø¦›uÆpMt‡!&P}—ð¯Ç7Þ÷~½˜ «ÃûÄçÈ ˜OñyÓúoƒ{ȇëñƵ¬ñîÕWu»ûxòs•%F
+Ž„K²\I*A‹÷Žöb}ìûclŸ—­4»ÍÔ×@Ç»=зjP÷¾_[ „%oÏN„L(„U
+a•šðûXÓB«lÏ*·ŸOúÔ çÔAßë>±Œ.û4CìYÏmˆúô ç¾÷qËûæ¨wf æ=ªeîaoAe_)Û¹¤ÉëB¹5_¯ÊMEr-øNÕóU¸Ž1#†&ýM€½™ƒæ«òÏ¿•˜&È0jíJò.âõhºÈU×ฃœ´Ío‡L¬f$­æ¥S¢ºäI+“¬ºV.:Ú¬/rc5ì³aßcˆȧMûËHßÁæȽ¦§;­Uö!y$Á‡X迈$ûà}¾ûm÷Ç?ÿÍÜýó?}–È1€ó¸(_ÚÔ>5˧Ëm?ËÔÒ[¹±£NkCn€«mŠÐœµNþxÈÛéÓ€j1{¼=Ôôú•ª¦%²“5 €u…ˆnU§këßÓÂ[ÈöWᤞ~¥ä»†õã–’/7”Ò `.šo[\qÿLò󳸸?­ wo‡Ž{­¨ÜÕŽù-{ÓJCà‚rù–Þt™ê|)Ÿ¿…ÌL)äË[Û®Ù¼.½•§n×>ÏãÛüÍLL|s²ÈÝîW¼µekkøïïÒ1~-+úæ¤ÞêŒê'Ãx…©´Ç´Ÿb¼÷WÍžæ—ƒ1Ï% eŠ½ƒ;æ)‰§Èa Õgx_l%òÓ(û¶®½Ïºþ4zÛ~Í Pôƒ‡qãö¡Ó÷a>rèŽ×tÍ Wôц98™x ªφ©Þ(®|3Lý¾œm§?2®Ö·4âŸØú™Ø*™ÿ»‚TõãO$ý¿ i›ZÊEÅ-ú€
+þÏ„y‰©²‘\ΊâÔdîR:2ª´,è8mÒŒƒž5œ¼ÓvyËÖÛ¤È[ð›¿Zx3€;½—p5³MúÞ
+÷î§l«¿šDùû(ÏÓ 9÷ýè0JÓCƒžíÚ4ò åtøýåë÷ìðë­×Ñ/pLΧ!­aÞ±ÿ¸_€¸6À0™J…Ž g…‰kzFà z&¹kåJ¨S.ÇžH¼ÈeŽÍy‹Ì*ù
+^UfÊçB.qGCÞ¡Ñ÷{ÑnÖpVž‡ ;p/ÝæÈW¼ù#É5œx›=Ü!)ªUš‹w™Bâp¯ÞÚÙ§€Óik»FÀ^Ê|¥ß6é_X¼ˆ™õS*çSÞj¸ObQÃ(ÔrPz4PÔòðÏ¿ÔÆúÕ-Œ¦K÷¢ûßS|˜„±B潟ŋ nr|±J
+Ÿ å½  ±‘ †‹mÓOš½Óý+SO­z`¯1>gÅGT0ËÄGW1¨ê%Jé!ú…TËÂ<ŠÆUÆ÷Ê.£þQo•)9Ъ\fì5‡¯sÑÙå®:d7áè,H„¡øö™q²OÔ¸ì¹ñ Kîàš‘ð–IËôT¼VüSK¶ðDe}Jóɲ„ÄŸ¨Mí‚s ‘š-{/Ð*cµa­þ¹‡­ÃóU6,î/@t/Cý°¥Ðlâ÷u4k'ˆb<M(ÕEÍG¨æ·ÐEËp«‚ ×N…4r?äõ‰À‹ø7o‹üô” é…—9Œ¿Ò K×=¸‡ñHgQ¬o[‡¨“ÙçÁûB{{r9+;:w<úØü÷À^ߪôr9 xÔ±Äk[´F:ÉÀñ¤·É>O»Ìz\{f …³oÛ¤É%;áïõVHÃë臀& ”6qP\ Ï$i)YÖ"Ø1ÄBÐuóŒ¬M{f :Q,E’Ý´°œœ˜¾7¥qŸÄ¢†Q¨å`*25‰Ã?ÿú¬¸Rà0ŒÌžBŽd3÷ÙE6™\ºÕ݇¸¸ÒÃ<ë9,>û‚¨ ®«¿j¸7a»«±™þ{WW ïÝà:Ç÷groŠ-%}_ÃïµYOMÍzRžõâI–kx×v’Ð(—Ã(—L&ÌÚl8H9~ùúý;üúCaé‹ì ½Ø¸ªù‡ùˆOF ÚÕXo磴)Aâ¬õ[æ²m]DÔÅΩÐU墓÷L¹â™ý#ðvNE‰HG4ÃcÉxVkÍN#-æ(PÁ"dKIlDµÃœç8Ù³ÕF¶G'¾=„ª; U¸ÿG¡e¼ZÈ7ËyDÙ{; ¶«ÇhÊÐ’;º½j&LæL…†•²$e–š/öì)¡i6ã4ù³>OGn*±ŒÁþç0Ù€¤Ä1q;óSeÅÆb¡Ñ¡°¨õZ¯5»GZ«Ü±M;Á8‚M
+Ëj¸é¦æÁ§Ä?] ‹«¯àÉXãR=¥¤FŸÃµ&[Ï;2<’'Ç…óЄÔêMÛ˜Í_néÉŽì7—UØɳ°J2ç'¡ 4>OŽw£<Ã/Tð§rmM²e½×Ä …|O¿¹ºÒ…ኧ…mšHP88Õ#ØU’2lìª)¼F iú}èÓÍ^'n¢§écl,LRªßM8§ œÒqÊdmŸµÅb¹q™<ðC29 œ³KtL¬—Òj7RUKñ‰gm0þŲ̂Á¬¢–ºã0½­
+?7÷0€Y`ä*QÀ5-«wgæÕþjàà®&ÏBxŽNîÍ{ÒѲ€÷Xz5$œ¾…{\·æ0f‹‡/³B?7‹qVíD‰C2‹éKk[ WÁËY©@— =^ &”ðkl´´~rŽ†ìë.,í´†ã:쳑¨@Æãô·”ý ?¦ŠÈ›s¤©LZ“`Ò»Š68+,cÑ£ø,ySñ9ºT¦á’˜Ø÷æ¹ò$H9³`ÌÝ€m-2¶„,RÒVXëm›ÌZ6)³ùfSnÂäŸÀu"&gUšH‡Î®@‰ªÊJf_h¯æ¾„.QX¹š?É T1•¬±¹ÐÍ'ؽ}‹,¯ªRUB¸%$ââ·‹$èÝ2Ê¥?Ô®‚ôÕV± ÆGåR¶œÇSšÍ{x6<³Ç–…Ðb±  q„οÀ¦EÖX9&Ö
+fF²>üN™»¬²`ƒšÅaÃ<‘"ƒœàºú«†{³Œ»Š |/üUÚß逯oð¯/îEx®š„ŠJ×™`bßêDŒlÔ°3
+îœ3£4™ƒ½)$ýæ$¦¨Ï¢kOy°2®¦ã1ƒñ&£_fNaU€å–®¸B0‰ƒ(ÑýZ‹Ð2Üî(Nn~ÞÅ(˜ï‘%.–¥éô^
+IÅcôÃ)Ø性ïÛm(·ÆL·Bž†ã-àë"£ÒSGþ©»g
+ÈQK8à‘šH8õ i>ã÷H­zÄ’Ò²—ëŸy¨ÝÖ' è•Es}L®-îÏr*“ëR;ÒÏÙHù‚×Ú¸2GHH›ѨôÞ¬ÐLrjGäsž1 ‹ªí t!5ẠíÚ¯E= ’£ÖÕ„á^6†:aDT)§!㸠³±y–냥UŸŽæP‘ 'XÙ½žÿ/ûU’1ïyE>àð",9“Ì òÿ·÷4¶Ç±’rBÞÚ½VUòëïöM••Äý(ÌêVú…Û`.¢{l©§[ ÁjV¹`I,µp=2<éú•+MÈà²ÜlCLt0qŽ8|0gHμ\}dKý?A­ÝC2ÔkC¼ûþÔo~Få¡¢p…žÞ!ApôÕ†¼ìˆàçlð.$lTŽ®{“'’w›r§3[ê˜|ì3¬àU‡7^¬ŒeW«(w_&ÈÂJnnq­pE×a0øk•~µ)w B®„ŽæDSE‘§9å7˜QÁŒ€S¸cà^×$³[ïU>Ü’j:$ˆ¡ ×ømC·r™BB÷éYH\ª] *é˜Ð¨“¬K8Í•öv Û3]õNÀË|ûr×`fyFõc‘SN@üÐÏ«óL(Û@‹§mÍ^VØtuÒ'§vÅ.9xÎñ[k±8=žÈçX[f´áê °ÆǧIý9FàH¾\| ¥ùá4O-ÌuOç OG×Þœ>C-¥N_­Ó~†¤- {æ#*´í¤]§è3îok°½eÖí&ãM”fÔCê£ëOoÑp”ï[zî*ï/2nHÞOïÃ÷oŒ²áyýp1£MœaùF†4]“AM?j»,0%Ok¾Ï2
+×  ¨ÀBÖ\FlÁ,ÀVÚ>p{'²q©Ç
+H‰LŒ±
+ƒ@DûùŠùÏÛ]ïÜmÁZ,bBl0þ?h’F^1<Þ
+õœª±tžJïlÔãëôIkåçßX‘ùD;LÇløŸ4B̘Îþ jx¸°˜$ÑÎ÷.3ÛiÉÜ^gŽ± 0
+H‰LL;
+Ã0Ûu
+] Γc;öZ(™C†f/¥YZHsÈ£]Š}´#…X˜J eØÅj.Øi &ñóÀoì0>ÑO‹Ó_)¶&_˜ãßs«I)Ës–Äû —•ý²ו3fœ
+H‰\’=n1 „{B-Rü‘Ú
+H‰\O»Ž1 ìýþL?·H'jDýG'!þ_ÂɧÝÊ™‰=7ˆ“zEs'/_ d`#)ŒÒI,‘Ré%rI
+qt\`G<A ±÷$*µLØÌ&TcT^Õj.µ<ßâ¼Nñi×-ÁT}M£½  žaU3jëã·‘ëÐÛÏYfúçÌœY6Xæ}˜à®û7üƒ7ü…ãùšãJ&¢… BZ•Ceóü_H/–®MV¿Z™ƒ—œîx¼>
+~øsÇ \à+À
+H‰,RKN1 Û÷¹@CóiÒœ€5bÁž€zHÀý%’ÌÓH±ë8©;?C÷ØvP4€ IHðHÀïûxƒï±`á†\ák<=¿.øü?@ÍèF5؇q…¸Ý«îc
+& s¡‡iè´afC3˜œkÖRÀmLZÈqJ´Á$ÂÍóà¢t ÆÃZEšU%O¢ä&×~0<Û.¸ÊeåDúЫŸf”½ßaÝƼë<u¥2*yà*WA­!´»Pæ”ÒÄ›Dôv½
+f éÛÙr2éNâÒa¨•¬ÙÎÒËq¯’Ê(´&›Š'³3¤
+R1¤ÂðŒÂK¶2Ê@r+_KαƧ\KgyV­&‘·Q¦ÝÑ°z·ï3ÕåsÞùJû hK~3_Àm|Œ—|þ
+H‰,RKn1 ÛûºÀ(–lýNÐuÑEðÐf¼
+H‰4‘KN1 D÷9…/ÐÆŸØINÀ±à
+ÞPY‘ÐÀsÓ´Š­åEëEæy”îˆ*†¶*:W}½ç? M¡<8³£ŠT[®,l>:ÈXs•48jD<ô*ŽL[áÌelG¾zÉË*ÌËÖ({Ì6˜)UÈw£šÖáMžXÅÙ
+Ð<0ºÒ•¬b[8¢Húí½1w]×¾ëÚªy–6dìcy~έ}´œ?
+H‰4In1E÷>(ÂŒ}‚¬£,r€V)éHÜ_jp©U’Í+¾áÃmhbx‚‡á”º‘”Ap.†¿÷ñ¿ƒpÚBª“,á{<=¿|þpÿ­Óc¦W!G5¸\Gg®ãèGÞOyAÃêX³c.a;\ÆÁ˜Ü¹8ÊA0ªŠAYÓZ§¸fY$špŠ[A—64ÕŠ•³e†.sç|µÎDB»‚¹Âo,ûY-ý¬˜s5<„3[·3Ëy×+¥iY>eѽÄ~6n‹RæÊ{7edÚó‹Ç¾t/ öѳï$MïKIkhÏõ5>ÆK}w
+H‰\;n1 D{ž‚M‘¢(µ‚Ô†‹¸ß"[¬¾?R[ÄëJz#ñ3ó
+6&7n¨J¬eVóHªm'ó,>ð–l1$¹ÅN³Ù0Ÿ»Ô:rº”h±s4/$=˱—ìw¶Xu
+24½¸ïhì‰6ÁyZyÅ d'{ÌŒTF—‰¾%uâXh#Gq|sŸ‚°b F:‰>"óÞ÷×ô¿À›°Á
+ßø `üÓ×5Ž'|™yñH(|Fååöÿš1ê(VËLNÇhU.w8ßðt]Ÿ+~Þðø`
+H‰\“=n\1 „{BˆLRâÚ
+G5¶|s÷7AÕ.! ¤ýH5“Ï~ÃË
+H‰LŒ±
+ƒP E÷|Åýc^Ò“UÎâP÷RêRAý¨Ô¥Üápàp7ª^XÚ‹8 a74¥c“Àþ¢VÚHð¦ö>8èŠ4³˜AÎýûï°fÜJBkeÏp‹ÄóCýŒvZÇ‚aÆH#}
+H‰LŒ1
+ÂPDû9Å\ÀÍß¿Éf· ˆuHazÓ(ÄÜüh#S<ÞÌŽÁUªSÕÅÌxªQÄuëï;®|aGáÝei8ð“j¦¶EiùïßÃ!£×d†ddØè¼=1­ì–­ðØx^9cÆG€
+H‰<RAn]1Üû\àƒ Æ'È:Ê¢øj»H¥´«Ü>þ‰¬'?`<0c¿7qžƒÌ…7vž$u-ú÷³ý ¿­ÓYoíéùµÓïÿí¤2BC '[ø‘ít»þÞ.e £Ü†ÓŸvMîcÓ58iã“Ü‘óŠJŽØtk×fÍ´v¡K0ÕªòŠPy©f(Zh¼Õ“Ì ›€ÔWv²p°fƒè,¸±g7°šUÝ÷¬°šÇDºsìý€<A]mW}EÁC× µdÊòoöÈÄ?ì6¿lø¨úH1ã!fò²#RÈÜ¥{ÍC©8v-öôF¸€%w‡/9ÝǶn¦º<b…‘¤ó„
+o€5ÜWÅcjŽ·¥Žî#UÜ‹×Øλ{vLj©Ë!hÓ´}Îl%z.x`:J¶¾ÌÃ!€„WºVå£ýj/XŸ
+H‰4RKr\1Ü¿Sèƒ 'ð:•E0•xᲫœ¬rû4è¥Þb¦ù´è†¯Kœb­aÄ"Ðs
+ ß?¯ãóbÒŒÁý½_/¯ßy¼ý¹¾†tDÆdZ‰. ñ^ãùqUæãz0Øs0™­ñ2Ù
+kN@«ÜÚ»4ð¢HmF'•J2ñZЊÎM0î›ÑYª0i¯"‘ F(ÅŒKñ_‰uˆðY…ÀÎ^:&ƒS03[)áІS¦Z—O¼£¥ÆT:3Θ§;Ê#λ:vpFg͵àŽÙP¤e˜Ë=ÊÌ,)gjÄ¡Dª¦k#ƒ9U «®Öy3kXM€å[ÁŒ»|íS¾î|ú¡»»å°ëvƒ„äŸ áÆß·Ûqý Wc!©‡|ÎÒ¹òìÂRú
+H‰\’½NC1 …÷<E^
+u0eÓ‰}†RÔ÷Ê…‘»TZŸÀdÿVàÂ3|ø´ýµvŠVVÁí„Q
+î`ôÕôè2FìyÛ˜ûÕÓE8ãþU؆Ðb¶Ñ—î v$XÑvÿƒ0üÈu®®ûF;(ÏK «Ñ;ñÙõ¯Âè_†Ð°ÇÀ´ÏKÃ>ÆifG÷¯ÂBët7øiü…ÎO‡{J_ù']SÉßéðþéŸ[*~<^®P~¿ŸÒº_àãïýA,Ug•Ñ°xU—ôżÏsÉ·s~;æô‘~
+H‰,SAŽ1¼ûþ@Ì öå°mrˆ6Ò&ÿ—RØVKmUS†¢ ¿;M‘nΔSûÄ¡ÒeLë?Ú{ÿÓEFç>ðünßÞ~Œþë_ûº_¸[ÐX8\Ôúë³Uä³=LÓV2ŸýQ
+—>‰çê“zv£!«¿ÚË
+éкà²Ók¢Ý 'ÒOÜ;%z*8½NšÐz}¨€Òš²ã¾ÅÁÝ‚RÙFè¥ë’‡Q‰0jCÈFv•¼t—JK¦rÅìxð…¶aµxèÁ[,_íš^­l~tA”oïùX‰æ <|¼™C›Úqˆãz¹6’Ô©B³¼¶uÌçy°Ç)€©ñ¹¥qoh 1*›ª„Ù.—1 e;'Šs‡Ë
+H‰\Ž;ƒ@ D{ŸÂˆYö×FŠR#ŠÐS„"!î/Å ED*{žÆ3Þ@…Øcö)WP%IÅ“JE52I.©ºŒ”9cL•D 'øK&'¨Òγò‘–=ÆÃ-5©ä†v~KAO¼N(Öã¹þý:Á ?°AÀ7tÏÁÇn´TK®xóf¶ªQ/ëÏвE3‹mÆ¥h‰8­p±æ€ûŒ{èá+À
+H‰\Ž»ƒ0 Ew… &Ä$k¥ª3b(;C âÿ¥Æ0´0Å÷(Ǿ+°ˆ¡¦@Ü2.JAµB­²’‰ÇD™²‘X¬ÑÈBÄ.`vPêE9«î>ñ˜rÜ£Irÿ vßµ\{±ßW>êpÕÏeÇkû&xáVø†æÙ×g¥6– 9ãM(çSUþÇßf25 ñØ)1j«Çî6ýp›ð1`|
+H‰ª6TÈÌKI­P0Ô3
+H‰ª6RÈÌKI­P0Ô3
+H‰ª6RÈÌKI­P0Ô3
+¹PTšÁTš0Òn¹ •p‡äÀq-@€
+<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
+<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.2-c063 53.352624, 2008/07/30-18:05:41 ">
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description rdf:about=""
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <dc:format>application/pdf</dc:format>
+ <dc:title>
+ <rdf:Alt>
+ <rdf:li xml:lang="x-default">VS2010_h_c</rdf:li>
+ </rdf:Alt>
+ </dc:title>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:xmp="http://ns.adobe.com/xap/1.0/"
+ xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/">
+ <xmp:CreatorTool>Adobe Illustrator CS3</xmp:CreatorTool>
+ <xmp:CreateDate>2009-03-04T14:21:57-08:00</xmp:CreateDate>
+ <xmp:ModifyDate>2009-03-04T14:21:57-08:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2009-03-04T14:21:57-08:00</xmp:MetadataDate>
+ <xmp:Thumbnails>
+ <rdf:Alt>
+ <rdf:li rdf:parseType="Resource">
+ <xmpGImg:width>256</xmpGImg:width>
+ <xmpGImg:height>32</xmpGImg:height>
+ <xmpGImg:format>JPEG</xmpGImg:format>
+ <xmpGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA&#xA;AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK&#xA;DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f&#xA;Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAIAEAAwER&#xA;AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA&#xA;AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB&#xA;UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE&#xA;1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ&#xA;qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy&#xA;obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp&#xA;0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo&#xA;+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9N6trem6VB617MIwfsr1&#xA;ZvkBlmPFKZoNOfUQxC5GmOv+aPl5T/cXZX+cRpT/AInXMn8jPvDiR7TxnpL8fFPdE8y6LrcbPp10&#xA;szJ/exbrIlf5kajD59Mx8mGUPqDm48sZiwXeZfMmkeW9GuNY1ab0LK2FWNKszHZURf2mY7AfwwYs&#xA;Upy4Y826MSTQfK35i/8AOQvm/wAw3Etto8r6Lo9aRxQNxuJF6VlmWjb/AMqkL2NeudDpuzYQFy9U&#xA;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</xmpGImg:image>
+ </rdf:li>
+ </rdf:Alt>
+ </xmp:Thumbnails>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"
+ xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#">
+ <xmpMM:DocumentID>uuid:8CA472115A0ADE118D6EE84B58BD5EB4</xmpMM:DocumentID>
+ <xmpMM:InstanceID>uuid:1c2d0ce0-ed76-de45-80b0-35352d7d0ef0</xmpMM:InstanceID>
+ <xmpMM:DerivedFrom rdf:parseType="Resource">
+ <stRef:instanceID>uuid:472287ec-7810-4a41-84bf-8a4190c7dbcd</stRef:instanceID>
+ <stRef:documentID>uuid:5B20892493BFDB11914A8590D31508C8</stRef:documentID>
+ </xmpMM:DerivedFrom>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:illustrator="http://ns.adobe.com/illustrator/1.0/">
+ <illustrator:StartupProfile>Basic CMYK</illustrator:StartupProfile>
+ <illustrator:Type>Document</illustrator:Type>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:xmpTPg="http://ns.adobe.com/xap/1.0/t/pg/"
+ xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#"
+ xmlns:xmpG="http://ns.adobe.com/xap/1.0/g/">
+ <xmpTPg:NPages>1</xmpTPg:NPages>
+ <xmpTPg:HasVisibleTransparency>True</xmpTPg:HasVisibleTransparency>
+ <xmpTPg:HasVisibleOverprint>False</xmpTPg:HasVisibleOverprint>
+ <xmpTPg:MaxPageSize rdf:parseType="Resource">
+ <stDim:w>753.222900</stDim:w>
+ <stDim:h>198.807617</stDim:h>
+ <stDim:unit>Points</stDim:unit>
+ </xmpTPg:MaxPageSize>
+ <xmpTPg:PlateNames>
+ <rdf:Seq>
+ <rdf:li>Cyan</rdf:li>
+ <rdf:li>Magenta</rdf:li>
+ <rdf:li>Black</rdf:li>
+ </rdf:Seq>
+ </xmpTPg:PlateNames>
+ <xmpTPg:SwatchGroups>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:groupName>Default Swatch Group</xmpG:groupName>
+ <xmpG:groupType>0</xmpG:groupType>
+ <xmpG:Colorants>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>White</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>Black</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>100.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>CMYK Red</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>CMYK Yellow</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>CMYK Green</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>100.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>CMYK Cyan</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>100.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>CMYK Blue</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>100.000000</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>CMYK Magenta</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=15 M=100 Y=90 K=10</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>14.999998</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>90.000000</xmpG:yellow>
+ <xmpG:black>10.000002</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=90 Y=85 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>90.000000</xmpG:magenta>
+ <xmpG:yellow>85.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=80 Y=95 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>80.000000</xmpG:magenta>
+ <xmpG:yellow>95.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=50 Y=100 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>50.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=35 Y=85 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>35.000004</xmpG:magenta>
+ <xmpG:yellow>85.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=5 M=0 Y=90 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>5.000001</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>90.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=20 M=0 Y=100 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>19.999998</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=50 M=0 Y=100 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>50.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=75 M=0 Y=100 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>75.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=85 M=10 Y=100 K=10</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>85.000000</xmpG:cyan>
+ <xmpG:magenta>10.000002</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>10.000002</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=90 M=30 Y=95 K=30</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>90.000000</xmpG:cyan>
+ <xmpG:magenta>30.000002</xmpG:magenta>
+ <xmpG:yellow>95.000000</xmpG:yellow>
+ <xmpG:black>30.000002</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=75 M=0 Y=75 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>75.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>75.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=80 M=10 Y=45 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>80.000000</xmpG:cyan>
+ <xmpG:magenta>10.000002</xmpG:magenta>
+ <xmpG:yellow>45.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=70 M=15 Y=0 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>70.000000</xmpG:cyan>
+ <xmpG:magenta>14.999998</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=85 M=50 Y=0 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>85.000000</xmpG:cyan>
+ <xmpG:magenta>50.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=100 M=95 Y=5 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>100.000000</xmpG:cyan>
+ <xmpG:magenta>95.000000</xmpG:magenta>
+ <xmpG:yellow>5.000001</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=100 M=100 Y=25 K=25</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>100.000000</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>25.000000</xmpG:yellow>
+ <xmpG:black>25.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=75 M=100 Y=0 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>75.000000</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=50 M=100 Y=0 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>50.000000</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=35 M=100 Y=35 K=10</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>35.000004</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>35.000004</xmpG:yellow>
+ <xmpG:black>10.000002</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=10 M=100 Y=50 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>10.000002</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>50.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=95 Y=20 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>95.000000</xmpG:magenta>
+ <xmpG:yellow>19.999998</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=25 M=25 Y=40 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>25.000000</xmpG:cyan>
+ <xmpG:magenta>25.000000</xmpG:magenta>
+ <xmpG:yellow>39.999996</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=40 M=45 Y=50 K=5</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>39.999996</xmpG:cyan>
+ <xmpG:magenta>45.000000</xmpG:magenta>
+ <xmpG:yellow>50.000000</xmpG:yellow>
+ <xmpG:black>5.000001</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=50 M=50 Y=60 K=25</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>50.000000</xmpG:cyan>
+ <xmpG:magenta>50.000000</xmpG:magenta>
+ <xmpG:yellow>60.000004</xmpG:yellow>
+ <xmpG:black>25.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=55 M=60 Y=65 K=40</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>55.000000</xmpG:cyan>
+ <xmpG:magenta>60.000004</xmpG:magenta>
+ <xmpG:yellow>65.000000</xmpG:yellow>
+ <xmpG:black>39.999996</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=25 M=40 Y=65 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>25.000000</xmpG:cyan>
+ <xmpG:magenta>39.999996</xmpG:magenta>
+ <xmpG:yellow>65.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=30 M=50 Y=75 K=10</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>30.000002</xmpG:cyan>
+ <xmpG:magenta>50.000000</xmpG:magenta>
+ <xmpG:yellow>75.000000</xmpG:yellow>
+ <xmpG:black>10.000002</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=35 M=60 Y=80 K=25</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>35.000004</xmpG:cyan>
+ <xmpG:magenta>60.000004</xmpG:magenta>
+ <xmpG:yellow>80.000000</xmpG:yellow>
+ <xmpG:black>25.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=40 M=65 Y=90 K=35</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>39.999996</xmpG:cyan>
+ <xmpG:magenta>65.000000</xmpG:magenta>
+ <xmpG:yellow>90.000000</xmpG:yellow>
+ <xmpG:black>35.000004</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=40 M=70 Y=100 K=50</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>39.999996</xmpG:cyan>
+ <xmpG:magenta>70.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>50.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=50 M=70 Y=80 K=70</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>50.000000</xmpG:cyan>
+ <xmpG:magenta>70.000000</xmpG:magenta>
+ <xmpG:yellow>80.000000</xmpG:yellow>
+ <xmpG:black>70.000000</xmpG:black>
+ </rdf:li>
+ </rdf:Seq>
+ </xmpG:Colorants>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:groupName>Grayscale</xmpG:groupName>
+ <xmpG:groupType>1</xmpG:groupType>
+ <xmpG:Colorants>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>K=100</xmpG:swatchName>
+ <xmpG:mode>GRAY</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:gray>255</xmpG:gray>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>K=90</xmpG:swatchName>
+ <xmpG:mode>GRAY</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:gray>229</xmpG:gray>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>K=80</xmpG:swatchName>
+ <xmpG:mode>GRAY</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:gray>203</xmpG:gray>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>K=70</xmpG:swatchName>
+ <xmpG:mode>GRAY</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:gray>178</xmpG:gray>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>K=60</xmpG:swatchName>
+ <xmpG:mode>GRAY</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:gray>152</xmpG:gray>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>K=50</xmpG:swatchName>
+ <xmpG:mode>GRAY</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:gray>127</xmpG:gray>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>K=40</xmpG:swatchName>
+ <xmpG:mode>GRAY</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:gray>101</xmpG:gray>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>K=30</xmpG:swatchName>
+ <xmpG:mode>GRAY</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:gray>76</xmpG:gray>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>K=20</xmpG:swatchName>
+ <xmpG:mode>GRAY</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:gray>50</xmpG:gray>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>K=10</xmpG:swatchName>
+ <xmpG:mode>GRAY</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:gray>25</xmpG:gray>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>K=5</xmpG:swatchName>
+ <xmpG:mode>GRAY</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:gray>12</xmpG:gray>
+ </rdf:li>
+ </rdf:Seq>
+ </xmpG:Colorants>
+ </rdf:li>
+ </rdf:Seq>
+ </xmpTPg:SwatchGroups>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
+ <pdf:Producer>Adobe PDF library 8.00</pdf:Producer>
+ </rdf:Description>
+ </rdf:RDF>
+</x:xmpmeta>
+<?xpacket end="r"?> endstream endobj 193 0 obj [45 0 R] endobj 194 0 obj <</Filter/FlateDecode/Length 445>>stream
+H‰\“ÛŠÛ0@ßýzÜ}X|‘FÊB0d½ÈC/4í8¶’Û(ÎCþ¾ŠNØB $ÍÌiòf÷¾‡EåßÃÔíý¢ŽÃØ™®¡óêàOØ••ê‡nyPúïÎíœåñðþvYüy7§l½Vù¸xYÂM=múéàŸ³ü[è}Æ“zúÕìŸU¾¿Îóöã¢
+Uת÷ÇèK;mÏ^åéØË®ëÃr{‰gþíøy›½ª—ÓM½¿ÌmçC;ž|¶.âW«õ6~uæÇþ¿u³âØáØýnCÚ®ãö¢¨Š:Ñ´‚èÚBM¢²€Þ¡ú€*h›¨2‰L YHC2Ð+d¡ ä j1Ô¢ÉnÈ®ÉnÈ®1Œ4Ù…ìZ 
+¢¡M-B-zI"CKCKCKCKCûˆ‚ŸÅÏàgñ3tÞÒyƒ­Å6j&Ú@ÐÄ­XnEè‹¥/B_,}nÅr+B—]ü~‚ŸÃOðsø ~?ÁÏá'ø9ü?‡Ÿàçðü~+vn¨³y8Xüã#~¼ÖûsŽS§>g¥»†Ç$fšûd £ÿœÞyšU<uÿe
+H‰\”Íjã0F÷~
+-ÛEñt¥‚!IÈbÚ2™y
+¢AKƒBƒ–…-
+ Zt4(9Œ#‡‘`ä0ŒF‚‘ÃH0r F#ÁÈa$9ŒVw#‹q…ûoþ6qvÕ×ĵ—â°¥OSv›¯~ð_ÿÓ8©xêöÉþ 0
+H‰\”ÍŠ£@F÷>E-»ZuoUB N ‹ùa2ó
+™i ѠР%µÚѠРÃApp4(4èhPiÐá§ø9ü?‡ŸâçðSü~ŠŸÃOñsø)~?ÅÏá§ø ©•ÔBO!‹'‹Å“EÈâÉ"dñd²x²Y<Y„éþc:ízÚÚõ´+´ëiWÉéÉ©´ëiWi×Ó®Òn ]Å!à 8‡€ƒâpPŠCÀAé3Чb0RRR/8·ÞÎöÇüøÄÓ&2Ÿû£¾cZóºšwÆc[´]üÜhC?˜têñËþ
+0
+H‰‹A
+€0 ïyÅ~À˜Ö6õ¢gшzÑ
+¾Þæ2#8©Á™©Sê5±†eMMäÐãÝé ‡„½FØâl¬*JÖ 'æÏÒ‹v¼ÃM3ý
+H‰\PÑjC1}÷+üÚÑ×ÁØséÃú~ÙVX;hûÿ0“;Øv DñxŽ¹©Ulfd¥â¤“ ÜH
+£8IK¤T¼¢D6iB!Ç6… h!6ÏB¥ {kjcT^§ÕlêIÿ“cĦœ·¦j«õ>ô5xšU L«ÝÇk'Ó1oS¸Ìe¦~Æô™ËËäGÜì¾À+~A!QǼÙpÍ?aÿr,øñ€›¸à •"w–ÚÓÝßÌðþïpƒd "b#w))…%ÏîNÏlšð㻎\®ðtÂýñ\ðqÆçà
+H‰<ÌA
+ÂP Ðý?Å\Àt’ß6þ½èZ,x
+H‰\R»n1 ìõúÐ"Å—ZkÃEÜ»ˆ‹u
+A9cw“஋dÕ4£”­¿%Ž"´ô Öx¬F̘€NCõÔ_G3¦)¾ ƒ!›ÄÌÎD¨JºÛáwKèïèÒsÔ„ñ¤éå_(憢Õ·[Qú[â(BµôL¼êñz5_/>häi×¥üßÐÛ>T \ÁN\ç|þ@~†Ïs7°Ðß;¿ØpaºÂݲ½[ÕL!ò7Dz·ÄQ„Ö6ý õyî&ۆ׫úÖ~õ?í³þ»=<½àóÕ~ð %C˜³£—I¶öÿéªlB+hßñhÎÁˆô£=¾ö‡—÷Ñ¿ÞûÏ×þÜžÛ_
+H‰ª6Ô3
+©É
+Å¥Iu¦
+ºèf (4*äË›Pi3ÒS!ªåÆ0•FŒ4‚[^_ P `
+H‰ŒA
+ƒP D÷9Å\ 1ÉÏÿè¾Øu©ÐuUKu!ôôMÌ0áñ+u·‡`=H—VQ{ã¢ÜX½ábÂî†}¦…¾ ¹jS¼À£Š!óšÌ[P1Ãt"ÝšnÁôBÄé€Jö/_;ºñ-¸~è÷`
+H‰\T;n1 ìu
+] ´ø‘Hµ‚Ô†‹¸wë
+ ˆt…2ôâh¢ÄË‹]˜T
+e˜ È2—[¤ü‘8g«|,³3Êâ‰j'û
+ ªykâ¸'<$²••0¢PŸò;\j|†OËð¹v íD²ç©¾Ã¥¶Uxl®h4âL›O¤…|ÄMû…K«ëlÔül4¼| ÷W¼ Ü®±]è1ß<pÆitÙ°”\4§`2ì€ïDM$ !õ.8eY¡Æ1ä­ ÑËÔsê÷äNcEY¯lt£¥—)]™˜µ²•c»µu›ÏòÕWW'XSíÛ†~Ó–üŠc½ôÄÑLÈøôõÚ"ž9W#‡)¶Q”ÖŽK÷.ÄÑ&×z$1ÑÏ„+Ì5ÿ%«™TøÌá]è±GÙ¾c9–@û~.¡”Z ,ñN÷/Ä‘„YTù¼óç¥YùíV8Ë]’õ_èg½ä_ιйíÐÅ OñHsòJ˜¹öâHC¼àFv‹Úç¼Rò0˜¹ó„{Ä‘„™ r9Î+)§p¹¡ÞÚ¯þ§}¶Ñ·§Ÿ/xümÈ;$öcÿų\Þÿ‡(ÎÃ] ·“k€¥øhß_ûÓËûèßû×þÜžÛ?
+H‰<ÌA
+ÂP Ðý?Å\À4ùMòÛ}ѵXð
+žÞd# a,¥;]ËV´Qe…5'3…‰:Riôë½<Êç¼'o}"Öa|´4W¼B1U7ìÈmÉmÆ|CÄyƒpþoV+ºã“1½Ë9î'À
+H‰\’KN1 D÷9…/€Iü‰-bXÀÁŒDƒ4Ìý%ìdÓ¨ݯÔ*§"ÝÔ:VøL¡ÛAq˜A x_X)‘Mtbx-ÿ„­hÅ&id7TÏã­Ñ6¬#ì{Þ~¹;Vó,Ç.ŠÌÄj"£§{Ï[Ç¡<¹“f±®“ÔãMHíòs—¬½¢8£p A°zô*Øǘè“(*µÙ‹¨§/„ßP9Ëg[¹4¦9‹ð{”ËãF4ÙÓ¿¶)P.£bm> |ÁL$Plbãqñ_ ÓÏÚÖ®{DÐÑuE'£å82ƒ¤Wÿ{aÎo¼îqÏ…å^¹G†c&½0ü{aK® ‘%/$ëð尿–gø*ÖóQnž*Îå¦uv†ù¢(àÀáÖÝW‡ï·ò^Na?¤±¥±Ææ͆Îo®8s•–×1ÃŽ{i™Àg¹{Û§c…óî_à±<–
+H‰ŒÁ
+Â@ DïùŠùÓdÝݬwѳ´Ð¶'ÛCÁ¯7)3ÌðÁBݽ,ieK(Ö¸eÃÑNªÜÎëD3}&g”j,ªÕKƒ3æÍ™o§„S-Ø××‚á ·Ý Ã•È_L+ºÛKpýÐÃõ`
+H‰d”MnÜ0 …÷:….E$%RÚ(º²höAÛ
+QþÕp wß×ü+Õ"X¸ã_Ê?Óý—Çš¼¥;ÂöHŽ/Æ Â&±i?ý§ù÷·ô=½&8ÜHnÄyÚdÅû­âs÷Ù°^)–Ó·QgqKŸžòýãKÍo/ùóS~Hé¯
+H‰ŒM
+ƒ` D÷9Å\ ñKüþº]K…@Ú®Ú¢.Oo"ÞËB’9¶HYøn­Â1WH`-ë‹žøQÀ‡šáaµ]¸ eÕ‹®7ÃÛ¨Ž¿i!ssÂwÄ€i†Åni³ïÞ‡O+šþÐýi´;
+H‰\ÍjBA F÷yŠ¼€qò3If[(]‹‹º—Ö ½¬ï÷Š´2‹Ì9ä !`'cÆBÂÏáB‘†3pR°/B…I¬/Ô\Q”†Y!SFàžÄ êä¦ETríÍ°ÐRVÔsäŠî5ðIÌqßx† Þñ®ï ¶oû†§+lØ5—"4*£Þÿý>à.?Ý‚| J’›¨"“õ–#ue³:Ɇ©{z0j 1–4¹/”½×±Žgx9àv?5¼NøzÀìàW€
+H‰ŒA
+Ã@ ï~…>PÇ»‰½ë{IÎ¥> ¤9µ¥É!×w@i`¥nº Ö’q_¡E¹*gÇÅ9km¡ýb×!C͸؀Ângq âOc„³)ÄiŠSÁüD³£æI"Ϩ6tã[pýÒ­é/À
+H‰ˆÁ
+€ ïûï ¶UqÓ{Ô9ú€ˆNæAèë3f`2eàUY¥G`Ùz‡g§e¶êQAÝ´ŽB‚´¡©6!ùûþëA7ž‚ᦹñ 0
+H‰\“ËN$1 E÷ùŠü
+:ÆØJࢊù9ù˜n\áâ´¬à0cµyZû{¦]¦]Çn×Ñ'®d Ë¾ aáPÃЪ#•*ÈËʴo|ì,ƒ—P« `½G9J¹É(cXoZj C„; ‡ 2Ä„^د®[qÖ›˜lÿã(Þ›Øý›ýÄGð:Ö$A!öìR†]åwºŽpLÁº6Dîá'^¨ =ß•~ ™õiÔ7D£z$ÝÑ&ån|\xDôtP{ T‰êQã&QqfßËŽì’|VŠ5—F¾µ€5EÍ&M8|ôWÂáy~lôT-oŸþá1H.ƒ¢ù³`åwËã«âqçì·`²)øl[Dk}½—w&6I£x.i¾Dº6³Y7n€¹Öbqyí5.ÿ.Ì÷`?®¢+ç«dÏéw~OPØÚµo³Ïg̯éöþò¿¯tƒÂsümoÏL*íô$ùóOú›>’9܈nTË Š6)°ÏÍÑ, Z› §•¡Z1oéî)ß>¾@þzÉ¿žòCzHÿ
+H‰‹Ë € ﯊m@xü)ÀèÙHF9#H¬^¸Ì&›F&¹îŒ\I{¡½… QX t4˜¼0F£œtÑK܇†‘¨‘0ÒŽÖT¡xì7®¹ÜŒù¡~
+H‰\‘=nÃ0 …wž‚(C‘¢(­ŠÎA†f÷PN ÷JÊCêLÒ÷dþ¼çH#iÍ+IéxéTMwÁ•IL•ª£
+•š§t\àMØR°1¹qCUb-³šGRm;™gñ·d‹!É-všÍ†ùÜ¥Ö‘Ó¥´@‹£y!éYÞˆ½d¿£°¥ÀªS¡éÅ}GcO´ ÎÓÊÜ@y²Ç,ÁHet™èá+P²Q'Ž…8rÇgîSV ÔH'QÃGdÞûþšþx6XááŒ?púºÆñ„J^:oÈTUGÿº½^3Æ^›YŸÉ2Z?¹Üá|ÃÓue|®øyà \àO€
+H‰‹1
+€0û{Å~ÀË]BíEk1?µQ Á×›kf``;¹qì…Ì)fÄ”9k5KP4žÛNq¯´ÑEÂ>E¼°Gí”oÊógé†AÒD¿
+H‰\’1nÃ0 Ew‚¨"‘¢D®ŠÎA†f÷Ð N ÷J‘.jg²Þ“Iˆ_z$¹ó
+,éE¬Spí.Diô‚½:Ê´v^¿kÙ„ìçÚiBΖ¬±À±‡U£ÿ^XuÉÚÕ…ÍñÄr˜ãñ„"¾Ö6‡;²E#y”¯Ãö—·‰ÈIzõ½ºö`¶óàYر©c¯#Ê÷Âë b°{RÞPêDñFQq±5Nß-ÃAÛK…—‡±¤/øITà;>/öy&Ì•íȪðV3!unxXþÿ0›.¼ 0¤j±ë_îéý
+§Ë­ÀóW8§sú`
+H‰<ÌA
+ÂP Ðý?Å\À4ùMòÛ}ѵXð
+žÞd# a,¥;]ËV´Qe…5'3…‰:Riôë½<Êç¼'o}"Öa|´4W¼B1U7ìÈmÉmÆ|CÄyƒpþoV+ºã“1½Ë9î'À
+H‰\’ËjAE÷ýõ.u=»zY-⽈mÈ8 ûÿ!U=ÂÖÁÌœ‹nßzôµéÄ6»*¼•àc¦`8Ç€D ß±s!O^,piß„­YGÒ2(J H´¨ãñö™ö#oŸì}DÅIh¢¡ÈȽP0Ê}ä­ià4Yìlæ¶È"ߌL·?»VöQÈpAJA±GÖªès. ÉN iÕ¢å?
+éhRñUV͇ðêeÌôGÆÕq3‹ôò…m \ÃèØ)–AnXIÔ±dÞüwÂò‹Ñ>kÏ8†í«ÓIÕŽ®Åæ¦÷úÂêÈ~X¼Vs)Ϲ6½cúÂVßr—²#‡o7íÒ~ÿÖQ4 Ÿä°üm§_ç/í\B`½8Ã$O²Ã—ÃûŸöÜ®-e¤2¡u¥é =w¬Ù• SÝ›œœ™§|yk?žàt~íðñ
+?Ÿà±=¶ÿ
+H‰<ŒÁ
+Â@ Dïûó¦I6ÙÝÞEÏbÁíIÅöPðëÍz70<†1§áxfÌkÊ™¬Œð¦”e„:±)vbäV±ÜÒ=½ÿR©T«@Zs„còs.x†Å¤Å±¡KÿfLW¶
+H‰lAj1 E÷:….Å’,ÙÚJ×!‹f?´è¤äþPyZŠöX__ºB52«h]H9ð¤Â ˜º;jMÞÐZ§R+ªRõH©Äq‚'°üB¢²Ogó4n6zxÊžyøK²QÛ Á–™ÿÍ)lt0' I¬hB¦m ב\~'œà ,0Ã;~CÁí|ÁþíXð|‡»vÅõ’ôê¨ÒÜ^Ž·ø„k–ŸG!B®™°ZŽ¼:îX¨k O]sŸ™ÎÒbl$$wÁé/'Üç‚÷_Ox€ü0
+H‰TŒÁ
+ƒ0Dïûóën6‘ä^Ús1àˆõTKõ øõ&xQÞÀðÁDÍ«L+™ã"BÙ|‚SVï¡ÆÑ–‘>ô?twìâô˜‹%ìÚ€ õZëµ (Ø
+W¨ÔÞë´ y~½K
+H‰lT»n1 ìõúÓâC”ØR.âþØ@Öÿ?¡ÎÙó.‚+Vi$r†¼·bF<¹ö)¤õµ˜ÐÄLsTcRé+’æUà@ØHU륜€­¨ ú$C«æ-¸}MžUÇ&BŸ‹6<èƒÂ¢Z#fð}’u¤Ó‰ór¦ŽÛ.åo¥7OÀ¨gŠmGÔ]g2W1æô°%ÐE¯Å·H‚˜,mZàÛhÆØ¥º”°•—ò½þ.­^¿Êý·ÇVŸßË{–·>BPB†÷ÃÊëŸågyý9‰œDžHhD™™Ø£ {ƒ#K»c<íÈÙ¬š“Iz•o¨MO“^Ë—§zÿøÒêûKýúTÊ^I›{?ùÞl¬ZÈý*EtY¡ò
+‡§s'`K`‰<&Z…Óª6—ì Ó4B)æ2î,å•ç}“ÎýÛ‡ðFnzµ58…?ÛœœØÅ”åBGI>Qãèâhm¬&RÈÊI­kIßµ›àÈêlf÷@»’|PR…ºùjù s^w
+2 2 0000091193 00000 n
+0000139097 00000 n
+40 1 0000139155 00000 n
+42 1 0000139665 00000 n
+45 1 0000139928 00000 n
+47 1 0000140364 00000 n
+50 1 0000140622 00000 n
+52 1 0000141066 00000 n
+55 285 0000141341 00000 n
+0000141517 00000 n
+0000141651 00000 n
+0000141789 00000 n
+0000141918 00000 n
+0000142947 00000 n
+0000149563 00000 n
+0000155304 00000 n
+0000160105 00000 n
+0000175707 00000 n
+0000175764 00000 n
+0000176129 00000 n
+0000176494 00000 n
+0000177113 00000 n
+0000177577 00000 n
+0000178093 00000 n
+0000178637 00000 n
+0000179111 00000 n
+0000179568 00000 n
+0000180082 00000 n
+0000180787 00000 n
+0000181153 00000 n
+0000181519 00000 n
+0000182065 00000 n
+0000182681 00000 n
+0000183291 00000 n
+0000183959 00000 n
+0000184386 00000 n
+0000184818 00000 n
+0000184891 00000 n
+0000185078 00000 n
+0000185145 00000 n
+0000185240 00000 n
+0000185333 00000 n
+0000185576 00000 n
+0000185629 00000 n
+0000185711 00000 n
+0000185824 00000 n
+0000185852 00000 n
+0000185925 00000 n
+0000186113 00000 n
+0000186208 00000 n
+0000186310 00000 n
+0000186383 00000 n
+0000186456 00000 n
+0000186645 00000 n
+0000186721 00000 n
+0000186818 00000 n
+0000186914 00000 n
+0000187170 00000 n
+0000187225 00000 n
+0000187308 00000 n
+0000187382 00000 n
+0000187456 00000 n
+0000187530 00000 n
+0000187676 00000 n
+0000187753 00000 n
+0000187850 00000 n
+0000187963 00000 n
+0000188219 00000 n
+0000188274 00000 n
+0000188357 00000 n
+0000188431 00000 n
+0000188505 00000 n
+0000188694 00000 n
+0000188791 00000 n
+0000188902 00000 n
+0000188976 00000 n
+0000189166 00000 n
+0000189263 00000 n
+0000189364 00000 n
+0000189438 00000 n
+0000189512 00000 n
+0000189586 00000 n
+0000189660 00000 n
+0000189734 00000 n
+0000189923 00000 n
+0000190020 00000 n
+0000190126 00000 n
+0000190200 00000 n
+0000190381 00000 n
+0000190478 00000 n
+0000190570 00000 n
+0000190644 00000 n
+0000190718 00000 n
+0000190907 00000 n
+0000191093 00000 n
+0000191283 00000 n
+0000191471 00000 n
+0000191663 00000 n
+0000191851 00000 n
+0000192040 00000 n
+0000192229 00000 n
+0000192411 00000 n
+0000192599 00000 n
+0000192787 00000 n
+0000192976 00000 n
+0000193160 00000 n
+0000193343 00000 n
+0000193533 00000 n
+0000193679 00000 n
+0000193783 00000 n
+0000193886 00000 n
+0000193989 00000 n
+0000194086 00000 n
+0000194183 00000 n
+0000194280 00000 n
+0000194382 00000 n
+0000194503 00000 n
+0000194610 00000 n
+0000194707 00000 n
+0000194804 00000 n
+0000194907 00000 n
+0000195053 00000 n
+0000195151 00000 n
+0000195258 00000 n
+0000195360 00000 n
+0000195457 00000 n
+0000195564 00000 n
+0000195661 00000 n
+0000195764 00000 n
+0000195861 00000 n
+0000195958 00000 n
+0000196104 00000 n
+0000196202 00000 n
+0000196300 00000 n
+0000196398 00000 n
+0000196495 00000 n
+0000196613 00000 n
+0000196734 00000 n
+0000196850 00000 n
+0000196956 00000 n
+0000197077 00000 n
+0000197175 00000 n
+0000197278 00000 n
+0000197424 00000 n
+0000197522 00000 n
+0000197620 00000 n
+0000233866 00000 n
+0000233892 00000 n
+0000234407 00000 n
+0000234433 00000 n
+0000234962 00000 n
+0000234988 00000 n
+0000235579 00000 n
+0000235695 00000 n
+0000235822 00000 n
+0000235949 00000 n
+0000236066 00000 n
+0000236183 00000 n
+0000236300 00000 n
+0000236419 00000 n
+0000236531 00000 n
+0000236648 00000 n
+0000236765 00000 n
+0000236892 00000 n
+0000237009 00000 n
+0000237133 00000 n
+0000237257 00000 n
+0000237374 00000 n
+0000237491 00000 n
+0000237557 00000 n
+0000237580 00000 n
+0000237918 00000 n
+0000237993 00000 n
+0000238474 00000 n
+0000238547 00000 n
+0000238750 00000 n
+0000238779 00000 n
+0000238876 00000 n
+0000238994 00000 n
+0000239108 00000 n
+0000239137 00000 n
+0000239203 00000 n
+0000239226 00000 n
+0000239589 00000 n
+0000239664 00000 n
+0000240290 00000 n
+0000240363 00000 n
+0000240552 00000 n
+0000240615 00000 n
+0000240712 00000 n
+0000240787 00000 n
+0000241017 00000 n
+0000241072 00000 n
+0000241155 00000 n
+0000241221 00000 n
+0000241244 00000 n
+0000241607 00000 n
+0000241682 00000 n
+0000242470 00000 n
+0000242543 00000 n
+0000242730 00000 n
+0000242827 00000 n
+0000242941 00000 n
+0000243007 00000 n
+0000243030 00000 n
+0000243393 00000 n
+0000243468 00000 n
+0000244067 00000 n
+0000244140 00000 n
+0000244340 00000 n
+0000244461 00000 n
+0000244590 00000 n
+0000244707 00000 n
+0000244773 00000 n
+0000244796 00000 n
+0000245159 00000 n
+0000245234 00000 n
+0000246048 00000 n
+0000246121 00000 n
+0000246318 00000 n
+0000246415 00000 n
+0000246533 00000 n
+0000246599 00000 n
+0000246622 00000 n
+0000246980 00000 n
+0000247055 00000 n
+0000247507 00000 n
+0000247580 00000 n
+0000247776 00000 n
+0000247873 00000 n
+0000247991 00000 n
+0000248057 00000 n
+0000248080 00000 n
+0000248441 00000 n
+0000248516 00000 n
+0000248838 00000 n
+0000248911 00000 n
+0000249611 00000 n
+0000249685 00000 n
+0000249885 00000 n
+0000249982 00000 n
+0000250100 00000 n
+0000250216 00000 n
+0000250282 00000 n
+0000250305 00000 n
+0000250641 00000 n
+0000250716 00000 n
+0000251206 00000 n
+0000251279 00000 n
+0000251467 00000 n
+0000251564 00000 n
+0000251682 00000 n
+0000251748 00000 n
+0000251771 00000 n
+0000252109 00000 n
+0000252184 00000 n
+0000252705 00000 n
+0000252778 00000 n
+0000252967 00000 n
+0000253064 00000 n
+0000253182 00000 n
+0000253248 00000 n
+0000253271 00000 n
+0000253634 00000 n
+0000253709 00000 n
+0000254317 00000 n
+0000254390 00000 n
+0000254587 00000 n
+0000254684 00000 n
+0000254802 00000 n
+0000254868 00000 n
+0000254891 00000 n
+0000255256 00000 n
+0000255331 00000 n
+0000255806 00000 n
+0000255879 00000 n
+0000256078 00000 n
+0000256199 00000 n
+0000256317 00000 n
+0000256383 00000 n
+0000256406 00000 n
+0000256763 00000 n
+0000256838 00000 n
+0000257630 00000 n
+0000257703 00000 n
+0000257902 00000 n
+0000258088 00000 n
+0000258275 00000 n
+0000258372 00000 n
+0000258490 00000 n
+0000258587 00000 n
+0000258705 00000 n
+0000258826 00000 n
+trailer <</Size 340/Root 1 0 R/Info 55 0 R/ID[<9ACF01BAB32244F184A6B6A3D6DB10C2><8710EA5F576C4886B943D8D96EC67FE1>]/Prev 89924>> startxref 258944 %%EOF
+342 0 obj
+<</Type/Annot/F 132/V 340 0 R/DR<<>>/T(Signature1)/Subtype/Widget/Rect[0 0 0 0]/FT/Sig/P 59 0 R/AP<</N 341 0 R>>>>
+endobj
+340 0 obj
+<</Type/Sig/Contents <308226FB06092A864886F70D010702A08226EC308226E8020101310D300B0609608648016503040201300B06092A864886F70D010701A08219EA308208553082063DA00302010202040100390A300D06092A864886F70D01010B05003063310B300906035504061302534B3113301106035504070C0A4272617469736C61766131133011060355040A0C0A446973696720612E732E31173015060355040B0C0E4143412D3330372D323030372D323111300F06035504030C084341204469736967301E170D3132303930333133323230325A170D3133303930333133323230365A304D3125302306035504030C1C44697369672044455620746573742034202D2050534555444F4E594D310B300906035504061302534B311730150603550405130E494443534B20535039383532373430820122300D06092A864886F70D01010105000382010F003082010A0282010100851B8BB0B1402455ADFAC35792DF63E2EA18CBDEAAF9C20DA4CE5F9F21CA9CAC1B7652D30E6B14295CF13C4D7E1AADDD7A6A09220A5CD38B192EDB2061BDF2AFA1632DDC6C1E42E4387A9691AC05DADF4DC7C3D61033A25FA2B6C3B7B21BCEDC91D1EBD14B9AB926193958D209BA9F406E22722BE0A3EF391A9141BD640DDA621B5FE1D680B5C2FD533E71AD1B9CCDA8206B6C43497412688D31D25B8E0D9C4591A830244A1C2EA055BA475D133DF18AC30B0A3955F3CBFB8C3B226A6C849882FC5CC8415BC7EA070F9D4291280C954EE9996A8D305ACB4A14650E7C69A32719E46B96103E3A19DD1954E25DC71F314F0CAAC00E40544357956E936FDDE049DF0203010001A3820425308204213081A906082B0601050507010104819C308199302406082B060105050730018618687474703A2F2F6163612D6F6373702E64697369672E736B303806082B06010505073002862C687474703A2F2F7777772E64697369672E736B2F616361322F636572742F616361325F64697369672E703763303706082B06010505073002862B687474703A2F2F63612E64697369672E736B2F616361322F636572742F616361325F64697369672E703763301D0603551D0E04160414EB00C2F5304C9E038D89D21C5626BE7AC97E8A393081980603551D2304819030818D8014157F5F5F08692AC67003A1FA516A4DAC8D5F9853A171A46F306D310B300906035504061302534B3113301106035504070C0A4272617469736C61766131223020060355040A0C194E61726F646E792062657A7065636E6F73746E792075726164310E300C060355040B0C0553494245503115301306035504030C0C4B4341204E42552053522033820200F4300C0603551D130101FF04023000308201380603551D200482012F3082012B300F060D2B811E9199840500000001020230820116060E2B811E9193E60A0000010001030230820102303006082B060105050702011624687474703A2F2F7777772E64697369672E736B2F5F7064662F63705F616361322E7064663081CD06082B060105050702023081C00C81BD54656E746F206B76616C6966696B6F76616EC3BD20636572746966696BC3A174206A6520767964616EC3BD2076C3BD6C75C48D6E65206E6120746573746F766163696520C3BAC48D656C792061206BC4BEC3BAC48D6F76C3BD2070C3A1722C206E61206B746F72C3BD20626F6C20767964616EC3BD2C206E656DC3B4C5BE65206279C5A520706F75C5BE6974C3BD206E6120706F6470C3AD73616E6965207072C3A1766E65207AC3A176C3A47A6EC3BD636820646F6B756D656E746F76306E0603551D1F046730653031A02FA02D862B687474703A2F2F7777772E64697369672E736B2F616361322F63726C2F616361325F64697369672E63726C3030A02EA02C862A687474703A2F2F63612E64697369672E736B2F616361322F63726C2F616361325F64697369672E63726C300E0603551D0F0101FF0404030206C0302206082B06010505070103041630143008060604008E4601013008060604008E4601043081CA06052B240803080481C00C81BD54656E746F206B76616C6966696B6F76616EC3BD20636572746966696BC3A174206A6520767964616EC3BD2076C3BD6C75C48D6E65206E6120746573746F766163696520C3BAC48D656C792061206BC4BEC3BAC48D6F76C3BD2070C3A1722C206E61206B746F72C3BD20626F6C20767964616EC3BD2C206E656DC3B4C5BE65206279C5A520706F75C5BE6974C3BD206E6120706F6470C3AD73616E6965207072C3A1766E65207AC3A176C3A47A6EC3BD636820646F6B756D656E746F76300D06092A864886F70D01010B0500038202010099DA573FFB82BAE560A23F10BAA0E2F35369EC43749D403E4DDF2AE70F73FAAB9D38511F71921E2830CBFD694FCA2BA1466E91D7911890AC0A3CF13704286BC243DB80D6B0D89EB28F44B82A75C9B805865312AB40CFD8E4B4903F547B024DA0527EC852E7B7584ABB0538A984DBE958F98D3302AE08B59DBB2E138451A649990D5384D76CDC7CEF4CCD40C13C655E15D48CC80A8D34E86BA6C82E431D991B344A515FD9E9EC684BCA53A87E750E6143B4A0870489D24B9CFF18355F386CF532C621800BC06872ABC5F4A034F596FBD5A245C5E00BAEC88509CEB4224FD12D6EB6A18CDE7036D4018B0399689DE88E2E7D731989F08D3F24F7A49C1623D6B433D23E6275B880A50516CEE0991939ECE72C3BA5774D0BF625CF884EE8DB35E049A5070D91070DA4516EA0EC0D520726E3756E82817173CBDE72D9CB8C8DA49D6FFFACDF975EB83E14B0206DABE96855E0ACE87E273D702ABCA6B010416882159817ABA835E0E8BB9557D9E7B5793BB9AD91D8E8C0C7015785A10948C1A02C0EA9B25C45B368B7DCABD46ABF825C5B56C90B07BE36119166552DD6DE51E46C9685C1B802C3CBE9637C59B1B48E14163ADD4D7055CDEBA74C135E1773B61C275D2ACE153AC444D6A496E9642D89B9996A7F61479ED32FBF03FD61A90D2B0947AD549F266499DC9EF8EAA4D749BCFCC2F1AB02E9435E15FF5FB82ADCB6DBCE5159CF3082088930820671A003020102020101300D06092A864886F70D01010B0500306D310B300906035504061302534B3113301106035504070C0A4272617469736C61766131223020060355040A0C194E61726F646E792062657A7065636E6F73746E792075726164310E300C060355040B0C0553494245503115301306035504030C0C4B4341204E42552053522033301E170D3039313130363039353933395A170D3235313130363037323930395A306D310B300906035504061302534B3113301106035504070C0A4272617469736C61766131223020060355040A0C194E61726F646E792062657A7065636E6F73746E792075726164310E300C060355040B0C0553494245503115301306035504030C0C4B4341204E4255205352203330820222300D06092A864886F70D01010105000382020F003082020A0282020100DBAAD08F2F4A9712D5B9EB7D59DC835C8B3117F2E56E5ECE2CD2C527DC67EAB38EF0D7052197D2940D5449B11F2BEDE4309C8D609372162F0E190AB7BEFF7FC918C9E44011CD5967B3844E848FE7C446A1BB8113E15C55BB23B98747E6C89886745C0920FCC55315D877667EBB63A92DB34BCA78F81C6F64D822BAA794C1D025F38F8314AFBADB5C5D2C57E277890C1C15226897C0B8806967F700B87330B8E231D67D9512BD0DEF2BD86B4816C92776D82D957F45AC0ABD1E129160F19C588EB62EEE8D42EB5A97E48220A8D930D5E0D486B1A19E5C4233A014A1611B69A626C78E6B8BC85C199AF820636FEEC7E115C2DE9B82B95FB502E9391176AD340076DD743B264DB8C4698642AE0F081DD4484AE2F5BD5EE6CB35B0420C14611C6F1DA7B563FD63885493EE40A477D4EDA782736257822D14B7D54D4EA1E78FC880DE160C833BD8093BE725489E4A946EAD6E61E1C8DFBE70215511D5E2E45B516EB13FB0318BD502964A83FD065FA94D2D19A940E385BFB88F5DAA0EE1848DEFAD4F90725FE6A255C984BC74233F79CA404D1291FD17DD2523661DC3C779AF14F99AF9BFED1FF4391627FCF0CCB01635D537E02E2CD4B0662C0EAE18019F8FCB9EB10FB91912820DC670500D7DE572CDDA8D096277ABF596392FE0C14E08DBC687317B2E79AAFB04A9686224ED0AC2483033FFED1E23B95B14BF456EA4D6DB35E8E30203010001A38203323082032E30500603551D20044930473045060D2B811E919984050000000102023034303206082B060105050702011626687474703A2F2F65702E6E627573722E736B2F6B63612F646F632F6B63615F6370732E706466300F0603551D130101FF040530030101FF308201580603551D1F0482014F3082014B3030A02EA02C862A687474703A2F2F65702E6E627573722E736B2F6B63612F63726C73332F6B63616E62757372332E63726C308190A0818DA0818A8681876C6461703A2F2F65702E6E627573722E736B2F636E2533644B43412532304E42552532305352253230332C6F7525336453494245502C6F2533644E61726F646E7925323062657A7065636E6F73746E79253230757261642C6C2533644272617469736C6176612C63253364534B3F63657274696669636174655265766F636174696F6E4C697374308183A08180A07E867C6C6461703A2F2F2F636E2533644B43412532304E42552532305352253230332C6F7525336453494245502C6F2533644E61726F646E7925323062657A7065636E6F73746E79253230757261642C6C2533644272617469736C6176612C63253364534B3F63657274696669636174655265766F636174696F6E4C6973743082013C06082B0601050507010B0482012E3082012A303B06082B06010505073005862F687474703A2F2F65702E6E627573722E736B2F6B63612F63657274732F6B6361332F6B63616E62757372332E703763307A06082B06010505073005866E6C6461703A2F2F65702E6E627573722E736B2F636E3D4B4341204E425520535220332C6F753D53494245502C6F3D4E61726F646E792062657A7065636E6F73746E7920757261642C6C3D4272617469736C6176612C633D534B3F636143657274696669636174653B62696E617279306F06082B0601050507300586636C6461703A2F2F2F636E3D4B4341204E425520535220332C6F753D53494245502C6F3D4E61726F646E792062657A7065636E6F73746E7920757261642C6C3D4272617469736C6176612C633D534B3F636143657274696669636174653B62696E617279300E0603551D0F0101FF040403020106301D0603551D0E041604147FF13D21C2975A2E97070EB1698325FD21863E07300D06092A864886F70D01010B0500038202010036DBF912E96542B2A3B989EE7BD91E726F6FA0B027C2A2EA8A9E17101DB69AC800B88ACB904B5E32DEB593F04582D8576AEF5F0700FD097BB7AB04E3B5FF9FC9381B5356954746FF072CD36E6929D7BF654394BC5CE9DAC12F79EBB25634768D8915B85CD37759B412B087F1068E55B357B4B96D0669D4C85DA460331C22588A686DDDE7BB53DB5A560F822D79770458E2E49F8CD4351C56D556079F8BA6783B7D982B3C55DFC37E3ACEEE56C55C9E2CAF2365E8F8C6D457399D17613136FBA0B9FD3A8DE91CFD57C7485639CECD6C309C992356989A46ED850207210579B0ADFF06ABFCF48F19C76081C154CCFDD833CDC76C36F87445691BDEA2BDB55AA12726B6906085083FA1E82C9AD5DE931386960EE6F57405F82F5C3596A75AC06E2B9F3F878681B9662A1417335D14911824274245C6EB1B40EC3B6E489F519955B3BA9A159CA1FEAFC0A5B87139272A2D3D3147B9975AB9A0ABB556C2330E29B29947B4076B06E725A7902633F7505A61075A6EBD75165C222AB88C37395771DE050BFA3A32F3CD3EF516CE488457DC20F36BB3B6228036A45A15870EF2C1D86A3C78218D6410B8BD4D479CB6E58BD848DA369F4E2676CBD985C255E9AD6FD3D461D646FA05A91F90E5100C61B0CA58FAA1FBC75B2E9EEE0DB7021999D04A646EFA303C33D2608F826612A2EB3DD50401A9E4E19778469E589493C7C5D9A3497AC030820900308206E8A003020102020200F4300D06092A864886F70D01010B0500306D310B300906035504061302534B3113301106035504070C0A4272617469736C61766131223020060355040A0C194E61726F646E792062657A7065636E6F73746E792075726164310E300C060355040B0C0553494245503115301306035504030C0C4B4341204E42552053522033301E170D3039313230383132343733305A170D3139313230383132343632355A3063310B300906035504061302534B3113301106035504070C0A4272617469736C61766131133011060355040A0C0A446973696720612E732E31173015060355040B0C0E4143412D3330372D323030372D323111300F06035504030C08434120446973696730820222300D06092A864886F70D01010105000382020F003082020A0282020100BE0502722CB7A5C658D646006F68A1E9234DB62EF65413927048A2A0282DE67A00E594F98669C5C5D48A9CF848677631AE0A3EB0271777FF57399051B80A3BDD27348A9B29FB32BC674FC7D104EE109A3FB3F3BADB12BBB92F45BCE558E2A9D1E4D913242F1A13F56539A2078161FD6E787969E81F88A3284FD04FB3FA44F95D4A85E4E8288EC32BD92A5AEFFF9226D23993E20F9948C24455449A38D809ECC185CAE672D8D76BEB658A31901AA474506A2AD3BF84D482A0474D345419E737CA50CDDEB9A21E67ECAC257D91AC05645D04F2A32A54180D2991D2EFDDBC04E27CB713E8F9167D1F3AF9F9ABE261E7BA211F0438ADA3B555973C5B1FC3C191F513AE1610C4FACCF7FC6F65BBC19AD870B005E227DA3B12CA375C9E3908CB2F4368FB5B0B8DCEF9E3473145647B3B9B9A9AB7C646FA892D893170E058458AB446D4CA7765DDE1AC44E483FD0D35C34E56E9FA740C98930A4C68FEFCDA5690B50657903B57C4C4999D3C48A4B7D4F97119F8033C9FB4ECDF367866391690410F300783F70F6D416BD1A87DF3DD9A37767872799AAF74A5C759EB7DF268BB01868F1D1B61A2B12429B08EB5181EBF3842B7ECD002DC2500DCCEB426B2ECDB6BE784394CF65807D29938EE7711EF1666B0847F519D9141C15D89E276CAD3AAAF3C1E1668DE5ED4FAC1B980336F055E887FBE9DF33257C0FBA2EF04B0070BAADD4AA39B0203010001A38203B2308203AE30120603551D130101FF040830060101FF02010130530603551D200101FF044930473045060D2B811E919984050000000102023034303206082B060105050702011626687474703A2F2F65702E6E627573722E736B2F6B63612F646F632F6B63615F6370732E70646630420603551D21043B30393017060D2B811E91998405000000010202060604008B300101301E060D2B811E91998405000000010202060D2B811E91998405000000010202300F0603551D240101FF040530038001003082014006082B06010505070101048201323082012E303F06082B060105050730028633687474703A2F2F65702E6E627573722E736B2F6B63612F63657274732F6B6361332F6B63616E62757372335F7037632E703763307A06082B06010505073002866E6C6461703A2F2F65702E6E627573722E736B2F636E3D4B4341204E425520535220332C6F753D53494245502C6F3D4E61726F646E792062657A7065636E6F73746E7920757261642C6C3D4272617469736C6176612C633D534B3F636143657274696669636174653B62696E617279306F06082B0601050507300286636C6461703A2F2F2F636E3D4B4341204E425520535220332C6F753D53494245502C6F3D4E61726F646E792062657A7065636E6F73746E7920757261642C6C3D4272617469736C6176612C633D534B3F636143657274696669636174653B62696E617279300E0603551D0F0101FF040403020106301F0603551D230418301680147FF13D21C2975A2E97070EB1698325FD21863E07308201580603551D1F0482014F3082014B3030A02EA02C862A687474703A2F2F65702E6E627573722E736B2F6B63612F63726C73332F6B63616E62757372332E63726C308190A0818DA0818A8681876C6461703A2F2F65702E6E627573722E736B2F636E2533644B43412532304E42552532305352253230332C6F7525336453494245502C6F2533644E61726F646E7925323062657A7065636E6F73746E79253230757261642C6C2533644272617469736C6176612C63253364534B3F63657274696669636174655265766F636174696F6E4C697374308183A08180A07E867C6C6461703A2F2F2F636E2533644B43412532304E42552532305352253230332C6F7525336453494245502C6F2533644E61726F646E7925323062657A7065636E6F73746E79253230757261642C6C2533644272617469736C6176612C63253364534B3F63657274696669636174655265766F636174696F6E4C697374301D0603551D0E04160414157F5F5F08692AC67003A1FA516A4DAC8D5F9853300D06092A864886F70D01010B05000382020100D96925EA8ED9E68FF70B544536BE5CBC6C5723924715241DDEF671BA9C14B2370A52FC8320D99E5831C712462CA75E33C248D3FEE20E273305B764C5C927E4C18D70E5522C14A1C79D68EDE3C45306F01144008DEA89111E72639CA7767077CD992E95287FCA9F5ED856B6A95700113DEDD0385C8C9F6EDD0388DBCFD379A844B6BC82DC1048DED0C8B154342AE544DA07E43B240E74691C9CC227884DA5C6A084D2E99359841F38DBF0C3EBB8ECE152D1226FF582D2D8EB82A6CCCFD737393D11D629224B42E853E22C35A420A5756DFD44E44ED61E5FEB318F576CB6542E5795B59F3035129DD4EFAD31AAE6BBDE982F6FEA312ED9BED107D9908221A423F174845045F6C6FE78A08EA9AEC1D17B20E8694E6D02CCD1F1B6F23B5D90D4AB7AF26E44EACD9E2B167373AAC24D50D65D90112EDD3BFF7ED8C7C853752C4B8B9FA3D21C777E6CC23C51906FEDD2146280622F543D00B021FE5DF4C1C8A753F6481B6986C3052CF0A5FB7F0AE0F8D48BD0F70A6AD41F958CFDE9B27B21C295481FE27D25CE540C0B3AAF5EFDE57F7D77FF163A17B4A630DC5701C7A5C0E4D25FBFF36CE488B4012CF43B14AC0B79F4D48C7EB67519DF59AFD995D817617498408DC4F6140857E2185C88830EE9B8928E56427DDAC94393E1CE446C742C6CC2287DA835ED1A17CD5F5A48CC894E6E44708414D56C90D7DC120A5A32AF3686B1304D31820CD730820CD3020101306B3063310B300906035504061302534B3113301106035504070C0A4272617469736C61766131133011060355040A0C0A446973696720612E732E31173015060355040B0C0E4143412D3330372D323030372D323111300F06035504030C08434120446973696702040100390A300B0609608648016503040201A081D8301806092A864886F70D010903310B06092A864886F70D010701302F06092A864886F70D010904312204207F16625DD84186495A4CEDFF59B05A1A008D27DD56874F16B48D9F3FE44B205D3037060B2A864886F70D010910022F3128302630243022042015C36FE3F117921FADCF4EDCBE9EECCA20D81C74ED08C3D2DBAD43087FB1EEF43052060B2A864886F70D010910020F31433041060E2B811E919984050000010A04000C302F300B060960864801650304020104207A4C03779BD2C51BCCBD73668A3C30110D7451D9222B4732681866EAEF961E65300B06092A864886F70D0101010482010008916912CE6ADBDB79AC15589EEC96CEDCF2ADCF0370329BE10FDAEB7D2B7F03F6025CF89FD1E406AF4365C368DF9D411C89B0D6EDB435159FB77D9CC2C3C11A15BFC5EE6A022723F89980C615DD5DF3FDD70A158224AD8A9AB7E82A7979585796127E7AB64ACE2BA94391FDAC151071A16A8306B47E48849750908EA396A531178D998A0723E8850ED101EDCC5D2F6CB1929DE5AE563E2DC87920D22FABB3E5F9EF03451F8D6EFA70A23E2D777607EB6FDD113DF4D902E5DDA8404E6D3D364B5DCF4D58F7B84CCFE0745CAD6463D595E6034C6CF10A7C9334702838EBD2728C22E4ACF9F24B1F153ED3C67B898BED04D6A9FB215F61A5160162CAAE38F68B3DA1820A6630820A62060B2A864886F70D010910020E31820A5130820A4D06092A864886F70D010702A0820A3E30820A3A020103310F300D06096086480165030402010500307F060B2A864886F70D0109100104A070046E306C020101060E2B811E9193E60A000001000402003031300D060960864801650304020105000420FCCE78095CE7663D47825CB034C507B1BBD33B8A36632801EF4AF94665288F4902031DA26E181332303133303430393132333433302E3838385A3004800201F402046174B99EA082076C3082076830820550A0030201020204010036E5300D06092A864886F70D01010B05003063310B300906035504061302534B3113301106035504070C0A4272617469736C61766131133011060355040A0C0A446973696720612E732E31173015060355040B0C0E4143412D3330372D323030372D323111300F06035504030C084341204469736967301E170D3132303631343132343833335A170D3134303631343132343833335A3081A0310B300906035504061302534B3113301106035504070C0A4272617469736C61766131133011060355040A0C0A446973696720612E732E31173015060355040B0C0E4143412D3330372D323030372D3231373035060355040B0C2E416B72656469746F76616E6120736C757A6261207679646176616E6961206361736F76656A207065636961746B793115301306035504030C0C54534120434120446973696730820122300D06092A864886F70D01010105000382010F003082010A0282010100B26E4793158A1DF2C8334676EBA81CC02B5D0E2EAF7E432F42646C3AAC8285E1DABA6C47AEA70592F1067A259B5B8481AFE6C840A8B5EE37F74CAC633623830624B5A52011E1297E4FFB7B6EDBA26549E3A4752A76A251F11BA54F65B08B78D0CCD2E7DCA808F2551E3A04286F39E6CFA430221CA188F7609B85B10BDE958E3629A9BFA5E8754E7D908D4A5842A2EF543C17589B496727475FB9C29E451661A3466120D8075C30D47FF903A528BF157905100030DF3BAF81E30E99817D1BC5BB073AE4539D0148F8504DCC6DE2A7CFD7A076C37AC21C112182800EBB806B1EA8FFE14E5A6B8EBCB69EA72E5BD5129F55FC9AE19A10EE78C1E92F4765980A87A30203010001A38202E4308202E03081A906082B0601050507010104819C308199302406082B060105050730018618687474703A2F2F6163612D6F6373702E64697369672E736B303806082B06010505073002862C687474703A2F2F7777772E64697369672E736B2F616361322F636572742F616361325F64697369672E703763303706082B06010505073002862B687474703A2F2F63612E64697369672E736B2F616361322F636572742F616361325F64697369672E703763301D0603551D0E04160414DF279B25630002C0474CD2DF945BAA6B004A2B623081980603551D2304819030818D8014157F5F5F08692AC67003A1FA516A4DAC8D5F9853A171A46F306D310B300906035504061302534B3113301106035504070C0A4272617469736C61766131223020060355040A0C194E61726F646E792062657A7065636E6F73746E792075726164310E300C060355040B0C0553494245503115301306035504030C0C4B4341204E42552053522033820200F4300C0603551D130101FF040230003081B60603551D200481AE3081AB300F060D2B811E919984050000000102023008060604008F7A01023044060E2B811E9193E60A000001000103023032303006082B060105050702011624687474703A2F2F7777772E64697369672E736B2F5F7064662F63705F616361322E7064663048060E2B811E9193E60A000001000402003036303406082B060105050702011628687474703A2F2F7777772E64697369672E736B2F5F7064662F63705F7473615F616361322E706466301C0603551D1104153013811173707261766163614064697369672E736B306E0603551D1F046730653031A02FA02D862B687474703A2F2F7777772E64697369672E736B2F616361322F63726C2F616361325F64697369672E63726C3030A02EA02C862A687474703A2F2F63612E64697369672E736B2F616361322F63726C2F616361325F64697369672E63726C300B0603551D0F04040302064030160603551D250101FF040C300A06082B06010505070308300D06092A864886F70D01010B050003820201003E7D012645CBCC25D661B3F6188D2AD8E89AE369CF5323159A4824956B4C49FC7BC76688FD193A794340F2C62406504C781815BA3D3E14F2C024807EB1653006FC3B2D35CF8AFBE61B0DD10C6599DB7AD16BF0F9D229163A00700534A9F8487356982741B8B79B2A8138ECBC781DF38EA3BFEDC1BE939467E8C059645745F4B6F05BDCBFF0DEBA077D276C217A76DF5E180E86DE7030D6E75DC7352ED04E27FB1E6B81DF448DE9639DFE07A3FF9E7270B1476CA72E4DBEA7E9F0C88B8D0AA6DE260372A2014E229FEB5BEC743FD038B705AC84B4C0733D1A1654FFC22C6ACDB7878CD034759E01720C9C8A1A88105CCBACFD885391DC533450DB119483F276F16CDAC0EAAFBD388C9D790A68FAA50C95AA089ACF99A58C2CA5E09424401529D124E08124833E01F38B04F18192F1BEA62F363135C4BD361218EDCA808AFD0FBFA7B38B70B4E417AE8F2B618320840DA2F80BE9F9B8BCE5B479D1B8662EC219C8E47BE97804D449BD611006BCC4E064F4B7E36B0F54DA3529F2FCC7FF5D16D0999EF4AEF1D272608CEFC3C2ED42DAFBF586BE4E8625A61EBC78576ADD5AA0D54E141FFBD6DBF81DEBE25ED723A0813EF9EEDCBAE1EB22E883FAD681773AF364840EBEB0F86F83104696BD4D5248E5505102098298478434A4A9E134E6230FC16C271B8C19EB483ED744EA1D72705BB6B42C75EBD1B9923FB9DCFE263EB86B25AD318202313082022D020101306B3063310B300906035504061302534B3113301106035504070C0A4272617469736C61766131133011060355040A0C0A446973696720612E732E31173015060355040B0C0E4143412D3330372D323030372D323111300F06035504030C0843412044697369670204010036E5300D06096086480165030402010500A08198301A06092A864886F70D010903310D060B2A864886F70D0109100104301C06092A864886F70D010905310F170D3133303430393132333433305A302B060B2A864886F70D010910020C311C301A301830160414E64E7382EF25C14F926EE7EFDD869676C685EBFF302F06092A864886F70D010904312204204E2B7B76031C4653476A4A93F1763B491335EC0EA5307E7DF5A4783B5FA8E688300D06092A864886F70D0101010500048201003C36E6ED3FC118CEA31050F913221DAC506A96CBE40C78327927A133137C2A44EE7A9DF95211CA9ADE1C0E566A8E6EE1765004B8A089F22DCAD2AFA677EF4B1FD01274854642C9C6B95071586F771BD6907D53579C5CD5ABEED46D757460D18B3D0D450F46CBC0FCED9023EB7D7A157687296A6A8C5844AEDE22625DE10CEB6AD635AB3BC78600989BCE6E9A0236062194F7DA3DB91B3463034301F9217E6B5D0FDEBBD2B953DF9EF4B848442737E3FE098FC2ED5779F1C691F400FAE2734849CF74DF7B02899B49BE2A3E46D624F272201CF2D34DDDDF38DC882771AAB41F792B691C307406DF02433577B104A92ECB0F7D5D97F4FE1C20EA42FC61C284888B0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000>/ByteRange [0 265190 285672 47313 ] /SubFilter/ETSI.CAdES.detached/Filter/Adobe.PPKLite/M(D:20130409143422+02'00')>>
+endobj
+343 0 obj
+<</Type/Font/Subtype/Type1/Name/Helv/Encoding/WinAnsiEncoding/BaseFont/Helvetica>>
+endobj
+344 0 obj
+<</Type/Font/Subtype/Type1/Name/ZaDb/BaseFont/ZapfDingbats>>
+endobj
+341 0 obj
+<</Type/XObject/FormType 1/Subtype/Form/BBox[0 0 0 0]/Resources<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]>>/Filter/FlateDecode/Length 8/Matrix [1 0 0 1 0 0]>>stream
+xœ
+endstream
+endobj
+2 0 obj
+<</Type/Metadata/Subtype/XML/Length 44744>>stream
+<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
+<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:56:37 ">
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" xmlns:stMfs="http://ns.adobe.com/xap/1.0/sType/ManifestItem#">
+ <xmpMM:InstanceID>uuid:7e7b597d-426f-3642-8dca-bcbf37236e1d</xmpMM:InstanceID>
+ <xmpMM:DocumentID>xmp.did:89321C534E266811A613EDAC20FB34D2</xmpMM:DocumentID>
+ <xmpMM:OriginalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</xmpMM:OriginalDocumentID>
+ <xmpMM:RenditionClass>proof:pdf</xmpMM:RenditionClass>
+ <xmpMM:DerivedFrom rdf:parseType="Resource">
+ <stRef:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stRef:instanceID>
+ <stRef:documentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:documentID>
+ <stRef:originalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:originalDocumentID>
+ <stRef:renditionClass>default</stRef:renditionClass>
+ </xmpMM:DerivedFrom>
+ <xmpMM:History>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E4B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E5B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/metadata</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E6B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:44:22-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:80321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:46:03-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:81321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:48-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:82321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:49:01-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:83321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:52:39-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:84321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:58:06-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:85321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:59:50-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/metadata</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:89321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4A27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:48:01-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4B27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:50:54-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4C27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:54-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4D27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:55:16-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4E27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:56:27-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4F27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:58:44-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5027385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:05:30-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5127385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:07:25-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5227385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:12:43-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5327385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:13:56-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5427385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:16:22-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:DE855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:19:25-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:DF855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:27:07-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E0855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:29:58-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E1855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:32:34-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E2855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:33:46-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E3855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:40:42-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E4855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:41:28-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E5855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:42:42-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E6855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:44:36-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E7855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:47:08-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E8855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:51:29-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:80C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:49:23-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:81C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:50:43-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:82C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:52:12-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:00CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:53:23-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:01CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:53:56-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:02CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:56:41-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:03CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:03:21-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:04CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:06:47-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:05CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:09:26-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:06CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:11:53-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:07CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:13:29-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:999093B2AD2068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T14:21:34-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:9A9093B2AD2068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T14:27:38-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:9B9093B2AD2068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T14:30:31-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:371C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:20:55-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:381C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:26:33-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:391C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:29:07-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:3A1C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:31:19-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:7A0142B9242368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:41:33-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:7B0142B9242368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:44:10-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ </rdf:Seq>
+ </xmpMM:History>
+ <xmpMM:Manifest>
+ <rdf:Bag>
+ <rdf:li rdf:parseType="Resource">
+ <stMfs:linkForm>ReferenceStream</stMfs:linkForm>
+ <xmpMM:placedXResolution>72.00</xmpMM:placedXResolution>
+ <xmpMM:placedYResolution>72.00</xmpMM:placedYResolution>
+ <xmpMM:placedResolutionUnit>Inches</xmpMM:placedResolutionUnit>
+ <stMfs:reference rdf:parseType="Resource">
+ <stRef:instanceID>uuid:288c3c69-7dd6-7c4f-984d-b085b3307748</stRef:instanceID>
+ <stRef:documentID>uuid:93F9F49755C5DE1185BCB9A8461E73D9</stRef:documentID>
+ </stMfs:reference>
+ </rdf:li>
+ </rdf:Bag>
+ </xmpMM:Manifest>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/">
+ <xmp:CreateDate>2010-07-02T15:32:26-07:00</xmp:CreateDate>
+ <xmp:ModifyDate>2013-04-09T14:34:22+02:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2013-04-09T14:34:22+02:00</xmp:MetadataDate>
+ <xmp:CreatorTool>Adobe InDesign CS4 (6.0.5)</xmp:CreatorTool>
+ <xmp:Thumbnails>
+ <rdf:Alt>
+ <rdf:li rdf:parseType="Resource">
+ <xmpGImg:format>JPEG</xmpGImg:format>
+ <xmpGImg:width>256</xmpGImg:width>
+ <xmpGImg:height>256</xmpGImg:height>
+ <xmpGImg:image>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
+xV2KuxV2KpL5z/5Q/Xv+2bef8mJMVf/Z</xmpGImg:image>
+ </rdf:li>
+ </rdf:Alt>
+ </xmp:Thumbnails>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:idPriv="http://ns.adobe.com/xmp/InDesign/private">
+ <idPriv:DocChangeCount>244</idPriv:DocChangeCount>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <dc:format>application/pdf</dc:format>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
+ <pdf:Producer>Adobe PDF Library 9.0; modified using iTextSharp 4.1.6 by 1T3XT</pdf:Producer>
+ <pdf:Trapped>False</pdf:Trapped>
+ </rdf:Description>
+ </rdf:RDF>
+</x:xmpmeta><?xpacket end="w"?>
+endstream
+endobj
+59 0 obj
+<</Group 64 0 R/Resources<</Font<</C2_2 58 0 R/C2_1 57 0 R/C2_0 56 0 R>>/Shading<</Sh6 150 0 R/Sh5 149 0 R/Sh4 148 0 R/Sh3 147 0 R/Sh2 146 0 R/Sh1 140 0 R/Sh0 139 0 R/Sh14 145 0 R/Sh13 144 0 R/Sh12 143 0 R/Sh11 142 0 R/Sh10 141 0 R/Sh9 153 0 R/Sh8 152 0 R/Sh7 151 0 R>>/ExtGState<</GS13 203 0 R/GS12 202 0 R/GS11 201 0 R/GS10 200 0 R/GS9 214 0 R/GS8 213 0 R/GS7 212 0 R/GS6 211 0 R/GS5 210 0 R/GS4 209 0 R/GS3 208 0 R/GS2 207 0 R/GS1 199 0 R/GS0 91 0 R/GS16 206 0 R/GS15 205 0 R/GS14 204 0 R>>/ProcSet[/PDF/Text]/ColorSpace<</CS0 85 0 R/CS1 100 0 R>>/Properties<</MC0<</Metadata 192 0 R>>>>/XObject<</Fm9 82 0 R/Fm8 81 0 R/Fm7 80 0 R/Fm6 79 0 R/Fm5 78 0 R/Fm4 77 0 R/Fm3 76 0 R/Fm2 75 0 R/Fm1 66 0 R/Fm0 65 0 R/Fm17 74 0 R/Fm16 73 0 R/Fm15 72 0 R/Fm14 71 0 R/Fm13 70 0 R/Fm12 69 0 R/Fm11 68 0 R/Fm10 67 0 R>>>>/Type/Page/BleedBox[0.0 0.0 841.89 595.276]/Contents 63 0 R/CropBox[0.0 0.0 841.89 595.276]/MediaBox[0.0 0.0 841.89 595.276]/Parent 3 0 R/Annots[342 0 R]/ArtBox[0.0 0.0 841.89 595.276]/TrimBox[0.0 0.0 841.89 595.276]>>
+endobj
+3 0 obj
+<</Type/Pages/ITXT(4.1.6)/Kids[59 0 R 5 0 R]/Count 2>>
+endobj
+1 0 obj
+<</Type/Catalog/Metadata 2 0 R/Pages 3 0 R/AcroForm<</DA(/Helv 0 Tf 0 g )/Fields[342 0 R]/SigFlags 3/DR<</Font<</Helv 343 0 R/ZaDb 344 0 R>>>>>>/ViewerPreferences<</Direction/L2R>>>>
+endobj
+55 0 obj
+<</Creator(Adobe InDesign CS4 \(6.0.5\))/Producer(Adobe PDF Library 9.0; modified using iTextSharp 4.1.6 by 1T3XT)/CreationDate(D:20100702153226-07'00')/Trapped/False/ModDate(D:20130409143422+02'00')>>
+endobj
+xref
+0 4
+0000000000 65535 f
+0000332170 00000 n
+0000286235 00000 n
+0000332100 00000 n
+55 1
+0000332368 00000 n
+59 1
+0000331055 00000 n
+340 5
+0000265159 00000 n
+0000286029 00000 n
+0000265027 00000 n
+0000285851 00000 n
+0000285951 00000 n
+trailer
+<</Size 345/ID [<72e46b7e882d7f42edc548905fcedd4f><e8a97564aad74aa17002cb23c576d1e3>]/Info 55 0 R/Prev 258944/Root 1 0 R>>
+startxref
+332586
+%%EOF
+
+345 0 obj
+<</Length 1617/Filter/FlateDecode>>stream
+xœÝUkPWÍn6BTŠøXn
+¨ˆA!D| é’D’¨¥$ƒ´>bŽÔt@E«V-"¢ Q”G´ø
+Ž+pI1=Ï~\¤
+{e¨ùíóýacj,žðe\]Ix(¯Ë»×Iû²¬$8~jÆÎ)³AóÙò«>ÖEJÓmÓ„å´ƒAÈly·=¿íø½'¿ªöμRM)ä+ ¿~§§rGXâ0Ï’×”Ð{zÕÒ³”à#íý«^àcö§Jβ âŘü‚ÛŠŽ—] ¿°@’âzk[ÍØ'?ÔÄæN6{.ÞíÆ^åÎËdbÜJË×ÈæÖØâ¡ s„ÁŠgþ—¦å;ÖK5eO-ÏŠ^ý¼?º±ÛñXÓ&‡–JÏå7XÊ*ë¶ûê¹· ­d³´¤o;ûK­ûæ?Œa^ÏK‹Ý¦·U´†¦fV礸µt›ÝCz}çÌæ9þ5ãú7q}ísºcÚ1LvŒÒx¥e€‘`7ó×L¥AŸ¡m¾¯¹Û¼ÍXZ¢*ïú.¥:Ôå8š^Ö/t—÷åÍZ¨ö>wèø˜©ÁuÏø²ÃsºûÎîNºÛ{*gþ™
+Ó¾úËPÒ&«Ã’ _æ‘“ÉÑ?IOw”ÝJ;oH^»òŠ£]Ýܱ¦õVÛýøEѦ Õ°­¹_´qõ‰Êí.nó:yjÁµG?,sN¯­š4kw‹ë¼‹Qm¥EýbÖæ3æ´¯°Å{oú'¿ÁŽ0|W$î›)6wìýûaéí˜s¯Ëà~nŠë°Ú»£ª½%~õõ
+endstream
+endobj
+346 0 obj
+<</Length 1783/Filter/FlateDecode>>stream
+xœ3hâd0hb{±€™‰‘‰‰‰á‹/§V›GÛw^FFnVƒ\CnN6æP6a¦`oCaA‡‡Ë©(±$³8'±,ÑPÉ@$ÈÅ#é—X”Ÿ’W©”ZUšœ—_\ä”%¦òð€Ôpó°{:¹ŠƒøÌ<<ÞÎŽ
+~N¡
+ÁA
+Ærâ¼–†F†F&æÆQ⼆0®™‘i”A2Î
+rñp¹dg¦+$ê늈BìçstvÔ560×52
+«èK Mµ\ÄÞ˜ø7¯¢2ó…|Çb ÿ þ›¹üŒõj}òB£ï°öM­¨÷ÿ'©]²œüˆ¦Ç!—P—Y78ßl=õ¬èÆõìש]†¤–”di]Þßr¥i»¯IˆäsóSgïí\$—þfjíÄ5¬)±,Ÿk…HðjN¼ôþî–G5Û…_ü«•·úùsõ£Äç»åY,Ö.Þ:Ý&ZþðÁ‰_…׉ ùuæûŸüÔÝgÝ(ØÀúHý–µÐ)ó˜y–§õ3~Gs÷žûùØÝÐ5¥Úzö¬YÛ¹ýêÔí4,xáÚµÅíÊ©òÔ»׸<iþËkzØ/ì寞“¹|2þý¹6a+[øëð#GfεñX²ýÊÏBÉÌ6ó·¼¹oV‘f)6Á‘߀½ù;®cöŵŸïÎ2/«(ªœµ¾déñÈ×µŸ2v3¶õËJ'.Ú¨¢¹¡o«„Ü~ §ío.0ÝQe¸sn‹Ú¦7·³Ÿ·Xú|‹`¿4Óâ]¹à{±´ -õs':Œí|Tvêòªõ6rb÷â®ü:¸³Á8Ÿ5®£~ßÜÏFá~/zϲ{Õ]¯Å³™˜71o2hb^g L>²ÂŒŒÿY8 Ø€#£A0HL$æiànàÊÆ«Ý(7qf +0›˜±qh³1²²²31Š©e””Xéë§èå%•égëg''ê§ä'ƒèøä‚b½‚”4'¡Š,Ö–âh&²±±0t
+T~P ²
+Y>1ÑúøxŽL­cÌ fù®éŸŒV½1ƒŠó›™ª¯ún>ëÿÎâj¶/fON¸ò$wQÙ{ß
+wÍÙdÎô§Yáæ¼ÃãBn:ËãŒy\þ÷ˆOݘu{ÊÑ“êOö< ÒYx|nÆÛÇG‚Ù>º0ô¾ê”+Jž³¼¬ üìL½©õ§æÇÝÛ¶2œAÐö틘žùyw™;nŸ¿\¹ÂeÛž¦;÷.œØb¢õÔåûk¾’L™9‡Ô;|—[ÐréåäÈy‹Û¿ÞñæaÐE¥ü¯M—n¼nZvæüusK[ÁkšJÞN/‚é˜.QXZšû×å‰ß5¹ø׆ýá9ÛBô§no`*4÷Êûµ†«ží¾7C?ÿ•¡ÞÍ}ÙoNhR\¢ü±¤%ÀõÛ± úV®;x±ZáE¦_.Ó™‹·}²ŽpeuÕ§<—Wgçi‹¯:äp-v‚ Þ]ëÿu7ŽŸ.Õñîž¿ø’Ly]Î!›À ùo/‰$5$é‡Ø2lPüûåà‰åÁß<¤3Û³ê|Xú»žëÁ+ݾse]‘ŸÚó÷å¦jÅCS=äÕªž áá¶Z÷÷i}mù1+ñ-Ë î„3_zàÉ¥øýŸsžtlaÔùb-²†»òË•žºm¥’÷#×ßœzC<±d†Cï‘o"á$b:šù^î˜ÔæT{ë¤óä‡ç\rJtriÔ®0}+%~6>ÊãL§_žKA‹ÈÕœ ×ïqE­7kÛhà
+endstream
+endobj
+347 0 obj
+<</Length 1659/Filter/FlateDecode>>stream
+xœ3hâè4hb+\ÀÌÄÈÄÄÈhÀËÆ©ÕæÑö—‘‘›•Á ×Û€“9”…M˜)ØÛPØ@Äaçár*J,É,ÎI,K4T2P
+C¯>z˜·Ñ~ƒa÷U¦i^ÍÙâWúêJ®txܺGì*¾‡-½ï×úO(Š¶(ôdËžeûÊS¾BÿŠßUUN“=|¼r½ÈÏY?÷¿•ÿb)¦þçÙ b¦WÍèé\٦÷N‚q~ÿéyùwJ
+5ñ+à­}ZtöV/gRùê¯Ó,õôã¸}¬Ý°Z¯rÕo–•I*o¹yÿ+§¼3Zd¿kÞ’k·M_<fbfd`\ÜÄldÐĬg
+,žî®l¼Úrg¶°200
+endstream
+endobj
+348 0 obj
+<</Length 4927/Filter/FlateDecode>>stream
+xœZytVU’'!„ì!!_"ä#$Iî[¿÷Â’¢jkp
+†5>²¿ÿ9Û‚ùXv[Ã/D`ÏbǾFv[–o{ƱG%ì£cmÛÀ§ˆ!°
+œ¥á/4 ܵï}&
+ÛÚß½ÇjB
+
+@Ðo2¼š²X*
+‡!ÿ~e72è¦Ãÿsâ Š©Ë<É__ÄM<´>Úßù ­[4OòÉM 0 >àq ¿§öF…pägafÀ¾ÕDÈ4°F[Ò÷ߌº‹­ˆ†R£mãa¸^¨ñ-ÄØC¾j» JÆaÏ´Òð
+$8klÁÕÒnÐø ÁbZð¡:%*„ãrM‹%«X‚G°fêXÆz*â
+ËŽ %Ú1B¬X=µ>Ò>‰ ”°/óØ ±«(¹ìOÌ&?%Kp°ñYðbÓ‰l 3
+©=pÊ9 ±7TtŒ¾ËüŽýE®0ò²ª0à˜Ú&Ó
+3–=«Oaf¶˜U…q†íÈœVèìC“2í GkØ™W72ìÛ¦Ã+|PÙµ+„†¡ÈC7èÜîS‡W½½Ç«Œ¬ò¹D~cVã4ÙŠ&P½´ Wx‚)zŠ„¦: §"Œš‰Ý:7¬Å™ÜÍ€>p,‹+hüaªkq¥†ƒ¶Á0_Bêð#ï¢2ŠÓãé¨ø)rd‚cæù’¸ÊÔ4Ë›õÛuÌÕG f1t2 êXxue1ÐÇ6—G%w“˜ÊÜdž”ì>x 5÷þ„WÛ¨Vþœa¬^úð%#yFáxCp¿\çQ$õáû­0p„>ý¶³Úc—¨C\Z!Oiã=DäF¤4(Òƒ$­t¼"v¥ ¨ÚÀÒ_
+Ö“ø«äX˜/-ÓøÅ_§räcSÎI?+O)¥Ú5-hü¼>òŠp`œà;VˆõšX‘Ø’­Ô&‚Àˆ¥=8ð%%à«aÖðál*àÀ÷"Õuà'’Èx+…·o.ÿ‰^Õ•ÃP>QÁ6æ‚éÖ˧¨M°£ŽÜ:—wêÞ„à 6å÷“¿¼ége+ßÅa3Õ•ï6pdú/‹`9¼ñ)Ëß6pä&gP‚¡ÇƒYH¯déãÈ¡DÓgP+„ã™îqÐ?,¯;9:ƒÊÃÃAp|ã¢[‘GuG`-áL«¨’¹ú +·N©Š™*IÈ(¼ºKî ¾³ðìúðë¨×ôe½äMWµ¹-L­øH1V^Ö%xú¯ø‚d=Äk2ÎËŠ‹JðpªÃp\Y£åž•­²…køƯrª>ÞR3Ù*ŸÐZ…)Èþ®ìŽÀ>÷•»é‘!:‹ÃPù)þçò)¤¢c›«ÁjžðZÅõ¹ñ<‰V{Ør±˜žLv;x±Ç<ü0ˆ}•9åàã½àSL)…/D|æà«( ÒvN©!ضØrÈB§h»‡¼¤X…b
+m çÉ@ ´¸¦U­¤Ž_+xÜ&V=KÒ c'¬×›T}G0ˆ#(ÃÐ$#Ô0fèÕC“#°Ç>š®a4‡Y5´Yé È3öÐG©M qbdÚ}R¯†^Ó\þW§ÊÃûHdÇã9­ZUÉK×¼Ù«ÞÅ°åš)ºú7 {@íªê P! |Aæ%*È Ï$Ãrh5Óvù‘öSÐð¢Ö¼$vˆN Uæy½zø0uÝá)]±3uY‡OÑ0Xâ±à ¿™4Ö“<ÔѾŠº°fmøC´‰Í÷öÃ×3,"´¾aìZyµâ`ƒf›¬5É´ü 4ÑÑ©ù¥‚ñ&Z<ËšÝc%6­sÍ4ŒWd¼Im/uJ•ÉœRµ±œàêZ;|JŽk»k7H8Pïx8 µ/ª^S¾F¶¹M¬=fl]š~$Í\ðÔëäÆL曜º¼;%Þ¤Š`<e‚‘º‚mYyï#Š’VÃj:ÓÇÖ``^}J†ñÑþýiµ/g;½‰Ø¬¨iË’Á!o±„59]űˆ²™÷Üâò ƒÄ«­J%aVB&‰¶Ä­ ”Ñ43‰õ ‚² ×!v”c̘Ó4OœU¥°{ô|ö·Óhª+Nvþ m‚×âFz­Š'¶¼œâlpv«M¾jq¸Ô9çI!,5ªì–J)€
+RŠôädæL Rå&rÂÄì®QŠŒ‚ àM„²[9p€¶$ðF›V.˜LvãÕ‚aU0…Z"|aZ‹`ËLàš{ˆ`"„t­Ã§ “cAí]Ÿ‡¦ðNÚ{d‡E©¾Š6Á›xs)Pß@‡OÈ–KX¿T÷lj w2œpLr×ßÆp™/ë©ãËרfýY »²å²Y}ê¿VþÆÙÕI0ë¿Õ0ÖL.G#(:êõ#ÃSPô#GÌR„— nAGœW°¼LðqF¦(….{p¤­\¥î
+xvy„%œÜ­|†³Ê9+ÛȃEú:(&Wá…1†HÃ')h¾œutF•Rа3MðÍÙ¨…j5V˼ou­Æ›óå›Q§ŒU>rý6º`yÿÍvC0t^Àdýb··ÜW~PyP&©Å£ÑáñrÙ\55¤IXž2òm¬†-Et§„—ËÌ؆Wlc‘öXÙP#SNî†ßÒ#Q|6 _Ò&¾ì“5³Ư˜rÔ8šöV݈¶¤±…‚æËoé 5ÎW02 ¿ù áÛXí¡Ö±ô6ÕkWa7ÃòØ4ÒÀž9eÓ¦&~-@{°¹‡2ÓÕ6/[šéGâGÜ@5«G&ð~ 8¡3F¯õðš•áûˆßxü§ë˜´7NúÆ'c>R{ã«8¦öÉØÕäAœ>̈Õ2¢ƒ¯ÇßžhiS”8\F[fÓj|Õk’¤ånC£ð÷ƒ-kȬ0 ®R-Çi5Þ¶„ÌØ–Oõjl´¹÷¹òZe zÛ˜ƒW®âœwä ¿m]IE¢+©¯ÈLí9©AJJrrÖNqïFümPʽ‰{×­*ˆÝÓÖ–6·úw‹{vÿõ†Žk_X׶±µ{ÉÓ‹Ä‚ÿÇW#ËE\}5²äºö¥‹f.¼#~ˬŸ-ž5cá¢ÎeðËò¥í3­‘¥¾)Ù«u\sËõVLôU_Ìš0¦)~]ó¤xëOãNWr¿ˆ¹hÙII—SÚÄômÓ¶MY3lβe‹ëëêV¬XQ;¿LYÛ9¯®}F»]7cé|ù6ïkªiñŒöÿsíÿúhÏ®ä¤,nûòém½sW'_x⵩ƒ›vnùùÃïn˜Ñï÷oîºæôÚ~çǹy³~ôàÆ g®í8yûÖ¹ÇV†ïïîOÿŸý¬é“¡³Oý­|oQ[ÍÅ!Ý?>=}Ú–Æ/ëgíZ7û‰gß>=äÕÇ_¾ï¯“ß}éšÍ?¶ô\z}ií½ß×þ0·èª›ZþkßÇî/¯\ý}¯®‚oqõ‚…[ß:½å÷mi³{¼ÿÌâOç,¸äL98ÍéóBwðmë[*¾ªš7çüˆ½C¿9SÒ¼hJWë¹Å;~{þÊ% Ö¯JŸð•½?ûÏÅ/¯wd÷»¸'©ãøÖ£ç&6tŸ¾éw7Û±ª×…'¶Ì\Ñuèܽ·>ÖqiË›ßÕ¿zdãÖg몗M6þŠÔÞºñׯç×íùaéÀÙÓ^k{`mÒ]=·µŸÌÛóEç×ãV6oXxxƥ韘²csÝö×z}óâ¤vÿþòâ´ sËÔ?¬î¸p¿3éåN]½ÿª}eOßz2õ蔿ΰ.Žÿìì«ÏÜUüÉéQ¿ÙðÅöÇË—mØ–<gØû#çíÛ±êëù·/ßù\wúçïœïßóܦ3"7^º±õ½ËO®+yÿÝË-G&®|êþ''g-þtì¦ §.<ðMi“=öX¯›ç7ÞräÛ!%“?¨¾ýÈñ‹Ï5t<¿üŽ‡š.»oó¾G<ûHéøXc}á¸ÔÆÓožþã¸m±Ëß]Z¿yå¥ígW¿Ûo×æÍ«|¶wêôé)oøüÍû'ü÷ÿ
+endstream
+endobj
+349 0 obj
+<</Length 782/Filter/FlateDecode>>stream
+xœ3hbæ5hüÆÄÈhÀËÆ©ÕæÑö—‘‘›•Á ×Û€“9”…M˜)ØÛPØ@Äaçár*J,É,ÎI,K4T2P
+… Œ , LL¢ x ¸€fÉŠ²0s1².00Ð3àñEXX˜˜®ȃ8Ê,b "õmMÒ›Îη1³Yõ¯b›;š—™›˜6žü‰'ðÍJû3¬5SwMIò$ê{l¶þAi[·_ÇwÞçJI0ÙátP2Zãvÿœ·ì§¢ê½Ï å¨[¤lº7{2ã¥ÖÏÿÕÝáoìåÛµêNƒJ¨Û±×'ª£lŽ^e½ÿè{¾œñ»o§.ÆõH®õì“{÷„óAç©UlÎ%*Ìž2ÇJîf~¹s7—Áæü“Bƒ3m2[Y_òúrgL8í2׬_w;ûÍsg2^6ü˱¸´qžkKLèÔ—›˜Så¶fÌ©î;\°ißµõg~ö´°x ïül¾03OÞgåL%å\…ÜéµÞû‚W>¨rWšYŸ·´\ðò‡ûk¢ïªããìh•ÿ˜™íÑý¶5 Lî0º.çÃÊâܤ,ºþ«BŠžÅ¦MéOò¾cú²Ê¡ÐwþݵÓάÎÎþºŸ#4®,ôËòM~…]۾ؕîx1³Õ›÷ÆLëÇwwZñ½MM<p7+Ð.X½=ãÇ<ŽÈ|³ïÕgWœ²ï·ÒÔ °<gÇ`>¡ëuGö[åO?¯ë=å¼ÐÞó<óÞ˃å'Ž¼xÕ=I€aým‘K§‚ÛgEM\¸ò»o’ä­»§‚Ô¿®ûÏ5_ªåcI)_tõܹû·Z‡‰={.³«?°ôR÷ë.¦Ç̶o}Êu’c‰NŠ¼Êqá×| z#·k -åžq~£íƒý“ƒÎ_Nvúcòãßy=¹5
+endstream
+endobj
+350 0 obj
+[345 0 R 346 0 R 347 0 R]
+endobj
+351 0 obj
+[348 0 R 349 0 R]
+endobj
+352 0 obj
+<</CRL 351 0 R/Cert 350 0 R>>
+endobj
+353 0 obj
+<</707ABDC9A8950BA2E2C0B80B412C492C614107A551ACC878038D57E5C79D5C82 352 0 R>>
+endobj
+354 0 obj
+[345 0 R 346 0 R 347 0 R]
+endobj
+355 0 obj
+[348 0 R 349 0 R]
+endobj
+356 0 obj
+<</CRLs 355 0 R/VRI 353 0 R/Certs 354 0 R>>
+endobj
+2 0 obj
+<</Type/Metadata/Subtype/XML/Length 44744>>stream
+<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
+<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:56:37 ">
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" xmlns:stMfs="http://ns.adobe.com/xap/1.0/sType/ManifestItem#">
+ <xmpMM:InstanceID>uuid:7e7b597d-426f-3642-8dca-bcbf37236e1d</xmpMM:InstanceID>
+ <xmpMM:DocumentID>xmp.did:89321C534E266811A613EDAC20FB34D2</xmpMM:DocumentID>
+ <xmpMM:OriginalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</xmpMM:OriginalDocumentID>
+ <xmpMM:RenditionClass>proof:pdf</xmpMM:RenditionClass>
+ <xmpMM:DerivedFrom rdf:parseType="Resource">
+ <stRef:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stRef:instanceID>
+ <stRef:documentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:documentID>
+ <stRef:originalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:originalDocumentID>
+ <stRef:renditionClass>default</stRef:renditionClass>
+ </xmpMM:DerivedFrom>
+ <xmpMM:History>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E4B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E5B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/metadata</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E6B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:44:22-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:80321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:46:03-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:81321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:48-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:82321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:49:01-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:83321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:52:39-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:84321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:58:06-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:85321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:59:50-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/metadata</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:89321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4A27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:48:01-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4B27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:50:54-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4C27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:54-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4D27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:55:16-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4E27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:56:27-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4F27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:58:44-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5027385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:05:30-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5127385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:07:25-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5227385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:12:43-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5327385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:13:56-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5427385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:16:22-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:DE855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:19:25-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:DF855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:27:07-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E0855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:29:58-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E1855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:32:34-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E2855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:33:46-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E3855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:40:42-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E4855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:41:28-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E5855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:42:42-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E6855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:44:36-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E7855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:47:08-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E8855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:51:29-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:80C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:49:23-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:81C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:50:43-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:82C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:52:12-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:00CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:53:23-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:01CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:53:56-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:02CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:56:41-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:03CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:03:21-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:04CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:06:47-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:05CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:09:26-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:06CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:11:53-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:07CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:13:29-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:999093B2AD2068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T14:21:34-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:9A9093B2AD2068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T14:27:38-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:9B9093B2AD2068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T14:30:31-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:371C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:20:55-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:381C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:26:33-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:391C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:29:07-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:3A1C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:31:19-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:7A0142B9242368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:41:33-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:7B0142B9242368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:44:10-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ </rdf:Seq>
+ </xmpMM:History>
+ <xmpMM:Manifest>
+ <rdf:Bag>
+ <rdf:li rdf:parseType="Resource">
+ <stMfs:linkForm>ReferenceStream</stMfs:linkForm>
+ <xmpMM:placedXResolution>72.00</xmpMM:placedXResolution>
+ <xmpMM:placedYResolution>72.00</xmpMM:placedYResolution>
+ <xmpMM:placedResolutionUnit>Inches</xmpMM:placedResolutionUnit>
+ <stMfs:reference rdf:parseType="Resource">
+ <stRef:instanceID>uuid:288c3c69-7dd6-7c4f-984d-b085b3307748</stRef:instanceID>
+ <stRef:documentID>uuid:93F9F49755C5DE1185BCB9A8461E73D9</stRef:documentID>
+ </stMfs:reference>
+ </rdf:li>
+ </rdf:Bag>
+ </xmpMM:Manifest>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/">
+ <xmp:CreateDate>2010-07-02T15:32:26-07:00</xmp:CreateDate>
+ <xmp:ModifyDate>2013-09-06T16:23:05+02:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2013-09-06T16:23:05+02:00</xmp:MetadataDate>
+ <xmp:CreatorTool>Adobe InDesign CS4 (6.0.5)</xmp:CreatorTool>
+ <xmp:Thumbnails>
+ <rdf:Alt>
+ <rdf:li rdf:parseType="Resource">
+ <xmpGImg:format>JPEG</xmpGImg:format>
+ <xmpGImg:width>256</xmpGImg:width>
+ <xmpGImg:height>256</xmpGImg:height>
+ <xmpGImg:image>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
+xV2KuxV2KpL5z/5Q/Xv+2bef8mJMVf/Z</xmpGImg:image>
+ </rdf:li>
+ </rdf:Alt>
+ </xmp:Thumbnails>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:idPriv="http://ns.adobe.com/xmp/InDesign/private">
+ <idPriv:DocChangeCount>244</idPriv:DocChangeCount>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <dc:format>application/pdf</dc:format>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
+ <pdf:Producer>Adobe PDF Library 9.0; modified using iTextSharp 4.1.6 by 1T3XT</pdf:Producer>
+ <pdf:Trapped>False</pdf:Trapped>
+ </rdf:Description>
+ </rdf:RDF>
+</x:xmpmeta><?xpacket end="w"?>
+endstream
+endobj
+3 0 obj
+<</Type/Pages/Kids[59 0 R 5 0 R]/Count 2/ITXT(4.1.6)>>
+endobj
+1 0 obj
+<</Type/Catalog/Pages 3 0 R/DSS 356 0 R/AcroForm<</DA(/Helv 0 Tf 0 g )/Fields[342 0 R]/SigFlags 3/DR<</Font<</Helv 343 0 R/ZaDb 344 0 R>>>>>>/ViewerPreferences<</Direction/L2R>>/Metadata 2 0 R>>
+endobj
+55 0 obj
+<</Creator(Adobe InDesign CS4 \(6.0.5\))/Producer(Adobe PDF Library 9.0; modified using iTextSharp 4.1.6 by 1T3XT)/CreationDate(D:20100702153226-07'00')/Trapped/False/ModDate(D:20130906162305+02'00')>>
+endobj
+xref
+0 4
+0000000000 65535 f
+0000389352 00000 n
+0000344462 00000 n
+0000389282 00000 n
+55 1
+0000389562 00000 n
+345 12
+0000332986 00000 n
+0000334673 00000 n
+0000336526 00000 n
+0000338255 00000 n
+0000343252 00000 n
+0000344103 00000 n
+0000344146 00000 n
+0000344181 00000 n
+0000344228 00000 n
+0000344323 00000 n
+0000344366 00000 n
+0000344401 00000 n
+trailer
+<</Size 357/ID [<b8d12dc8f9ff8ef9b45b85e6c6d797f9><c053b9a644fd8392f5ead8daf0359013>]/Info 55 0 R/Prev 332586/Root 1 0 R>>
+startxref
+389780
+%%EOF
+
+359 0 obj
+<</Type/Annot/F 132/V 357 0 R/DR<<>>/T(Signature2)/Subtype/Widget/Rect[0 0 0 0]/FT/Sig/P 59 0 R/AP<</N 358 0 R>>>>
+endobj
+357 0 obj
+<</Type/Sig/SubFilter/ETSI.RFC3161/Filter/Adobe.PPKLite/ByteRange [0 390594 411076 46954 ] /Contents <30820a4d06092a864886f70d010702a0820a3e30820a3a020103310f300d06096086480165030402010500307f060b2a864886f70d0109100104a070046e306c020101060e2b811e9193e60a000001000402003031300d0609608648016503040201050004204605d90937c53ba1e4e4320cc80aff57cd0a41fec494cf1d10b315196a67cb970203212dc5181332303133303930363134323332332e3235315a3004800201f402043a5bc766a082076c3082076830820550a003020102020401004485300d06092a864886f70d01010b05003063310b300906035504061302534b3113301106035504070c0a4272617469736c61766131133011060355040a0c0a446973696720612e732e31173015060355040b0c0e4143412d3330372d323030372d323111300f06035504030c084341204469736967301e170d3133303631333132313534365a170d3135303631333132313534365a3081a0310b300906035504061302534b3113301106035504070c0a4272617469736c61766131133011060355040a0c0a446973696720612e732e31173015060355040b0c0e4143412d3330372d323030372d3231373035060355040b0c2e416b72656469746f76616e6120736c757a6261207679646176616e6961206361736f76656a207065636961746b793115301306035504030c0c54534120434120446973696730820122300d06092a864886f70d01010105000382010f003082010a02820101009edca2d345f2dc25e9a996aa9938b87a8d7415e5442a62bfa431bfa67518d32df5577f156bde1cca6179d301aae8657745c5342a794a31a89c5de6074c423e28243a9bd3fc71a9605ce45766aabc009ea49ee2e0330db8bfb4794f4313fc297f1314a7b7122819067992f4584ef508341010a9b8fd15e3eb7ae6c4aafaa76bce61ba174346007ce0753b54b07a3d28ba98be2e9fdf98788586336985dcf1d6d80b44c098fb2ff8808660a8ec8d0177f1cc52e25a717d61451c68aed82e03eff1cfb333e104ace4044e1d10be022f03467a44ecc13bd48a44594cad5d94b78a547893d426769db7af8da2fe7e332a1afd192ab723e9d48a414ca2a7ef54d2c2030203010001a38202e4308202e03081a906082b0601050507010104819c308199302406082b060105050730018618687474703a2f2f6163612d6f6373702e64697369672e736b303806082b06010505073002862c687474703a2f2f7777772e64697369672e736b2f616361322f636572742f616361325f64697369672e703763303706082b06010505073002862b687474703a2f2f63612e64697369672e736b2f616361322f636572742f616361325f64697369672e703763301d0603551d0e041604140b476313fc4a78df06c7e48caf5ee56c950e9f613081980603551d2304819030818d8014157f5f5f08692ac67003a1fa516a4dac8d5f9853a171a46f306d310b300906035504061302534b3113301106035504070c0a4272617469736c61766131223020060355040a0c194e61726f646e792062657a7065636e6f73746e792075726164310e300c060355040b0c0553494245503115301306035504030c0c4b4341204e42552053522033820200f4300c0603551d130101ff040230003081b60603551d200481ae3081ab300f060d2b811e919984050000000102023008060604008f7a01023044060e2b811e9193e60a000001000103023032303006082b060105050702011624687474703a2f2f7777772e64697369672e736b2f5f7064662f63705f616361322e7064663048060e2b811e9193e60a000001000402003036303406082b060105050702011628687474703a2f2f7777772e64697369672e736b2f5f7064662f63705f7473615f616361322e706466301c0603551d1104153013811173707261766163614064697369672e736b306e0603551d1f046730653031a02fa02d862b687474703a2f2f7777772e64697369672e736b2f616361322f63726c2f616361325f64697369672e63726c3030a02ea02c862a687474703a2f2f63612e64697369672e736b2f616361322f63726c2f616361325f64697369672e63726c300b0603551d0f04040302064030160603551d250101ff040c300a06082b06010505070308300d06092a864886f70d01010b05000382020100a4f0cac694feb6638048b5287cc12b503db5b44c300478894ea9401427e53a31e3478c93eab06dfedffd94c0a3b41dc4258d7041ffee19f2bc1e2aef54498bf89ba7364ae05a6757c22d6bb09e153bfaf7d805c9d6f850326dd1dff6af180b31b576d4bba1ab2367ca55bbdea9925f1dd662b4cf1efb40acfa11586d4df11d96731bcdd9b32bbdd94fd99dad55532a9889729116c0c8d7431c90c7d74e2d79ad8b645da70676602d528ad4b5b3daa75fa4d8833b9dd223aaa4bf7e558ffaa48bf640cdd52b5c3b87318e5fb68487fc67859bb6530614dfba0bb4cc7f9291518abf85d7583924adf7ab10484cf40532637a4e819ba1a2c11a048b937602d318de09d56cae1f5ae8304c0a137dd346cb78b8400e93034b7533773ac81d3f8a3739ebaa1981f281726ebfea765f6f82ca1967b67623ce7ded552d16233f9b8ba350e31fd208b54db0e4f549ceb61d59e57a04162c59d7668410082d6f26b41f37d5d2777edd7aba9a4b713654c2e399572baa5585446a55e187251f08f8f882fbbf868cd4e59b5eaefe38d587eff7393193e0abdd7c86bf2055a0e539bd3cdf2d22b48e985aba5e883b3e31945d8f83eff5d6a1c892f30ac5d85bf6b533d0f92e0c440e11b85fff43e4d4070b6f1f2669a22a2e376ce60fd2f758292f522cc3edb8a71f05deeea5320439047a508777faafbafd25d532e7b70d89f9ff4527c4b959318202313082022d020101306b3063310b300906035504061302534b3113301106035504070c0a4272617469736c61766131133011060355040a0c0a446973696720612e732e31173015060355040b0c0e4143412d3330372d323030372d323111300f06035504030c084341204469736967020401004485300d06096086480165030402010500a08198301a06092a864886f70d010903310d060b2a864886f70d0109100104301c06092a864886f70d010905310f170d3133303930363134323332335a302b060b2a864886f70d010910020c311c301a301830160414b50c062e6a34decdbceaef637460b71c33211c55302f06092a864886f70d01090431220420cd56988f2590b0a1f061364a9ac66a336e04a9580213764adfbc95e095bdd7b1300d06092a864886f70d01010105000482010093b0e60c3488c6f9be1a5e3d96e352491635608e118cd6dffb0b4922ff5d338134c069f18548d4571837f72bbd0fbe2d15f5f6d32589b1d345df3081e06f039cfbe38b0b3d1cf1f34078462d6ca8361820c15b88cf61e460caded8946b78bf418eca58c2984e137c9e7d75973eb9d778d12a5621aa27090a81783959f2c8fd824423aaf136e23e1ee4b52ad532dd6cac912e3f373aa4baf5e78c7db13758a0a471cf7fd2b1ce0ff0c27e7250686dfb5ce6d34929e40e40dc6876216ba4ea30d3ed3c265b3ac0f8b7760be7bcdf902da3cb8f9b5e6e541359de83a80212bf9b70d7bb3633ee64d74f57fecad46497ae0a5f40fc5e80c31741ad7b595b24ee78f6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000>>>
+endobj
+358 0 obj
+<</Type/XObject/FormType 1/Subtype/Form/BBox[0 0 0 0]/Resources<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]>>/Filter/FlateDecode/Length 8/Matrix [1 0 0 1 0 0]>>stream
+xœ
+endstream
+endobj
+2 0 obj
+<</Type/Metadata/Subtype/XML/Length 44744>>stream
+<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
+<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:56:37 ">
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" xmlns:stMfs="http://ns.adobe.com/xap/1.0/sType/ManifestItem#">
+ <xmpMM:InstanceID>uuid:7e7b597d-426f-3642-8dca-bcbf37236e1d</xmpMM:InstanceID>
+ <xmpMM:DocumentID>xmp.did:89321C534E266811A613EDAC20FB34D2</xmpMM:DocumentID>
+ <xmpMM:OriginalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</xmpMM:OriginalDocumentID>
+ <xmpMM:RenditionClass>proof:pdf</xmpMM:RenditionClass>
+ <xmpMM:DerivedFrom rdf:parseType="Resource">
+ <stRef:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stRef:instanceID>
+ <stRef:documentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:documentID>
+ <stRef:originalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:originalDocumentID>
+ <stRef:renditionClass>default</stRef:renditionClass>
+ </xmpMM:DerivedFrom>
+ <xmpMM:History>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E4B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E5B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/metadata</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E6B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:44:22-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:80321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:46:03-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:81321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:48-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:82321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:49:01-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:83321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:52:39-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:84321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:58:06-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:85321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T11:59:50-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/metadata</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:89321C534E266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4A27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:48:01-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4B27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:50:54-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4C27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:54-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4D27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:55:16-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4E27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:56:27-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:4F27385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T13:58:44-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5027385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:05:30-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5127385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:07:25-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5227385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:12:43-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5327385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:13:56-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:5427385D5F266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:16:22-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:DE855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:19:25-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:DF855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:27:07-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E0855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:29:58-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E1855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:32:34-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E2855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:33:46-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E3855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:40:42-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E4855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:41:28-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E5855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:42:42-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E6855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:44:36-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E7855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:47:08-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:E8855BC063266811A613EDAC20FB34D2</stEvt:instanceID>
+ <stEvt:when>2010-06-27T14:51:29-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:80C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:49:23-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:81C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:50:43-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:82C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:52:12-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:00CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:53:23-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:01CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:53:56-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:02CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T10:56:41-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:03CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:03:21-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:04CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:06:47-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:05CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:09:26-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:06CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:11:53-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:07CECC59A92068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T11:13:29-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:999093B2AD2068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T14:21:34-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:9A9093B2AD2068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T14:27:38-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:9B9093B2AD2068119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-06-29T14:30:31-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:371C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:20:55-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:381C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:26:33-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:391C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:29:07-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:3A1C0BE61C2368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:31:19-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:7A0142B9242368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:41:33-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:7B0142B9242368119109D8C24D4F5870</stEvt:instanceID>
+ <stEvt:when>2010-07-02T14:44:10-07:00</stEvt:when>
+ <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ </rdf:Seq>
+ </xmpMM:History>
+ <xmpMM:Manifest>
+ <rdf:Bag>
+ <rdf:li rdf:parseType="Resource">
+ <stMfs:linkForm>ReferenceStream</stMfs:linkForm>
+ <xmpMM:placedXResolution>72.00</xmpMM:placedXResolution>
+ <xmpMM:placedYResolution>72.00</xmpMM:placedYResolution>
+ <xmpMM:placedResolutionUnit>Inches</xmpMM:placedResolutionUnit>
+ <stMfs:reference rdf:parseType="Resource">
+ <stRef:instanceID>uuid:288c3c69-7dd6-7c4f-984d-b085b3307748</stRef:instanceID>
+ <stRef:documentID>uuid:93F9F49755C5DE1185BCB9A8461E73D9</stRef:documentID>
+ </stMfs:reference>
+ </rdf:li>
+ </rdf:Bag>
+ </xmpMM:Manifest>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/">
+ <xmp:CreateDate>2010-07-02T15:32:26-07:00</xmp:CreateDate>
+ <xmp:ModifyDate>2013-09-06T16:23:05+02:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2013-09-06T16:23:05+02:00</xmp:MetadataDate>
+ <xmp:CreatorTool>Adobe InDesign CS4 (6.0.5)</xmp:CreatorTool>
+ <xmp:Thumbnails>
+ <rdf:Alt>
+ <rdf:li rdf:parseType="Resource">
+ <xmpGImg:format>JPEG</xmpGImg:format>
+ <xmpGImg:width>256</xmpGImg:width>
+ <xmpGImg:height>256</xmpGImg:height>
+ <xmpGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA
+AQBIAAAAAQAB/+4AE0Fkb2JlAGQAAAAAAQUAAjSA/9sAhAAKBwcHBwcKBwcKDgkJCQ4RDAsLDBEU
+EBAQEBAUEQ8RERERDxERFxoaGhcRHyEhISEfKy0tLSsyMjIyMjIyMjIyAQsJCQ4MDh8XFx8rIx0j
+KzIrKysrMjIyMjIyMjIyMjIyMjIyMjI+Pj4+PjJAQEBAQEBAQEBAQEBAQEBAQEBAQED/wAARCAC1
+AQADAREAAhEBAxEB/8QBogAAAAcBAQEBAQAAAAAAAAAABAUDAgYBAAcICQoLAQACAgMBAQEBAQAA
+AAAAAAABAAIDBAUGBwgJCgsQAAIBAwMCBAIGBwMEAgYCcwECAxEEAAUhEjFBUQYTYSJxgRQykaEH
+FbFCI8FS0eEzFmLwJHKC8SVDNFOSorJjc8I1RCeTo7M2F1RkdMPS4ggmgwkKGBmElEVGpLRW01Uo
+GvLj88TU5PRldYWVpbXF1eX1ZnaGlqa2xtbm9jdHV2d3h5ent8fX5/c4SFhoeIiYqLjI2Oj4KTlJ
+WWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+hEAAgIBAgMFBQQFBgQIAwNtAQACEQMEIRIxQQVRE2Ei
+BnGBkTKhsfAUwdHhI0IVUmJy8TMkNEOCFpJTJaJjssIHc9I14kSDF1STCAkKGBkmNkUaJ2R0VTfy
+o7PDKCnT4/OElKS0xNTk9GV1hZWltcXV5fVGVmZ2hpamtsbW5vZHV2d3h5ent8fX5/c4SFhoeIiY
+qLjI2Oj4OUlZaXmJmam5ydnp+So6SlpqeoqaqrrK2ur6/9oADAMBAAIRAxEAPwCReWvLfleTyzo9
+zd6VYPJNY2zySy28JZ3aJGZmZkqSTlgApgSbTL/Dfk3/AKtOmf8ASNB/zRhoIsrk8reUZKlNH01q
+deNrAf1JjQWymEXlLyYIk9TRdLDU35WsFfxjys82Y5L18peSmPFdE0tiewtLcn/k3gSubyd5OUcm
+0LTFA7m0gA/5N4qt/wAKeSf+rLpX/SLb/wDVPFXf4U8k/wDVl0r/AKRbf/qnirX+FPJP/Vl0r/pF
+t/8Aqnirf+E/JPT9C6V/0i2//VPFVK+8o+T4oeX6D01fiAqLOH+EeSgLLGRoJY3l7yWp4tpOmgjs
+bWEH/k3lnCx4nfoDyT/1atM/6Rof+qePCvErWvlvyZJKtNH011rvS0hI6f8AGPAY7KJbph/hXyT/
+ANWPTf8ApCh/6pZXwlnYb/wr5K/6sem/9IUP/VLHhK2Hf4U8lf8AVj03/pDh/wCqWPCVsN/4T8l/
+9WPTf+kOH/qljRW3f4S8mf8AVi03/pDh/wCqWNJtv/CHk3/qxab/ANIcH/VPBS23/g/yd/1YtN/6
+Q4P+qeNKl975W8nxTEHRdOQAA/7yQgf8m8sjGwwlKihf0B5J/wCrVpn/AEiw/wDVPDwo4nfoDyT/
+ANWrTP8ApFh/6p48K8SNsvLHkt1YtoumsNqE2cJ/5lZGUWUZIn/Cvkn/AKsem/8ASFD/ANUsjwlN
+hv8Awp5K/wCrHpv/AEhQ/wDVLHhK2Hf4U8lf9WPTf+kOH/qljRW2/wDCfkv/AKsem/8ASHD/ANUs
+aK27/CXkz/qxab/0hw/9UsaTbf8AhDyb/wBWLTf+kOD/AKp4KVAa/wCSfLlxoOpwaXoWni/ltJ0t
+DHbQRuJmjcRcXKLxPKlDUUxpUhVVbyJoAbp9Vs/2Vb/j28HdBlh5MBzSpLdZHEcY5uxoqrDEST7A
+T5FLJNDebT0W1/R04aZwJJ/TWNaE0BZQ7fZByQQWTPoek3/G4vLWOaUqAXYGtB075CXNkOS+10HR
+7Kdbm1tI4po68XUGoqCp7+BwJa8wwSXOj3EESGV34URUWUmjofsOyA9PHFWE/oK//wCWKX/pBh/7
+KcKHfoK//wCWKX/pBh/7KcVVbXy5e3NwkMlu8CuTWWWyi4rtXelwTiqdWfksW91FPLcQSpGwYotq
+qE0/yhIaYLSn2ooJLcKTT4gf15KB3YzGzCtV0y1kv5Xk066uWPGssRojfCvTft0yZq2I5IaHRrCW
+VI20q8jDsFLs2ygmnI/F0GCh3J372SaZo1ppnJbQPRiXK1qSQOgrhugjmV/6Suv+rRffdH/1UyPE
+ypMrFWu4BNJDLasSR6cwHLbv8JODiTSC1bVINJmSF4pJjIvOqtGoG5FP3jqe2PEtIH/FdsP+PSb/
+AJGQf9VcbWl3+LLb/lkl/wCRkH/VXG1pv/F1t/yyTf8AIyD/AKq4LVO7PULK8SP0p4/VlUP6PNGd
+aipUhWO4742qF1S0juZJI5CeMicGA8CKHJwOzGQ3SH/B2j/yv/wRw0Fsu/wdo/8AK/8AwRxoLZTF
+5bfRLKP4HljBWFFVkBACmlTIy+GCUlAQ3+J7X/llm/5GQf8AVbBxJpv/ABRa/wDLLN/yMg/6q4OJ
+ab/xTa/8ss3/ACMg/wCquNppsea7Yf8AHpN/yMg/6q42tN/4stv+WSb/AJGQf9VcbVNtL1K11OMM
+hEUu/wC4Z0ZwB+1RGbbBartcvW0jRNR1WNRI9jaz3Ko2wYxRtIFNPHjjaaYbZ3Edt5I0GSSKGcG0
+s143Cs6g/VwagKr77ZPow6oWPWoYnWSKz09HU1VlhlBB9iIcFppONK8yRXcnoXjRpK7KsKxLKeRP
+iXjAGEFBCO1LzJcaZcLaxiAqEVv3gn5b/wDGKF1/HInmyHJB/wCNLz+W1+66/wCyfBSU1j8wPLoM
+uqr6RlhcIwpMIwSyDvF6n2XHRcCpV/jS8/ltfuuv+yfDSu/xpefy2v3XX/ZPjSu/xpefy2v3XX/Z
+PjSp7oGry6vDNJKIgY2Cj0hIBuK7+tHGcCo69/uf9kMlDmxlySC613SbOdra5uBHKlOSlWNKgMOi
+nscnYY0o/wCJ9C/5ax/wD/8ANGPEFoppp97bXCJewyc4CGbnQjZeQbYivbBLkkc2v8X+XP8AluT/
+AIF/+aMrZplZX9pqMAubKQTRElQ4BG46/aAxVj3mqLS5LyE32oRWTiL4UktknJHJt+To1PliqRi2
+8vHYa1b/APcPi/6p4UO+r+Xf+r1b/wDcPi/6p4q76v5d/wCr1b/9w+L/AKpYqyLy1pFnE36TtrmK
+9jdWSN0to4SprRiGRVb2wJTO8/vj8hlkeTGXNQwsXYqlPmQA6fHUoP3w/vBAR9l/+Wohfu3yMmUW
+M0T+e3/4HTv+a8il1E/nt/8AgdO/5rxV1E/nt/8AgdO/5rxV1E/nt/8AgdO/5rxVHfoHV/8Alhf/
+AKRrLFUVpum65Y3sM8drLGA6iThDaR8k5AspaM8qGmKsh85/8ofr3/bNvP8AkxJgSxnTrC41HyVo
+UFsUDrZ2bnmzIKC3A6xgnvllWGF7qH+FtX/ng/5HT/8ANOPCVtXsvLF6lyj3jp6Kmp9KaUtUdKc1
+p1xEVtNtV0DU9RuFubVohGUUfHPNGaj/ACYlK5E82Q5IP/CWufz2/wD0lXX/ADTgSn0XlmwihmgW
+S4K3AVXJmYkBWDjie24wKpf4Q0z/AH7df8j3xtXf4Q0z/ft1/wAj3xtV8HlbTreeO4SW5LROrqGm
+YglTUVHcbYqnWKoe9/uf9kMlDmxlyS/LGLsVVrb+/T5/wwS5JjzTLKmbsVYl5ue4W9hEMjIPS3Aa
+5Xfk3/LMjL9+EKkHq3v+/n/5Gah/1SxQ71b3/fz/APIzUP8AqliqrbJqN1OlvFMech4rylv1Ffdm
+jAGKs50e2urPT4ra8ZWmQtUq7yAgsWHxy0Y9cCVHVZGhWaVKco4yy1qRUAkV475OPJiebEP8T6r/
+AC23/Iu5/wCaMbWkzh8zWJjjEwk9UqOfCJ+PKm/GorSuG0Um1xb3dzb8bSG1ncOCVvQxQCh3Xirb
+4Jpihf0Xrf8A1b9F/wCAk/6pZBknC6TplBysrflTekSUr/wOKsSudSeG5miTT9O4xuyrytbgmgJA
+rxgI+7ChT/S0v/Vv03/pFuf+yfFUV/izWf5LX/kVef8AVHGkqkHmzU/Wj+spbiHkPU9OG7L8a/Fx
+5RAVpjSpn5ukWbyXrcqV4yaXdstRQ0NvIdwcCsX0kaivk/RDZTx2zmztPjmYBSvoLsKht8u6NXVr
+l5k/6udn/wAGv/VPBZ707Jzp7XUlsqzzpcTp/etCwK7k06U7e2SBDEhNo5vSRUlmVGpXizgH7i2Q
+JFsxdL0uEdgiTozNsAJFJJ/4LBYTurN6sal5G4KOrM1APpJxsLupi7g/5aI/+Ri/81Y2FbF5b/8A
+LRH/AMjF/wCasGyVwvbbvcR/8jF/5qx2VViuIZW4RSpI3WiuCafQcCuvK+jv/MMMeaJJDdWmrSzt
+JbaiLeI04xGBX40AB+IsK75Pdio/UNd/6uw/6RU/5rxorYR2l22oxSMLq9FyzikTeksfA0beiseX
+UYDySOar+jfMf/V6T/pDT/qplbNNLWO4it0juphcTKPjlCCPlv8AyAmmKpPr8+uRXMY0szCIpV/S
+t45hyqerSSoRtiqVC8839zdf9IUH/ZRhV31zzh/Ndf8ASFB/2UYq7655v8br/pCg/wCyjFU10O+1
+hpTb6pDcPzNVnkhjhRAB0IjletcCo68/vj8hlkeTGXNQwsXYqjLHo/zGQmyii8iydirzq+sLhr24
+YWE7AyuQwt7sg1Y7grcAfdhQofo+5/6t1x/0jXn/AGU4qmlr5Su7q3S4Cww8xX05hdI4oafEpuNs
+VVf8F3n81r991/2UY2lMPMVhBp3kXW7W3Xgo028LDkzfEYJORBkZj+OBWO208Nv5H0F5oIrlTaWY
+CTNxUH6uN6+OWdGHVA/pOw/6tdl/yMH9MFppkNhqXlu2ISzkhhkn4hlQEVbsOnvkgQggo3ULK4nn
+WSLRLbUF4KPXmkRWPtRgemQPNkOSnZWF5HdwSHy7aW4WRSZklQtGKirqAvUYEp1rkscOlXEs0Udw
+iqOUUxCo3xL9omuBWHW19ZXk6W1toenSyybIizJU0Ff5PbChMf0bef8AUsWX/I6P/mnFLv0bef8A
+UsWX/I6P/mnFU40PT44Fa5m0yDTbmpQCEq9Y6Ka8lA6ntgVH3v8Ac/7IZKHNjLkkF1pAup2n+uXc
+POnwQzFEFABstPbJ0xtTTQwjq/1++biQeLTkg07EUxpbTeFecgSpXkCKqaEVB3BxlyTHmo/4bT/q
+56l/0lN/TKmaZ2dqLK3W3Ess/Ek+pO5kc1Nd2OKsZ83XUsF7Csd1LbgxV4xyzxg/E29IIpBhVIBq
+NyN/0jcf9JN5/wBk2KHfpG5/6uNx/wBJN5/2TYq79IXP/VxuP+km8/7JsVZVoVhrlpdiW8kaW3kQ
+g+pdSTEdwVR0XfAlHaqJSswgr6pjPp0IB5UPGhbbrk48mJ5sQ9Hzd4XH/I23x3XZNY9K1P4WfVZu
+xZCifSK4aRacm1ubuEpbXb2TKwJeNVYkUO3xg4Jpipro+qggnWpyAdx6cW//AAuQZJzirAb3W9Vj
+vLiNL1lVJXVV+sWYoAxAFG3H04UKH6e1f/lub/pJssVd+ntX/wCW5/8ApJssVVrXzJqcFwks1wbm
+NT8UT3VmA23itDirIvNkhm8k61KV4GTSrpitQ1K28hpyGxwJY/pLunkzQjHPb25+pWg53dOB/cLs
+K03yzow6tfWLn/q5aT/wv/NWKphZXunpCPr15YvMCTyiZFFO3U4QVRt5qF1BIiQapp9qhRSI7k/v
+N+/94ux7ZWebIcm7DUb6a8iifVtNuFY7xQGsjClaL+9OBKbak7R2UrpLDAwApLc/3S7j7e4xVjw1
+C7U8l1jRgR0IoP8AmbhVf+ltQ/6vmkff/wBfsVd+ltQ/6vekff8A9fcVTjSJL2aFprq5trtGI9KS
+0B47V5VPJq4FRF7/AHP+yGShzYy5JBdasbadoPqN3Pwp+8hjDIagHY8x45O2NKP6dP8A1bL/AP5E
+j/qpja0i9N1Y3F0E+o3cPFWessYUGg+yPjO57YJHZIG6I/xE/wD1aNS/5Er/ANVcrZpjY3hvofWN
+vNa/EV9O4UI+1N6Bm23xVJfMcmmJdRC+t7yd/T+FrV+KgVOx/ex74qlAm8vf8sOqf8jT/wBlOFCt
+a3+h2dwlzDY6n6kZqvN+Q3FN1a4I74pTP/GFp/yw3v8AwEf/AFWwKmum6jHqdubmOKSEBinGYANt
+Tf4WYd8VU7z++PyGWR5MZc1DCxdiqMsej/MZCbKKLyLJ2KsKu/L2tS3U0kccpR5GZaXcaihJI2Ns
+affhQpf4b13/AH3L/wBJkf8A2S4qmNl5SaWANfXN1bzVNUSaNxTseXoDAlH2fli0s7hZzcXFzxBH
+pzmNkNRTcCJcVd5yAHk/XQBQDTLwAD/jBJirHtHhmn8m6EkFtBdsLK0JS5FUA9BfiGx3yzow6t/o
+/Uf+rRpn/Aj/AJpxpbTK20qxaBDdWFqkxHxqkSFQfYlcNItXvNPup5EeDS9PukCKBJcj95t2/u22
+HbKzzZjk1Z6fqMF1FL+iNMgCuOUsO0iqdmKfuhvTAlM9alSDS7iWSOKZFArHOpaM/EPtKqufwxVh
+v6YsP+rZpX/SPN/2SYUO/TFh/wBWzSv+keb/ALJcVd+mLD/q2aX/ANI83/ZLiqP0/wAyXbPHYadb
+2MfM0jiRbiNanf8A5Z1UYpZPcGQ2qGYBZDx5hTUBqb0OGHNjLkkd1ruk2c7W1zcCOVKclKsaVAYd
+FPY5Owxp1rruk3k621tcCSV68VCsK0BY9VHYY2FpM4XWOQSOaKgLMfAAEnGXJMeaNs7y2v7dLu0c
+SwyV4OAQDxJU9adxlTNXxVi3mqLS5LyE32oRWTiL4UktknJHJt+To1PliqR/V/Lv/V6t/wDuHxf9
+U8KHfV/Lv/V6t/8AuHxf9U8VTOzn8jQW6RXUtrdTLXlMbfgWqSR8KR0FBtilk2lrpv1NJNJVEtZS
+XX014qT9kmlB4YFQ+qxGZZoVpWSMoK1pVgRvShyceTE82Ir5SueQ5m2K1FQDPWn/ACMw0tpuvlrR
+UYMtuQVNR+9l6j/npjQRabHTLLU4TDexmREYMoDum9COsbKe+CaYqX+EdA/5Zn/5Hzf9VcgyTaGG
+O3hjgiHGOJQiAkmiqKDc1OKvPr6wuGvbhhYTsDK5DC3uyDVjuCtwB92FCh+j7np+jrj/AKRrz/sp
+xV36Puf+rdcf9I15/wBlOKr4tMupZEi+oTJzYLye3vAoqaVY/Wdhiqeappcmk+RPMNtKYyWsb2T9
+16hFDbMv+7nc1+HxwJQeh6hHpvk7Q55Y5JVaxtE4xAE1MCmvxMu22Wg0GFbq8fme3lbhFZXkjdaL
+GhP4SY8S0jLPUzdzekbO6t9iec8YVdu1eRxtFJhLrDWRWAafeXNFB9S3jV037VLrlcubMcnW+utP
+MkJ0y/i9RgvqSRKEWvdj6h2wJROrmBdNnNykskQA5pAaSH4h9k8k/XirFYbvQYJo547HVOcTB15S
+VFVNRUG5ocKE2/xjaf8ALBe/8BH/ANVsCXf4wtP+WG9/4CP/AKrYqjrLWWvJ1g/R97bhgT6s8SrG
+KCu7CRuuKou9/uf9kMlDmxlySxoYXPJ41YnqSATljFywwoeSRqpHQgAHFURbbzoD7/qwS5JjzTJV
+VRxUBQOw2GVM28VYh5wlMd9ABcPDWLokk6A/E29IYZBhCse+st/y2y/8j7v/ALJcUO+st/y2y/8A
+I+7/AOyXFXfWW/5bZf8Akfd/9kuKsz8s3OnvC0Fpd3F3KFV5RcGVghpQhGljTauBKJ1USMsyw19Q
+xkJQhTyoaUJ6b5OPJiebEPqnmnwuf+kuL/qnjuuyOs9J1WaHnd311ayVI9MSJJt48lUYaRaex2E1
+zarBHeTW7RceUsRXm9AR8XJT164JJit/QN5/1eb374/+qeQZJwilEVSxYqACx6mnc4q8/vdavo72
+4jW8lULK6gC8hUABiKcTbmmFCj+nb/8A5bZf+k6H/smxV36dv/8Altl/6Tof+ybFXfp2/wD+W2X/
+AKTof+ybFU3vL+TUPy8155TzaGwvYi5lWYtS3Z6syIgr8XSmBKzy5aW155R0OK6iWZBYWjBXFRUQ
+IK/jlo5NZ5plbaXp1pJ61tbpFJSnJRQ0ONLaKwqmdv8A3CfLKpc2Y5KuBKA1yCW40q4hgQySOoCo
+FR6/Ep+zL8J+nFWE/oHV/wDlhf8A6RrLCh36B1f/AJYX/wCkayxVGaf5VvbsuLpRZBAOJktLRuVa
+9OFemKswsYLm2txFdXBu5AT+9KLHt2HFNtsCW73+5/2QyUObGXJi9/5iisLuS0aB5DHT4g6AHkob
+ozA98mSilO380200yRPC0SuaGR5I+K+5+PBxLSdWd9ayzUtpkuHQFvTidWYgDwBxlyUc3fp68/6s
+1790f/VTK2abxOZI0kZTGXUMUbqpIrQ/LFWO+ZZdNju4hewXEzmP4TDOIgByPUGWOuKpN9Z0H/lj
+vf8ApMX/ALKMKHfWdB/5Y73/AKTF/wCyjFUTHbWUqCSLSdTdG3VluCQR7ET4qm+h6barKbxbW7s5
+IjxVbqVmDBhuQvqOMCUdef3x+QyyPJhLmoYUOxVGWPR/mMhNlFF5Fk7FXml/elb65X64y0mkFPrc
+q0+I7cRHthQh/rx/5bX/AOkyb/qliqJsEvtUma3sLiSaRVLlReyCiggV+KMd2xVObHS/MtjN64gF
+x8JXhcXbSJvTfiV67YpR/mX6x/gbWzdRJBOdMvDJHEaqD6MvQ/LAqRabZXd/5L0KGzdUkWztHJZ3
+QcRbqOsYJ75ZWzDqus/Ll/63+nz0hof7ieUtXt9sUxpbTux0+LT1dYpJZA5BJlcuRTwrhARaMl0S
+3vytxLPcxsVA4wzPGu3+SpyuXNmOTdt5ftbWdLhLi6dozULJO7KfmpO+BKpr5caRcmMlW4ihBcft
+L3hBf7sVYJ6t7/v5v+Dv/wDqlhQr2cGp39wttbz/ALxgSOc18g2FftNGBiqZf4Z8x/7/AIv+ku7/
+AOacUozTPLeoJPz1Oc+mgBT6vdTsSwI+0JABTFU/vf7n/ZDDDmxlyYtqFtdSXcjx6TaXSnjSaUpz
+b4R15KTt0yZQEN9Tvf8AqxWP3x/80YPgqdaTaR2/CdLKC2uyrBliVRv1481UbbDEjZRzTWwl1CWN
+m1G3S2kDUVY5PUBWnWvFcrZovFWMeaNSsbK7hjurKzumaPkGuvtAcmFB+6k2xVJf09pH/Vq0r8P+
+ybCh36e0j/q1aV+H/ZNiqMi87CCNYYLezijQUVEldVA9gIMUsxt5DNBFKwAMiKxANQCRXY7YFQOo
+CRmcRMEkKURiKgNTY0yyPJhLmkf1TzH/ANXCH/kT/bh3XZsWnmOorfwkd/3P9uO67JwYtQlhK6dc
+JbSBgWaSP1AVodqclyM0xUvqfmf/AKuVv/0jf9fMgyVrO216O4R72+hngFecaQ8GOxpRuZ74qx67
+8w61FdTRxyShEkZVpaRsKAkDc3Ir92FCl/iTXP8Afkv/AEhx/wDZVirv8Sa7/vyX/pDj/wCyrFU3
+0PWdSnl4X0FzMkxAimFssUaU5cizLM+BKJ85/wDKH69/2zbz/kxJiqR+X4bubyhoa2dwLWQWNoS5
+jElV9BPh4sRlo5NZ5on6hrv/AFdh/wBIqf8ANeNFbCY2yTxwIlzL68oryk4hOW/8orTCqtLZ6xOV
+kstSW0i4gCI26y79zyZ1yqXNmOTrew16OZHn1ZZolYF4xaonIdxyEhpgSiNZnmttMnnt3McqAFXC
+q1PiA+zIyL95xVh/+Idb/wCW5/8ApHtf+yrCh3+Idb/5bn/6R7X/ALKsVb/xDrf/AC3P/wBI9r/2
+VYqyDRdUBtvW1PVIZXloVjcRQtHSoIYJK4NcCU0u2V7cOhDKxBBG4II6jJQ5sZcmN3vmC2sbl7WS
+3nkaOlWjVSpqA21ZB45MljTVr5itry4S2jtrlWkNAzIvEe5pIdsbWk6hbhIHoW4gniu5NAdhjLkm
+PNR/xE//AFaNS/5Er/1Vypm7/ET/APVo1L/kSv8A1VxVDeY5bGO6iF0l+zGOoNk/BKVP2h6ib4ql
+SXmko6uItZJUggGUEbeI9fChN/8AGNp/yw3v/AR/9VsCVW281WlxOkBtbmHmaepKsaovuxEpxVOI
+p4Jq+jIknHrwYNSvjTFUBqcvoLNPTl6UZehNAeIJpXtk48mJ5sU/xm3/ACyRf9JK/wDVPDxLSNtd
+b1S+i9e00xZY6leQukpUfNMbRSdi41CG2ElnZi6mYr6kRmEfDYk/EVau+2CaYqf6S8x/9WVP+kxP
++qeQZJvEztGjSr6bsoLJXlxJG4r3pirB7zVtHS7nR9GsZHWRwztcRhmIY1YgxHc4UKP6Y0T/AKsl
+h/0kx/8AVHFXfpjRP+rJYf8ASTH/ANUcVRtv5yitIVt7WwtYYkrxRLxAoqeRoPS8TilM/Mly955D
+1e6dBEZ9KupOCsHADQSEUYAV2wKlOgahaab5P0Oe9k9KNrG0QNxZviMCGnwg+GWg0GFboj/FWg/8
+tX/JOT/mjHiC0Uxs7y2v4Bc2j+pExIDUK7jY7MAcKFWfzJoumMtrfXPpTBQxX05G2PTdEYZVLmzH
+J1t5s8v3c8drb3fOWZgiL6coqx6CrRgYEorXPq36KuPrkogg4jnIYxLxHJf2Cr139sVYTTyp/wBX
+dP8AuHp/2TYUIqwufJlrM0lzexXiFSojksVUA1B5VS3B7YpTA6v+X4p+7td+n+ht/wBUMVTaz07y
+5f2yXdpY2skMoJR/q6LUA06MgPbAqLukSO2VEUKikKqqKAACgAAyUObGXJI7nRdLu5muLm2WSV6c
+mNamgCjofAZOgxtu20bS7OZbi2t1jlWtGFaiooepxoLaZ239+nz/AIYy5JjzTLKmbsVYp5s065vL
+2GSG3eYLFxJS3jmAPJjTk8sdMKpF+gr/AP5Ypf8ApBh/7KcUO/QV/wD8sUv/AEgw/wDZTirv0Ff/
+APLFL/0gw/8AZTirLfLVvDbwyImnSWEgWMSySKqeswDfEFV3pvXb3wJRl4F9RuVOPHevSmTjyYnm
+gaaf/wAU/wDC5JCuiIi0jAVetFFB+GKou1dEVi7BQSOppkJpiiVkjfZGDU8CDkWS7FWFXeiaxJdT
+SJcUR5GZR9ekWgJJHwiPb5YUKX6C1v8A5aP+5hJ/1TxV36C1v/lo/wC5hJ/1TxV36C1v/lo/7mEn
+/VPFU28wRtD5B1eF39R49Juldi/qHl9Xk5DmeuBKC8ryxQ+U9EaZ1jU6faAFyAK+injlo5NZ5pl9
+esv+WiL/AINf642rvr1l/wAtEX/Br/XG1TWK6tY4kWSaNDxBozAGh+ZyuXNmOSol5aSMESeNmOwU
+OpJ/HAlQ1eKWfTZ4oXWKRgOLu7RqPiHV0+IYqxL9D6r/AMt9r/0n3OFDv0Pqv/Lfa/8ASfc4q79E
+ar/y32v/AEn3OKp1osl/ZBba9ubF7ZQx5JcSSTVJqN5abYEpveENAGU1BIII6EZKHNjLkkN1pAup
+2n+uXcPOnwQzFEFABstPbJ0xtR/QI/6uF/8A9JB/pjS2mtlB6YjtvUkailPUZqyHYivLxwS5JHNb
+/htP+rnqX/SU39MrZpjY2YsYfQE81x8RbncOZH3ptyPbbFWN+brqWC9hWO6ltwYq8Y5Z4wfibekE
+UgwqkH6Quf8Aq43H/STef9k2KHfpC5/6uNx/0k3n/ZNiqM0+LWNULrY3s8hiAL1vLlKVrT+8gXwx
+VnNjDJb2cMMrtJIiAOzsXYt3q53O+BKhexJMXikHJHXiy+IIoRk48mJSj/DOh/8ALGn3t/zVhpbT
+JUCqFUUCigHsMUIbUtHOsWywCVIvTkD1kiEwOzD7JZadcjJkELZeVtR012ex1KKBnFGKWabgf89c
+ilN7C01W3kZr/UFvEK0VBAsVDXrVXauKpHc+SnuLiWf61Avquz0NorEciTu3qiuG1U/8Cv8A8tdv
+/wBIa/8AVXG1d/gV/wDlrt/+kNf+quNq7/Ar/wDLXb/9Ia/9VcbVV1jSho/kPX7UOkhawvZGaOMR
+AkwOPshm7DAqF8uWlteeUdDiuolmQWFowVxUVECCv45aOTWeaN/QOjf8scX/AAONBbLv0Do3/LHF
+/wADjQWymv6G0m7RJbmzhmcKF5OgJoOg3yuXNmOS+HQ9HtpVngsoY5UNVdUAIPscCVPzFT9DXVSo
+HFd3EZH2l6+tRPvxV5/RP57f/gdO/wCa8KHUT+e3/wCB07/mvFXcY/57f/gdO/5rxVOtN0Gx1BYu
+GpWhmccmtlt7R3AHUH064pZfdIkdsscYColFVRsAAKADDDmxlySC6t9akuHe0vIoYTTijRciNhXe
+vjk92Oyl9U8x/wDVwh/5E/247p2TPTY71EVLmZZLj4qSKvFdwePw+2A8lHNMLCLUIo2XUbhLmQtV
+Wjj9MBadKcmytmi8VY55j1bUbC6ijs2dUaPk3CBZRWpHVpo6fdiqUf4k13/fkv8A0hx/9lWFCpFr
+vmOavo/WJOPXhZI1K+NLnFV/6W81f77uv+kBf+ynFKa6Be6xczypqSTKgSqGW2EArXxEslcCojVo
+ZnEzxuIf3ZpKxACGh+I18MsiRTCQ3YpGl4siM/mK2ZFYFl9SPcA7j7WN+a15J3+kdN/5b7b/AJHx
+/wDNeS4gx4SiYru0SD6y13AsLtxWUyoELCuwblSuAyCQCi7crdR+taypPGTTnG6utR7qTkeIMqKs
+Lebw/HHiC0UEdU0tGKvf2qspoQZ4wQR2+3jYWmxq+k/9XC1/5Hx/8142tLv0xpH/AFcbX/kfH/zX
+gtKKtbm2vFLWc8VwqGjGJ1cA+/EnBat39zb6fYXN9emltawyTTmnKkcal3+EVr8I6Y2rFPL99a6f
+5Q0Oa7cxo1jaICFZtzAh6IGPbLAdmB5on/E2if8ALQf+RUv/AFTx4gtF3+JtE/5aD/yKl/6p48QW
+im8uv6TpxW2vJmjlChioikfY9N0RhlcubMcnW/mbRbqZLeCdmklYKgMMq1J6btGBgSiNZFs2mTi7
+laCAgc5EXmVHIdF4vX7sVYf6Xlj/AKutx/0if9muFDvS8sf9XW4/6RP+zXFVSFfK0U0cralNKqMG
+Mb2nwsAa8Wpa9DirJtJuNBvXkk0mOMPDQOywGIgPWm7Rp/L2wJRl7/c/7IZKHNjLkw7VPMsmn38t
+mscLCPju7sG+JVbcBD45IyQA7TfMd1qN2ltHDCQd3KyNUID8RFUGINqQyWEsJAUHJgDxBNATQ0Fc
+MuSx5qP1zzP/ANW23/6Sf+veVM01tmneBGukEUxHxorcgD4BqCuKsb81X9ha3kKXdnaXTNFUNcsQ
+wHJthSN9sKpH+mNF/wCrXpv/AAbf9UMUImz81Wmn8/qVnY2/qU5+nK68uNaVpB74qmun+dbGUuNR
+kgtgAOBjZ5OR3rX90tMFJZBZ3ltf26Xdo4lhkrwcAgHiSp607jFVl56axSyTDlGqMXWnKqgbjj32
+yQQWNfpXyp/yxf8ATp/zZirv0r5U/wCWL/p0/wCbMVVr1tGu9IhkUy2lqZTwENvU8gGrWMxvQe9M
+BVDWQsi8dnZ6pqMXqNRVWD005N4/uABirI9P06eyd2lvp7wOKBZytF9xxVcCWKXFvoZnkL3d4G5t
+UC0BANex+rnChM4tS8rRxpG1oZCihS7WTVYgUqf3XfAlf+lfKv8Ayxf9OTf9UsVVoPMOgWwK20Mk
+IbciO1kUE+/GMYq35slSfyVrU8deEul3TryBBo1vIRUHcYqxmze1TyRoJu45JE+qWYAicRmv1cb1
+JXLOjDq1pt5ZwXBlsLG6mlCkECUSUBpvx5nEFSn1jqM93KY5bKa1AUtzlAoTUDjseu+EFFJhLqlx
+aFYYtOubpQoPqQhOO/b4nGVy5sxyU/09ef8AVmvfuj/6qYEoxNQnewa8NlOsimgtiF9U7gbfFT8c
+VQf6evP+rNe/dH/1UxV36evP+rNe/dH/ANVMVd+nrz/qzXv3R/8ANeKu/T15/wBWa9+6P/qpiqZX
+v9z/ALIZKHNjLkw7VNS1y3v5YrOKR4F48GW2eQGqqT8amh3yRJQAFlleeZb2UxAC3opblPbOimhA
+oCT13xBK7MmtBP8AuwzL6/Ghanw8+PWnhXGXJRzR9mt2tui3zpJcCvNogVQ7mlAST0ytmr4qkOv6
+jrFlcxx6dE8kbJyYpbPOOVSPtIy0+WKpV+nfNH/LPL/3D5v+qmFUyspPNV7AJxLBb1JHC4tpI327
+8TJgVX9DzX/y12X/ACJf/mvFUzs1u1t0W+dJLgV5tECqHc0oCSemKr5nEUTy8Wk4KW4IKs1BWiju
+TiqS/wCJx/1Z9V/6Rv8Am/Ch3+Jx/wBWfVf+kb/m/FXDzQB00fVf+kb/AJvxS3/ij/tT6r/0jf8A
+N+BXf4o/7U+q/wDSN/zfiqTuuhSO0j+X9XLOSxPCYbnftcYVVLWXR7K4S6ttA1dJYzVWMcrUqKdG
+nI74qmn+KP8AtT6r/wBI3/N+BXf4o/7U+q/9I3/N+KqXmS7+veR9cufQmtuWm3o9K4ThIKQyjdan
+FWOW1xBb+R9Be4hiuFNpZgJMSFB+rjfYHfbLOjDqh7XzBbWTmS1s7SF2HEsjsCR1p/d+2C00mun+
+bLSYuL947cjj6fAu/Kta1+DbthEkEMiluNbiKrY2UVxDxFHebga9xx4HIS5shyV9Pn1aV3Go2sds
+oHwGOX1CT4EcVwJRN09ylu72kazTgfBG7cATXu1DTFUr+ueZ/wDq22//AEk/9e8Vd9c8z/8AVtt/
++kn/AK94qj9Pl1GVHOo26WzA/AI5PUBHiTxXFUXiqHvf7n/ZDJQ5sZcmPXWl3FzcPNHqFxbq1KRx
+kcRQAbVHtk6Y2pro12rBjql0wBBoStD+GNJtOYVLyBQxUsCAw6ioO4xlyWPNR/QN5/1eb374/wDq
+nlTNH2FnLZRtHLdS3hZuQebjUClKDiFxVj/mzUbmzvYY4bh4Q0XIhLiOEE8mFeLxSVwqkX6dv/8A
+ltl/6Tof+ybFDX6dv/8Alul/6Tof+ybFW/07f/8ALbL/ANJ0P/ZNirNtL0+5tmFxPfXF16kdPSmK
+Mqk8WqCqLuKUwJRV/T6jc1pT0ZK8iQPsnqRuMVeaf6P/AC2X/SXP/wA14UOrb/y2X/SXP/zXirv9
+H/lsv+kuf/mvFXf6P/LZf9Jc/wDzXirq2/8ALZf9Jc//AFUxV3+j/wAtl/0lz/8ANeKurbfy2X/S
+VP8A9VMVd/o/8tl/0lz/APNeKtH6v1C2X/SVP/1UxVlut2f1D8vtYtigjddLvC6Bi4DtBIWozEml
+cCUm0+7vLLyVoMtlT1DZ2amqNJ8JtweifLLOjDqh/wBPa/4L/wBI8v8ATGymgrWuq+Yru4S3jMaM
+9aNJBIqigLbkj2xsooMolj8yMIzp81okPBaiZXLcv2vs9sgebIcl9nH5nW5Q301m1uCfUWJXDkU/
+Z5bdcCUXq09xa6dPPaUMyAFKo0m9QPsJ8RxViv8AiLzN/Kn/AEh3GFDX+IvM38qf9Idx/TFW/wDE
+Xmb+VP8ApDuMVVrTzHrS3KG+jLWwJ9RYrScORQ0oSKdcUsluJBLapKoID8WAYUIBFdxhhzYy5MR1
+TWtVtL+W3too2iTjxLQzOd1Vj8SGnU5IkoAW2OreYL+UwxR20ZVS9ZYp0FAQOpbrviCVoMltPX/d
+8uHr8d6V4c+P30rjLko5qdPN/wDPpv8AwM//ADXlbNN4vU9NPW4+pxHPhXjypvxrvSuKsf8AMd9e
+2t1EltbQzq0dS0ttLOQanYNFsPliqUfpjVf+WC1/6QLnCh36Y1X/AJYLX/pAucVThbHzCwDCHSNx
+XeGX/mrAlOrEXwtwNRMJnqf95wwSnb7ZJxVu+r9SuKVr6T04qHP2T0Q0DfLFXnXG4/5ff+4TB/1W
+wodxuP8Al9/7hMH/AFWxV3G4/wCX3/uEwf8AVbFXcbjb/ezf/tUwf9VsVdxuP+X3/uEwf9VsVdxu
+P+X3/uEwf9VsVdxuP+X3/uEwf9VsVdxuP+X3/uEwf9VsVZNoGgnit9eyJdQzRnjbzWcULoxI+JuJ
+begO3vgSjPOf/KH69/2zbz/kxJiqR+X4bqfyhoaWlybRxY2hLhFkqPQT4aPtlo5NZ5on9Ha3/wBX
+c/8ASNFjRWwuSw1lXVn1YuoILL9XiFR3FRjRWwmstjq1wVks9Uazi4gCIQRybjqeTiuVy5sxydb6
+drUcyST6w08asC8Rt4l5DuvJRUYEq+tTzW2l3E8EnoyIAVk+Db4gP93EJ9+KsN/xDrX/AFc/xsP+
+qmFDv8Q61/1c/wAbD/qpirv8Q61/1c/xsP8AqpirMtJury5th9dt3gkQKpaQofVNN3AjJAqcCVe9
+/uf9kMlDmxlyYXqw8wfpCX6ibgW/w8PTEZX7K1pyNeuSNoFKNpB5luJ1imuLm2Q1rKyRkCgr0DY7
+rsy6FWaQKrcGYEBhvQkHfDLkseana6Tq8FxHLPrElxGhq0RhRQw8KjfKmacYqx/zCNeNzF+imuBF
+6fx+iIiOVT19VgemKpbbxeb5ZkilnvIUdgGkZLchQe5AeuFCa/oXXf8Aq+y/8iI8CXfoXXf+r7L/
+AMiI8VRmm6fqNpKz3movfIy0VHjVApr9qq4qi7uNpbWaJV5s8bKFJ4gkginIdMVYX/hjUf8Aq2Rf
+9Jkv/NWFDv8ADGo/9WyL/pMl/wCasVd/hjUf+rZF/wBJkv8AzViqta+Vrl7iNbzT0jgJ/eOl3KzA
+ew5Yqm/+DdC/33L/AMjpP+asFpd/g3Qv99y/8jpP+asbV3+DdC/33L/yOk/5qxtXf4N0L/fcv/I6
+T/mrG1R2maNY6T6v1JXX1uPPm7P9nlSnIn+bFUJ5z/5Q/Xv+2bef8mJMVY1puoyaZ5L0KeLgS1na
+J+85kUNup/3WrH9nLLoMK3Uv8W3fhbfdP/1Tx4l4U60TVW1SGRpOHqRNQiMOBxI+H+8Vd6g4QbQQ
+v1LzJcaZcLaxiAqEVv3gn5b/APGKF1/HIHmzHJB/41vP5bX7rr/snwUlN/0q1z5dk1KeOCQ71Rlk
+aI0cLuGj5/8AC4FY7+n7f/lg03/kTP8A9kuFDv0/b/8ALBpv/Imf/slxV36ft/8Alg03/kTP/wBk
+uKsl0u91u89CeSC1WylFecbyc+NDSiPGvfxwJTG9/uf9kMlDmxlyYXq2l39zqEs0FzDHG3GivPKj
+CiqN1QUHTJEIBQf6E1T/AJbLf/pKm/pjRTbKNEtzFaQ20sgdgHV3Ry27ciaO2/fE8kDmv/w/pn/L
+ddf9Jb/81ZWzTSxtobS2WCCR5UUmjyOZG3Nd2OKpR5h03Ub25iks54okWPiwkuJoSTUn7MQocVQm
+n+X5iX/St4QKD0/q15MTXevL1KYVR3+H9M/5brr/AKS3/wCasCqkGgWCypJHd3TtGQ4U3LsDQ13F
+emKpzirTcuJ4/aptXxxVJYNO1+DmDfiUFQELdQQoWpDI/cb+Neviqrm31wMvG6RlUmvMLVl7fZhA
+U/fT3xVEWFvewBze3H1h2puAAooT0UKKbUxVGYq7FXYq7FXYq7FUl85/8ofr3/bNvP8AkxJiqV+U
+v+UV0T/tn2v/ACZjy0cms802wq7FUBqWg6jqFwtzbNAIyirSSS4Vqj2hkVcrPNmOSja+U7/6wn11
+4Tb1/eCGa6D0p+zzlI64LSyazs4bC3W2t+XpqSRzYudzX7TEnAqvirsVdirsVQ97/c/7IZKHNjLk
+xLUvLJ1C9kvBcJH6nH4WgDkcVC/aLivTJGKAWrLypaQM5vTHdggcQIvT4n/Yua4iK2nmnWNpa0tY
+IgkLFqoK0PIUPXGXJRzVP8LeX/8Algi+4/1ytmj7SytbCEW9nEsMQJIRelT1xVKtd8uNrNxHOJ4o
+vTThSSATE7k/aLrTriqXReRgsiNLcwSIrAsn1RV5AHcV9XauG1Tf/C3l/wD5YIvuP9cCoiy0bS9O
+lM9jbJBIylCyVqVJBp+GKo7FVC+5fUrjhXl6T8aVrXiaU4/F92KvOqat/Pcf8Dff814UOpq389x/
+wN9/zXirqat/Pcf8Dff814q6mrfz3H/A33/NeKupq389x/wN9/zXirqat/Pcf8Dff814q6mrfz3H
+/A33/NeKupq389x/wN9/zXiqN0/Std1L1PRuDF6XGvrteR15V+zyffpiqZ6tp91p3kTX4ryX1pns
+L1iweR1p6DgU9Us3bAlb5S/5RXRP+2fa/wDJmPLRyazzTbCrsVTO3/uE+WVS5sxyVcCXYq7FXYq7
+FXYqh73+5/2QyUObGXJL8sYuxVWtv79Pn/DBLkmPNMsqZuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ku
+xV2KuxV2KpL5z/5Q/Xv+2bef8mJMVf/Z</xmpGImg:image>
+ </rdf:li>
+ </rdf:Alt>
+ </xmp:Thumbnails>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:idPriv="http://ns.adobe.com/xmp/InDesign/private">
+ <idPriv:DocChangeCount>244</idPriv:DocChangeCount>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <dc:format>application/pdf</dc:format>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
+ <pdf:Producer>Adobe PDF Library 9.0; modified using iTextSharp 4.1.6 by 1T3XT</pdf:Producer>
+ <pdf:Trapped>False</pdf:Trapped>
+ </rdf:Description>
+ </rdf:RDF>
+</x:xmpmeta><?xpacket end="w"?>
+endstream
+endobj
+59 0 obj
+<</ArtBox[0.0 0.0 841.89 595.276]/MediaBox[0.0 0.0 841.89 595.276]/Type/Page/BleedBox[0.0 0.0 841.89 595.276]/Contents 63 0 R/CropBox[0.0 0.0 841.89 595.276]/Resources<</Font<</C2_2 58 0 R/C2_1 57 0 R/C2_0 56 0 R>>/ExtGState<</GS13 203 0 R/GS12 202 0 R/GS11 201 0 R/GS10 200 0 R/GS9 214 0 R/GS8 213 0 R/GS7 212 0 R/GS6 211 0 R/GS5 210 0 R/GS4 209 0 R/GS3 208 0 R/GS2 207 0 R/GS1 199 0 R/GS0 91 0 R/GS16 206 0 R/GS15 205 0 R/GS14 204 0 R>>/Shading<</Sh6 150 0 R/Sh5 149 0 R/Sh4 148 0 R/Sh3 147 0 R/Sh2 146 0 R/Sh1 140 0 R/Sh0 139 0 R/Sh14 145 0 R/Sh13 144 0 R/Sh12 143 0 R/Sh11 142 0 R/Sh10 141 0 R/Sh9 153 0 R/Sh8 152 0 R/Sh7 151 0 R>>/ProcSet[/PDF/Text]/ColorSpace<</CS0 85 0 R/CS1 100 0 R>>/Properties<</MC0<</Metadata 192 0 R>>>>/XObject<</Fm9 82 0 R/Fm8 81 0 R/Fm7 80 0 R/Fm6 79 0 R/Fm5 78 0 R/Fm4 77 0 R/Fm3 76 0 R/Fm2 75 0 R/Fm1 66 0 R/Fm0 65 0 R/Fm17 74 0 R/Fm16 73 0 R/Fm15 72 0 R/Fm14 71 0 R/Fm13 70 0 R/Fm12 69 0 R/Fm11 68 0 R/Fm10 67 0 R>>>>/Parent 3 0 R/Annots[342 0 R 359 0 R]/Group 64 0 R/TrimBox[0.0 0.0 841.89 595.276]>>
+endobj
+3 0 obj
+<</Type/Pages/ITXT(4.1.6)/Kids[59 0 R 5 0 R]/Count 2>>
+endobj
+1 0 obj
+<</Type/Catalog/Pages 3 0 R/DSS 356 0 R/AcroForm<</DA(/Helv 0 Tf 0 g )/Fields[342 0 R 359 0 R]/SigFlags 3/DR<</Font<</Helv 343 0 R/ZaDb 344 0 R>>>>>>/ViewerPreferences<</Direction/L2R>>/Metadata 2 0 R>>
+endobj
+55 0 obj
+<</Creator(Adobe InDesign CS4 \(6.0.5\))/Producer(Adobe PDF Library 9.0; modified using iTextSharp 4.1.6 by 1T3XT)/CreationDate(D:20100702153226-07'00')/Trapped/False/ModDate(D:20130906162305+02'00')>>
+endobj
+xref
+0 4
+0000000000 65535 f
+0000457235 00000 n
+0000411292 00000 n
+0000457165 00000 n
+55 1
+0000457453 00000 n
+59 1
+0000456112 00000 n
+357 3
+0000390428 00000 n
+0000411086 00000 n
+0000390296 00000 n
+trailer
+<</Size 360/ID [<c94cabd6d311d14656ede5448fcba052><8ab700b1cd51e5dc8899e4d7fb138f4b>]/Info 55 0 R/Prev 389780/Root 1 0 R>>
+startxref
+457671
+%%EOF
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/dict-bool.pdf b/xmlsecurity/qa/unit/pdfsigning/data/dict-bool.pdf
new file mode 100644
index 000000000..cd87f71ec
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/dict-bool.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/forcepoint16.pdf b/xmlsecurity/qa/unit/pdfsigning/data/forcepoint16.pdf
new file mode 100644
index 000000000..9edccb47f
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/forcepoint16.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/good-custom-magic.pdf b/xmlsecurity/qa/unit/pdfsigning/data/good-custom-magic.pdf
new file mode 100644
index 000000000..2c532cbf6
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/good-custom-magic.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/good-non-detached.pdf b/xmlsecurity/qa/unit/pdfsigning/data/good-non-detached.pdf
new file mode 100644
index 000000000..8e5b21511
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/good-non-detached.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/good-pades.pdf b/xmlsecurity/qa/unit/pdfsigning/data/good-pades.pdf
new file mode 100644
index 000000000..987169eee
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/good-pades.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/good.pdf b/xmlsecurity/qa/unit/pdfsigning/data/good.pdf
new file mode 100644
index 000000000..f28566442
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/good.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/name-bracket.pdf b/xmlsecurity/qa/unit/pdfsigning/data/name-bracket.pdf
new file mode 100644
index 000000000..ac152793c
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/name-bracket.pdf
@@ -0,0 +1,2241 @@
+%PDF-1.7
+%öäüß
+1 0 obj
+<<
+/Metadata 2 0 R
+/Outlines 3 0 R
+/OutputIntents [4 0 R]
+/PageLabels 5 0 R
+/Pages 6 0 R
+/Type /Catalog
+/Extensions <<
+/ESIC <<
+/BaseVersion /1.7
+/ExtensionLevel 2
+>>
+/LTUd <<
+/BaseVersion /1.7
+/ExtensionLevel 1
+>>
+>>
+>>
+endobj
+7 0 obj
+<<
+/Author (Petras)
+/CreationDate (D:20120616164408+03'00')
+/Creator (PScript5.dll Version 5.2.2)
+/ModDate (D:20120616164534+03'00')
+/Producer (Acrobat Distiller 10.1.3 \(Windows\))
+/Title (Untitled - Notepad)
+>>
+endobj
+2 0 obj
+<<
+/Type /Metadata
+/Subtype /XML
+/Length 8 0 R
+>>
+stream
+<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
+<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.1.0-jc003">
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description rdf:about=""
+ xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/"
+ xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema#"
+ xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#"
+ xmlns:pdfaType="http://www.aiim.org/pdfa/ns/type#"
+ xmlns:pdfaField="http://www.aiim.org/pdfa/ns/field#">
+ <pdfaExtension:schemas>
+ <rdf:Bag>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaSchema:schema>PDF-LT-V1.0 elektroninio dokumento metaduomenų plėtinio schema</pdfaSchema:schema>
+ <pdfaSchema:namespaceURI>http://archyvai.lt/pdf-ltud/2011/metadata/</pdfaSchema:namespaceURI>
+ <pdfaSchema:prefix>LTUd</pdfaSchema:prefix>
+ <pdfaSchema:property>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>standardVersion</pdfaProperty:name>
+ <pdfaProperty:valueType>closed Choice of Text</pdfaProperty:valueType>
+ <pdfaProperty:category>internal</pdfaProperty:category>
+ <pdfaProperty:description>Elektroninio dokumento specifikacijos identifikatorius (pvz., PDF-LT-V1.0)</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>authors</pdfaProperty:name>
+ <pdfaProperty:valueType>seq Entity</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>Dokumento sudarytojas (-ai)</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>recipients</pdfaProperty:name>
+ <pdfaProperty:valueType>seq Entity</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>Dokumento adresatas (-ai)</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>instanceIdentifier</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>Dokumento egzemplioriaus identifikatorius</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>originalRegistrations</pdfaProperty:name>
+ <pdfaProperty:valueType>seq Registration</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>Originalaus dokumento registracija (-os) kopijoje</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>originalReceptions</pdfaProperty:name>
+ <pdfaProperty:valueType>seq Registration</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>Gauto originalaus dokumento registracija (-os) kopijoje</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>originalReceivers</pdfaProperty:name>
+ <pdfaProperty:valueType>seq Entity</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>Originalaus dokumento gavÄ—jas (-ai) kopijoje</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>registration</pdfaProperty:name>
+ <pdfaProperty:valueType>Registration</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>Sudaryto dokumento registracija</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>reception</pdfaProperty:name>
+ <pdfaProperty:valueType>Registration</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>Gauto dokumento registracija</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>receiver</pdfaProperty:name>
+ <pdfaProperty:valueType>Entity</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>Dokumento gavÄ—jas</pdfaProperty:description>
+ </rdf:li>
+ </rdf:Seq>
+ </pdfaSchema:property>
+ <pdfaSchema:valueType>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaType:description>Asmuo (sudarytojas, adresatas, gavÄ—jas)</pdfaType:description>
+ <pdfaType:namespaceURI>http://archyvai.lt/pdf-ltud/2011/metadata/Entity/</pdfaType:namespaceURI>
+ <pdfaType:prefix>LTUdEnt</pdfaType:prefix>
+ <pdfaType:type>Entity</pdfaType:type>
+ <pdfaType:field>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaField:name>individual</pdfaField:name>
+ <pdfaField:valueType>Boolean</pdfaField:valueType>
+ <pdfaField:description>Požymis: fizinis (taip) ar juridinis (ne) asmuo</pdfaField:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaField:name>name</pdfaField:name>
+ <pdfaField:valueType>Text</pdfaField:valueType>
+ <pdfaField:description>Juridinio asmens pavadinimas arba fizinio asmens vardas ir pavardÄ—</pdfaField:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaField:name>code</pdfaField:name>
+ <pdfaField:valueType>Text</pdfaField:valueType>
+ <pdfaField:description>Juridinio ar fizinio asmens kodas</pdfaField:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaField:name>address</pdfaField:name>
+ <pdfaField:valueType>Text</pdfaField:valueType>
+ <pdfaField:description>Adresas</pdfaField:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaField:name>eMail</pdfaField:name>
+ <pdfaField:valueType>Text</pdfaField:valueType>
+ <pdfaField:description>El. pašto adresas</pdfaField:description>
+ </rdf:li>
+ </rdf:Seq>
+ </pdfaType:field>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaType:description>Sudaryto ar gauto dokumento registracija</pdfaType:description>
+ <pdfaType:namespaceURI>http://archyvai.lt/pdf-ltud/2011/metadata/Registration/</pdfaType:namespaceURI>
+ <pdfaType:prefix>LTUdReg</pdfaType:prefix>
+ <pdfaType:type>Registration</pdfaType:type>
+ <pdfaType:field>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaField:name>date</pdfaField:name>
+ <pdfaField:valueType>Date</pdfaField:valueType>
+ <pdfaField:description>Registravimo data</pdfaField:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaField:name>number</pdfaField:name>
+ <pdfaField:valueType>Text</pdfaField:valueType>
+ <pdfaField:description>Registracijos numeris</pdfaField:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaField:name>code</pdfaField:name>
+ <pdfaField:valueType>Text</pdfaField:valueType>
+ <pdfaField:description>Juridinio ar fizinio asmens kodas</pdfaField:description>
+ </rdf:li>
+ </rdf:Seq>
+ </pdfaType:field>
+ </rdf:li>
+ </rdf:Seq>
+ </pdfaSchema:valueType>
+ </rdf:li>
+ </rdf:Bag>
+ </pdfaExtension:schemas>
+ </rdf:Description>
+ <rdf:Description rdf:about=""
+ xmlns:LTUd="http://archyvai.lt/pdf-ltud/2011/metadata/">
+ <LTUd:standardVersion>PDF-LT-V1.0</LTUd:standardVersion>
+ </rdf:Description>
+ </rdf:RDF>
+</x:xmpmeta>
+<?xpacket end="r"?>
+endstream
+endobj
+3 0 obj
+<<
+/Count 0
+/Type /Outlines
+>>
+endobj
+4 0 obj
+<<
+/DestOutputProfile 9 0 R
+/Info (sRGB IEC61966-2.1)
+/OutputCondition ()
+/OutputConditionIdentifier (Custom)
+/RegistryName (http://www.color.org)
+/S /GTS_PDFA1
+/Type /OutputIntent
+>>
+endobj
+5 0 obj
+<<
+/Nums [0 10 0 R]
+>>
+endobj
+6 0 obj
+<<
+/Count 1
+/Kids [11 0 R]
+/MediaBox [0 0 595.2199707031 842]
+/Type /Pages
+>>
+endobj
+8 0 obj
+9317
+endobj
+9 0 obj
+<<
+/Filter /FlateDecode
+/Length 2574
+/N 3
+/Range [0 1 0 1 0 1]
+>>
+stream
+H‰œ–yTSwÇoÉž•°Ãc [€°5la‘QIBHØADED„ª•2ÖmtFOE.®c­Ö}êÒõ0êè8´׎8GNg¦Óïï÷9÷wïïÝß½÷ó
+ 
+V³)gB£0ñiœWו8#©8wÕ©•õ8_Å٥ʨQãüÜ«QÊj@é&»A)/ÇÙgº>'K‚ó
+€x¯Íú·¶Ò-
+¨ꇆ¡Ðnè÷ÐQètº}MA ï —0Óal»Á¾°ŽSàx ¬‚kà&¸^Á£ð>ø0|>_ƒ'á‡ð,ÂG!"F$H:Rˆ”!z¤éF‘Qd?r 9‹\A&‘GÈ ”ˆrQ ¢áhš‹ÊÑ´íE‡Ñ]èaô4zBgÐ×Á–àE#H ‹*B=¡‹0HØIøˆp†p0MxJ$ùD1„˜D, V›‰½Ä­ÄÄãÄKÄ»ÄY‰dEò"EÒI2’ÔEÚBÚGúŒt™4MzN¦‘Èþär!YKî ’÷?%_&ß#¿¢°(®”0J:EAi¤ôQÆ(Ç()Ó”WT6U@ æP+¨íÔ!ê~êêmêæD ¥eÒÔ´å´!ÚïhŸÓ¦h/èº']B/¢éëèÒÓ¿¢?a0nŒhF!ÃÀXÇØÍ8ÅøšñÜŒkæc&5S˜µ™˜6»lö˜Iaº2c˜K™MÌAæ!æEæ#…åÆ’°d¬VÖë(ëk–Íe‹Øél »—½‡}Ž}ŸCâ¸qâ9
+N'çÎ)Î].ÂuæJ¸rî
+î÷ wšGä xR^¯‡÷[ÞoÆœchžgÞ`>bþ‰ù$á»ñ¥ü*~ÿ ÿ:ÿ¥…EŒ…ÒbÅ~‹ËÏ,m,£-•–Ý–,¯Y¾´Â¬â­*­6X[ݱF­=­3­ë­·YŸ±~dó ·‘ÛtÛ´¹i ÛzÚfÙ6Û~`{ÁvÖÎÞ.ÑNg·Åî”Ý#{¾}´}…ý€ý§ö¸‘j‡‡ÏþŠ™c1X6„Æfm“Ž;'_9 œr:œ8Ýq¦:‹ËœœO:ϸ8¸¤¹´¸ìu¹éJq»–»nv=ëúÌMà–ï¶ÊmÜí¾ÀR 4 ö
+n»3Ü£ÜkÜGݯz=Ä•[=¾ô„=ƒ<Ë=G</zÁ^Á^j¯­^—¼ Þ¡ÞZïQïBº0FX'Ü+œòáû¤útøŒû<öuñ-ôÝà{Ö÷µ__•ß˜ß-G”,ê}çïé/÷ñ¿ÀHh 8ðm W 2p[àŸƒ¸AiA«‚Ný#8$X¼?øAˆKHIÈ{!7Ä<q†¸Wüy(!46´-ôãÐaÁa†°ƒa†W†ï ¿¿@°@¹`lÁݧYÄŽˆÉH,²$òýÈÉ(Ç(YÔhÔ7ÑÎÑŠèÑ÷b<b*böÅ<Žõ‹ÕÇ~ûL&Y&9‡Ä%ÆuÇMÄsâsã‡ã¿NpJP%ìM˜I JlN<žDHJIÚtCj'•KwKg’C’—%ŸN¡§d§ §|“ꙪO=–§%§mL»½Ðu¡váx:H—¦oL¿“!ȨÉøC&13#s$ó/Y¢¬–¬³ÙÜìâì=ÙOsbsúrnåºçsOæ1óŠòvç=ËËïÏŸ\ä»hÙ¢óÖê‚#…¤Â¼Â…³‹ãoZ<]TÔUt}‰`IÃ’sK­—V-ý¤˜Y,+>TB(É/ÙSòƒ,]6*›-•–¾W:#—È7Ë*¢ŠÊe¿ò^YDYÙ}U„j£êAyTù`ù#µD=¬þ¶"©b{ųÊôÊ+¬Ê¯: !kJ4Gµm¥ötµ}uCõ%—®K7YV³©fFŸ¢ßY Õ.©=bàá?SŒîÆ•Æ©ºÈº‘ºçõyõ‡Ø Ú† žkï5%4ý¦m–7Ÿlqlio™Z³lG+ÔZÚz²Í¹­³mzyâò]íÔöÊö?uøuôw|¿"űN»ÎåwW&®ÜÛe֥ﺱ*|ÕöÕèjõê‰5k¶¬yÝ­èþ¢Ç¯g°ç‡^yïkEk‡Öþ¸®lÝD_p߶õÄõÚõ×7DmØÕÏîoê¿»1mãál {àûMśΠnßLÝlÜ<9”úO
+¾„¾ÿ¿z¿õÀpÀìÁgÁãÂ_ÂÛÃXÃÔÄQÄÎÅKÅÈÆFÆÃÇAÇ¿È=ȼÉ:ɹÊ8Ê·Ë6˶Ì5̵Í5͵Î6ζÏ7ϸÐ9кÑ<ѾÒ?ÒÁÓDÓÆÔIÔËÕNÕÑÖUÖØ×\×àØdØèÙlÙñÚvÚûÛ€ÜÜŠÝÝ–ÞÞ¢ß)߯à6à½áDáÌâSâÛãcãëäsäüå„æ æ–çç©è2è¼éFéÐê[êåëpëûì†ííœî(î´ï@ïÌðXðåñrñÿòŒóó§ô4ôÂõPõÞömöû÷Šøø¨ù8ùÇúWúçûwüü˜ý)ýºþKþÜÿmÿÿ
+endstream
+endobj
+10 0 obj
+<<
+/S /D
+>>
+endobj
+11 0 obj
+<<
+/Contents 12 0 R
+/Parent 6 0 R
+/Resources <<
+/ColorSpace <<
+/CS0 [/ICCBased 13 0 R]
+>>
+/ExtGState <<
+/GS0 14 0 R
+>>
+/Font <<
+/TT0 15 0 R
+>>
+/ProcSet [/PDF /Text]
+/XObject <<
+>>
+>>
+/Type /Page
+>>
+endobj
+12 0 obj
+<<
+/Filter /FlateDecode
+/Length 99
+>>
+stream
+H‰Rp
+áÒw6PH.æ2P
+endstream
+endobj
+13 0 obj
+<<
+/Alternate /DeviceRGB
+/Filter /FlateDecode
+/Length 2574
+/N 3
+>>
+stream
+H‰œ–yTSwÇoÉž•°Ãc [€°5la‘QIBHØADED„ª•2ÖmtFOE.®c­Ö}êÒõ0êè8´׎8GNg¦Óïï÷9÷wïïÝß½÷ó
+ 
+V³)gB£0ñiœWו8#©8wÕ©•õ8_Å٥ʨQãüÜ«QÊj@é&»A)/ÇÙgº>'K‚ó
+€x¯Íú·¶Ò-
+¨ꇆ¡Ðnè÷ÐQètº}MA ï —0Óal»Á¾°ŽSàx ¬‚kà&¸^Á£ð>ø0|>_ƒ'á‡ð,ÂG!"F$H:Rˆ”!z¤éF‘Qd?r 9‹\A&‘GÈ ”ˆrQ ¢áhš‹ÊÑ´íE‡Ñ]èaô4zBgÐ×Á–àE#H ‹*B=¡‹0HØIøˆp†p0MxJ$ùD1„˜D, V›‰½Ä­ÄÄãÄKÄ»ÄY‰dEò"EÒI2’ÔEÚBÚGúŒt™4MzN¦‘Èþär!YKî ’÷?%_&ß#¿¢°(®”0J:EAi¤ôQÆ(Ç()Ó”WT6U@ æP+¨íÔ!ê~êêmêæD ¥eÒÔ´å´!ÚïhŸÓ¦h/èº']B/¢éëèÒÓ¿¢?a0nŒhF!ÃÀXÇØÍ8ÅøšñÜŒkæc&5S˜µ™˜6»lö˜Iaº2c˜K™MÌAæ!æEæ#…åÆ’°d¬VÖë(ëk–Íe‹Øél »—½‡}Ž}ŸCâ¸qâ9
+N'çÎ)Î].ÂuæJ¸rî
+î÷ wšGä xR^¯‡÷[ÞoÆœchžgÞ`>bþ‰ù$á»ñ¥ü*~ÿ ÿ:ÿ¥…EŒ…ÒbÅ~‹ËÏ,m,£-•–Ý–,¯Y¾´Â¬â­*­6X[ݱF­=­3­ë­·YŸ±~dó ·‘ÛtÛ´¹i ÛzÚfÙ6Û~`{ÁvÖÎÞ.ÑNg·Åî”Ý#{¾}´}…ý€ý§ö¸‘j‡‡ÏþŠ™c1X6„Æfm“Ž;'_9 œr:œ8Ýq¦:‹ËœœO:ϸ8¸¤¹´¸ìu¹éJq»–»nv=ëúÌMà–ï¶ÊmÜí¾ÀR 4 ö
+n»3Ü£ÜkÜGݯz=Ä•[=¾ô„=ƒ<Ë=G</zÁ^Á^j¯­^—¼ Þ¡ÞZïQïBº0FX'Ü+œòáû¤útøŒû<öuñ-ôÝà{Ö÷µ__•ß˜ß-G”,ê}çïé/÷ñ¿ÀHh 8ðm W 2p[àŸƒ¸AiA«‚Ný#8$X¼?øAˆKHIÈ{!7Ä<q†¸Wüy(!46´-ôãÐaÁa†°ƒa†W†ï ¿¿@°@¹`lÁݧYÄŽˆÉH,²$òýÈÉ(Ç(YÔhÔ7ÑÎÑŠèÑ÷b<b*böÅ<Žõ‹ÕÇ~ûL&Y&9‡Ä%ÆuÇMÄsâsã‡ã¿NpJP%ìM˜I JlN<žDHJIÚtCj'•KwKg’C’—%ŸN¡§d§ §|“ꙪO=–§%§mL»½Ðu¡váx:H—¦oL¿“!ȨÉøC&13#s$ó/Y¢¬–¬³ÙÜìâì=ÙOsbsúrnåºçsOæ1óŠòvç=ËËïÏŸ\ä»hÙ¢óÖê‚#…¤Â¼Â…³‹ãoZ<]TÔUt}‰`IÃ’sK­—V-ý¤˜Y,+>TB(É/ÙSòƒ,]6*›-•–¾W:#—È7Ë*¢ŠÊe¿ò^YDYÙ}U„j£êAyTù`ù#µD=¬þ¶"©b{ųÊôÊ+¬Ê¯: !kJ4Gµm¥ötµ}uCõ%—®K7YV³©fFŸ¢ßY Õ.©=bàá?SŒîÆ•Æ©ºÈº‘ºçõyõ‡Ø Ú† žkï5%4ý¦m–7Ÿlqlio™Z³lG+ÔZÚz²Í¹­³mzyâò]íÔöÊö?uøuôw|¿"űN»ÎåwW&®ÜÛe֥ﺱ*|ÕöÕèjõê‰5k¶¬yÝ­èþ¢Ç¯g°ç‡^yïkEk‡Öþ¸®lÝD_p߶õÄõÚõ×7DmØÕÏîoê¿»1mãál {àûMśΠnßLÝlÜ<9”úO
+¾„¾ÿ¿z¿õÀpÀìÁgÁãÂ_ÂÛÃXÃÔÄQÄÎÅKÅÈÆFÆÃÇAÇ¿È=ȼÉ:ɹÊ8Ê·Ë6˶Ì5̵Í5͵Î6ζÏ7ϸÐ9кÑ<ѾÒ?ÒÁÓDÓÆÔIÔËÕNÕÑÖUÖØ×\×àØdØèÙlÙñÚvÚûÛ€ÜÜŠÝÝ–ÞÞ¢ß)߯à6à½áDáÌâSâÛãcãëäsäüå„æ æ–çç©è2è¼éFéÐê[êåëpëûì†ííœî(î´ï@ïÌðXðåñrñÿòŒóó§ô4ôÂõPõÞömöû÷Šøø¨ù8ùÇúWúçûwüü˜ý)ýºþKþÜÿmÿÿ
+endstream
+endobj
+14 0 obj
+<<
+/OP false
+/OPM 1
+/SA false
+/SM 0.0199999996
+/Type /ExtGState
+/op false
+>>
+endobj
+15 0 obj
+<<
+/BaseFont /CFCALL+CourierNewPSMT
+/Encoding /WinAnsiEncoding
+/FirstChar 32
+/FontDescriptor 16 0 R
+/LastChar 255
+/Subtype /TrueType
+/Type /Font
+/Widths [600 600 600 600 600 600 600 600 600 600
+600 600 600 600 600 600 600 600 600 600
+600 600 600 600 600 600 600 600 600 600
+600 600 600 600 600 600 600 600 600 600
+600 600 600 600 600 600 600 600 600 600
+600 600 600 600 600 600 600 600 600 600
+600 600 600 600 600 600 600 600 600 600
+600 600 600 600 600 600 600 600 600 600
+600 600 600 600 600 600 600 600 600 600
+600 600 600 600 600 0 600 0 600 600
+600 600 600 600 600 600 600 600 600 0
+600 0 0 600 600 600 600 600 600 600
+600 600 600 600 600 0 600 600 0 600
+600 600 600 600 600 600 600 600 600 600
+600 0 600 600 600 600 600 600 600 0
+600 600 600 600 600 600 600 600 600 600
+600 600 600 600 600 600 600 600 600 600
+600 600 600 600 600 600 600 600 600 600
+600 600 600 600 600 600 600 600 600 600
+600 600 600 600 600 600 600 600 600 600
+600 600 600 600 600 600 600 600 600 600
+600 600 600 600 600 600 600 600 600 600
+600 600 600 600]
+>>
+endobj
+16 0 obj
+<<
+/Ascent 832
+/CapHeight 1000
+/Descent -300
+/Flags 34
+/FontBBox [-122 -680 623 1021]
+/FontFamily (Courier New)
+/FontFile2 17 0 R
+/FontName /CFCALL+CourierNewPSMT
+/FontStretch /Normal
+/FontWeight 400
+/ItalicAngle 0
+/StemV 42
+/Type /FontDescriptor
+/XHeight 1000
+>>
+endobj
+17 0 obj
+<<
+/Filter /FlateDecode
+/Length 50073
+/Length1 90748
+>>
+stream
+hÞ¬{y`TEòU¿7™É$!“ƒœ$™Éä"“B2$’p…#@€„CB ®åQ!ÞPð¾‚÷*"“€Wv=ñZÄõøþð
+ÚKç/¾úò+÷_C4èÑ7o45Ι÷aðÝ%Ä ˜op*¬ÏŒ ·à=­iÉŠÕW•ÕŽÇ{Q¢uñÒ¹sBþð ±ó ]2gõ²Èôà1> ýí¿›³¤ñ佫Æ_6H;²léò ä\&ç·/»²qÙž£±3‰² ‰¬/‘¦çMd"‹éÓ@tKòåÚº\DšL¬ aºþ eGiu9f R͸r;yÈn\пì\‹½=)æ{ˆ ÃÀèýn¹Eë_¡œˆ<Yk d"ã”?“£d{g‡aˆ÷å”~ô=5€ûTZÃã|9Í£´„î¢-¨ÈoÒ“  õ'HcâZrÓ=t½GSŒ¢ÖAз”CC©Éè¤ZG|=‚FÒŸ©‘6 ·æÒ¿&¦lî¯íâ(³ÔÐfŠ¥·0c¶aÅû^‘„3¨]›mÉ1úÿÃGõWz˜Ýâ¤þ ½Ag9U§ÎõÆ6c;õ¢sZRÇKF¾±£¦P=­¤kAA3=HǹN GŒÛAS-hXGÏÓëìÒI¯§Hš„Þ7ÑVÚO‡é-ú aæpÎâfþ3Ÿ0QDZÎcÆh£ÁXJ•4žª©­IœÎebº6]Û­½ßñyç'F2殡U´š®¡´‰vÑûô}Äš°Š1EÛM‰4Œ¦S¸yhz’^¥SláA\ľ…Ÿ«t­ãdG§Þàà(Åý»hxúí¡cô6½ƒ9ÿ žjÏ.žÂ3ù:¾™ïä{ù1~šŸá¯!8Ñ4ízýOú×' «ñ€ñ$ÖM¤>¾8™B‹ó<NÃþ²9‡Kù]á9ë¡‘Æ:ãÆûä¤LôFØó8šª¯¦é ý cÓ›ôý
+yžBßñ Üšû#Î&M\Nº&æÒ Q‡S›#E?^ 9]Bë¹…r¸ƒÒâ.ÌÚá ñY‚/œåVmµòú«ú«BÇL/‚›ýa=<G`#¦@3Z¤¦L"ò? p,Eˆó|­XL x«öW~L”ÑjÔ–‹¼¹ó¼^¦ ÇÀš” µÉmJÒáÄ¿¤Hã|Ü1Mú)Ó ²¬ýY;gÔŽÎÙ¦^Ópg¬ÛzèÒ(úcø2ž¨¢J7Œ©´KìÑ?6b9”ôŽ ë|–ÝœfØù
+#„'BÂ/ z²ã~}½~³¾R¿wÓ°š·ÐÝô
+ü¸ ã.§…¨_ŽêZ ý¿•6Àl¦Çéñ”Ø¡9Ämâb•X@Ò‡ÚËš‡§Ò ýv}M¦4šÈQXyN)ã6Æj})Ö´ro|mœ4~ßñæ{´ß4œ¾*§,šÀßë lò ŸRã)-æ..Z8¤`ÐÀùýóúå渲ûfef¤§9Sö”ä¤>‰ ñq±1½££"#lá½ÂBC¬ÁsI×SN¥sD½Ý›QïÕ3œ£FåÊwçTÌéVQïµ£jÄ¥}¼özÕÍ~iOz^Þ£§Ç×ÓÓÕ“mv7¹ssì•N»÷x…ÓÞÎÓ'Ö¢|G…³Îî=«ÊãTy“*‡¡ìp`€½2®©Âîåz{¥wĪ¦–Êú
+L×b-w–7Zss¨Õ‚bJÞXç²VŽ-aU±•E­‚,a ʛନôÆ;+$^-½rÎ<oõÄÚÊŠD‡£.7ÇËås ^r÷†»T*WËxƒÊ½fµŒ}Ü ­··æmÙÐn£†zWè<ç¼93k½Úœ:¹F„ ëVxcלŽ»øŠÉ#ËkoíÞš¨µTÆ-°Ë×––[íÞk»·:dZW‡90V¤¨o¥7€‰U“íXMÜ\Wëå›±¤]îDîÊ·¿Fg¥¬©_h÷;‡;›ZÖãhZ¼4éjG[B‚g¿ñ %TÚ[jjoi¢³nNEŸÖhj™tõÞx=þÒ–ÜœV[„±­½Âý…аî…Æ®6URÝe©jRgYRä ðÚçÚAI­{*”Ic!µÌ-D7<uŒQÞy8‘Þàòú[‘¬—㽦t›ÓÞrž γß\Z3Ç_”n;O²(å¤KÔÐ({].ov¶s9Î4–¨÷‚ÜœUíbs™ÍŽ ì£jðvN]QØïpÈ^ßx›'ÖúÞíÔØFž<WWÔË–£–ÞSdKs ¥kx½’¼dÒÛkÉèún‹‰ªl*òrÌÿÒÜèk¯šì¬š8½Ö^ÙRïçmUÍ%o¾ö®6ÉU^«%
+I$jªB9³«³|© õêéø¤„z^»Ù©T5láµÕò¥uV‡ã7j7þ!G©ìâ0?™Þ"×¥ïÅ—¼_B^h‹‚õ QU3½¥ÅzIÛX ––Nûˆ–ú–9íFsƒÓns¶ì‡’Ѳ¬²>p¢íÆõ‰Þê°‰&.‚´
+ÞêäÛ&¶zø¶ÉÓk÷ÛíÜVSÛߦ¼~x]kÚj÷Û‰<ªVÈZY)_ìò…ª‚ÞÏQöOÜï!jV­ºªPïsÛ™T%PÇ4·]øêl¾…2ÔBø®sÛu_‹'Ð[GÅW×ìëåïmA‹M¶€ÛF6úi5Êkj»ËƒR²º\’"&ïIx+Ç ³ñ®þ£ºKÜ-ý¸¼§e™ò×l…÷|ØÉŸŠYœKŸÑ&váŽ?Ÿý ZvÑKð+q$¢±/9Šs!nÊFº·Ýûˆa¦án{QÒDN‹0b<ÓfŠ£~Ô„»¾ -ûßL&¥ãžKï‰aô9bïÓXýâž\ŒX‹ï×B/Ð>:jzÃsº mÍh} wå *Æ]Þˆxó,ßñ^ô‰Pc­Zi2fº»0Îü g À ?\€gq×F^ª¨Vl_Šu"AëÌÔ@÷§“—\ˆ<ž O[d α!úø‚¿Æ>o‡qëÏ-Š¦&`$Ý…w/<žNÇ<Û@ù\pÞL‹D bÏ(ødÇÁçO0—Œ1%Ö‚{>hR0YÁxBYÀ"AÜʸ˜O€{S±æ~pæ=:+ÜF]ÙïÃz¹8½^¼
+±Ï\ÿ‰Ës¹sÊÞë°O‰k3âÖܤðA¼w`õf…͘9€ýÀ7‰MàZ-ÆI”ólĉHœ .J
+×a‡2b}–¿M×gï%b¿q½e
+¿³‘îGlŸ$±_’L}x$©Þêù¥ò/?b~  ¾&øðœw¼] ””Q;v)°¿ºƒq*¨ÆyD›à¼€žlH8à’S×uá"Èî"øšgÀµ‹øFìƒd¯ülöó3ÀS?×tñ2€éwy¦ï«õ#!qÕ´ Z)ëˆvÈ—›nõ¡èB‰Âù8Èò°Ÿ2ã{Ê6N îšÚˆßSZZnH½t̃Ü s±B¼×3(5àÔÖ#ÞšÆ:€— ¿]„CRÊàÇŽáJÐþ螆3¬¤•œ…Ò]À•J’×ö+9ÞENð?þtV‘Hk1†já¿_ ¿7 -NбÈOÅ:P‘£è¨ƒç¬äÙMƒtÇ€ÞMàÝ5«éÈ£ñVXMám/Âê‹”%yô_…}Ž£ä
+qüàÇüð5þˆ?ày°lçx×ðD‚fΤÍèý…ÃïðwÆ™“½¨¯ Bã‡ùQD¢Kxê¶s×CöÒU—
+R=m C>›ÀyM}Í$²äó,å?h ðèõ t
+;øGHî~vA3âø2®Ð®£WÔøü?Æ/)w)ÈR`tÁ1p ûûEŽÞÀ®ûó·b÷»ãçð ¬’¼3·ÃoÅž7Gwœ«üJä¿0†ó8šÎa aŸ£aGW+\hÀx‰Õì¾°­ò¾š1äaÏàQ|0JÁUJ‹¤$¤±‡ýÖüµíW´ðgq p[7 ý%쩹¿¢Á?ÑØ_Ë¥FÐP~¹ßjúµü'yÀšþJÞe~!X‹_Ë»ø «¯ó;UF|¥ë\ á¥~kê?ÿUþ›`înòÆA4Q‹[å(ïVÜrÑd‰¢/BÍr~ƒW
+"‘ö<…
+öF­ôìÜЮŒÛ«<»cðî†e•þ²Z6 ½¤§ü‚àƒÌÝM¹ˆi¾¤FD€ôX ¯f€kAs9¯Ë øœrå€ xˆ6@V|ce›Ho³§íñÙ˜—x v àÝïø|Ú[èKEq`©ñY—Øi[šÃe+l!J2ž¯nø&ºp`=Š¾SÔwâàKJù ¢Êp®·Ÿ{Eè1·Ì]´\Á.pèc¤wÞBœ%áù唶ã<dLX†·³ˆÌ6ÐnHØ>õ÷š&ø‰·ªì§ßÁ³kV-V?4t•žD4 X¹œ È¥¯p2|#DmÜ!z‰^ˆ·<*
+\CkÄ`Ü(‡ºqO’wê±U›w"òÈ㸎 ؃w7¢?¤ˆdìV
+Ý)f7F¿‡¼ ×H×âÕ\¾¾¼8›Ü«þ
+Æ¢nöÚк=F¢‘ÈÝà`}è1N„ñX…Í
+­=>ÅI¹½«È1ÛÇŒcênêd¬
+IÞH;ilFKoïyš]
+†åè…¼NâAœ­žPZ©Ó‘_ž¥|ÅåÏà{ê°"°#‘ˆ î‚[Bçá¼ç¿Hâ~ýùž¯¾l?"¿Ê/˜À€ÿæ»là¯øx¾Œ—Ñï âZcÕŽ¶MèiGV¤²½½Ò4Ë<$LåmÁKËò´£´ ¸øP§ÙH×ùk4JAZ
+”µUûNí yGoeÍÔ@ÍÔ@M©ÖN¬=¯=×––‚¥÷íOðmY‚¶—  ÐîÒÖãÂJÑ.óç³ýùFäÙÈ7ùó;´õmÅ)áeÁx‡( 5€{ÛÞ6r€ýª0Ä­
+Û5Ûö¢&¥,^Ûª¶ƒªí j;¨ú)cÖm¨ß†úm¨ß¦ê·«©}ýSù ÛÛÂcü5(”Yµ:m*N-E«õçÓ´©mRŽ”ÕkS0õ•îÔjnTél•NPé:ÕºN•—ªòRU.UåRY¦yÝÒ•†ËT›¤M†Ç¢MÔƨ¼Z«„Φhð.óñð§e>N©ò±¨Ç-¥U¡_$ò1šòûµÑx¯@>
+ï2©h«Hé_¶ ï³Ñ&°ž¬¯
+@9 L+Ãæð ÅCšæ”J´´ CßaH=š[íÑ^n¬ä¯Ü˜ÙãqãxÜdÖÜHíZõz€ÕÀz â-ãr@WVÈÑr¥h±7tŠf÷ç)b½Œµ´d±¾-9ÅS,öQ5°¸ Ø,öµ™"ÃË¢ÑOöÍN
+)«²½¸xÄß–ª„9U g*æJµyHKU)iŠ–Ú&‚ÃÛÁ_.
+/+ß'
+6ì(ØSp¤À|PÌÔ‹z•bb`\##, e6¡ÓL
+ãÿ¨t·J¯T©G¥±ž„™a§g†½23ìþ™a÷Í «6~f؈™ay3ÃÚ¹Áë
+ûȶÉ6Õ6ØVà
+è
+ëë
++‹@? Îäa•Wé
+{ë˜5?m÷®‘Ícœ­´¦²¦¶u§±¢mŒgL¥sNEÝÞ‘s²w_²ÜíåZ³çüÌdsädÙr­‘»¦y·l)×Ú-×Ú-×é©ÖRR±´Ððºò™¾|¯±B€ëuÃclËJ”4;âÖ&ЉO!®:o¨s¸7 (›rËrËd´L6õ’?Üô7Å­-v$àßû›l¨Žp§¸Êø·|¹¿ðÿ-—ÏŠË–_¦rõoùŠ•@yPòô
+ÂÊB•UN}Ê2K‹,­¶¶|yÝ
+R§º|%ÉùVÈäâô]¥•˜™—wZÞó‘²á"bºå+½dÇ•~ÁY.ÿP‰iHéŸÍ'Ò盤7n¦­AævÝ'˜Lº,hd 2¡ðœ¦‰„`³¬{Ž)Þ2áš8×xÛ9÷¸÷xÛ÷îq¶8î·Äüþ#éŽÇ|.ص£<&ú‘ìúQØ·¯ÏÄg&“òÇ'xÂO†œ ³•lµ"Ó?ï‰
+£„˜gl%l-Iz¦ÛÌæCb4Ù©“ÇSœËöý¬³§OÛNŸ¦ÒÒ³¶³9ÿòû#ÀÔ‚‚œ©™ZFÁ ÁÄôŽÖTäD-ªÄó"6"2V¤‹<§³_c¦kXI¶Lô»;¦Ûìâñ¸Ô~ýœÖ –a®÷°ì\·´ÉVñ„ö¢þ®ú›J}k/S»¸Åcekp0L¶õýàâQ
+‡=¡öˆ#oEœŠø6Âq€cHˆÃ{-ü>µ‹GŸíoYŠ»à¸>â?©}œ;këÀnÎïÜ67ø‰m8ü»¸XÀZ#‚ìññö „(²—`7éïv&d¤¤dð¾'yÐX«G˜†#«â*ÏÀê¨ê>;¢w$î‰Þ“°'Ñ<’Fe¤.ó ÉÉ<c´'ª`ôsùÅù‚«œic,Á‘I}¢fŒi7Ž¶¥¨,Í—%©ì¹Ø‚1ÏņŶÉ&z†™vrÅNOß¹öi<£ŠfŒòÌR:£°dÈ QƒªEZgDψ(‰ôdoéI-ˆôÄ¡^0;’#ÛEµ'w\¿¹3§Ï6cLAÉàA£Uá1ƒ¢gDoŠÛ'ų́ŽÞ½3Z‹.‰ žLe‹Úµ3J‹:$þIcÁlj’çf¹¾™uv–í,JçÎ}ƒÜ¨Çó*ž;w!P}Úu”—gë=:Üò±©TÕu¯ÀÌâ.1’'’™QP( ‰ò‰ÖÀ ƒŒémÖº•|ÃNm f|(9!!ù D1"ÞqØ.âl‘ñlß#kŸÜž’ò°Ã_ù‚ê•ÀŽ½²µó»¢‹ÓÿŠŠŠíÌIŽÓÃÂùÍ‹%YÏ•žHŠ×mq¶ÎKjÔ¿ ³§2í+ÓDªá…ž©©¡¶Ò1Î1i«W§¡‚¦¤Þ”úlê³iz­ÅîHu¦¥g˜3Sª'Œ7¶jŒyô¤Òvñz[á§#ÚyFÛ€Ùe¡âzêG½Å«Ô‹Ã #ÄŸÃòöáû,G°Øaõ=Ž¤ ‰ˆˆlç°½™æg·‹7Ÿ+=,3aê 2+:”‹1‡ü¥Ð ²ˆëÛR†MzA,EHÿaŽy7Ck: 5çΞ…ÙõAÙ-•òÎÍrËÃ=w6OÖœ; E*1¿ùÕ÷Èš¤¾ééUI5)rT#›6ÚÃ#û"IžÜÇÃ5dŸ˜Š¦Ôê c2Æy8Í9vܨ¬ê›ms» œ] ¬¨z®¿þYÈä*oúÄéµûF&WEW6p«ßP0Ùø¦P=utÅ,Ød¿Mê;ØWŠVê p¦õŽŽÑcc¤œ˜} ™ÑA¾’ƒæ Rc2•E+–‡ZQë済¨¸¸([ŒT8ié÷”åsqaõ„¶'dû Ì1a‘q±Q‘aÁ"hÇmw<ìödßò‡ª±êÏ,”ò¶0(%+>.!ùºä„Þñyƒoš<9'µ8Á¹zÊ•»#~=~°Nω
+OH~491,8¥`é-uÅ5‰ñn÷ŠÅOÉ¿½4¾Ò£õ)„bÉECp–Ã=U¯ÄsP*/²øþω+»opŠ_¢2ƒ³’ãÆ¥8O9…ÓY ¥Ž³Å¿/âãµâ!FÙ¼ÞC4#|Hpèpˆ9$¨¿ôØ*’K‚²J
+‡„çpŽQ2d@»øîùŠ`Ê ™»+Î…ë€mߟíÀí
+JPbü‚â Þ§¨OLŸ^}ÜeÁ.1ˆŠ¹ mœ. <RjØ'Jp̃|b"EÀdòÕ<$ÝwÑ™ƒ´_è+¾Ø²`áæÍ nv/Ÿ8q¹D{áû^æ³)R³ö²XQHÙ²pÁtÚ2,ÐIû×â­[/Þ²eñä+&ßîÐ#C­Ö  Þi[¼eë"Ù©fùŠÉ“V®À ÔiœÒ:õÁêïêß{Š®5_|íÐ×ø »©8{jÿùÎùyטo*¹½ìIóÃ%/•XÓòúz
+òŠ<³2¦¥õÏÏw-C\ˆ“m÷älÈP˜ïtæç§Qp4ËÒ¸¿ìªýƽΉò~ÿ}g&ÉL®9’L2¹ÉäN6»›=`CfYEÅ"ŠkXÔ¢QØB½+(EQ¨WE°ÞZµr. *mmk=Z¼ªµý!¢u-Z´Ø²ÙÿûN’Ým?Ýûæw³Ëä{<ßçù¾ï$õ#S–ÌöÄbJ?toõ§UVÞ×"¾
+ÒÝ× —ƒ£öBßšÙPéÐ’eh?æ'ÎO¾Z øPµ „ê:TEâ§øcUÖ`ø€Kµ¸ω@ålmíBþ\ƒ—9xŽ‘"Uyƒxf 4©®_ƒ×À>p1»íüñ+ðkÃnx'0‚‹ o1rƒZ*„`ͼpä+oy)BÂìÐÛÉhƶ ”X†t¨[5ƒ=(Ët„DáÊ> Õó 7ÿ!G¨@ÙŽ>L,»ì2tO¯ HBð°
+QM¤p·ÍöbX‡P¤4T­#ž(§þª¦=róIìÖëb×ůK<(±Ë¼5ÉX£X0·%©D$éOÙcþxñ0)ҧ ø/aH¤ât<)¸&žžÒƺUßÛQ3ªî¸¬ aˆD4ÃÍî~øÍVí>v!aŒ
+šî0èk•´†gz½†ˆ•¸Ð}‚/ûfž¼òâÇ$=cæxçüçløP鹤òöÀÌvÚ®:ðù¢L/|èê²Ë`tr Ìygõ¸s–,­¼wŽÝß H!c[¶!bP¬©±±À“O–§D»Ú~ôËB×µÝNÝZ¸£íÁÂCm;mΗl/Ù_q¾kû‹ó3Û¿œÃ9ÿÞ6{9’ïGõ¢I‚fM©8Oæи€.â’?WÒ
+…-Á î‡7mQŠMˆßÜ´M(ê#Å–~hQŽ"éõ¶“îq¹ä/qÍ“ÔÞ¤Ó[>€Ë«ÎÀòCæþýÓ¸ÈþSq` íG—XbøÔR
+å‚¢bYªb¥ ±W¾L¥ÚÊ}m ­Šb½¯P£šÕ–R‡NíJóR=gªN"mK¯øªáÁ,ëä8ûÝOÜòÛs¶—ýnI:©ïÖõWqKšãM¼ëŒË×o|ù\âñæmçþìã³8s±Kv,>eÝ÷pnÁÕ=sÖu4Û'/žþÜOfÞjÕŸq~!Æê!ðªjAõ=HøC:_À+"³Øîó=+²¡ÎU«õYG0º€ s&‰P ˆ ¿ƒ$)]Èoñ㎰¢b„ê—Ï‹SA,Zd?±Be¡ÎzÏ
+°‰¯ó‹ú¤LM<$9ô:|ý©1E<Q+/àqCºrì=‡Œ}Û®òU`/ñþPÅùó8ΑåÒà¯jØäa¼a&!sé2‰S½‰‹w&þ ½ëú›‹–p‹8ˆmhâ Fh;”Å€|!ð ăB¼
+÷«Œ¯HQF DmýðÿTÆY4º‹œˆ• A,܆ÞyATî‡ÙÁI™(e¬‡ð¨ÍýD6ªöW0éÄ}­ÏR%éíZkÑëryuŒW‡ê¹‹AƒGïS¡D;G#¥p*Uîƒ|*°’;.r#aCÍÖtò²)×ï}óÐÖK/ž¦*.Ž·ýló­{Z¾bEЂdÕ !Ô-•yÀ_·½p¤m ‰‚$Üô‡‡o~âÎ%ŒCBd]7B‘h€©ælØ.7‡ý)ȯ  Àð‡ªµ@§»¨SèÓ©³h}x ²o°öÖ^#Írÿðª£úm™¶ô£ß\FQm§ì´B)tÒ6ÎvŠ­Ç¶Àv¹ízÛJy—m›üŽéáo› êhCP¯H¬Œ†æÏ ]º<¾$·¸aKxWòÏæÌÂY4"A/mö€Ã/úœ粄l1GMŠ6äˆlU•„!•Ô9õV‹œG9òà¶L‘$O?ü«*Šv]¬ÈX\è‹ É%ƒÉ†$•|†x4ÊÀL<´#\l@ÂMÊï‚mðšŠWÆ n¨¬ITD°¯÷W÷\Æ´W½Ñt0DÙ8–g–Ô›-& ¡OSImá~ø Õ#âvQ9N£Å”.£ÂÀ?1Á¨%¦‚„!¦‚±ã:4f‡q­O+8{ª–ž -RPÙÁ±R‹HàNê˜Ð §=8ﺽÏ>|Ñ3-]¥†Mo^5³Í%ò!QüMå9I¹Ñâ›æsVa[rñûÜñÍu7>ñÚ½×Ïß8/ÌJ‚Óh¯<ýqèÕí÷<µfÅ/¾×Š²òõá
+ùg”•°üi†ÄÅ[ +Ièõ$ñ,c¶X.p
+¹ÒEFj<N†à-²ÖóoÏÐÇ©š ™¼'À;(Ú/Uàµ#ʆhС2à"yhÈÐ9ä‘ะ~[Y€2,÷¾.| !5|p RèƒÜ‚D~UfйЕ΅fÏ K[³›Kz»¯9ðš¯#fÔo­ƒÙÉ4è[Ç4umcæ¤mþ…û6mÚwႳ“ãÞ¼ãgoŒKXîûÑÒû6^réFç/–/ÿÅË–=AÜØôðÜÛßyçöÞ‡› í3Î]ý§?­>·{Ü' ï¾gÁ¹·ÞZ1,zà‹øÈ#m(.¢  v«M% )}Lõ
+ÉH V,Vc³9Œ†F±)K;0c{ò ßDþ‘<œÕ=`£$þ­~ìtùÿSЈì”A¿¥·oË?Ÿ=OÍ¡-2P¬æ˜)Î$‘D3‹‚,+'ŠFÆ3Õ˜C€f E‹2€0ËB<¤å"ë.¸?0ÓÏ€æQèâí׶ˆªÑ°¿4Xk!µW,– G(‡Åj¶zÑgç(½.šdPŒÄM(FbJØ!c¤²Á,…Å'@‹V4D¸Zß2úÜv/PNaÀêƒ#†æZ’ÖÚ_5¶<¦æBsLuok ù\ç–9gÜ?÷¹M?ÜÝÜÕ®ÜzöÕןÕîvñfg¬éMØh/l˜áÏ~þø%M!âwK–~ÿW Öݼê‰6_Ò}G®æ\¼ÓdƒM'ß~éÖ­7Ý°EUSÈÏZï„<XÌ« »Y4Ñ›^ØE„ ·™L’äm¦tLåªJBëÓR±ý§Ëè@žÛÝ:~þZ;Òu!`Ûp’Ú]¸À™*¿Çº×ú6·Ïú wÈú gp"’òØ–²ýЭ2èþØp¿©~(ªS³õ5V„â;Ð×î” ¶ \m‹ ¢iµ{Ìí‘¡¨$fFÛ¦w·¢aÆÙ®|äxWP?æV_®4„¿Ãlúã\ÐIµSS‘®]¡úŸÖCšad
+d¦õžxæ­»+›ÓëygîìrÄsÒã?=ãñ« ~Ì ?OH]‚rχ Î¬†n6Þ`º^¸Ávƒ}cm`mpuè¦ØêÄÚ¤U¹X0á á‡)˜»bÛBDíôa¼5¹ÀíöŸ“&ðuA—ÐöR|4Ÿe~QôùtÊÏ0„Ÿ&d…Er‚ ²ëΦý~DÞ&€”ÙÛ!=Ú÷M,yPhîÈü· *” ÍÁ¤Ñae-¬™5±”^‰Æ¢ñh"Jém‚] ô¡hÒ(gaÐÉÂ(›Ê°ÈÖ¢x;³¶É‚êóØüÀÛØo†Q$Ô²kŘ–>í4|~ÁSÙé ßWžwm¥¯Ü ó v–%y¢¼fFåOµ¤8³­wÁÔùK¯ùò¬‰8+VÿjÎÓŠ³»Ó'£|8ù#‡üQ€‚êî ,Ò/Ó“¼ÉšŸ)ì "Ÿ—dô˜k±þ~UÓ¬TÒÏ"PU´»)›ÍçnÎâ
+Þæwsv¸¹rg¡¥{ÝæÖ¯†ºÕ‹òvÖí6 9}§/œwsù’»^ý:‡­ÈÅ.è´YDòè…(«¡¬ê‚¿VÍÂ}⓹-âs9ª*L–TM!¸ƒóç|З
+ù|ÁÏnÔ–@æM¹\c“/Ý1/ql)P"J©®Rib—¯£ª#LúTMFTE„ILÔ4D*ªý$Êã)9ʾÔø^êm°-ÕÜÖVhö„ý
+'ä´C²UŠx|¨|çÕ¾(ÿÏW‡«-­ýžÃÍ
+|ƒWš{ëï‘‹‰–ŠÿXÉ¡ù©pk}~T¬ÿÅÜGH€|‚b.
+ÃÐX„òÓ9ÈIÁ5ï»F8ö:rvIkfü®ü.o}ë¼Î1 ÃñÓãÎììÓH¾Ö?¤&ŒkÔ˜}Gèû²›¾T¯ºš\f»Â~±†\k[m?"Ò a²›äzbƒá1ÃÇÜGöD=ÅÏmç¶Û©FZ F
+H`¥€÷]—Ë0°‚ÉD„€ÐÔåÄPªZøPÍ\i€ËÑÿ玳ç[ý4mÀ?0à,7@ƒÛ°¾Y+wˆÂaŒÝ?­&±kÏÅ âSÁ9„­ß%ÂœH袼ŽE¨Ëê 6Ò™œa°H™*9ÔúsÉš€*׎xÆj';I¼ã‰õÒq–%ŸÚo¸°Á©?›rÚÉ­=•8`‰ó«ÆrßµïŒó`‹¾_Nž÷ß<ƒ80¦;;!â]Èʉï«eWÆÕâî”›
+M­-“C=„v^ºªsµººó.õîΧ:wu¾ÔdcAKÓ Mg4Sl8ÕrbsgaVþùÒoÔ=´'ìÉÏÏÏßÖüTæÑ–ƒáo2ß´'¯Gsê˜h¶/ô6Q@}R²AkØ3ë2DCf2ëò™LCޗ̃j¬[Ꚏ w"<ÕpODðu·Â*¥A!•T×_"êlV[¨ÒÄpÀ
+ÛC¡0åÃT6(Ɉ’L$¤|8Dù‚ÆE´µ*J%šæ•¡A?qÅÖPÈÅ4öÃ3w'щJã
+â¼<„S¯kÊ
+p^r¹ƒ›çèr¬tqÐ6tˆÕ-—;yKHäƒÕ¢VzÒÀ[[¼iõ"ªWÙlÁ;
+ç]è^Ó¨odrÆ6K ›ãr®I¡´%ËƸ˜++´"ÃÓ¶l×ãèqntí¶‰Ìc¶ÇÙ Üï뺞™Ž3\%a-»Æ±ÚuŸpÈLrLrNrMNgÛf³grLRh±58ÍÂmSØIcÖ›¯ÞË$mqG܉ýdÒŒÃVEƒƒV{ÌDYc$´µ`Ð¥|Ì özÚ¯­”ÂÂ&!o WÀ’@|%Oj£JX&6»L>{‘ë<Ú‹{¶oð«^N(ºHy€•÷]‚Ë_HcÄæ½×&’S‘^×7ø×ác3GŽŸ'½±Ò;H³“¼Oëû+ÑÎP7ÞÀ $4*‡X¬ªôˆô¬³h©ôaUÙã¡7–0}{•‘c@ªï0Fv`ä yDJ+Hœ›£/ºåӻ˻aa÷ŠOVLÿä™'AÆg>A•ÿ±΂Vhƒ3וÿùðŸaGùåw?*¿ 'ÙêÅ–d¶$P Ž(í¡½†
+j,G¥#Ò&ÚŠ5 \1ÀM ± ÜäIÓ@ª§ò¤iàëHõTž4 ¤z*Oš4ŽÑÒY°¤3T(oÃy'•i %¥*µ˜2*ý%Zì¥ÁèÇ‹Ïj˜9½Mj™ì³pn“sJSCê®Iu?¸`o´ îíø+7VðòkVoél{ÈåÜ›Y‰ »]'ð<{sNù€(|ù¡ògå/Ê@ G«=R3"Ïb­¯ð?¶ip§òÃ4>Í»…ñs
+‹ê®ª£ é–º)u³=3ë® ]™¹ºpGaCꑺ=ò¾à¡ýò¾êOe»M6ÖM
+vHWgn ÞšùUðwÁG3»B/K‡ÒUíƒ_#°}«…8Ñ¡m±ÁP*-éÃÕ™H°4T¼ÓjÈÖ¥¯!ú^SÃ`ÇWN¥H|'¸ ] ªÑ:¥
+à °¹˜ÈPÆâµy™o¥ã˜ÀçÂpZx]øµð‘0&€ØfWX˜e°ˆ›¦\vb¾¸´ä`é`I­ÞmSkU¼¡ò°!rJGgÿÍN8m#W‰1÷-¡mƒýøÉ÷oJ[
+® ÞŸzò¡:¼× ±r+!fBeú~Òà:Á[Œå† Öô“ýÆã÷¿yã}³»ïPÈÑâûí*ñÞzÏxøšònd*O9Ñl½ô³Ùk ãïû\uÝÏΞvYÓÙ¿Áøs+F$<¶^§€*©q¹Ó½¹Rn©ë&×ÍžÞÛ›ï™h:5Ô1‘xxÂC÷¹¹¿p¼ä&B)똗V’ãZ=‚MÇØh­¯P5y’e¶›E¹­-oµ›CFãÄéæÛèšÛâù˜ÔNÑxó‘Ô”scl^ +€ž>¦ÔÉY™Ð•\–\™\›|"©KŠ“î߃£ÿc¸¨ÕµkyèJ":ÍØÕJ%ù¯Õz¨©ƒºZB”†j…õ˜$³Æd ’Á¬ð‡˜dl…¬—‡K?¨Õ ãÜP·~ùmÖœ>Ñ£fÌ:ôþvyºÚ™í<ðTǤÚß¼>wîm¤ÇûÈ"ý5@òÎ7­<¯þÌ\ÐîóÇo=wÕîµäÔ$%=÷î.›xaÀé‰üà7.¯ÎJ¬ÝmêžþK%e3Z
+$öH¢1ºÉœ9DWöíŇ½„•Iìƒ][XÖ
+ªauTW×ÊnÒ²'IcU•Éè·k‘¸Ér®«Åö)"'“‚Ì™dÎŽü͆¥
+
+7»… pºð.$»ûÐO”€ )§LÑL\–<ä/rÈUz¹Ê‚à³0
+u#ÛãòTÀÜi=ÃÔ64øqbÜ}ƒGžt±C`$ J¥YR„0BÇD’ŽœÃ1fŽzsù'.ÿiP5¿MdÜÙõß×xù š=&AªxüOôøá,m˜Êú¯Q–xÖÅnÂ@9e W€-RS¤Ð®X:]5šÎ°Ìs•jÎh:Ïò#×jÎkz fUÓÂ}\ŸÔ—ïkßÅí’våwµ¿>ÎZ<Üþ%ø ~Ɔü±õk·sí6a¥|®Jù|;Çq)ÏKR¾>Ârl
+µw ø6·÷—¥ÕÃ΃|§¼²ž½Oš³` Ì9,7õˆ-Ÿ2,7O£šaQ‰Ã·Gs2ö@•±¬àÝQi¾†‚ÜyÆóœó]‹MKÌ‹]ú>êôb~Ù‚”Û–@Yª ©NjµÔövº…²i(Àl<§²ék ©ö¿´efmˆ²Óº€µ
+qØý‚ŒM lŠ¿D_Þ&Ó$O5¿¡ ÐÀãµË– !;a\@Š¼ªZ{»ÄdµM Û£
+žŠ•êëÑÅÖc+¯OÛèÞŸlƒŸ?‰¬C,7ÂMÚLñ¢„ÏÿÙ[éŸr[‹ˆ²Û4KP’¤ÂHõ¶]rBçPJ—*=2ð:Iߢ}ç åäé^K=cøRõÝN[z|¢ÆÈ@4®<@­¡ßvСÈv³õs
+­o²ú—¶Âݤr3K*7÷
+X#†bäÁ U2¢Ep 'r¼«üŸåÿtòxH–ëÜVNðÀîr·W䬪þ‚=ôŸËPª6æ@3Í‚ìIõžôšcëUI(Eq`ÏÈ^Ÿ¦(NW‡ïQ‹l` ó ‹ Ýáiø9~ ,ÙÃø#Kø3ÝîÊϬD}PÕÇ.JälîEÜêü¯Š:3'ò¯b­1t^5¸Ÿ>‡ê Ð
+LÏÃÅÃj{¶t˜Ä4úÕpêPø­ÙÞ<f£¨ìÄ4í
+pæS¯ÝýÈ7[néìî>ÿÉ‘u›¬ ¶g1±X/´.?õ© ¸ôÇ—o_pÍoïéºv‹½eÒ¢f“ÀÙM6Oêþ{Õøéïìlg뙧_4cÉÿT㵟5Û0ú$q0WÌlVu.ÃU>9vˆY§(ºœa_À@AsH¶”Ì}pÁfY2†$Œo()ʇ÷'¬Š~ɆŸ<Ò{R‘³%ääIqïâ÷óØp'Ïýåèå ‹pp(µ†-&qžð~áìÁ
+_ú{vmü„-•ÅPξÄk͵Ñɉs ‡7DŸ‚[ÍO¶Äwêv3{éw™ƒº»‹®ƒõºqævØi>5pœ®+Jæ…p‘î2óUè:Óuk‚+Û‚Ï„7Ç\ØÒé1³‰¾Áž ¨tk•8 Úñ'H¸52&óZP–,LýæÍ>¨/¹ùÝÕ/ŒªNxà;ï|‡¼è÷Þx±üÅó;ËG^Ü@öz¼J,Úµöï_‹_&æiX3SàÈfÉd¶‘äîQ%ƒ/9ß½?< ýO죸!ꌻN MMO•b³ã—Ø./Ž­-.’Ú½ÂÁÏrœã¼4¶(~Ô£Ó{DÖéI²I.湕½—ýµ°Æ³Á¹_‘9»Mä½jÅ•èskqpp‹]J̽´Þ÷;·1[[™Yë‚pUð¹
+z2¼$“E^'CB
+©—vC Ñ…Ÿã§ý(Ö…
+m%ò¸ì’û\Œ‹ãÜ”û²IË4ŒÀÏÊ?§Ž%3r0 ÔMâóè]éØÇÒÁØ1©?ª¿4yyõ‚ì‚ܵU?M.ÉÝžìÎÝŸüUîÑäºÜ¶€1Äœ¯£NÇÃÒuBˆu‡ðZZ«ë¤)-Õ²iEz¨‡ †L&ָθÑHÙŒ$ñò„qQgôj¤îȪȺÈƽ#²'r r$BGÄ|꼄Uµ„ÍŠƒ€ìâAbR‹CõÄÍcŒÄ()Þ¼ƒýÀ3Øß“bêû¿ê 0€012L-é’–™¬veGÀA'ȆI†¼ÁŠ"•årÑ/+‚
+y.W?ÚtP×k{_TX<wªZàõÙ”¥q×Íû;vì±}7ï¾ãŽW^¹ãŽÝh×oU‹±õ쉙sjåÐ駦&ß
+áæÍ”O»ëÕ?¯¾ëÏƺ0ëÂåXšà•ê{<ÇBˆ†N¸P•~¼ ­ƒ¢°™6èoؤÛlxÑð–a¿ÇàaìnÕnÛø ø¹Ï»…°=™UOfnm&“­ 'Y“fï«`Õ\5©f5üjŽÍ­àצzr)dë
+…úºp$¥³t2‘ÀËÝhkbŒ!q¿
++$ëñê ú˜W'¡ÇàÓTëä(fÀV ìß²y ýÌÒrÐvµ°l£«®†c ßE€gN[=çüsÏÅŽM°ü©B»áª¹²—®ýS5ã¢c3&OZÙ9ðå°þRs®­-øxhBƒJX{ŸÁÒàÒÙ…ì2%ëEE<S\ ^). Ž*v&q¬Þbœ©Ó…-.Ÿ¸Æ‰q,õêƒwmñé«,&
+hÿO¯/W‘Pš<s渳Ë_¨Àxérr÷ÇUÍ_péªê ªø·_ˆµ|^×ÕXË ¨o+Hb1vU“¤2š·¨½ÒÉ™‹:~ï@;ó0ŧb5ÉT>QhŽcã’Åü%ü%ó"Œ8(Íw&ߎ½ÿ8öqþXìXži‰µä/‰^Rx”4¢" ™qó° ÷¥ß‚0$_ja‹¤WXŒ¼ƒs#Á`8öE@uNµµµùÚÚ\>\/ØÍêY³&«Õl
+Û ­{P§^¸G%Õ‡½¼##“ùÉÉäÜX2)Ç™X4†
+y¾PÈGxç@8
+Q^áVŸÏÙêÕË­™\kuu&ƒÌ­œ0­™xâB»"0òÛXtza\bx¦jq¾;BùÚüü<•'ÖÈßèÀ{?Þ}»ˆ5†Œµx@ö!½QlØïÝZºk¤D†%6jÉáþÕØìP>K-]«ðžÝÍ7Ó5ZŽÀ1¸·7ÐFH©{{}Z/Ök½»Zí{FŠc ©ŽQ#,„@ÿýåïŽðŽ½›²ì÷–É8ôz¢y^eÚÚóbqO~Ô,59‚ #AóLlÛàçØÛ?:ºâ_¯šV¹ê«Þ˜˜5UÂÆÄIÓ°GpÍpäXŽŸ”¸xz”³ø¼ ­êJ1ç•ûàÚóT*Õ2ÛZ¾þ¤|ë(×ñ˜!惌˟”g –¯Àµk5J
+ç N >,3 fÄ(q&Aˆœà\c·‡€!€!;Ëv²;XŠÅÑÖÂﱂßiu¢ýûœØ¿!×a”QÇ¿Õ‰ëŒÉ:PJi³5Úš¬Í¶[›mœM±µÛ&9ÙÒ`ÙäíÉÐqØ
+wÂá` k¨Õ&slå:²¹\m6ÜÐ¡É ö·ÃöŽb{»R Wgõ¹¦:á÷é¡!Õ¨´‚}J¢<’ÑHb1§©Êr»”`¡ÖÕíB®ã²?ŠËäXî–‘||<ȆŠãI Œß1~Ïxj¼89õ˜0*f‚é¶án¸x¸RL:”+ášÁ¿Q\:¹ÜlHkôÄ
+«`b,¨¨ ŠP")ˆ& ­3Ç’t<uzÑä„.„‚ÅCP†ZnIÆ¥†Þ‘bwÓà'€Æ/Ãà;ø»ÞÁàå!ì —¨ÆÅ@~g¼¾OëÉ/éÁ=Ðÿ§QS½Ø€Q‘É0‰ŒE*c•ôƒK/›p¾ÔtEËœ†É“UvÑs5‹&t¨Ãκê̸vuúŸjÕ„:¤ÎŸ~ŤŽŽI­§ÏØL¤Ý­œ=é‚7Ôñ¯Úgø“ µƒgKùeXÊg`)o‚7+ûôû´S¿“Aë™}C-1tÐÃBf¡—º×»A® öÂMˆò/ "
+¬ÐÚQÙ•4LË‚Cc€mU¡C¶õ­Mz¸ 
+¼^¬R‘Ô'©³=·@¤ÁR1KÔÍŠKjÔM« >ÃÚgµG´ïiOh5Ú<¶Ï…¶ ªÝ‚„ÛØøà6°ãï;ÄÈ4ÖŒLÒ@ʼn“û9Ñ":NC÷Ø>³Ÿ÷Ÿ²'IØg""%â‚ÇîM›Õ_4Š¨Ð³¨ÐáÿDñ!O't‘wv‹¸°‰8) 4ñ‚" Ë"eM „UØJíß*ˆ}·UÿÌd/W¡<öÜ å¿Aá…ç mÙû;v¼ðñ_—O@þÙ_C¾|â7?þÏw¸ÿ½w±ç¼|Y½u 6*ÅfÖÚC¿\ãYp5h¾
+ÙxÞÍè@ _§­z¨wg’À"û­>5³„ñI-“ïDµ«ºÞÇ
+Äp&ÿÁק’OvÕ›ÒØîh$‰äfbª7OüǯbáÍ Å±k×^1"‰ý+—Ô_ú‚]W\÷Úååñ§ßÿž3žäRàÛ¶=ºý‡Géó·¯>gÓ‘£å‰'ËZ5¡éy¢]¼õÈ«wm}õöF"Ú=Šh)¸ð
+)Âub-Ľõb¢„(ŸFYÕkÿ•0TÕ)™æÚõ[âI&þäòâÒ»íØSåqH?óÞmG·m;ŠÔá혂_þ¶JQø'!}b¢¼`ë‘#[·¾ú*Ž•`)ý/h··+âu˜4,b× W ß~ }À¦óªnœÀËëÍc?HíFÆŽ¢*FY¢÷XTß©¯¯‹„F‹h2"šhtfh¢…c#uyвE Cd‹a“ÌÃZu't”ÎÝD9b „UÞ‰°6,%Çï8%UºŠAÇQ1¬Õ@ÖØ:þ§Ž¯‚ˆr|…r£6Ñâ¼U ª²ê&£t_倥¨ÍZp£dc-¶pVjûѳpQÝ/ÃVü¿Ø(}þÑ{–]è¶I:[ؽò±r–GàÔSýæÈÄ»t­²™ð¿•[Ä¢·‡‚Uàâ™»ä]m?mÅvxÆÚÞp¼ÑýÎŒÿ²Ï~4㟶“Ù/fF›Ö¡é6ÌØì{·gÆm¡{³‡¬Æ¶³Û/n_Ÿ¿¦ý†üwÛ¿›ÿ™¸WdïȨ³ô‰x8Ú¬t²n—Õ¢³›:@¶%fšZ­Íš—ò]]A>ØË–`n?-ã$(øÅm A^·¬#¸È¡´ß=»yi8·,%H*«†ã0.ÍêÕÑÚ(4ž[Yr$Ū~q˜Àh°²Ó˜`wTTGÇ$\‡÷êÀÑ.¤°´·Ído­ÎÙm€¼§#
+
+_7÷’G. ‰·ÿ—ˆ}íMtñš™ý©”œ]W¸t3¶:¿´­<F³ƒÃJäK4{Üj';Ê>Çþ‘=Îj®´Üd¹×ò°åEãF­SuxaàFÅ®g>9Ñ`ç­/ˆÉ/Á‡ÞŸDtyÖ”Œâ-L þB“I½AŽ_^Î+{7xŸõjðÁ¾Flè!&:NÂ,'I8ŠÀ,ÆÇÔ@)I‚›*„q|ÅíaF·!
+ WÂê
+çÅé!ªhnj¼ÅaGêþËD¸¶_1²ìÅ6Ñ̹Ìòç#wï&ЊabÐçãÅ=þïóÎÏÈf‰·šƒ}·^A¥ðÉ/p'<«Ñ<®¢Ï1´›XfÔAÕ; [o5ؔқL}ȪRžþJ 5ÄÇ #³åH$(‡bÐaå`ÄX§+ðû­zCž³jÅ m”e
+BYàEdeŠa
+Þe·?ÀÙhŒzYd ?5ÀÇ ô€Ãv’ª@_ßú|)‚{ É’ë^‚{™˜¯´Tq/r ÷"O½ȓp/r÷ò,|™ë›¿½‡]™ð=%Ì€¥ÒK6–ºó²-oÖæMAY6›MÚat=/A†‚»%%“”úDVRêb¨ðùQ!¹Qaå³R^ª‡õ‡à#ðr›ât,£”æŽ,…ûQ¸¥p|–*ÁG³F²Cûó"s·˜×`WY:‡«}íYr˜PÑcHî@j4žÔèf¸V‡3«Qì¹Íš;5ÆÇPš§á1Ÿ´¦>¬Éþ1ŒÄôoœ
+ÍÍMU
+ëO‘|Cs>‘h°
+H\a¸¯aÁiñÖ uiùÉï6Û3WÀÅ#”'6òmŸ^¢ˆéÐþ-˜í²/¢~¥²bÀSž)¼@ÿ qœ|¬°슆z K==ñ0O|XÀ`»G—¢u:†±Â73m)«ÍÆYC ¤J6[D³Ùb6Qè0S&h±ÊÀ‰ôgÙhbá “·²Evû%Çà° š$ד\}•¼êã5ØM%Û{ÐvɶC©Áy
+‹{´¥‘íj¨þÓ^´§U·1××âu°& +V¤.˜ƒUüMŽ~cü6ªäuŒjãøgª¹`¼kžÒ—PÏmÄ—
+#r¶¢¹2ƒàÄOÅl0 ":½d© ‘
+}ãØ€HDWÀPäݨ­°hr1»ÿq3ž|ÍÕh;Fœ ï)ÿ“î x]±5„à5¡ß…þ¢ Ao²®1ëB‚S± †/„Š
+¢†`Q Á¬Ÿ£È:D3+´ª4K¬V0õŸJ³
+¡Ü5Ò!I€HöõÈÀCÌ„˜ºB-µ:d¨Ãt«’­¦™"¥n#ŒVéUAÆT©‰‰Y!X ŠAˆImËðˆ|²Á,IÙ9½ÓéÉθj‰$™Ø*ù’Ýp]û|†6˜Á•™yAy!ŸM$ä+oCä³ &­A´¼¨Ø÷ˆCpc£Þuàje~>jˆûéU¾õÜ6î@„ÑKÕûœ†vø<&½– ˜‚Ÿo5«YV^ ®ÖfZí¦¡•¦)ÚsHÑ54¥úÆOž?ŽQLhDKeÆi8IeŠ7˜plåãI »ãP“þ/ε{^ã9Ë:ò.Ÿ;ÜåC‰Ó=c]s| xa³k΀O¤îwqáŸfZCœ8'È:y.¸¸ëô­­3M`ì`žÕü‰Š‚út¸câahiE¤©T´özR=çõ ÷lîÑö¸KŒÎM ƒªû u²2’ÿŠ*ƒ#¹\õNÚÞÚÞ™ø=øöÒT›*V³yƲ@îÈÁ»|w—ÊÏ(ìÜMôïl9@݆o×}î๹ºçàH‚Üusy³ù%ºkÝU þ¬À¡˜ ìh³ÌAØ¥—*ïz¯DïÒPïzò·}G±@® ¨Bäâ¹ 4ô
+v¤¾Wu†½hDHA²,ŸÎ+ù<“÷=H »'ÌÕFúk#ß
+ ?I=›ˆQ14æòæ‘Óf}ú¸^ô¯b¢ö ¡ê¼©ÿŠ1þÚL)—b NB¦Éjý mÔþw0ˆ‹Ð3h*ã܆˜ˆ¦"Ó¸è Z)NÂE¯«_óØp¢¯€Rùýøë½ðÜÔú××ú÷îÿØu.Ü[>Co­÷»
+@‹$¦DEÑeX-I.N œp5¯ã$¹ªÅ‘T ¤Æ«ù}g@•W‘î•„ëŠz
+cŽÍ’òçjÊ5 žë±ñM[ÿùsR¯$à9¸€DàGÕøÏ¢N_§ù#Î< #§ØY.ˆÂ‡j ªGQmEäƒÒ¨=I Im î5%äú¿à"UÉîÇ°äq¬‡5,{*
+Ý&ª?‹†g=´qÓƒ]¾ñ¡ËÖÌžµfͬÙk˜g.ðÁË/èÁM³×¬™~Žl«4í üN‘šô‘Ëabµ¼>™ ÕÉ—ȺÞ\W¢¾Ü'ëóL NŒ.rC÷2óAø1á/öfór ~±/Ír| îW õÛô:b ØÅà ¶%åL&‹ŽFÛ¤üjB[ÅN«T8­m|üäøøàØwœ¤Zò®ZS¯z¯Vü¹NO #êéô…A ‡
+o»; ;¿Uãä#»%‘Ûo¬aÕìÅSaÓ3€uUË*J45*IºålÃbC(ï õW_v×¾½·ôÞÕbçGæŠÛq‡{ŸûæYŒö˜ >gæð¼[Úp;Ü…»¿}ããMqÞ)øäùú#øúáí»w|ó,4××aM‡Ù f¿)Ë›N6PLC¤a0½²™ih^2kí¬Rø­Ø»Íov|ìü8ü0›èŠÌÊÎêňq{C¦¡·aazqÃòÌ —¤4°»æÞŽ¦·®Ç£xi$J´F1¶$ë;CEñBo º÷[t¯±DÓX³…I²M}ìAø ´œ$%P×›”¾“KÖ½Æw=Áw[©Àfœ 3»ž¶°7ÝèžĊyNâ¸<@‹e àØÒŽ«™‰ètd\¡µxd'²Ôñ„·Nu‹ «ú¢¹SŒ¬"Ôpp»êwÀ%ÜDé¢9†rò‚´~Öø¿ÛåLDr¦?ái~¾c÷Uïts‚¸è’רÔïñÙƒl~i[Îå”Ä%Ã.wQÑÖ_/îmÆ$üÕÂköÜTo‘¤‹nXNè~ŽÏu燞Åy‚wNÜÀt¡¦ ,+톹±¹ ËÚl…t¾eAZg\Rç篵ÝjÓè s^Ÿ†Q9|O,––¹ôÒ¥óÛÒÝéôœ9ó»K°K1 Ìëútp¥çãcO}}øõXÚ("Ž,JÛ÷¢ Ýît"šN”àì½²(Á¿Œ®ÐëÒP2[q(O›Úº;Ò¦½½ik6¥²ÒŠ]¥*¬
+GæøX¥ÆÉFcªäCÛ]µÆ ²_ªK!X™ýŠU®S]=U„=¨fÄ*V_›ê"¢µáSÃ*ÄÅ}¢ôœÙ—ìßX×úÆÈÎÖÖË/ å¯(¯çÑi¸ò‚ó£™'¾µ»3¿ac¨pÅìŸYÄÁ?¾þG¬ý‚Hó¿uÙ
+æ/oÙm6ûýf6'{®QÎí.ööœs­ù‘9ïà ?¾ª=V.^paooW÷6“î¹tay==#ÞØÚ¶zÞÙíZHuÕE»—Ïë.`»|þ+}.½ íÆ-
+€PO§Òµ½£#¤4&êSb:Zç1hZÜ’Ç_ç4ÄÒ¹¦`,¦ä‚ pb„ºÛߣ°þ otƒ¢.Øò`0hµ@‹{žˆqbl{‡ 4wΖª'©ð¡êPGOM§àŽ¤ô„€ê6Š¶ÔŽÓa!H F3mÙÊQÚVº=
+E¢"1D ÖÕ<jµÄ¡
+/cB¨êI/ªxtZ+úÄô nHýâ†Í{®ÌÍí{øÒsnp ‚jê"+.ìY¹ª}aÀÄIö® 3[VŸ{…Lü¿¸XJߺþ'¿ºáúűƮ=úÂw×;$—Ô«ÿÕº%·.ˆK³—²}©[†gýóÊjþ6›
+‡¥¡PHš?^ÁFjôÌy%(*ûÙt_´«Ëµ¸ßÞÛÙ£”¨C{Mgƒ•|B»\êw¹$tac: “%8¬°ÂÙZim˜u©º“"dûÆTYŠÿÆÇNž$ ¨~Q±P pHOâÆUá¸V’ß “Ó MÀšš È –ƒB-^gm‚f#*l{Ò‡Q‘¨pE‚ðÄ z<%·í"n×ÙÕäb-¡}%ÀךêbÖ9ˆ°®tC«h¢aæ¥ò}åñò}píx®Y~îØûåßÀâûÇ`÷øü•f£^o4¿¬VŠ¢ÖP^uÍ•™y‹ê*çW|Cùák†Ï›õ85·v+t[tr¿ç`÷3_h:I£1é´f Õ¦5iÑÑÈœÌÙþЪïªG\H­jI/ô~šeÆùúaËùÜøMÇ –nDÜì0 Á!Í%ºaã°y˜² 97À šÍºÍÆÍæÍüÛ'GÏ¢çPmzDúÈ­Þæ–Ú†Tª·—¦ÁlÐïøö¨<;=›š]¢ìŠ¡ëÿÐ*S‚4z‡æ”lýShˆ ýdø“QÄ1ßÔ¦§(¦Þ·1‹Ì¥ fºN±Çæ‹1ô689Ftæ±ã*h Æ‡1ÆLp3Áȧ1ÆLp3ÁáIL ¢Ñ¿‚þ5mZÍ/¬%Eºmr¬šzø5/?b1²fD"ƒ™¢Ó3–^ÐÙß…›V²F£éCËniõoûÖ¿|%…áç!Þjå¿c1êÌÖæHKqùú%—<p‰ÉÄz7-ÌÍûÆúg°ìe¨!æ0ó}àŠRæ/÷.ORüßòìg®.ÀPŸÔ4é ‡’5k½&ùè_K²­q…—¹Æû#ï’ôJßÊÆ “tƒ¯¡±œ—dš
+^o‰Ú¢°MbccSÒïóáÃÞÆ$:Lºñçñ›yšçýÚçs­­‘H]V«ëDú\ ¡!§(M¦t¾S4PÐdlÔiuÍÆœ±DmVÜi:YGét©¦¦d2‘@³ëÀl¶àˬH5yóI_ ÑM7ÜáÞã¦ÜnhÃ'‚œ>n}ÖJ¥¬Eëf+mU –¬Õjb˜”¡h  ˆ{µ
+†é)W36[fÊ ŒÇÿŸû¤ôr¾4óáΆ†Ÿ64D.Ù±ã’iv2g•‚2ººçÎxüÕWãñ;ËOÂYå¥äÜ—_†íe+iïƺç!zœæ5Í€AÅhŽ¢7Ð[h ýü;0+ühSØÄD_¢«ˆç¶ê:£¾sp¼dà>qâŠùWDI`9+©xìi(2 ôÌïÉÎÖ¢xè ë»Ý lH›6˜(Ó¿ ZÉe
+<ï§úDŠê£ø(Û'D¥~PÁû
+îàIœâu’À9UTÑšúƈ[…è¨À]å§ábœ¬œL0)ö<xò…¯I›i™2î«ï28½«ŽÓ
+8ŠˆÄMž† ¬åpòU;”¯dRל4a>¨ÆÓ¦°f]ðašZ[~gY+V2‰; Šß&¨ŠõØW¾þ!2Ç6þCp·†vêDŽïÆ=/]÷0¼µü»ª²Iÿ•ø÷^À—>*/ìÄn¼qÑQö=ç4j9Ú`“Ê%937SkÆ
+HEÕ¥oáÞĘù„åºùN¡3ÚÒ¤K™c¼ìOE妢¹Å_D§¶ƒ{,¶7˜ãz–5ò¡x¼^  ¡¹™|^7l¼á=¡fÆg¢¡(œ:–­nýA4„ɽ¦ô(Á•Š]HÖÉ‘:«´6U|œOö¥} c×)l¬Îôÿ÷ø(Ê»ÿç™Ùsö˜cÏÙ+;{e“ÝÍÙ#Én’I!@B¢ aŠ
+¢mˆ"õ­ZE­`ÑzàQ¥µ^ „À‚úÚ¾µÖ¾jU¬Š­ÿTkmZ-Hµ’Íÿyf„`û¾yžgžyž™gžçù]ß/Ÿp«i²ë T!e¤æúŠÛGÚÆ@ Xˆ KÉ.±4O…Bñ‹6Îò¥*§Â[·’‘2úÞV¤˜8" þ€«F§÷ëk@¤&Ú
+= "ëÛ#³æl$>Ë œ7§÷û*U§ÇZãQ˜Y½‰v¬n/23ŒåjUÄ]WÛŒÆ'€Æç!4>Xg<$:Þ"Þ’Q¡>Ð}À¾fxÍ¢2®¤'ÆÂäFPΠ\Ô£‚.È™’fœð%”³ø’e&÷Ñaµ6Œ ¥ïsá+Ÿ;@9@[ai',ëŸRH«jÀ±Äl°AlÀ±Äl°Áé^Œ*¾6?]NG'ÚÿÃîÇÇi7ž{îø ¿Ù°s×%vîÜpÖ¦kÎ< $Ë™Éd¿ 7Ù`X"žkLxHO"I&ä|EW¢w¶ØwyÃ%}Ûèí [zé»g?9›%RŠ~çŠíúûœ÷5ܹì!Å.ýã £ŠúgO'žíÛ·ŒÝÖ²£…H¨œËóËdè«’„<Çw/p¸¤N8½ »©˜›'tuå”H*#:M7òõ+¹À-EÖ§Y¶ÝétÙåY“h2÷â¾ölÄqÀì‚l?&¯¯XÙ`R µ¶•M7ž)øøw„ž
+ÚOQìvÄ`SIsD3ÍN õB™Õ&av—d Œ·•KÑñcÉ ‹wé#ù.‚‹ü­ŸP,xü ƒgÖ€%JÎðŸ^Ïò.­åS’<Ó(ÐIc¦@·Nþuï"žp-.L~R¡ONk¥4…É¿î›kœÃ÷¸z§Ú€a˜†‚ä­œ
+ãIˆŠš()Õud)y0+kKª*]Q–}JeuI?š‘ýbâ/ô­³–üˆ£9‹.¶¦?×zyo*sÖµl[”=óªïF–†×¶
+k6 Ã;öµÍ¾¶&“è˜óÝ_/2žÞÒÕÞ2`Z9³îÖ S­´¤¢â"¸}ôüùëi+ÇÐÉÚþn¼¿Ez[Îܱ0sZ°E§»ªûB§MÇ3Œ«sÅÂAbâÇÛó]˶÷Òt§1{Y›+x!šŸë&“MŽ m¤DÁ?ųëTîZ†Q«w-˪
+„[¤ýÐ i>Ð|¨‘iøX}•iPZÂÇòÙ>Žþ³hl 38]O”dš’‘”CɸŸž•ÕÄPØës8µ:¯Îï!gÄ }Z†õÞij¢_9¥&KúaU=4–ÕCEY=Ä‘((^mæ8«ùŠ+ ÿò#?¸Ê̱¼ùòË‹Ÿ¼üܲöºG>ùNûÚëùxeç5ÞÀ˜¯¾~÷³Ð°j“Ùj`,W]·û¹âßH8ÿ÷Þ4ÔÔûÇ{o½i…/%Ÿ#¿t žS×8n‹ßîxÐ!c¬Œƒ‰ó̃æµæó;þËý–ûOî£nµÃbÜk!Íú8ɹƒCj W‰§ÖÃ_©”ýÜÁqa5™ÜæfÂ,ÑÜc6'm‚Ý}-JF ð³} !»©”ÏÀ/@#ñ1ñI)°3Ž¼ª‘…˜Ç«XR'Ð÷˜8–onfñÂ-SXOÓdÅ»§PVBãÓjJM‰/
+µ¶ÕãdÖ%߈<|mç%‹ðzØÞ°`ÁÏ_¹Œx¤µ>‚t°H¶¸ñ ,´o8­aÖЃ5ÁYøìònñ7w/ß‚dÍgÅ+ˆÈï¡q«ý"õß<D–½Ùj²²Që•Ö6ÍNÓ «M¶Ð MÐbîˆ[©(€ €äµÀ”Þ±‰1l—«€S±ßgÆ«JkÝP s—×âÁÉ­~H¶ØàõF‰ûñ£ãW81@\ï¶ÙÜWX´ž†ˆŸÂ¯tÉZ‰‹Zö
+›“Ÿç̨ȗãÿÁÆf­1•FÒYÁÐ,ÍÑZ¦h4f@³%i:Ñ
+À"MXcœâm5)+d#¯GO˜Œ\c#qî”LêUÿдøô¶+ˆë$Ó•KxGl“Õuù-ß¿|©‹H]/H¦þg0 5¾ze..>kþZìmÆ
+Á¯ñI ¡ê¾úІO‹_¡µÁ¡oùy ²Ñ“ îÁlªcâäe¥m¥{eä܆sb+ãCɵoÇ(WÚž©O×gÒDZ‘M_OÜ–Úœ¾%s'±U¿=µ=}oæŽì¹äÇcõ;B;";b»R»ÒOfÎî%FèQÇžØÓ©çÒ£™ÑìhÎÿ—Ч‘ãc_‡¾‰|W*¬TˆŠÈãŠF:kVØB¶ˆ!nkò+¡pÄoÈ$­™ë•7Äo'ïPܺ?²-¾­q{ÓÏÒO„žˆìˆïh|´i„|J±W9j{&ôLd4>ÒøLæ™l¸NeöÕµæRj”: )_®¹•ú•!ÕŠL@h B³rÁxÞ
+‡œÐÉ· Jƒfʦ«‚óÐÔú8¦O_%’SJñL›(¹–ÊÐ< †–HȉÛÜ5»?âŽzA܆’WØ cŽDEÓƺö4Ãmocdü'?ÉÉ¿ì®7Wì1¤UÂ|\„Äp9É$S”u…’%&m;ÓŒrÅ
+09¢S¯#Q.š­­ePçY ‚uŠ¯œ¯p|Ci¾JˆÉ݈cç’BYzÝé’}Z€@¨¦·
+¥ ®ѼSâÅŸV"¿äïKÍ¢ÅP%PÉ‹?•BÂÑ(’ÊC\ö;$•—•ý9PâHÅf?5›˜ÍýTâH¥§£úË̆U8² ñ«rÓøU%6ÀlÏ$6@çt=
+a(ÁR¥,Ý%¨0aD ¯P
+ö ˜J™”\k&£žÀž´kƒÁà"
+º_zíÎúúúZRñî†v]ª!æÔ×Oì#"(=¬‚ʽ¿¹Ÿ3g_{×¢m»þÙåZêr½=?Ê65}Úܸ|ËšƒWIu»‹'ž5Õ²gÓ¸ùSla_€ ¥k$Û¢Kômש ZÙ
+
+ÿ| ¦:%9#"IV2[ Z"¿ü+…¦L%/±c¤$Sì“tÈ]ø ž&…)G¤t®ôûKrÂPñiâuhB»s@¤JÛòQ´/Ë
+~·¼G¡„Šej'~¾ºCÓÄ;>¼àÃâ ™ iìX¾Í*NS’o†A-qn-”dgRX̹ ˆåÜ¿/ÝèX ‡q<?Sâ~›¨»ãTQAÑWu;Ë ­“ŸÉ6Ë&Ø@hsÁbp\%Ö¬ygr'=8qÂã„ÅÉwð…ò|9ï.ç]å¼³œ[ʹoC‹P¡ aÿr˜§èU/ û¢½©Þ¦¾¶þyê5Ôšæ5ýkÉÚÚ¶/Yª^Ö´t`ÙBehQäÔmtk4—Ê5µ¶µÏS÷P=Í=ý=‹dÎ>TŽ‘¾ ÊEMHZB!Y˲Ì‚=;³ #Ó‚Ks2ÖŒ —¸Œ†Î€qp¯)£â…ŒŽžÚ½$3‡ß¨p:<ýÏm™(:Ý3+“)öŸ»@Өр§À…’ nǪ2úãXR¸”R8šT9*
+C¿a×4¢÷·xnµX#ØC¤Ð}S’c 1ý¾©Ê=%-"8M‹‰Åž{>ì!A»g ‡ìAwýɨ¤ÌžºmY™ÉKï’xé<ÒEÜ°Ó'ñÊ[g°Òÿ
+8`
+“Ý%fëÉO¶õ¼RêÙT~2³ô­(ÈgD§S„0yÒ$Õ>uÕ>¥™é@ßÄaÜ ñdl;Åg5óN]“ÿõŠˆÜÔ
+Ý­›Z ·DJ'1)½WÅŽ«áÖw$4y6°‚•b“×”0‰¦Ó*Ó°i“II«µ‹Æ£&TòÅzTœÕtËz¬
+µŠÐÍö3áùÓ6–œ~˜L‚äyû¿àù) ŽÌqÉáSÖü‰mp–³V—M&CÂyÞ—.;ËgŸø‡±0²â
+Êˬ”ÚÚJˆ8ÒÅs:óûGÌz–wÈ]ÿSBw=ú(˳&z¾ ù)ùsÙ~¤&®¿ jèÍ„šRØ4N²ÆncôZJIÕaÇîÛÐ舉ýÖ°n÷&²¨,Òjš¬!£$I¾oäÝ'ãúÆó€>6Žñ2c§Ç”›ctCòsHAòJ–×3:ñ»-î`«ÝÀY´¸ÚnqúÙmVš¥#NS¨‰·2¶`–_9K‡±*»ÉÏI»|‘ä#>MÔ˜Ew0©Ç‰Ëo”³8)˜$3¦ñÕ(QƒŒ¶
+q«^¡p9f—Õ]ëÚnº'¹­í Ó“ÉÛžIîiÙÓöb–ÑhtN²¤kh7-Ы©¦Æév Ôón×¹]“*tQ@±§öæ„ÏD'¤?$Ä€;õC¿¿Y%A³à6ÇÌ¢™4+£ñÞ‰ˆŠÛÒ­ƒ:[GN0ðbýÖÊ/‰W:ñ1¶zÆ°Ÿ(?.ñJqVšõ%lNÈlioLéMm¤¿Å”ó‚v%tÚ ³Æf/lå^Ò—¥ˆ@Hic'ãøÊÌI˜ìy Î@ VVA2fµå œb“Ífâ­ÆÄØ7Ýtcñë7^*~ U/®Ø‘òÕV]W<d4X]Kn vÍ©u8ì×ÂåÏ~gÇ#ïÿœìŽ5ÚË5FûÕÅ#¯‹Å£Ph?”ÍjÚî¼ÿ’uf†¶ÛëÕFµœgë7 –?±æ¾·Þ¾cù¾sªFEcÕÃx«´‹Ú®Ýì)Lž»·éÚ'E*+þLy¼ìÏÄ}nA»šÔ‡+LÞ-õÉLßÍ°'Ýg­ìÈ€/Dñ ö±ø“©gØCñC)E\¥„²´Jå„>—òû.‹Ó–6›ÎZP
+œ !ÓhNg\”¨†´ºFM¨ Ä×¢^€Ñ—±ßM¸Êf¸\NU£Ë&BgkV™]?ßtü²*ϸD3–˜ÞÅáÜDN*äqI­ÿûÊÅh¿XJc õŒžÕsz™"îOi#0f@IR›ŽÀ„>©DŒpœ1«(â2;TZÚ&ádHqyH„ò¼ 'Å ?„Þ'ß›“˜?Ðrfñk(ˆ‹vœ»l´ñ]¨Í?<ÿ±k‹oÉnÇëø¾ßÝ4p­¿Éf¼g:CgVžØ}ú¥m«îDZ•úŠg!ÙâGkxTQû‹ÐÏ#?ËêT3u:=fÚĽ¤×{L5~OÔåò@]Ôê™2*h(³I¯@€ Ä›äaY'ëÝ.Ú9ä$œ|bù¦4rì”—Ôr ×üF׋×å””¼0F¡¤VYç…qu´‡+­9VB%€[-Ûø­£Ù§»êç?qÉ•¿¿¸8ñìoyEÅ¡Ê(Ú\ä}oÜu÷›oÞý“7eŸL|4¸lý«'÷xñ°ÊŸÇ¸c[_}mËÖ×^ÅúŸü|ž|À€cò„¨^ö½¤A†û!â00ÇhP‰#Ž^
+Õ£¡†ŠSñ 3]ÉZ¤®}Më)Ž·@Eñk3ϱf¨„r ‹A5ß@%ªQ+(=¡CÍ”å«J3‹Ú£É¬Ú¿)~Úó2Fu±†<SŽö!ðó=œš.÷‹í6F«¥™NµŠÀ|”Ë Ø©21ø4vG†86ʪú¥Ø¢‰\Ÿm'
+<ŸÎ@oÞ+—#}ï7@8:s{°0ùç­QÊň†kWùà¹ÞbÍ¿ÜrJg– ©î´Ú ô”z·µ&\ó?úW¯Ôþ (åÈ Ù¡; ‘UD £!4 zÚZƒÔÏ݆Œ
+-áWÆJÂûØóÃØÿ=ÆL ¿ñ<o/£Ó†á·ÛfU ¬T­åÊ`¶wßþý9·óJM;äÏX{á9¼Ñdîï œ6guZgdŒa}çê+¬ùŠ}y|þÕ)^¥Ö0l|0•$ £Õ0ö´3<§™f(µöÿ³o%àQYøï™É’I$!W‡„3“„#lè„3Ç@¸Ê‘Cr¢“pÉå"""º„p™UÅE@6p%° ¨‘Ad%rÉ" *+Þ¿;, è®û}ûõô÷wWWWWÕ{ﯫ{ª‚CóL¡ÐÓM`8¢úV{ FÔuºÏtßéAÓƒ ÁAAÁ¾>^ùë}†ô‰ó Šò `
+ÉŠŽŽŠ0GFFÅE÷*M1f98Yö
+‘\¼,1.dx”Q-Ì”š¦u3õo‘æyÐÍæ Éå|Ðht«Â%‡!@J”clOê>H™¬®|­&W®Çž4ª“H¨ëÊòºËê—êúÉöêÌ êÚNåµ·a)uµ , ¾»÷5þéT¯Øàb³;ø­!ýZQsgwoQ_®êæý;_Ýll\N |½£«×m¾¾ÖÅËÝÓC×ÏÅÛÍóÚk>vNŽvî }„f݃;ìÖ©‰ÞÞÑ–œž rš,ƒj¹÷­–K„YxLr¥³‡Æ›âÍL̶w”Þ7J_ßà `:Ål®ÚH]BÃ<BCÃhpCD?ß ¤dŸ`{t0‡î2gÅ„›º›ú›ôŦé¦?˜ô&S|Jò°®‰æ„„øƈ»Þ;aL¶Fò¸sû‡¥‡éÂâS†„U s¥&áá:ÄÄtMN
+5w3Uë–K~I!!®½zézÍNŒ¨ˆ«HìÖµ¢C¤6VËÒ:Çã&Ý"ôCŠ0Dù"r=DÖÆÎ+³sG*ëÇÎ×/ìU¶€ÂGÞÉë×ø*E…s„wþ´1¶qÞ ë:2—0/•I¼àu¯ÀÏqÜýM)t¶·
+jvÛÚÞH7åÿ·;1lêµ1žÎî^úrOg7ïòºõ‚ç?ïfŽnMýü”âÕÊn€í¥ûáÕõ–1ÂËu£Üœì\ì&»9±°“³qPP·¨O›ÕÙ9(B¤v‰I:)QJ–ò¥‚ÔÄÔ¤ÔüÔ‚Œ¤ŒüŒ§.11¢ï!Iñù
+w:%%{$%%K1ñ] 
+áï#åæu‰w÷7$í*ÈJKLÌÉÏ’<4'+=}”–—W+—jáÄ:÷,Ûv<J®­²:ÚvDz²<Ê1H²J“ò2-mh^nRA·D…&¾¹}ûºfdé²fç ¨^‘ÓmhEQËÀˆf#õÕº‘ë}ÊM9y.Ù ÌS_ù”©ðê¿‘÷¢I¸QÚ­Ì0¼‰&·äF¤¹•'ê_f¿4¬ÛüšL½ï'îÔµ1J\
+Ð/PÏÞ<$ÏÅxd<rߌäS6±†36eh?ÉÁÎß:û«Z8\5å^ÀÞ¼:F
+ _RK\í¼š:ðIT’YR’aQWY•*ì\,é%F•¨ï%}…aEKÔ;aý½ôg;
+ôaÿ³€d̶֑̯𩸠Äëi"0Œò<ôðpA9‡÷F°žÌ±Å:2x-óMàæfß²W
+#ÜàŽ¦lµšÃ^ðF øÀ~ðG
+¹_Ž™xÊ‹E8YxÏâ%¬Â«¼2‡ú}åøßá9žÏÅ7XŠÕ¸„‹¸ŒW°bþ‚,<‚yÈÆv|„]ø;ñ ¾Böb7ö ¹¸€2À>ìGþ¯ñ
+BŒAÆbŠñ…%‡RŒÇœÁD<ŽI˜Œ©˜‚õxÓ1 Oà÷8‹sØ
+ƒ„ !S˜(L¦ óuÛtGŦ¢‡è%z‹-D_ÑOôE1Pl)¶;ˆ1bWqM`KY¦ÍÄ{h¤Œ¶]H»ß®‘Wî¡‘µ?£‘šÛ4ò‰U#ûoÒÈ‘{j䬪‘ wÑÈÕ_§ùý/ž^+¡µ|þØçÃè§Aô±`ˆòEzxwù}1ˆžß‡g:ù¸þù;Hò1ù´|\¾$×ÉWä£ ï—#NþLÞG¿ F”|Rþ†~No—OÈçÈGƒ|V^*ï_b/Ê×å:ëà)/d?®ñ¾2¦7ÈWYÛ\%êÈ«å9òlùë~£ºúÆþŠºŸeÝo‘Wq?S~J>/_`Ù‘ÜfpKs¹yÔ¯_­]Êí%n«js[Q›U»¬6»ö©Ú…µ3¹ü'èÿÝOÿ³%\è å
+nÜcÇÖ¨ÑH2]°^k&4±¦ L·´¦m™Ž¶¦í-¤(O7ƒƒR§ð¤5- ½pÞšÖÁEçiMëÑ^×Êš60Ýßš¶ez’5Íþè–ÓE²»þY$òY’Çø,ò SÌÞ3ÆNb¼UrzðÌ´²Ïd~¾Z"ŒW⛋xȼ\Þ_Ê謜eó˜ÍÒã¹Í’J ãxž¯æŠô¬lÆo‘çJùL¢T­{4óÇðhaÜyOÎ/é×*±S‡ŽÄÁyÙ¢¹xlqé¤G³ÅÅ–G‹-™¥ùÅcÃÄø¢"q`~n^i‰80»$Û2>{tXÞ=âSRBz³äg[úeOHdü
+endstream
+endobj
+xref
+0 18
+0000000000 65535 f
+0000000015 00000 n
+0000000479 00000 n
+0000009881 00000 n
+0000009927 00000 n
+0000010126 00000 n
+0000010164 00000 n
+0000000251 00000 n
+0000010257 00000 n
+0000010277 00000 n
+0000012952 00000 n
+0000012980 00000 n
+0000013194 00000 n
+0000013367 00000 n
+0000016044 00000 n
+0000016137 00000 n
+0000017189 00000 n
+0000017469 00000 n
+trailer
+<<
+/Size 18
+/Root 1 0 R
+/Info 7 0 R
+/ID [<1BB3350AE06F3BC804CB17F01927313C> <7D83F4207D693A4F93CFC07CDACF7461>]
+>>
+startxref
+67634
+%%EOF
+1 0 obj
+<<
+/Metadata 2 0 R
+/Outlines 3 0 R
+/OutputIntents [4 0 R]
+/PageLabels 5 0 R
+/Pages 6 0 R
+/Type /Catalog
+/Extensions <<
+/ESIC <<
+/BaseVersion /1.7
+/ExtensionLevel 2
+>>
+/LTUd <<
+/BaseVersion /1.7
+/ExtensionLevel 1
+>>
+>>
+/AcroForm <<
+/Fields [18 0 R]
+/SigFlags 3
+>>
+>>
+endobj
+18 0 obj
+<<
+/FT /Sig
+/F 132
+/T (padesSignature_0)
+/Type /Annot
+/Subtype /Widget
+/V 19 0 R
+/P 11 0 R
+/Rect [0 0 0 0]
+/AP <<
+/N 20 0 R
+>>
+>>
+endobj
+19 0 obj
+<<
+/Type /Sig
+/Filter /Adobe.PPKLite
+/SubFilter /ETSI.CAdES.detached
+/Name <FEFF004D0069006B011700200050016B006B0075006F00740075006B00610073>
+/Reason (signature)
+/M (D:20141112123930+02'00')
+/Contents <3082064706092A864886F70D010702A082063830820634020101310B300906052B0E03021A0500300B06092A864886F70D010701A082040B30820407308202EFA00302010202044B84F591300D06092A864886F70D0101050500306A310B300906035504061302454531223020060355040A1319415320536572746966697473656572696D69736B65736B75733121301F060355040B1318536572746966697473656572696D69737465656E75736564311430120603550403130B4549442D534B2032303037301E170D3130303232343039343635375A170D3135303232383039343635375A308196310B3009060355040613024C543110300E060355040A13074F4D4E4954454C31193017060355040B13106D6F62696C65207369676E617475726531223020060355040313195045544B55532C5045545241532C3337353033323530383839310F300D060355040413065045544B5553310F300D060355042A1306504554524153311430120603550405130B333735303332353038383930819F300D06092A864886F70D010101050003818D0030818902818100B6428770253983815FAC33A4628967D4B14C9846565294ABE790EDBF328EBFD990B9D17C3C713B991447A42274C8D77CF665FC1C68E46D560843C5914A5A209BD62793316F4608479CED12A14AA595DC4B3B2C6EC9ADDBED7410DF02EB280F9B9B63ECB1B00728D3CD5FA622D68C89CE1A20066F7937B32EDBFA24BDC68306210203010001A382010A30820106300E0603551D0F0101FF04040302064030360603551D1F042F302D302BA029A0278625687474703A2F2F7777772E736B2E65652F63726C732F6569642F656964323030372E63726C30540603551D20044D304B3049060A2B06010401CE1F0B0102303B301206082B0601050507020230061A046E6F6E65302506082B060105050702011619687474703A2F2F7777772E736B2E65652F6370732F6D69642F301806082B06010505070103040C300A3008060604008E460101301F0603551D230418301680141C07F49CBFA4256CB3B49E221F1F94481B587A8D301D0603551D0E0416041400B75CB9AA2A84AC54360E22CA7B52840969AB52300C0603551D130101FF04023000300D06092A864886F70D01010505000382010100A9D18876ED607C5678B19DD2622764C0ADAE37F4625DED79F1B91BC53F9D4C5F65A865D9143978AD1B174FC83C2E3A98F9CE02F5313450A5FAE6499DA958DE3C4BFE8CCEB71CFB50C104B456CA11F015622150CCC43D505F53BEBF652BC0EE50278EE54464FDD4DA94E1CE24753B8112A8E595E46B89CBBC1AB522177DC20B41FD7D8E2C2A552B037DDE1CE5D39480D6E0E48C5E68A0CECF0771DE529D1A11A31FBF8A16964F4CB5B577B0837962D172818C58BC806C92FF48EE52A3D3D14CABACC701B91966C39575F31E6A2A026AEF758C2B84E7B342F7172A8B5CBD8E9F34393763AF6A1520909884964EAD0CB9D2F033413E9140C17540DC093E2316A49631820204308202000201013072306A310B300906035504061302454531223020060355040A1319415320536572746966697473656572696D69736B65736B75733121301F060355040B1318536572746966697473656572696D69737465656E75736564311430120603550403130B4549442D534B203230303702044B84F591300906052B0E03021A0500A081E9301806092A864886F70D010903310B06092A864886F70D010701302306092A864886F70D010904311604141450A8C997893287B4B501179D178C0542AB0D733081A7060B2A864886F70D010910020C31819730819430819130818E0414B3B71275738D180A9A54A5E01C5EFCF39CFB07E43076306EA46C306A310B300906035504061302454531223020060355040A1319415320536572746966697473656572696D69736B65736B75733121301F060355040B1318536572746966697473656572696D69737465656E75736564311430120603550403130B4549442D534B203230303702044B84F591300D06092A864886F70D01010105000481806C4B61E3026064645B4F29B64050535F3B7028660F2F1C302323BD957A0BE25B60CBBE23CC6C01ADB8437495E879EE088A30803823BE9B005AD8DEE492C3C70FB1A817CD2CDB3BD1A071BACA9271E1994EBD8A6B4D91B2F8F3A6FC1E55318B51E92588B6B90EA8ECF39AB2B99242AB4E81A494113AFC4360925842979F5416B7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000>
+/ByteRange [0 68786 74932 712]
+>>
+endobj
+11 0 obj
+<<
+/Contents 12 0 R
+/Parent 6 0 R
+/Resources <<
+/ColorSpace <<
+/CS0 [/ICCBased 13 0 R]
+>>
+/ExtGState <<
+/GS0 14 0 R
+>>
+/Font <<
+/TT0 15 0 R
+>>
+/ProcSet [/PDF /Text]
+/XObject <<
+>>
+>>
+/Type /Page
+/Annots [18 0 R]
+>>
+endobj
+20 0 obj
+<<
+/Subtype /Form
+/BBox [0 0 0 0]
+/Length 21 0 R
+>>
+stream
+
+endstream
+endobj
+21 0 obj
+0
+endobj
+xref
+0 2
+0000000000 65535 f
+0000068149 00000 n
+11 1
+0000074991 00000 n
+18 4
+0000068430 00000 n
+0000068576 00000 n
+0000075222 00000 n
+0000075310 00000 n
+trailer
+<<
+/Size 22
+/Root 1 0 R
+/Info 7 0 R
+/ID [<BF432A7C56D5820F25CFC942E39B1593> <BF432A7C56D5820F25CFC942E39B1593>]
+/Prev 67634
+>>
+startxref
+75328
+%%EOF
+1 0 obj
+<<
+/Metadata 2 0 R
+/Outlines 3 0 R
+/OutputIntents [4 0 R]
+/PageLabels 5 0 R
+/Pages 6 0 R
+/Type /Catalog
+/Extensions <<
+/ESIC <<
+/BaseVersion /1.7
+/ExtensionLevel 2
+>>
+/LTUd <<
+/BaseVersion /1.7
+/ExtensionLevel 1
+>>
+/ADBE <<
+/BaseVersion /1.7
+/ExtensionLevel 5
+>>
+>>
+/AcroForm <<
+/Fields [18 0 R 22 0 R]
+/SigFlags 3
+>>
+/DSS 23 0 R
+/Version /1.7
+>>
+endobj
+22 0 obj
+<<
+/FT /Sig
+/F 132
+/T (padesDocumentTimeStamp_1)
+/Type /Annot
+/Subtype /Widget
+/V 24 0 R
+/P 11 0 R
+/Rect [0 0 0 0]
+/AP <<
+/N 25 0 R
+>>
+>>
+endobj
+23 0 obj
+<<
+/Type /DSS
+/CRLs [26 0 R 27 0 R]
+/Certs [28 0 R 29 0 R]
+>>
+endobj
+24 0 obj
+<<
+/Type /DocTimeStamp
+/Filter /Adobe.PPKLite
+/SubFilter /ETSI.RFC3161
+/Contents <308006092A864886F70D010702A08030820DCD020103310F300D060960864801650304020105003081DE060B2A864886F70D0109100104A081CE0481CB3081C8020101060B2B0601040182AC180103013031300D0609608648016503040201050004201E400186AF27B68CCA8964104067934E92ABB645FE995FA01CE8E984B21D4AE4020310A336181332303134313131323133303034322E3433315A3004800200C802087CCC4BF048230D24A059A4573055310B3009060355040613024C543110300E0603550407130756696C6E69757331163014060355040A130D42616C547374616D7020554142311C301A0603550403131342616C547374616D7020515453412054535532A0820A7C308204B73082039FA003020102020A160E4D35000000000387300D06092A864886F70D0101050500307F310B3009060355040613024C54312B3029060355040A1322536B6169746D656E696E696F20736572746966696B6176696D6F2063656E747261733120301E060355040B131743657274696669636174696F6E20417574686F726974793121301F06035504031318535343205175616C696669656420436C6173732033204341301E170D3132303531353131333435345A170D3232303531353131333435345A3055310B3009060355040613024C543110300E0603550407130756696C6E69757331163014060355040A130D42616C547374616D7020554142311C301A0603550403131342616C547374616D702051545341205453553230820122300D06092A864886F70D01010105000382010F003082010A0282010100821C4FA052C55A990B6B62E5D59054B5EB08B7324C6B6C29048070A931DD58C90E33D92FDED48AD39C697C230A854ED7B7D9303F3A835E9220E4F4EE0D62D78D675B8E4A75E2B7EF513C9B47F21F38E7BCCD2428CC88E8116DC42330E2464B20518C68D850881EA2EB46EDE52B3896AF2128397F07EAF1A27B5F1AE9551557EF10AA6F2C56E5C265A4B443A470388D75BD9827EB4F6214AB522D015954F3F4325BAAFDCB0F7F39407A57AC1F0C2D46C4CBA568ED1A5B997B590D064CBE24FD6C55C1DB6D8B874E49425C61A7DA30996F183F4D8F2F0279D2B8875FF2E7F1E47B4E49DCD6DDC886AA7DCCCF04D480674D6520ED7190E879E1B64A046C559DAA0D0203010001A382015D30820159301D0603551D0E0416041451F4B16D4E550EDF93975C83236513707DF6AF3F301F0603551D2304183016801408C941FFE79B5633DAF0D7B361B4485C15A31B5A30370603551D1F0430302E302CA02AA0288626687474703A2F2F6E63726C2E7373632E6C742F636C617373336E71632F636163726C2E63726C306C06082B060105050701010460305E303606082B06010505073002862A687474703A2F2F7777772E7373632E6C742F6361636572742F7373635F636C617373336E71632E637274302406082B060105050730018618687474703A2F2F6F6373702D336E71632E7373632E6C742F30090603551D1304023000300E0603551D0F0101FF04040302064030160603551D250101FF040C300A06082B06010505070308303D0603551D20043630343032060B2B0601040181AF650102003023302106082B060105050702011615687474703A2F2F7777772E7373632E6C742F637073300D06092A864886F70D010105050003820101003ABB17DBAAED138816BD95DEAF9EA9555D0F6A93678DFBC092B389A621A34E7D87556A83908CA18E838AEE89B28B04918A08B15DFD2DA1FE3D4FDA9EFCAC3220F4B5A562591FA9E4ED594D45E3CA4EC28F5EAD80B7971A8B109491107B14B4588C8C4C2E05FFD66FD14F791F000B9DAAC92E1D8ABD6B0645C0D7B0798ADC15726ECF3BFC202056E375D1DE74C4271216D74586A7BDA7266C6AA6679CD29773D791B9FF10AE92464C8DFC525740FAFDA4E40D2D067AC93855EFBADC4615D495FB95A87C660659FEC75185C9EF599BAC277BB9D3AF5922D46B8980C84949FD8A04B377D953FD3478176E509C8BC012C003BA00D11F27E20755DC9CA7AE18211BDA308205BD308203A5A00302010202105891669CC008CA254070B327FF9C069E300D06092A864886F70D01010505003074310B3009060355040613024C54312B3029060355040A1322536B6169746D656E696E696F20736572746966696B6176696D6F2063656E747261733120301E060355040B131743657274696669636174696F6E20417574686F72697479311630140603550403130D53534320526F6F742043412041301E170D3132303330333131303031375A170D3236313032353132303530305A307F310B3009060355040613024C54312B3029060355040A1322536B6169746D656E696E696F20736572746966696B6176696D6F2063656E747261733120301E060355040B131743657274696669636174696F6E20417574686F726974793121301F06035504031318535343205175616C696669656420436C617373203320434130820122300D06092A864886F70D01010105000382010F003082010A02820101009DF52784E64FA593EDECD8AD94C3DDB503E58A6E709468A6185A54615E3153F487953057DB98B3735EF9E16E6E4E5E63E76005CBCAD78D82B9D184C4C8DB15AA7C8A5FC893C3C5B0B5B90CA2EC7286E520AB80478DAEF5381846FF6699F5D9404C2C514942DDA8C2B1BAA4555DB3765F38929257D8BDA92B2F788F6F062787B34A23878FF1B665F4D402EDFC93FB08947FCC8389BD289630B61CE0FF6A49E20CD6486B6A3865FCFC534E013DE7ECCDDDB656594AD6883CEE2273248CA46445EA61F9933F69792752AFFD72C189CF424D32D6766351E79A1A768CEC893C7B3D86F21DE481156E519C8B2C426D4D9C0C3791F02A93483D3CACC3E611C6B806E7D30203010001A382013E3082013A306406082B0601050507010104583056303306082B060105050730028627687474703A2F2F7777772E7373632E6C742F6361636572742F7373635F726F6F745F612E637274301F06082B060105050730018613687474703A2F2F6F637370322E7373632E6C74301F0603551D23041830168014CCBFDEA79077626A1D78692E0A389B77515303F0300C0603551D13040530030101FF303D0603551D20043630343032060B2B0601040181AF650102003023302106082B060105050702011615687474703A2F2F7777772E7373632E6C742F63707330350603551D1F042E302C302AA028A0268624687474703A2F2F7777772E7373632E6C742F63726C2F7373635F726F6F745F612E63726C300E0603551D0F0101FF040403020186301D0603551D0E0416041408C941FFE79B5633DAF0D7B361B4485C15A31B5A300D06092A864886F70D010105050003820201005C035DE76F88FF65493FE6221771C14922301FFBAD77F09D77C8155BABF3FC26CDEBEA2724D4F7A3A6630DA3903426CC201D23FF328FC40A7A4A7463CC72B2526EE97D4C361826526623680DC3B7940F545AF923C63DBD3194792986AD78527D609C7CDD03A5657DEA1D4F1E96CB5DD021D5C9782E29286AC56B5B10EC419B90EC5C429173264D8CF1433CB500753EDF3AB93668016F759DC2A2A1471F491E96FCC61482A8ADCAFD11AC895101627C9585362E2B98ADE4C1E015203AEA03C3777618CDD569E4A66CC415A489D9CFC4628BB24980C9F0318EB98776CACA9D9C0AE8BF9288B1A04F379DBCA2BE015C71706F16B5E90531CE335165DEF3B5369773727601E409AC35BD20573591C0C4484DFFAE39A28DA836433206511BBD4C35DA54182DAE632E57C47D13EF075AA10937EF3FDC5B4AF81FEB2001ACB344E71DF7C00AFC79322EDFBF08B888A2533CDF0C07E50D3F90187DA3F49F17032B1C552C8056073931D189B1D4904EE6373337734511A6F7E6A16965D208EB7E04BD945D10D4D5C1D8949760CF5911ECECDF7647F809BDE7C31C73607FF386D506B1D6C0A6E8258F4D69AAE37C93810BA095869095D52FDD3E52593E4A37EF067C42A51CAC7E781BA6000FC52570017433CF6B1008E1CB310F3A1EE078D2111107178FA337DC884CD15B90EB558A4FBBF6A68B6D2954C2F3905A380112D755D78AE6E829318202543082025002010130818D307F310B3009060355040613024C54312B3029060355040A1322536B6169746D656E696E696F20736572746966696B6176696D6F2063656E747261733120301E060355040B131743657274696669636174696F6E20417574686F726974793121301F06035504031318535343205175616C696669656420436C6173732033204341020A160E4D35000000000387300D06096086480165030402010500A08198301A06092A864886F70D010903310D060B2A864886F70D0109100104301C06092A864886F70D010905310F170D3134313131323133303034325A302B060B2A864886F70D010910020C311C301A30183016041420A352E2CE2E73070BB3CF9DDE8A4EFEF0F0A35B302F06092A864886F70D010904312204205898C2306F5547BEFD9098224368E435E535E8D79F7EC7E5DF858237742E85B2300D06092A864886F70D0101010500048201006CC546313E0309B6B1B26CE7BB222CAACB05AD8E1323F14442893FB4B716B480031EB7A8E3057C644B0EF465E4E3A6EF4DDF79C46EA3DBC1B5E54D385C753CC24C1333C7A52C3A6E3F38D2F669A4164BD62AF892CE3EB9D7E2DBF37A1AEBC2D09CDDD826303E364A22FD8919A4912EA67DCD75F29E640A907AF81CBA0A62BFF8B87B334B9516344CA8EAAB528393806E5562B0A6FE396A8E12A01219FD52D0F3D1B115046281E662C3457A24BDEEEBC0B656403F8271A698156AEC97306CADD39F819E445774F067DA5774BC82478EC4DF50CDD40095E7660778D8DFA97DDCD35A69B12CF7E37317F036C1C6F37ADCE938FD76BFAE02D80E04F2D3F8AB723F6200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000>
+/ByteRange [0 76328 84522 316068]
+>>
+endobj
+11 0 obj
+<<
+/Contents 12 0 R
+/Parent 6 0 R
+/Resources <<
+/ColorSpace <<
+/CS0 [/ICCBased 13 0 R]
+>>
+/ExtGState <<
+/GS0 14 0 R
+>>
+/Font <<
+/TT0 15 0 R
+>>
+/ProcSet [/PDF /Text]
+/XObject <<
+>>
+>>
+/Type /Page
+/Annots [18 0 R 22 0 R]
+>>
+endobj
+25 0 obj
+<<
+/Subtype /Form
+/BBox [0 0 0 0]
+/Length 30 0 R
+>>
+stream
+
+endstream
+endobj
+26 0 obj
+<<
+/Filter [/FlateDecode]
+/DL 1850683
+/Length 31 0 R
+>>
+stream
+xœŒtUÅÖÇ)!P\z¨ „So¡H @B±¡à³¡(*¢ öBUð¢ÈCTPD, ‚ D¥ØP° Š]±w‘þÍ>³Ïåç?ó¹üÖr½ßºs2eÏÞ{v±¦4í·¦4íÖ¬RÅŠVÍìjn)½eOÍŠ«T©`]lçXÕ²+Ÿš•W©¤Äneµ ÿ¨ž×¨×É-N9nüE\4þŠ‘#Ç]téEW\2òŠK®¼Âniå““×ðh`üÈ‘c®¼bäùv=«.!•órJú÷9þ䲎e%b5m϶mÇŠÛqÏþ§ þS|`×:VëJY–ûR¬¦•ÿ›e%mßN ·jXÕÅï5«ŸU¹zÅ
+ôÏC¿Š°-ÇI
+Lü¼
+e1tÐ
+cåA»Nlâ£TMQ x¤þÍnL-Øw“NC
+eÁ¿u¾b!D‰ïÙ ý¤@x¸öÅrÓ‰%Ny)©ÛŸ¢@x8qðá)Ë·’NÜÅSà¯V <\üµ`2ãb«x¶çã¿£@xžRÿJÈv…Èõ|<\—Ê
+„ÿº¿ò‘‡\ ø¯ëñ¯TºGBbûº~oßûg™@o“é Ñ*þïh©’ÅÐ×
+äChðÅòÚÇS\M¾¡ëÈAÐÞz]ä‘
+Ä…xo½bhG°,¾ø'î¤ðáÜ[ïW‚2so³Ñ¡è±’®oÁyÚÛìZ¨åµ<Žò’NCÿU $„Z_Í[E\AnÒ…Ûwoë›  Â¦<\BL¥ôdòp…í  ÎíƒÉ æÁµà¹ÛÛ¹§áoJ=ÉjHBÇÁÃ¥6)žÌ.r$-® „½]þ4€zËcîˆ HÜ‹x«ôh
+‡Û׿}Z`ø¾sô/e1ä@ÃçÖ”çºpYö _n
+ï–}×N“îæ$Vÿ÷]{·tãká 4À}7¾k
+äBhÁ+¬®‰ Èsüá >T x·ì[’”à {K\dGkö<Ü’>Ð2ys&ÅÁLˆ€r|ß²Ï  gþL;_\2ápÏV5€ÖlM«!Žícé»oÍw
+„¥ïºÐL">¯²}ë¾T ¼UÖÿ S1)±çð¼”e
+1±,¾ à7íoVn
+âM@Ê‚êÿvo+TF´¿þˆâ'Ä=þðö“.ð¢!lº‘ªÂ.“Eg+<ÁŽ‹/Å„Pµ5ÎáÇl
+«µk/Ï„°|°n{6I¼À»†×®n\ðÚ商Ž3ÛñX=˜wŠ ÄÎ<’ˆb™5Ð/PÛÁ|¤vJˆh¼ ÚS ¼ :]+?9¶æ­ì`§©
+„‡ë¼€ØIäÊçî¼Dà-u°ó_|Q»VÊOà;ø UÁ
+1Z`¡<@ùtxïBò©¬B³}|•‘›ÊƒGª¬BóBßTVá´ni!§@)0`
+Ží{qx#èZˆuñÙI'q´Ó“§`À"hðM|Ì)˜ ÇahŠtÝE¬<ÐÃc. Ñ
+„FYÅéÍxY¼@(Â=^qz Âó´ð¾¨!z’ÐnÐÊLÚ-em“|`,Ûš­²è=‚» Rq6/°g ¥úŸTÝ
+„ÿº ¶N¬‹Pà뤀<Bn¥¤ÁåA“ð^@ݯݤëc¡=!ÆÄ>i‚4Eºà(4áh. JSvgBP³/«tkK©øQä¥ÐìñŒßÚÖ
+•óa `Y¥…•3!èŽÐéÉ$o¼9+-¼Hð²¬yŒ§€¶¯ S=®@øÃ7Õã«Ì“†j¨@H/«ôÅ^ ¹-°f¸/ª¼Vj=B
+¡aAõ_@'*²Ë*¯O±è!3ɃŽuW ¸ *o{š
+‰@á†3^yÛÂÝû3YD'i@|Ì+¿»´£o:°ÔõÍ<í @x
+v?{Ò¸'´Vð_÷û\†Èi’ÒLæïw)þëþ!'‹Í‚‡ûcd&„eAå?oDOµ‰5Êbh®t€ÂcìÀ\N9øÝ\@›  Ã§ü)ÊʂʇÇ(”Y2$_æ0T±¢Áá²²+ÄÂÀÒTTyÈb¨ŠTµq°,ra\l#dUmf
+"q CH@(þ¥Þ³{ \ßx2{¯0€J¶²âç´ðpV)Ù®@ðÜU)}œ]p f[hµÔ¿Gè"å_ŠUú÷6€Õa!æÓÂý¬Bõ/ËIkÓ&®ÑØSå¤  3«°Zë’ÓSs‚Ϭ¦@xíÎãx•àÑ8’žÅÃw¯tq?žÏ
+ÛRÙ£7€.Än×69†NT (X³/Ÿ#Å!s ç’hž4î9y•‘§ÃO`]%{Ü ÐUÃD
+熩+²ÿu׎8²é„ª×îÚ *4Ù7¸|¤H´&4{ü†„á]05|Þ¡D
+ü4' ã  [ÒÉgAà0téfßr›á)˜öB: Æó5¦[ö´
+„wÁô/åApŽXì>Ížþ­ãÓS½‰ë៓“ Á< ²ì»³±ìSjvXgß}²ô@ž‚ÀµŸ²¨@xû.á<j›‚85ædö’»  ¥Ÿ‡âÐ&_,Þ*K¿V ¨g?ø*o:r0FBBh«´Bk$Ý P#zV,S ¨Óe¯üÕ;xxÄ[eåÂÛ÷I¹Ÿ„Ò'º«‘Oæ(>RO§‚­bÙ‰@…Äáén™Öz²wý›Þ*BÑÆÆMö®
+‡«új'^'x‡ËRõUÇ
+QÅÕP üKç· ¦€Œ\J‚2³úùwiiúR ò³0T¦@xŒe­Ç¦p«Hà;/ËØ7ÊÌê×9éwÄe›ê×Å© ëCW%=`=³ú„
+„ÿº‰ÒO'ÓDâø¬úÄÞ
+„g|Òñ|8æE"¬y
+&9Ð-•ùÚˆ§ °¯~KU‚FõߧgŠ‚•áp3~΄ŽjahNW©†PŠ€°6Žš§l†NP 8„î• ”ñéëh«ß›0€–Íc÷)=«&5§eÙÝÐÓ\&x"Ðxª?½Û
+V±Ä M8¨€Ú+^à^ç H,Œ§;Á/lU ¼Ç7Ë”›Šz×Bh§ôÆV!T ¿ºUã°áµûþíô[dæbè]‚]ÎÔ¯Cvüä”3õ{‚Ãåü·‹h/pÇBù”óߘááfT•P„ò=£93ª+”*9sÚ°èIR€öEçÌi§@ø—æ=yÄÄu#QY =­@ð¢ÎYp;ÎüÀ‘8gÁ¤Lû¢sJÕ(xÞq49 (<Á9œÂÇ\¬›î!;çÓ  Mð¥( ¯'gÓã
+„xËêôdŠ+;©r¶<«@xÆß‘YÉÀU™Âîøœw0€ÞŸ›6qã¾/ œ÷ïÊ„°¤ËÙQ'=¤jã×îœõŸ»²Ò%¶ eþâ]°ó*èçóyYâb_j ®œŸG)Þ¾¿b9El˜æüZÉ
+¶È‹ZÖ„§yo©Qðº49¬wH']<]cò•
+÷SŸÊCG¬WKÐèçÿÈë5˜NG Öøù ü÷2)¢]r2&ðÍYãïGÿÒž>,0hû¦4˲§Tð.Ø˃rG)Ü·7¦@ð›jVXŸNXGûŸ²Ú @ðpÖÌûŒ'Ó¥ Œoóšy_)Ü*5< …˜#ö’.˜¬fƒ¥
+„©™¼¨SŽG©‘8t f³µP‹V¡SÞùp¬QÍ
+móšÎþ?dÛÁs
+Î9l
+„ï–Ëô£ äYó×]>Íú‹ž”PŒpá*Í7€®}–g®8RšG¾š×®3€®ŒU#7xSÃÛ÷ú'Ž 嶯›v-9ѸèŠ)œ§Ün»øJRá^ìúÎíö¥A5$·ûTŽ
+/ht•Üî·(þ¦Ö²ˆN‘K{!sOxQà~Êí['“x,XsûVQ (¢sûfLJG!V±úŸÛ·šÔïG6$h#å¦BèW‚ò)·ÿ9¼}i2]¬±æö?_ð7 x†?œ‚]#·T­5€†ÈêÅäc¦Œü× ¹É
+½ ¤´æ¾Ë=³Y¤¹ïrÏä
+kŠ|Ê=ó6‚o@¹#ñA™°Kð²ŒXb
+„×nüÈpƒÚlø˜e
+½X;îFÜx¸[ÞR üMÓ¹„C`àƱï0wz}è»lKcçþï'›nÞe¼À º~°I’;ï
+ÂkwW®4Lƒ]lºåÞUWðdÞÕ?=œç{:h i¾‰+à
+)d4,ó& ¿+‹î
+jÉ =‹îU h·ä>ði,t}‹#ªÙ¾|©@ø˜/–*¤m õØw5‚uñhÕ©R`8d§`-®@ø—Vw’NUʽ$VFsW[
+„§à™baXš0J4ªÑ3½  Mý¥è$ƒÄ,7 Ì„°§=wKèi§dF[såo™o
+„g|«¬H2®.%wë»
+y­‚¡é#åº5„†+\»Z“÷„J–mEsÝBh¿áá¦Ôfc9ˆ4Â×F­)õÿu³i“DˆU,kÍêb
+±ZwÜÊ[%)´‡HÃîŽ9ÐœëÂe×nd$ 
+7]­{ö.ê¤âáî9d
+”mŒU!×
+U_u{|®@p?Õz85Œì‚ºBà<Õ–¾ÊÈQ…ﻺÃNÈ„4>Œ²m)¤$öaÔ=Kº¾SÁÛ†ƒ£àêžu¾4ª8€’”%ãkRëêŽ*U xZê^þs¨E/xPªÔ½ü7‚‚µî¸¶¡ÿI¬^
+gÊÔ×^ðŒOpÓw°ïGjzòpâ
+„7ݤ°¥$µêÕ”&¨;iŸ4U*íÉ ÆN¤¶`m1€¦Mû})gïñéWš@CY äxÄR ¡WŸ–;¿Ê˜LMDlÝ;¿S (XëÎÝŸÖ0RѬ<ÜÜÃ
+„·ÊÂìñ#¿Jßuï« @ðn©ûÜ•|›{õ̺Ï]sl(ï†{Ù_
+Þàpy7Üo
+åSÞÓ2ð=¨”fᦰš¨@x<íËêò¨û¥gú)þ¥çÎ7vÂr<ï¹sL 7…³æòž{Xð‘zi#o_ŠZÒø3ó^Úb
+ä¼×GÈkƒâ-ÜéS@@o}˜Öì-·ÕÐ'Ð34ÖöEç}ðªá¿î3Ùˉ<ÔOoºÏžÎ„p`iÞW²ž½7TÐs
+„wæ÷·†GŠ*æa;8ïû™
+„·ïO‡3¦ b,óüœ¥@x2½4ì,D?ÍmþëX“ùû/iï¼À¿ÿ¡@ð®Wk¾TC¬ ^)¾€êÕZh
+/Ë„ð›býÊòU–¤ª(8¶¶~å‡nºú5‚¾nAð¿kiª^Ö¯±5Âr¼~­wb¡gÔ‹fÓópµ>0€êüÊNírâø*«_çO¿TWöç Lª ?¼în‚R¥~Þïòp:^Ч::êçýe
+Ÿçe :?ã×Éú…ë^Ôõ­„Üt¤ÙºšÚ‚õ­î
+T}›ûÛ2rOý³á=îŒL×ZŠ;Ö¢ë;—(>RÎ*y)RmA;‰ øúÎÓ
+„)~^hNRŒ¶ÊêÇ/0€’ËÒF çkLÜúÉåPj“üp7ÈÇÅÏõS¯)Ô0êw™šnÉL,ĺLQ (ìë—Èp«x,èàÌ«ú%_(þëJdú¨#kkvfßJ
+„©Ÿ”O¯B ŒOp¿o¯]é#l&‘ŠQÿCh¥4H–¡ r¸»*ë«@xƇwá+Ÿâu"½Uy¸á=Nfƒ–çò»²B(®AË‘
+­ü]ì`
+¨j¸¯«!Ô ‹o
+„iêÁôd&­H!4†n®¤@xY^Á==jêg6Xxµ´HN§èqßÁý^´Ú
+2-q;bcÓOU <Ü­­YD»Tz¦±[ ŠÃØ\îÏIùwn ŒØÜ_  «ÒQº®¥ÑÇc žQ <O Ïb÷DPN
+„?ü©ê,)<(Rg”‡{*×
+Ô¥US!öçÏÐ>)Åö¥ [@±}ÃÎõBW,L$u…?üpÝcC ·ÜÎ[ŧ:Yøni¸e®Á]ÐðÕóÙXNUáÎløêE
+wfÃ7¸µ]£faAÃ7@ÛF³!A™Æš¾$ ·5€>|ŠUmÏv¢ <™>g
+uºFMdh“„ÜiJ6jržáojšîvä…öá7½G fߨÙÛ±0À-áEÚÎópÍÞU ¼ Z¦”'ÀF­z@m*†Æ …KâµFmª@mßaU›œÌš¬¹Fmß7€ÚÍJ›¸bãál‹FíîP , ŠÚ¥M·À!
+gãÆ\½Ø ªŒb ¨qã©
+EOã&'KõŸªUúaŸÅÐP‚wKãæ{ŽN[–Ö¸ù~¿ÔI–ÃódÓuìÆiÜ©o&„w¾R^e¶O*$¾w¾Và²4ö9°”ªïY÷Dc…AYиû«¡o%ýH÷vž‚îo@Å'ñ»A%<\ñ©
+oÎÆåÛba@’ïkº6.Wð< ^ÀÇÜ·R~¤=øàE
+eAãS®‡“2ùt]¡ŸrµtæFp£NN.öÏ|Uð/õ‹±yýHµYþð³¾Q (}Ÿ#¥oJáF"by¸sæ@ç¾–Vÿ='RÓ“‡;÷M‚zfãó*È­âoõq^–á]0ZV:0Yš$˜Æ£4€ÆÉb5¾K h5u!»W jÔøÚ]¡I♂]º¯ýÒ
+Op“Ùaøž'Ž”&P¹ÉìÐ}ÅÃižz›Ü×Oào²ú¾6è„ÆñmÞdõg
+·J“ç_gÁJ}¸Rø¢nòüVhG™%í5º›lðOÁ{òI<H4v4™š¼w‡ô·L‹5Ñ5P“¿_W (¢›®²ƒê øzmºâi‚óÔtÕ]¼,T~$R¿ C÷(Ô›®ý+övСCÿ@/Ü—vw  ¿å7}á‚êZÓ—Âb”k1ÝBè!hãÂðHQ¬ ~¦oºñhS)ĨNVôzå)Ø”¯@P4Ý&CâAz–…; 5Ýv½´ýÂXøà/Ôc¬þ7Ý~‰ô~5žø×÷~®ô_AÝMѦuR <OßÊvê *aEžœB¨š ôqxåÓ‡cÝôÛ]
+ï–¦ßßÄê?GG`h²A!ÖôׂXø”Büá¿vÈ„°/ºé3ðY¡Öjzƒ5ýc¶áoúók)0(Æ×TpkúçnÂÃí©-—…º¹šL™¦{ê)þ¥½²ÚGP Û·píø¦{W 8™Í²¸Œ’ìHBͲÆ@U¦ÈÉ”7¾f¸*ÓL ]G /ÒS&„¾T 8OÍjNaÇÅ´hºm7«9Màd6«yoZ I8‘
+„É›È
+ô,ÿäݬ@ø—NjQÀ3õ‡Ã¡¼ÍOØo
+ÎukÞï¨TÆŒÆ*V£I"n^:B ôm>ÐeÁJ€‘Ð&n`Rð~:å6LvŠÊæaèyhèyäS+
+äÄÐ(ètnsIîx[ÓjºùéO@Ãz§“ôÄ­=͇•@glæíkË€9 ½®@xgž/ xa¾“ ÃÁ®ÍÏ_¦@x?ú'í|¡¤O¼ FíU ¼ .^Æ“Ó wñ#Ð¥%¡`¥çB¬ø5¿´¿t• ˜¤ Ǥ§‰`l~Õ™
+„Oðõ\ÿ‰ŒeéÖüúû  ‰²ê
+ÿºüóeÞ«OMƒžüó/T Í/ÉÃI—bJ×:*ÿü·ÿÒ8 ™ g ]Fvþ¸!Ðw°ª-6œ1¸Bè
+¥Jþx©þ')<Æ‹4… ¡3  «oc\ÊòÜvXç_}§tÍűô¦ëc!ÿšK  dˆE*H4Ð<É¿aa&¤™ñ©òA ðM³øü©+ÏøÍy¬†ø~‹óoŽ@Ó”plçO[£@øÃg4æ¦.÷šž|ù3ò  Ùãù é`ÇYþì«Ÿ–;ÞcC‚‚]5©¿ùw|¤@xçU`MÁꚈŽüyU  »ùù9(}q*ð¦»{·A]%± ±H©BÇYþâ2è¡@ë Ô,atc“$ÿ¡§  ‡«ÇÂGc×ÖI•‡k@+¸¾oe£é”¿âE§ee Vd <+[gB¸Fþã2iÂñ“¶¦T}þãóÏÓ\‚= ·p\tþ×(ÔŸòŸØÁ
+2éºýôħÐê½i§B\×Å'õAÂ;óiYÓ%M›Ì\8\/„ðd®yQG5툃‡[ó²A!ÿÅ i‡0–ð³jþ‹“  —ª°Ë$”èÃ;ó¥ãïÌ—.gåÁ
+Qj ñ
+¤îi¾)Ü*®QC^Zc
+„/ê¥,¢ãÈǾ³<Òè*ßH9éx²‡ †jQI–•D«®Ÿb‹J7gB¸"`‹Ò°ý<`á_*}Gà‘jÑß—®€ U3²ÀY ¥2 HÈC+ƒä³@9ò…­ •¬+/5€V9Rñ£EûÊÌ«â
+÷S‹gÞÍI;îFZD„Ð{г7IˆÊDÙ¥½Å³“   2Qž®DÇ”ºàÉÜðªA9ÞbÃÖÐ$¡¾“ØIÕbÃvèC†(XESk©Å†Ðk7ÊMçÄ)Í›$-^›¨@ð·xãyV×·¾æÃßXo
+„·ÊÇR5JУ]ºQð/íXÇú›Ç±N×bÇKÐg'±°÷©œ ¾[Z|vª t˜…XÒvu¥ [|^9Âr¼ÅפM7ê愇ûâzÂÃý%íJ8Iú µÔ⯠ ¿óÙI%D=µA„ÃýÝJ°8ü§Qh&Q9aœpÒâŸ|Â[eß»Gœ
+Ô ·ïCèÐ@VÓ<Ê´8tÒ±¡–•ä²¸A©‹H'˜š @𘷬´Ÿ/jr*h²œZV® @ø›*?Â0”½H(o­P <\ÎøôöµýÈÚ…Ð5
+„ÿºZC䲉¨ö®µ¬uªáoª{ Vzþð±زnoè¼´Áe9.ghY÷‚ÖF˺ÿÆÂÇJÞ×@  z=ÒÆ2õç„Ǽe½â ÈÃI-ëOg…F¦Ñn¶!4Ë
+m„–-sx2©xd¤ÙDå*-­Í1~êµH!Å[Åz]ðiñ*ÆBçpÒÕ^héUU ¼,ÈGŠB]u²àï
+„gü_ÙO‘‚5¨LTk[î­xl¨UÖ‡¬®¹Ôù †i•µCà·ªSªÿv0ŸèÃ[Õ¬@𘷪ûC4œæQ¦UÝ¿  ÆÜ<—‚î¢ÕcBès¿ÔDF ‘=
+ÙªÉwPÓ×ø˜'í¤i¡Ì“ÙôM‚{¼Uó8 WM¯ÞVÍ»@ùMùÃÉù¢‰³o•Ÿ¯@PØ·j)snA&MͼV-ç+®m=>æ¥ãççVm@E„"šìiì8kUô á=Þ©+£Ô)]ÐݪSžäý–v-ù¾£™ï/Â3ÞåËPÕ&§<v™´êò­ÔµWú"¿>þð®%&,S8Mta³­º¾ª@x«tO¥‹iùVd2C¨›ás×k*ØAwdlH´ê^¢@øÜu']V±"E¥ÃáÞW xm´ê)…}\–ºÀš}«ž»Þ-­úJ‡PÐÑ×”phÕwˆáýÔ÷ût8Cð0ƒ¡Ÿ¯]é4v¾ÄéQû Z•Î0€Ô䫌Ҫ\T[ðÚ (8"X=!Ñj@¨,;}¤<W£¶*ËQ ,UÊ€I¡>R¹8¬a´x“4$/­Œ¦œÈó7$f
+'³4'8þ9tš gpµV' N{Tð~:óy‘ÁåjJ‚´:ówh?<R‚«)4ÔjÄu
+„é|iQ'©p´Iý`
+„eÁÄ×C…†ÊáᘬVß6€¦4ãÉŒ/3XŸÒRðáœjKM ®øQ«©žtg‚ JGÖtŽmugWèõ×C'UПzÿ[½þÖ±¡Ög5 ;S gìžh}V‚² õUëX]KRÅ<üØúª—ž»ÖWÏÌ„°Ìl}õí
+efëë7°ˆ¦Ô_M‘òÖ׿b
+„§`ÒDV(ìChÓzÒTÂS0ã‚PÉ—¢¦sGë+”*­çr `ÐÎʪQë¹ç@w­•“)'A3w½`
+—¥ÍÖÕépÇ×ô
+&Ðç¡Ù-î1Mƒè6;¿:¹#C»_b%˱¾¦uT›ÝzÚ|/Ë(‘°òá‡È
+„¯6o߉Íÿê@ª²O%Ž#î þð5Ïø°ÐµkÅ]MÉ¢66+®m¾Ìlà‚¸OÛü½P[Y½Øuƒn ø¡mÛ ÞœmwÇîÓ¦Ã{¼íîL _ÓIŸv4õ7îOÂß´¿§Ü¾AkJ?d·ÝßçØPAE®¥KáVVdgf1t«Á.¨ÜNŠÃ <&R„‡«|¼ÁYP«Mú¢¦‡U(é
+j*œÌ‚Z»®‡}=µ~6€êL:b,»U» ÎÍ
+„§ ~ø˜\qWS¸ þ8‚Ò· év¾¤Ä1ˆcC¢ é~‚û© ,_4ë²5%
+Ú|¤@xY:tM»O]_qVÐáÂóÔáð‘v4%D Š²  Žìž 0/Ò96„¦)þ¦Î5báãzÒÖt®¥@ø›ÓCAÍÈpÎMAb–A‹º ÛÑÉ 1þ¥nó  Þ+bác(ùóð_×û Â]ÉVv¾ádØõ]P²Í
+„÷Ó ^òp©¿I¬d *Q üKƒ¹úžXगÀ·yÁà¯3!ͦ²"}8}2(ápCžP <™C¥Á%Œ-j´†Ÿz †þl
+pXš­rÕè¿2á$pwyš¦Õÿœ a“¤`vgi’Ù­K+˜í@s
+Ò|v´âV)>ó¹%ÁXš~Ôó?S 8ã…¥Ÿ3DEì"§%„¾Î„p¨\aùűб/60>-…åcL ca¶ï9xí
+Ë_΄ðÚæ†ãôH@ÿóÂÁÿ(|++<QæâRÑŒ¸£éÞ^xâY& #¢¶ó ÇÅ"ºðÄ-ÐÐê,ÄRA!;ü× ÍU ü× ë&)
+?òÿØ
+ƒ>G ¼v#9IO˜IqGcÀŽüÔ
+Ço4€®^žV^¤X2øÕ)´ ¯íÆÛ—ÚPiÊç^ÛÓ
+¯—ËB àŽ—Âµ¾ ¯ï«@ø˜ß°Ÿ§@ºãñA¸áaYpãèôãþÄÝ—+þënú¯¼€¬À©€õÌ›f@“ÿ Å!µAÁU,
+'ÿc
+„çéž„öŽ|ïÅÒ÷ž.
+„?üÞ¿ÒÛ7åDò[xïÝ«@ø´,›xÚTy».~UðiY*Û\&‚Bך‚–…KhÙíRD“
+éiJ.›k
+„g|Å»òz%³ÛÒt®øÐ
+ß\ÍÛ7%Ô,÷Y.|óYè­®,É[­ #*|«Ç±¡vsO‘“Iÿèäx»¹§@ó¥Ã:AÑÓV¤hÍR xîÚÝ¿–?œÒ¼Ø*kwÿ‹™¶ÊÚ=ü;ÎljN‰…}»‡?U x·[‘ÍuJlgï´[QÍŠ¥‚åhú’´[ÑD ÆÚîñÚi÷DÊÓ¤´¶{¼ž´j+Èü“Ä!ôíVí2€ž’…Ó½àI\SS¡ÝSsÞRížÉccY /RÁ-„bкãÒerÝè&OÁº‚¢§ÝËÜÜÛñéK•v/_g
+„eæG“å­Èð£L».R ¼3wÈr.¤®Qy ,3wdBØ»ÖnÇ%dNO¬Ð´Ûq›á#µël©Ö®oM%©v»FdBøæl÷ 7À ÄÑ´"k÷Í.è7~YL
+½!í‡Û—^U=\6°Ýá
+ŒöU=^îñVi_5a
+„¿iÏn)0(ü'šB?@ž“›ŽìI?RŒ4„ÖêPñVרOOA‡ŠŸ@•ÿ惲’¾­²•÷*Ô;T ;¢úvPÞ C  œkÃ`¥üH*TC7)4n:ä¼ÌPR\6vévÈÙ¤@xÆóÞgíɆÅúXð/Õ«K»ýH
+"x½†PýÉiqHe¡TéPÿ¿Ôð-v3“«2bÀó‡7|Gð.hÄ¢‡#\M‚e‡F]L Ùü-IÙ¶¦¨O‡FK3!ìÕîÐ\V åÝHÒBýj
+úTV ¼À}wH!&Û@b‹ºCßO  þ/³aêõŸðdößd
+„Åaù¢#Á¤òd–?¨@Pê0h1»»Hyд÷è0èAÂ3>äI©†zìj#: yJðpC–[ÅN…†ð_7t…á¿nØ+±0.3<™Ã6+^»ákøpR@’&Õ ÃðuЙòV±©@Ãîpæ%йÿ Õ*í„ÖÎ=×
+„ÿº²‹4
+~+Zq¯aù´2Áæ¤'fTS¤¼heèñ•¡âG X±!Qôø“
+„ií#¡úO­u°»«híã
+„'sí1LF*¤æ‰ hí¯ÐËÜ7)¨ófcÝ·èålÂçnÛÞ* ¡GÞ9y«l{óØPÇù=|¸£éÌØq~‰tÏE,z(xZ“DÜñžK3!ìiï¸è9\ÐlOóÚÝqÑ3!Í/=ø,¦AIiülÑñÁç  ‡Ž“†)õ³4–bLJj@dÄdù‘çše
+?\ŸôÙqýÍÐkǧ'“¾ʧŽ¯ÙÐÛ²Æ>5/ª~¶èøöT‚·TÇ6ð1§‡>MÅÒŽl4€>/Š…Ï; WóÔÛñóN
+oóŽ?žv™PÓj¨<tüé?ÐïÜ96x,Œt¤¡û3!–ÖqO˜i‘s›Ý÷ÌT <‡d³Ó °ÔÒX@•+Þ™‡e³® Qˆ®šcÇÃ+Ž __ÔT’IÓõ÷øú›Îã¿;%&Èâ”âƒã0Žÿîtè×Þé¦Ð5¸,ÇÿÚW TéT± Vz.Ô¸:UÌ7€²džbJW×Y¨S•,¿T5ìî$âôöNU
+·o§Z+x«XúÊj=©@ðzí“Aœ)ê
+K-Ÿ0tÀ
+„÷øþ ÍIñáI¬ wþÏ~è,‡'ÑãFº‰ðpg 2€FÈ`|
+»šrSGÌV , .ìÇÃQ¡U×÷í|a™ $ûR“¦¸—Â!Ï/’ áëµóø±¬´SñHMa˜Îã¯4¸/.E†ûqÍ1¿Ï
+×Dï<çbÂçnÞê´À R²x¸yÏ@óI7x(Ò´³ê<¿©áyZò
+„÷SP‘C,ÄÕOð’sŸà%_ðEMmu4EÖ’¯3!wh-e³› ÏÑlº¥OdBXÏ´¼0ôé;I¬þ[^¢@x¸•ï¹ÍC‘µr‡ás÷¸l,Jå„B£¬×Q Í/
+ JqÇ퇬ÇG@O÷âMG…o4Q&ÖÓ}OæzI¥{SNÄ«Í[eÍdhmØÍš(à¹ö5Â;óù ³ ¡§¶‹ðߟ¯@xYÖÉíK¥ç|GFd­Û­@ø—^x.:ö}í¿ð‚ácþB!ä>yüM/l6€Ö_('“ÊMÙ‘T(žÌõ+žñ 2‘Z{$\Mù2kChcÛ#¢ÇuŽvOðp;@›¹’‰Ca@ÕÈÚ<Kðlê†yC}4ûióß
+„×î-7-0ÈœÀSðVBð¹{§½<œt½Š¥ÁBìN™æúP>¥ÈºÄš3Ö‡w(¾[>š“VÚIB£õÑ<èã7Óî‰%¹Ãá>Þf
+OÔ»ZŸ<k
+„‡ûæ>>$ 5yeÖ7(>Áß~$Õ5;x*Òûo?Q ¼évËÊÓ¹*í¸FWÙ}®áýôÏßá‡S¿L’õÏ^èÐœX躑‡ìºK vh×}ˆ…µ‘Ó<®ÛuW*œ'{k‚]&ÂPŽš“<ÜÖ®
+„¿és®^L⮦«ýùè«Î,0< 4à !×
+qç‹-‡ /8ÕÞ7€j-<råG»‰„Ð&Ð#¬B’6R#6„V@yòRŒ©ušB'ï|‚ÁiVQ¥bõš’jN›P‡|8“ték¶J‡×SçÁ,0‚âÔš=ÞùÈ Âúƒ1—Øzuܳ ï«q›Â°ñ_çW4€º^Ë¢'(áŒd§ë
+„¿©øn^`™$!tŸÔïõ?®[Ôf Î~o@d}_! éÑg8ê(ž‚¡“2gØ*s†NU ¨Ö:§‡ÅmIÞG>…P+èœñ¬ÖÒã•Núžstžt*PP°£sé:çÝk
+IT:…2½ÐVq»o3€†H ±¤)ËÅà l
+w¦÷ü8b¢ªy£öž¿:ÂoÔþÖÝì8£RC;8‹¡Ÿê™þ'ÇB—nà܇Ã}pšÁýäÿ1‘•¬xPÊsÿ©
+§Àßó/pB¨£öþžŸÎxü¸)ÁÈæ¹ #~Ü4(÷V²‚ô,¼Uâ¹ÿË„°vo}/‹K妰g4ÞzŽTÔ6-Ä’^$™‘?¼¨ý±¡D½ïC%+˜xå'êý¢@Pf&:Jç0•uòüH’zÝ
+„?¼_ ¬>• Éò‰~µŠÃÄ`žqŠÁð#Ö<ÜàöÐI2Õ€\•v4R!„rÿu£–„ŽZoò‡Zf
+„ÿºë~qx1™IX5J^÷·tC©Ð8&¥éE¼¡“4Qž;±,Â*ñðAHN¬¥@P>%§ –¥Ûë²é“SN6€n¹‘•Q
+EÑ-ð-“  i ÓF 0•ñ NNkfýÉ›.i‰áðÍ™œ¶Ç
+„÷ø'­ÙÑA 3ãš+ÿ“BèS¹}ý@ˆYظI~:Û
+„'sd˜ÉGq‘Œüá#_4€.žÎ œ bÉØaÝõâ
+„·ÊhYÏ>4Q°qP×Ñ'@7þ“Þ¾qa,k ½
+„ÿº a+ Ÿ*÷âp«®æ(–*·²çR­ˆaÊSpë–cCÝâ°ÁåÈ8N }¬@p?u;ýW)]~¤EÞíô?  ‹öÊ+?H@<ÜE  1Cùڠ綨»®@ø¯»Š;RˆHø)¼3»]5Kð7MRb&5¥Ý&ç™@ÏH狸ʨ ¥z>¾žnSJC#P‘f8!Tn
+OË ]úÇBWe’RÀÑdžÐe Á»¥G›r=^`HÀoêÑf°Áoꑨ–>œI/’QÄÃ%r  ç·H –ã=R2!,Ç{tMÅ8TŽ
+Tã²=ºv7€JÂZKN½…§ äIè<žLJ¯Œ6
+¡S2!Í_7N&RÄÉ=aÇqé¹ã^U ¼ÀãåõJ[¶§==ÆÇþu=OĆD3‡#ózžr’ÁK±ç¢Ì*Ï)œQÔsQ{héŸ|8“Ô$?Ðö\ºÇ
+o©žoË©AÀ$Å*£ƒÐóím
+OK¯;¥C(N‘®¦6s¯;@±mÕþp…^í1€V-b™•&Ͷת¥
+g¯§ï r¡bf¯§—@/~Ì!hU‹µè^/~¢@píz½|ˆ‡Kˆá\lÀ÷z¥’ô¦|ä£0"OdÞëÍ;  íµØ„7áK±×özЮ1áA vêXöÚu…áyÚõ!„¸€RøHõÚõ‰A!Öë³­l,{A6Ôzz}öŽÁû®wiv'e³x¼À½«œ¦@p?õ®VQ^¯$Ÿ£ »<\µ*ÍîÞÕF²°§Çõ8ѽ«2€jŽJ›Ý–®¼bïš—@¹kXi÷„Úça ¨wî
+„ç©öxVC‚`WìÒí]û“YG¾ºÅéUÙ¤´†Ð
+7]ŸòϤÙMO´~$¾ „¾2€††+µÒ„ôÚL ÆÚç4Îᢧ+Ò%‹¡‡  áì‚ &3R‰‡¾Uð7ñ;CT’ÉÆþ‚>gü­@PØ÷9[ú})Ô±4õzúœ=Ä
+«Åõ¡á}nzÑ
+½F”‘ÂIÄ}f]b
+Ö’Åls:¤†$°›¹dñ`hI]©þ‹HàÃ=^²¤¾A[ªdé:VµmJnÇZtÉÒ—  ò¤èâÀO)%Ë**ÞË?± Ž®|͇/ÿÚ
+Bž¡è)yí4‚PÉ;;C§‚¸Ê,œîWòÎgÐg%<Bº‘àŸêo
+2õ­Ü\ ôí›õ /‹¸îíHîdC»  ãZʧâlº,̾ǵ5€ª·es’Ú1h’…úVoo
+„×nCØ– S Ö¾º*T!û~·Ÿ¯2?xÓ@‡  ¿Þâ+?¨à†•‡¾m7€þ™‘¾ãnÄX¡ÙÐÁÓ.“„8æP>õ=øIä`=³ï¡•iGGÒŠò¡'¢ê]šr}­2ù¥gŽýKýªs!4j¡+ Ó¯úï
+§ _ÎN6…¨«¾×/gWÒö1íWG¸ydHD}Ñ!´Oð_×àFbB‰ŒªF!4É
+‡G0:ÅCbW@¿áõM~©‘òKø˜ŸqÎ$9)°!ÑïŒIÐ(ÖUÈ(õl\P ß¨®Ð8–*Ò¥‹À~ã¦@w?Éj-•($0…ÐS
+ÿºÒRYÊУÉô\lN––ÎR ¸éJËd˜c ´Sr3†FgB8“¯´l|hNRæ/Þ¾¥e×(þ¦S7ódR"E¤ZZ½¡@Pª”þGÆ­˜©iÚt¥ÿqnßÒs†ÇÂÇP_\‹ø›Î9[à~*½éFVCRÔÂ_e¥7MR xs–ξŽM\*1ÇžöÒÙ7)T×Jç~Á.!2¼ˆ'‹?|î×ÐÝg†!+!, <ÜÝç*ö¥ >fa/TíhAúD T)]z+ û >’fž–Î2€”
+M"(ÇÑ]¥Ö1€–Kë•Ò‘=/utÔOæò"èñ+ÒÇ<0O1tôD؉ž4õ3KŸøL ^Pú?6©IÍ1ê=Âc‹,*MZ…ãá¶ü~l¨ÿÿ†ŠÕÞî€þó*@,…˜„oaè1è±ÓYÉ¢¤*îÛÿ±3
+Œþ?Ì.„)7ÅÃ=¾Â
+b¤~&·£ƒôC¥#®%²ð0”m
+§`ÀµcyÓ¥¨Í Vk\{•A=`;—;§+ÑÖÜw¶Ï0€>x—…“iJúøà#è›Î|• ÞMaßá€o\èÛwäØ´ƒ]¼U|ûÁ=>`wøš›àµ1`÷
+„—å÷P÷%\¤‚øï]ÿu{No:¡Aâê öþ®@Pª 8$›1§ä„Ÿ-zçØPYÖlHP
+EtY î›äP5>^Vc…Aý©¬æyRy R<ŽÆ-XVó(7,De¼5OÊr_V üáµ
+Y`Ä©pºfžj)ž§Zs"ÚÕ¸LÊjÍ?y÷DYåR ¡àpGöQVçQ¨€5 ngTYÁoP¡,Ý4ö¶8±¬p“áyêp‹CútM’²W)>-EOòdúÂLò°>^VôŒáy²šò$ÈÓ£™+ß
+Ô€{CÊFÿe
+„ø‚ ¡’4à |Á¿4:+}WSR­|ôq
+„×nì VF)uEï[>v¶tźPy®!<Ü/@WVf÷ãÑ$Ç–_™­@xY®<Ys
+¡·"­Cè4ÂÝum¤{‚þõøQ¦üºvÐäòr‚V‰X5*Ÿ<Pð7MæR†ŽPþ­HVÞ¾“eB¸ßkù-yáõ¼ßA#°ü–ÐôÖì2jˆ¯›Ìéí  [¹ƒ
+‡6•ßZ`
+„7Ý«²@ªË?¤þ964pÆ,0œ ì2üð3&)Üg/•5¹ö]º6pöCÐÅ|msÄñpÉìw”@s¶§”çkú˜œó4—ó¨é ø‘ÂZg
+„éÁržLÊ´NâÚQ øF=ðÿ;ó8«ÿÿËV>­JF¥’JQq/×u/Bû&c†fÛ`¬3Ö±Œ}0²…1–FL ¡‘­a쥢J)Ú(Z´©ô)Õ‡ßõ>ç}Ýîó½^ç7çñP=÷u͹Îyoç½,—±Q
+ Ú~ÕN\þ¦´j9¿8=3ˆ;q&®zIðÎ\çg³–ÜwMqlâºA!–¸~Wl«8
+‡×ðÍMâVÙ噂ž4Ê‚Ä­s  ×Np@($rgñ;½ö[<„/hwãÇÙŽƒã©£æÇíáIâΩ,0ãH—“•¸s†ô~bì˜S‚^‚÷“M ®¼>€ƒy‰ï÷P ¼ŸÞϽà,4iŽ‰ï‡p0/ñ£]¬Êh´§¤•_ü£ÝÐʬ€¢Î¦ `ç&ñÀÅЧ±±ŽÖ\¨%~z¿a©rh@§ÊQ—7è94œ)D»g¢'­@X`Y“O¡`g*$Yf
+„?ËÙl×£îÅ8k)ñìPÂã¬ÛÜ–úŒjû‰gÇ*Þÿ uí'çÅ=“ÏøqÿŒP lýó¥´}EŽ¦7Nâ?ß”µ¬$ïi–HÄ»U\è´á_Ú| [$ 4'¸åæK  |D–“;Zîi
+?pË.q}sòËð…ZË.3€>jÊþå«h¼²–=¨@ø¯;¸™ãOâþ;ð-n3€>îÆ/NÙÿšÊ«–÷V (zZÀQ#²ë-ˆmyh°tXÚãTOÑQhB¶<ü¤AÑòËÓ,0D ­mùåŸ
+„wæ÷ÈÈÅÇË
+Ö–ß?l
+„éæ÷ÙŠ¦ƦQÒÍ)ܾI7KpoIÈÃJ1éæ  ºŸòV±œ‡il•¤º_(ÞOu9ÖCÑö &Ö“T÷ÂïtëvE('è‘*ü¸[w@·Õr= Ç„ÔTa&ÝvƒA2©^cþÀaº1År<©^3Âß®¾tIDiÐ3}”W?Ï
+ĵóyñÍrRx®Á{„¤0Ol¦›Û3#Û…6*4’×`µa‹ñÏø×R üN÷r«z*ǶmiOjRAð:=Y–àæ„žLO~Ü“[  Ò¹¡~¬¢ã7†V@­9
+)je<β )þ¥§Ü*ÌÔ¤9&=µPðOoÌnRDtÿ”ÞLð/uÿX4ÔIÊâhHR÷CP/Ñ·Vä*D-MFlR¯zPoD§:Ê]Ã[¥wš”É+îˆ *…*?)s‘A!)û« ê>Ðè»ìo
+û䋳RŒ’üÁ• ÉU ¸NÉ—òøkêeâ­r¡ª
+uKrŽìÜDɬÅ݈’ktQ ( ’È­âl\Š`ã!¹ÁQ¨a›!ŽR j#’Þ`
+¤Ëˆ(^§^óV¡Š¢
+„·ï;¦M;Â|òKðb.Þ&'†…= äů+Þ*ËFðbF)c_cû.m
+„×éùZüé‚@SÏÙêùîñV+[ó¶óX3ÿ®ÕÊ6Ъ2‡”‹®é_ÐjÕfhM¾4ÿ©²ÛÒô2iµf–á_Ú ‹­-Qu£© lµ±¢AµÑj³LŒ(§I´iµùwhg 阊¹¸‡‹·³–Ák‹V;ݾT!ìÇý3[í`
+„×é}nC i)>Í‘zÿè`‡qBb"*Þ¾‹Y­¹½ãC";–CË  #ò>Øò ý£Ù*G†+´0ZÙ+— H”§dÌ…>0€~”S¤E„€Gˆñ‹ÿ8Ø
+5Îrë·G@û—±` ûmÝ„“ÖûWÄCø6©õwò";D‚•ª'14Ç
+ÜËPê$…?ËCó  ‡o‘žÎTУ¨ùÅ®g
+µTJ7ߦy@º$Δ¬t¨¯;½=BõϚܷá_¸Sö öxÊÀí
+í‚”œ'ù E«U¼â9I
+„W|ÄcljS.ºçB¦ŒxÒ
+€…[̤Nm
+„sÿ¿ ±Ð·nŒ\êþóÐÁ«X)hãøSêÁ
+„OË—\ÕËSñþòIÂúî›L÷Å…Âø›~Ð÷<¨–Œ-Í5}ê÷ï)Öæ?Ê–ÙaªÅu¼üâ?ö3Ü–Ù”=áé–æBà  ŸÏ±".°4Bì—Š
+„÷øIùå iMá`êÉZ
+„×ézñ¦6 ¦þQß
+Xk~é÷•Ð_SÜ …¨p'Î6MW øNm+·å€èˆíñ¶•;@Uü ‰
+.œŒß¶Šm
+„ש@&'RÉ‘£4p\¥]ÁЬ:2¨@åȶ§«?nÖ­&P)«ß
+jŠ­ÛÍÚ`
+ 5QÛ=_!Âvf»…WÊáŠÕF»…5L i‰QÏaÇz†_»…ÿ(þÀÅ¢¡0ÿ©©â9
+ÕF»•½ò‰™ë¨TæZöA¿(ð€‹Y– @ÐÔn·Á‹Kqš>£í6¤@Û_Npƒè¾`
+„wæÇðbÒ´HMÉX»?2€Ž¹#l"úÖ,æ±·nßöeËY°R'­(v'Û—½d
+Ç£8ÀØþøL‚Ǽý‰S®KB—´šÇ8£@0jÔþäËÂV£íOnP (ÛŸ– IbÖ\PÓm¶ýéoàßeh‰® vDó¿]ðg9ÓAn:QzÕ¼Ó™.
+„ßé¯Öñ›7jÿWèüÿ¤‘EI`Þ¢ u¨PAà/u¨áwÐÌAO’Te†Æ@õvH’¶¥É…ìPï-¨Ù6×ì€VDwhöA›®C÷å¦sbЯ)"îÐ}eùPÇËÜ Ô°ÆcBºPè¦gä‘¢vS~ÍhàŽ7å+üÀ·æ@GTP#tlœª@pÅ;Þ{';\¨ÁEzï½Ç
+„ßij «WŠ/y*e*3´Ò
+Ï]§¼‹øpF(m k©NyUJºNSñA ÉÓK×…‚
+„—Ÿ!Mmj~äó\d3TpžµyX?@¬Ó¬Š
+F§9iÒbuì‚€7Ç¿ÝœNP!§òR¸73Wx“ Äwùd©èº6u*LŽ‡p¶`§ç¾bL~°¦†«ÓsÇŠžNó'¹Ò—¬CÍŠÏŸj
+ ¿N¯ÊÊPªm ¦žø¿zÊ
+PúÎkÙ™ÚXQ§ï¼Î
+HÓS¡sƒ×  /dË> r 8ìüÅ£ÐYŸÜtÔ™ÁÖÜmt>T ¨ïºTüR.NKWéRñk¨
+{Ôt¯‹Ùw©2[à‹w¹JZö”“åÓÝNv©^I æìR£§<4¾†z$¡­Ò¥F–TGnß°¼çÄ!¸.uî6€î”³Uu(®” 8ìr§Ï
+„שÃ˱cNí¢ñáìPf
+ª+þ¥eòæÆ1ü·Ä-Œ.Ë:ÄCØÂèòMO6ÉMÒŒ³êòMŸxkó®aY¡&º†û5í_»†6€î} æÀ“º†aœ®÷>a
+„×)½:/¦ã.;.<þ¥ôšPÆÅ n€Ñ±èð¥L׌K  nC8‡†&zá&Q]» W ¼3»ÿÅ"šz*hæpuíþ¯Ô£«k†ˆ>;x zt7€x8€¸u j&RtÍ\¨@ÐÂèšu+È4ä]SÙ5«žá_p‚7M ÿ¯#ÁŸeÀé8ÈÓ“Š¡rˆ§¬š a £ëÀÆ
+„×iˆ´Ä¨ 7ªÌÞuÈ‚Zªë0Î|]T=ÙüâÃ@¹²]
+¡ôíšûH<„åx×±²¢ˆÜq_76Ýs–©sµòÖ,ÁØh|€µêÊl»Ž·–I“¥ñ}¬±‘ÕuÒ3дKc†_ÀòôŽç%˜v¥”ŸÅaR®¶Fªä÷7€måðDÐqqý8Ͼë¢í
+„åøÒ T úÂŽ®u]ºYð·[%'ìúE×Ë æÛ­²?nã&W`@Ô¨Û»­<Ň"F~Ï ^‚­7(Öœo<çnˆ"éðqo@;ܾ!4JSÒuÇPhW ×M¢£ ÑÁ»’/æ;ýÙYQžJéúN¶aÁº÷b6ÚcÔÒ¸n]÷^j
+„_ü‰lЈ,Í‘zgª´ç~qÙ˜oß=‡ʧŒ}eüEV%62ömR üKÊÑÀ!¿X|—ñáHÂëtð‘˜ëFƒcñ;|Â
+¿¦(ô62N|Çaч‡ã3Nü¨@ø¯;³–U¾E=/5Û÷̺ò¡nU¤Ì¤úRª(‚ëV¥–á_ºž¯Ÿiþƒ­ÉWévý&‚Öa··Ä‰hMöi·_1€‚2!I\Êø4M캟Š‡°ÕÓ­ñ[l G¨Ú\³w+ܾÝ~“áS›B>O_ü·>ñΤêö÷hvIüb^Ì¿Ç•u¿ˆ[ôù#¢3¤`
+B÷
+>Ñ"Ë C(Œ<tt“ÆC€æÀkú´wôR (0ºGG°À¢ ».4Fð.xà}ÑÔñÝ‹…º?ð‘ôH}i†Ï;¢Ù¾Üc
+#¡™
+„wÁé‹Ü '…öñÎ<}™ô»lO DEG@|¤~ol
+OK¯ãÒM¢À¾c¸c·»×ñ…
+]·^gú±8ŒPê4‡½Î *ê]©;ê ˆSvzWd
+÷xï{g±Àᇳ'zßûl<„cö½›È^p‚ ÃØáêÝ$ß
+t¸z7Ýd
+½Ð
+mºÞ½@Yì&"Ôï»n½³Z)bý¦±‘åˆ ÝÄÞýf@Ã䀞ÍX¶‚øF¢÷°
+ufÃ[䦓|ø®,³áí
+5B¦ÿl‚îrÜ$ÜL+Óÿ?‚]fãÿðP™­g"ª ]®@pgf6{†ö(íZÊl6C |Ê| ‡E4ÍáÒ\ƒe>0Ò
+pÌË£¥\è~‚Š:3mžkÖ’øÁÖafÚÂ]{Ù÷?D†vPÓ !³}¿ԡnlûჩC=¿Ô/à†Lõê™ôÉKÐ/¤@PßeàNæTkEq=s@Ô
+ˆBbü×|¨@øÅç½ÊŠš
+4c¿²æ½¡@ø—溃Ü-\³œ5¾TäF!)§)Í*ÊP ¼Åò˜©ÙQ-ÐxÈ*Þ¯@ÐÈÊZÊ­Vƒ4ØZÓ†2ki²T’'? %LZ~…Ì*™¨@xÅW½ÀF{Ô †°1šµêE‹¹j-`êdîÇŠ:kÕF‹Y6ƒ/!jqŒBYe
+„W6/føÑD Í㊠ 2 ›fòù½ó[\h‡á]ðUÞ¾°è“?ðWYбѶs‚¸ótÖ±vÐnÇñGpÏᬞR ¨ƒ³~Ífw’ú‰yªŸ]h¨á_:ÕF
+1Ç\ =Yß¼˜§Ú@§]ÓÈ1þa·ÊéA
+„?ðÿÜ aj‚5gÖÿv@çÞu'™Zšw:·_à;õ©(;'ZÒXÃŽ>Ï*\§>Uêó1§bk'–ö©rTõ=Þ¾õ;ÄúTýÐ
+mº>ŸÿÏUeòJ ¾ø¡
+ñvàûy‰Gø˜÷9²Ú
+.h+3´Ú
+—à©ÞP×ñ,zhfƒ¦`·oקˇú…Ú²KB­E4r¼_¨c<„åx¿Ç«°B×…6–ý¯¦@øqÍïLpŒoxe†îR hj÷k%ûdÑtË[âãB7@™²7‡I5âÇež6€ú.dõjÓõ*ôë»Ø
+ˆx…ðã†Ü¨@ø¯£iþ]ÀAv÷ž4J¸n27 Iví7ªŸôtxµ}Î~Oßj
+@hÙ_¢’Vr»à‘ê¿ì‚+Þ¿¤¹xñˆ?JÓDp¼ I¢á_Úx9Ÿx4üúo¬n
+w怣î-¥™kJ|f
+·Ê€³·°£d MB÷€³·ÇCø†k`Å ¬ò)‰SSv4°â¨êŠ„¸+'|—?°êj‚›n`Õsl<P2¨ç„¡‹/R ¨9^ö-úÀšDå—ýh
+M¨2;}S<„Óˆ²»?'ƒ
+~º×ôŽÏî^¤@P#d÷”£Èlú0–§XÈ…
+ÿuƒeì’5Èá‹9xµ4œ{œ9gÜa8j”=<aÓ({Òê˜Ûm;_ª²ìI¥ÐäÛYRö€§)¢ Õ7€ò¿æ%еªæçS ¼NsçsxBvWÇBlîóÐùíD³zK
+È^°Ê
+â~=ƒ²îS ø× ê_? yïžÙô.tE<„Æ As.˜ÿÞÁX•*4€r×°s ?Ç@Æ/ž»Î
+„Oð^i ;2NÌG†ŠzÐÞè#®%qÄ…/¨û5è£&Ð&WØSÍ‘úh«A0èÀk ……`Å;°Ã
+ðáÜÁ—@Ûþæ#%*qqÆþàmç®ÓàWÖñã"T0„S迲Ñ:ˇÓáoüN¯ük
+ûÁ'>”Wžëg:h
+>“®5HÕµÃË)øR Ë™õ²ÜtŽ³lÛšÔ¦œYë  Õ2C(HM—}š)c9«ÿQ ¼eÇå³Ðx¯9e'¯Ó†ž®AC. 6Ús6d™@%lø‰áÞ8Ñ&gÃ*‚Ç<gS ÷HDW&¸U6%)>‡®Oˆ]øû=Ågü¸C7ÅCX#ä|³•·¯5
+È9±Ñ
+¥ïˆ'd{ ¿Ÿ®Ä5å#ž˜m
+ðÎáâÅL©g
+½ ]n
+{~\Ï"Âï4䫘H!Fü¸!ß@CÏ%¸×ªÑ`§9ŽÌ©¨@PŸ&> ý²,Í°Ó‘ã;)^‚ RßEÅpJMÑÈ —@Ó>æŤ¢Ù6rÚ!›®TÖ·Pj“#.4ß®ô]hý nòßòXö.t@ði)+aã!* dhÐŒ,[i
+±‘ïð?ÝÛX°Ž|ç9‚q•‘{þÃ!D}Óq väž+Út#?®ÄWÄ1YðqUÂûÆíÿX5P¸|hÔܽ1ó?jk’FÍý@à¦UT'fÖ:N7NºUt›Á%µ°ÄuEë@¨6F-\m
+Åᨠ3Øðó‰öŠðpŽÚ0K èµ9vKB†‘æ³l>i
+~k;Œz#Sð:íö1Dî&f?j·e
+„_ü‚{­JÎ^Ìl‚:xÔ2
+I›.jiú´úá„áÇø•MÈ°ß
+Dpùè§  S¯ºF»£<=öy NíP ¼Ngnf3„ÚjúÐŒ:s›áýôO*/#}šñ£þi§@øqÿ»Š•bFJâÌáQÿ»VðüosLå‡-Í¥ñ¨ÿmS ü¸s'cãÞh„ý¹ÓåC£+¶äϤÙv8ùgtÅÖ
+ÿºÑ—væ#Ea¢xûŽ¾´›t—Í. t‡LFß5€O&¸W”²?ðè@’á_
+çIUF©AOâ– MT ü×Ee –® ƒAÍD¯ÑÑKâ!ìßn2DN
+xÙ!œ¬1ºÉ0èa? 1Ÿ?Jð?l+Þ*_IcÔõÔ¬'ÚŒþªÈ
+¥ï9-.d+~§‡[IÑCÇ*¨¹êópªáÇ5gÓH”ÜkL£1ÍÇ@-d •Ù†l€1¦EU(Q¦†ÓŸï‘šÅL¥@x?¥¤³ÛMÂG“’¡@xÅÛ>ÉŸ…
+îm¡Ó6Yðgi+¥
+ïÓ¤p¼˜m(ô^Çt¼–k€Bèøš~LÇëJß1ë°°ùVHsî:Þj
+„igˆÓö[º&vcwF»d“rE渓Øê»ëMèÀæ˜z¥†qPfŽ=ðŠt“]eÙ6–¾cv1€¾¼™·/]ïx¢ÿüâ_Ö5€~¸Q~`QT¥‰ÙýሻaÓ 2Gá‹ÿi
+Op^¤O‚›ÎvŽ'þ¥È
+V2k°W–÷Ðn(™- ?¹7š¨v^r¢”~± OœƒîÆìB—*ÔRy]d;ÑNØÒôÌëÒ@ TÉ빋?‹£^-Íø¼ž»àÌ Y•Ô2¿xæ‡
+= ¼Søq>G‡­ž¼ÓZ=y£‹Ý­BA8ͽÔ
+N|X•åÍ]b
+„÷ÓÑ\D _¥h´Ÿòö<«@p?M>, ?j÷Ð4^˜|B À˜0GÉ‹Rø4¨)Ì™0çzè+j*”×ܽN˜ó‡4ÿ‘7eǧké?aþЋc!á˜`èRhÍ4WØS ÎÏœ°f†áuzµ7/¦c"ÛQ
+˜ðj_è,†È)ñcÇtÂý  }³ÊŠ#pgNØwÎ
+Nø<Ýú]¨±Ô;(ÍÑjÕ áï6€† £Ž«YÌ!ÃjÎI#F²Ú vI7iÄXÂûi”¥!Æe:›ï‚Q  1ãÜP¥ß;€•sÌÓ
+ãO“òÜ; ›RQ°?)o¢47Ï ¾øƒº"âIs'+^§¹³Y°Ò¥±gü5¿øÜgú-“ʉ¹ItO„©¬¹á_ÚÊs'…‹«¹J™´u½Áo7¹^™T@”Ddyœ›Ê m6€²e9² cÀùO“³·(”ã“Ç cžô½¦vrò¸QÐÄ%Ò\“åB8ò0yâ2h’¼Å¥A]ŽäÁ[eò¤°Tpš·
+][xºòbüi
+5½×¿øö
+åøä7ÆŽ©ùÀ;ë@oË * ŽXa¬[&”i”HEu¯x1W ¼˜ûØö¥>íž.Ï.d+Þ*GŽò ¦ˆ½æNqò‘o ±oϳn¡è¡çî•×éX%èD}ÖæT·¡ñÍ'Ÿ¸Ç
+o$¦V©ÁúŽ¦·kzRM­rÁŸzIWŽÐP/GÏ¢ õ0Þy¯þ@§ÇL½ä}‚K0µúÍ®§HBØŸZ½®Áý45!Ÿý–0M‹Ä~ËÔ„ÙPí½¼é¨ÛlD³˜µ?P ¼N·ºŒ$|<³Ÿy níc
+„ÿºÙóÅbÒ ¨®üaÚì…&¡¤nŽM®ö´ÙË  …‘˜‘E‡Šèi ›(<œÓŠe@È/f€Dp‚Û´â·  eûùH mßiË(^ñÕò>8"ü„0¾Ÿ¶úKÂ+¾VÞp…}"ÕÇ0¦­ma
+4×`ÓvÞb
+qxbÚ/—™@©|Zèº0ˆ›ŽMû¥}ùÐô
+OH;ÓÑ>;Œ]·é  J­ø³DE*´¢§WJU (}§_ÙGÚO$}½}\h ”uW‚ 扄$œ@2=Ëg
+„·ïé¡ îå•ó;8£cúé
+„·ÊÙ( jàÃIRÓÏ65Z»‘1檲égSM 7YƒŠ4©áÓÏÎ/šq;þšRÓ<Pe†þ0€xP--§Á½*g$Ì4€ê¸·¸ÔRMsK2£Îe
+uËŒ[ºÅ¢!tI
+„ßéNyÌ£ô>:3dÆ+þ¥²eX:÷$3|b
+ÈïwÎ
+ΛÑpœAõ:Ãïvþ¡¦ˆž¡.t…áÇÙr@H‡¬®4žaO0€B±¶74(O"žz9Âue3mäBþpÐ3\É…Ð2UÌ6וÙÎx"Ñ
+„W|Ö% ±Ø¡O3ì4Ö¥
+„Oð9k.$†—5Ç|Á
+„åøÚñ ‘™¥ñÊò×>m
+„©óù8‘¬,:³ó×PŽluá˜}ÂЂßnfN=(Õݾ”ªŒÍÚ™9i&ÐY6²,™Š€¡ÿ@¹GجuPPÓ®sfî×
+-Œ™c¯g³–Zy†—ðãÆÞd
+ÿºY×?[LËù,PŽÏº~±ÁÏ2ë†ß¢¶Ëš†³nøCà·›U·#« ÑW‹èYu»(~ñ†îTr…¢)ŽÕp§á ”à^€P).þÀÜ«@ÐSœõˆ¨NI4¨i 3ë‘jP"·˜ Ò^+êY‰M  ŽßñP«UMÑ笎ǡf_ó5o:*©i»<ûšc
+wæìz­Yå;VÀc´»P[¨Qv»i.®g$· õ‡p>Ýlÿ}ÒÔˆÃXDÏö?h½“à&kÐÍ^Lÿ»-ÇêPä;¤±5ÛN2€BÙr«(¸¤ Î 1€{+Á½¶ 0Ôæ³Û­@P›ÏnÙ€³ ¶ ÖÙ-ïQ xîf'q¥1A q¶àì¤>P[i«DØdߥme¨ý ¬/cÛ¸XhvûåДþÒ4r4b8Á×`³§d+^ñéò–$#£Ý…Ò~–9½ž»ðYžÇ.´Ð
+„¿ÝAÑa’ÃþùÞjl
+<{í«P­‰ D'¡ ˜ž­5Å
+„ßé–b":bk2ó
+o9g
+ø4-Õ
+¿ª@ðÞÏEéAràm\mQxÿ=P+·Ì–šñDñá,lõ¾AÍYø'Ý‘3ôDCøqOUV ¼ RîcÁJ *B8¨0åaÂ/ž"º¶ THÍã>T |¤ÚoàÏ"Zb]Ø~³á%h¿÷Âbú4} Û¿¯@øÜuÅ®Ec5¥+…sã!Ígé'=E D©€ØÈ*ìwŸ4àêØ‹‹~çðÅ\«@øÜåTA9\I#Xs*›@IÒ4ò‰V«¸ì¨0§µ4ú5VŠ4hNãHŽ~Ó
+'_«@x1ôf‡ËçM‡–
+ô1€6.aG‚Ši4Å…—•Íkžå.¹ÝøBm^óþPR†èðÙÞâýÊ õ0€rm~ Ö0>Áór#PžLë§r;¨Z=/o½4å#Þt4ÔL“k4oʧP‘´3C”0iÛø2t^QÕx_æ=ÿzìpüš¨ö¼çw*Ñóíe>JƒE±ˆž·è}h™báJøpàlÞ²<ˆ÷¸hOm{æóã6.W xîæmšÀ™4Ù…&+^§Wþ•Û7HŽ`~ó^9¯@øq;Ç\$LjºÊÍÛñˆ´k VJW÷4jt¡qÐvqÉh÷á¿yæ(Þ¾Ÿòüjöa…þoÚ‡ Ýi
+uËsÿJ¯,Dnw@3Vç¹OÆA¼3çW{‚¡ÿOCËùÕZ@7¤°¥«^œ$5ÿ†4‚šùw.¿àvSû ­4€fŸà&!P¡<\Ìù³+üÀóÿ•ƒgDvu@£¨çÿÛ_àgYPç¿1ç†Ú­Â ÚuÎ*Ü* ê­`צÒ|ß² Þ*‚;sAýß\U&ÚMA½ þj© Ûñ‘’åÈPô,hØÉ
+Låƒ@×;š ÆéÐјá±£8,¸àá&
+¤ù¥&ÐÛPÏ_]õ*ºAhAÏSИ9üY,jÓˆ âŒ)T (éäeƹ$|Õ» ¯¯ÁoWÔ\¶É¥Ëõ(ÅãÑ5Ï0€Z´•Ø9>KÓe§¨E(‰ÛቜftTQrE¨ÛcŸÒv,,X‹Ú\g
+µTÑî±\J$‚Ûw÷èÙRÍqG(ÑFó?)2€¾8ƒlŸ¦AjÑ?–=¿ßèwgc'ðùýo@¿®aG‚zÂ{Òc\h½t~tàÎ1xîò‹Ÿß…±¤[8£*›Fä#y|súO<„÷ø£‰,z(qVS>ºðh²áÇ}&$ÙX‹ž…߆  c}ج%ÁÂæÚÂcýÿu?sÖ·[í©Ë¯ÌÐx÷ZZxú( j ¢™…¹ðô·ÐYwКM»
+„©ó7Œ#–ï‚ÎoÅCš]0à°<RA
+Ãiz™,pÔ
+ש8Ò•7]hzUGz(”OÅÍܱ"•›FÅͦ@ÍÅõ³HKó{‚ 0ܞÄÓ4û+nþ‘A‹µ¸ ûw”†Mcé Ôµ¢Ô]ÎB"aRÓc¿¸{GÂ]V‚+0hˆ¾{-Ϊ­@Pô‘½–(Ìì Dqä¡xH¢ Ô:fЄtmÞŠ‡´Q h†wGiP}‡»Š‡¿¢@Ð.(#û‰YbÀ‡§òŠ7æèé 6Ú#”üƒ¯œŠŸî©@ðR¦xòOTpÐ(ÅâÉ¿@S|ü8jäÔ<nJÐ
+^LºxÕ$F,^qôREv'é¢7ŠCK‹_ª¢@x1×Ê\1ÀÞ{÷êBo@o–ê•Z ;Ÿº¸‹7Þª@ø¯ÛÌ}×âZ‹žÅ›ÿ4€¶îäà Ù–æo}Û
+ìÂ?²P ²øøç¬Êd" ~Üñ#
+_|Ii†Ð ×@ÐS#Q™¡VPS9Â]~;„K—4…±›´äë•lÖR{ß.ùzÁ%XòBE-+ˆÅá’o†+<œKN¹³-¢"ç’SSî§%¿õdçF¶[Õ@YÐ9965Ê ÝøÎ,z¡*_ÓS›!K3è…ª~–.ßÃ
+ÈMÕà‹¿pù{
+·Ê W^ÌF–-¶/4k_¸òRè*9{‡¦øu“Ï^¸j©TÓÕ©‡ß“bÁÐ  úëY•9ƨåI·â%¨¿Ñ
+CWÇCšo×ï¨G‚†Òá%èð–áÙ‘;O;‚5ð\®óã:Î4€:K‹•.e¢AÏ$ÊP h?½Ð³nLåSÈDÕS ¼˜™®¦à‹æ2{@ƒ;». ÈØ‘xap7‚ºeiýçâ·
+¾”YZÿy¨‘œ¦¾¶f~ËÒFuê–¥Ñ ‰„ Üícit¡ôÈ9>RÔîÜã·0ôh%èq9é3"M6D_úøz¨E­„Ø…•RÀÅlqƒáoÃ#ÞilÍUïÒ6Ù
+uËÒô«\•OV26—¦×P xÌ—v¹.ò žq¡  auäA QºBù¥Ãn7€F4K@X)6ˆ?Ë¿áw)ûø9̶<¥u.4Û
+{aŒj¢µKw¯@p?-ëe—$ Ÿ·¬(GÞK‘cJýáÎ\–óV<„Õë²gŸä% )ˆšÇËžm©@P·,[Ù™]Ü0Í2Å¡e+3.æ²ÍMy1©¡&•wÙæû  76³Ú MŸöeol5€vlçŤÁ3a…\¶c‡áϲ_^ƒEhÄ»7u€s©ô{ÅØV¡‚8¼é~¯b
+µTÉÔ7YôP Æ ,™ú¶”Ï–˜ºèþ$¿©áuš9ŽE]Ïi2ÑKfNT ¼3gÕd—D$Ëi–`Öu
+„Ô³2õ2$’É4ñ§’g?1€–|Î ñãðiÉ’/  ’XQ 
+„iËålÖF„!©®2€^‘<¨|ÔGù€p1_­T>´¢k„C”ìÄnÒŠ®M  LY$ʶ}ѳ"ó”AY°"W^aRÐÓ1ÿqrâŠÜ½ТÑüC²IZÌ‹Æ)<R+–s8^t×D²V,¯§@pg®XᎠ¶\!œd¾bÅyhåúØP¶2´UV¬Üd
+äX~Ü&÷¥Š!‚rü¥=c9@·X¾´'Ï
+ U3€jö‰hY
+„ß©I÷7Ñƶ4CV6é­@øqÍK‹ÆŸPK­lvT –Zù° P¡¼ßÛöÆ…@É»\qHÑxœÚ´2y¯Ác¾êú+¥‘åH{›îüѬºþj¨öaþ,aÈð¯ª}Dð/ùßfc”VÀÆ÷-«ü{  
+³_óå%
+„_ü¸¨"ÊL7ŠlÍñw  _dúžH»¤«> -Ž‡pPaÍec=‹~ÀÓ-?ðŸQ A^ówÞ¾«ƒo×üÝ£|hmÕÃ1õêóÞºÐWñÎ÷]{ùä¦#'ÂÒtÜZ{ù•
+›µõÄÜIz'üKõ@MeA%F8æ(¾lXÛ4l
+ÅaiàÒ>±AC­S<÷æ.ô¯4êzi<Pø€&½¸tÔMPn¬ZU´À‚Gª4÷s‚qºÒ©w±Yë¨ê€Få—NmÙÿ÷nƒ¡‚®¢¦Û+¬[J VÅCšušû!¿¸*àøSé܃гýø˜Sa³'©Å…²  ÂC1í÷&»ò‹1€žãÁì”WôジÒù  Åo²1Jø£ø*¥tñnhYNLˆQµ‡¥ËF@[¥Ar>LˆìHø¸­—)^§Ãr² {ÇÀÙ]¥‡ß6€¾¿Âý,Îã¢Ø*ýþêò¡uöIãÁYN[×hÝ„¾Óºâó|ÌCb@4†W4x*¹ùäiæîB«ÿu/É>~¶Xà]™¡»  |%NíÃÛx´Yôž~RÄ;µÎ…:@>eóßvÎzóÖ8¤@x1?uÅ¡Mi¸•áºOƒÐ!yÕ5'šhíºCÛ  #1aOA(×yÖ
+-±õçäM ãqSx_¯?—§@ðÛ•Uq' 9Ïói>•UùWà‹—±ÃEù’”T_¼¬ê·
+mº²jr¦-FkZ–UûQ æ,»¦q,<AI¡ø¯»æ>¨;+E›ŒQè(»¦·t§[GêÕsÌ/~ç­
+„—àîÚ œ$å9Æ(þ¥»ë˜@ñ‹SG³éÊî~Ì
+÷¢‡.S¨±†zÇCÿ·Z•¡fÜÏâ4Ã)Ëš  ÇäUJ( FúâLϲÇn2€Ú´æcîíAO
+½ ¥@íXŽû#¥Â™TeíV@¬Ø¦ XžH» E  ôkc®[ÔÛ Ž_<ý:Âû©Ç'±MñféºÐ!¨÷å nâVЧi$[Ö»º4HÉ#_2`yj$øqƒT üí†ÄÆ7:1¬‡Cš*^§a¤©í—Í#ñAÖE –*.#Y–ó¼¥é_6¼‘á]0\Þ,Ó`Ѩc<`q8<a·lxSdøÙšÏ2ü~Â{<Ov)ŒP\ßq
+ûM—üÍjÃù,TÀ·é’óЕO¸‚Õqn4®Û¦+[*~§3ÜÜ–’/ƒ¿eÓ™æñö[6É”Æ(4Ž8„[eÓ™¾ÐÙåì&ÑÅ£…ÍMgW(<w›«¾è
+1T73tsÕ•
+Ðæjâ&Pxma_‡à6W«®@0†±¹¦Ì> Ó¸L‡q6לm
+„_¼ãì^…ÀÀAôÍS ¨Í7÷š?‹LƇ'xsÿ)Ð@™µäI$~œÔ²yàqhÈŸì,‡H»âPÀæ!@9³Ýì(×n:¶9§°|hKÓ,0(dÁ:xKÓÕÐð¯\•O=qÞá–áß@ãä%•û…­(ž8¸e\‚cK™ì©­<4m¼·”ýT>´uê‰÷Â?иI[§ž6€æOfžúriÆm?Í
+6IÈc©b1nIK´>‡¯Wz õÍ|}]‚;sÜ–0_Š@o‰|·%f@ðz·ƒKP˶°%jÜŽ¾èPyåžðÒ,ÇǪl@xU׫—Þôµ¹Ôоâö<Œ;;Ÿ•QŠÿ²dò;»È€à</¥*µxA-®~ùøRE¨òÒ” [
+yŒ¯¼Ê€àŒÏP* Å°
+9>c®á_Êé`G,¹°µ1>ç ‚Bl|½¡)qt|jˆ†þm@píÆ7âàDz
+ ûªìð²4J7 ¼vëÚ‚îêSÚ5t
+~Ç“]*€·ò¥¨h¬´OÜ^²LA¢{ʸ‰F|)÷zB
+¥¡}è-åc¥C1ù2žÌ·*žñwT;uJsm|ËÀßm@x âàJ…
+ÛxÐmh„N§¡²\1Ë.1À€ðÚjÎnœDÈku‰¡á­2UE™$¨
+žŽ$±ú?aúß%C{õäÃIy‹ž‰½ž@/\Å*$9b-ŽŽ‰/\'€úêûÎ5nÜ[^Ôû>a@PÒM|'S»'¨D5nî=ñ,4¨<o•¤ß—eâ Ê÷ÓÄAûSnœHÐ÷n®?wH
+zâøý„eÁäí,ì©Ó€¯0nòn4¥}jû&mIŸ§t@ù¯§”ѸÿAMCý ¯ÝÌF¼Uè²ÄOœùTpD7Þ£Ëñ‰  9eRêZ0Ãñ¾ç”5 ,׌L9:\;kL\ó­
+ Ÿ±CÈÕÅ]î§)=¾@B¬ø©– ðHM5 xßMª#‡#äÆ>Ö)CO‡°uêË+ÕµöžR° nêËk ÎøÔÁ¥yÓ½Ba?upYôÑ{¬Br3m @ßÌMÑïÅ”§à›…ØÔïTÓjŠ|w·0~¶˜úÝÝhÚRmNz­ñL[i@ðOs/‹C¯i&>Sçt@ûÛôsaÂÿÞÂS°¿­A]eZ£ÿòAðÊlb;xZ£?P×Jú*óÊ"Z  ‚ <mú@Vk©O{¦MO
+ ú椇G_J^–§ÐѱÒNMSC–}D
+ZZ¶å7h&€vbÕ(¢‹nßü†] ÿu>VËBÏDшe2}j@Pä_ð²V! ÂÁ®ù¼Z Šb'z~“y)—I"bÉÈÎo²P
+]V‚ZˆÅ°µ‘Åc¨åÕ,]u͉a\~ËV„§ åyY¨½‡/©JC‡°_%¿åÞ@Ê}jKýÍoy@
+Œ`ÁŒÁµ ʧ¨R†T^1´T¡ŸñÁ4l{@?'mÅ#gxÕúÏAx?ýgjÓÅC–Ô•c@¿¢¯ ÷s–b3~ÿ€ Æ:cÒ%¼ébÔ¤ »tgL
+  i7©ÃIªƒ´©im%ŠÏL寮¡Eh®*_æ…k„}†©†~@óÖƒ–]0o“
+
+ ïz±qã¹!_˜†zÔÇg/ÊUj¹KÉìÙ‹t¾Ì^>ŠÍîçÄŸ[þmÉÐœŸ è »¸­HùœŸÿ@ãU´ =îƒ <g|†Á‹zn&Ws¤ ›¥aÁÜÌëPÝ 'L ؉>—Dk.˼ʵRªvØfâΫ\×€à~š—ס„üç¼¼{P£ZD»¬%Gb^£Óg|Þ%ëRjˆ5útÞ%›Ðå+•ºFÆaK(ʼË×
+ ‡á.pЖ<¯Å ‚¢g^{eQǽTr_Ë6žÌöK ÞóîxLs¯}c©ywô0 ¨dÍ»S—v¢Ò 1l˜Î»³™
+ îSØ€§p«.k:¯{¾
+å¥;/ËžUíyGžæÉ Ñ„Kçy®dh~kýÞ’´§dÌoýqqgdÏoÇ éÂ^«lÏo×Ê€àõ:ÿvöBzÁ‰–Þôóo  y<ð°À‡§ C#‚ÒwþÝY¬Ð8¤da›sþÝÙ•¬ùÏ«´È¸ã+œÎŸ{þ¨
+‚# ÐÑKØXŽ¸ÇÜÁ…† ¢çÕöxŽtl·,(z©dè¯\~~¦Æ¢Q‹°ÿ+÷Q´æ9­†xé+pà­yÙ€ ôýëtV½G>¬ ÿuº¬
+ðV‰º§Ü—K¢¡Ú%C Ë*-šZ¼;¶Êø ËþX r°>¾°\M>œ®¾áÉ\X®–
+ Ü/S—"h•¨¡‘¨yŽÒ`³{aƒÇPtsŠ âù0Z(€â¬±RÁN;P @W°¤£¾ÀAKzÖÂ+  «RÝØh™qu†…WÕ2 ¼v[v(5„ü¥S4´Ç€ j´¨Êš£&M®:ƒåø¢6×
+ [Î9_\õ¿s.ºe»AKqQ»WYô8$3°U¶¨ÝOð¢ìA¦€aÇ2¦QÂcºk-.á…aã)¸kƒÁûnÑÝOJ»zN
+òâñ Ð~lp'’²Û¡ò°x è/.(à•>
+â6¼‹ÿh@x25Ö—voš  %k´q㌃¢gñ’õh7ñ QAp‹ÀX¼íj´ïý”Bã¹b1ôAI·¤Ô&>æT2ÛRpwI©m÷Ó’ó¸ÖwØ ÆÆ’óî0 ¸Ç—TÛÁWy}µ'øsÕö‡ð‹Ä’¬Jy ¶„Ž¥#ê’¬­(ç]I*ÁòÿË1ô¾
+ÍÒŒ^({Ë^Ó \Nxiö<tá%¬ÐP:c_eK/Œþ¥;”9I飶ð˜¥w<h@Pf.kÂõÇ]M Uà/kr‰Áƒ°ì†ì
+ðŽñ“ø².”@ºñLÌ%}%Ž5´À€ f¿ì¾[Sjˆ«„`Á²ûî4 8ãËоCjí`ñõ,{`£
+ÀZÚÅ,ÿâ‚“¹ü{UÿÉ¡ò îàá.XþýwÁòŸ
+ø¢N¸?cÙt˽'§sþ¥±+yàN(ã°åc×  ?ždÁq¯ê0ND]þGo4ñ½ÀôD€“ª–Ol#tˆEÂËq‡²`ùÄ—ÐôX]Kƒ¶:È˧ÿ,€ò¹¸ºvâØ$YžßÏ€à1_>Ÿ[Dx!KK¤åóŸ@ËÃ,zbäÌÃî®åËÂûií|¤ÜÉt/E|¤Ö>-€¶ÞÏ›Ž:ˆY"b—oý§á¹upÊC¦>œ[?@»/æ#åŠ [ããå»›ž§¥•jDN…¨Ïƒ¬¡4tðýÔA rhhÉЊêñçÔtÛÁ+ª*€îä$½p,d-:¶âÎá_Ú¨v&=[¸×4vX¯Ø@;â­âøÂO˜+vŽ5 ¸ŸVœ9Ɇ)Å $qgΖ ­,µ‚Ín
+žŽà>+K­@éòdÆ©X™ÞŀಬÌ(Ï sØÒneFeÔðú€v0’•‡• o2 (Wðát•LJßÇÐ;T+;´IMA$ê+ÌïÐN
+ÅŸñ»
+¤®3D
+VÇfÒê±w IÓµB|X÷]=©@
+…Qý µ@{uÿ`¯-î#±zïÅ!ì_}H¥’Ç(¿ÇŸŽ¬¡«ЩÇS¼û5,3WŸêU2´¦Ì }½Ar¬††H U¿€Dk<ji´¶¦Ì¿P݉v z¡Dhš
+ {gÕ(î)4P®½·WÉкŽ§Ù B×¾n‘êsëî.U±ë^Wµ¼Ç«ˆÅ6_÷zÁµ[÷ÆjÞ¾!ª½€ Óuo– æÌÐf· Y s
+У¿óá$ÉÂJ{á£ãÐK*ŒÃôz'³ð¥« J•ÂWtŸ@JÍ ã ¨ð•Ñ¸ðU¥jÓ?îõŠ5ÖÂWûž§þÊ=áµCŠZ⢠ûw@óÚÝt™jh@Ðæ,ÈÍ)©UÐWmVCþœ×gY%ĹÖU
+µ@Ÿ¼˜º]M_…Ÿô5 xßTÒNjì€=…U ÞÁ…³Ÿç­¦gìë)œý²
+Ö ¼Â aü(³~E
+ V:»’c¬ olu§:›ΠåÅ¢gc«¿ ¾#ll[>¥jSª<ÁÛV@÷¨^)qOóóÕØç)¸§»
+]n@xLïP†¾G,•Ì7¾wV
+,M„}`4t¨dhS+% Huù›¥1ÔÝ€ ®²éþ[ÚIåê3XØoºÿ6ô”*ÈDÉBqdz驱h
+Þä6(žéæS4ô˜
+ Ž‹µ‰¢büpY¶v\f@PÏÜÚé(+ÈW ±äânítB
+
+2OÔ3w4¿W«ÚTä ;öw4ï$€ÂüΆ¨ŒÞá?ÏA_s
+ f³2špÍ$KñÎf§ ÿR—լи椓Àɱ;»¬@¦§”‡hÔâˆÝùh5ôË/èÙ¢ºó±ëP÷¢s×kÐbQïìqž
+ÏÓÀ5è}N ÚÔDzUÞ¿^
+ _Ú§&3éÏÔÐh,—âQ­ßp,äî±Ü»ÿT!`Ô͉Z. Ý@ÓÙë•ßðuîàO  ™ñÀãta'úî™  ¹£Ï©kAß3=nî´”»Óx…¼-%v/=m@xž
+›ðdR§E Ù]Ø\
+ÜŠI¡ñ9:4ôš
+!ñ=¥h¨P
+jÁ û?™m@pLûg³K×Ýuî!·|nv´Wµ(¥0"
+ü€ëþ½¹%Cq1/œÁ×kNCõЊ|)ºÿF,o¯V\#€Ö}¢„º†ÆÍu_ £o1DŠ_‡¥8úž
+ 'K\®™kqŸt² ž»ƒñ¯Ù¸ñJÏᦃñÑèÖÚ)×’k`/äÁ[¼¨ÞÞ†¯¤KúÔZ Ýf@P>ì°ŒÕÚˆ×2oßkнMÕ1÷
+5±çáབྷ” ºT_ŠžeŠŸœ]ZÅ€àjÙœ…½«Îø‹‹ðçZFP›!ìZ¢4K\Ï¡6#ÐíIv*P;©Ý~¥
+ÄÑ]‡^èo@PŽê?OÜ]•8<Ô‰AíðЗÛùp&<7¬‡¾Üc@xŒT}qU2£Ec=4òG4ùSµÀž;Þ—þÀS0ùK‚'øÐŒýäse4ž§kв§
+‡¬©u‡–=W2t8Ò•öÿ‘Þ~8ÒË€à<îõžL
+
+¶´ ?Ü+(€>Ñ÷•ZµXÔ‡?É3 ¸ŸšÀ[ÅUüÜûî§Ã£¦ÜO‡ÈeˆJ`Yöøá
+ 9×tàV"è3qy
+æ´6 ¨jÞø«FÔ³"ß^oì!€ö¨ê ¸E}*$nÏVtÀIó =­ÂÏH‡°Æzøø%)2±´¼=|<"€NÈ&‰
+E,¡r‡O@E/ªMGéŒTM ¼¨¯Aa$KÕW‰ÒE“¸鑬q¨Ö>^ŠÅ÷ÉL @u†²Ë$AAn–×.€©–#qeLb}¤Ñ[¨¯®î¥øàMw¤ïwèÈë)‡PÈñ…ÇðçŽ @'Gñ1Ozj;”™GNŽ1 ¸UŽ©N *„Þ·ÀêZ2t´b36n¢®H´¼&­@U”îKEǨí"ÑG«ä
+  u8©s<j
+>š7 (Ç6š’Þ“?†ò ÿÈå«ŒJ>úªj¨‘A™y´ÅàÔ碮ÖÂÑC -~cU;NÔXªm1N
+ÑPÌßm[C  ½ª¬©jàÓU44¿dèxÝY ¡[¾Î¥!€ÜÏÛ7âµ ‡×Æñ Ê‚ãG¸°ž÷Hë;Áª"€þVARqº7le”ŽÿýÁ|üÔWlHÄ<n•ã§F• ¸(MôŒŸÄO\TA
+>0 xZN&¸ñ ‹ [B
+O&ÒÐåuYyˆÓ7q=Œ“—×/á°Ù“W~tNiXÂ>N^ù‚'øäÕJ>EU;¼À'¯¾Ð€ 8<yÍ¿X`P›p_µYþÜ5H Éü9ÇÝ*qÛç¦  ëƒ¬ø9ˆ¯“×GPëå|¢Ô‚£LN¶^e@ðF8ÙNùŸâ„àªkxíÚõ@·{c
+Qú¸M§;yû*ôàcú*£ËAxðqÔóõ”ò
+ŒÓ‹G  ¥£SÎwð3Øé¥ß  Ï{ŸKªÖ¢Ø$9½¢AÝ÷ôº¼}ô †Ôéu{‹AaË_W¨Þ€¨ÕO8d±òOŽ@›P#÷\KxL›:  ýº‰UøŠã‹úôþ}šÓ‡TÍ—8iÛ ÞÁ§¿¤ÔÏ ô¹qxàÇû
+ ²8¤† QìÕ>}¢KÉЙ2ªCœbµ´%<Sf›Ác~¦2×f&G^8Š_»ÏTn/ö°£Ã{ºÀ/Ëg*4 ¨gžÉTå_©<u’JèÀÏe.1 (éÎT¿A\T’Ö½ñÀ«·@µÕkï…£¾v <ðÚ ‚BìL£®)U;éÿ¿Í©¡nèâulHîg±Ï\¼I
+ «žQ‡3LeÓrÕ‹è†Ûø˜SqÛ.£tæ†莟”S!¢® (XÏÜñ«ÁkãÌݹ¬Ö:Þâà_º»‘á_º§Of˜ob}æžÛДÒ,z¸(†Ê– ä°èËøæ<¨c@pœ½l„6“\ïK5Hcè‚çîìA¾#Tš »Ï^-aÆÙëuæ:µäc!vöúï .ðÙ6*HŠÂ÷’¶ÎBgÛ<c@Ðz=Ûn ΰJhÄЂ7çÙöë•Ò&+ŒS ζßl@Púž½ÿ.>R!¯Ì1žÌûï5 ¼ vrRÅp!þ³÷2 (ŸÎvº+ ûI*/‚¡ûпT‘Jc [×î_—”ãgÞʆ)kDqxñÙ‡w  GÎðAS„1¾€Î>ZÊ€ðVéV#åT w
+NAQ¿IhÈ«Úµäð–êêECú  óXÉ¢ÔŸ|ÒPC4l>_”ÆæÓÇ5´X
+R?¼Í‹fý×€ vX4[y×bäôŒÆ°jT4»š
+žñ¥X´âq´IGwQ2£åq½hÓdtÌ«üRíN£8DµèØ ¨hžÊðÁ%úŠŠ6—µ)5I¹O½2”a\üÈ…j
+ ü5Ú$ñ®ÑÎt¡õhî^–™o0‡Ë…~6 ´ \h
+<æM&Ú¾.”o@xLóÚ=A Ä †áBµТ£lHP»_‰c @;ßg5Ä y­±àÀw~`@HŽ»ÐT 4£ä{oaèàe¬dÅC4x<[ #Üb+L¡ï Ww¡%èìË|¤"4x„àB¯œ‚Ò¥oâK1á^A (]èfÄ^H
+º£GZt#¸ÐVTS.Lí`¹ Ý*€’ƒõá GÜs
+´ñe¥hˆsLCôè–´ÜRk_1~ ÏøÚ7Œ_ŸÛÀEì¼Âs¸Ì› õ@ë ˆ>|Åu¡¿ЮμU¨ü¶O°òÀw=\2”Ö¾tê*‹FqÈŽ U4 xZÒîPqbÞ¦ ùÒ¶5TÓ€àÚ¥}õq"^³ËÀ¿™,€~»Y©Ú¤†¸Ê(Óo·
+ ?ñÀ©\MßÁi4@êút1T®SChÒ)Óͱ$é¹P4]Wþ‰zOsx
+òK^»¹W»Ê" |8Óæ¶2 xîÒæ_ÉP<´”vr¡–„g|á^­þÓ+=6$Ò@«¸X×° ߥ\èn´ö]6$(͸Ð`´®Aʵ”ˆà‚.t
+&[xóShKZjÓ9® éBåÐÖ<%ÄÂÔXÔÁ—bÚÖ /Ë6îúKaŽîþàB¿¨;˜¼OÑÖ}Ó¶5~ ^ùiÛ~üÒß{Ï™I¡°e«ü}À€°|:®Q£ê% Žéx# ô/ Åkø’ˆõç^@'ïe‡k
+ óU1¥’“v„—åü¨.×' jq•­Û[
+Œ² ¯f(Š;øÖ…®@Ž°Àpÿ|÷‘p¡efÙ ?eaOÊ(îyåB_
+ È=)U›ò­¡+yÀ€ T)+¬Ô•ÞeceÐ5­ìÌ£‚LøÊ/{Í­5Œ²w\Ç“éP%|½–½ãF‚c*Wþ5á©ÇØ™W®ü/(C™I^“O;Lcè´
+P÷Nz«xŸÃP÷ΨWNtUíD8ŽTåz4@½ö³8ŒcþGcžÌ^‡ ºã˽À-l¼Æì>¥?÷‹è•Îü9WdDq%zÈ€ðÀ_«¢¢püK¯U@¹—…3Dâ0|Ï…F— •o—Ëî 2'£ØRþ¶¯S^#Šòƒ‡³ümß\àòTí ŠÏ¤J樵
+MùgWbå_œ¨–…Tפr¡©襞jûz6'î÷êBOK %ìêHáÏç)xi³AAùW¹êe8áuÀ¿ôê¨?^–x(d3qË÷Ë€ RþƒzP"¢Þ©áPþƒ‡ÐÐO xè—h˜ÚtŽÊ¶Àþå‡}&€†?ÐÞµH8†}=å‡?m@P/(ÿ‰Ž­¥z‡Žåp~ò‡áyRÝž8¤žëx
+T@w Ðç«Râ0ì$qìZùÏׇ°+ üçjûÆ(
+=Œ)\h›
+ IºâÕ­Å!ô.”.€&Øÿä)¿kb“k  i[ùpƼ|)¬<LÛe@X5š¡ ZRÈJ ÇŒ–Ÿ±Ø€ð.˜Íš˜×í5„ß9ËÏ>k@xg.+£?G¿»¹PY´|Ûæ^î$Ìár¡¡h­z ‘"êwzj¨CÉP…wt{YÚy­§Â;w”ãF©dFjqÇqø^…QÍ%Π¥x_v¡†è—[øŠQ6=þ©ðË­h÷—¢]t°TaÜ| ´„U£8©Û0ÇÔ…V
+ ñËY°RJJIU¿Z
+,Uþ7”ÿbJ…ŒF}W.¿
+"^'DËçb„åÓ_§”ÃSµ¸Uá¯"‚7g……[–~¶¨°p‚
+xžNž.ªXV•Ã£Þô efŲ/J vXSåÇ×ÚNî[TñQVÿ]ñìÚ¹PɪX±‡A¥½bºŠ÷“à¡ŒU8ðôŸP5}î긎oΊÕÎ@5.ÒÆ úêk¨©
+Ý.TÅ€à1¯X—«[QÅR×ìÆSP÷N§¥çå{uÃlmT¬w‘
+Ã.Ò.Ô®8+$¹î‹ë•žÀB¬R³i„OpPx ýS ¡Ï ÿR"•]Hê?Ñ•{ ÏøeSSS‰øjìkh¦
+ .Kå~ÜÝÏ;æ¾R†:*€FÔ‚•JnaO{åÑÇ ÊñÊó{ñ²$¼Ú§PW©<ÿ™’¡ôAl˜†ƒ®Ñ ÓôAs%º¨“ÞX¢–Ò-@vÓª½9aµ6ýÃÇÐ窀sÔ=… '3ýóîè ÖŸ E;šÀþé_¼"€Föç«,F*~¼JùŽá¿ntež÷˜»{Îežñß›±è‰yY ð ¤ÿ@ãt<«qXú΀àAHŸÂukÉÈ [²ŸÓ§´—@*ž‘6àÓ§| €feh§U ÁUQÒgU@Q6'îV±DX§$ Jºô‚V,zT F¼} Z  ç\¡¨%o#}ÁX´ø{>”›´lºÅ?
+ ¥¥ô{¹WðJ_š&€–Wå‹š²n¢8€$}y T8È0'¡
+™^ø
+Ćâ°Ê™îÅ KúhF™)ç\KŽ¯À|C3PêiŽªÇX‚‚3Êö@•9ÝËX¶TŒÈ¨<_
+¢U â.c.4A
+]ÇéÊâ^âm2j—@uî`Õˆzùž-xYêÜ#€êÞÆWÌ^w-£nG”«ºm‡½
+ ÇŸäÉt…j0Œ33ï-€zVåëÕ½\#V×2zÖ@:|/äŠËSJFϺè‰BVkî'}qöÚ$€^öU
+È;Ð€ðŒ ²ZK›ÅR/:s\T
+ùìá1¯úÂ
+Wä
+×°”•¨^¶©
+2s nßêµÿ`ÈKHÆÞµêµ' :¦D+£±g´z‹ ž–깺´“;™~YC î®FäutpÎrõ Î
+ ÆW©ë5”¤þ48Õ zãk Ú-Õ“9ìZr¼žŠøp&ëJ =|T{6Òv¡ƒèòÉ)C"öuúÔP¾á¿îŠs½baŸ3OCßS‹|¤¼ôì/¨ÞâtÝ¥ …\©îÊê×]!€n›®…˜w,Ð,tWR+4AP.AC—K –ú¢v•KbNõ»®@#©ÃéUÿ‡ËÒ1f@øzè VÚ•ÁU£ê=-€ºqqJ‚‰Z:6Wïö’Á1e%Ôã•×íȵ TÉJd  ËVεøž05´F
+é{1åÏ=½_aÕˆ.j‹‚œõôq“ùNêÄ–ÞÏYïœ@ï5L9:bQŸj¤¡‹ÐDZ’E¡¶]ðñ£„§`:gõF¨¨„?7½ZÉPáøŒ”Qì|©1|™
+¨¹éb´UÍ“W”ËŸZ§¡|´WÝœîUæ^ÖIì8«¹wá?X'uÌÝK{µkÌ3 ( jNãeq¨ÌVhj®(€þ~Jð^wUÇò¹¿Ÿ@E*ßœ
+îÒçðde´²KMcá5ÀÀ6Ù¥f‡°ž™¦ºmÇÜ#žt…¯jVÂQ&Ùåîgž\B¾B²¥ú§
+´”ÀÊ®XC
+ v­Øì¦}¾Æ3jm@ø¯{`*»L(×’þý@¾áýÔém†‚^Î'^àNƒÐ?ë²±ì𶆾ÙÿÌ@Y÷ SX?N÷Ë~Ì@óndu-Œ"©xàón5 x8yµ£FFX§ ä=d@ø—ê N‚¢ø* 4üLmÓêȵq@R á.Ô˜«3xÏ’Thœo@ø—šÝvnÓ-iÛfPTíJ_¢àðz D£¨5GÇ{g,5­Ÿ3 xn~D_ÔÞ…!pswt‡2q)Õ€’áAÜÑF
+Gqè@ ïè•æ)GG$â‹úæϽ@oT`!§‚´ÿß-¨¡tÔo Ö¤÷†Þo
+Å©P·Âhà¥d…“®ic‰° <"€Þ]ÇW>u
+~$òú‘ÏÚ:ðk
+~|E
+…â°VÓ‡ÐK•ó…
+Tû[¶¥1´N
+'öÕ]ÓО'ª6ké°[;g‘¥®Dì2©³„ï–ÿQ¿ vŽ’™I2&ƒ–ÀÒÚ9+ŠPL>-µsV¦„møäT;g5Ÿ;ªùÅ2³vΚsG*ÃÙµsÖ¦´è„?çFŽkÄÒÀi'À_ªõ&C1/sOA­wPžªŠB^ÈD4‚£»jçí5 ¨ŒÖ¾ð*µ}½ZK~Û¨}ᵨ±r}G\ õ5ð‹DíÆGnvêž`käÚºÙ)CøH5znSì7†>’@Ÿ±Nço›Ýµ›}e@x„·Ô{‹×Þ²ÀáÝ(¡œèTÄUþ-ç.ñ•
+zS
+Í›Ð{§Ú'wm)|½_Ê€ð}7¸YÊC“ŒÄq¨\íÁa4ŒKf«
+±Ø¨=l³a1ú“”’s,½Ukþ¢8dÙ™ßÁ›Žj0Zütµ¿U2T§õ]¬Öº‡Ó b;NëûP×zÓ¹·FßœuºÞc@pÔéÞ?u½Fl;êt[qo0‚¢aœžU§ûP‚ÞÚ:½K§6åàÁY§wYôjc¾ã”…‰…XW›
+ þKRÊC"h‰ª¬Ó¥áe ¤oÌóXâ¢ë xÇ€ð_7xK@{ÿé]
+
+Œ:ƒw ¡^­ïJ³DRÕúTq[u>>/u):!ß ÖPô¥
+EQ– µ:_•@“tP‹ãÅdAïÉe *4u¦^pÎö7 ÒPÂk7?Â#éÅhâý4?&€V¼Ä~/]
+ûë¬xÅ€ð<­¾A VŠ¡Ážö:«Û 5=Ùœ¤ 5Û‘ZÓ»8„ýOu
+있Qó,l’Ô)¬#€ÖW“éÕ2ñuˆÓдï2m©Ç#ÞOûZ cüVæõ¹±tÕ¬sl¤
+ þ\Y#LEìl
+rÿ ụÿV6“è˜[Jcæöß%€ÞlÐáVaŽ„†®@¯çe¡
+4D—pU¨ƒä¼!Õ ÏÓGmµ
+¢ ox8ó>º]
+nÞ%h¥*_– y…Óq@Rý• tº»¬®á‹&pá…ú§{œ§~È׆;§ Á…ÃP“×øÜQ¸¥›mƒ&ýPð^uî¨z8ŽÏ]ƒà(<…îN'…æÁ‡§— 5|þF>œ¥k©dÞðù[Ðk{RêZ4ǯn _Ûo@PkÔÞ+Ââ)ÛtØá4jÿ€
+÷õ9ÑÓzK
+“r ðãF¾$€Æ/Ëw¤¢88œ>~…AŸ3}²7¢ÔÖeÅqÍrúä7дÍ!uE@M[¡©>í 4Wöi zwBHŸÓ üë§|«'l2×ÒW@K®eS;J¢ ±ô%eЊìºÅ#¶m謑¾b°
+ ƒ3|aÇ,\ß’~pŽ
+¨ü‘Чµ|aOà Ðè˜çv§è«8
+©òÇ”@^b)uª§æs†Ç Õ ¨ÍË÷ˆ2FÑÅZªüwS5ÊÌò?¾œ§^#†^•å|M
+|ÎÛ+¶× (Ÿ*”Ékã
+.C‹0TTƒà·«pãs!uEà¨2èpã (½;–ˆ;(.f…ôž-Ö
+½›@ªàŠ™5V¨ø‡
+{I-”AcàµE…ð ‹éæ–¤m(î¨é)€j{“­½Qd1lþW¨]O
+0ñôÛ£AÐÂÈØ€—€„}` 
+?n`c ‚–XÆ ½¬€l×h3@o á¿¨Åt´¡omÆð?4¿øÃýcNŸŸà‡'k>Ács•ëæ~¨€2Æn”@žn¡æl±àÀL½+€&tá­âvWÁ¡ïŒ =ÐÄ8«¸óò œÚ”11)€fñ•¸[,èÝ¥ Ýhö;!u]1¥agÌ> ÝsÖ°è‰R¤Ãð¸9ë$WÐRÐ3ØCH=n³áŸEHb݉*ºJƒ %–1ÿ:>4š&0Á’_|þ „Ý"UŽ¥„Ã;-ª­AX·,.ç}ê¯t˜TÐmH ÒHXÃ¥LÆò£„FvY>æ ºò7¼xöMhM5O$)o8kj  õƒ9à¦ò”âúa„݆qêHEHµàc¾a’
+Â'xW v“,ꊂ¯R2vÕÉa‡+c×»T 1r6
+zO
+©@,×ÁÃYñåm„ó@½|
+(úVPCtг lJ2BNÔ üë>îoߤmð9+|B
+š-€Š·á 97vÝ2‹·× , ŠŸðC)ÛÊ,þAY\`
+X:!(èW Âéò†ì’P–²…¯ 3/o"<ËÞr[$ KpùT"ä}Jg°S8è™Y¢Œ
+ ²%}a‰Ìÿ̲¥4/fÙOØh§$‹(nö—Yö˜úB=ŽZ`á$©Ì²_kþK7Ï ©P¥óQp9MæÍsP¹†yK`j¼Y®±A!ó–9Ê1u\oC«ÕÌ[æ  ÛZó‹'Ì­Å3oË@é¿û/îì˧ÿ©AØx(ÿ¥ï’Ä¢S;³ü ”y3Θ³1ƒ*˼E
+ȼkž
+, é1™c3ЄñJ•Q ÀàpM˜$€&¶ y!8*KÂÄ{%P[å:&r 0eNì ¼Ûn
+.%/o߉Û4ï§I^v—;%Ð6Ü·dNZ+€¦,ä§dWÃدÌ)K5 ûé*¿€>†qV@æôÛ5j„Ê-ïó¬d$…ï[*·l§AðÅ+·¾Ñß¾±h©Ê­Ë  ¬ ù6¡©Oå¬MèyO‘ñœâ“ÆÐ ¨Ëãl®…Í3Š*wyJ
+ìGƒÍÜùqkn•@B*›
+'pêeå5]5ï‚u)SÛuKð_·Eƒð߬šiQVÀYVÐWhËGƱHÅâ0Nå-ÇÐÖý¼éî¼WhÓUÞzP
+ÎÒ¥´ÙX ±;®h,€®šë 1z\4‰C&w\µ@
+Q0TµÈÞ* ®„ÖU‹L@—¿ï+ ˜Â7ËU/?$€J­`Ó(F—s8Á­j©Õ(£
+/› Šs²ªf„PÛÛÙ¬¥ôD×ÜTm[±`(|——ÓžŒºíðð £ð]ÕóCØV ÷/=ñiXAù?¡l±Æܸ'þ,á­ †"S&+¥¡V«pÓE¦Ì@SÛ°Àˆ˜ÕFdj4/¯Ù_2’§ l ‚æZdÙ<6ÂTjB‘e‹òC†uZ›â€µN1”‰DÖÖÐ üëžyËT—äl:¼˜Ï@»¹¥?¥€ÅWü¸Ý‡4/æ«%Ùð£²È(Þ¾‘WKi´0"o{¹FTj¥p+žÈÛã5ÊñÈ×gB*a’Šcñ;}}N
+ NìºQ¥³œx:õÓ ¼N]ßô¥3D±h~\×wPO¯N1Ê3
+´]VÐR ‚«}òɼŴXfÚ'ŸÖ üYÎþæm_¨5t#²ÏþU0/<ˆõ©
+®A0®ïíÉL*Œ˜®⽋  ½ÇYôÄÅã{O Sù˜SY†a(GüÀ ôþe!•Ê›Œ¦°RŒ¿_BƒðŠóM + ©
+°ñœö~ÁPjN~ñ¤[º eAjNÝ‚¡j%Rì,Óá [+¨º
+ @ïd±¹¡â3¡©öN{t€íL7½Ø0Ž¡Ú?ÐÁ®ü8*€ˆá¦ˆÕö@„ó©ü@º¿øQ ‚ç®ÚgXˆÙnXúæÕŽ’@YˆÅ¨!VùÕŽw× ¼Ÿ~ò
+Àmwôf_UûéNô;Ï¿‹P'­(Ž‰Uû=,€þð\ÛmáÂ)ôÕþØ¡Að³T¿ø>6!©ƒs`Ô´‚ÚkÔæÕ‹daï¨|ËмzÑèXk=Ž‹ã’ÖêÅîÓ ¸ ª§÷ó7]ÒŽáû–êéƒ4êàê•šyÎÛ|.ƒÌ«Ô\
+ C!ju»§áow×}ì’Ð0ACÁIõ»ÚjÜO5Ü›@:Ô60ŽBbÐM-ýƒ°“¸¯Q›î@·rÛ›0æÜî4†ú ôV¬cTX‡Û”ÔH¿W
+z)dèŠRcöÞ*)j…PÙã †j¦ñˆwGµÆÃb5Óz ¬u!uÕKYið×TåYÿ'ô º(J˜G¶Õ|pŠ
+ê¦Aø/­övA‚Œv@Øó¦[=E
+§õ×¹ýwTQõ2IRܧ}Ô©ØNƒð;EÿãÐRØ;늖@½ù 8fHÔÐ?³N¬Ÿ
+ ¦·°©MM[ ƒŒê4½M
+4
+-€NñjãmQzç©•ù!\yU÷uNQFÜU(Xë¾ÞY
+­Aø/õñjÝlºœsÞžà}ê  ã}Uf¼%i0b¢
+ÄFÆæl 6î× (}lñ{O8ØÆ—W ¶¬Ö ¼ŸžHxÁ—°ÛªÎ<‘Ò h‰5xâ8+ÅmÆiðÄ—hǧî‹S.r|8w@o^Î|R,¼YRƒð·;¤æm8G<ÇŠºÁ¡ÐŒœ£Y ƒÖI 5Üä½xÊ->3‡n*¥Að7|¾AÈOŠ`>ßD
+ÿÇ[…ˆšÞßuÑEmº».åñÎA Ú3x8ïºôTòw^ËUp î*ù—
+‚BÓØ%¡2ù8ã4
+ÍÖ x•¹Á3Üi1†!ÃÊÜ,€Òׇüô½HÀuã%HLy¥uÔ$Š.1áVi”þ“
+zK
+k”MžõÖÉmk³°M×äÙwÐë¯óе…as“×ßÖ ¸}›^YG4ÔÚ/AÓ+ë  3kB\p±‰uÓ3 †î¾õ‚2ÿ©t{Šwß–¦Ap î®ïuþIÐUŠÉ¿»»~B
+ ¦"†¶ðÍêO@žáíë]€Ào׬ѳ¨é=Ê4¢1MøÜ5kÚJ
+ ÷’Ï
+ êq4lÂàpeØ(¾æà‹;§e8%€f¶åcNíH-ìNfÍì AxÅç ðÍ5*Ö„‡3kÎ` ‚‚5kÁv¸h”†!’µà#”³$/<AÎ)|ñœlô¸wMŸŠPR°¡ÅqÖöê¼NQ·^§íuÐÎ-¾Ìt<3AÎÚù”Ἣ"¯Õ°f^eíª¬Ax1w?¡ìL*ÔľTÖî­„ÿÒËË=éëØadB!–õr¶A!–õŠRù–!Ç{e«
+j­Ap·ÏùÕ9æ®ÞiŸó§
+g0¶ß­AxÅߊ*#Ëù¾ ³oÿVJ
+p;“AK¬ýþ•uKûCoð¦£Å4\9µ?ô¶
+lB¶ÿó
+ ‹ù׃¬£”ù»Ç´ÿk ÁƒÐá%Õ€æpÅ°8ìðRUôÉvàcTáÑŸL—@ª±^„2ñ¥L‡OÎh\§ŸäŤý’À™ž>;¬AÐVép²mžÑn'p§ÃÉ„×éTKVùt#Ǫ¬Ã©¶ù!8ëðÝ¥òI(bÐá»\tº/&õ,µqÿ‚§³4
+±´bG•bøuÜ[0Ô±Ð
+éü¸8¹%8ãìþ
+•4®Óý‹óÎ]ÊŠá,Ýû.êÔw=‡'Ü,]ìÀwêû˜
+†:ßåõD·¨›cÄÑÑù®¾Etç»ã Ñ‹[Ø4ê|w5”«êÌ
+t½Lch·
+ŒÎ;'æƒ"8K·ó«CØÅ¥Š0CGåί@oܨI8¿ÓåÐÇmÙÅR€Ø°˜w@ǹˆØÍf˜µ
+z]
+Ú#€.¨^p–{O
+Ú£Ap?õ(Ʀ‘ÛYÃÂÛ·G±4
+Ö7]æv"â!ø´ô¸)¤Aøq_y¾õJ‹Ø1úîñÕëù!…ìqr¦ÑõsÔÐé®Çɹè¯<ѳ’¸¾¥Ç_—  s7°J¸}Ñ¡Ììqî¦üV@=.ìö9~Ðuëqáå‚¡ž—,U¦¶{5÷SÏKViÜO=‹vñ)êˆ!a²gѨä2ÏÅu¨{åÇ•\¡Aø×]Q4¤Ò­âaä…žW\––XÏë¯c3„„†!8ÜóúÐmE|ç&4?â¿íR ‚ú®çmÞP×gË᤻ž·­@™êJÜ¢~€8èÙ3óQ ‚{¼§Õ‰Õ†M݈pÂdO«»
+†z­¬Â¦6õ…ŒâyÔ½VF †z_¶—MmËí¬…XïËö  Sj
+bÌ ã@ÑÓûT\ƒ ­Òû7¯Ð‹4†#êq²FïßÖ  ókCê¢(6ÄzzŸ__0Ô§hY%zÈYÆKЧèM·oŸkÚòg¡Ø~ §Íö¹¦½
+ ‚ß®oý7}¥Ž*´_
+ ÅÞˆ-J0OÒL6 @Ù×òãÈ95Äzúf—@kÔ¸˜ujÁ— }׌@k_QKàÎ5†á‰¾k_@9^ÝkÜígŸÄ&dßœ­døK^SDê©àNƒ[%ç¹üÎÏì»ù ›ÿÉ¥@'°ïæóh›|ì(i+РBA7  =;X…Ýþ™øïùŸá=þê<= 7­¿ø« †úM{×3Ú©Ì6fc—¤ß´Ch¡w›”¤~öC™H¿…Ð ê˜Ó«Âý^(©Að÷Ûÿ;¦ÔÄà’ôÛÿ™
+Èëcƒy–8.€ª®áTZhèÝõàÁkЯŸ{B,ì
+ ,züõk ‚ŸåÁ ë<D7´4\¾ø… Cý Ýͦ¶;5çÖö/Ô\ƒà;õ/|eHÑ“‘€‘Ås³qò ¸ ú_ö2üa˜  a(úM¾#•Ä×ôý£? ºÿùÎr"fãt†þõ
+K å9G!j˜&Ò¿ÞýhˆR¯îD/¸éúצAPúö¯7‹— EÛÇUú×›'óg¡‹ÃØŠþõŽ
+ ú7²è¡))l´÷¯‹A¨ýê¾ÑîœNœRØ¿~- Ô†@*¸Oâ4¢þõÛk>Rõá­B‰ïà°Z‚)¨A»J¡·mC3ˆþ : {2Ùx ð’…Óúßs‡
+2†ô½AÍFh”*ƒöÌõ5%šCa?hÏ¢‚¡Á¥§²À  q†0ÎàÒ³PÕ6l®ÑäØ0öïWm¯ApgŽ=REz±°…oIÇ^@ •€›p“ábN¬@µ”M³- e¶ƒký Aø×Õ®¯†#X -³×¾K
+ )܌ԭÈLZPÐÄwÁ¬ž¹Fýìƒ%cüâ³F  •ï…8G~ N&¼ò
+l:}%€Ööå%p¨8T9dí
+Œ¿Nc¨ª
+¥ò‡Å±úU¶A-5ô«”¢¦ƒnxñ?Ê +šÉÛ—Z5®-† zŸxÂ>ê~ßÿÿZ•Wï3Ôø2%¢£Ž8Än÷°Æ%4®Ó°æª—.:RØxÖüú‚¡áe^˷鳜Š0ô¦Áí;¼;\”RHe÷ú]
+Ú—)¨ÁÅõÌZ›.x¨†nÒ èK ¯Å0ç:¬ã¿T«½
+ i X)Rª†…CK#¦-Îá|•ÓÛ²*£y¨I1½£
+ O±¹Fͦɉ
+úN
+Ejƒz†Ä‘»;  WûzŸ%Jel \2òÕ5ÿ¥ +EM%5Ø.ùñ%÷øÈO/óÀdÔP88òÓè›—•¢vTuæŒüæµüÎëù}Ve ñ|ßLƒ Fxøê£üY(½8w¨ c¨A†ï&E# ,n©APŽ?|ÏÜ<Áê,§š_04êŽqüY"î4q¸˜£î˜¬APˆŠÜ­BK·9 †ZhüÀ£¬Q¾³ìÆ*ÑbŽ²Æ
+ V^àHÔ3k¡nÕ*)€º©>4n#4|÷:ªÛ4ã7VÔ©ˆí{¼N3þÐ hÙâÌa*…"Åh€~)Ýîu‡ÔÂÁÐxt»7P—6ldÅ(°MÈÑ]Ú  n×*'0’° .Éène4îñÑCïäÃIåȆ£‡Þ%€†5f7a¾~=ìn4â„ÿâqËôYF|£Ap«ŒÇ…^t,Ã1=î- ‚ÒwôLo¶½{ÊJ`ãaô̈/×)¤5䌎ž¹Eƒ ,=÷%ŠG(h¯
+ÃV©¹]ƒðŠÙÝwàc¶áîuì—hþ,xŠ:Fê%ˆü¸ ƒ †Æ¥}ïAnºzÇUÆ¥ý$€.ª¢œeºÁ©—ã.
+k‡ã..Æ¡
+-JÜŠBß
+J× üN=3„.Šì˜adÛ¸Îoä‡ ² kOßÈJS/ùq]{k~§nçóÔk,P>ª ÿPn_æ6· ”Üó‹÷_”2œàÞ$=Gº¦>Rž@3X`8¯œH¡ L4z·’¦ñ×ãFï@3¿Q!“e9B4næ÷h6Ê»M”l¤7{LÁÐø–¯²èˆú`óí4†ö
+ ®ùpºó=ð ×ø®÷ ^Þ='9%Q;p¡Æëõ™Á]0~‡O)é.8Œ™7lŒ
+nß©Ö3(5–ƒ
+n¯UÜxajj¼áÏRý~]§ÅpìpjõŸP-oÚ‘‹‚O­õ¤
+6óãvÑ (X§íšž'Ä"IìNNÛ5Kƒð:½x »nqw°(^§¯@/Ý«98†­òR ÂK°/C-AÄŽÅp’Ô´}™CÓ'q©—uŒ,ø¸é“ž@38,Hm”,C'Îé3  y¿r(ÀM{Çr|ú¼?5¿Ó²ÒyÎrpûòã–•@k·óA ØY é=?níó(ç-9ŽM̠ʦçü €žö¦®Ä©Ys¬àŸþôe÷øôíÝ}ÃÏÙ¼X>MßÞSƒð~ÚË™žî°ø@(@AWk~Ü73/öÜpAÜô›òC¸ûÞô÷ᜠ¤`<œrúûSÐ^Òù€îµ |Ü×iþu¨ný j1ƒ‡é4@¯bÃÏrÖà#õñZt|Wˆ/©6_¦I
+ºY©ø8µ2„¦¿\
+ slŒRÃs+0š…—àÜœ‚¡Ez„ÔˆeÒ°gé¥AP`Ì(:%¿¡¥Eg kx*?F΄!?sƵP™ÿâ Ë éf”)“Â’nÆ5'.U ¹µ34@ÇlþÀQw ~ñcI ‚ºeÆÏÞ݆å¦ZúÏøùetÚÍTˆ¸¡açãÏrz‰AÍ9ãÕ7ÄŽºÉ(ðq¿4Ó ¨ïfœóR
+Ãîb®çÞ@ç½FCny»ièâŒóå
+†f^4?‹M8¬€f^ôˆÁ_7³Ä‹žz¥;Έ¡½âÌ{4žà™W«+LhlH’šyõy ‚»`æµ³*KP»sì˜Î¼öl~ÇŸf^ë¥}Dxì†B…%Ðì˜Z”œˆÝ¤™¡­è„/¢“á@q¬‚N凰,˜Yfo:2!#%ùÅˬ@7žçL·Æ†ñ²3½Ë† ›øÅÝt+Ã5ýÌ›¾× ¼{y£–7aÃUïÌŠ}Pæ_ Q!j I¹‚ÎhŒdͬ«ÚÞDÝ~üëê~!€š_ém_g«€Næü¸æW ÍjÕJ 1j}ƒS›fµºWƒ °ŸuoçJ›µ­$3Ϻ·›
+ˆRÀ î伆Q ÂëÔ8¬8º4VPa ´G„(÷[bóï@M2øÅÝF›80¯IeÔ"Ň“†¼ÌkQS
+N­SÐN4ñ'þ,žwÏÝü‰¿ i³tÎ] ¿
+/Á´ÑhæJ¶Ÿânc2¨æÏ|Tƒ Rœ¿Buyv«$p~ÁüPŽÅç.éùÔJ
+ Üå¬ïè.ß0Çt~n¶
+ˆ*' Ùñ Îl—@ÞpÊT$îÆìñ.8ó²á?{Ž½|rª±h~ÜÙ -Œ…—y5¦Üq –…—@—àÃéÆ~ñ¹[xùèz¯Ë35¿MÆ ñÌ…×7@e;ñÎL±†?ð²]4ÿº²_+ÓÈÍd…aaÙS(£GÈ77ä.ÌÈ@á¼ËPÛÔaa$Mƒà‘Zh]Ï~p„ú«àÆBë&tçüºGHg^ñܹ0?„-Œ…õ¦°ñ`Gá@+?®Þô‚¡E×qOtšÕk'q^Ï¢ëÞ@7åUd“SÝ¢›Îá+ñE·ªû‹Ü|Õ^të€ü6ÝÁÓÛ£T9g(Ž]tÇ$dmVŸ…&Ÿaƒf‘µE
+*à„¤ÅÃß@”ÌŒºgÈ‹',Ô ès.žÚ“
+ãTÙ⩽5ªÅ³nõvŠ³âÅœu»á_ù ·}£aºKÂ.Éâ•P¶šJN÷Á†Xôâ죄ÿÒ‹^
+  õ½Å¤ª9+•âÒ wi<œK7tõ? ©Ex¤–nè¡Ap–ó;FPŠ&þKËŠÕÔ ü—®lÃJÑ¢1µ8óeÙ•íPÙݾáç¨ , –•}YƒàŠ/»MÇ:ûÎ2ŒØZvÛßù!l. ÏRn]cã,“eáyÈŠ³¢¦+C²ë2«š
+  –ï,Ç­.
+(ˆn[1yXYò;t7Ñ+åÖK*CW^SZƒð:U¨Î¢‡.üM‹Y¡¦
+ Ö³ìV[àBùU­Ïj>œí¸dÌÖHåUÐW¨g Ve1
+žb•¿ªg- ‚Þ몎ñ¤(Í'n­zàs4ð³<a.eV ü\
+ þ9,Ĩ÷D '/Aÿõ„ÏÝ@Þt$ìƒ ü¸Õ4ԭ[‚údáúì‡ú  Aó”¢þTö ÍhØÿ|×-aÄ¡‚v  ‘KC*ÄÙxa?r¹
+XÌ
+\<òbxS
+=ÍÇœºÊEðŠ¯)ô¬á¿tçaP(Àã`Þšë ÛT§–d”"ŒÐb]s[Uå”BÇfOÙU¦ &¨VÌw¸¢á@gWÅ5šFkîä¦÷nÛC×Ë5w–@›ð¦ó:qB±f`3ô¹è¨Ö¨!tÍç} †ÖVŸÍ&dÔÍMƒ[[}®
+ˆÞ>aøvŸÖ øír"^W^÷6Å
+4Nch
+¢Z¬òs¾~Rƒ `Í9ý oŒ¦"D=”Â~KÎ/Þ&ÉŠ˜©é}Î/[Ðoj35s cÓ(ç·NèŽaDÜ\^Ããþh"€þö*×i®ªMWõš$€Î}¡Ä!…«qø4çÜ×è¼J|w
+˜ô•
+ ž&B—Æv,ŽBëw7× ,0öýRéÅŽcŠ[‚¬ß÷
+'€n¬ÌƒÚ¼FMóbÞx‡
+è±´W5ú–“8ŠÒÓú^
+QhSZˆ6¥Ÿ´Š•¥”¤TJ%û:öm,#Û0vÃ`c_‡™±ÿ>çó9ïÏ|ß÷óz_§îí¯çãûþÌ{9ïsÎû,l&YÎ× Cè3N#£;jh‰4ì³Ö¨·Û^6DåBaìªÖ»
+ 7tDöó/µÃaCÜŒQŠ 
+5’@Ã^çcîØIØ6ì- ô•wÑ›1ž‚a}S!, † ›ÅÊC,”4y!‡ ›+€F­ö¶âŽõ§a£Ö
+ ´lâR*¹Á¥;,mŽâxJŽMÐáTÈ0O×z“™¤ò‘ºN
+–õ¥RþI' o•¬#„xmEåž°Ïy ;ö‡­½Lƒð7­í­„X(öÕ…äÉ\ûµ
+ ãÓصäxì Ðñ™ç††—šÃ¼½U(¾Có5ÿRinI…‚†ÆXÃK?+€.8PWQË7\)†ŠЂ¯DØ)}'€2ª(uÍ–s†.Ã3hñåf™Ò؆/þX
+F\ÔM
+ ÷…}”bèVtm{6à)s?‚ÅáÈk_@ñŬB:éKX…_ªAxžê©È<Ûࢠ}$€LS¼½,†¦‘N@ÍP“Iå„qÄÙȇf  ¦Uª E(zF6­*€Ú”ã'-CÃñ‘m"¨­Ó»0D[ãa_‘Mµ× ü×µ}UH
+üᘇ‘m;i^»ç¹s‡Sp7ˆ]K#Ÿ  özÛ7Bí0t@ƒàm>ò•w*xšj*@­gä+ï  7&±!³•ö°aYÞ˜.€:¹±k R¢†R«#;@rÏ'<Žíà‘~¯Axízfñ¥HÎ._;®çj ÂóôE-umP%,¢G~q­
+BVGtŒì]^ƒ ¿Ä!;Nc‡ºÙû]Ôw•2$(X—NÙwAëuä·¹ÇÜID5!Œüö_è7Õ·;éô"ÃËòÛôçu¬BRðOØópÞ €6pB\Ð)‚ŸœFn¸5®¥Q—\ÊÆM‚ß±wmÔ%—§@>¿
+C/~P qIӳŨ¿@/åɤGU_ÚøK…èö®Qé^ÛÄÁSðÊÑT+££^oɪ6%-øŽøëO ®Ü‰Êrù/E®kTƒàzWu`JPCü:êÝÛ4÷1ÇЃ?5ÄÐ)ÔÃíô Å‘ˆ¯Y—‚
+ >16–)AËPtlTŸ¤áp’•[µ áV£œ@ù€ŽSš ‰=Y£†—@#~WêZȾ5°™4jÄ_hÌT%ì©K©aYÆÌÐ x)ŽÛÞûLÅ£¾‚'<ÜØWÐ8Σ¦àĈ¡8Û¨qÐÄ’í· á £&†5ïñ‰÷°°'Þ÷hÌ>ñ>4õQv-Q`“Áà5õ14Ÿæ¨e©Yרy]Ђ’Bh””oóQ r5OfÆH¾^I§õ«áá2ÆjÔzF-É*v‡[²F
+¢´À8pkTN# ¾-WN
+ÿÁÆͨmÛÐN•ÃE.tC†Ú¨a´ëµ€
+NŒ… ­íFízC
+ºJƒð<µRËâ´>À.“±­žÑ ( Æ>§’­CÎ-Þ*Ï}-€Þº6 Ü’AŸaª ëP— qs`éØ.áTçºý°%o:z
+h°pâà¸îïi\»qŸ»/ËŽ .bH÷y'ôÊVµÿñYŠ¥zI
+±p
+¾û¯ ^–·î@]~ñ*(Œ‡ëò»
+˜øI[4°¥çT°…Aô |R
+¨çB
+y†žöŸ¨áozè 7™±¡ÄqÚCè·LŒB,C/Ì´î@/¹žv' !hp-¥½T^
+[†p«´·Ž wØ6§RËÐ)í‹лx¸$•vÂ)>iï^,€>¸ÆŽšQ 9†ê ï•¤sD4v0¦}ÿ„
+¼ÃiI8œar¨š
+ +®fÃ4ê<ƒÁ‹zÊ×jž§jÓø*£SîKfäáªÍ@5ÝôQ{¿ÙÂÕðP4¥æ¿P]VF©}IÄ-8¥î‹ ‰)7¬T-2ø˜O¹a­Á=>%6€U#r3‡±ŸnJì' ‚ZÏ”;¸%…)Sai8ÜKÐ}ϱ
+™pâ”ñÜ÷b*„èSêuå«,r:̯÷¾ú……˜sªpÑ”z¿  wóA ƒ+ŽÕÚ) î× (}§4P‰ò¶I‚ŸÄ§4!€-iÇ`‚Øe2åÑ+4Šè)s¥»pÒi!†—åñ¨•»UÈù‹úŠ”ó‡·Z&€^òDSb$~Þ™ÂEX„7]ûå|"Ôn—ÆœÒ~¥
+ ªi5oŒbµvêÈR%ÝÔ1®ÀpÛ1øŠÕ(¨P
+òÔ  LUÈ#ä4øÀSÙZ
+µÖwÈ~°™A3iz™Gé=”I?¼ 
+ 3»Ôö¥P9ìØŸ~f﹡ç©[Ñû\•ešªApÆg”¾Z¹–h™±ò0£t ‚WÙŒ êxf7ýÿÒuPåk¼N˜*'Ψ|zÌUh"NC_låϨÜJ
+ ë¾q‡£()Y.õ@Á{½#ò—â­¬'€B—ó¦³lÒPÄnF( €"ù,“¸…Ó"gDv  X?o¸Ãnæ±ïÐ7”[0ö?RЭè¡€ÙÛ?Ïx¨º
+a¥}æÝ_ {Æyf¦ð˜Ï¼g‚Aõf½+y«P«é .©6³^5 ‚‡sfƒ¦ÏÝeùB
+y¸jžÌ‡¾óØ> XØÏ|è ÂóÔd3»Lȱd0“f6ÉÕ ¨EÏ|TIJ8ñµ"ã)xt²áÉ|–û’Ø¢05”,šùl®
+G’Y0äi Âóôç‹žâg«Xøšùg{ô÷þÑcJ5˜ù÷a4v5O=dqºß̱ëЕh…íí‹•¬™K× ¨Î\é.K‚RîýI |VZç†f («Ü8´.8ÄbÖ€òÏݬd9æ4ëÂÃýøK*„#ögýšÇ¼­jSñ* í@Üf€gÄ
+c‡õ¬ßvk\»Y¿ÿÀÃÅ(8§BÍú}
+½É$C ês*œ@•¿VÃ9µê/€.Ë(¹òýE¥y
+.ûGƒ j4§ÊÃJ¥º>ø‘oN•f¨ª›
+¯×¹ý ¡ÜqÒÛ)‚C;4
+û¹#¥˜I6IæŽüUƒð7ÍÏâeIPªbsç¯@Ërø˜S¹)CÓŹ˶
+ ¬ì€JlŽX¾ó<\Öf´]5÷&çKÌ°Ÿ¶¿¯Ax?íãrÂŽK××¼DA“Ðár)“é{WP ÂßTx75/1ÔŽŸ[xLƒ ª=÷ähoÓQa|NŽ× ¸}çUr51ûP ;üJ2¯R‘Á]0oéó•Ìµ|´¥j/€ŠrJ SSëƒyE[5^eóNÊÛ×I­ÃVÙ¼Ó=Ï Í¯éFœ…Ü3Ø!4ŸSZÿ7ÔLe«†C R´àpÍ^Ô ¸Uæ·~ˬ!º£ø•d~ë.ÏÝü~n™\Ë6¹éQnºùý>7´ 6w¤r !CÈó‚ÚÏi”™ nqC’Ná9CŠÏ‚[6  XZ@9΂¦rx bSÐw³ºfÎp oßwÞ+€êýê G% TYPï7Tßk;LDcø/¨_(€öf7êT¨À ÜðëT[ù žr» ºQï ìîZðT 4< BT; CcP;wHGÓð¼ ]OÔ>=ED' SÐ~žáƒðòqvD)Åû ¼|J
+•³‚©ÖÒÂrP
+üáŠb¾ kT@¡n•ôIJ2ž‚Ð'hÅ׬ŒÆ)™‡Ð/\ñ­Áµ[¸òþð‘àçç…+?@ëkz®€HØ U®¿6ÂReaÎeîá SáOƒZ»0§Š
+6“q4Cد²¨á=,ĨèM›I‹Þ¯Ax2
+«MLZaü¸è¡¨á]ðеéœv{ð¢^ôÐAÔLµ"s\yØæ\ÔìA “ÙZu8¡°R_ñH^–Ö–
+zK
+h”ã‹Ï¨„T|ÛÂO½‹Ï<}nhÉWA¦ÇBRü °_²àI ‚Nª%«]©â¶(õÙ
+š+€Ö¶fs2F¥x°º¶dí“÷Ó’ JÚ
+²/MA‹ÐÎÖ¼U‚t™aÇÙ’O  ½³=u͉U†S°w®
+Z'€ŠŽ±èqbKŠN “n}:'4ì³[TW
+¶6–Öj
+akci­!%Ã… "zi­¿PÜ+BnøZ
+ „«´ÇO³Ï£ ½ç†–EÜ4¶„S˜ËÂaYd£AnÙÜrÄ©Äohgµìb ‚WÙ²†{!f[Ip2—5l­Ap,{…K;9Mƒb8´iÙ+?jþ¦þ*k.²Õmì¡YÖÿ^ ‚wpf{U†Ú\”öÌöG5ZŠ™oŽåíKAf¾9A
+SaCŠOæž'Ðñž£ÃžNüx•y|÷¹¡ååÝŽ:…< I ËË·@ÕöT1*K õÌåÕ
+ Éí•8´¯×N>[>ù4µ"7–ÂE˧þKƒàAXž>BËŽkŠÃåécЂ“ž
+I­íðp¥Ð?­ù¢N8)cP`,ÿç ‚WþòE®^ “ò`pã,_4R
+ eùžºf‘ð¾l·
+ᘇ>ÎËB% WþŠ [  ‹T;PçîÀWþŠ‹ÒпÚ{†)Eõ[ñ¯WЕª¨4½4’ôV\¹[
+²Ó´Ïø'U5ÎxV|8NAK(X³jü¬ApdÕ˜ä Vê
+=Ðƃš}V¢œá¿.y‹hw•ñ‡'k¦BX³Ïºë™€
+þ¡˜BüKw=›*IeÝ¥ÒÛ©¨t ?øgÝõŠ
+Ê@/¹Q&IGi7Äad½”£Axg¾´‡TÜ™Ã/íÓ <O/‡yûÒ m«µY/GP‡GùÚSê
+VF³:<&€:zy@¶¢e¨-˜ÕqªáýôJŒ·¯EqTØe’õÊí„¥ïÇ<(B¡6*@‡1³ØPx!«óHô¶››DIUäjÆãí±¨Ë>>œ)"†ïrP
+8ãÏ>¨Aø´ä Uʨ#2ð Î.€6ÏõAS'˜•›hѹ\!)d+£þ*ª
+š£Að¾[Un>o:Ë=Xh2W•ûG
+(dÇäô\5§
+:?ÂŽ³Õ5¸¢2õD š(¬®1P
+ ð'žT‰[¾šÃ<œê½ó?¡Ä%üáögÊ ¯N\¦AxïïÇz&Eì'pÇæÕ÷@»1ÈÇ·µC¼vo@ͳ'Xß-«›g
+ 7©áìE± ûéÍ_5î§5—/ñ¤/ÕT6@™Oðš+ž` ˆì`_€R =-€jVRZù°[Só2 ‚k·¦Ö#)!M­f¨n]Ñ §ª®îM/Å57´âe¡~¾|NžÌž@7~äŠhǃÇ }×ÜØ]ƒð‡/QžŠËÃä5ÁÊ/Å5ÉBO;Œ}•ÉtB
+þŠh<-k‡³ÝQ …d×ߣAø—&Õð„˜­þ>|R-tJUߣ*`öø­=Ð xîÖMç(8Ê¡Ž:¥¯›þ½AGìºùcØkwbÿñpóÇ  %[ÔV¡HOìWY·$W
+á‹z}À= ê—IM}áp¯²õÕݾ¸Ž“*”Àâp}õÕèß·³•Ÿ çgìD_ÿï»4îñõÿVý“îD`hˆ
+vÁ »”NçØx
+nØ«Aðo¸Ñm±å4t;Úpc;t“;™”ÆF%wñŒßTYƒðŒßìf<:mŒB†€n.Ô (X7G+ÿ“c)àÉ ŽÓ <™wñl)ǬÆÐ_„günŽ|¡&¼ACe² wß¡AxÆïûFmÇ6‡ÒwÃ}ß  ûÝÄœ¤SR-Ží– ÷?%€š¿ð’`–Aô4o¯Að6ßÐÊM‘ŽF\ß
+Þ­Î@­Ý§'á>hð†lhÝQ
+vA!»–œ „¸AØÞ¨AÐgŸýèe|¢¶ºfˆÌË~ôJ ‚Ò7»åYb¤øšäe·*­Apd·*Wòáá$Ž;Ìnu
+ mþpr &±ï0{[5tà+~ôá¬õd(Ö ø×mì¯b"a§ †¾Ð (U6þújŠéfh··ñ×N÷øÆßJ{†DŒJÆa¨¬ú‰'LŠ
+á<Å“²XRù²$.t½qÒ Âó4w.›$qzvĪÑƹ 4Ÿ–y™¬´'(«kç­@ ^v?Ü>R1S‘¨ ^Õ ¼3ªú*q§É=þë¶Ö ü×-îâ9„ì#…#ó6.îªAX®êbpJ…m\õu
+ä pchu]u¤¨Œ#Ú¸ú& Ô…•Ñ¤“b‰÷Óê÷$ЧJ°Ú¾á)eãꞨŸ'0ì킯׫ûkþëÖÞÅêZ‚
+‚&sí½h]E¥dÙªQ«ÿ×U@[j3D-ocØq¶qK ô¡7™I+Š/·tÓ |òš°°'uÛÂ/ðóš§BøFØtÞYÏòg91Tº´
+ê AxY*¨ä}Ê"À§¥òïȤò¡‰¨¡Õô¦Êk%÷
+Ú¤AxÆ«ßê-°}‘a…fSõ 
+ Z¥ÙìN†âÑ$N
+ȹao:r-E±
+™sÃ,tË:%É‹_¸rnÙ(€‚é’Tr ?åç  ;J®2jy eAÎ[4Ÿ–;]Õ(á” ôE¾ðpw^“
+dÁÝAÏ€[†«,çî°
+ ÆÓNnA{÷âyj¼C
+ùú½ò?ú€
+ ·ï¨B‰°!D5çí»P׺ÊùB­Ë±9™ÓõfÔgrOØ›ÎPj5§Oö¹¡ÍÍÆñdÙÆ…Ÿw67K@-ÞákÃQÚ±aº¹Å{è~t5Åñ¹Ûü̃ÈÝãŽ<¤'L8™›_n,€:°[¼ì!CY®Í¾@±2JoW1¬<lþà„
+rËüÌ“i[ACYÓÜ2¿  ²kY/°(M{ürËn@å\MÌ„N¿'øbš[îT¾ßw´}#xžrË7Ô <O]¯¶S£0ê«nÅÃU|W
+Eð[~nƒ¨
+bŽÀÀ>ú˜áÉL{È[+š4¬]ÚÄ¿i2wú$‡<½.cèy4Ë­µäTBbkóf…ÐüyÉ4¸òæÒ ¼Ÿ2T¦ŒåÄâá2ž@+¯ô”
+Åß´²Ú¹¡mTË6êÃea‡Ð¶P—kÕ¥htŸ
+ÉÃu¹Nƒà_·­·ògZT¨Û-Ûz7@}“„^pžòx
+úæh\»mß¹1NGÍ¡Ëý¶ï‚„çièÃʸ¡¾ÝXúnÚTƒðdrTšËøMÃ÷  £ªV@"jè8¸mÄX4JÕT D¾¾^·j¨APôl›è¾pQ¼o2bx Ý6qƒážt‘'Ä("oºIÿ@Óoa9I*¤aY¦‡Ð7,Íéïgh·mØ&€6ÿ õÆf÷¶Í?
+ \Õ©Šº²œ¶å¾«Aø—v·c…†žº}uøÃww@n ¨¨%ËÔ zÛ 
+CD춣W
+ c®k)$õ8‰¯ümÇökžÌÂ7<å–ªFÛ
+ßÔ |¤ŠÜä}Ê“‰ûc×x
+Š’¨X•ž£Ìî n¶­¸‚a©rœ»Ù’ˆŽúº´ò‡?‘
+fü¤ò<Ø
+–e(+±íd ‚'x{©—®»+f7>ÑSŠ¡ö¨¬
+2·yØp·l/{B
+á:YÛ+\ɡ§ñö
+W ‹_ä­%Å¿,o¿¸½
+­@,ÅíÅ/  ã¥xYèÖª¹ýx ÂûétM¾é2óuÌá?]ûÜÐŽÒî“ãŒb¡óeGéFè¢ïX…$áÁ!;;. €*¥ÔÃðWÖp§`Gåó4ÎøŽ+
+•ª´ÕZ,0v\q\ƒàßQµŽkHPY‚ ¡Ú쎪u%P›’íK
+î9T]½KYN0+¼ÍwT%€j°k)â>ˆâ¯±_ƒðŒ×Š±jd+íö„Bù´£VRƒ ÀØqu3¾¨ƒn$+üð«[ ºÿçm[¡1l•º]5OAì)w©°=…ÁábÏ
+ »YD‡T+›I;8¨åCî+.Ips
+Z¬AðnÉ¿ç€RmãÆÖŸÏa ‚ªvþîδÕ+{û¢OóX+€«¤<ıî›ßø ‚'8¿É쀪CcO&sÌo2O
+(€Þw&“NÍ—¨A¼ÿ—
+ëÅ©²±ØÙw@*„#Îvö›É¼c˜b#pg¿9„g¼?{ÃTÝ÷á<\ÿ«РOøz%h(kºsPOô‹[ÂÔ+â çá~雬üw ¨Œlû€âê1;ÿ~O
+(\Ý0\•»ÐÞØt#‹2Œƒ]wíí!€öàMA0Áîø]û?Ö (ìwáò¯T×(l¨¸ëÈ×o„]…»ùzMPï,¬´ï*ܯAp?í*ú% œyÔ /KÑ`t¶'»œ6¼ØÜuö«sC»Ï/ï jO ‡Û}~ ‚çnwŽî‡SêJÐÂÖÆîŠP¥*<™q
+
+ÆÆòîJÕ4.ðîJ9,zôàmóÝ•¶
+ KÝÓX˜Ü8†.ˆ»/ý—Aa¿û27IO5÷6@gP•%!lx+Û]å”
+]&€Úåðp '@
+ûÝí¶žÚS³£2IœÜHxZöÔ|UƒàßsÓ )“™Äaý{nj'€n¶Xñ ’2Š+¾ï¹9.€Â×(ÓÍi§o©=áëPlðT³)ŠK‚ì‰í@q*GS`¨«½'ÞH
+¢–öÔ_¦Aø¯k8Š•ËÔ²§áXôàep9aýPôìyð˜
+OÁ«WI 7•£Ã©š‡7Ý«PçIÞEŠ$±{bO穨‹×D!Dëk€Þ@]]-š’ȇ…}ׯ5ÏS×í¼}ãäØÇiÛ{ºîÔ h›ïyŸ³ÁœÞŒ üJ²çý‰„wÁ'+Ôµa¯¯¡ÂäžOV¦@qÃ}÷ù-ž2ê<Ë`(¤Axžz¹1íñ%eøJ8ðôj&€¾iÍê¿£Gbßážož@?¨^s´À¾''î‡/Ð@ÕŽž- E¥÷ ¬£Axž©=î™ÁNª=ƒºjÞ*¿öçMg_e~—?üׄo„áìÌs& ïw{†ÿ¨AxgN੤ÔF,lmì™Ö ¸}÷^ö›¸Î¥iïehþ¥—6óUf_¯aCW¨½/åi\–½í¸ÿ*gèW¶·]ôŽë༎¸¿ûƒ‚î@煮@ªè+L¬ ßPwnì@ΠÁàÚÛ} 
+úTƒð_·ÿ Œ˜mR¡öî?#€ýÁqŽ9>‡þÖ ¼À'¯ô„=M&Þ¾'ÿ­APëÙW–¸Ïœ‚}e¯@/•/¹€¨F†*hœ‚}“§{Ærد?)h¦
+©˜—eßÂ+Ð*×gq<B†7 }«îJ JÖ¾M™ÊìvúâÂM·oÓ
+´¥À3Éá5Ö}[
+P¾*á9­'ápùå4¯Ý¡wÜA€Rô°}ß¡Ðág¼)H† ÅEö~Nƒð<qŸæ"ŽËÚ´ÀGú  ÂŒ€
+/&*Yû
+  bÎ{ %íŽãš/ûŠ«  ã?ñö8½¡TÙwügt¢?qê•‚Ó‘÷˜
+áפý¥Ý ‰0•þ´°Ï~é
+ ê5ªHTÌߎ§ zmTûB†l2šøïSýK½ÆG[üáµ;¥@òþ:Cyû’C7‰ö×!ƺ¡09ãpÐýuÆkÞOÉužÁ• V÷ðÓн7³I'· VCöß{«áY6Τ=†ž ûëÏ@OÔ÷Œ: èAô¬[üˆ‚î¨^?tXïöÔa¡»,TÄÁŠáp†ý–¤Bÿm˜ºÐò– Q÷QSÝÚåwÁê#Øà¢Ò)I|¤T%€n¬ÁF }Ý›ò[ÜXK
+ 7KÜlûz¾y­
+´´ åNˆ y,¢©Ü9¹äápó~@ ]ïZ¹Ì|> na´RqçQOÁÊ÷S!\äàzˇtuà_ŸÔ ¼,›ÝBöÆ E­¾nžªAxgnSå©mÓ-ÁõÁmwK î)jH+·}¦Axïtk¾D)1jˆØ?¸óø¹¡CëÜ''Jo …­Û)€Ö»(?hrXZßCƒàV9´þ`À+kôóR @9\š€C-à ü¡œ²eæ¡í*9JepØ¡í
+ ùo-vÚ±[
+ `™ÂlâX5:úñÜБZVF#Á¤-{à_w¤VU ‚Ý‘kê•\ŠQ_™·R ýG
+ºKƒàp¤Q3έ±UÈ#Ó (UŽ4¾š'“ÒÂ8´éHãkP“¼U,‚ב&£4ÿRKu#¸ONx«´ì¡APªiw²ä˜[>ÇOA»3„'³ƒÊÞIPéH|éÐ6ÂïÁG:°¤sŠšú²RÔp4ïÌ®uÚÈE±‰{¤ÃL §¥“ºÊb¡¨©Sú‘Nå%Ð$VÜc…?¼ÓT ÂËòw”wÚíÚ©y«´
+ Wznùå“‚I Ç”Zk+È–aY^m%€Þ<Ä›Ž"ø Õ° Þ<¢APA.è:ÍSFmõKß‚®é„÷¸[ßÉ
+ 4J‡‚VYA¯cèë›Ô¥h/‹!±¹àë[5ï§!µøR¤z «FC®@æ+×R(aŠ*øs—Á ¨`hÿeÔÖBð‘:@
+‚ø¾+˜Ÿ#€ÿ Ž”=œ¯¢‚~J…°÷¿`1G0ÚBÚV Ç|ñïh¹UsZGjR,¿O¹í¯#ÔJÃï`TPC Â;s¹×Œ™®Xlº¬8OÕMQ× ¥ç
+VÜ(nã­Bª‘Ay(X@YC"¥=‚Ÿ0 ²†  •n"*µ%ŒEñòp*„ŸÄ V¹Õ÷ÈyJm±|Z•@‹Øœ¤@9“8\µTƒð¹[=%E…Œn©Õ3К)¡,WÁšÑhíW¬<Pyj_ vþðµ½кF|¨çˆ¡òOÁºGÐúSJDÓV1lß ¥$ÐZu¤¨ ¤áÚØ°A
+î–çù¢NPkoƒ‚|ä¼T?¨m1Ž§€"] eᶘ¤AðÃŽë.K8Náظ9:v¾AÅïè¸3ìr°ñŒ_ZƒàŒ_Ó[à¤e(*}t|m ÂS0ٽʒÎÃcoߣ“Ë
+ ©!VÿcNqxÑ ¨j1!’Ò¾  @³Ý‚LTL˜Þ-à¦;:ûr4;óY“øÙâèü]hÑ®`u`„±î{tÑ3„wæR7XÃq.… AÁG—nÔ xQ]æ9ˆæoÉÍÃ-»Jƒð‡/»ÍƒÈù‚²°
+ ­}øÊwܧX…<ºõ´‹ƒÌCœ6H•]«Ð~wíNƒ_= þðýQt¤b‰‚l߯xû¹äÜб²ªBœÚËâ­r¬ìzt~/†¢¤bá ©cç£Að>Æ ¥ Œ•¬cèZÕÿ.ŒŠGòp×v@u¾óBÎc6®Î÷Èv:?D}ÏÔpc$òÐP¢¼¡…ͱ:3%·P¦È S›cuæI å¼,ô冖HÇê¬@×¹ßw|E4_ƒðŒ_¯Œå°Su OÁõi<ÁÇ®çø'*@2d9»~¬áýtý>T¨ÑPäØõÓ5ê*Çnâ Rý-C³øc7Ý©Aðn9þ# \•1j'3<T
+-€Œfc9JïØX>Ö`l*„;ìk|O@µ> ¶‹P];Öø~Ôù€WB4bx£>ÖùýsC…ç7ð„}Äop•e¨‘ÁƒPXáïJ† µ–
++Ü"€.ªâ„d$›—^t¥
+I fªLÈi[§ Yô¸Jow
+ñc%«ðñ?5ï‚–KØ ð½8~o)l™©Ax´ärS$­®WØr›
+ Í*¨%A!nØ“U´ùg Âó´•ké’õe«*è2”»Ö=h‚8‹r³5Ë‚ªE)]e¾ÖQ
+Z+€váMGÏ…–Aôì>Oƒð_·—{ò‘GÈò¥±)è ‚›®¸ì'|•QY _a˜R }.€Þìm߸•ÀSPÜð6ô)—ž£–·ÑvŸºCƒàjêm_ûbÄÙŃZ !Ü·›R£ ,‹‡¼%º²{"Š„ W~ñ÷Ð0 ¡ѤŽÂá†5@#TDÅ^&±8,1EƒàÎ,5–'“& ÁÅ£&hôÐOní©$\Áá&?%°2v
+›âošü£
+ …îpÔÊÕÑ àp W Ž`t݆ȗâÅ¿  Ì †hŸÀ‹3¥BX÷-Îú“m9Ë 0²þÖ ü×eK1–ƒø‰ 8«X
+~©rií—à.8^ÙËÅ¥ÒÛØqv¼òE„é²¥ 9],Ç_¶\
+NÁ‰R?
+  Ü䎕K\•'.è¬Ap
+N\x«Ú§r
+TµO\ø€
+Y´Æp¸žÓ x·œìÖ'ÂõÉný´_‚;óä×*Ä‚ššÅ°§ýä×ÃÐ÷ù*£¥q,UN~ÿš
+ ÍG=%+5˜¸'7iö§~äVTØ4’À.¸S?6× (éN )£„==ã›óÔó%êëFŽï06qO i'€þ.â#åÔÆ-¹Oý}<ž‡S#XP໩¬Ä©Ïj<-§Æs(
+%ë-òŒ?¤APØŸš cdâbÁzjB+ ‚7ç© å%7sؤw*㤒`(—Ó6$ð‡/j«ApûžZï&-XN“aC³øSëhS)Ij’‡HNm*snèt)7d‡”H
+5‚"út©÷PÙež±l+~8pëtÙåè¯Xi§rç>³›‡»°·Aõt…’»N/m8\…nøte7ŒÈrvØéyºò\ ÂÃ]ö<›¸áS„~øe/  Ë÷¶o4j¨¥{úòV„wÁå/JÂÕ}…‰Õp/  ë¾æcn«YaÛâéëú  =nFvŒ’ƒ†°þÓ{’„×îÐ0o©à^»C£4¯]¡ë뱜¢ †gúÓ…PQ”'“R ÁO%Î )u Î(Í(º;Sª®ú€·/¥F°søL©n¨´
+)¤jˆî:Sú„Áy¦üGJ] &L Δï®Ap«œ©TV]ùôÔ‹CvÎT*'6²BuràA8Ã}–ÿ7ty_ž‚½(âçç3—+€X`еahÌ~&ÐY
+Ýa+”Œž ÏT_—
+aåáL Õõ—`$ÿŸ±3ó©þþøØf c²Ì Æm†Ïçsïý,¢UÖ"¡TúÒªÒ—"¥BiíÚÈ’V"¢hO«¥úR¢"K$*¿{î=ï;Ÿw÷õþÍyôÐ_ÏÇç¾ç½œ÷9ç}üÔ{¬I®â¾n”dkDZSáX“PóyÁÀ]†{€kþœá1µ¬V¦BÚ ¬®kYCƒðd¶<ÊË’p'ÀPº÷XË4ï§6¹ TX¿åJCh•ks‚
+Øñ“{h\»ã§p]m*_æ„‚ñt³áÏvVÙµ5,ðñÓhÜ*Ç{mL7Š(„Šßñ^;Pÿ¾ÁÀ#–ÁÄ=Þÿ,4´ Œ˜×.李U$Pý`àŽï¸Ç‡6@*¥Ý MÄ&Éñ k KJX°RÒBè]JA  | קó›‘aµöø5{ÐuÜ[5FAi1lH¿î] ‚zÁññ«µ”Žšu@>a¥ÝK;Âjíñ ŸK ­e<•ŒÃз„ÏÝDÿ™>AÏ®<Ä <±¦á1Ýêk¬Int / ã·Þ¤Axí¦öT&.e â[êøÔÞèN?¹#E33½?~gÛt'¿óFÞtîUí
+D<wÞ¬AxLÓTVWɲ aiǧM@wOQê¿‹ÅpPËñ»ïÑ ¼Àw¿]¶U,Cªãw¿#€æLTj-¹P±ƒñøœI„ï»y_ñV¡²†`²ãó¾@K—ñÀ©Q¢¡—øñ¥+К³JD“–!Áòøš„vAïŒvþã•×Ô™Þù0TO
+µo@ù•è‰Æc1ØáÄ…ò5^¯¶qO>* ãà˜,)€~P©È&.áBE„Θü¢ ¸,¼ í@{‡±éF¥’øʯ°÷R ›îÀÒžpUmdNºÐ4„
+G l…›äñÀ ?U3Òpù2ê¬AxLÇâl&YÔÖz²\¨£ÁÏU¬X—Åñ$4ðŠsPž§ˆ×nk‡«ä  ªª_ÍÁF¨Xõ
+úC
+ ÉwèNJÿ5@ŸjÞ™ÜÓ@9óâ.œîB÷  Ç
+\&V4”ˆÊŸ{|OùP¥Ö¯±B÷šäAÑS©õJdíð¯2O}’UÐ/ÅJ]ãìZJzðpVêÚQƒ |ªÔÓvµ½tä8Ìrr¡Ndø¥“üöZrãÒâ.t²â~ež¯2Tð„§ g/tîkÁ»ö¶Í+»B
+ïà*[°éF—uïÌ*[Ï@;Ïò¿˜í©FpûVÙ9P
+ŠNà'(J
+_e™EЉ×ñµAÝQ˜˜ãB7¤CXýÏlÛ'0I¨Ðb™mûiþœu§ÿ9/¹#ŽÕLë ‚u¦ÅUå¢^: sÌ´J‡`¬vïÌNªÓ‚c~4Îì´&2ÌxéIawu?¼}K»  ®“x«P"ª!81³ëät;_2»ßÍfÚ„ªõót¿W
+ Ö¾GàÂ[*«uËt¿Üdµ£¶
+…†cÇYV»ÿ
+ Nô¢ÄH(”WA
+ 3¹X2…#9¡ì<ð3  ž§§)~QXæÍ…z
+ ^ÕõJî.ü\˜Õ«‹A!–Õ—3-¯áöÐdõ%€ú](£T@®ß•BÖ@K©FQÛÆ.@ƒ÷Õ5¯Ln¨4Oæà£OpÖFJ­¥Î…øFÈ’¯Aø¯» apQÇÝ;Oæè“Y qnC³.<Mƒ Ö“uá ¼,Þµ=Y¾$€†ícÑCËbx\Ïv@ƒ ôÍv˜M7×xBYÃþÐ ,z.iË!j·‡ëgºP{tY#¾ò©Bn,êBù½kYW<ÀÃöJ3ãµ»b¦
+‚cqøÜ Â;sasµ}©`œa,l™vÁ¢ÉJÉ¢L–µhª
+V½¨APi¯ú¦ê,D Cu×Ô_
+kFñ”]ëY4âõ
+ ­»XƼX9¼v[÷ ïüè.òr8–Á}šý]ô^ ´íp•þܳЮOËB®Á…Æ®/О÷ùprYD }¤AXªìù­ r ϪÙ{~× ¼UöÕá‹:é¥ á#µ¯žÁ›3{ÿ9Ë„šà1í$–±˜"ñƒŒÙûW y|¤¢æZÙš ƒœ&BQ
+Q\€Ð…zjÔé²®”Ѹ¡g¨ ½%€Wc§58ŒøpM ´)MôàF!.ôµ
+ ¾ª•ä
+ Sg³éFQü”RíÔg5ÿuˇžêÈâeY>Lƒà\={±2“HÄÎáêÙKPŽÌó ,lÜTopƒ
+UXrGq‚eõ”
+V/î,”âGe¥“†MW¼^
+òà)p ‚’®º£JyÃöuJ5ÚœÕ;õŸê1á#åÜ#€m÷9—àµQ=Q"€’þVq<s ÷lp¡÷PG~¼òÚ£ÅñÃcõŽ­5ïÌN6
+08=«wJ  .×ò¥è^Õ–ƒ£«w¹Aƒ°À袚—P‘C4sõ._§CØì®~ŠK%© @Äàˆ­~Ê è4•J*dÔ°}O«*€z½¨”,Rþ°§½z¯W5©³Z°B5v8q¡V„'³ÿru¤Ü‹,bø\ÿ•„ÿº¾s¼d¡P©  Ô üKƒïäe‰Q¢öBV|·á[jÈÛ¾‰K%6ÜÁ…Þ@çEqè~'zU?Ï@ªúµ˜5èž.€®XY¦E ª_±J
+W=Æ‚5çÞí„é¡LÞ¾äŽc·`ÎCÙ„ÿºGÛ¤)ÃEóh;ô¸¿3¯åˆS5s_©APÊ™s7ôÂ>±œ9$Ð%¢#Žm(×™3gž
+3¤Üç,¸.ÂÊhÎ2¶è™ÈT+gY‰§\,‡_'s–MÐ ¼Ÿ–_í+4^ñ¹P)CžÌå£ÐÊ‚K154ÈY9N
+ ŸýûŽš{SÑ(0jü¼=ÂÑñ5öÍ Ü8V ÷us¡ùwfÃuË®×(n±åBõÐïw*—I4Kà »¿ß­Ap?Õ8î§Ó$hûÚ>5+øA-Ô
+O@í|™é?;z9ÕâŽ^ aï­­ýÓ<ÅlÃ<u(@ÿIÜ{Ù8‰¸Vä;d«Êddâæo.TE
+® Ë1$XÖŠ"€N:³zx$• OæI½P÷Ì4ÓÍ`˜Öêž-€zrÔ7Ý
+¶Á[[«ç˨—êñHŽŽP£m× ,zzíç)H¸SÃ9ðµz@ç,ã›ÓKÇJV­s^@ç>Á’.Nª6T®uîShÐ6àÉ4¤®Ôt«
+Z©Axíæ Œ›dľWkÞP´ G™!1FÔZÐ[
+OÁä| ‚›®ödv F<*>µ'ß*€f¶daïuÞÁŽØÚ3[K Ž„˜áR¬ÍmSÿè1Õ ‡’ ¾öcÛЬ¼À1zòÇžöÚ³,ôôc ÑdŒ¨ýô,ô|v*¸[%ŠýWÐ èåż,Tv9‚âj¿¼T
+Míoúhþ¥íªÔ*F¢koÿ,Â}$joß̦‰û(~rª½ýk ŸÛ5‚•÷Êpí|•í•’ôjº(m í@kº¸|¨Î`®qFÇ<jc¯v´"v^ =£. jôr¾(È@/ kœ¼è:_ƒà<ÕyÅb…t[q¬ÐÔyåZôj +£¶·JW#è5N°ŒQ€qÈwÈŸ{í3´r_eä¤2”Qª³ò`:d˜ÌÕ-‡P"ÜæRA­Ó!ÃÚ­þ›îÕ
+÷TÕÇÐ[ªL®MMб
+Yç­ÐÛ5PN*J”‡auÞž%€Þ™¡Bî¾KbçKwÔ <™g±`MF©6 Þ*WÓ èy¨ó ‹CÏÿfx¯ÃýÍ•ö:Ÿý‡M2“ØÁX糈k*¸JèîªóÙ-„§à ?¿…JAxþ åJ Õ ÚOÀâð‹wÐ毒žÍñ¦Û¼MƒðVù¶O&u¦ ¥B)(W
+ Ý±ÒîÐÒ`§gÝÿ‘@Ü$J)­†šTuvÒ ¨´×Ù·Ž/q¯\ žÌ}ïjÓ‘D™ZëšæP«s¤“
+Y×Y%€Îø…½Ejî¤W÷Œß5ÞuŸQnœ$µÀÀ…«ê>S,€Ž(7N2š²’ø¡¨î[ƒàAÈÍð)!JñÉ`ÈÑ 8¹Y«ý&3Däf½¥Apç6ð‹‹Dc)/
+î‚Ü×H X ¡f†¦°¹ Æ  ‚âÀÑAŒxà4î§Üu̽Fy†y*8*€ŠÊ
+|Q8/^ࢇP«&lº‘{"efn«f¨òÙ§ü&¬ºH
+é•
+Ã¥xr/ižñ$»ã½V‰†&/¹É¦dø%nߣ))í
+ºY
+•Iâ5‰€F`î-Pß›Xy°¼XW<ð¾4zrûùï^™7WŒáeéW"”ˆ¦Jü œ"Ûo¼á¿n2Ij•ˆµžÜA' !¾Eí%ïGCŽ}=$€Îó3ù(-2n”‡ÜóÎÕ <çùyÔœØl¸ÊÎ[/€.~˜…=•˜1ä›ç^üx:„ý*¹ÃSºf™Ú1äï¤AP¡ÉÅIU$ë­Páø¨5OæØÙ<pW"FCBøscŸ•@{”‚L%ìp¹Îܱû4ÿÒ\·–îŸH»»rïì'€îÍæMGÍ& E6sïÍ)ª×Ç_;jʆBÃT*€Îµãob Õ (}ë ªŒ@/µÞõÓ üKç?¸'â‘Pó=*€.\æ_¯1ræÚÖ»ðut‘z£V¶¦e¹h›
+r½É÷ )ï(—JàƒPoÊ„ÿº©M”8¤ Í° ¦6“@ðUfÓÓ’ª7õAtßÊÀµDí•ð¿o•á9ƒ›xz%w =êÍ"€Vu²¯#þÜÃ+Ð#·Sà„€SðÈdô˜¯®Qãc2—ñVy¬¹baOI>áí@Ïr€›+žáÒ½<Ï~«Aø´ÌíÎjˆ+¤MMaëÍ==¾žzK—ªe!½Ö0¦¥/kÓZ•vD)>†ìÂzk³5Ž©þº,ÉMòþ+(¦ApgÖÿü@àZrçÀð¹Ï@û¸í*;Ô¥5ƒ¡>åC rÊ"Ψð4nä\ €ì?Y­õ£Ú¡¤k`ÿ¥Ap«4ˆûIz)j 6Ixàñ)èÊ_•ˆ²0tXƒ Ý`w„•‡-0ŽÏl°ÛÒ ¸ žöŸÀÑá%¶bh¤ÁíÛð4ß’ô
+§'ñ‘jxÚÃÞ°gM6“’^ä,œ§†=kkÜO {¿ÇS@êšcCöþP
+š/€®¸/E*,žÂÏô ¯˜ªAPWi8š- rÂÅ %³Žž§AxÆG¿ÄBŒZýJˆ6ýª
+úTƒð˜nã˜,
+Š°Lâ𶩄—åöø Ø ŠƒÞþ“
+ §êÇܦT/ø¹§hüëÍåŒ"*Ydšx6šÛY
+ ½u¨P^ﶆ˲·ž
+Z¬AXìgûŽ¬›H ‡ò6ÚÿŠáMwh«ÚôÔÚ™<‡þ£Að˜7®|¦‚¼c7]ãʽP•l˜Òç åðW¢Ap?5δ•ÀˆÆ­Žyhœ@YðÀT˜_Š³†iž§œÉ<ð”×
+ Opã¼>Opã&ªƒ%R2\e›œ'€šm,SµMmä7Û¬Aø¯ûéÁÀts¯2¬<4þéQ ÂcÚ3šNí& Y÷Œ@‡w²Oá †óï@G¼· ŠÃ&eíß6'/Ë‘Ãè(þôb
+C 4DƒðVù[õP£b†2ÞÿÞ Axóã¢ãÞef(*ÝøXò¡¼JþS vºõádæUzB
+}5$æ=Ón©¼Â…X^Ë"^`;æ%cèD Â[¥ø ^`
+·2´ŽÊ+^+€RAx±;t ¿,ç¥þ@óX…ôÚËâ—å¼Î¨Ûÿøsþc¶J·mèô®l,{MU°Ÿwzw 4+0L혡 @ÞéOjþ¥ Œ˜»… mòzÄЙªU"5D2¼ºå¹A
+PßѬBÆÍJ{^ßë4©ÿL†(@Õ1ˆÃþ  óù!æ¹¾q᪼ó@ÿù¯|rèz€äýç/tÉ?ê ¸©k ]š!敦Ž!º+ïÒ…h +È1
+" y—¾¨AxLÃo dÒ²ðç†OÐ ¼ŸF]Ç‚5NbÚ°ŸFÝ AøsWªv1d™F GêÊ„?7FiÑ”²k(ž7æ<4±¬‚kµ`#0oâ‹èÕ`2“–é–š¸\
+™^{ÄqÑÔ¼„B#ðŸÿˆ
+¥±9–¡‘vþØOÐÍÜ‘Â+Æcˆ/È¿y´a©ró¥d¹[ÅÚ”ó:4ÉÆñt;ÔtQA¥CøÅ4ÿ¶=ÁdÆ(JCû$ÐA^`WŠÙ†äØüÛ~@w²™B¦è®ü;W  {T·mÛ •3@ëÐýSØ$I¹…yù÷ß%€ÈS@6¡’´
+,€fZÁ1·ÝCe€ ÂÝÌ“Ò>gÂÌ“УcÙ¤ÛÕÆNôüGoÒ |•=í‡}8ôDàþþÜÓãТ)ÊùB Ÿ “¹èn Âó´ø;%¢É«kP×ï@K”ZkyxñÀ—Ü«Aø˜¿¤šçR©‹6'ó_Z"€^oÆëy‚Üò_o.€V{nAïxº—;Ï_}’
+
+*VÐ xK«v T2à X Š«k¼ƒ ŠÛ²À w|?«·× ¸Ç ¬Þ,ìÉk0 ¬~×®ÀRÔ"/ô¯  5ÿu“9ÿŽ\K1ƒ]0ù½tkÑÜÍ+üi2 îý^
+ Çü«,å•6lºÇÎ@•°÷60^–Ǿ@ó-µP6µD*x|–áÉœu…2LÉT¢§`Ö5é¶[
+žòËS'hÝÉÄ»à©_5ÏÓ‚í|Qǽ-|¤ü €žO‹Ž· IŸÏo@/M ŒeÏÎ…âð¥IhÙ%<™®Ún:Ä,¡Ax2Wp“—ˆCIéØùR°b
+W|/øî¨
+:K
+¶o„ÂñáÀw·Ò ,¢÷¼«Ìn1´.Øó¾
+ úÓ/åCM²ÎfÓÍv-·N5h’5Pƒ ÌlÚd+C ÷_k¬M›|'€z=\e)ÒÑÀ›özAƒàÍÙ¬·l£âl”{„¡‹5~®YÿÁV¡…1@«ÐÀŽaš´ nœf»hø%³BãxS
+ͤf—\*€ÆøeÉ¡K áöm6f¥
+[½¨ÿNÄP4£°Õ2 ‚ËR8²3_Ô""Ž½!…#»
+ [ÿaÕ(E
++£…“2Ð'›Ž¢ºñçîh¤Aø—¦ú™2^¢cx+œºJ
+ê+€Ÿ THzÈÆ•§ ¿U
+±Âç,´Äž¦ @js }Ñ…K¾Ò xß¾x«Ú~Iè8+|ñ?éî;YøÊUlpQÙÏPÀ$ü•Ñèµ+ù¢âe¡Â
+ºF
+ß©'€ÞÈÛ×kâ‰m©Âwk>Ž Ôòéâ8^ƒðõúåÿøs®rMâ+¿ðËïÒ!ÃÀ¿ü•=¿‡KyY¾<,Ž²è¡ÂOVá—  A\BpÑûÂ
+ ¯>QGÊQCI¯>@[}¿/…Ÿw
+·~ AxûnS]ƈ2¤#n‹  ïçÊƒí¤ Wþ÷óÐÎoøR¤ðâP
+gª) ×Pœ&RT¡—Á]PTé%0( ßÁE•žM‡ð\”é?[D©˜ÅÁ‰E™[P–ï£ 1îÚ6ðpe½ AP÷-ªª:ØT²‡^U­Ap튲»ñ1§„ƒó¥(ûTTƒÝ8îª |Õè®Ap«Õ
+B›"TVÊ‚¢ZPƒ1J¡‰Æ,Ckà¢cPÃ%ü9’«)\…¾¨áK¨ç&Q‚OÄÐö«¨Ñ?¨ðÚ@…¤TyxŽ@­|½€Úí¹Æ$NÕ,jÕIqÃqréÆ Ù`E­n@mTô)=ïRZ‹Ú@íÚ°8Œzþ¨D
+ ~jñ´-€æ)!–¤4TìØo1¯Ÿ:‡˜,c†e™w®
+p •îå?÷„
+úG
+zGƒ ÖÓòýóƒk#j*MÐòý‹4ÏÓCÙ¸±É™gø¥.@r÷v2oÂ.ø‡ÐæÕ¬þ'¨„ƒaY6¯@_]À ì%–å«‹Ð×ø˜S' ƒS¡å×ç
+ ï8 É+~j&ÈŸÛ~ ¸ƒSvç¶Üþ›
+Ÿ`êÖkhìÐòÀé„Oð‘×Øz%¯vÌpåY.€Ž/âý” -Ú UŽ¿P>tâ§~•ºñN¨¹RCŸ  /ý×IÛËm0TB8ñË…؉›nL×Ä°-u⦛5Þ-'îäTMÚ*NH(¨DƒàŸøsõ4Û<T‡FA5ÐÁ¥
+¢Š¥X;ñàËè×g}œâñç~+€Ž4 ¶JÒäW9ñHsôg¶9émÃ`’œøgo ‚·ù‰Ý n)ª3Š•¬ÿºI
+ z¾^@yŠŽc(0ߪ^±Á]Ъ¾ªA¾ÃÞt­ê¿§AxžšrSXŠÌ‹„ú˜*¨Tƒð<5Sª½À2h[5k£Ax
+šqd/_*‰ß[5;Kƒ ômÕªˆ!Ç Ð„â°U«VÃcZµóÝ‚)Š‰Ž„Ši)è ¿cU;æP~£n;]
+zl@=¯çϹ[.Ü'?×s¬Ás׺çQSÜa4ä`TÐÓ(O^|&œ‚Ö­ ’+}uͯ»†§ uÉÕéпeŠ¾|.aJ
+ nmXuÕ>WàyêV"€ú=¦<448Ưu¿§Ð
+ºI
+IõU’8~¼]æQ”ý
+ÔW­ÅnÁv'Ü¡Að ´kìKߤ÷ÖÄÙ`íçI _`П«=áø‚v@MX…¤§X»ãÛ59Gƒ ,hwâ­aj‡ëÙ+èv ‚ò©]ë·ÔV‰x50´N
+ “ü''÷ìÒøÙ¢ÝIç îùâ÷×ý÷²(è ÂçnÑ/Ê=A5 ;sÑAtðÿ˜{â>hß;øX:dø_Õø¢Š¬†ú*íþª‘áâªJ–m[øR,>!G
+üws¯_YÄP̽¸ ¦Á ¨¸Mo:ºòC]Z3Ê@í†ú[ÅUk-JÃÐE¥Jq‡Qqã®2~x,îp•
+uÌQÐ#龊»©Ž¨ô,cpÇwûL
+ ÞKÓn¨CSÜûet¶ßDz?»¾Í‹Ïž¦Aø—.Ê+û\ÄQ|Q ¤±yA`X°^ÔJ
+KÁd®†T‡ú«Ð 7nœ„åà]Ðá„ „ç©ñT¥ÐP¨vwh|
+*ŒcM¬C!ef‡ +°
+I•RøÚèpa4L9ö©¦BÄ°U†× <ð§UwïÑ_ùž^#€~M²Z›¤ðpl˜vøµcùP$«¬+¹åÊ0ø¹HÖ™¨_h~”É`è”{HAä
+À½"¹GPÁÓ,XcTû/p¤`¶ÁciúYÙõê:6Gš~)€š©î~©#‚êZ¤Ù ÂkW¸¥Ì©`ÌîHáÿЉ~²×óʽ¨áœxT
+Õ•ñfhp TIð¹!7(ƒ+’ˆzG†Œ@ÃÇ¥9„XŠ Ÿ €F°vÈ¡Ð쎌è®AxÆG<|.njUFFÌÑ ,Gªçg*šacïZdäF Â3~Ù3e
+²ŠžPÐ\ §el°ÀQò+àe›©AX`ŒõíêÅ–2¥ÓDÆÖÐ <¦q)Åú¨á
+ {ª’tü¹›³5êãÑ[ØôÂ> ï-Ñ[  {ždmӭ᯻ç4C½·Ä¼nGPôDgÔÕ <O³|;8Nþa5DA¿ ÙUX]ójàÂì, Âûiö†2õ?üü¬ OÐœÇ5ıÑšó„
+ƙҎìÏk>-ç]]¦dY†· û¼Ñ„é‚xÚ|bö) ÂRå‚Ç!Få}ñV¹àItýÄ
+ws…=õG0@7H 5|½¦"¶cº6^y[ƒðd®¨¥®2*†‡m)gE´îÌ@D“CÀ
+5PV+£®ògÊ”$²š¦C8õ7‘Í-o)iÁ”GÈÎ’@—cœž‰ì+4îÌD5Õ£ˆœÌ_t¢ZëtËñD¶ü9j[a‰%¨¦¯û&È)N8áɬùŠÁèÓDÍwÊØNá0ÇDÍ÷Pîh5ð˜·Äº^
+º¶|(™ÁG*šˆ¸_Ãî‰dFD
+Æ:]²`•Aå!ÙTõ¼¢NËñdÓ_PaÍÀ=‹„ÌnÕÖ (3“E5”{"
+BåT[ƒðÚmI3“"ØtKýOƒð²´ª¨kVÌPö&Ù*Gƒð<µ™LfÂäN¶yX
+ V×’¶jÓß×÷ËÓáøÌä‡4î²ÙþõJ!®í Ý‚I?‡«èšíB“²C—‚vjT’ÿý21S¦qò¿[4ÏÓ̓ƒvåv-%o>O
+V>”êÑ™NÎ<C«ÄT®8ÕóR¸;™‘¶ƒS=GiüëR½}7sŠ’`¨/9Z–Tï‡Ò!¼À©>Ÿ(qHφ1õù\ƒ ÌLõý#¸€’®=‰'³ï?åSê~êõÚ‚Rçt@çþLf2f(zŸ:÷¨áüPÙU19H ~T
+ Ï2X°&£I+ŠÝ©Ï*  ¯”]N¨01OæÆåéÎJImÞÉSà^Ô”¼?·yWùPÇTÉ"z"%Á(h
+rç+ŸÕ ¼ŸÆ–ú¦›»Âq'b‚º••Æ»ò¦£²cìy(Ÿ¬Að¢.í¤"¬©„ƒ!å¾´SLƒà.(íTÖ¯Œþ C÷xiwUUÎkåŠK»ÿOƒà—žò-_ùî^1Œ+=e‡á)è³98œ®°Ç ¥}¾@ýª§‰CÔÒ~µ4îñÒ!+å!á°–yCƒà/½`$«kdn(+QzÁå袯•aJm SpÑ6t ËL*3<9•^òš
+tYÑ1cýñÒûoÓ ¼ ðkP`„—DŠ¡=èÁ6eÛ7ê…© 4«Ì×C•õðV™µ'Â6Bé“-X5Š¸Û×ðü\úd«tÈðKOýê¶kÛ™žéKŸ® €Þ>Ê5%ì†J°³èyû ‚q]šû¹Ý‡<‚¯.Íj”O]š/&“BTá‘êÒ|¥Á=Þåºá¬B’+'T ‚~Ý( ‚SÐe|]
+<OŽÁaÝeü hÆ*†¨ @((XAkÐCª¡/%¤°þÔå¡)OK—Y-± 2]fµ@Ïl  „JQÐ4ûÕ2¥ÝT¿ Ëì×5éù^Á‘JšŒÀ.Ï÷Ó <¦XϤ¶Î¶á³Ë ‡4ó.«&²B“Œ$lC‹­.«n@o¾–vQ®ü.o®@]Ë[…Ü‹†ç.]¯Aø—¾¸’EtŠ¢‚±ZÛå‹«ÐæÛÒ/ Ø6OÑ <¦ï¦±ªM… Æ.ßÝ'€~â2
+ÌGâ¸ÏM—Cµ4Úw]¥+†²7]]-€Ž8lÜP’ž¡ìr—# t4?0“lÇÐê§ËÑfç©k¥û•+ šr?·o×J34Jß®_VžKÿ e0ôZ:„ë®u-öŸœè©!éÄpÐ]×⃄~}Wž¿?ž‚ë»k”™]·ÜËBŒŠ
+b¡Lcž‚E»ÐæïÙ‡a{Åü` M·Í?•õè¨ütÔ¯,Žuº§hÜã=†ðAH‘ÿËÌÛ
+ ©Ê*£š
+†¾¸=¦Î@O¾ÄJV½òcXˆõxò5 ‚kwæ`öĨž˜ÁnéYp¢R!]Òð@Û³ Aý©çÂef·©
+XÏ…£Ê‡zUÎ ôÌhÌ`À÷ª\Uƒà¹ëý”ÁHMšÜmŽ­×ÞOÕ xå÷Ëò_$(Ì‘Œ.¸ŸúeÝ €œo•™D<nvÚÏù>½UûõRE!•ÄjH¿^¿
+ ¿Îà›Ó‹ŒÀ±kýþêY>tÖù¾ß7MRâ'¶ÊÎ:ÿ¸Á|Ö6$(°ÉIb'ÕYS¾@OúÆžV.UŸÁЩåCgwùU¦dºáÏÝåp:„#öÏî›Á’.I–96ÝÎî[Eƒà-Õÿñ!ÆJzÜãý¿H
+Œ ¾ò_]©ã.q(ÙZAo¤CØt»øì›X¡ñœyØ*»øì‰Eôųú0DšÂ1~Ï Apà—|9•/Ť«E†Rî3º·|èÒü |åǽfñð¯»4ÿ ‚Ýð¦/¥ƒZ;¼ékhH) 1zp
+e€d0ÔM
+‡¥]~÷©7Ýå?FX5r¨>œ—ÿh—þüW^
+ÀupTÀèÏ× ¸vמV‡ÕW¡±ì¿ö´úéº%~‡8òùÆb6Ñ×-y©|èú;š±`%?VÈÊ`¨…Á1]?+›Mòª_?+§|hL¥?Ø$!ë5ä¡É`è ‚r|Lí VC"‘”ejS»RùÐ:‹Ne¹ rü¿ ,{¥zr²H¡ÁGj앇ˇÆïml:ËP§¿·XƒàOXvGpÌãT¶}n²;5Þ涞̧ þ6I&l=½|hb±—JîtJf„vËÄâíÈ®ÉÊă|¢]§|è–ùãYñó o觻eþD ‚ÇüÖ*~0n;­[«ü¡Aðn¹uç=,0è‘>ŽÓ³nÝ9½|è¶õü­â’cKñ¶ 5ÞÁ·õ. L\2¼¡f[ïVèÍ~¼,)ô”R™¡'óö{8íÈkeÃ6çí÷¼[>4原Yi·¨i.—0åŽ}åCw íÁ[%qÂV~C}Ó!܆÷®Ÿöó²P[PabýZ>t÷9çòµá˜Óî>ç<4¹‹hºôcÿV²øs“-t'·—¥öV¨±¨‚Ö•ÝÛnšÿ¹˜W
+_¯÷¶»?ú·8ô¡ûJ*5„J§cµö¾’ßÒ!|·Üö÷|mPø´T÷Ÿý£
+”³Bí2ZX>´¨ôV¾^îUf(~´¨tŠÁÉ\Ì]îÝ  æÞX÷]<¶ª
+^s, uÑ ¨-yã»@­¥f‘h§
+äÄ2KÖÐ (0–lø;€’V¨ñ CŸd ]‘ÀàŠ:œ˜³d—á4¶>âú*^lq¨ø‘‚Æi¼ï^>¡.œj—…DOC'”-?ãƒ@ª‘á–Z~$®Apà¯×ÜÊ!æ]ŠpÓ½^ó;”·Œ/ J¬3”8~=o¥
+e´ž·f*z»ò—¬ÐP‚¡pÕÛ•· Í Šz‘¬øs›—”­oÜ;ÝÑ/ÅõÏ@ç¿ÃËBë1\žzýù¦A¡ sz÷›Gù xØ™÷î7O
+ ßoTæ¤çú†»àÝßÇkÜï}å·÷ Âsq;‰#_Þûêc ‚Sð‡«'-*jÁwð{ß>]>ôáüžÁUfÅ …<>œßWƒà.ø¨r +Þãú¿gC±ò¡ §½ËŸ£íbèõá´4Ê‚ ³ï
+ÌIÛ6´ŽÚ0û^ôÎYJ%3[ÔÞ9§|èóŸ‹Py[ }V>ôEf}µ,¤þc#ð‹Ì†…ý—ûæ+ç %wà8Œ/÷=_>´±rCv™ø%-ááÜX¹@ƒ ÿicÑò2åÁ”J¾±heùЦa×ðá$m(w¾iØõÂæ7_gȦ„]´Rƒà.øºæ§Á‘¢“h£AÑóõCm!§Hg0T¬APªlm:‘¹C™tkùж¤ÿnžò¦Ó`pmKN,úvγÊtsÿ…Ô5Í@oNåÏ%©6$¾}óîò¡¯r¼Š'X-¬í|õóò¡ª¾©6]„J§ µ÷ø®õ#Ù$sÒÆ®Ê]ë¯(ÚÝ W`˜Ò?x‚w7è«Ap?íùâUÓ‘i ¥(èu ‚Ÿû¥MÞ¾)¯ø/mª  kNcѧHx
+~¹æ t]+4®2ºSPuôØžÌ(ꧨ uåCz}Â̤P‚€‚>O‡p@÷¹oòÙ
+’RÐÛéп-j†VdñöM‘ËKº+ª  ±8Œ¸ßP‡æÀÇùhãS¼U¢:€ålœS>tð—¬@Õv5VÜa÷à/Õ4þuGzÎæe¡† !å!ƒ¡yåC¿·â°~/ Ðàý½ÕåC\ti01'´, @«á­B‰ò×÷«¥Cøú¯k³Àˆ»‚Â_çj<N洞¥á=þçôÎåCG›qw¯uT¨¬©‚úiüëŽöÉê?]ù
+>ÚgTùÐ_­T&w앯 Âò¡ãµ.çϹâ"bPŽ×º&
+Å3to:BìPz»‚~.ꓱôUÞ*©ˆcc÷© ½^>TáÃ,X®ø •/SÐé|ËïS±ñd>R]°PÏt¡»Ê‡*UèÁj-µS…†+¨wùP•‡+ódF© 0lÀêBUˇªÞòO•Ûÿ;ZPAG4»>U¦‚eI…c!Ô¹|(û±M¬®Qy¨Q­‚¾@Ë/ãƒà*3Ô²CW
+ úò'Iq‡á{.Ô¿|¨Ú:¥ÖRËñ(4“\èùò¡ÿãìNàm,×þ›B¦)džÅ3®¡A*°E%*’’YÒ$¢B#ÕiV¤D©4¡’94*%‡Ð (”H†2ýï{­ë÷ìóþÛíµ®ß;>ç]ßóÜûyîy¸îríWGS¡]4,øG_fñ£á­%«x6(|]mó#ï~ô ,ò£Gª£˜§6ýËjeþQùnÏ¡²7C·DÅfdþQ…WŸ’ì륮J,ðq^}6órŽŸ†ÁMAM>~ôüÿùQy¼â„ûäqŽ](*°å4?šœùG•º¸R¤ìA¯œ Åb™T¹N˜~™vù2(øضùÑ)Yüè9,ÐÆìt^C\ó£DæåO û¦‚Ô¼šö~T`i©2¿lTa˜bP`“o~T>‹-j½z® ®¶ùѹ™Tõcœ
+|™Ul+üG§+ѱJéThÌTÕê…©ÐsÿϪÛ®^¢RõœT¬´ôïR'EÒüŠ‡iÞìÌ<Š'À»2ÜŽL,o~åç…ñÿÆ}ðµ¥yÇÚ•©Ä'Á«0ÜÎûZþÖ9ÇQ<
+|"ÅÓOï\iîgêÄ;^\º…†Iq™1K,o îfË+-¬áÍ).O2¨ƒ–§.KñÁó(.OßÒÿTuâí¥Ä>x[ŠK÷ i×ZêÄ{a«ÿM»Ö¡¸”÷­9ÃõÎôdà# îbýçø6Dâc21\ýæS\zVûr~ x
+ã4R¡k†ž~Å¥ºøì·ô‰wc˜xùìw(.¶â'mŽõ¸ŠŸ´§¸TV‹+NSsÓÂa×ÇâŠÏS\ž¾ÉyJ̓0éF|
+Å¥žß—û¤þÕ9 tÌöå>Mqùîûº>ÊpŒþÅ¥º(}KWmeåÚ0ÔIðnQ]´Ø†ÅÄXj!5ž‘ÇLçmœá/m\Þü–·¨yÌó°çd~ËÑ —½…yïÞv¼žØCnx9†ûò·×ØŽŽYÌ.ëØÜ”‰›N1V ïÊpYÈ»nÙOjn*+ ®[ö3ÅÓ¯®sn3_Ëm·PªJÃc—!pí¯îO-ieþpñÔn|Åe×lì†#Ï7»ŽzºØ“Šaº/žeua/•ñ°÷à¤bµ).Sθjž°G‹Áo¢¸ô.†=õ°–Û;ÏpfdØS3;™[Jêyàa›VËA§Q\†íÚ§uf(䂤¸t¾µ°0^@·Ð‡ŠcUèà[K(.•U½/««¹àé†×¢¸<=œñ£úÕ%|8á8¶aïi§Î6öú
+ÅãàÕ).{Λ.Ûu BqùÛsÖ|Gñ8øO—¿½òe%
+ãñ!¶ÊY;˜§ã4n•³vQ\zVµÖ}ÏpœÆ­µŽzu˜!o=~5Åcàk(..ñT†KUiøE—×öíK)ïÉpì5j·¤Ð§ÿ[¦ÅnŸvKzQ\>ÜùSO Ÿg*+/zn¦x
+íUþ+—šö­
+#(‚ßLqÉ´óKÅŽnóKšiÿ•Ë›_õõ@ŠÇÀ‡R\jÚÕ<†Kd!ÃCŠK‘ù|oMŠÇÁk3\NçuújçGLÅ µõ Mü+—÷͘ÝTâ“à{Ž­ ›Ê>Eñ
+u¶±‹ø‡—º®ÝI- ãTÔžyo.ο·;©5Å¥}«L'ý‡‹âÞ•âòæW}6Xýêl8nL÷}v-ÅåéǦìR'ÞT”˜â>6åŠËú¸Ãé3­‡p†?Iqþ¿tñ_êWç˜þxüÁ=)ý qÈÜóöÐðçž)¯¼ð^ ïù)‡!Â~)Å¥OÛmúõjóâèœt›>‚ᘣž¾»Á£•‘é»{P\
+ìÌäSjw°§Ôð)—ºnhò4=±MËð3Ž&2oÅ#Jnç`,“·âqŠË‡;0삘%>0¬'ÅCðÞO€ßÏp¿wlÞôxðT »Œñ*={ÿ:â^ŽâR`g-j®å6¶ ÿ oEq©ç±õ‰÷c–ˆ=Bq™|˜üîmzîD‘&¿;†âÒ@·»è(¸—e¶1eÑ2;µ»¸(Ã1{0zg’áض1zç—òþÑ°E…ñº…¾maq¿ÌGÖR\ºõÕSs?ŒcÊ«þ¡†—7dâmêWø¶¨™8šáøîuúê
+桇Nu­`8VÔÄ-'
+žpp5á(.íûÈú…~¸yjê¼)Ååé}Ú ²Ê2.qêw8'eøc G‡¼Þ¾jîFñi @plêØ®eiðt̉ÌÜ<×^Žâ2oóͦ±jîºIŒß¿ÙtÅ¥À^rožš›"ƒ{ɽQ\rÝ]KßUs3ÃÖÄ»–.¤¸TÔÓÎÕ÷À0[8íܲ Çåw¥ï8IÍíîûx}ŠËwï¾I6…zYFŒôÂÔNqðc—§­óÃ1ñr´ÎTêéòæ«Ï¯Að¨cV}~-ŠËê@Íœƒcê£fÎ!Š#ö~_t S±û2Ÿý7¿³1Ø}ð;).•Õ+³=-·7‡ãé¯ÌŽQ\j›FK‡éyà [ØhéŠËÓ[üq£úÕ™u]‹?n¡8vïñ†ž‡˜!7|ÅeÓH‘GΉv:=z-ñ –8µžšÇýÂa%NmLq)°Ý†¥/2Ñzœáë(.#èÙ0g•ŽÝ—¹™ÝÐ  ]ð—®Ñû+.SóÀô͒ཎ»óÞXºGŸx' ßËplÇý­èd&ñ~Ħ8®dêž; ™»0ü"ŠËw?®«œ‹ô²Œh~ç81D8îÂ"#
+úàÏ_¤x|6ÃQÛ”tšªy<ˆª‹’N ŠË«k7ÝÂTäÀl¸†° íæ5f8f ÇO¼YͽüêbüÄQ—NéÆ¿§è¹ç‡ŸJpL6æ•Õ´0^ÀÄK,u/±Þ‚âéö½s•3ïP'ÞtJåÕ>ŽâRUV›¾M:’XæE¥¸z î«6ûfŠK=?ªÃM…ñ^]Ün©Â‘“Qn§¸Ô6Wœýu‰,'Zícb2Ýgøm Gh 1=©åæg!ž>æ¡gŽ§?xQ5uâ“ÑIdÃk1÷IM³VÍãañ¬¦ù/ÅåÕ{rµš‡AUå±'×P\æ.ro°ñ¬œT݆©Yÿ̉wpþÝðߎ öWG6),ñ“mü¨¦}ud ‚#ìa§E¿íR¿º„‹‹B ßCñh5°†>Óæ?0ŒÈó†ã¶Êûo&ª Äî3|Åeî¢z—OD3']¾§¸<ýô¡I†#ÔçéCO£¸Ì]Ü0{‰SG²ª*/@euÃðz—ñ{ó?{ªyþ½B†_Ép`?yiu5wô. ¯EqIüŸ*ŒX]QŸÖð! G÷`s›ŠúçDA6·©Ìp³jØf‚þÕ…˜h5ü^†ãš’،߈Êô¾á{ŽnaÓW±U)™å²N2Õ¢¹à/R\ZØó¿ªæ1“i]ð×).•ÕñE^#¨‰†¿AqÙ
+ÙÉì§6f¬.|»=ÎCäÀ1+.§¸´qt½OÍçã ŸDqÜÜwN_"ñ lœØzÎ
+ýîq;kƒmknpŽ-+5ŠU÷²}u~Úð—ý6/,úUÍc®‹¹ÊýÎp|¸"½©ç~nE>šGqéQÿkR±,—6Li p]…á­).u]…ÊåÕÜ´îí[¡rEŠË‡s>¸XÍMc†Lë|Ѓâ2èðÝý«ó£Óy¾[Bqi&ºÞõ,‘xTV†O§¸äºIŸVóD~ì¾I§R\*«š÷UVóüHà†W£¸ Äî®ß‘Ê´xg†£¶ÙÛ¯1“x B÷ökAqÙgÕ$O_Þãî7\_Þ-—lÓ±!Fб,§¸c®icp­pdž›).ö’Oâjžp/â§R\Êûøq=ÔÜWÜ;0~\OŠKâ­ÓLÍí±Ê¼ÅѾßßXÍc¦ªtÀ[P\zVå÷•UóÐOäóŠã¢ÏMcõÎObUè®MwS\ž¾æŒæú"ãG]£5gœLq©*÷·< æö
+×Uþ<Á=lŒ\=ba¼À—pp—á÷Çi;8ò ¸›OØ°2SjøvŠËìA“ë^ÓsA “â2{ðÌáâjó=|÷g—$x´{¿Gƒ£jžt¢Ýû=¥¸L°/í¶>ñŠŒáí).O__ana¼€"cîÅ1
+ŸâÒ1›2¨;ñá¢ë&§ êIq)ïÏ­}QYd’n$±úÜÚ—).SÇmj¨M¼âÆeÖÇmjLq™|(Ûp°úÃaˆã6e^Kq)°_–­nê8mæWgÆÞñüS™_~“âÒH½ñØF5·)]ðï(.Ueý^'‚gÞÖ>Æ Cö°~¯Ú—!ð¸µÿQs¦%þ$Å¥®ËÁF)7}Ák¦
+ãXÏqp»áÓ(.‰ßï§N¼›\wW| ű"öÝyD¶qœˆw ¸TÔåÿÔ>=uÕ&ÖãÊÿ©}zú¦Niãê½Ð˜âx3ŠË¾ ÷ÉžúW`¾Îð+).ÝÂ*õþ
+ã4оÝ4‚ÞÅ–9£).uÍfyêÄ›zGNj6Ó¿º ÝXž35mú²ËL—e¤¢ÇåGQËûÅeÖÈYY <t1ÓE!öwž-¬8+kR\ž~ÕêMzn
+lü;ŠKms}Ó–jîD›ÿ w(.û´ï~Õr»mw Oûn7Å¥ª\8š:ñ&{£¢^8ÿy†cüg³Ö¨¹=;ÿšáIMœ“Ô'ÞG€YÃO¥¸Ôu?¾GýáLžCÔ…ßKqi&>?²S_dÂèžÐÏ좸 ÜÑúç‡Xý7¼Á±úŸ÷è;O¨yàa=Îð)—þ|ùsNž¾è3 îùa*¤ü9Õ(.îëK®
+¢ng§çàw0u]ÅÿôRóXþ.îŠÿéÃp<Ý»iGa¼€ÊÊðh,cøo—9êzN׿:/Ú~ÿBÏ —lÓiñ±múWDÓû‹m§¸”¸¿¦æžoCq™¯;þ›ýêzùwë|ó7Åeü^æ”YD‘ÁÁÃgS\_iýjza>_IñôßÞ¹DŸ’Zž
+‹?žâ8‰ü:fÌR[г¨*ãf0 {à¼>†â2ùàìî¤æöú9œƒÞÝ•â2åµú™6Zî$\\~gx[ŠKyoôÌo…ñŠLÜ./`Ê«Ñ3¿S\FR·Ä,qú‚×l^]Âô_}ðž—zþÈä=jF÷¾—âÒLä^xjz?s‘±—]&òùm ÇDk³ŸWÆ øp »´{…šýü1Å¥KœûM#ð¬.þ³<n½€7£¸¼º›ÿS/èÕ¹^´˜hø—§;o} N¼"*²á«(.ß½W¥ÕÜÞF¿™âò·ß×öý«ó¢ËqîkÛƒáèUÎjs¶š'Âäfµ9‡âRÓÖz¤úÕ%£¨ †ŸIq©ikäÊ‘7}%SæÄ'ÝÔ¬øyÇ%)/–Us/ˆ!Fkƒs(.݃ŸW¬ÒrÓ9Á~ÃWS\²MÎà_Ô<DÓ}9ƒe86…ºŸ\R/ ÛØëçг2ü2ŠKâoºé$õ‡3u fnº©>Å¥ºx1÷/õ«KØ
+l…&²—ØËî8û;7Ê´†¿Oq©m6×?àv´n®ß–â2†=©ÖRðì>Ø{°hý¤Z+(.O¯3±½š'‚h¸ÎÄóŽUà'ž.£å¦¶ÀqZÃ+P\?{È…êÄ'£]^†w£¸ô¨ïù°³ž‡AXøC"ñaÔ¾ßÿ¦:ÛØMà˜)½ÿÍU—»qïjîzQ0®{÷S\ÞüÎ'Î%²Mœgç).s•-ßߪç¶ç¾âÒ!¯óZsp/[nÃà­(.£‰¡Ts»¸ñ!—"³¢Ï‘Âø?»Fö<hþ‚ÚŠ«ŠR\#uËŽÏÅÁµ ‰·‡mbÑ…P‡¿¦8b>t.«æ‰ Z‹lÒ9‡àÑ«›Ôý[=w±‹Ûð(Ž]ÜO¿£æ®ƒã6†/ ¸tN¿º­þÃùѽ§_}6Ãe§SǦ_žÝ3ó»Dw#^šâ’ë¿£šÇì̓à·P\*ê"»¨¹½”bw/¢¸dÚŠóNÑs/@̇ŠóÚ0^êÜÜHÍíŒ[Ä›Q\^ÝŽŽõ‰Äãê=ÛP\Æ°ÅÚè÷1½ox ŠKº×YLôÒ3n¶=3'Z“êµà(Åå铸XÉ];dC$±Iô ¸Œ¤Â£Åõ‰wCÌœ„GKR\:¥ï—»SÍÝhmøŠK¶©ü\‚ØõQù¹Ö—ŽY¹ Q®s³å1ßGϪ܆£—îA£#Ÿky*x€þ%ÅQdpC«2ñøi—7uéiêÄ{ѽ†?OqIüØ2«ÔÜŒ!QÞÇ–ù”â2
+,¦¸_ú¨Åe8°õ³þJnÍnýlÃ1éTù—“Ô܆·×§¸¬€W_äé_]€°H†‡—6Î;s•Y§õìqZœD6|Å¥®ë\:Oˤ‹Ûç ¿âX—ºIÍ!º…†ÏpT“nœ¢æf DüYŠKmóz¯"úç$0‚~½W1ŠËr^ñ©_«ïÚ䃯§¸¬æöh©ÿp~å=·GkŠKyo9àM}¦îÂ6|Å%ñ]ÊÏÔsS`#þ2Å¥}?u(fÒG‰3æ5ÉŸ»0ütŠK]÷ÅiÕ<æcS¨áCŽ­ßm©y`ƒ‚ŸJqi"¯íå蹩ë"î1we{¾‚š»®£2¼ÅåÕØ u–S¿ Ð)=±ÙO Çø·*_«¹ãá.lÃ71ÍDΛÛôÜA÷S\²Í¸j½µÜ. û¿šáˆáÖòè`5Oú8±bøµ Ç”W8ï=â8•λ”ḞÆ+*ûm¼ô¡ÎŒ¡m@eßÊWtÅ¥c–Ü>IËíf!tJ“ÛÿCqì£^"1Z½ô5%NFKÝŽ}ÔK^¢¸t [|ÿ…šûù÷Ë´øþ¿—~ÝÂùïéo~逿OqY <ec¡{‹È6ê>¾–âRd~¼ôKuâã&Ü _Gq©¬Šß$÷ˆy©KR²Ø(e¯h Ñ!/~Ó·Çðÿü³Ž-©-Î?—â’ç'܈àQè¿I'7¥¸¼º%kÿ xtËÉ’µû). +Gr'2¯3¥Gr4R%Ïyšà^>–yóXTÚuOcp7KnÃ"a¹ëž¦—§¸â š›dñCÇ~Ú£}µÜ^çŒeÜœ£ý).sÔ查æñèþ8ÃÛSÁóûIøz/}È+ã6ló3†D Û¤ßS—ö½õ ßÆ üp¡ù×øw GÏ*¹«»žG+#†_NqùÛO=è*y": â!Ãq­ðe{î&^6>‘áˆs²jÿÇzb7¯á«ŽÝ¼MÆ”w³u˜ö1ü†ci㱋ª¹`0bx ŠK ûtëújnjy'â )ŽÈSv«y"t£ÀSöR\
+ìöÇ>÷ܬº… 7î¡KløjŠKâ×V}UÍñ* ƒáÑe—¸À½`^@Eðì¦
+㼺ÐÔÓ1=Øþè1ŠK¦ÝsÞruâC?€ï9o%Å¥²j¾»¦šÇ<ÜÜgøIG¸Œ{° ³ËçYq3Âð?çž?(.-ìÖÆû•Ü^ìmQÛÚøoŠãÎÄ+Ç빇ຆßCqI¤#Ãeõßð (.%®oIL¸ÅìBj†í¸iž “—Ñ·äŠKe5ùûaj÷XØð›(.Ù¦æµcµ<uôß¿›â²½ø§Cõ<ˆ‚qÿô:†cò¡âó3Õܳ׼‚¿LqI|ý›æ«yÅö1|ÅåéMŠ^¨æ®â:ª&E/¡¸$¾k¢šûà<]çQ÷Mü2\x: †›‘Ç'À)-ÃGR\zÃŽä)¹ THväBŠK+Óf}yp7ÕñÈ"ñ¶¸{à).Mä„?i¹kþá°&ŒØFñô«;¯s¬MÄSGJ3g;øO"Y½†S…'Róu™Ÿž0}›h{^½†Ï3\Ú¸ŽÇf¹jn¯›Àù¸YÁCÜ}ì½ÔÜu±jø,†ã~™c Š<Ç[P’âÒ¾÷¹u©ð¤“yWgš'mÜDð Ç´Où¶Æ H|ê4.v6–`Å¥ºhÛ¿ÁL¼´í2Å%Ó¶œ•:rbk0óÿLµ]¹ùÀwËY ÿϼ€žæò·?9ðd·Y¥yÂ.5~r¦Gqù\¢æI{0ü2ŠËßþã´[Ô<žôÓng8¦û¶M¹NÏÍh¿â’i[í@ç$YÐ]Zq×tŒpŸT«).n[ßÅjn×ÿ#¾œâ²2RkÚýjx¶iød†#ÐhéÒ³r,î“JÿÎïø­ Ç^£U¶Rs»>îQ\ŠÌÈákÀÝ,yêJ§ˆÅpô¬ÞéÚSÍãaí®½).‰_Ò³¹–›Œ…¯_Ò³%Å£«÷Ž+Œ—,(ñAů[ÑçxŠK‰«´ôrõ«3C …*-Õ¿yËe4á]#»yÓñ 37Ð6œ”éX!þü5y Gy/™8EÉSeuÉÄé—l3òîµjîùÑUÚ#ï^Oqyóç¶øÜÍ–Çí-jàP\Æ2ŸT© å®=%€W¦¸¼ù:VsÏü0¿žâ2WYý—àØkx@qi"Îz_ÍmÈ|Å¥¶¹lèx57ÿˆºpÙÐ{(.³•Ë8ÕôgÇc¶K>ƒâ2gU¬M]5O„cnxŠË´ÏìsŸw³ãžâ>ƒáhß·žpDÏÃèÂÇ­UŠ0Ù&þË-·]ÄêŒÿ²‰âRוMÝà–ú·Sû¨ ?™æ6s;àë(.ƒÐŽûjžð|£¸TÔ :ÝI$sÔ†g8¼l­]FÍÝ0mØ[kW xT]´Úo›Hûï&='}õJá/†NˆÑD«ýûþ/<,RÄ1šxᙾ…%¾@îyÑ%æ/<ÓâÒ»½”>Û„¸Úðã).­L™ª¨¹©ª0Š,Sõ"†ãʆεåÔ†›ÞW™¹ºð]3Á¬QçÚó(.%nØŒaZî$„ˆ1|$Å¥ÀÎ?a­ž{Heø†ãöãÖ©_]àDW¬>1n=Å%Ó¾2ì5wýh
+îfÉÓÁ…?PŒâÒ-<¼ÝUóÀ‹n%>¼=¤8VÀ×ïVó¸þÇÀ÷Q\z•M¯{FËíÝ:Ø¢Öôºç)ŽÀÂS¯S'Þ §Ôða DZ‹Òscjn†Á\Pzî) G‰«ýÅ£jžtp—áOR\Ú÷¹„§>dæöØE`vDî½ —Ž^û.¸›-Oh¤ _Åpìhrò“Zn÷»à ó“§P\š‰ ³Ö«¹ÝðbøFŠËÓߪ2LÍ(Ü¥á7R\
+ìE{WêïãÀ‹áQ\j›{ËÞ¥æ]ÓŸ@qˆåÔºNi“ѵ†g8nú¨Þ}µ>ñ&Z _Cqlþo¾TÍ]7óþÅ¥k4¤¬¬ˆy^êÐGÆmZ^*lŠÌ²c(.òmOô/Œÿs0⥖V0ñ²í‰A—zþ„£¨i³ŒÁžº4gÀ _Èpt.½©/xjšñÎ…Ô¥JÑ-'—Þ4€âÒHmïR¢0^`â“.Îþ~<Å¥º(þÉ Ç*°á7R\z•'ÿ:CýêüÀ #>“â8Þî u⦉Žø[G³稹éÕa%´Ñ‡ú§[.3f»®ž¬åvI uÝ®«£¸üíG?; æözZü0Å¥ªL<&k^:&sfnÆ¿Ñm•†¿Kqé]L»çY5OÅíŽâRU¶~´1x*JjÆ“J†'}œ›0¼9ÅåÍß<ãáÂxA‰·Ç÷±%õæR\ZØïKý¨çAˆs‘ß—ú™âòáŠÝu’–;‰¨?oxŠKU™×v‰:ñ®Ç6¯ír†ã4î+×¾¬ç~trá•k_£¸ÌU®œÓCýê’^"Ÿ_Nq|¹@Ÿm</M>,Ø©çö"ótU™ûÌx}â£/†ßËpìx™t'¡éÈÀÙ$>4EÆŽâÖqF5ùA>¯Hqyu×M_¯æq?ºôðºé›).%®E5Y‡õ
+ŒŠ\
+Í6ÿÆe“X^üÈÕzí¯3¼Å%ûáú²ÓÉ‹e9õ3`Ìv8ÜàxŠKÇì¶ƪyÜÅuT†ßMq©*—žZIËíÕ˜-\zê —ŽÙ§N¥¸>âRÛì½wš›q"Fî½w(ÅåÕ½<sV© ð™ïÖIý.º†ìå!ƒ(ŽË26/ŒPQÇlüyÌœü¾¡Åe »í™3•‰7<Œ¡[ØöÌ—(.nÍÌËÀSaR2Bã©Ð‡x/ŠËHꛧ†ä ¿‰âòÝw¢å©0¥øõ—iŸJ]N òªÔ¥Å¥‰lâæ‰æ相U).O?½}ÅÂxE&n·.ÈÔ‡á…&þß8f‰{=†Qd–[‘Íc»E¼'ñ
+ÜêÈ`5wƒa‘Z¹–âRÛœyÇEjnoê Á»Q\z•Ë^øšû^èGüq†c!uÐ*¹ÍKm„Î ÜîôÉïÏZõÅ¥¼Ožv¢’Ç=SY [8yZŠKϪhï?À³ ÖaãEKZE{ïg¸t óŽ5Ý¢æöÆF|+Åeøõ•èY¥·çeǸ“bøtŠËhâ„Qg€g*ÄüÎsp-‘áí(Ž#ä»/
+ÅeÛÆ® ©ÄG¼)ÃkèÙH|2uä$SàA/uiAˆFjèÙ§1³?nz«0^@⓶[ˆ^å›æ鹋Ø>OXÔÜÍn¢5™šx Á/¦¸4÷4½‹âø‚cu SÅ÷©¹ï†èÛTÜù ÅeÎjôÙ¿«yî3|/Ã1>xè;5{¸ Ûð).£È¢[õOwó«‹¢[`¸t‰óZ·\¯u~ ‡ûZ·ÜÈp„p/šÌYÙPIY·±¿sÍ%ÁK2>Þ™÷šŽÛ«ïBl˜1üuŠKÇ,çÙõàvClæWg/ÖµøÁ7Q\Þ|ó/ªyÒTI𗎧Ÿ}ZnaüŸÍ„ÝigøÁ«Q׈o®®u.î‡5¼Å¥osìù ÕÜÅBðK(. tñËÇi¹ëùqÔóÅ/Oqyz£¹é¹é”ºàÿ¡¸Ì]\6¸‹š!ŽÏ~Å¥žoÙg„¾È¨. ¿‰âÒ)½öþ¹znb.ø»—lóù–ㄧ¶ g€ÛÇXƒ6¼4Å¥²ú³Úwà©¥L¡ìc~Ïd8¢ãþ¹s‰š'½0Ÿ@qé_ä!=÷£  ÇyŒâRÞ'u{Bÿê¼
+OoÛÈØ=0ÿ7fO‘ƒ_Cqùîá–Ë•<ðbÃ-WP\ž¾ô÷zn+Kð›).Ó}Eo'^]ˆÐ¾†d8®P¿þô_Àí00‹lc·màšQÃ¥¸TÔã†ü¨æq?Ú,4nÈÏ ÇÄKÛ.Vs»12
+Å¥gÕÿW4‘ém™++óÖƒ8b6öÿuÁX¾ãF‘©ô,ŠLh7b#ÓÞqlÅ%Ó¾ÍiZn†Q$±÷¯iCq©¨—ŒóÔ‰œ(Äë’q!Ååo_[F"Ìx©eÜÌ›Àí%æöåÿDqYP»dÎÝà^¶Ü b¨*/™sÃ1É|ë‡r¤ÔK/md\ÖI]ì‹m™†—¡¸$~ßéó ãÿ<Øè¥zóxú¾ÓP\r]õÅ÷«ïèU>™á˜9Zå}-·1~Ze ñ}Ù…¾ù‚ïG7°/{à]ŠK‰ÛÜá}âM餸$~Ë€3Õ‰£­†ŸMqùÛ¯Ü¢æ¾  ßJqi ‹Ö*¡uæ¿ðRǯÿWÍ“vQ |#Å¥SÚòÔ¿Õ¯.ð±€nøŠËPèЖE±y _Iq霜_™6‘]w/a^bMêürçR\öœlY¾AÍ“~ܶ,ßDpdÚŽGÚ×rÛ<ãÂÇ#ío¢¸tÌJÖ Õ‰Oø ôiKÖ;…âRY}¡O¼\.ZKqia_ÛÿŠšÛ èîrÿ†#Îɇm}¶q“Hõa›8Åe¢5ù^ÄSÇm2wÌöÀ ú6É÷N£¸ ÿß¾å>5¢/†O¢¸äùÕÔ'X܆7¦¸<}óE¿ë¹‡gø^Šc »îr5{ „MÈ­»’âRU–¼^"B{éP·¬˜ß%Lm•
+÷œl´úéˬq;m…K¿£¸tȯyúˆš'¢ã´¯™R”â2š˜¼o/‘ø8–q'ï;@qé–©ö¤š‡¾­‰eª=CqIüiÓþ îfs¤ÔþΉv÷¾‘àQ,îJïÖr'î!6¯áŽfbPË úÄhã ¿—àñhÆlèEàYæM=ÆÇ ¹áÝ).¯nv…jîùÑDëìK(.±‡êUÔv)Êpì`ÏP\Íý{ /Iq©ëÞ*‰l㧖ó2mU²¿ ¢Ü ŸÄpŒaßi6NÍ]'Ž¾Í;Í™Ýݪæ±0‰náîFQ<ø‡Oœ+<È*
+bg‘%Á/d8Ö&®X…ÑD˜Õ¯öw¦7e+VýÍpDQ+« åö2,Ôó%c¹—zþøz3ô‰·_ü%ŠË8®ÚSgª¹½º ~Å%Ûܱäw=7õtþÅ%Ïÿ´ã šûÎ~˜âØ |ãŸjnrmóáF}âm¦—úüçÞÒ¿º0Úísþsó)ž~ó+-øUŸøQ‘ ßÃpܾeÁMÂc©a`æŠ:昚c™- FQ\rÝUƒ(ŒÐHÅlŸûë®üÅ¥¶y¤ÞTmâMóìaõ#õ¦S\ŠÌËÇÆ«_]2ÿ÷ËÇ<ý›NV'>zÜ¡¸<}Ó¯ÅÕ‰OØðDà¥(.µM£·†é3­ œ
+l™³©yÂã°O™³›Q\jÚï‹MÖòÔ¥]>ø#—L{ëÌ%SS^™B…øéë&£+æüÅpl€?þıj„Q$ðãOOqI|™‡dêCBûfÚšè§v„:ØÝWæ¡ý—îA뺞š'œ¨sÒºnÈpì9é°u“ø0âQ\2íÜÑeÁ³:Èì§2|t ÙÜÑ9—6®È[ýõÜÃ1jÃS\*«^w?-<½€ž™Ûó*8¼oøT†c8p¤ñ-· Öß4>Lq)°¾UŸx×þʉb8Ö¤–ͼSø„ñqðñ G×`FB¸—Ýzêw.b fœFqie~ôêûm ¯OqË´»ñ<ð¬Â˜[wÈ6ínìHqùp¹ºßüÛ^6Á÷Ò‰cÒ)÷ñÇÙÀNUŽUÑó Š WåX ŠKçdX›3ÕÜ þQd†µiGq©çßnªš{¦c?ƒâ’ç^ÛžàѲÎÂkϧ¸<}õä_
+ãÿœdvÓ›ð—ùŠa2käúY÷SÿùaÄëS\ÊûÜO‹ë¹í5šûiIŠË0ðøÍ‹Õ<æE‹JÇo^ÎpÄòš¾b«ž;Ñ
+5¼$ñ¤µ¶Ýwjîº „ˆYÛî†ãTæÅ•¨¹Ýž‚¥¸´°Uçܪu.b°~;ÃQâ–îÞ!<–Ýa{Mà<†ÿÆpdÚ
+ã*i¹½)ŸW§¸t K–¡N|ÆȤ8Nçm¯¬N|Ü‹¢¨UÜ^…âÒHÝ[éCuâí`$þ)Ãqðáàü"úlxˆ}p~q†K·°s¥£{©<€ ò¼ô¬M@3‘Úª”y[¦3Ýqì91¼ñ÷ Çy%´ÜÎbž¶Çy¥(.‰¿½Øðì6ÌØ#Üf ˆë¨Š-¦¸L6æŒ9QÍíò$øI —)¯¼Ò¿/+Œ0ÝgyƒÐÒ¿¯`8–ójMÇz\"˘ýö”žCqyóžª2Ë­ ® ƒÍ†ßLqé|µü$‚;²ãÅðz—õÖ]Á³[¾7<nÚg¼ÅåéÇnòµ<u‘w<Îp,ã7RÍMm…na±q£(.ÃÀK»mÕs/ªë.í¶âX›x²¦š;A4^ødmŠËŠØê/Usßñ±|¿úãž—I§²sÿÐgA™ ßÇpÉ6y5ÛÐsÓ–%Á1õ|‹ãÕOO]èì‚ÿEq©¨mO ¸‡ÕDÛêLm#':~Ñ%*ï©Ðý™»FI{‘6ŽÑåŠK‰zÖ*5ý8‚ç=ëŠËp TïYzn_øË Gúç1õÔÜ£IæŸÇ4¦¸4ã×JÚs²›öñR»¬öpüÚ} G`á7v½ªæñ À&±7v½Nð§ï9ü†ž{¸BÝð¹ G ·ŸŽlTs»iÄÿ–â2G}Ú SÁS“'™=ûh'Ÿ?Oqyu“k§æ‹êÂðóŽû¤:þTs¸>ñ!Ž~ÃÇìÕyeˆÄG·¿:¯<Å%Ûìýì>ñù»÷÷~v”âòôcËÿ&^]Ò8ñtÃ¥ª¼¶Ki=7ï.
+ÅÑÂÆ^`8"J•ŠÍ¤¸Ø: Šƒ§¦}2]æ§viáâ?ÃKR\ºFÍãËÕÜeÅð)ŽµÈ‡îÒr3†D QÃ'R\2ío=«y2ˆZ™ßz^GqéUW¦¨úÕyÑn㸌ãjVß O¼ÆIâ딟ÃpL}ÜÛ|¡žÛëmÁ—P\fæNn¯~u©0làç1‹ Ÿì|KÏ=Lï>àÑôþî%{Õ¯.F£‰ÝKö1›ªŽ©*Üs²¹^Ö·{°ó:¦ñ=Þ¡³–»1ßÃY¡x‡ ).µÍµÿ-®æöŠ˜8xi†£c6æYõÓÍÅ%ólI†c3ð’V•ÜKMu&Á3Mä+o ¶Ioϸ¸`¸ _JqIüÂOßQó¤‡Ý>†¿GqYD>ñ—¢jnÈÇÀKP\ò|µe;À½¬¶ß§®ÖņÃw1s·ÏVs›m“àsà°Ï÷©¹ïHü“(.³Ú½åpŸ—Ú —ñªû;»’™
+ÅüÿN95O†8žÆpõ‹Ëp¹yÿ²uà™xm$¢,èþe).ÕÅáÍ Ô<ù¸‹Í‹(.7_¬„l£öc¦„ò³£ÿ4øu G¡-þÅ«G.nÃ_§x
+½‹þÿßFÊü.‘¿˜Xk]5ŠË×|UwõÍ'äl4¼'Ååêó ÔÜü
+«BókÉpôç·üÙBÍ~´½åϳ). ©õ–¶f
+-ŽÖ­·ô†cuÛÛ®wc…çùöà=mo»ŽáÈ
+_ܦÔp†£C¾óI}=ïš¡ ®¯i-—³W?¥æ¡©*ÓàÏ1çŒT¾ê+ý£ ,aW¾j3ÅeüžW¨0ñµ0¯PQŠË£«µvÁ‘ Æð—GWwâ¹÷°±±îD¢²
+½(ñàŽË‰B⎼C?±ÇYá ï™3Õ<£àÿ]3õ”å2Ž±G–´üLiÈ<`†€¾ŸD”׈=Ë).»°O¾¯6x&t!g`¤¹LÊMc8pò}u).½ÊBGõWO‡IÌ:Ú€âè˜}p”àQç¤ÏP\¾¸ÄÇßjy¦sñ]—R÷ýSMô7列ˆ» GwÞÙñ{`#5cpû;ñ"¥.ocA†c²qêý )ž
+Åea¥óí[Á½¸Üó¬Iu¾ýŠË“ß<ñy5‚
+µ{c²ž‡i …Ú½1•áè—ž=‰â!ø‹—ÕZK¾VrÏ.ìà4êZK¶Q\Ú÷‡+f8žüÕOe8Λ(Ôi¾ž»Ñv¡N ).{ã*ûÀ3iNsNû˜ßÙ…Üü
+÷J} å¦Jõpfâ ¥VR˸×I˜›Š·Ýü΋–ï ŸCq)´ý»-d¸ñ%—fâ©KB-·Y ‘2â©KÒ—ÎI•_꫹ Èx#†#ž¶ÎMÕÎ éd¸Cq¹ù/šTsÛ3rÁP\ŠMûråÁ3CàÜÁB)›)+¡íËUd8VB÷œVøßøÿMÎcÿH/‰±=§¥¸T¯¾ÕJx:V:kû»d”pÒðóŽ`àeó«¹yxøÞ—Íûâ2ZTòsâæq"³áëŽÍ¼ÝšÕ’j—1M×,¯CqyqŸçmÓr{8Âu>ÏÛIqé4nÑF}óI?J_߸Å(./îÝŠ7ª¹õ. ïEq™§-RèW57ÿ)kІÿIqyïU/¿&˽LJþÜ•U6œñŽº®Ÿû<Á}?×ÏLq„
+ÏL¸åü` 7Å™…Q\zÔgüg»š§\¾[Ï= F:Œõº–»®—Èç (.u³;===‰5»3Aq©*ïIÿ&< œ{š×³ÁÀ>*ê{ÒQ\þöŠ£ÿ_a™ÿ·6—I˜OÛ?FqéœÔïv¸ç¨M{ß2ÔïV‘âRæ'®‘)n/8‘³cfOÜö¢£¸&®Y@q©.~_—TsÏCMkxsŠKmS¤¾Œ"½˜¡ 6!“^¤þz‚Gg —-º‡¹:n¾lÑï©›—ö¼"UÁݘÜõ¢]™†×¤¸4R{7Ý åNÊ”m¼Å¥sòüËÕ<aþ; þÅ¥™Ø\¸žþæíþðF—¾MËAW¨¹ %TËAWS\
+ímú닇SÌ ¿ƒârõ¥Æë_œž•áO3Òõ[ðÉñ6´zv’7‰)îõ[N§¸ B—j­ä¾ ˆÅláñRm).³…ÍŽÍ!n>…¹‹fÇæR\FÐÇ›ÿ_òÿÑ@g¶´"ÚçxÓÇ^¡í«þÿ¯›·cÈè±íŸP\^Üý‰wÔÜÜ:ŠÍý‰—Y£zß> }t6ûßë}ûñ…ü器oÞ:ä†Lq©i§½“–;i/ZHö~ŠË,qÃC2gå…1b6ý¦¼ /Fqé¬]Œq\6p"wUÚ%-®]<ŒâRæ/:pÓ¿ñÿQllò=±FèCqi&Ò};ioÞ4Ð!êºtßΗbóýÕkõ.ÀHÊðu—›ÿýü‰zb5Ððç).½ÊÛ$’ÙËÌä “ß…à{).ïý¦Þ*y6 › ÞâRÛ<þߺ —VÆðÔÕe {ÿe÷ƒg‚r7Й\™HXqÿeS\Ú÷÷ÛwÖòÌfâ4øe Ç澶[ˀǀ›Ò‘¸ íÖ
+—2ß½hJÍ}/Úûß½h ŠK÷`ÆØjîú¨ë ŸMq uòÕÜŽ–“à †Ë£ëØhÝÍÄÍ»ÈCÞh]_†#«Rµ×$ÙKÆ;,Ã\ÆîÎóÁ—R\¾¸‹j|sâ%iÓe ÙE5~d8–6>}·¼–ÛÃ2P]|úneŠ#ÁìͽÕÜTÓ˜`Ÿsó-—wln}5·'‘¥À<šî;Ñ}‰úÅ¥¼”ñå—îAù!{ôÅ&L ü¾üï).m\ — O9±‘íeì
+p4ϺO).µûÕl5½d>•â8žæµ©Â³‡Ûææí•â‹ëðÚtŠcÚç±¹jnOêôÀ_§¸t‰ß/}¦š¦oqâÒ@yøV57BD6~yx
+<Vp ýãDñó…J¬¡¸D÷9?ÿ¦ææ@l¡óó_—«?²¤µ–›GÍÓ>²äŠKþõoõ{f ~ŒâòÞÞ\]Íí>æ
+#©xÁÀa& ZѼåWm¥¸\}ıjî{HÖax!ŠK‡ÜoŸ7£}p9ðíï‚
+êy˜Äu™=…Žz~ãÍ݉G‡ÁˆáWR\êùéÏž Ê]lìï¢ÔéÏ?AqéQúàgjn†ÿxïŸ>¸žâòÁn*8MÍ“¦#‘ŸÉp™»èðõÆòjº dMüzc%Š#Åkõô΋–uÊVÿ˜áÒ!ïXõ§6zîcmÂð (.ß{Ïç©y"H×ß¼åÒ9é[
+ÎVót€# ŸËpÙ‘Ú~Iûà^œÃmíe<ÓŸOßÉpLyœ?WÍC/
+M,8ÿMŠË{¯Wã÷ìAŸ9S؃>Ý4rq׫¹âÒ·)í¿«ç¶”þÅ¥cvñ Ÿƒg&Ür†ç™ßÙT!.øÇÞÀoú©¹cš‰ˆßNq©¬–ï<¨åv/.‚–ï<Êp„a\y¦žûQ~›+]†cçÂuº©yÚóãåŒ:=Ž/¯Ð¿¸
+_\ÌÐD{™ÐC÷Þ¨ßåpÛ>\ÉÓ™„.øã—à)S1[˜ MÌÝ1KÛ‡¥Ì)SŸf8¦ûõ¼UÏ}Œa Àpdúî‡ jî™ú" þñ Öó–{³Ü‹—âÕpÏsbøý G@ì¼nyà™µœÛi=;Óè 8p^·—ÎIá&´ÜI‡þ%ŲR\†ÙcFsÄ<{ïÑ¢Róâ›.±G>-Apé¬|ZšáX—iÜ¢xf
+?w”âRU–[ö3ÁL¼”[ÆÜ<R}¶uCoŠ§Áû1³•ÿ³CÍ6µønŠË|]í1¯g’ïåì›ßv{øë—«;“jhyfûgüt†c¼TR2‰y1“°Ù£uMûîÏ ¸ô¨ó”PsÓ-C:oÁi G3ÑdÅ-wMûŠ,©MV¦¸TŸÕ­ç.FR†§8v"o­¢qщN†× ¸TÔ»&´×óÀÅhbׄ‹Žfâpßyjžv“
+î;ŸâH¢¾éˆžG{ ÿâ<ФûýjžÒ˜%nÒýa†£žo:EýÁšOÆÇáwM§”§¸”ùo—ÿÜ‹Ëͯ°}þÛåc).]£wSª¹ï{è¾›:FqytÕœS„Ç;N:s?:#µšS”â²á%¸ª§ž‡8WÈð+ +ôs½ÅJž
+M/e8VBÜ÷­žûI,*=¸o7Å¥ÐVõxÌa``zÎ!ZØŠ££¸|q=î8¡æž›ÂÕ{ *Èp4RGgìVsˆíOq€7NŒ']”“¹qâ)ŠËÕ×M¿TÍm¨’~Åeêã÷…O07t¿/CýíRê.|ÿáÙ ±œËy™ƒ¼q¶á·S\ÆqG~½‚à&™üz-Å¥•y¨J%%·áyö<T¥*Ã1}ô^à±Ë°¿³qZ ð¾—÷>çлjî Ì9ô>Á“ˆtj¸~·–›naéÔpý—÷üê£ê›·UeÄÿ`8fJ§ÝÒEÏ£n¡áÝ(.S^?7<¤~t)ß»áG(.“I;ë_œÔ9i úÑe¸”ùFÍevöóSÜ¡›±ÁÍð(.îÑù—©yÒG’Ã{P\êºUŸ•wcm)µ—ñ£qܪÏÊS\ú´%í¦æ©hMÊðž ÇÕW,ßMÝ||/Å¥ºèVSÜñŽ¶¿3ƒ! »•ëCqi ï.)Ù6äpÛÜ<õϙһK¶¡¸4R_$]†£{ðE2`¸Duvh4~6ÁH(Ýhü—G×`ÆïÙÃms›”éG« FU`8Â2NX®çn7?pÂû—ÊjÎM–»fíÒº)IðzÛÜê›ÏßhøAŠËx÷Îjžôq––á{(.KØyÎ\õ£³'´xà¯S\æç{Ôí«æŽù_xŠK¡=ãùˆg¦}r†.Øõg{\ø ŠKϪjn0BÔê.øƒâÒDVîSZÍš ÃËQ\†Å×âêÙ`¡Üni{mÙFmx9ŠK·©ÕWjnÚ(L¼ljµ…áèn^9ZÍ^ˆB»yåxŠK »»Ä;JžÊ$ç Àߧ¸TÔÁm3Ô7o;¥ø,ŠËÕg~^ŸxqÑ‘‹3?oÈp ÄöÔ\¤æ© ÀLéžšKŽŒ}NyZ_lB<yߥ¸|ïå£G Q‹1K›ŠYR ÿâØN›>¨æ®D›yÓG)Ž‰ÖËßÒòLºMümŠK31÷ý7Õ7XD6|Åå‹[ºãb5OzQºŒ¥;ºP\n~ûýMÕÜ·3p‡âR]üyˇúGgFÿ_Ið
+8íÛ—ªrO¡jnš)'â­(.àOíõ£þæCWº…† ¸4Ð3 ?f¦>rwN2‰‘EmÆ‚f Gj EWO¤¸þÅå“éxOq=÷¢Ìï)Eq98 üiŽš'Ý„Œ& ŽÊj×ü’jžr\Nìš_†âÒ1 _ÿ@ÍÝhzÇj‹ÿb¸L6þ7Å1ÙøúÇ—ªò¶/Vs?L`ÛÅm_>Jq‰ú¨1tõ¿ñBÿ‹V _Ëp ¿és—úæmj |ÅeêcÅ¢zGl¡á(Ž£÷Îk'<s¢5aÃu°ûþÍó:Q\>Ø67|¦ç~˸mnXÇp4ÐåºOÔsW7ü9†K(rǺj¯f&Ø“àú«gþ%ƒ‘Ç:‚»1¹=ÈQ•»„áXÖéþëMjng>|ð[(.“Ž]®åN2@²Mï$¸‹<'›~%‹ü6†w¥¸üíûOþHÏÃhmbÿÉ«ŽµÈç+ž&<™Ùؘ»[h–pÛçùŠå).7ÿÓʯÔÜ÷’hã~Z¹™âÒ=X\ám=’òä _Îpädþdk!-w“6xŠ'e8 ÉuU7ï'óùé G°Ð‰AŸ* mÒIæŸÜwbÐ:‚G'÷Ý°éIܼ'•w†ûÖ oØô,Å¥º8Xû3571|2k¯g8²*í»¿»š§mP,ø ǦwŽïÒsÓHE|/Å¥c6àË.ZnÏ‹D ;àËn GÄË“]G¨¹ëD'><Ùõ ŠK©{ôñâz¤±wàÑÇK3;Ôªœó%ÑǬÊ9›õ<Äùï—:
+~!Åeö Ä°*ZnºF¡ñj—Éƺïªé sbxŠgß{§âuë‹Mˆ=à†ßCqyï­_#<k«‘ýíÛ$Á?c8>™ƒ¥Gi¹] Ķ‹ƒ¥ÇP\:fÎætJØEºX èi7áXÊüxpŠKúŒ^€Ç:®ÂþÎT83ñŒ^í).kRU™
+ž™hÍ,d7׶”V}d:Åeø_eçwÂ3r¹k7> ocø>ŠËðÅc¯ëyt(’á (.ŦÈýÕmñFŸvŠþêi7D2®j¹ëšþ¼ þ6Å¥{ã -´›Ìð.Ûvåä^˜ÊçÝþžó{Ž©VÔ7ïÝ I£åòÞ‡Õî­æI'Jé<¬v?ŠË{ëTéšüX¬=,#JwëK)žïJð‚oZ›âÒ¾?Yi±š»¦šOƒ/c8&ÎZ^<^@¬ù'ôRË<ky)ŠË(²ëærjžÌoeºn®Hqù`Ÿ]AÍÍ׎ñûï³+S\J]»¿:ªyÚKbüÞî¯Î—6®Äø[µÜu£¾á·S\‘÷ºÜ‹sà£åATÏ~Å¥®[üÔ =7….ŸMqé×õ]ßAx6:ç´ùéa¦´ïú‹(.lÛõ÷ª¹ Ë À¤¸|2•žh¯æ W7¼Å¥¶9|ä=7ï.ÞŸáÈÕùãúvjžÌ=øq½þo·\‚…ÊUÝ«ç!²ßþÅ¥º(zwÄcv™YB°±Ñðý pó®Rs7ô¤®3ü:ŠË÷×~Ápl»8ãÚ¯(Ž /çVóÐM"wßæóÇS\fJÛT“v7»ñ!çržë{æö<Ð¦Ú Ç@ì‘ÞCõܶgà#).}Ú™§tÕsÓ’Ê÷ÞûÑE GÙûÑ¥pó=).5íÉç5Tr»áI™ oJqyt—Ý:<ÞÄ‹á‰
+<ùêÉ—R×»©D¼Ô® ZÁæ}ÃçQ<[lÚïX\ÍS!•^™âÒ5JÝô«šgÒnƒÿFqi߇?Ó@Ïm"uð¦—>íþKÞÖr›É÷ö_²œâRæ?ôoQsÓH#ÂíCd]ÐqD¸yT².¸ÙµÜKI;•±Œák).u]Íåha³!+¹++{DK+#5—¥¸ FN?ï=LqŸ~Þó ÇŒY‡ž«¹©°°Ù§CÏÇ(.í{ƒ…#”<i÷Œ`5°ø¨årõ!«¯ ^œx›!«¯¦¸TV«ŸX£t^DüSŠË»zã|5w“N«7.¢¸´ï¥:§õ.±3±T糎zøñÁàn¼‰V{t=r6~/ÃÅ=uÞcjîÑéuSç £¸¼÷å'¦êoÞCÆ Ã§Q\¾¸É—"h$íÄ9èÓþÎq¢cJ&_:‹áÈ4òÂøÛ³ÁB¹‹MÚ± ¹">âÒ¯Û;ê57ƒô.öŽÌp„.ü}Uk5OûÞ–âRêF¶z^Ë]ÇÅÖBÃ'S\n~öjnF°¨ëö×¹˜âˆX‚àÈŠlxŠK±¹hêB5ÏßNkø†#?í©›|=7 ¬ž¤¸›g'ŸEp¤2¼Åe5°ìg’ÛÇËÆè§íòRϾ˜âòÅõÚvDÏèsÒkÛŸ—>m£‚£uÜËn›À¹BÇQg¨}Ó<“¬#çd£áfìá µošR\Ý‘7é¹EyYчâRæw¶¾\ÍÓÒ~%ñ}~à’'õÜE\¥áOS\ŠÍEÅ«êyà`3ïEÅ«S\Ú÷>Þ©ånþj†Çpì¹µõ©zîG'¸ÝÚºÃQÓŽyí"p/V2.{/ŠöóÚ%—Úæ¦!Á8wà¦Í).5íïëOUsûÿÁ/Iq¹ù&‡ÏRóÀæ»oEqyò{òdÇŠ—Mkƒ{v(äƒw§¸,"ìòž>&ÜvYÅpìTš3¹œ’»v{!‚æL®Dqyï箸üM¸ýß1æw¾‡sÀ á¨ç÷Ôÿôßøÿºy7eˆ5|=ÅeØkß8-· à°”ÙkߊKºôßíÕ7oÇHùøwG‚ãhÝN%Z­çQ¤“ák).îéñŸ ÷bäm—9
+ |ÅåÉŸ´l Á£#NZö$ѽ8t<:vð¦¿(.Û¨ÏÙÍp<ºÆs¾g86´þüðÌ{έFF†N
+3‡?¿•âR×/^…àiTÔÇ£~ŽKç$ü(OÏ]ox ŠËÞÀÊÅ.Wó”ùa~ÅW™×”àˆö1Ü¡¸¼÷¥„z$Ñ»XzAšâòÅzÒ[jžŽö¾ˆâ2š8ó·W´Ü5-$1?ó·™ G¡MÝõ­š{^€ ·Ô]»).½Ê /"8²ã~)Åeö Ìï·{±6ûØËHÝoø@ŠË@lý»SÕÜn»Á§S\¾÷5w'y¾‡áh&–¯>GÍMÁËW·¦xöæ;•î‡23y¾ù]Âʼn†ï¦¸ôiûµ®¬æ©ütÖýZçQ\^\Û§ñÅùñ¶ÛËDÓû†_ÂpÔ6Ÿ×~OËM§4:/òóÚ2“N»o=MͽÀÍçå).ó6ÛÚÉ»— ËŒÑ1 ìH̉ø;—6®î&T•1“¨ÛËø!R:×ÝtÅ¥žÿñ¯vàñ‚ÄÌe‚0@ÄË]Dqyt5Ç.Só„eˆ­9ö]ŠãdŸÎÑr»Á WoûBkŠËÕÏš®çѲŽá³)Ža`÷ÁêG— ¢pOwBqi gÕYž ÏËýɘ߄ѯ³ê¬ ¸<ºÄaYÒò²iNs. [›ß1KnNqYL,3ë%·IV]ôçËÌjGqéÏ_}ä+†ûÿšâ2®úä‚û®úäxŠc®²ÆJ5Ï?²Áðµ—öý!l=Pp?Ê‚nø GŒÙÑ ªy¦_wtÂ0Š#ÇË÷ªy~ZcÃõ/Îri"ïøª®š'£ã¨ oHqé<=zò™”¹»…™xˆŸ?xúpŠË@쥟¾Òrƒ‘u¡CIw’š›ª¤û"Å¥{°®ÖÝú¿=ð±©s]­{).]£÷OºTÍÓÒÞáø`{,zWýèìiÔŸâRÓ&MWs7¢5yh6ÅåƒmökRÏÃ@Þ»áÍ)žÄ'³žúd¤?_¤»¤Iñ2‰…cL}$3SÜiðºÇêÏ8ó]‚#Q‰á+ŽÀ‰vÏüîÆJªluØT§à‡).uÝy¶éy~úyv0yJoéø³š›'néxˆâróÇvPótˆ¼…†ëŸ¼åرR·”–Û26¼2Åe!õÌÂŽ¡áU(Ž>í±+ÔÜó£,jU]Kq¹ù†?÷â-*Ùˤë£áeŽÎÉÊJSôÜ‹fJWVšAq™t:²FÎPó²!è¹f2[pÒÇ‘5ŽNé†ïWr~­€oøøaŠK©«<ûÛãÿ#x •ÉH€ï¦¸<ù¯ÖÞ£¾ùdíc¸þÑY.©û+~|®š§¢¹ám).ÅæºþkôÜnôß@qùÞ+½pDÏ=iÐ*½ðÅåƒÝ3¦§ž‡ìsÅe8ðg•~àn¼ ö”Mõ™ÏûS\†ÿ­›tSs;í_Nq/Û¦2Á£D£?´©Nqi&V,}ZÍóÓaþ,Ã1É\¥F=1 4¼Å¥?_üÚdgx+Šc vÚ5ÌxÀÿ†âòÉÌ®>mv³Oîi^»ÙÇÁ÷ìÚ‡Ž©ÎK‰à>6û\úûTŠË¼MÍ o&xÔ¾×¼°/Å¥…=þÇÓ ÇÖƒã<ËpL°÷O&86÷~/Å¥Ô5ÿé6‚#ѨáwP\êºÞ{áhax)´8+³C“kÎQóÀ"š\s>ÅíSÒìv›ÜÕ…¹ŒŸD·´æc—¿=Qòz-wýge~#Ãù0ºÉ»ê›Oy)¼¸ÑMÞ§¸Üü—U×?:ÏÁ†—7.«Eq¹úþV%ÕÎTÓXýßߪ Ã1K|bÜõÍÛƒRàÛŽdÅ‚!ê›wýºÅ‚(.Ó}yÆè‹eYÉ«0žâÒD¦*œ¡q.–ï ¯GqéQ_ò“ÌYùÙÔý1*+3Šò]òÓ!ŠË8î†z€ÇÛnãg‚q±¸pÃ×P\
+í˜Ý¯«yÒAð¿áó).Ãÿ‹
+깩¬TyQa†cÖè´“jù? oJq)6·œ><³Ý&çržå®'ÅÆð׎DdePϽhÚ§¬“d8FRÿM½¡ç¶Ï¾€âÒ£žç65÷£Õÿ¥¸4‘?Ö§æAþæýk<Iq©*KlÑ_=é#­±áŽ›Q<Û@'ì±¹–uÌƒTÃË3ûawý@Ë]/JùhøJ†c\tî<áñ°¿sl× üM†c‹Ù3ÁÅà™@è\”ýi£0?ÿLÐ…áôkÛXËtö"ÞŒâÒD.x³µš'=tÌ ÿűúý}úGçâlâ¸ômFT¯žYÚÈ’š¹Œ‹ƒÀ oBqlp«¶^Ï=œ^gøFŠË£׺™šùY•Æµö(.{µó¯#x
+g W;ÿ&‚ãѵûkÇ5zî£kdø ŠË“oÜÉWóDˆãi OP\†BÕÇ /y¾ýݘœáÑÞÀ‰SŽÈ†Oc8Žh©R÷C‚‡NÄWQ\êºe“šªy]Ýðf—b³`~žšçgU2¼&ÅåÅ]Sî*ðlJª<bÙð뎈—qíçj¹iNpüœáoP\#é‚»ô<ô¬#]ð;ŠK×xpU5ûß®Áp¬Œ4ºòLá™äù1*+›<Ç”îR\èK«¨æ68
+µ}zÅñ²s³ž‡!΃þjç6ŠK ûõüÕ/Î ¢eܯ篢¸4R¿ }VÍmSî?Oq™«,8ê þƒÍŸ«,8êW†£WYpü÷ÁTÔEÒ®þƒu£dÚEÒÑ9pÂSé¹]Þ
+{Çéy´oÂð Ç*ð{çܦæi/:•ø½sn§¸Üü3ó鹟Ä{f^ŠËÍÿWVË]Çñ
+^‘âò·÷x#¸çóÌe<dQ3¼Åå{?öÍ=¢Ø±ož¢¸ôi«qš{öI~=Åe4Ñi÷ÕÜT•v£¸t6ìîªæa´nxŠË“ÿ¼Æ7ÂÙÇòÿòÿ‚ž¹ŒMQ¾ƒâÒ-¬tAƒãÿãæÿ M¬tA#ŠË‹ÛûæðXLj[žö£,©{ßÜGqûjŽš›1¡}5âw‘Wy©–›ï§v¨Yìu‚ûˆÝ;(OÏ}3¥÷ªAq)´{J_¡q2‰~ť̟rtš'ÌþÅeu Ú¸êGgºu^Ä7Q\úóu:¬¿yÏÁ8®NçO(.7ÕÀúgú®)ðŽóã–.ÇŒY¼£yìïòCR ?Fq©ç¿?ÜUÍmÌJ¼ñ"Vs@M5·yx=ð3(.ýù–mÞÐs/ÚÈܲÍ[—mk'­æ~´ fø6ŠË`¤îž´Ü‰!z¿îžÉ—'_fCZÏ»°ËlhAð
+µMã½(.7lÛ‚ãÀG÷3¹ûNn±HËÍÏ¢ŽÙÉ-–2ÜÇÜE…4x¼e{™
+Þ’â2gÕ¥ý]jî»ØkøŠK©»UÎPSñh3¯á—0…vNïzF#è9½S\*êknQóÀwÑ5:°æ6†cÎêð}ôÜ Ä|ð[).ŦÒ>é×¹ÙƒÀrÄ2JÓ؉\ißK—R·£zp7Öb¢½Œ›–xZûQ\ÊÜTUÍSa ©enªÎpd9ñÂ&5·„ˆo¥¸Ì×5ùˆ–Ûä{Rh Jq)´gÏtõ<Œ Ÿ=3 ¸4^n­æ6¼~Åå“ÙTlƒš‡a
+Çl*öñ#µå{Kÿÿßàó;SË#¶°å{ï0õGŸ§Õ7o‰|~ÅeÝ¢ÇÂãC–´e6ô±s¡EÑG’ÕºM´Üü‘ ,ežW·Ååæ•8MɽLùˆW ¸üí³»<Ep{Äfwy†âRÛ ŸöÁ£ö}ø´¯Žö}ï ÿÆÿç'cúàÿZhÿ9ÎÛ7€úÛqŽØ¾A—õºõŸLà‡ßLq©iO¾p¸k»ùNÄ'S\ú6eO~IË ü^aûÍ—B;éš?Õ<F‘“®9Fq¹ù97”U?:[l}ð
+—Fjë_ÿ%^\tõ­¦¸|qU>Y¨~téIØ ›á¿¯zòÓL±‰Î9ùŠËß¾÷úúú›Ï?ðqïõxäïSÀc%U¶— Ì“÷ÀO¥¸Ìœ Ù)!©nÌͼv;«…. Ù9âRhÓJ¨¹ C¹i¥ Ž'ßaßW¿g7´æ\@·Ü¢ûö}Õ˜âRl¾?é-·ñ°ùüy‚û(u/ô|LÏýh)ó…ž#(.Ãêg UsS¼óùH‚ˆ»˜øÈmzøù|
+4×r×î>ðÁ[Q\ÞûžÛ©¹âø9Ãÿ¦¸ŒaûÜ=PÍ} ´áƒ)Žì±œÆJƒfÃãÌP(ˆøhŠËŒÙÅK¤“›=,gxž›Ùôˆ—‹/Aq霴©<XÍM“6•ï¡¸L}\²9/ [6ªÒøY—R×{üùZèhžÞãÛQ\ºÄ}v•Rß¼ïcÿ»áe).Åæ·š{öàCð&—ö/ApD°ÞœâÒÂ6î}*ñè\‰52¼Å¥wá·®çaàGüqŠK=ÿ¨ó­þ“ñAÎð]—'?òìuêO&åFÁÀ#Ïþ‚áˆpY3ý£3M\Üc8Â2Ÿ­UHóND¼(Å¥þñHkõÍ'‚º…?iKqieþl2L_l¢Ã¬ ×—yË¥[XaÓ¢¢FÚÿ§¸ÌÛ|7TýÞíB.Æ2ß -Bq©iüŠ™ÒlzµÜòLú=?â¯P\þö: oUs»´áßNqiã:t<Ü•xÐÍl¨Åj`‡ŽmŽ¥Ì³ž˜¢çB• ŸÎp,i5Yr·š'=|ï†ßOqéÓŽj³PÍÓö8kð%—`¡ßVÐs?%Uþ¶2Å¥‰Ü9ü-7MdtØÎáCuÏ[<‰ô{ÞCq¹ùó~ŒxÌi^s{ Oqyq¥/?_Í7À\eéËÛá÷íg¬k­æ6]GüŠËwÏëϨ¹©¬
+Å¥kTúΙ Ç ´ô¯R\>™w–"8Nâ6¼ ÃQÓØ\—â ð—õÚ3'蹂»à)Ž<äKK€»qy2@·Ðð2 ÇF§Cç_©æ)/šò:„C‘”\†÷ý¾NÏ/î¾ß¿`8Ò>{œ–ÛÔaÄ'P\f‰çwn¡çùQÜó;ŸMqi¤–žÕ]Ïýh²qéYW0K™­œ îÅÚ¼o/ãcqÁð¹ G#uâÐH5·a#!øXŠg©N§ÈÜ…—ÙÔ‡{~”„Íð
+—bóB“ÒJžÙÅõ M´7Ÿá8ͪF¥:à™¥ÌœËyöÔAA¡†7 ¸´°sËQ\^öÈÅœ ©†§ògNæžÉpœ‘Zëàðxá÷ž—Ùâ–
+žAð$ä
+¬Oq©iSwNÐsÙ6 †àB•Œ
+žY\È]Y%ì‘ÊA1‚â2?ß`ý«ZžÙ¼ñ7Žùº1˶¨¹¤??fÙ7 —)îÇOºTÍí¶Ê
+xf›U®5ËS>r÷>‹âòèJϯæéhÝð‰ ǺÃsµÜµ§Ï%ÁÛP\Ú÷ÿ®î§t–´ ¿âÒ)Ý×­°úæíÞBrÚíTŠËÍŸ¹Cóæ%À÷P\z•¥O©¡æÉ "õß)µ 5Ð-«·TóDt~œáêB›áødz¿-<ˆ•þÎ^Æ&ÏOƒ/'x
+ èZÜwã,"ÛËd6€·`8#—­ùMÍÃ(Í©áQ\~ªÛJÍ]?JÆõSÝÖ—¾Í¹’âUÃS!Î2ü!ŠK=? h¬tAõü€ )ÃQϨýºš{ÙÂåó).O~lÑîjxiL÷-zÅ¥®+Þp´ž»ÿà㎥Ì*Ó*©¹¤òyUŠ#9χ“õ…ÖÅ|áSŽ``÷ŽÚúÊʆj×e82ÿýÔs/ºzÐÿg†£²z¹G7p/N`¤½ŒéW¡SúrË).ï}ý¾÷Ôܦ¿KÈpÌ—ù¤·ð0Ö·”òñ¢T!e>éGqéÕÞ,Ë:n¼àËSAˆ½µ7Oe862‡s®“›Od‡#9¹mÝqX†á71û"_ÙöÁŒ _Ù¶‰â2.7q Á<`ø ŠKÜE“9€ÇÚjdyÚváÀ‡S\¦}.?óU-·^srù™¯S\nþÑåÝÕÜ^ï€_Nqéhô€š{A½_ Ñ×ê¢m÷êúDûãÚv¯EqùÛ'ö¿I}ón7±o‚»„¾<²þæ½"Z_Ù˜á8ŽªUjžÒnÄwQ\6û,¾ÜÕ?:óßiðÃQYýì9Ä£s$a…áÅ¥‘š×S^ /Þ’VÂ5£wìýŸ×!Åð špk¬æe+ýwSŠK+s·ô7ïcYÇðS.Û¬Úýù†I'ÞDkÒüƒãi Kq€ýÏ•jn‹­~3ÅeªóÏù Ô< šá‹Ž€™åo$õ΋*êåo´ ¸Œß7|WOÍCóÁ:à ).7¿³ý ýÍQʈígS\j›£VóÌV'ðߎQäÔ6ÕÜ òÁ~„áòâÚ¯ø³FÙ©rWÔI×ñ†møC GÄË÷gtRsÏE`¤á]).Ŧà«ãõ7ïDû" ¾úÅå‹Ô|–šÑÉ>†Ï¥¸›’ŸVÕ?ºè(mëS\º[§=#Ü/cqÏ ĶN›DqéþçÒ}àn<ž¹žü.ÝOqyòÛ[ÔUs»%+ ^Ÿá(´óû×ß|Ô·é0¿ïÉ—WYòU*¸ëæ§ò®,ù*•‡Wúàq57](dîôÁh†cÜÆExqiœà‘“'óc6.jBqi¤ÊÝx²’§3'qùà§P\jÚcî`8Æ°Ç f8*«ò#Ór>”Ù’âR×5{©/só¨.š½t+Å彿wáÅànœÔ™d?š»xïÂ.—ïý•­Ô< ~ÞðÖ G¢’Â-_Ró0ˆ2Àn9…âÒ5*>©¸o!5í&=Gº†_Eq¹úü[V«yècÖÈðO).³c¿½ æ6¥´þ2Å¥²êtd«žç‡¬t:²â2šøù‰ õÜó³ñç'ÚS\fj¹DÍý
+?»“âÒ9I9_Í“¡‡)îôÇz‡6?%8¦y _Gq^íŸL±Á“ßyíß—z¾l»™jn!ÆÖvsÔ<s¢”tºÎVóüD£†Ï¥¸L><xÿX=wBt ¼ÿ)ŠËÌÉÊŠ÷ê]€|†ßOqùÞ ´—¥ 7mgrpûÚHÜðG).T•]ÿQrßtDZ&ex†£…íyÙjžp££¸z^Ö›âÒH <†z>š˜s¢ÕµA¡È8aø+—«:õ=ˆ³têû—îÁã¿LÐs© ŸÈp<º'w?¤æ¦CŽná“»£¸<º§¦´Psӯ ùSSΦ¸<ù5ýOSsÏņÃ+P\j›ù—vQódˆ8jûQ\fNö\£/6nmêÜsÍ$ŠK#Uå›/ˆG‡3ÿ$¸‹\^M^‘ºyœ#öú†£ªûfS-··Ž9ê±oº—O¦Q1tJ³Ð¹‡M<€CÌ»›àxòí{¬¯æ‰
+¿wm:¶þÅ¥Þã´Psßw=oÓ’â2N ;VÜL@lŒÊ*ù# ïËp¬EŽª¾Zͽòµ—>íÑûJ7ïG‹ ÷Fqyq¥ûÝFpì¥û ¤¸tNê™=9áfˆ‰ÃÓ6>¾—âØF=ðQâæ=Ì”8Œâ2sÒü¤«Á3ḹ'ÜL¯*ÄžPïg8bÈ›xMσü«xƒá²o¢}ÇU[ÔÜ÷p¾ŒáßP\꺶݊«¹}o/MðèŒÔ^jîæ¯
+õ:˜"¸ï î^FË´ï!ƒÜÒîå)ŽÜ|G›(3ð¶ûŽþü©±¤3ØüήlD|#Å¥sRºM)p'Þ҆ᾛ/ݦ ÅåêU¾Œ‘^6\'çÍÛ£&£Ý¸†ï¦¸4á÷›Áãx6ß%v.¾•âÒ«,×±£šûÑñ4†_LqùdÜ$r/4’sÊËûç‘ †o¦¸¼÷òãþ"8BV ?Nñì{ïTjè}àn¬a`&€1%«†?DqÞ8e»š§œhøÄ);ôÜüùÒ-<´è.-·©ÿüˆ«]†ËpàO÷E5÷ÌÅÓà/17Ÿ¨Ö Ür‡ëxÿÌ‚nxOŠ#·ÏCÔܦeJƒ?Èp¬„>7fžû!¶Ó>7æs†# {c»õ<L༉ízS\:ä£*|©æ¦óŽpÜQ63\¦ûÚŸÿ‹dó²IVs6‘æwIÏA¤Óù¿Ô¦¸tÌ
+WyWÍíü|
+ GÖ…‚íž%x´w `»(.}›Õ#Ïf8êùÕ#Ï!xTÏûéc=w±„ÝáÁsG3ÁžûÅ¥Ø8³l¦‘L“2Ûdãp|qÎ,çÿá¹»…åúøéææK\äÑÏ(ž_ÇpôçßÉ›¬æ©ü£¸ÞÉ›Bqi"ûŸ‰ öì’Vî©dfG«t û7;‰ávù§jîç¥=ìòÏeþk³š^tÔæ+m¡¸4‘çÜ¡æ¦Â'ÓyÎ]—ÎÉ®²‰Û‹¹˜è¥LE†µkc#ŠKùk×OÕÜÎÓ:à(.ßûÊöÔ<éyM\Ù¾0Ñ!öáBýô<ð½ˆßNqùÞ—>ú•š§\Ýð-—R·}æf=>É«{˜ÞïXyß\-·)+<D÷í{âŽ{´Úb†ccãÑjË(.õ8$VpÏMaAm\½ÇnÜé›ô<ŒÂïwNÿúÿãìNÀ¶œÖ¾7Ï£ÊSš)Íu÷€dÊÐ\dL
+I™‡a÷Š’D"iÐhHRT2U¢DJE(JƒR‰Ô·Öýœÿõ8¾½÷}þßãØö>Þ}ÿöµžkXã¹ÎEqéœ<ÿ€dM òÓae
+å§ÂÚ¯R‘ÌwßÂp U2ü6ŠËWiþ¹à¹%¤2ÜTUèVšßŽâÒ£^¼óºãÅþOºcÈ ïGqùdJÛ«.|:ÀvÃc8Ò"õ<»¢žÛ\`à•).m\Í2ýµÜöæ±C­f™Ž~Ý'Wž¤çQ:vüdŠKÏêí“Nù ©rá¾i*BðÍ—Øåý†èyˆpä¸ÌYí½¿²šÇ‘;–hïýU(.ýºªØ‰f´²O>ä/ˆ¡‘ªŠÈ:Ž}‘Õ¯(Dð
+âëòP\Z™ç[Ts?ŠSú|ëQ—ïýû]ÇÔÜtaÐD~ÿKaŠËK[èËBê×&%q T¡/‹Q\¶—©y²þ¥µÉ¼Á›P\èzƒÔ»=Z±zƒŠR\ZØè¬^ú»D%ÑY×R\žû±Kï">ØîØ¥÷P\Ö&j®–=à¡ŸÛöºÐÿç2nÍÕƒ).W¿èÅÝO`òá¢÷1óóÏäÍ!¸;8à™¼yÌÕe(Ô±~½G ´áOP\î|ÏÏ綴axÊø`ø —±L½›;ÿÿïá€áQèz•õn¾ˆâ¸ú‡•Ô…OÄö€×û°Åå곿Ap·­röW#).mÜâ×—)à ÿ„âòÉ|á‡Zîûn(dxLqi¤ZN[«æžŸŽ_¯ç6¼0ŸŸqáê[—“h&θð&†£G}ÝÔ…Ïáþ Å¥[xù‚;Ás Ç óÃ*LqyiûOß­æ6Oi¾—âòÅ ?íc5·!è1ørŠË÷Qý—ô·.ÄY؆O"¸; »ÖŽÂjnÃBbáÅ).]£Ä¦×Õ<iïø›—ºÐÌü¸ì³‰F³ÌdŽ[Œ°ÁÍðã î¶Y•š½VÍ“¾A—šý5Ã1‚nêW÷sYÊ´¿3_¬KLä× ¸ ÀïmVVÍí'ãW¤¸L°?pÈSsÓ>#<ïCñ”Ù¥Ô·Zî¥Ý@Ìð- GHêÎ{Fª Ÿp ' Eqyî·Ü·.ôr9ÔØþÎÉW§¸T•ÍòŽ0“ͪb8‚¾¼ÿz%ÏdæõHq©ëʶŸ)<öE–ÿì ÅåÁu¸¶3¸ŸËŠåÉØ¥MèpíE—Aè‚ÅŸ©y"HáX¢‹WS\:']ÚŒTótäv wió$ÁÝôQc¯Ws3 DáGíOqi&Îiw9xN‘ù—qÉ6Ïiw%Ãqú/z«y""ÇûPë°Zé zn™0ÃZÝN"n]ÇÔêÖˆá¸u7å4½ŸÎ^ŸB Ûaq †£oÓoÍ$5·9"ðW(.nÖÅåÕܦpÀ+R\®~ðø³îöŒ<¾-Å¥•¹Æ5ÍsO‚Oc8Γú¢Ü^ýk»±ÌåöS\†e»£‰Œ2ÐÙ;ä‘m ±Å¬l÷?)./7´9EÍ=Ï57´9âòÒþÙ|…–›Ê5­á+).Óû… =®ç~„½ÿ… =ApL}tlzp¿úÖű›³jzPÿÚXŽª²ãÅÂãLÒ†\xÊÃ9à†_NqéYý]§¨’Ût—!š‰¿ë” ¸¼u§<QÀS\jÚ7¼¦¾uÉ(‰qÜÞd8‚ÄŠ û<§Ü3—‰Ø;PdØa†#‘ø誯h¹]öŸAqi 'œSD]ø„M
+­Ä5ªNe8B–•‰õ.v'–•IQ\š ÿaý­KùItÈý‡7S\zVþðÑÁÇR\êù{«¹Âç”ò13!¡_gø6ŠËk3{óCz`{áC)._Ü‘çªyÇ(ü‘ñ…Ž>m¹™‡˜[‡]ZåfþEq©i›?SMx"¿*ÈÊvº çE6¦Åeu QƒôÜ´°>ø—/5)ƒ×¡xþ'Ó©šBko]|Å¥WY9ó󉜒uØß…‘;Ŭr^EŠK§´þÕÅÔÜ+¿×¿º$Å¥{pã´'Õ<ˆQÓþ4Å¥ªœ;ù55·É¼q.ðä9—º®è[ç'2ޑⲸP}Ò¾ãÿ4bç$¤ª>é
+ýü1xë'“ð0?oø'—ÊêîBÕÜðâø†c,Sí‡?ÔܦYM€¡¸ À'OÿŒàîÈÅÉÓWQ\®¾èƒCz^ð½/úàOŠË÷¾ç²mjž ‘òÑð—
+ÝÂ"æ¨yÂЯ+Òh>Å¥…­YÝ.çÙ žPÉž+³¤`Ƭn™É Gø}ƒ9“˜;/®Áœi—>í µ£Ô<ŠÝÑ<ƒÖ>IqùÞï¿î5|—þîþë¶2IÒ½ë«?™d˜@=ŸîÝ€àÇm?ô3 Uò3›¸³§Œ°i\¢QÃwS\ž{ãg€û¹$˜µ<Y~ßxD[ŠËÕýcÕ<F8ÐÙ1Žâò½/<RË}Ïå¯3|4Å¥ºøü§ŽêÂgÒ6€w#¸;½®ñ9¨.2›:s*|æHgð™—á@­öSÕÜ&çAf¡ö3ŽÌýfÈ.l?³±1‡O&a[8ìýï7c3ÅåÁÍjyHÍS¦® Áÿ¤¸þ×b˜)Íßr’çŸé¡¸TVW/½ÜÏåsû»Ðôi}ðë).+àÇ6×Us›ö Þ€áÈŽ[tÝ•zîá@gÃ{3ìC5Rsß ÿ JqYƒ®xsY-÷R†'Á+0Gó¼Ðv¼þÖ™G—
+ +挥8’¨ÿñ¢šÛD)>øDŠËs¯òÆ2©'^ÌeBdÓ2üIŠË»¸Þ÷jnúãh ×ÛBqé]Ìùþx}ác—&eÎ÷5Ž1ìï³Uó(H"ËÊï³FP\zµ+c]&CmöÐÄtæ4+Ç;R\\‘
+çwŽ²óLþz¼Åå·è÷jž0geøO ÇœÕGÑr{ø–u>®¾u.u]µ[©¹M0›ŽªòØ•}Õ·ÎôÇ‘úØ•ý).…ïßXö€ù›}²¾´6ZÇs¹yû7^Fqlòš¿<·ðû sŒ·Ûb6 ñɫÛÛ5ÕÜfeJƒ×!xˆ0­WÌÑó
+?õ¼#jnƒBå¹O=¿0Å¥s2eß)ZnðÑ)²ïtŠËÒÆàÁW s:ÐÙþ.¦±|?xpŠËTçonÏjœ½²
+ýÈG„›á?Q\Ö&~q¾šÛB𗘓[ÏÙ¥ævÞ' þ+ÑX¸ãW§
+Ï„.dM ì¡ ±ý°_Nq™9<ëF5·/w
+wûÆÅ.õñƒ>¢¸Ô´‡/xHÍ£(™“Ã<Lq¹u·ݧæ6“X ~€âRÛܵ}Šž›¯+>ârõg¿î¤å6A 2J=ûuWŠË­;€-¥ŠÂ›Ÿ¡O{à×6 ÇaÖ¥·_£æqáLäÒÛûP\Þù¦%%ÇKcò|{Ž–‡hÃe¸Ì”¶;üì{à~NIZ ·
+ø—O¦õ_-µ<slãÅå‹:åuáÓƒ‘¡SÎ¥¸Üº§mÕ?8ßm«|úØvŠK]7þÆßÕÜSàŽŒR/uš¡¿uém_êô*ÅåÖM™3UÍMÑ1s2eŽ¾º°\©Ùëê?»°žGqùÛ_=\MÍ“!ŽT6¼:ÅåoŸûà>=wA¡†ÿFq©.¾¸xQQ»<¥_\üÅå‹[³ÿ-¢ªôBÇç3C¡—ÑWAŒ©;/+Nq¹óÇ.x]_Qîλ`.Åeò¡ôß¿êyœ@t_é¿ÕUe†Ë|]ýQê«Êоþ¨ÿ0\©Ž :LcªJ, 7è0“âÈ–Y¹”þÖ…æ*[U.Cq™£Nnm®¯.|Ô´†·¢¸Üº»æ¾ ¿u±»uwÍÈpl»˜^¥æ‘ïŽPŸ^Mqt‰o¿<Èi³¹Là§×¨ãíƒ).ã÷Û'÷QsûÒyàý).ÃÿßFMÕ>ti‘~5“âRU–{;Ep—6¡ÜÛ§1­L“ŸÑߺ‚9ê&? ¸ôç/þøÛ}wdÃÅ»=#žšz«šûžM<5õŠKá'ݼBÍ£
+õ¸Oö ¸ÌYþÃj5#(uúk)Ž«ÿy@ÍmªüŠË¼M3¾Só8´¡Æú—Ör™p»²æ05|#nøp†#Úgñà‡)sWÏÿÛÛýµ¿=xfw–亙ßÙÄD ð‹).Wÿ»Ö%jîù)™¯3üZŠK=_øÄjž(8r±ð‰Å¥ª[ã=5|Œã ÿ€âÒÊ<ýè Zn†ß.ßÅÓÖ¥¸TVn£.|àa Ûð3).“â¿Jp„.>‡âÒ9©øfâ\R>f~ç F*¾Q†â²|_´Ï Ç’VÑ>gQ\
+Ÿwc’à¡ïø©—6®ø~ ólÈ>õÛ-¥˜%.¾ÿ)ŠËªÐÔ1ëy˜ŒÑ!C\Ýp™%®7á!5Oûnw^½ S\©ß\¥å¾ÝRš¿†áˆ³ê´û°ž®oÓi÷1ŠËÕ'l;EÏ붵¦¸<÷ÉKÏÒóØóoKqéŸêjn”ÁŸ¤¸Ô´¿³àÈ8aø·—ÑDÍwèyä2 Õ\X˜âRÛ̾ü}ð ‡c‰2<r9 ÿá²å¤}©2óÕ<°¸`øBŠËs??çƒù'¼8¿
+ÌÂö¨MD¼¼ÿöŠË ´è¾çÕ<òprŸá(.MäŠÏÖëyˆé}Ã7R<¿ðíþü6%<³…([šÓÌï×!7ül‚ã4«öÕÔóüƒâòùŸG^£ŠGÕ<Æ.-R¥Â ǃ«xß jnºF¨m*Þw3Åå‹ë‘׃¸u¦>zä]ÅpÄ_×õ2æÁ!üþº®Lá}$\1ýj5O¿bzŠË­û¶bs¦ðhã¾­Ø’â2õQkêpæµÁv›ZS£¸´qí6ëÿöD€ù:Ã=†c%ô¥_:ƒ›†/—ªÒn»@6-Ã/¤¸<÷JK/×sÓAÀ{R\>™º-^Rs?p ä붘LqéY=ZñN=ÝDë£3‹‰ Ïy[Í#Ñ}†¿ËptN–~W[Íã¬áõŽV槿¨yºôŸþº‘áÈWY²hc5O˜d¼ÅeZå†×´Üƒ°*7¼Aq©*óNz–(¼Û›wÒ‹—¿ýߪ1·óóïüvÅ“Ò-\Œõ¸´ÜåÂ3¿“¡á).3¥í;>¯æ¦[\À_d8¶¾rù¦ðŽ_QˆâRQ7™ß–(<²¬ÞŽá˜tÚ8~4Á‘ÎÚð1 Çáw'…Ï{F Ïüí²¸Ðñý‹W«y¹mVï_üÅe {Õþ[À}˳¤Êð8J#5ÐUûog8â.¶½:GÍS¡‹»Øöê<ŠKYt÷-÷M#àÀ¢»÷P\¾¸¥7ôU>x±ãý).ŸÌò²ú[g F–—]ÀpܺOúnPódäû¤ï&ŠË­ûá5÷Ã
+øø®jžŠÓ¼;ÅqÌh¯IZîG‘›x9Ök*Å%l£å’]êÂ'C,a¾›âòÎ/þf¼ºð¡K“bøŠË'³îɱjn†BòÜ ŽâòÜ›]Ž/Îü·9q»é#)»2 ¿ƒâRU®Z‘àúó«‡Çpôç¿x¬3Å‘»ï±n—ÅÄÃÏ'Á}˳ ÙÐ
+g¬ ]VŽâ2‚nñ‡þo7Ý7ìPkñ‡þoOÙ-¹ù.½IB•üü Ðì…·!ŠÛðK(.ƒ‘'ŽQó0H SúÄÑâ—/ns¹?Ž/ns¹¿¨«KUÙ~F æ¦}ÆÄKûÅ¥wÑã€þÖ~Œ ‘J3 'ë>µ<3ñ’uIËüÎKZuŸÚOqé´r»šÛ•
+Çjž(Ho[ªpZÍ3'ç~ÕçêycÏȪÏ£¸ŒeR]Ò?8/|V©®?S\úó5a‚=•™`Ï>Í›²Á˜9©ÑèAŠc5p[u5·KZIðš÷ñÜ;íùNËmì²çuÚ³…âòÚLzžšGQ
+}›iC/ ¸\}a«ªúÂûn²qa«<ŠËœÕ7sbⵉqë¾™“¢¸ Ä6u®¡¿u¡K“²©s-Šcâ¥ëúÂGØjdøGê€u'©y:Laùþ÷u'S\bS÷éo]œFÂÉÆ©‡(.5m·W¯Uó8D3aøõ—;ßd/¦>ò7>d¦lJ&Ô6Mö®¥¸Üºªí»(yÚÄ0ü¯ÚþB†ãè½R —©yàc·Žá+Ž™“'–oVóÐ øVŠË¤Ó² CÕ.åcUÈðaGEÝþÔö!¸ŸSºù$«óÔöI‚'ÑL´P^Íý8…w¾í€JÇé´«Öh¹—p••áë(.õüÜáú«Û-/IpýÕ3§*å2‰SNTß:[W%ÀO¦¸¼6Ï|õ!xfãCö‰—´]TÂ<í3_-¥¸<÷'®ß–σüY+jó;3 Ãn'®ßAq¹úüsÁý\y:N`øüóŽáÿôO«h¹ù8ÌÚð<ŠKeµƒš{é3'†×¤¸¬œÐQ*«ÀÄæ0ñØð,až¦¸\}ò”ºjîG¨* ?‰âòÖ-þu³šÛÝ:Žo¥¸<÷º[¤¢¶¹Or™ú2±xëên©Jq¹úiÿY¯ç¾«¬NûÏ· Ç@ì寂g¦û²ÌØßù ^Þù&ÃoóÉõyZnw„"žö“ëkR\º…Óše8r6NkRŠâÒ§}õ¥jžr¹÷ ¿‚âò½ŸÔñðÀÏeˉùYÒt
+>’âòκu®š‡¡‰£nÏpTÔëvlWó à °u;vQ±Fƒè&Z Oøˆ«4üÅåƒzÛ…êÂG›æzÛÅ—…Ô*½K·Îmh­Ò» Ãqì`òPe5÷C¹hxUŠçw‰;•k½O_x)Ü ßOqùâVí‘ì÷A˜™hÍÚ%Â̦¼"Åe8P¥ç8‚'0©Òó†ã¥=ZþI‚»Øƒ£åŸ¦¸~ïýyOáˆÕ½÷Ÿ@qé®úe5óà°¤µê—5Ôs—ná#»Ð) s›t2¿ öQ?²ëtŠËƒ«´ñl-·)+
+øy—ç~\ÙqêÂ{‘K,|\Ùñ—/.øñT5÷ 1~lMqéUÞ~a?õ­Ë,ì€d8®þÄØ&zî»SžÛŒâòÚìû­ªþÁ…zÔû~«Îp´q=½¤æ¦=Arž‡&Q<’Fê½wÔ·.ù&ò½E—náïÕdÞ&ˆìVŽ\xÆéØñeJnÏñ°'tiÍõO#<oiÍM—ö½ØžßÀsÛìc~g#±àŽÌBy7îÒóÀV™wã†#Žz奴ÜKzI¤ËXyigŠË­ÛqÑR=÷Sxp;.úŒá¿¯º&­çq
+³U×´f8öÇ}~xŸž‡.#ôç‡Õ/m†Ë¸ÁìGõ¯¹ó1øŠËƒë žÙè”}ÒÉa…Ž/g8Âï›–zRÍ“náOS\n?¢‘š'\n^ÛR\ºͮó›¼r€âL—ØIq©.ή²@Ív羈âòà¦÷š§‚¾÷©ÇýÃñ½L#nÛfõE0“âRø7£Ô<¿ù3Ÿ/¥¸<÷×ÆÏm³Í븃^ûÃѧíÒ·Ÿš‡QŒiŸ.}<à“’§ è ?âÒ£žÔên-·f8iR«{).î–5çþ/ö¿
+_õaø—÷Y›ïÔ·.¹!ðgm6S\©ÅG0ù¿Õ(ëò}`·˜¹8êÅGêR\&¾{£3Á1’2üB†#†ü–qxn‚D& šã1ÅeÞf̪sÔ<ã¤NÃÏ£¸Üº8¥4wn‡XX€SJ•\>Øu+¨ Ÿ´‡´€Gqùâ/µC_øLjþ Å¥ðO l¥pQ€ö©ú—Ör¹ó+xzºÅÄ• "ŠK¯²D½úW°W¨D½F GªÏF%OR?8»%4®¾ºáØÀÞñå¹ËÔÜ4’¸úËs?%xÁÕß:¨¾uæ—H¢þò¼Â—7åõÒúÂ{®ðS^/Gq©ik7‘`¡ ›U.<¹ããk7iÂp™hm÷w‹Úà~NɸÌe"{Ð=xSŠK]÷ÌÁIZn†ÀÈ gøLŠK~I·mz^p4Ï’n;(.³…ËŒ'
+` [¸ÌŠK¯òœ‘èÛ$ƒœ6÷ÙÁ·ïFq‰|(ršzägŸú°Ç”„üi†c,S&… öüð¼ì±´go²îQ\ZصÍïÓòž±²¶ùýG0ðwß«yàZXÃ7S\ZØåg¯VߺTè–ï—Ÿ½†â2SÚw+FÐù‘¹Þ´pèUöÝVˆâRÛ,zh¦šÇQ„t‹z•â2gõqü²žn¯ÐÇñ‚ûÒD¶ï¹OšÈÐËmêÃîð’ÈåÕs_%ŠËß^õËÕ<*X ­úNOŠË­{>xŸ(<ŽÞ3ücŠËk³{…4Üw›¼¶`¯’Ë­;Øc®š§"—"æ`—6îÒj'€ç6ùÚM¥Aäxm†#áä3_VsÛ¯óÀ§R\z•ÏÖ?YÍíq>xSŠËs?§äïj, ŸSòŠK¹§È%jîÔ´{Š\AqsÒyj1ZØ“NjGqia›û”þµ‰1KløÓ Çæý_^í£/¼é$À¯§¸|°Ý_—ó"Ãü4æY»Ä6r!D¸áWR\bW]AÍM[*ƒã¸üí#ïÔ>r™…FÞKqiãÚxµÔÜݪP¯.ñ*ôåèYÄ­‹°œ÷åèWŽÅ…¼à
+½ñà\ÞƒBï÷ ¸ KvU¿u6Ý%²ç•ìª®.,Çr^zö§úÊÊÃÉ}†Îp̘½<çG5Oš®M¾â²:Ðaà¡ŸË6+»ž—Üu‡açR\*«°þ—Zn{¥ˆ%믥8®Þa”š^Qa‡1—ʪW¡Yê[—òݑʽ
+½Fqéœ|ùÀeê›—™¿| ÅåÎw¼ì%𜀳<aê*|2ÅåÖ½5¬‰šÇ‘Væ­aÍ)ŽAèØŸôÜðÒ¾5vÅeêcڑ£œ1·¿“…ùü;‚§ðÚhš6Î$aË>ˆ3iÿœârë6TüYÏ7Ù¸¡âNŠË"rÏB»Õ<]p@LÏB¿1ã¸}ïÕó(…¾Í¾‰«.݃÷vzî6ûž ¸|qõ~ÊÓr›ü·®ÞO'P\š‰Š#ª¹]õÀo¢¸Œ on¹JÍC™ÿ ÿ‚âÒ5Ðc¬ž±ÌÏþ,Åå{ì¥jÅ)TÔïíÁpTV“NyQÍゼ…“Ny‰âRQWXŒf"áå’
+ÌòDèÎH­°x'ÃñòSÑþjž 06üFŠË¶äcõ…÷‘AÎðn—צÒüJzî2^âRøã»%•<‘YØñÁO¡¸þÔ¶·ª Ÿ
+ݦSÛÞNq¹ú%‡è 殺Ñé’CÚ·.êT§Ôhp?—M^öw6»ãc(Ž3´Òr/í'GݪAÈp lh¡/|ŒrÃ}†c!õ¸à=}áãf >¢8¾¸.ÓÕÜô§±&u|—WŽÉÆgw¦ô·Î…ß~ÃqõE7ŸHýíxêo—öýë?Û¨yÂeœ0ü,ŠËÕÖIÿÚ)\ýçaR\ÞºŸ_ü@Í£sV†ÌpÌYÝؼþÖ…)7ycóþ Ç^à÷®SóTäá¤÷~ÃpD¼Ô;:<§m•ö2aèrûÔ;úÅ¥?S§Ô<aSä€ÿ‡âX;Eu?Âù°†e8¦ûØÑVÍåðã|~Åå“yèô"j¹,©†g8–°ç>Ð^ÍSvq¼#ÁÌÛ¬˜ö½þÖùIT•+¦ýDqE.¸ÿeý­óÝA! îŸJq™`ÿà‰ñú6FbaÃ'R\fNvž©¿uq
+uÝÎÁ¯2uÝÑkÞžÌ,ßûYy2óÉÆà‹).ÕÅëªèyŒpÃó(.쾯ƒç´Ýò”cWæ¾s).YRK/èKð@úu†d8ŽP·Ùh5·Û½cð±—švͦnzºùù5›ºS\®þJí£Zn×1‚~¥NŠK—xê#ÔÜÔÓ±ã#)Ž,+‰õzb®Òðo).Ó}Á§5Õ<4u]¼ÃQQWÿÏ%j¹è>Ã/£¸¼u³¿Y¦ævš9_Aq€?±ò_ßùÿšôVÚ?±ª(Ååo¯¨“ºð¦ªŽWW™ó¨åƒ™|[Ï}:3¹€ârç;7ž-<•Iéœ}Ò)i#¥
+ø—iŸ¼SÀ3«|Ù¹íSˆâÎ[1âRYU|d¨žnº¯â#P\Ú÷óÖnWs3äÓyk÷R™…þ
+Ô¼`¶ÐðÅ¥C~ï4©œR…Xn×”Ò࣎¿ýÎî¦xü^†#ù–w>Us›X8
+ÅåÖí}³–š›w…ßû¦þÖY.l ·›>rèÚ«Ä¡LyþÅe÷ý#þ%jžqD‹á—3Gë.ï^^Í£0…—vy÷J Ç™Jû×¼§åö°
+ï_óÅ¥>ý°¯çæ. )ŽDâ£eÿ»za.‹‰öw~Ò¥1]Ÿârëª}?LÍý‚+Õ¾AqùÞßVQ_x/½Ào#n纫ÞJÞeé\õŠËß@pwèá†Ô ŠKû^º/UxœøPºïÝÔß._\ýÞf^yç _Hq¬­u¡þµ ÖØðK)ŽiÞm³Áý\Ž›´Ü <Ç_g8þ[1®¥š'#lt2< ¸~Ó³Óõ…/€ozvÃ1ᶵÁ/Zn:' L¸mm°âo³oñéê›^]ìx[‚‡8Ñ~ê•»Àƒ_ZÓ#F+cø^ŠK]÷Ÿi5ügxkŠËK{llüoü¿RÍï<S]à)ŠKM[kàr}áCä!7üSŠK¯ò³ËQYEvou]â(–éƒ÷ ¸<÷/?œ©æé‚ă_~ø*ÅeÆìãÛƒû9rß qôžá(Ž#Vý æÛkø—«·~m‚šÛpÚüeŠçWV
+Õn¨æ±I#exŠËßÞpË^=Œl¸åW†c,³îæ6jžRžãgQ\¾÷µ×œ¯çÆï†w¤8Ž\ü^fÈmrò\ÐÍïìɺ!xkŠËÒÆßé Ǯ̿ÓßQ\÷nï¯æ^œFöÞíƒ(.=êÏtbxäxŠË'Ó¬üý­3©
+3õüÁ§kQ<¯Ap·K«Öß]Ô<i“Õ_Dqéܾs‚š§ì—1|2Å¥²Ú;ïgð̤Sö6mg¹1~ß;oÅ¥‘š>2OÏ#·_fúȚǩO¬æAœÂöù§šR\>™Ç[Uó(ƹ†£8#ŸÐóDÁ&î;Ÿxžâ²ŒûäkKóy™•Ûê;ÄüÉ×VP\æ*‡}W<$–u¢Õp{°p
+¼ Ã1š¨\è$=1ÑjxcŠËh¢ñ ñjnòøK—zkíÎZnêidY1üB†£žO¢¿u¡Ûà–<ð Åå‹{÷Fú[ç!_¥áÍ(.»ïË•Ð_=#µáú«[.ÏýžÁÒ1 ìP¹=¸”}R†/£¸¼´K?(¡ä6*Ômæ]úAi†ãÈÅ°Ùjp?§$l™ó°\â‚°ÙW—®ÑRžš§
+Nd>P*Aqi ªÐBËmVg—a¦‚ºð–#ÃÌüÊ›Ž#™ ÿâÒÆMÝÜ<“¨$ë4¯½Lä~3£«šÆ°†_Dq©i+~DÍÃ0(à#ŽLbsŸxšàn5p.:':.ƒ‘ŽM'Õó(DÒ†¦JR\:äGoøJÏcL÷þ Å¥‘jÝåw5Üî<Ã1k3®Þ¦æ ßN;ãê]—I§Ž›vèy˜Dm³©Æý÷ºÝ:›jLc8V¦n¾€ªmüí»©¿]èJË<m`EÊaò!ó;¤2< ¸ÜºŽ,Ps߆F‚/¢¸„ë4j1\_xÏå=hÔb$Åe,S¼øhp?§”PæwAà&Z‹Kq©¬>j‘Òr3q¹û>jÑšâòÖ•mwºðQàòY•m×âòÒÎPU_ø‚³óæÈ£¸¼óó~ýC]ø8Jc–xÞ¯R\®¾­ë=·SÂà2éë½Z^Íí@¼"Ñ|¯Ò‚2z ŠÛp¢ðA(ŸLÇã%iCŠœÛM±ôi ¿˜âR]xÏÎÔ󭆿Fq'ýñ¹ZnšÈ4fÈ'~|űÑiB}5·µE
+¹,©[kÜFÜ:w6îÖwR\Z™™£0È1ɪá)/ÂiV3G5b8úó³o{[ËMÙ‘Þðw).oݼr·¨¹MTâø—ná–§¿Ró0r§œlyúkŠK·°äÝ+ôÜV˜à+).ḵWܣ汗ÀÆÆÚ+†P\ª‹ëÑ£Ny9¥x5¿³’àO2ÛmÊÿ2HÍý‚SÌÊÿr;Å¥žßÛçB5·G¼Fà—P\ª‹#Ÿ¨äfèû¼1ñ vÆ)îê~N¡‰A*³$–oÈpIÒqâ¾ë˼á(.݃õ»^Qó Jb »~× †cÊk÷)³Ô<,èí>å5†ã‹ëÝ°‘žˆ|0¼ Åe¼p`eðÜb{˜tZ^ëQ\f ·ô­¨æÉS^†ë o8⨷&dÓGör
+Ï l@l€•‘ÅO~BñøgG”W¢Ã1 ì]­7Ñ ¼wµ> ÇK{C¹ÇÔüÔ åFS\&O˜9™(|„D%'ÌœNqi"?žØ™áè˜}<ñB†#TiØó1ÃQ] {þŠË`¤ßõwÜíTêwý} Ç`dï·çè¹ïö~{Å¥{Ðeþ¹›_á­ë2HÿÜ-—¯8_ÏÃúó+¾Kq¹úìçß!¸Kž?ûùE—צMéçÀsKok~ç…XÆ5üEŠ#T)š®ç’°>›ârë*Ô߮榉ƒ«PÿŠK÷Ô³Ô<i»1à¯1éï–}÷Í¿ñÿÞØh~—°ëÈàßS\îüî2;õ.ö°cew™Ý—1lâùîjžp‘†_JqÇ šTKÍã (àõŽz~w1ÙZæo|È:
+NöùáØ!†c8°mPo5÷
+Ž“Þ6¨Å¥²Z}ÈÕ68u6+OHgxoŠçqíŽnzƒà±¼´†¿Gqùâæl\ ç¡k"çl\Hqé×®\’à!:ä£+—a8ÐÃ’k¹o^[ì‡ K>JqY@?öö=÷CĘ{{ÅåÁ•X~¦ž‡¸ºáP\®¾áâ>ê—,8~nÃÅ×S\èþR¿6¾©¬0gõÁ_Ž9«®©ejFAþ)ÃѳZ::¿¶ 2oCËy†Û4-ø[—îA…›¶«y*F|á¿P\ú6ç,þXÍãùë _Nqdé¾
+ÜÏåðz{™´‹Þ7ü ŠK·ð»/×s‡×~%Åå¹wú|=\”W÷§ÛS\>Ø£¦ª¹]ø‹À§S\Æq¥^¤åf8„xÃß'8FK}7œà.åc©ï§¸ÜùO×îÏÌdKÚ`yàG¨¨?]»Ÿá8Ô¸òÒçÔ<,ÃV^úÃQÓnêyPÍý8‰ùºM=ÿ ¸|2ËšÌä” ÆüÎbÇʲ&³).o]Å£5…‡^.¡Èöwvצ¸ FZ~¹HÍÍp
+ß«ä45=—y WÉ Ç@¬U™×õ<H¢‘jUFë,—x›:‰Âi©¬ UÏCl·éп?j›Tf7nÀöïß„áÈíÓúƒ¾z^0OÛúƒ—w~{ËÂJnϲJ¢K¼½e1ŠKõ¼æR< >ሣ~aãqzâl\Ãó(.“ÑèœygðC—îÁq…Ý÷áíï|›j4ŸWû¡Åå{/;ûÿ´Ü&ëÀ/;ûQŠK#uo·[Õ…·é6àwP\ª‹£}ºéyà6÷íÓâRQט^RÏ#ìÎ3¼Åeî¢þ;ÿÿ×6« wÓ}†w¦8Þ~“¾ð.PÊðÛ(.{‹˨¹ÍÁîxy†ãÌ…¼éˆ»°Ûçsã±ï>ؼé_èy€SJ;¶îú‚šGá?øK—Wh=¡ùBe ǵ¿KÅ!\¡õ£Ž(¯J£Ú+ o·UºöJ£:S\¾÷¢“PÛØíuÙƒÀíïl"ñ4xw†£sRâ„ÏÕÜ „åUâ„5ǦΎeß8QÍm\füd†cÊ+,RTËM‰\†g¸ôçÛW%pßór9RÙþΆ&à—P\^Ú[ßبævs_|ÅeâåÐ';™Âð_Žôõ…+|Í­…+P·{…Î|êp?§å{ó»L%øbŠËÕ<´@Ïãæ¨<´âÒ£n¼àG57¥G¢’Æ ¶Q\ºÄ§µ¿”¸uneä´öWR\þöÞÇÿ¢æö ßKqi"Ó]®Ðr»|ŽF*Ý¥'Å¥sÒs Füü㨲."›Ÿ%]âû03f}?¨ æ)ßå5êûÁq DZ_ËÍ÷s9ŠË^ÆNzÅà (. tÉ>W©y:@6l,¬É$x#·!+Ø$O¥¸´q ›?®æ~ä6¼,l>ZÏcûYùnú›«ûàÝ)ŽÀÈ7$îÂN+äă̮Î
+‚»ð¼ÂûVR\¡÷sšÞ·]33 ôÁ«P\ÞùÞ¾¡æ)w,‘áó(.w¾jߣZîÛ#¤™¨z}!†c {ð6_Í1'†Ç—º®Hמzîœá½(.]âqc&ªyºVfܘ) G+Ó`Y35||2†·¤¸üíMÿ¼TÏcl)5ü
+ŠË|ݬ»ÿRsSO#…û¬»1\ªÊŽ—»GÍAXÀ笠|26è#<ôÒQ"Úd\8ÄüÂý(.®îÃÍÕÜW‘÷(.ßû{ÓoWó„Û¼oø]—šöÇ>PóÐOa¢õÇ–2]£ò=?÷-Ï4b/§e’Ùð5 ÇšÔ™kÚj¹Ÿ*83ñÌ5çS‡Y?¾KÍí°%ßKqùÛÇ­k­æ™ã2ÀÏ ¸TV畽XÍÍÿ
+õ|•+n ¸4R§?{Á#tÈO¶Å¥›<éTõ­KÆ.Îjò¤Ö—º®lÂjžþÇêâ ÇP¯Ú
+/«¹é`¶pG…© —z¾c©{éy!gc©¯¥¸4‘õÞøLýàB›ÚüsŠKÇìò>!
+#§Óå?¬¤¸ôm&?×VÿÒFnâeòsÄ'¹½#/~<øü¿CR ·Ébð—(./mçýþÿŸ…OF)|2÷?Lq©.ž¼¨’š§|wzÝ“Ua8fîn^e*3Å5ùžù]*H"+òÝ-Þ§¸<¸'ÿÓWÍM#%Ã@ÃP\îüˆ%ô<ð°¹oÄ’¦÷Q]ø oÕß:Ïm¯óÞNq©mÆÌ8[ÍCÛ. ?âÒÂFMg€g&Z³wNÌ×滓y£¦¯Q\ÜÌ3Rj„X—1üTŠËÕ7%¨ybmøG·Ðó´Ü<`|q†‡—·®ÒÊê‡q
+Ø+­Ôÿí–#oá媹Í7éøQ†c¾®Öðeú—ÖÀþ ÅåÖÕ^SUÍ3)©À«S\jÚ¼ö’`ÖOg–6²ó´=‘ m\^û).#©âGת¹o
+œ…}ôkŠ#Åë_ÿGpkÐ¥þÆpdËlûçàv}3‡¸ ¿O UHÛ?;R\VÖ—Ú­æA¢ÒúR¿2ƒÐf]Šé ïaUÈð—z~yÍõz×hyÍo).kR_ñQx?t|þ£Æ"=w••áK(.u‹Ú¨ylÿ ~&ÃåuÍbiãL“m'^²¦Eòív›ðA—®Ñ=ƒ¦ê¸ý ×1|ÃQø¡SšR< Þ‚á84á™ÿ4Vߺ´çry=óŸæ—z¾Åª–Dá1sb¸ÏpÄö¾âb¢ðÈåeøeÔß.Óûaïõà~®…#¤¿3ü[†#ÎêÊQÔÜÎYEàR\þö¹ß­å¾º¤ s¿—á˜ê¬·õNý­óSIÕÛª.|†K÷Ào_ëoßHqi"·ÌÎSß:ßE÷~ÃñÅšx…ºðæÆá{/4ñ*†#ßE‹%mô…#×D.9‹âòÒ¶O½ žY\È(eÿéb†/¦¸\ýãEÕ<amx ŠËôgÍkéy#ªó³æuŽ©ß-øFÍ#mø÷—ê¢ÖÌ=j']kæo—Qäó·]­m"ì‹4¼Å1s2òu¢ð.iC‰‘sŽÚ¦ÅcuôÜO`u Åc'R\ž{݆øöˆ«ì[ 3»:Ý©Ä5vßËpìýï?¨9Áž7Èc8ú´ý'ÜÇÞå5šp?ÃñÉÜ^aÁ}\ýö
+óŽ«Ïû­-Ã¥[høùTáeƬåâ†÷ž×rqŠãX¢÷1¯ ¦÷[¾·„âòÁz©Lákä¥nd8&£ã«P_œ^Ⲙ?˜¢>ØüTŠË­Kuþ‰á¨¨S·S\
+FpõÅ…àWP_œt®hÌeYÇðtÉT§á5(.ÕEµoVi¹ ÄÆÂJµoÖ0˸Ö~§æ^†Žÿ@qéÛÌþ¿Ûô…˜p›ýwR\Ú÷%Uæ¨y¢àŒÔ%UÞb8Z™¯JRsÓºcÇÊW¥3ÜíXùîc5·ÛCÿ„âò½7¸½þµ‰=[Ðàö~ G=¿­û úÂGîˆÕmÝë0±—6„›f/—‰VÃmòüx’áh¤ReÎPrû»0pülŠ#mBÙRà~Ž<³Õ(^žáØ>²ú5÷\sÃ÷P\fÌ~{ëC5]z[×3¹÷ó®SÍ{¢3øÛ—š¶ñôcú[%±2ÒxFŠËÕWUßJ½u>øvŠK·îÓÁú[»5©uŸa8*êÒdžéo窋ÒÇFP\:f'äý¬¿uf‰ ×°†£SzBͯõÜO!Šû„šŽ®QõÇ1ídBÔ²O6Ú 5áVýñC Çþ¸No¿©æ‰Øí‡íôö|†#@nuÉ$äo!ÏÎÍïü8r|Å¥w±}J95Oî@çíS*R\
+m­ÓÀý¹Íè„E¥kkµ¡8Žm½HÍMŸL•ÖK(.5í½k¯e‘³&´ß…!bÌî];€âÒ!¹oš›š±‘û~%x'û,›\HÍC»Û¼Å%¦ô’jrô^¿ñ!k@¬m#b·ú’jP\ª‹Ñ%¨y%‘jt‰CÇ1dçÎ x„)¯æçÎ&xŒ„Òé-’Ò9Hd†ÙyÂ"
+Wßpá z¹“>6Pš)<Ô6PârçÞ:Bÿà|œViøã—^eõKôwÞôh#ÇõwÞpÌU& Ó°zÔ†—`8bžÈû<Èm˜4]bœkø—Êêç£mÕ<ŠCœþóÑv—·®ÄŸôÜmö1|;Å¥sҦƻjžŠÒØNÛ¦ÆbŠK ûz‹Žjžöpç ïBqi"ÓÏ•Ps›ÁÝñÒ—O¦õUóô/mâLäÖW- ¸¼ó׆ˆ5Êßf•}(”2uM8^—âÒ¾ÿ¾û57mœ À ïÁpL6žß¸¤¾ð¡‡˜“ó—a¸;ÁÍ­ÃæÎSQ‘³ýßžŠÜAÞ»–zj¹ó& Žõ÷è²3Ô<±.cøÙ—×&µðoðÌÄKö%l{0;:µ¨Ååêo?ªåvƒ›Œ¤Ú_¼£ű€Þj»ºð±‡ä<†ï¢¸üí­¼EÍö@kð;Ž4§;Îú]Í£Ð%œÜqÖ Ç÷^nÙ/Äkƒ9+Ã÷QÉu‹<Ep“NM‹<Íp,ièÚDÿÚÄnûüˆ®ÍŽõ¸×oüZÏÃPb‰ ßÈpìÊüiñÖÙ$tàÄ[góyå¿´ys䈖 s_öt{+løfŠK‡¼ÃêJn·UºMVÿÉpüí»¾©ç>N»0|,Åå“™Þc–šÇ¾ÛZ8½Çë—u™5oÑ>J!lcÍÛÏP\ž{[PÏçop˺¥ÔüÎÆÌà˜Ñ[î`8VW:KÍí:n¼-ÑPú„zŸé¹é’Gà«).ì k~ª¿uA€­Ä k®¢xþÛ©ÔµcµÜKÙV
+|Åeõ¿ùP9_&Ìßb–ÃKkº)$m>´ Ååµy®UW5OFX7ü"†£›ÍCú›!xþ0Å¥¢ðÕà¹mö íðù¬ ßFq¹u[ý‘zî
+1|4Å¥™(ÞDÚ¸0? 6ë»]Cv¼~˜âM,óÕ<a?¬áñÙgô…÷®cø5—ç~ÿ ë©ÂÇà).ð¯N<8Œã _Cqißkµ-Opt ¯Lqiß«ïw·.³ –u³á)—×Èðï îcøÊ»®Qó´âÜ+ﺎâòÎ÷s…–Û£uÑ«ì=¦Å1åµg°žÇŽ-ø}ϊ˃;¶1­æQ€%lÃ[S\¾¸S>ª­mB„¨^—âR]´XB]xSOûŽ—¦¸ô.¾­\TÍC+#†ë o¹Ô6EÒIýkã¹ÄÂEÒ§R\
+_â´#†ÛV70`¶E¥üßÙ“ûàÇ(.w¾Ö“{ôܼ´øo—áå.'©¹=ÁO¦8Ž)¹ xfò!n>Ø p¼Å¥®;8yžGH\`øo—Wìû¯Õ< Ø \ìûo(Ž£÷¶öPóÀ=wÃo¢¸|2.ÕÿíA¢®›péŠK=?cWK5Oygìò c¢uÑÄÞjžp{B ¿†âò·QSÿà"»¬~+Åó_›NÅÎí¥æiSQ§À¯c8‚Ë=3UxèeO‹”ÿ;Û)Á§S\ú6eîg?'ÿw6¡´ã£¡O›7î*-·;ÿ1á–7îŠË÷ÞxPeuámÿ$¯JqÇÝ^§æ¾]î¿žâò·/)ö¹úÖ¥BìÎ3üKŠË„[¼&­m"wæB¼æTŠKmÓ¯Íã̴Ͽ/.Èeâ4öËôk3œáØzPÿò¶à9¤îÏ¿L¥Ç/ 8ο$RóØO»sÀ/IQ\^›™ ÿÔr{¨2Bf6<Jqù`?+X]øT„³u ?Âp¤»,5»¼þÁÅiÈ•š]‰áÈkôQYâÁyîlÜÊžÆp\}÷»õ…S¼ Ã1õQ÷ëzà™ðûœÈ¿LfG-xCŠË,ñ]ßTó¸`’ù®ƒo3»´Ž«ý‘ž»9j×S\Ú¸¯·—TóD€­F†—c8âmN:wñàüoø[—6Ùú5·ù¤cð—öôi£õÜÇF'ÃÇ01'ÇFŸ-<ÎL´fo íÞy4†ŸGq™p|Ú¸8‡‰—üßÙ#“àI†#ò¡ØôÇ´ÜK{1|Å‘÷ M¨.¼ç¹žUƒ6 ŠË¼M·ï¨y"D§Ôð÷(.3'e.–-'~þ–Ò채íˤ“ácžÂ¶‹‹/A™Èa3/x8~Å¥gµ}׉jîň-4¼Å¥®+½õ -÷Òa•Ué­_1­É=õ…œ˜ÜÓ…âòΗûà9áÉLXæ¿/*åÿÎ~´>ø —Îɱ—0ÉììÎaª3ù 7ÃGQ\jÚIåúèyì6>L*×â2üo·k®šgYŸOqš0êM5·‘9þ6Å僽2ø„àÈ løç GöûÛší"8–q ßGq™t*Á}z¢Sjø ÇxÝKç«yÂC`¤á(žÿÚ´ûsRY57M©Du^‹â2®Ù½„ðT‡&äÿÎN¤ÁË2S^“oéJð$ÒœN¾åBŠËkÓåêëÔüa™]®îGq©ëVý\OÍãÐÕ´«~n@q©¬j¼{që|ätªñnŠËßÞ¹.¾÷Tfº/{™2—N`Ý¹îƒ w#èx—ž›A¾‡âRÏŸ6tªšÛTâø ŠËláˆTU=“Ø7"•Gq¹u_ú™þÖ….PêãK?g8êù£µ¶¨¹Š!’ùh­­Göë1_—ö²'ÎçI— ÆðÓ(.ò¦¿]¡æ)›Ð¼'ÅѯÛ<EÏÍh" >áh ß,[\Ïã=«73 èÔ\–ï;¶ò_SóD!™v+.ÅåÖ/çnïçÔ=HÛ5`¤ˆ)^nÅ¥_wÃEýôÜ >áh"_l¹…à1"Z_l¹•âH²ZüS57#1¤ú¬VüsŠãdÞ—ÿÖr/¹}R 'b8¦¼õ­¿uîà?ßb8šÈŠÏ²Ëebן¯8°-Å¥‹·¯Ró N¡Ooÿ’âH@wôo=÷‘íã ÇŠ0»qóZÈÔ‡Mè— ÷ó%’WcûM—6õXc5O¸ÅDÛQ©û·d
+åû¼ÏR»Ôu.}<3ÑšuÊËmøÈédøóG@쎟 îa=îØŽ]—;j\[ͽ Ddã©q}ŠËÕ»=«¹Ñ¨ç»=œ¢¸Ôów ž¬æaè"îü
+Ã4òóØõ.Ày‘†7 ¸Ló–[<]Ë=»‰Üñ™—¥ ï²êê›Q`¯ÉpĘuoDÜù(…¶{£“ŽCNWôš i#·º¢—þ¥5¹÷§ï”Þ…ÍæeÛè”ÿ;ó/ÿOßù4Ѹ`^•9JîÙá
+r8¼^~çEîø¹^KŽ­…ß]u#xGiçÿÎ\kß]u3ñÿýì¿ «¹¤8qößÅŽAè _ž›½™°È Œ¤½ø&Å¥??µó`5÷ÂÏ}jç! G¯²Ö{=Õ<]F©Zï]Íp锶/ÖtµšÇvÊ |-Åå{3«žfÆÌê@q©ë6Üþ¤žG.?móÛd¢ÕÏ£ÎÞ¯ Mß}¶ÿìÿqv'`[MmßÀST*Í¥RŠŠFöx )E‘†»BR)T”R"š”1’4 ™•Ò<R¡¢A„H„fB‰4ã[ëºÎÿ¾}ÇóϵÏÿñ¾<Ïq¼×ïÝëÞ{íµ×p®sœ¯æ6Ùf
+|1Ãѧ-ºä1%ìR&Γ*ºd<ŸóO© è×™;_ˆºóRmFöê#u@ö2Éü¯#{u£¸l·)W­·šÛ­ïËpDq—ùužš§=3jøBŠK§ô³»¶ƒg&ÜrFšËx¦ å‚隸tNjí[«ç>v¤¾âÒPïx¯ºšû¶o^“âÒP—z÷g‚ã”RÃ÷3‡&Œ¬ÙBÍÍÍCÚ„‘5/£¸4Ô»‹µf8^™ÝÅÚS\ê|Å[ôÏÝžñ³)._ØŠ‰Šzîý‹W!8öÇåíù±¶žûÈjx]†cæ¤Ç{ÝÕÜ ñÊôxïzŠË­ûì©ÔÜ|á0CþÙS}(.Òâû–©yÚNâ.¾ï}ŠËÕ¿ {]
+~ÔHx"ÆAŸò;Q܆7a8BR_>VJÉ3蘯{ùXY†Ë|]›znsðÌ{Î0-s™d~sQϽ”áØ9vÁ'jžò’XÚ»àsŠKáË&W¨¹¤1Š,›\Eq™æY`¶–gö@¦Àç1Ë÷ußxBͽ(ñ á“)./××?MÍ}/ÀŠØõõËQ\:äëv> sqÁÅݺu;§P\«
+6«yÒI`8P¡Ó· ǃÛþôznn]
+‡•Ós?”€XÃ+R\F‘\†HæìfŸ8<FB]pÙK GÊÇGJÒr×7#ÁøQ†ãÎW>І)|ñv—¥ §ë»jž ]<w§ërŠcÒiÈoú[ç!zßð?). õžÁ§ª oû6xqŠËß~(ñ¦ºðö¸¶ø; Gß{KIáÙN9Ôžðq”¶áå(.}Ús& Gvs蜽L*t–y΄åGö¼µÜ†…",3\1ˆâò·Ï{阞›qXüo†KkÓ¦ã@Ä”¦c¥å)Û+šâÒ%>¸·ššÛ,j>øY—‰—ó .Ðó;Ð _LqÔºdzÜsâ%ç1ÿ6¥GcÎø‡áر╖Jëe¡ss×èŒ7Î+}'Ååo¯¼é„šg’O ÿ²
+ì6jÍ3îÖznc³|iï»ÔÜt °´±´÷0ŠË+sÛŠ§Á½XÁÿæ2¦sFüY‚G'¼¼ôÒl=±ÉËð¹—ÞEâP5OøQòüÄ¡b—ÏÄ]%0Òˆ*å Ç5¿Ë$n
+3|"ť𛞭惸JÃk31äE·®RsÏOaÊ«èÖŽSJuܧæ~~oø†#¢uû×2[ègCVrFl§ÎÁvZÃçS\&Ø›ÓZͽ
+?üNq™h­Ð±Ÿšç/ß~ Åå+sFÓjnÏõø—¯Ì).ÖóüjsÊ Gks~ÿ©Zn§ƒˆÏ ¸¼°ÛÏîg¦¸ã>:ù|>Åå}/{yWðÿ+Üu‰3¿ËA/{ùµ —U¡v…Æ^#<È“»ð Öфá×±…m&ö= <3ùkqÁË^MóNì[›á˜æ=tÉ]jndöÀGRiRÇ´ÜI™‡‡¤ ©¿).ÝÂúcVª ŸÑÕÇ|Hq¹ú›5—¨¹çâqÃßa8bÈwÜ£æ®t†ï¥¸¬þNVóÐŽP/œ>ÊpĘ]tåjnÞWÌœ\tåW—xÚ]×é_ØÀA¼Í®ƒ(.w¾×$Œ"ÃÌ„[®M™ßùañs(.ÕÞ{€Ç:>ÞþÎñqL‰áR\^ØÑÍjž92¼Åeºïþo'ª¹ÍYþÁ1g•×p:šÊЋ³ÁÍòT˜FØFÃ'S\
+ÿõ] O8qÒed~焲åÄð6°ï9p3xÌyÂvIqõ=<‰@©9Zë¹yr ðv—Niµy7<¶®Ú¼›(.W?2©®šÛá@Þ€â84¡ÙÉjn‡#Èü߬Ã1ŽkòÈ<5BD2¾ˆâò·—Ù~LÍùw¾Ìö¿(.¯Ì¢û==÷‘˜ÈðâöATÚ¤'T)ó»èè=ÃûS\ÜèäÇW&ù Ñâµi8ç‡äâæßQDkÓpÅå¹Ï›×UÍÍ`c™y󮥸T›…î;úÂ> Ýå—ç¾áí)jn§yð(.ß÷¿îÓr'í;˜Þ/ðëï—¦²ôüOõÜ °ºôüÏ).ýù*'õÕ?8ÓÎ'ÀûS\þöQ·<¤.|*ðº0ê–Ç(.3äykO9q’çg~g7Ѓ¿Éplö ëWÐsÏÅuX¿Åå#ujÁJn6¢3O-Ø’â² 6u6æmRnœ P{™dèc-rêìZ—)¯ýÛ©¹}aC𗫯ü x¬5{ÏÇ7Ã?c8^™“?ýSÍC7Ê®sò§GŽ–öã¢Ï Og¦ûrÓ6Ákñ)ž}p­Ô=k£“ý]h²…×+AqimÚ\¯åv ³¶7R\*m¥Wª¹9 ÀS\bÕŸª¾u¾mö©þĆ#ëB²d5OúQC,Ù‹â˜1»¥½žGIZ ¿‚âRëÞù\bì:Sœ v×±aøÏk3{Ävﬦåö9tÈwï¬Eq™òZ:Iú´öÀÞá:^öHe Ä–NZÆp‰%Ϋ=å
+¿ûŽîzµ1üz†ckáî»+3…nÝÝU).•¶øíÕŽ®QñÛϦ8âiË×wÝX]b›Œ+ÀFæ ÊŸKqi¬š<:GË]›c5 ¾ârõ%-fêyµuKZÌe8ÂóÚ4”Õ7$–»¹0Ýé
+øÇŸÕ§8Nê»QË3ià_03¥×7ÙîÅ
+”²‡:HÆeøfŠKC4‘ÈÏ.eƛߙO4¢¼‚&Å¥cv~Ï~ànœCíï\/Aèù=o¡¸Ôºí¾¡åö¸
+œø°ýÁ·)Ž ð•ÒÞVë<TŽâ2 ¬»xšÛxXÄÓ.^Çp · ºRÍmÿ5 ~ÑÊ{ÇʇÔδ³Hw¹cåŠKïbïÄKô…ÏÏSºwb+ŠK[wÒ®¾ð>¢y ÷ŽAè]¥Ô<éciÃð& Ç+óW£à1‡Bv6|5zŸá²ÞúØjIà%bv‰Ž=ýÎßBq4Vsú¨¹eU2üfŠãð»¶_©¹ýD'Á¿f¸|"ó÷”ž2B?2îYŠËÚÄWßWVó”—Ìçg2ûþG檹ÝLœ
+YGœu­þÖ…hç ¿žâÒÎ[úuµÉÏWix‚#_eÛm%>TÞü'}l+±–âRø}ßJ¼2Hcøí—na÷·P…wÀ¿c8ÔŠŒ:•xp¾ñÓ(.³F5 ~«.|˜¿¸P³à÷Çq“«%™3%”=Ü6H"¾®Øêñ—¶®Ü÷­Ô<é²÷ßð<Š#oá]«ÕÜ4Ôœ˜w×Z†£¡^8´“þÖ¹iœF½phWŠKá:½¾ð^”ló§Ó;P\>õŽ|¡æé0Ú‰\ïÈfŠKSyû¤K´Ü5O]£Û'µ¤¸ÌÝ~€ºuið? Žøº6«†•ÏLqç 7—I8„6¼"Ã1Á¾ì57=ò(ÝØ—.qª¹=a5â·3kÐ…òž%
+ŸŒöŒä=Ïpì9£Í^5·~8c¥Í¯—vþ‚#Ùô8~¦“Ÿ{89aÕT¼7Åå3Ñ>ýŽš;a›¸Û§—S\êê³Ë‚ÇJƒfy*HcgbõÙ(.-í”!›´Ü.â¢K<eÈW—W¦ 7T_x‰‰ Îpz¸ä®}½ÌÖÂ\Ë÷ö2)‘†`8>R%v¢Òz±R÷Ûˤ£(nÃP\
+ÿi¥mZž‰O€ï$8Ð[i[Ü‹³¸`yà‡2WixŠË­û´Ãl5OI?âó(.w~õÑâÂýX/~&ÑgàF¼$Ã1)WçšÛ†Ö?JqùL¤:'ÕÜ&ÁQ\Z›ÆµUó0J_oøc Ç ìÅŸB[Äšò²¿sòSjÅå…ýö‚ jž9|ÅÑ=¨}HÏÝ”¼2†c8>ÐÏ¿<3ε°bçùQê€gŠßNqé],št³šaW¹hÒ-—çþk£êjnÈàgS\«_/œò¿øm5²¿³©‰ð(.•öÏ#Wi ï¤Ì€w¦¸TÚâ ÇéoŸ@ð@ñ†ã)ž½z»—¯Qs»÷ßÿ˜ârëvUŽnçy™iûœÜtߤCnxWŠKC=p× zDawÝDqì/ðžðÐ.¹«Ð ¢qœá뎕ë~XÍ}?-f×ÿü(Ã%ý]Û-½Î¡x¼ÃñÒzuCŠàÅå}¿©hO=ðÂ~Á“˜â~ߩı…ï;U(.߸¢Eîw-Ï–i)'âC).“N¯Ü÷¾š{a4ÉüÊ}«Ž©Îy£Êé ïâtZÃOg8fÌæ¼ÔCÍM‡C¡9/õ¢¸TÚC{jyfò9܆ö¦¸ F*Ÿ˜­/|~–•Ê'æ1[ÈëŸÛO]ø´‹9à(.{ƒ[ë ïajx;†£ð·ï¾W_øÀAèÂí»d8VFŠÛ%<aó@¹Â°íï\':̺ظŸ(.Q/ï}GÏÍF|9Ãq´nŸz×€gHîÎI±IÔðk).=ê…ÒrÓ\D)#6z˜âRm^½{¨¾ð>ry>’àQ.¯›úUn>º±>‘¦_¤4rS¿Ê—ÏÄúBÔ<¶aø!ŠËÕ7—›Kp¬¿¾âRëö›šÛô< ð?(./ìïg>ÆÜ: ?sÃ1w±åY|ãlN2Æ@Ì‚–FN§-ÏÎg8v¬œQbˆšÛm.øpŠËÊH‘/_÷bòÌ„›>âò™¨páP=£¬ .IqéÓ^¼ïZ‚#®Òðž—j3ý›ßÕ<p†šá‡(.S^Ç—ÏÒ>š91|>Åå…-ýç'jž©¸àŸS\:äcÊîTs×GÖÃwS±ÛÞÔߺ ZXùlÛ[—:ÿèGxp)'‘%ÉÁSNà§ÕùèG‹).{»I«¹âꆥ¸\ýÆSÏPsÓX`ÿû§V§8âižîZž»k”² qÒGá‡g2+#½çÏ×r7´{+ÁRioš¬æf$ƒm•·Ýô ÅåÖM~øu5ìšølŠËgâÕùŽšÿ+ùÞ«ó†£ÒÖÔV_ø‹J†·£¸ôëµ­¥æ~4Íkø¹÷ð™Ôç657-5¦}õ¹ƒâÒX=X¹¥¾Ò:Øèdx+ŠË,ñÏQ7© ÌO<¬n.,GÖ…EwMÔ?8óKü)ŠK¥]üâ…µ[nÀõM¥åRç¿-s¹þ…uòàË\Iq€o¼°¨š{n”iã…Å).ÕCÝRÂÓvGBŒXÚ.ì ÏÉCÝ. ¸4Ô³¿VÍSa”pröï=).ûügZi¹=–Èx;†ckáÞEŸ« ošiÌ×í]ô%Å¥¹x¶D}=w¢UàgKœOq©óU;ý¬¾uN”Êð}÷pbãñÏSÞ³“àųU»RîUsßn°Wÿí.}›-K[€g–qsO2§m*oô¬¶,mIq©´›KdS}Úô#©8Ó¼öwNt<Íæ—S\:'+×r¬ƒôÆŠ%).]â:_-ܵ­¹j{Ìhƒ«óñ5—¹‹VG_ÓòLj |Å¥©Ìûþ#uáícøz†#Ýå°/n&nô°/R\:'ýZž§æ~˜DÔG¿–.Å¥ùâvõƒ³•ÖßIqùÛׯ®.|à e„ágQ\úu;Þ•)n{„¦yasB»62J~ˆârõƒßWóM}üþ4ŠË'²Ì›W€{1¹kÓ}¦À¯b8º…ÞÙÒ¯Ëtòc|&äø9¼'Å¥±:æf5 Od8&^þøî6=·©FÁ4÷TÐߺ‡"^‰âˆŸ¿'¡çºÄ†§)Ž‰Ö[·h¹M‡0­ÏnýŽârç¿|¨Žºð¡ŸÀVâ/ªÏplh-ýÜçú[ç…ØN[ú¹/).ýùÚs橹„F™Bç,b8þö¡'¯b*-ÎÆzòG—¿}ä}ÄD[ÌFÞG¼q†Ë`dßew3…—7Îðá—>í¹£e1Ñ$Ä™`·ÇšŸ¦Á_g86¸}tÛX57ÿ+bÝ6žâ2GýÑ=õ<Úvax†cu`˃ƒÔÜfŒÄ8îÁ;).“B£žÑs3J?Ïpäî[ôÔËZîøù§˜-zj*Åe»ÍÀ­ËõÜNh(çj¹¼ï³¯¿âiðÁ£požn‡ÿ¹7¸™ËQ ”áPoÜíÕ<ác7®áy—þüsËnÒÞ‹r°?·¬?Å¥©,5÷CáÙPäÜ uøïͼ¥æ®¥¸4VçŸu@ÍÍ'Î?ëÅåê-Sï€Û‰—·.ŠŒjÓ2µœá˜=¸oÞz¤Âˆ¡¸|¤¾ß½LÍÍGAàßï~ŸáHkük£Ýjžðä9ùµÑÏ GDëÛFè ôaø(ŠËÔÇ/; iyfŠ;~
+Ñ]gϾýêÂÛ.yü Ã;ü|e1'^Næ¤ð;(.߸ZãÛÜCóZãÛQ\:'“S²SÉ͆&Æàö‰UàÉ©U—ÎɱÂßèy˜BáþŽáxeßÿ1xfÚ'wCmSB9˜9i|ÿ§ Çv›S>é.<®ƒÛßyË<å“—ñ»ßæ5wÂ4Þw¿ÍM Gö§o@:»Œ›3m‚=r1ôœˆ?Oq¹u=yš§¢ÐDûS\nÝæu¯©¹Ý7‘ŸÉpdœ¨ºp”–g¢q}ð)Ž@èZ«¹èdø'Gô~Û£5ÊO;±íe¢®‘áå). u±Âß«y2ÿ¬b…·S\n]ÑUÀ3 ©¹§¸3 ©ˆ`/º£:Ñê³Øý빇Ý÷†_JqiëþF«yÚÒþ<ÊpÌ×}0êN}áƒ&Ü>5Œâ2ŽÛ0“Ì™%쯌=~.mæ5¦¸t‰¯›p½š¦oæƒ÷¢¸ üÕŠài üÕá¨ó; ÎRsÓ5Ãòý΂óôÜ4uÒ£ßTV…ÌG3gêÃü΋rû~ ųµ®]™ëÞUsßþÅåÁUlu5xf8³[èÙ„ÌÑšTÅV×P\†ÿ—³ÕÆuÌàÎ ¼L QNn»óIðŽÿñ·[ŽÁȆËÔ…÷Ãè,ì! WQ\æmîÿ 3q뢩û?èÆp¤
+)2âu¢ðÂq‹Œ˜Cql£Þü­š'½r°ÏÙüÃ1Û>ê-wÒž‹ ­ÛG=Æp„*]td‡ðlèBÎÆÊüΞ'í€ï¡¸|¤jÝFð
+]¨uÛOÇ1dmÿSn‚šûæê)ð' ]ý@É1Zn†BQdã’S\–2 WNéo‹¨NÃ/ ¸\½VeÙ¡æÙ¯OŒ­F†'Ü„ñC Çpཙ€ÇÛؘ9øÙ6 ?Lqypk.{LÍíø=Ÿ@qùH=¼¹Œš{ùÁÀo®Hq©6=w¬Us߉V{îXOqù¾OîðŠš§ÌG»u:¼Fq¼ýjmðÌöºÜÝûÎ «’áu(.¯ÌE¯wPsr‚_AqàÞ]R…x™åûÜÓ¼^v & Þ—á˜pK¼šTó J¾gxšá8W¨õï‹ÔÜ‘é÷%—Ö¦è_²°âeRsO´ÚRLs᯦¸T›j¯¶×ògŒ¬öê•Ç©§Ë*°—]ÎË9
+|$Åe8P¸JUáÙD%9ÃïÍï<;å^ƒáIUzô"-7È4¦y+=z ÃQi·¿®æ®ï¥£¡Ðë-).u~wßqjnžf w÷ÈpDûùòýƒ3]3|+Å¥©¬Ú{þÁ…¸u†¯§¸|"þöþÖy¸ó†a8îü˜øÂfs7Ôv11Úb6¦Ã†#gã±öÏ©¹0aWæ±ö/Q\nÝ´m€gÂïÓ9yÒ.gæóÑljNm®îÅäÿ:–ÈðûŽUà/jNp¤¿3üRŠËGªCùjîEÛ. ßCð
+6u–y‹âÒ\¬}ï\5÷óóÛ¬}¯Ñý™Z2šðíFÑ +†Û”)ð—Žè¾µËzƒg–urN6úÙ´F.x_ŠËgbòµÙ¹=|ÄùoþßFž0mU¼Ãñ·ÿ1ù©ÿÅÿÏÂ']¤t6üŠKSé\ù¦š'BÕƹòmŠK²Žr·¼žæ€Û˘ÆRº†/£¸ Ÿ)Ð<³¸«ÒÚ˘ûŽÈ‡g
+\Oq$—ƒÀ4<Èß÷Ê]).•¶î”>jîyQ­«;¥/Å¥_W÷ð=úÂÛs³ÀüíÍ:Rs'Œ‘5ë\˜âRø÷w4Vó¤úoFqùL¬¼p„þÁEÃÃGQ\ú6:WîÅJ8iú‚;t®Iqyã:Þýž‡ÑÕ;Þ=†ârõ‚Œµ•ØþÎÔ™-4|Ã1[øù–ºZnºP2|¾¥!Å¥ÒîØSD]xÏ&ÿ/Æpt̪îO ÷cmê´¿3#p¤1¯º¿1Åeê£ä…Oª¹ ¦ÔðgŽ˜“ËêÌÑrûÄö²: (.cØQsg»2 ŸMqé”N:¯°š‡Q¾ ÃO¥¸T›‹vl•
+,³Ù|`#¾›âRë
+=ÚAÍ3› Á¯¤¸T›aÓ=7]£< ¸4•·5ø@xàÄYHµ¿Ëd6|5Á±|ßæµûoÐs{pøM—:ÿüÖ¦zžšÕó[/¡¸|ßk—ÇG*È,açîØÀ‰(YíòO1óó/™£æ}và (.©ŸN]¥ç^
+Ÿ‰ŸN]Cð(`柉Ÿ«y¼3ÿ’â²
+\fé¹ZnGqHñZfi=‚ãËk4s¡ºð¦cåEü ŠËÚDÿËô•6LËÜ…áïS\^Ø;'LWóЖïïœ0‹âÒÚ¬¯×MýàÒa€Ã°Ö×ëAqi*ßÓ^x˜™tÊýMc•F‡üñ=W0g*ÍŸsXÉM• £ãeçÏ9NqIòWj
+x¬Ðû;'J²jø|ŠË­+üy-·Và [øs‡àÑÁ@ÕÇvRsSçÐ1«>¶+Ååo^¬°š'¢c‰ /FqéQ^ÚMýàì–ü:ŠKÇìé;û© Ÿ£nOß9€áˆ·™~í½ú»X2ü‚§–¹lÓý+ãâlÇ1}›CåÔߺü©‡Ê?ÌpìH-ôi uáÝ …ðûBŸ¶¤¸|eÂ%#ÔÜ3ƒÈ$ø(‚£µi»¡ßß±¥2—±Gu
+¿¹ÅåûÞshw5OºÈ{`xŠKßæ­NVsÓZäó¢—WfSs¼q‰Xìeì¡Liðá Ç–“é0ÁžˆµõÀ^Æ毋øQŠËZäŸåÎQsSk1û³\ŠË­;6ÐÓs?åG<d8&Ãmø@'cÙ`çyÈŽkøµGžÒUª¹öqÁ×R\ú´^ctRNœ­†Ûn!f¼Æ>Å¥o3ì`}ðXÉóíïì îøù—Y£Ò¿Ór'eÛjð¿).­MÝåÓõ…£ó"ë.âòµì{uáíÁÂIðí—vúmCô·ÎK!AÍôÛ†S\®¾eðÃú[Mïþ(Å¥Úl´[]ø„æó½—ö¤:Ñûž™êÌÝ9±AE)sRŸâòà·}YÍÍðMeã¶Ó(.uþÎj5ÕÜnTJƒ×e8ê]g¯æ™äƒàÛ(.·îÐÕ?
+OÇJXag*Öe]ý3Å%êcÚw;ÕܳÛÑÀõ…÷¢ØÂ65f!`&ë oËó—5<ârçK¯]¯åf é`=®ôÚ Çz\¥™}ÔÜîûøÍ—)îk¾Sß:›ø;ЯùîrŠËÕûž[Qÿàl7¼Å¥¹6¾§ºðŽÍ»
+®×sG¬Þ‹á˜ò:¸çðXÇQ>³´ö|Hq¹óÅUó ÀÄ‹áÇ).·®ö“3ÔÜô#ð«ýä,ŠËs_åÝHð«ÿ«¼›(.ÃÿAƒÑ\dCRsNqÛIÞ¨­3|Å¥_7ûÇwÀ3a™9'mPfÆðöï2 jŠ¾ø½–ÛÔ2ocøŠK¥=u[wuá=?-¥§n»žâÒ³Ê[$Q^æŸX“N®Ýk-mä-º˜â²6Ñ±Ö JîÙ”Ò^Ä_¦¸´6Û/xÜ5ñbþI‡8¦ÄðwŽ-fî qƒXØß™.±ñ —[×­˜D¸¹™ ‘…þ=½ß­Ø†£ktjâBðXÉ÷2¿s¢µSÍ).ó6÷4Òr'á{^Ä›P\ªM±+ÞUó´­A»bÅqõ3ðܱÚË„nôÊ;c!ÃÑÒ–°NÍA{é Ž¸‹6ý¾ý/l¼‰VsSekÔïÛC÷±ú? AmÞµ”ixè!MŠáõ î¡{н|w=·3ðë).ß÷ûî)îÅë”&ì6–u0Ã1‚þ¡Êj5½tñµ—æâ·{ô…·»_Á÷R\ºû‹ß ææ#‰oÜþâ}Ž[Wõ¯¤ðdÌnaÒ1U©ªþÕ˜â˜hóšš;ùnÃæÌ¢¸<÷ekj¨y`ú´øÙ—«{éf5÷ó߸o/ý†áÈ_w÷Owû¤ Fq þ?üº…ÉXi,O:ÑA`‡ßšJqi¨ÝÇë¹—ÀBªûøß G®NïÐ3ZnCбSÉ;ôÅe [³Yá™ ‘Ü|œÍ€ÀHqiëæ¼}£š{.Öß ïÇp FJÔ¾<Þ&/ÃC~Å%L«LïBjž4Ñx=N|hów>ZîÚu™ˆßBqypáèºÄߎ€Ã<‰ r|ž
+ÿÑÅ_©o]*ÀqT†o¡¸¼27!IÔýì"r ži*ÓàÃ1Ž«úôF7¿³ ©\ðM—‘Ô{×¥þvüqŠK¶Ìc6wcm!7—IG‡ÞŠâÒÎ_2ó5Oè˜Þ‡áHs&âsûo'â(._رG멹]WJƒ7d8VŒZù”úÖÙDhøÓ—¾Íà »ÕÆCf¡‡^Gqùƽ^¹„þÖåäýzå’—«ï*ÐN_x/Êgµ«À Ça—¥®ùFÍÍPŸÈR×|OqùÊôyð€ž»Ñ~™>þIpœ›÷Ü›ÔÎ Â1üîÍ').Rn½XÍ3‹xK=÷Ñڮ茛‰æ—vÞð—á‡aët“6r!ô°ˆÜaØ'—Ö¦s»ìœU˜=Š+÷¶Ýÿm·€O£¸¼°cÿ^¯ç^ÙuÆþý Ååê‹wÞ¡çN4O»xç]—[·|sBσ茕å›Q\žûŠ¯ë«y¦¹?áÈ \bÞÓjzØ^gø³÷À7çˆþÅeæä‘ãýÁcMqÛˤ}Ç=rüV†cÒ©êŽâà^LnŸÃèUw”f8†Ç:ü¤ç3|Ã1HVv…gäÚNf¾!‘%+‡—‰—Ö›^wãfçiOÓzÓ4†Ëô~›iÅÞÒr›àÓ>ÓŠ-%8Þ¸63ïÍSó´›Ä†—™÷^Îp¬Ö·F}ë¼0Ê Wcc'†#@nôènjš7ο–â2C^á‡]jn»Lƒïe8¦y‹Œ_,<™«sbçØÀLð· Žµ6Cjâ MÌÕ1³¿sݨg5¤æ0ŠËø}è×3ÔÜî«L‚Ï"xô·8Ý×r›,)#œž¢8¢÷Þ¤.¼gÁÁû3½‹¢#¯Ô>H ïAÑ‘Ž¼ ¿üVÍa”5±á—ßQ\îüóÏ=®¯´æ_8Éë¹I—«¿Øã7}¥uÓCnøï—Ô—vÏ,çå
+Ó²<é`ºÏð—9«o›7WóD}ã¾mÞ’â²{Kµ®jØÜýà×Q»q×<¯æa˜ÀÕç¬y™â2Á¾ãìõ…·yÁ×Q\¾°î$<Þáwöw^ˆ¥ Ãï ¸,aí8_Ïí€/¦¸|"-+,ÓþΣ¥ãG+1aZ½ÕÓó :ñ¡w£ó).#èMc_RsÇMb·iì« Ç~™ºë_Ñró‘Š^غë_£¸´ó?öˆºð6-±þÅ¥K|_¾Âã¥E²¿óÂ¥î«ÑŸâr||yï&5wÌ: >€áRiÛ\´d§ðl€\®pÐO¢Öþ#ÃñÆ-Ü{‘š›ÿˆÞ_¸·9Ã¥±Ê«_þ€š§ü
+?³eMâÖ%óymŠK¯ra¯ÕÜî¨Å¼Mo).ݱÛÛê¹ ØØííŽhÞŸ?h&Ü•Î:´ge˜¡˜Þ‚âò•és¬%x¬ö2^tØ¥ámŽ¿ýôY2‘#r.¨¹vÒ&ÊC~ú¬Ÿîa0Òok[5B!jý¶v¤¸ÜºK>l%Ü7±¿3ÑxÅ¥¥mûÖ*5wÌç=¾–áèÝ2º–Û.±ñ¢—Æê?/SóD~2í7þlCqyîç7ÿùM>œüݺDþ®Ìó›ï§¸,&¯Ò…÷⤳Ü4U˜£.^¥?Ã¥ðí*îüྃ4h;×R\Úº³ÇKð€/%Tæ$êü£÷Î?™âÒ5zb÷ 5Ïæ5|6Åe,óôχô…÷pæ‚áG).³å'¯Pó”="|%Å¥w±qZK5ÿ×zã´V—ÞE™ýÝõ…·Kýà×Q\Æ2GÞÖ?8/×Æ‘·ÿ"xtÊIúàà™¡P® ìöw¾ŸDS™>8šàþ·yõ¯&jîE)# oFqéœ=\MËtè!‚½è᳎Èƛ֫ x!
+¿bÓ'O
+¼Á±['ïÐÙMõ·ÎC¯Òð‹).Û.>N-<+}}æwnQ^§Îa8FRµ>Æ6Þ‘L™ß™6þÅ¥ðçmNj¹©4QæÀó6§).wþªªÔÜT›«ªv¦¸| Üÿ=xÌé>0ã _7àþí—ÑDƒEeõ<Œ’ë6XTžáh.Ò+†OÇ„¦íYÔ˜5J¯NqŒô¸T¦:c fNhÁÞ@ß%8ÖeÚte:¸ç@gËm—<>“áˆòöy¨æ©
+oj³þGÁB†7§¸4“ÏVsÓ3Ķ‹Éç2;R÷¼x¹šûa2ÊÅýâ•—I§?koÖr'eÞÙˆCq?ÿ57E>ˆáE6>e‡úÖÙ`¥|Åѧí\ExÌå{›+ÃKù?“áX‹œÖñp7ÞÄ‹]ÂŽæ.¦u\NqyeÎ[ åN‹öI œ·„âò+ÕGòœdæɽ„móöQµ)ÕçŠË­kÚâ(xÌXÂS‚Í>M[œ ¸\}â•›ÔÜÆ‹§Á73 +ÅšlTsßIK¼á_è¹Mm™}pwO˜¬æžàÔ»'<Ëpd]hw:&²ÇÓä®´I›0Ñ>íN_EqùL,›t·–›lÃÀe“†R[ ßÛ®æv+p|'ÃѳÚ=ùTõ­K¨ó†—`8|¼kâ7ê‡~´¤u×Äï(./l¡ß0‰¹‘Ù˨Œ ì…~«Oq–š~\Íæc*W/5£
+Cô.VÛMqùÊ4™ÚN_x/…T`M¦v`8BÙ½F_ø Š³úe÷:ŠK¯Ú¿që´ÁðΗ™Òµ½.$x€¼k{5§ž»ðšÍ§ ÷2“̹Bìïìë¿Nq„&n+'ÜwâL>ž9F‘Û*2Û.æÕ¬äöP¤jݼÚwR<[ëÚU¸b¨š'CD2>œâ2
+O8ñ¡f(æãê†oc8¶§×´TsÓ9ArÝôšÖ—Æj敃ÇÚØhgÑ#¾‘âòÊŒŸØXÍýü¥ñ/¤¸„.LØCËMçi ¿‘âÒ»(uíP5O˜§5ü†cž¶f©Nê[ç¸Q–•š¥ºR\zßăK:qŽ—µ¿sœhø?üÉ‹(.µîŒæÃñ…=£yŠâ¨óí/!xÔ!ß¾%Å¥¹hòzU%Ï$ CÈJ“׫S\ºÄ‡ïø\]xÏ2 ¾ã+ŠKµ){c%ðXÛi™ãç°:`xUŠKsqï™Í´ÜuB¬¿ÞœâÒڴ꘧ænD¢’V/§¸4V·>6K}ëL¥‘•PÃçR\æ*O{þq5Ã
+ü‚GçÚ[…¸uH4jxu†c·NáGè ï&$ÜðQ ÇÞ¯÷Ôs/:ÿ½ðë72ÝÂEw/l”º¿DÑŸ(.݃s‡¾Ä¼2¨óç}•á¨´u>ÄTœÿ^÷àŠËß~žwªžû!¦¸ÏóJP\¦¸ÏŸïͲaž ¸\Ý™rõ‘
+ÀϤ¸<wß»“øL$¼ˆc8ªÍ%/Ì¢^™4ø\†#¡të·•6úL´~ëÅåÁµ]À|ߣ¶í‚×™;¯LÞ-©TÞ–âRøv|F¼°É â›<ûÁ£W¦ó³/2<ºúsOè+­çG3Ï=MqyezÏûi*QëzÏ[Çüí¨uý %‰W;Ô 'º…ù±ÄfìÓó0D÷€P\nÝÀÍÕ¨6 ~ñsaÐS©¦2>ƒâRëîúSmpÌè=C—R\
+߸qTCŸÈpüí÷-ÙÆptÈï[²›à)\ýÁ½™± fNp3ÅåêãάÊtNÐTŽ;S_ç-—æbÂé©Ni
+|ñ±qò@}ÇÌsNĉ÷ÝMDG.>Bµó.ø ŠËqú÷Ô­ Á·S\Ü++ÿCõ¬ð)TC-wþÕŸÆ3…#®ïX./ìrïR¦©Äz¹×šêIµù áBb(ä8_Bqyp«=ßÈU‹ž§¸<¸Õo½J3 Dv·^f8îüúö5˜é>µ¹¾}-†cÏÈgãn!ºFIô.>G´´aô…ÝòKêÖàÝ).…ß¾¸‚žÛ˜Á+1IÔÉëHL¸%±yÿ—¼Î—ÂÿqôOj8‚¥Þ8¹ó‡Æ¥©æ"Þ˜á¨óǯ'
+å1;6x#Å%â唂RC¡ˆ_Lýí_wÊ^â}÷10üvª?/K™…}}§Ô…°Ý'
+$pÔfш^¥þãdÞ˜¿=JP*˜ÍQÜ¥‚ÔªÜùÒuc*-R>–þèzŠËBj¹nÄìÍs
+N¼ï†Ë­;}dm¦ðÈO{úȺ—;_i 3GÑRi 3Gnmƒ6TÏ
+g.m^ ê¼ðF‹0«¸uëW½ü0ì JÔ§n]ÄÏ£8bÖ¤«øÉ G†™¦µõëïI»¼Åå}¿äâë¨qœ®/¼ýÛ%L«ÕÄÚKáê­î8Nq¹z^ŸÇyàÄûîcQ©íÕë˜õwä91œèœxQ0ð G~d:¥øDÞpägŠË {ó“ʼnÁHtÛÍO–¤¸¼ïýÒ¯A{ÑD«á{Žv~еÄÜ…ŸB¤Ó k'1¯Ì£‰ÅÄh_¤á#).…Wûw¦¡FF©qµ‰¡ð2þJj%Ô‹øŠËßþÊ j8€Ô¯ "&<lânûê-ÄR¦ÿ¿z Ñ%6\þöÙ£ô#hÏ‹x=J?‚¶\
+?÷Týü¼âN‚÷%8¦}Ú¾±¯(Uø48ÑTzѦÎwªëÿv'IJŽáýŽ\köu>Hâ…]³¨óAMåÆŽútÒ0ÞØQÿ6'~Y³…za‘çdÍVŠË~ØâÏ­ •0Š4üŠc»Mgýê€= ›}:ëW,—]™Þ&b²ÑtJ#NŒ £µ¼ êÕL¥ÅY™AÕ®—[׸1~÷¢MÜK0Ó}È~ŸwÅ'L¥uq
+ùŸü@qÙøÐsÐiLçqÔ=•¦¸Üº>|EM6"?í#ßPs²Åìæwˆù:Û¬ '&ܼè¬;vk‘^t²Ï»vP\žûÝÏ23fX1œ™1ÃÊHÞˆEúv/ÄPÈðo©u¹u#výÂpl9±k?Åå3q}[8ÑöùûûèÛ:Ñœgtù'™ÏöI.¯ò²\
+?aõ£LµÁYV3~tÚ+¥‰1{B ¯LqùÛ§NNQMeĉ©=ê¼yÕˆæ"J,lø†#íáÒjDkc
+MˆÕÀ¼UŸK<8Äœ^âRøµMBâÖaÛ…áÌâŽÚÌÛ°ûA扣67ì~˜Z‘ç¾/ùóÊ ©Ü—\Kq©´û/'Ö&Â$²eî¿œxp†Ká,Öï\0M%zVGëw.XžýÛÛ•h§„Ú3œXÚð1KÜî´É‡‰iŸ Ÿëç¨ÝhÝ®üëÔPHjáú8êÌI²Y^a ±é#Ä^!Ù5"ÛU*Fl1‹6ûÞ‚šæÍò6çÄÚ„ë
+ŠË­û¢Éz„Yù¢ÉŠKµùzSI5ò3~½© ÅeÂmÁ/ÛµÜn%Æúû‚_vR\æë>[¤~eÌ` :¥ô³Eë¹ç cV¥æ¯úÖÅÙ:†ï§¸ÌÓžÛ j^&YGÎ1v ×AD«áû).Q^ãO ¦4fj_{,›F`äøoP\êüäW\5w| Ä O<¥Ìg¿ö¿øÉÿgáÃha¥ÇÙ3).oÜÔ¹o2…Gâ‚©sßa8†çý\SË„=¯¼6Åe {dÄKjžŒbÈ ŸJq™Þo0 ŸH/ÖÁ‰Ll_áÖ`ÖŠËWfäD¬ËdR:çN,lÿñÒˆ!9±Å¥Ú,ÙJÍÃèꆷe8’2­V_Ém*ï´ÌY~Å¥Ú<Û·‹¾ð.â. ïNpÄ]äíh8Nσ4MØÑpÅ¥kÔ¿
+´|×&KÎýÊdNM@Á—¶nÃúÎZî¤?ˆø5—W¦ûrlhõM}üœ‰‰Ìe‚ü™»/ßLq©uǪTÓs'Ïk2gimxû í2Y˜®Qˆ¥Ì ON§¸<¸îW`11pS±œ)z€<f†Hqi¬¾Yu‡ž‡ÑÕ¿Y5„ârç-:UËmò|d”úµèt†#$õÏÚ÷«¹é"êãÏÚQ\–´=v§š›ŸÉÖð»).Wx[Ït _Nq)üoëÿvûÜ=ð¡—æâ÷‚#¨jモ¸Ìו«²PÍó1Kƒ¿IpœÔÙúD™“„‡Žiý½ÜC¡Ð±‘Ì/Iqé~qa+†ã…ýâÂ6—7kä!=wšhøQ†GIZº! ›ýŸLöÓÜ CýfNÎïÖ‚â2Šì2ô^5÷m8øƒ—÷}Ô›ÿhù¿Nxɵ¤ Åeu ò"t‰m
+Ï8ܦ9²ãV^ä0<ÊŽ{Õ½O€?Hqþ—í5I×NEåžxIº®©Þ)ð… Gôþg¿ÿ¤ç¦k‚ÿBqùÆ5»j–Û””jvÕ DzN×-õÜÁ±Â†·b8r÷Uh× Ü³<wc•4â†BÚõ¡¸ô*Knªæí“*¹ýŠK¯òÂ3ë¹ÅÏ_xæ› Çø}HÛÞú[åŸ7¼/ÃñÜçžõ¸”MŸš;Á¬ùcþ‹ ~œâò•ù©ÙEjž Ùhx ŠË¼Í7Ï~¨æ)Ó+ Á×R\R}®„uÊMÅzaS6õŸ|ã ßLq¹u†}§æ~è#Ùæ€aÛ).Ï}àâ«Ô<á"Ýð.—¹‹Û®¨§åöÐCd¸íŠ†—~Ý+cŽé\˜ÄöùWÆüCq–qHuóDúÈ¡¿(.]â¢O¤/¼¥p/úôzŠKÇì´ã¨¹gwZ¥¸¾l•þêj“6=£$ø­ ——wFø¤þÁ¹!z•g„OS\z•Îç¨6i{ÄWŒÅ…”=n½ ç‹—Niß«Ž|V}|Dq)üñáÛ•<mûã8üîøð]O`†¼êÛï3…÷#NÝ:ÃæÕòÚ0;:äµ¼ö Ç [wÕ‹TáSà¯RµNºFïª.| ²2ð÷î—¾Íã‘œ'm§ÒÂœÇU˜ß9>p7|Á“²”Ùvñ×Õ<ppÚ…áÍ(.“Ìÿôª«æž-¨ýÓ«Å¥Ú »u¤–;)½JÃ笠<¸3*IžR/ÓÏŽ±š¶ÝD}œ1p™š'BþÅåêÕOkAs•mG§åö…Åá8£?hÏp™pk»h@/uáMo=«EH{¨äRç·¿ü–Ž{™Yì¾ßþòRŠK¥}ïí£ê‡6êüÃÑÒ»ö9p׉33—ñì ³à/Q\êþ%›é¹ƒ8+Ã[è¹ë`¢uæåý´<{Tø
+ÄD†_CqdÇýx›š».²¬¾‡âÒ·yúÚjê[çQkóôµgQ\–° ¼ô—š'Mµ¹
+Oïÿ¨¹`QéžÞÏ<j¬Þ?'­½u®ã¦±WèýsS\º…M^˜¦çº†Ï 8BÓ[ôÜT|+Ååêá×_R•Öÿšáˆêì?ç$5OåÄöŸs2âööªÇ…{±¶œ˜ß9 ?@XæÛ«&1Ë:›êzZnœƒÌ›ê G.î¯O_ .|Ò|â’à‹Žˆ—'öÏÏtÈs-*e†éž‡]ZOìŸÇp\ýµq¨¹©^ˆ9ymÜE—¯ï_[ÍC7Êé´¾ŠKcÕâD/5ÌhÑ¿™âHå}[A5Ï?$ÅðS(.ï{åŸÏ.ëäîøNÚEºKÃ?§8N³zb«–gN%NÿÀp¼ïu¦µSsÇ‹I©3­ÃQmêñþÿ?º6aE€Ö¦Þ‘áˆíùÀuáý0JDÖó{Ž«¿º¢€þÖ9iYP3¼Å¥Ú¬iø¾ðѦNÃ?¢¸ÔùMyשyÂEÆHÃ{1S^ ª e‚(ø¿áC§S<û··>:õ3áAf(”kêÃþÎó=é”þÅ¥­KMùJËmL'ÔRS¾¡¸\=ïçÃê»ö¥?NqŽ“·NÍ}/j*_ÉÛ@qiëÞ{ô)}áÝ4úuï=ú4ÃQø½É–ú‡>^ؽÉv—u™ÚïÑWZáy†_Kq™5jÿëÄ­‹ò×µÿ•¨´æ?¥s2uÞiú[ÅÓ^šâÒ«¼®&ÂLz®)¯ÌZ\€3ÃWP\fZ^€o\˜ Ãκ`/“üoø)—«˜øŒš›N1ÚºŸ£¸¼°_®/¼½°_»‡âò‘jæôÐs3‹ø —ø f_©¹Ms’
+½‹.߬£¸üí‡TÑ>ˆâç/¨Fq©u5ú߯åN2ˆ&^jôˆâRiÜ·™â ðo).£Èv¯]­æi?: »Ýk×S\þöñ£¿Ós'ÊG=~ô6ŠKSyÖ˜lJ礛ÝКk×^& R¿?kLŠËÿ¡Æ:nçx8™÷‡).ß÷Îw.wcuÌ O˜‹§Á—0“Ìw\<CÍà :g䎋gS\Æ2ìsþÿï‰V»™Ö‹Ò×?²Ï§¸¼°ó‚åà™.qÎ ·Ìá8i¤Œ˜|Àp¤ë8ißÿâÿWáÝT”Úðß)Ž7ne?}á½/g­Àpôçwü½Px¼M^öw660‹âò¾§—–Só0pÐT¦—V¤¸ÔºUUs{ T>‚âò·ïn#3fnvƒ[Ρëe¶Û$À¯¥¸4Vçöÿ–áˆê<·ÿ—ÞEçû*¹û¯5†÷§¸¼°s
+|o fêDuÎ)°âRißØÒOËÍ?Ñöù7¶ xˆ©ÎÃÐÞq?øу —ÉÆvži­.|‹€+ðL;ŠË÷}æM7Ç[D¶Ë¨¦©FƉ›úS¥îl«æA”{ÿÿqvçq7UíÿÀ•y¼Cf…Œ·!{<gC¥Lá6”LÉT)D$™z¨ô ¢9
+¥(¡ÌS†¢ ©(™2F†Ìá·Ö>×gÝÏëÛósöu½zÑíw{½×^óº–â-Dœò|Ûò(i]+RØÖÑãMOê›I_I8Ä~3éO ñiŽÕ}…î·£,EÖ×Ù&ȪâDœrÝ©·ær¹ÞFÒæÔ[ EœZ•=¢ñ:Uíêh
+©›ÄžŽ±‚6í±Û¸\uXÁ®øN!ñù%‰Ç)¥ù·•"®Š¿ä6Ù”w»f}]þm7‹85Ç€Û¶Ÿú °ð:ÇGg$qü˜„£û߮Ƨ\®
+ÀŸqªejO}xà5uÜq,õܱs¡öÔ·EœŠÊ¬“–s¹­9¥±‹B5`sÛ pBk¡šíEœ>™‰‡†ð»nÕ‚?#âTPì?‚xË5£Fû¿"â.^Ü2Ñ‹£~Üñgƒ#àPJî9&Øæñg–‰85‰«eËÉæ¾ç"×UË–UÄ©~ß|¾q7ZWH]çøqìùOÿOÙÜw]Gñi"Žc‰6$Þœùø†R"àÑ¥‹õãnxµ6ÈSvÕu®‹ÈÀŠqê¤ÿ|šÍ=לN›þóŸ"Nneê–$ÞÆ>è2u+Š8">8ŽÍõ–*¬>y7ÆçºGĕ$ ³ªG)hƒ“œ@OêS]§ªHìÂΨV (Ÿ»1ôeª($â43’eÃV.G¼ò$ß.àfBK5lÇæ® (­ø"žÀ‹ë!zqTIå¬Û˜xréBꆙgÇÌô½âÍEœ2m㇘< $Žþ{ãGDœê÷ÇW›Ä)*î¸8Õ(£f¶ÏÙ<f™žTÍl3EœfoÝÍ癧U^¼u¿€Ç9ËÉq‚Ä[hf9ù¦ˆÇñâ*‰^Eªð%¸1Û¨*ÆìÆ-–1™Íã~ìÅ2&Š85NÕ›ÀO¼»+>IÄãxt‹%5l™Î4FíDœHÕ!ÜuG|µ„ãØ‚EÅlwLàÁEÅëˆ8•6+û›ÄGìëc̱žVñµŽÆÉÜ`>›;f{]FÚå\nªGaŸËëDœºÿõfMaó„ëàxÙz³>q**›Ý[Tx: Ù½%Eœ
+«–Öûìç»èI)þˆS¦ÍSp9›»¾‡y
+~%âT\L™þ›Û.ÎPS|¢€›^çsEŸ 6u~Fkt€ðH ³00Æ*ÛÏÌ"âÔ8ÙðyŒÍUY…%è>¯%âôÁV*¶ <xI9Ô©¯ó\¬òªTlˆÓ'Óñ#\.spÁ‹8µëŽÍ1'ö¤L¼ç`¿Œâ§Dœ*©=÷Ô%NçEö lõ¿À÷¾çžÛEœr]© ûˆG`W×¹Ÿ1<K]6×Ó°>xBÄ©Eý]öê×âÿܧc2[æôºï²ÛŽvÝ¥u+؉·¬)Uük§‚ºÛÌÑlîXf{]·™cEœrÝÎ+ùܵ°Ojgþo×ñ¬šuàr+бÁ;‰8N|Xò ?ñ>ÖÛ(>SÄ1ø0a·èƒ¥L;s#ÍA»É)­x„<Ÿð±ªSñ]ž 
+ºéÞùó¯ÅÿgâãžÙÌ»wþB§\wª|-.ÿO•¿MÄiNªÂGÅE<^Z©¨ÌÈ5ì4¸î€§ÞV©nÏ<;¯ÞñOØܱcˆ¢VïøÇ"NÝÀl¥_pLe*>J±LëÁnâr[´
+ÀËJ8N`?7áCvâc®9
+÷Š8ÍË\¬üoâ~8…ji¢¾Î²Lis±òh§Ò¦×›Ø<na3¯âM%½‰³±\|î#Ä«âyE«>DQ©Ws¤úÐ×ÅœÀ¬9ypˆS¶)öðcîc„¼ØË85ÈK–w¹ÜJxXCžaíɾ»×appk:yÔe6·ôL⣯“p^÷DœýèÇãZ÷D- ÇÝɵÿâÌ÷®øAG܃ÁƒøÎóÑ,Lü´„c¤ôé¹ýÙ\Ÿíãñ8>[ôÉÐ÷>nz±° œª®¯s¼¾÷qºˆ8åºå ´í"¼Îò°Ùgcù‡E­-àr}¤2N«¬P¥-›ûæÔBÅï‘pŒ”Þ½v)û·ë¡Îø
+ ÇoÏ5ëi>7ÇÏ)þœ„#šV©–$/Áóo]¾ Ü‰Ö …1¥ðÝ"Ž³2µÙ\ÿ<ðÛEœÊºÅ÷&;¡©‡¼âª÷nM(7â ›ûžyqåFœqlŸ_ø ›ë èXù°pƒˆûxt$µLñ£w‚‡‘T©ú:u{ÄxyÕZÀæ®Ã.Ÿ#âôä[6Êæ1 VÄ<ºÛDŽ~û/¥p÷ÀŠ²tAñp#œ>LÄ©´)²­5xØ LuLI~²˜¾oöL»›¹\Ÿ7Ä?Ó®”ˆÓ{¿2"Áæ¶ëbáÄ•uEÜÅ£k)zt”ø}÷OD
+§®Ó÷GGìÏ5}¸\5Èãžá‰8=:k_;ñ 7A‘…/$âÔºx ÃÁ£3ám yX.GÀɾ;E/¹®Ü‹I®ˆÔ$ÖKV,ÌM\)7JÀm4êö¹Ni¥Ì´:x¾9ÅLñ+"NCß7ïÉæú(oÃ{K8Š‹¹OÌ$žÞOYP‡I71^æ>ñ…ˆÓ¼Ì¡zð¹gc-ñ¡z‹8•´=»gsýðR`ka®±–€c·ŽâžˆÓ'Sú“ùÄ“S)¥aè~Ó<(ýÉb§ââÈ×3Ù<pÌùzŽ„#ŠZéWoaó¸Çl`éW+I8ÖY=ûÕ>×gÿ%ßû† <ÍûfÔq“ø]¢ÄÓ8í­K}ðH©ôu®ClÞ–Ù÷ó¹Ç`cËì»Eœ*©>‹±¹9ôÑgñ¿Dœ>™aëop†­·Eœ?fXO6¹X’ªxo Ç”ÖÕé'ØÜq5Qñ¿DÜC¦å?:ié‹ÛX©q7쌤lÙúØ‚BÀm¬t¯ˆS»nòûÙÀuƒ<åµð:ÛÄ»˜ü~.7ñ.ÖÞ{Ÿ»¦#¶öÞzŽ¶é;·¾ÌåªùŠåyŠ–pŒZýže'ÞòL”•~·L`sÕ‹Ã2ì~·¼%â”mò¼ûĵø?èÓ.Lü:ÅŸ’p³úÊóìÄ{&pâ/‰85 ÇdYÄïnìc²,qjUîÈù›.¢ß+>IÄcÈ´O‹2-}qEÒª÷¢umO7
+ñÞ‹¤Ù"Nï}×''Ù<ð=ÌçÎw™Í3ó¼â—Dœ¾¸à‹Ø<îš-fÁÓEœ]ëŸñ¹‡²NñÏEœ'ÿ©¹„Íc
+Q|¹ˆ'mþdl·ñwæ´ø_ß&fY8•øƒËƒÙÜÓ9|€ˆÓ“óŽÉ×âÿ£ öl½n">UÄ©¬+”–‡ŸxÇtÀ ¥ð
+ÍuIï âTPgíø0Ÿë (ð"N/5›ŒfsßÆ
+vÅÇJ8åù&ç¦cŒ:¹t!õð¾>D=AsRŠ["NMân ž6}¯ô°M8ën ‰8 6þgõÍ|®7Bƒ—qú`ïk+àæ¬ Å+K8ÏÙºPxÄ`W|‰„c\ƒ)4}oÑÀÛÉž\
+Ÿ[ˆÑš‘ó•×âÿ£mÓ¡FÃ׉8åùŒŸ°s°WñÁ"Ç£«$ztôÞ¿ßž <Òdb"ŒÁnÖU~¿=§ˆÓàÃÚÄ=l÷ìÚX›h#âÔ4ªðb_6÷\sè¡ÿùul®‰">ûŠˆSiÓöòs‚'ï ¸h{ù GËêæw›³¹gåƒóß»æ1¼¸ÇD/ŽzR÷çkK<)
+nGä:J*ÞûŽ²×³¹>üŽú°;Ê\q ‰Ÿ/J< ´>øMmØ'Ôl½'Ôv ß,âTÎÏky<ÒÒD}—¹éc^˃"Në¨ÏíšÀåú‡ÈB»>qZO;fà#ìÄë‰xO§vÝëo~ÅO¼ $žQ==+ÿÉëXààYDœ~ûÎ7²¯wê'ÀŸ–p y½þærÉ££Öf_®ØJÜÖÒ×9˜›P|›ˆS9·íÏl®ä8r1סÝ\®zræX¢\‡vŠ¸Iü&Qâ©q’vµ
+H8^–d),áXCžóé¹ü÷î:L”óé…"n² ÿî:ÛP-Óí_—ˆÇ#ø˜ƒr&°æ¤Û3׉8•uÖ1tãaÓ(Õ6êð:×w VÄéÉo+Ó…Í=ÛŒÛ \•àrUÇ™hØWùŽƒB–uºÍ¡ÿo/âôä¼³›«²ëm~¼³¦ˆÓÝ/MkÈqf2Qñ&"Nyþ§Gø\µç]ðc"î#Óv’dZ¬`?»…xéÈ}å"ÀlFÞ`›ÛŽƒHbyƒïEÜCâˈO“J¥Mw¢u‚p˜ÂÿHÂQIõÿ(x"l§n˜©ëì“R¼†„#ÂÌÈû²ñ¹X†çqzqÅzdó˜ëcR©X¯c"N¥Í˜ÖyÁ#×<ác)²âi"N…Õ©ú¿p¹ðÂ,ð©ú;Dœå‰ëØ<\ОMÄ©´)¾ù›;NM£â›Ïˆ8ݽÊÐÙ\ÇôÀ?qjYµäÿÑéÙ ð¿EœÝû¥w³¹å™€Òï—Þ/âTEžQ˜ŸxÏGð½Ó#ŠŠ8ÍI¥UºÊÿ`-³70­rV§Zff‘ŸŒçþo§Ò¦ë‡üÄV ‡wý0‡ˆ'ßärÖḋ„Ne¦^†­Ì:Ø¡¦ø` Çþ¸Û¾&âqð—DœJÿ…ràáÀKÊ®úÛ¶Ôqþ Dœ¾÷]õÒ¹\½6“‰×a£ãî–ƒ ìŠwq‰¯(J<ñ÷fíRnpS‡V€ïqª".?KÜŽtÈ©¾ÎVí:Ã/ˆx2ñÍ‹,¥‘'ânŒUŸ¦þ§ˆSë¢cÚðâ$·ÛDàºû°HóŒ’pDEns_\Äá}Š[èƒWqúâ²?!àff$ëð3"N_\áò“¸\5ȱo¢yžÓØ<P¥ þŽ„S7°Ùû®ñxQⱶü{¢GGÙfúŽ¯À£uÕm< mÅ¿qÊ6…û?Í掇ùwÅŸq*¬¦d+I<â´Ž¾ÎõÊ{J¶›Dœ¿þ|%>w¬-\>]±T©cÃLŠÊ†EDœšÄéÜmRI¿5Ë ó¦ÿÑ@ÄéÑýpy'›[~@3bŠïq*ënÛ\‘Í=Ë,¿¿mse G¦­zk6÷]„€S<¿ˆÓ£{17Y9~´Åê:Õ¢õ Ÿ!â4Ü7ûÇi|nű¶pöŸŠ8m1ûrþv>÷-SñŽ/®ÍC]À#…ËÐ\5Î0ÐúΩ|l®òîþΩ<ŽcȾ½ú Ÿ[.¦°¿½Ú]Ä»¯i.>÷b&r`Ó¼"žÀ‹ë zqÔ ¬Yc.¸­3â‡jTXÙãžæsÇÃzZ{Ü`·ø/D‰§»ç-CSZNr=uWHõcÌPgÆùáãùÜ ãåüð1"nï‹OcŸ[
+¹É)¹>Êò0¥U¸ÑOŽå:…+å¶: kŒ0§%þjÃåzÆçKüuˆÓ{ox±›«6>4¼Ø_Äé“9ûé3ìGS-«ø0 ÇÐGÑ.– ñ¦I\´‹'âôÁþ°d;ñz¹áóDå|Ýv|îbÇŠâ÷‹¸ƒO&‡ä“A³°÷‹·€G
+²ªoól)íýbEO˜–Õ•¥|î›° E®,qjTÚ1ËõѾ(.*í"âÔûuر-
+ñš‚‡×Å\«¼Æ~]DÄq®Ðé lþ ~YÄ©]ôß åÀÇð:½ çˆõß%âTMÔv;›{V,“ß%âTÖ¬µŒÍ}'†’vd­•"NÅÅ#ý'ž\<bÀ-ÜC­WpÁ‰xò“iž{Xv6ׇûºàYEœ2íŠKÛ¸\%QÐß)â4'ußìÅl®·óàË$‹Oo>ÀçN çËœÞ|XÂͼÌÜ»ùÜ7Á6ÛÌm&âôä~|ŽxrÉJžð}ÌŒýøoG¶/îeò°MŒ’öàmDœÚ6ç÷¬e'><"|ƒˆS-3ÿàgàv„ ­ámt'˜&«®yŠÍׄ˨º¦Ÿˆã„—ƒŸˆOôQåÁ£læ osJ¼âUDœ>ØxûîlîY&.q¼}7§ï=ßéŠÄ½(‹ÿÃë¬Ìp—ùN§‹8e›Ç×åes73ÞÅãërŠ8uÄž¼}x”å¸áu1; «OÞ¾GÄéî#‡œcsË7ƒN#‡\’pì¾ÿ´Ö[\UvÁ'ˆ8 u–yj'›'\³¢µÌS{EœŠ‹KƒŸa?:_$þœˆÓlàu‡‹±¹n—¹à¥Dœ>™¸ cÞaà`§¢²KÕlîš!/Å›I8âYå=Äÿí®*l|ð~"N¹®ÂÜ^Äc»1ÕF@iÅ{‹8½¸Ueë4À®¯³b¾ ÂvªÄ96WíyÔ§JœqÄâ¾ìs¹æÅæ¾r—ŽšÝy”ŸxÕ¢·À‹8½÷+…~ã'Þ7Ò+…ö‰¸‹lˆ² uÀ³ŽìI<9±’b€=¼>æ4
+«= ¸Ù¼¿§Á§ÒfùÖJlî{ˆ­xU§ß¾º}>w±WHñB"N…Õú]$/‘ÄÖïj*à˜iºkÈi6w,×6ü¼„#ðàβ%‰Çúº#£ÊJ8ªÈ#£nqªãr´é$àæ·çhÓMÄiÐ)í¡%Ü3üc§Äû‹jK¾wDMôÝ&â4ôѲäkì’6ðml§mYòm Gw`æ ~aåeÆtš9(]Ä}|2íEŸ }°ßœ¥JÊŽ´…<¼.³y ø
+”½¾è“¡÷^~âíàQŽ) yÌ2!ËO¼KÄ)ø^õ/³¹ç"Ó6+ñ[ŒÍUË×1¼–ˆûHü ¢ÄS®kµ¸'›û¾ñºV‹qjœ¼ùăÄÃ1~Ê%èú:3Z¨ø£"NcVÿ½ŠÍãz"ük§/n÷ñæl®²,ö¿Ÿ¿«:›ëÊد"âô½Ï»é¤„#Ïϻ錈SI»xa?þ£³L$ðÅ ˆ¸yqME/ŽÊºæo—`6¼ÎvqzâåEœF w5¸•ÍõAÜÔºh[¾Èµøÿ¶^§CV:àÅEœ>ØÜÖ<vâß }䶖‰8 ó^ñ›+Œ»_1\ÄxqÕD/Ž>™²›^$)@MxÞÞg¿,âTMl»sx”#“×98sAñÝ"NÙæL…Élî:âzpùŧU|ŸˆSqQï“ìÄ{6ˆQ|°ˆS¦­uh3›ëñdü?"NõÝåJð¹çbBíîreDœÿç«…ùÙ&sJëÏW‹‰x€Lûž(ÓÒá¶?lI<¹ 6uÃ,°-s¦’âDÑ°_|•Ë­¸oÑÀKF¥-3øÜÅY™ŠOqªãÞ´ŠÍ ñ¬_#âôÅUyáIþ“÷cX$Vå…"žÀ‹-zq4è413àÉ%©©yBû`õþÄŒ‡%f&½p…Ïm„þSü¢€Ç‘i ßT!ÉõŒ²l#üKR¯,âôä½r–ËÃe¡ ð Ž ÊmËÔ¶lCý÷Œ·-SOÄ©œ_Ô—>X'ⶣNXŽá«EœF~ìð1x”ÃëT)oþ©ˆS-S´ÅI.W?2¦QÑÇDœÚóõGÒr'y||ÊF©¾Î6ëiëüAÂÑêÝ%›«VF {wÉ%âTMLz¹.Ÿ{qÄ|˜ôr= Ç€[ÛÝ ùÎu1>?ɳDw÷Àkˆ8uÿ«|åZ<ÇÿÈuú›Ão¯ZðUwðèî=:ª ·Ü˜<Úâ½/Ю̌ŸWeáòÿêdü¼òo§O&ÖüÄgFIÍ_§ˆÓ£ëzt1;ñ1s¬°â+E<—[ôâ¨uQ÷0QG;¦D_gŽ sÚ­ïJ6Oø8,Cñ¥"NÕDÕuØ<ž9û_µÀm"ŽÙÿ÷òïZX[xôý»EœÖ]”øn?ñz×ø
+w‘mj‹² =º#¿·×¥Ü䥇Ë\DUʸpv"Ÿ›¸FŠ¿#âÔ<ÈùÕulÓÛÀsH¸™\hû¨(ñ1ðÇD<Ž÷µèÅQ⹞ÖÑñ4);#꺘Š¯qjÜѲ6›ÇUyéƒß.âÉ'ß<-?ÿ·ë#•]ðU"Nu\öú•Àõ‰]!*ƒŠW•p¬§mX§—‡»q)Ó6*7‚ÍUwám•&â_V”xê
+½|žÆ.’…DèŒèµlT|ˆˆS5‘kÝ«\®ƒm"LJÅù®Åÿ9µ¡ïž¹Â­âŠ<"NmÚ}‡þowLø»}‡j‰8–ç­-zt4Ä=õ…¬àa÷?uƒÜ·½Ìè÷Ën¾Ìæ‹™‘¦ËÊ\'âÔ²Z5£³ ñ S_È!ùíØ;°jFGÑÝ©»xwœxòˆ–ÔMb=•é`ÕâݵEœÆ¬¦Õ?Á掇cF?#âÔ4Ê}î(x´ðá9#6Z•7\èÄç"ÿ+~¿ˆ£û¿¾
+Ÿ»&fcÛõÕEœŠ‹e%+³¹eãH&Å«‰8}q›ªÝ-à6~û¦jÍDÜA¶9,Ê6ôÛ;õJ<bxGψ™Pz¼ â”iO]Íçª7cƒ¿$á8‘yÅ!ZÁîD Σxà™9è‡
+‰8µ¬*A-“ T’ºYè¡°¸òœ|îY˜\(ñí4>÷-ÌA—øvªˆÓ'sÃσˆ‡S©—¬8:ÒÆçZÄé“iÕ¿–€£=¯xLÄ©°ZÓ%mr yê*2aÇlsVæšEœš…¹/p3©”ëðbÑÝ)וûôQ6·<fq¾Wu6·m3Ôy¾W§\·|ÉÏ\®#áà½/_²UÄ]<º‡E.Ù¶iòw~jœÐa)¹KA^‰¸NÂE­T“t6·§Ï—jRMÄ©–¹iJ>7ë*Ï&â4JÜ4í_àÑ–"‡×™–UÓ´çDœN\:±€Íõæ¾ø §®ÐÅ‘¯€;Q¹..<ð‹8´h™ñà
+]«ûÒÓ‰8=ºú#†r¹ªamÌ€×ñŒˆS{~Ýo°ï¸q #¥ìfß=pšýW|§ˆÇøq¢ÄÓ£{¼Û'ÄHË6Ôuúh[Ôqw›%âôÞ_>Û‹Í¢a+þ¸ˆSg¤ÆtOÀÍÞÿÓ㎩m¶Nw"r;°MÝfë'"NÃ}ÿ*Ÿ¸)l‚¾ÎóãèMütp=ŸÛn&_+âŸU”xªß»í=AÜ‹rÀkx*0ÃO‰8bû,ª"áhí]TUÄ©ú{£§øÜŽaõ8½÷ÓÓÛGö ¯óÌɼ§§ß/âÔ(Í÷SI.·â¶9Ryïß°ïî¨þ^ ük÷‘øb¢ÄS%õš;܉pÄjx½}ž*©w>«Àæ¾™“R¼Œ„£¤}Í,J<•ó£F%î‡è©&•ôuž‹èyÍóÕêËçªPöÀ»‹8}°Õ¼©l®ø'"N™ö¡K³ÙÜQ?
+Œ—¯ú]`s×±MY×»&ñwˆO_ܸÃÁ#¦oã;¦{up=6w\¬%V¼®ˆÓ€[“£›Ù\o›ˆÿGÄi6°o¶×Ø<0íyÅßqj”þ8»-›{ž94áÇÙ÷‹8õ߃†uø/Îà®ø"G¦­/Ê´”m?&D:‚M_çzh*~TÄéÉïZÿ›{¶‰K¼ký7"ŽæÁæRl®‰YàÅ$áqwE5DÚj¤¹^ë‚qzq²óïž°0Ъø_"Ž˜Ì
+\‹ÿc¯¾NåY”uí:q*m¾X¹…ÿèL÷_ñí"N¹®ìâü\®êG”óŠß âÔ,üôÛüÄ{f)ò§ß–qìƒ^챯[ô6x-§Ofýó3­oâÛºžýÞmßÂéuŠÿ"âA”xúí]c#‰'¬(aNõm"Fññ"NÍ™_\nGã õËMë¢H›6\®þ6gmiÓ^Ä=$>»$ñX¶á]ÿŸû1ú`"âvOw Gýþæ==Dœê÷™V°¹oVï+þ•„c6çÖ9àzr!嶋p·ƒ“>_ â´¼êjÏë0[Q>X½CÌÃzFëÜ÷³¹å'°ÿ½uî¶"N_Ü[ÞE>÷°áEñ+"NO~Fášà‘ÖU†ÎPÎÏ(ìˆ8}ïå¾ÍN¼íàÑ)>FÄq<Í‘Z¢lC '>-²xrÑHªÌáu®…RŸÒ)f\Ž‘“~¿*îè9mGåd+å$r² Ž‰ÿٟƽ»žÿÎäyEœ~{飅Ø\Õ1–áEEœJÚz?UpœÄ­xºˆSI»ºjw6™ÐŠ÷qê
+e<ñ!;שÖFJ3žøDÄ©I¼hP+6wU-cß+âÔ®;ÜèAâ}Çðu"NîÙÏò³oÎÿcö0ÇHi¿_DÅEòÉ79û~Gº»m¸Oeícœâ=Eœª‰JçZp¹.«QTžÚ}÷¸>
+ÙñH!5ëí¼àÅD<y÷&ç $.‰0>.˜A,¯s^p9i6s÷m|îz¶áõDœšñ´·Ù<< ;É/ö>+à–gø) Gt}6wìV÷õè\KÄ©U¹ú¥…ü'¯ž]|‰ˆSyôB 6Wù±£îqêÎÌþd¬„é{ŇJ8>™MÇÙ‰w?§8ÿ½+Ž
+ú×Üò³ª ±+3w/§G÷ç×Kù<ó<©?¿^.â6Š‹7$,?£æ “ äRó„Ž+„“¸g´úLÄ©'µ¼]W&ìÀO ¨\Þîa§ÖÅÅñ%ÀíH¡ÔuŽáOþö‰OßËæ–ƒ´â-$ý÷j«s¹Þ3‚xµÆ¶ˆÓ£{1ë#|îyÔ—Q¼—€ûX²rqü¢GOþl‡[Á¨<æžáŽˆÓ(ñÄî%ØÜóANñ›Dœ^\ÉúÍ“Ü ×˜¥žÒ
+‡YmüW²þ="Ž¶Í™ül××&y3+›»Ž9§™•UÄé“Ù]7—ˆàüß®£çQ®›ÐµÿÉ[–&Nèz«ˆ#ØË›Ù<0»uÿYÄ©z}ûüGçáì<ÅGŠx ™6(ÓRâóÜÜÜŽ´ÁÑÓa&‚\ž››H8âQþbsñ‘]‰éø܉ãÅ•˜þ¶ˆSa5âóqlîZ1ì ñùë"Ny~óûSØÜ·chÓn~ª„ãÐô¡×±y\ua]ðl"î#Ûœe**«|KìN2ô_ʆ™“<'$þ¨„c‘Øû•þ`sÏ‚¦ø §<ß°ÿ·»®9ݦa«GDœÚóÛ7?nG
+º^gQ§øó"NÙæÉ}¸\•qÌŒœÜÔ„}wÕ²ÁÝOnj(â471ñ±^ìÄ*Ë;à½EœîþåÝù‰÷p¤²âEœÊºïÊod'>á!Ó*¾IÄéî?H°ïºN&¯#âÔª,¸j…€»ôÞ_%â4Bn=ú=›ë‡gøf§Ò¦vÁúlîdnú¨]°‘„£qò䊢₆>ÒÇÐÞ'¹,3uÃLOhy(¨­ù˜ÍÝÌs­ùPÄi„¼rWx5låq§¢²È eÙ\õbQP¹¡¼ˆûxq•E/Žš…ÓÝ-t€¾Lõ&iäP}§vÝÃëØ\€wÁ¿q*çO5(Ææê¹£A^½íB6×G:ÇÀ犸‡Äß(J<½÷|‡PI%—¨¥\$¦O%ö=,QËwh“ˆÓݯôšÃçú0ð"Nw&—bóðˆWð2"NyþÏã.›;.V}dÔ¯ü›ë…܆q*ißp—ë½ÿ(ißÐ^ÄéÅí]Љx×÷q÷½ ºŠ8¥ÕgsËG,nÅ‹85‰ÇÔ¨.H¼‹Ø¼cjÜ*â&ÓZ¢LK‰÷îšI<¹$5åb!Ž”ü §’6møƒàv4®£Ç›¦QÚð®ŽÀD¯_܉4±¢¸oŒPüv ljj}Ñ¢ö#/«¯³­ΓªÖwˆS®Ë7‘Ï&¢”âë$Mâœv!ÓF Σt¶b(isvÚ#â”ë쟋±¸fñ€ýóŽí6Ë*/RNmèC¯=sÄjP¯.›«F%¥A½Z"Nu³G°¹ã{X8ÑìÇQŽìÛ¬šlî;fáÄ6Ëq/n©èÅÑ»´Åæu’‹ÄRV1½WS™KuqÄ1±™Ï³Áˆ-"N£/ùF”ø
+)>RÄ©†Íòúl®'`¨Žó?ÛÎæž9†Lñ­"NÝÀ¢-®gsWý,ðì"Nl©:µ¹ÜJø1L¬”ªs»ˆ{xqãE/ŽŠ‹2 _"îêÉa7Õ¢}^½Oïý ã¸\uA-|qL-â?L”xeº÷âž®ø"|°ú|,kv¤·Ïæ…»+‡Äß,J<Õïó; nGéˆéë,/èyó;/âôä›7ùƒË­¸ãã?$áØà–AÑ°9<pñÞ_%âôÉ”ןŸxq2'Ÿ»V¸ÝwÏ£Ž@%¥þý5ÿ½«ÖM
+¶™¼Î¶ ¯&âTÚ<šö²ˆÛà£%õ{¿øoàáàCªÍ>N¸‰çE*¾_Äé·÷³:
+¸©eúY]$ÅE£âëØÜÎ<¡µQñŽžTûÖ¿³¹ò?$âTX/}?ñžx_º¬ˆSãä‰q7€‡ƒ)—m„:†'ÿĸ"Ž'ãOµˆ‡Ë´"|2:üï~»ˆSqñL÷ñ¹™ÖQü97¡ûG\Ïç¾|qùM§1«Mï bs×Æê>ŇŠ8Õïž(/âxe ÇÄJßßmðpð!uÓȱ= qj×åz·'›ëðÄ+§gsÕºÀÚƒÊécEœ2í7{ø¿ÝÒßxm§þû„ÁWøÜAäf†dq/îQÑ‹£lsüºq×ò#Ôzf! Vñ„ˆÓ'3bÒp=ä¡a¦¯3ÇUŒ˜ô‘ˆS£4û=ØÜrã(ë²ßóƒˆSY÷KñÆlîèxÉß^­Iq6wÄ=P¼ˆˆSâ;.ÏO¼s¯(âq<ºú¢G‡—çâÉ…‘)ÀÛº˜ŽQè
+[]ø˜VÜqª&Ž¼×NÀÍšÒ#ïuqjÛX³o»B©+è¸sÂ(ñüµØ\¥Èæψ‰8Ë:]âr+¡*xüªˆc·NûìÄǼ8"…Îk?PÄ)Ó^ÉÓ‚ÿâ, ÙæJžV"n²ÍÍ’lƒi¹h'²„]à”[NÂ)ä
+[ñ "Nl¶1ÃÙ<pD]ñE<Ž¶µäƒÅ£{ë ´¨ÃeZªHuúü5§îÀ÷«N³yÌC
++Å"NÕÄ÷ëãs?ÀQ›ß¯{\Ä=¼¸}¢‡x?¢¸H†€KÝt›̓ö?qúÞ7YOó¹ÞÊ >DÄé“ÉÛ
+áÅM–¼8L&Öî€1«x¸L+uÓ(n¹ª‚ÆÀK‡"NeÝŒÆ]ÙÜ× µÀqzò…ªŸ̤þ`“×9àgDœ†¼ò>~–Í=è2¾Û¼šÍ-¼*¾JÂQX5MßÇç¾Y¦Õ4ý ˆÓÝwä\Î媎ÃaŠ%âT¿—)_€xÇ7Ó¸eÊqêÇMÝ°Žø„9éCñ "NŸÌçE~e'Þv°ÑIñ"ŽQâñ…ùÙF•wØ}?¾¸„cÿ{ÞÇO‹>XêMÔìV‚x`¥>r‘®³ÌÑ{5»•qzòZݘ<n«G¡XÄéÉ—*t†Íãæ¼ ÅOˆ8mtúàòp;õfÞämâ.Ödl¿þ6OØ&vßöë7H8âUŽz›»¾•ÉÛ‹8Õ2u‡ásÇÄæ­;¼„„cSç—7I^Ž!kuƒÌA„
+»èe>·bˆé´»Øõ"NõæOÞesßr°Åló'ï‹8•6>~”x"<fôÚA•é:¿]ñ^"Ž*·Srš¼Î5gm(^ZÄ©y°uS>6Wå´mxA§/.çC·±y\Oeƒ×q|øfiS6w|Ú÷›¥Dœ>Ø÷.QQ©2ð¢gÐ]´*3´|„ÍõFfÃñ
+V(þ©ˆSA½ºJ'ðaR’\7Kðn"NcÔî ¸ÜŽYh](ÞXÄéƒ Ê5gsßÁö:Å[‰8•6‹gìcsÏ„öUü€ˆSëâöü ÙÜñLôÛó/qŒœLÌÆæªXÃBèš³H8FÈÿåö!î[©ÌÒu:Ä,øŽ–Õá,¿‚‡ÍÂÔ…•ºNÇÛ
+'¯SÅ4¢çe ÏÖaòÌìÙ¶ü)â”ç‡LZ!à&ªÒI_‹¸‹G7Cô訸hчÆi'B¶äužêT¼Ž€c3oÓ-*yc!¼m³g†ÔbsqÒ‹¸…Ä?,J<Õï?0‡xrˆ;5×CÜŒøøù"N%íS}¾gr½½‹Bß âô½.1<ÂQ›ÉëôÒDü_"NüӲ-çrUXÅ°'tZ¶eŽá¾&—σGkèƒloz²Þsl®ÚÔ¨ßOÖ,âÿ—(ñTPœ»#ñääBê*ÒÓÓ:ˆšøqîN"N™6öåp;u´äu¾ƒ£yß/á˜Pë6yª€›ÈÝ&,â4©”çÆ\n¾@£ynœ-â´,³>æã‰y>UЊó_œæôÞïªþ-Ÿ[æÈÅ»°üžÉiVhïXZ~ï$‡yS~8"
+ç?WÍã¾9W(ÿ¹t§õ¹Ø\õe,ÃqÊóÃœÊt6zЊOq/®”èÅQ«ò£1hF\†­®SìøhÌ §Z¦yÑ,ùÜ3ªxg§ZæÁ}¨ß#´†!ÍžÐ÷Ý*âTÚ,_”‡Íõ,p
+‚‡‘”ƒ:&³ºŒ¦ïûîœÄå:X'Îê»s¢ˆSž¿qëmlî˜}‘Šß)âÔ,<>òeö£ TÎ3|”ˆÓì@Ù.7°o9ˆñ¢xwmòK² ŽÖí±o9¸õîzxÊÿJÄéƒ;¢ ›ë¨ TA×ùq<›«¶ ŽŸ«óãX÷‘ø{E‰§¢²]lñˆ‹ÿ]½õ öv±—øܳР/Óâ6××ùàEDœê÷êww`sÕtÇÌHõ»;
+¸ƒVåÞj#Øü¿ú2ëª_ÝÝ?#úíq$þAâM_æà( <Ú5W/n1g*å‰8e›Ê•«²¹g¶]4ϵé.×'¤ÒoW|½ˆS¦W¿ŸÏ},UR¼“„cÙÆ5–²“9bvG/Eœºo;Ìæ:ì¡~TÄéÉ÷nØŠÍmÕ*L€·–plp»Ò²›ë  ~£ˆÇðÉT}2Ô›;*¹#Õ —B§úÐ×y¾Y8ϺŸÏ-t…ß-âÉÄ7¹8ìz6wÌñsŠqjf/²…Íõrs|›ˆÓÝkvù”Í-7ŽÈ5»Ìñ²McQ¶¡Jêõow¬(“ÈámôîðwDœ>™<Y¶³yÜëøo"N­Yß á0¬äuª Šy™¬oÿKÄ©†½áÜ
+mBThiʫηÀ­¨Üqp%SÊÛ•ª³¹í"ð âÕ¥Tâ—ŠO}›JFw#mþOþÎÁBj¥#E7}t˜ éªMËgËqRóUùƒÍM;†•Ð|UΊ8Ú\•òðoÁyrUÊ/âôô’)¯ñ¹ƒ0æŠ/–p„ø¹Ã+¢G݃¦§÷".ðlQS|ªˆS »°bðÿÃ`DGÇuÐÆåΗ÷ßø?=ÝŸðC÷|7‹8µqeGTàrUM#ð âUDœ:¥cßü‘Íõ4oü„„ãèÁ+Mbó˜c¥ñWDÜB±©'*6˜¯Û\<Rè
+Lærœƒ‘D Ž¯eÓgv´ÐÒ?1h=sÿ×lîÚA#uæþM"N=«|gg²¹ÿÉÏq*´OÕø‰Ím7ŽÄ?U㤈Sï"~çH6·\|2ŠñŠMQ±¡êbïlÚíc%6†W¶ÝdÀ‰8UEŸø™Ëõߎ&²è'Dœz˲ ëœHa‘ôï,ÛÁ’Ö²,™EœÆq¿¦ïÂåªM#©y¿ü”ÍãF Û°ó~ù±„#Pɯé;Š•‘—Ñ·q"…5öœLTüg ÇœUÛ›hün%§¸Ãh×?T"âÔ¾_øm›'tu¾GÄiºoáë}ØÜvƒ6náëDœÆ°ßœÿŽÍõ9hŒŒª¸Œÿt'8ø0ªâb §§¿_”xšöYz¤)x¤€Òúwj‡å¼¥Gš‹8 ¿ŸœŸÍu´ªmþÊ™•ÍU—Yÿ•3£ˆÓ×kf^þßîؘ§í5³€ˆÓ`$èãln!à?)â”uÙ~éÄÏ:õæcà‹8=½Ä·§Ù\ßã‚ÿ&â
+mQ¡¥ÎÉ›'ï#‹¶%U_Qbãì@jìË’\nÚvÐÂƾ,&â×èjÙln: š«Tüm§/®DUvⓧFÀoqªiWojÁN¼jf0õ±zÓƒ"N“oîesÇ
+.Ãú¦á~§f"ÏžÕì¬ó |ñ8>™TÉ'Cûi›æmãO« Œ¨Ç86u‰¯)â4~e欒Cœè
+\*ÝÛl·‚+J¥[)â4’šÞåA~âíÚ¸é]»âT],þ¥ ëLŒ ß,âôâV”ï+H¼‡¨ +Êp”º¯Þ/à˜pS¼¥ˆ#FkÍ~’O{ìO:Ìk%´†WÔq=–Á·ØŸG$Q•îùz ›;ºß&âô·¿ü F‘É%ìðÊÊŸ±B|›—ù^Ä©G}ü‘O(¾^Ä©²:yKò¶>ÆbGÙ¦å?#)ʼn8uÌŠ>Ó <Ò´ÿ;} ¼ŸˆS©»Q‰·#]#®ï;8䕺➭\nú+Hà›EÜCâŠO¼f¥3ÄH+ôcTçÕEÍJ¿K8ªÊÑUŸt9Žÿ;#ˆ(5ºêÓ"NÃÀËNq¹
+ñ˜ec¤íßÃ&pŧ‹8½¸=/}nE¹^ÖÖAØ\DˆU|•ˆS]7tM{âže£”þ]Ì Ž ]ÓEÄéÅUÌ1ÜŸÞï”êt0ùP1ǧɇÉ-Ƴ¹Žñ’
+®èÎæ¶j mð>"N]£ZÏ$ØÜ1‚P!µž©#â4 LsÍM3Ž¬K›^Ä-<=“„#ëRçdqš-,vK.7⪪ ¶aOe?ݲ|°eÓOqjeªfxGxZÅW‰8}ïO}Fx‘žþúG@ªŒgÙ‰OXÁLéþŒçD<bSPTl¨o³wç.âÉ…•Ð˜iþ-„»â{%Çi?¼ã(¸eC¬æª‘ÄTç‡wq*´gGåæsìŠçpL°7ibÞ
+4ªwqg¢â%Dœþv¯øh6÷\\n«ø8§B;7qÜ
+…g>–ƒPÞŠ/âTæçy·³¹c[ض1Ï«-âôô¿`sW ÿàE$/™ÙÜÐ'vÀ³‰8uÌR>ÆÏ:'ˆ¢6ꙧÙܶÐ=PüqGßæà`Qâ©g5µÅ
+âv¤Ã}êwFBýÃOÄ©Ø\¨ö›ÿí¬Ð_eà?Ý¢*ýõQ:GÇ,Åü`8—›¶DÃ6?xVÄéƒ<«›[v°ëcò¬ž"Žö½viÁ‹K ¶Ï‡µ+ˆ8=ý×Æ]Ù‰×7‰aY§qw·PhO‹
+-}q•°€n&7N„nYÑ7¬¨vèv ‘pšúH}qY6WÝqD
+}qE§w¨` ðHZõïTŸ…öPASÄéé3Îu6õaú÷=Ðh¢i·±¹kà(±âUDœêùyÓ²yÌ–qçMo$âTQOéïòï`›–â 7ñâ:Š^5RöÄ“Ëy¡ júw¦‰á€=d·€[4ió>›»i1ZãcV‹8uÈï<ò ›ûõx§/nÕÉ›Øܶ]lˆ]u2ˆÓÓ'UqˆÇü
+鬣VLðƒ"N}Ú&ís3yÂø[Ù¤}~§bóê %ìÄ{.¶¬(þ¦ˆÓßÞ¨Ip3J6ýõµc¿Mçž¹\¯ÀãŒXçžíE<†Äw—$nü‰narÃL”§ë–Æ°‡jµas5Áô¡ZŠ¸‹Äw%žêºêÖ$¹åo× Ÿx±ôv,.(þ™ˆS⫶Þî_ŽºILýÓ¶ãØ(UbóÓl®ƒ6 ÒÈæa"n#ñ[D‰O›ÆWl'ž\Â}q–¾iàOFñ#Ž#¥ÅÛÓÄ‹eEº²AÿN EhÎJñL"Nu]†‰xqþ’VîŸóÀŸqj¤2ßžžÍõ‹x&§Ú¦ËîËÄýÅ…Ü_•ÂFè¬Óæ°¹¡ïŒ
+ql
+Ýz3— ÇÃÌIíyD<ȺßEYGì“û¸çD˜îÓ'2ƒ±ŒâÏ‹8›¡ høïÇ¥‹Rl\}ÓÎm0\Âiq!¥\ë‘à~,ÆÐá@2Lžð"NÒ½/? ®·KÚá ´^Ö fÌö¾ÜSÄ)ë¼ÐˆÍÕx¡ˆc[fsô¬bª,Gɺ˜â˜)¾EÂ1wq¥$r^o®víðŠZeBuÑôæyÓØÜ6±6¡ød7‘ø΢ÄS{ m×±ôá­(Õ…§ô0üÿ,ÇT.×éoW|’ˆã¶‹{¿`'^Ú°Á7‹8 ¿Xœ‘Í Ç.Ï"âÔHÚÍud!¼§ˆãB¨ýÅÀ5I‘¸>F¥™ˆû‹BØü?#—„ã´Î'Ÿíâr#îᬯ]êϺ…>­â½DÜDâ·‰Ÿ|zã‹»ú€ë[ªÃ·¤êð8vœúóŠqzqCj•eó¸j!cà%EœZ™™é—O^$žÐá2p[åÌôËEœ†ÿSFî’p7à{ç¤R¿_R›ÏÍ ¦Ó÷KêŠ85RO¹îw C·iéß©.\À¯Š8õië}y ››V°
+üC™ƒl®¿:|ŸˆS#Unûp~âí pA¹íω¸‡¬Ë%Ê:ª*¿z‡Öau|¯(Í„Ž‡eY˜Ÿ¯Ôê6· ô*(â_G”xˆU5hçƒê¬%¢ Fô¦ ÃơΪÆ|§Væ™O²y,8#¦x}Çf¡Î¥ÁýNièÆH=Åk™8äucÎ6·,L:)¾UÄ©_7¤Ï‡lîZXÚP|ˆÛȺ[EYG +Ùv'Çïªåð;faÝÿw&vy)>VÄ©[¸ät67-”ù¦¹kŸár}3eâ?‹8½¸†ŸüÆO¼í`ý½á'çEœ¡…j–e'>æ&°=¯PÍŠ"NŸÌ}-ʳï_Ò^IÀmœ[Þu†çºøÞ—w¸$âÔ³Êìä39êÌnQ§/®Z¿í‚Äã~XÅw‰8â˜e<ÍçV&%žñw¡ºÈ,©.p›U¥=C‰ëÞHùÝá` [ñ§DœÆ2ñ¥ ÁýXX×HÿÎ0‚ó2•Ž­àr½E !¡*{SÄ]$¾®(ñ4’úú+Ô´–? ›pÓ<fÛ´vìØÆ枃踊oqÊù—?ÌÀæþ¥àYDœJ]+Ÿw"+žMÄãxq'E/ŽÚ÷ÍÆ"â¶ezßÿ…ëe_*â”u5VÕ`ó˜…먯"âÔ®ŸµÜ
+…&rü-Ó6fÖÏúVÄ©‘zå™×ÙÜq]J¼âóEÜÒ$>Ü¥•î¬„ãV£Æ__$ž¼#+lòAÿÌ1ƒ+æ­ârÓrp•¶âïˆ8&^¹¾U’x3à;Dœ>™¹+N x°ùîŠÓ¢œ§‰Ö×Vð¹ÇúkïK8Îän´ÏU5oƒïqª.*Õ¯ÃæqÇÁšT¥úwJ8VÄnÿn6»Ð6F*>_Â1_7-ï AÖYFÀ‡ˆ8uÈÝwnð¯7%_™^Ä]TVçEŸ }q¹Ïþ nEYDÖq]»y?¸v˜Í´ÕÀ®q‰ÿ]”xœ‡=‰çú“NáY§CûÆnÆ©›Dœ^œ‘§ŸÛ8بx/§©ÎKïõas+¸ Kñ"N“œ?Í"óba“Núw–ªmlð9"NO/¾ûŸ» TÔÅwqª¨¿ß™¸ç£pýÁšà]EœÊüw•72¹§Æ žþ]å¯Dœêº|­pÄ«Tü7§AèNvp¶uÁ¿_ÅÆž“Ô<Ïds5Å'“ç¹[DÜDⳈOOßv© ñ¸? [\пsu| ðf"NõñWÞ´¬£§w™àˆ8­ÇŸ:EÀqœâÓEœFR%=Èæ±à"°¦…
+¿Îæ:n‚¾PÂ÷`Ы¿³¹a%Ð1ôêŸ"Žp?Zlnbw%µMÞ5/q¹.õ˜«Ì»æe¡ØÜ/*6ôÞ³õH<{žCxB7ä4_§x_§Eä^«÷ƒ[Ñ:¥ ýÁâ\d¯Õ߉8µ2ïV˜Àæú“uÁÇŠ8Õ6å'$7Jéai¤®‘ëw"—ŸÐAÄ©osfÊbp9/ôÅ™~ì|ô¬ÎLy]ÄéÅ¥.*F\oé÷OÕ‡póo#¿UÂQ泎©Àæú6¼ŠˆSïbnßMl’Iñ­"Nu]›¡²¹ž¥Ž,â4Í;k¦ÁO¼c£žŸ5Óqª*3]¼Îæúš{šdÎt)½ˆSÎß\¶ ¸¥y貎©Ø8‚°Ý\6¯€£wÑäÏæÔ»Ð;Ilÿ´e·’U x Ç´ÏøýEÀÍX¤¬³t\% FÆï/&âÔ1k0°6q›ÍﳄpÛïàuEœêù{+ ºP=Û=nãøÈâso…ÛDœ©r‹Šr¹^Q£ÍŠß*á8ÐÚ,_â:ДŸ£!ÜñW\]ðÁ"NUå—×z³¹m'E­ò…¸ÜH¨†×Ó\h!áFøî¢ÄÓÓËíI\ÏûkË!ÜUYçaa¥Üþ"Ne¾GId]Ì0"U®¶‰bÓ£dk§W|ð1&éɇ`Úgð)§ªò1·ðïxïŒÉ%âôÉŒ»\Üo¤B‡¦¾FÜB§tÜeSÄiüþC–blw<\½÷C–[Eœ:¥·z]Ù\5XH]zùk>w‚ï}éåMŽkJnõ:‹OûÙwßØ=ˆù·]P31-ß!6÷¨ïq‰_!J<5‘{?¡Mb¦çwNB§÷Õï,Õ–»à•Eœ^Ü™›KGìœxúJ(
+—‘úò˜Å\î øB§Xæú³¹áÄP×eþh°„c%ô™mÙ\‡Ó
+xG§6nZ§¬lnÙØÕ©xvÇýïØÅFµq%ÓâeDœþöýy ó ­»´/!â |2n¢Ø4I}Cà¸îGèÅÕkaYê ›ëïMž{f¸ß%â6õlapqÀsƜ˩‰|©ìsÄ:b„ŽYB%{RO hÆ玃/'¤H8æ¬^*û´(ñÔʼ3b<¸ß%¯¨ºx!¤ó;#^q꽕-#›N‰Ïºª)››ªªL€7q‰O'J<•ùî¡©ý/£pËÐJ°Aîƒ{2‹8µ°oXÎæz/q|‰ˆÓŽÖG¾¤Ed+9ñÚ!·Tã8­óÈ—óE”IÓ¼Vrê#œ[~€ ¼­„£ÔkÕ¸?õëëÒp×FêúùËÙÜs]ô*×Ï_"âÔ@_Ï}›Ç‚Ä+nˆx Y×K”uTÛšD+à–ãW•¡Ãõ»˜2¯øïŽõ¸×ŠòŸ®2ŽjZÅÏŠ8õi_Ú‰Í=ÇB\£Ç—¶qžþ2¸®*çû,i·œQËÕÖ0ž_Ä©{P¢ò­lžÐgµÀK‹8eÝäâøYç"´¯â™E<†7Aòâ‚Íÿcï%®ïë‰Ð)U¿³LìöQü>§Õÿ<O¯aó´CŠ*á8—½â6p¿‰ æµôÒB =«ZUrq¹¾çKصªäqêQ?™q5?ñ6By+þ‰ˆS™_5Õd'^uüiø¯¸-âTæwî~ˆø¸jj\ðn"î¡Ø|-)6ˆÙ¸'?mŒ´’S¡Ã(Ø?¯xF Ghß,ïç÷'ܯƒø8VÀ ˆ8Bûîú–Ëõ± ħͶ뀈Ó'Ó)o>â^Än¡“‚]^ŠqjãÆm¼Àåªkä ÌÛxEÄi41îËŽÚFñÎ"N‰¿œm;ël7¸)¾WÄ©¶©[
+ÒäÔGx3×ÃLq×^ߌÏõ5äà-DÜEâ»K;ó¿º ÜŸx dVqÒ&Zó¿ú–ˆÓ{O}añäÔG8OèÐùFÀ_‘p¼¸7—~Ææq ËyŠ¯qzq¯Îæúú; Üqš|¸;÷ëàþÔGx±Iø—ïyàKDœFÐÕš,ãrÕ£6ÏêõyÝÙO׋ðqð‡EœJÝÍÙ׳¹kµÍÍÙ¿q*6W˜ÈæV°óAñÉ"Ž¾Í-UùïÝ N¤f¿¥º„Ó›š{è6×»2>Oıý¾nqþ‹³â¸¥4_Ý[EÜÁ'³HôÉ`] Z¾· #R§ÔÖ½Gœ‡Uü´ˆÓ÷Ý&°¹a¸˜h½;Ã$§í¸é·Õ$ž^œâ–ˆSâ÷wè I<÷wè"áXLü°^^ðh[VtX$½¹&YêZýñ3—ë¹Lï·úㄈÓt_o+ñ¹h­ñmU§Šú%ØYg8XÒR|ˆ{xq¹D/Žr¾ÂÁäÑB׿Õ=Ârž~ŒŽ{ ~TÄ©•ùéHðHÛ6ôcTßÂø½"Nc™]»³ONï‡-mèßéMÜ”uñùÜ n9‰÷Ø/â.ŸY”x*´Cr.!m[¦þi%0 ’s¹„c«Ò¦§Êƒ[Q¦÷]ÿú;—elzªŠ„ãš’
+ýïasUM;Oqªçkö­N<9íöɨßùgÀpKÄѳºw6ŸÛzVýî}ƒËuXc+à $œZ™”–c«±¹Ž[pƒÏm¬¤¼Tz;ëTß«B/•Þ/âôÁ²7?ëŒ`8püÉ~"G±™!)6¨iGµ~—xr²1¼¢vu€ÌYj½JÄ)ñÍ?ìî7a›Fôc<û*SéÂ扴ŅÃE:ˆ8"J½q”ÍuÇ2àÇEœf‰¿ýŸÛA+süí‰"îâÅõ–¼89©6ix¤Íú1np»Mê“W‹°¹^3qêæò.ð¹lËå]qú` ºïó³ÎÀŽÅW‹8½÷"t‘ÃÍ´ûeŠ|rQÄc(6¯ˆŠ wtG±ñ7ÄFèyúvïïè^\Ä)ç;îÃæz%Ôï/âT]œO7ûD¼J[q/—" Ï9O÷û´á߻ގkÑŽVÅŸðàör&³¹ìhU|ªˆÓÄKû‡ÇðyÚ­…í'á8Rzá­v\®{•˜x¹ðV'§ÎI¹®¿ó_œ…Y#ÅÏK8:f­Ša'>¡¾øx1aöü“ÕÙ‰W#9¬€Ï?iˆ8åügEÿdsà "J}Vô’„#çOŒŸ.ª.¨¦PÃä’VØÔ‡þaç 1$Ó¼…ßÏÀæjH5mÓ‚ïÝÊåFÜupŒºà{EEœrþÇ…õø\ýüNÇå¶ï§euR붷¢M>èûaƒï=µn[§ø‰¹˜5J.¨…wz†¹‹ssK8rþÄ‘bl·°)Tñ"N݃ßÎ÷có¿ üí|o§bóؾ·ÀÍ(K™® 8Â7ÍкŸ[1|qZqjaó­zËU5ì!Ï·j´ˆSU¹2]96׋.xG¯òú4vÖÅ]m\Çë³DœúóM¶e'^oÉ2ÀKŠ¸B»DThiù>{™dh_}ýe”é}½ªw‚²—9-âÔ³*µÃbsÿBipWÄéo?êþÆO¼í‚_Zÿ$ÿé6ÂY+þ„ˆ{Hü/‚Äã.­”Û¾¡Y#
+X¶Œëê€:x§švqÅnl·Wñ"Nì•<ÍÙ\Ñ°ÁSDœZ؉vOëý`Íd
+ðÿvñ ¼ˆˆY×W”uTYe™ú<q=·a©§>.|´„#ìaûe#À#mŒL.h[VÚ/)áôô”N¼Ë榪¨ãà«$Û°÷ÅåFÌE
+m³º‹Eœ¶&N¹¾‹ÍãFЩ%–7bs]>ÞPÂi¢U%~›$ñØWi_Ç›<ä:ñbê+#âØõñÓÁúl®ªiì«üé`mÇ}‘CÖòyÚÕ{C†¬qêœÜ”i¾ ñ6®âº)Ók"Ç‹ë%yqTQ7¾Vi3x¤ƒÌúw1 gF_Äé‹ËÕtq9B¡Õ‹ÈÁE!¹š>#âTU^©ÿ—ë¹Jl
+±è;öÓci7}ÌXt@Äéooñl#vâÍ Ä«â©"NO?¼¸/;ñº¦5ÀŠ8õ¨3e|“Í–‡=f™2²ß»Ïq%Ó¼*ì¬Óû}°þ>¯šˆS¡}0ß5O`ù`þt|n!b®Ôgç¼?½O‰¯Ô}+qÛF$î¨ö,à;$1Ü.>Ö<RÀIý˜¸aàt‰•O±¹êŽã„Z‰•CEœr~ye›Í¶.ñòÊžˆS±YÑ»+?ñú€ xw§ï}íþ‹‹AD©µî“p›ã¶ò³Î N¨ï´]Äã(´MD…–ºÄùà§>ô·8öQç;`‹8 SÀƒó2=›ßÊæŽG=ß³yq§¿½fú®ln¹XÎS¼§ˆ'uYEYGí{Ó‹oOa ŸlôÔ8ñç_)áEž½c,ŸÛÁ• gï˜ â”óEòc4á¯AGh&<=ƶ"ùïqúâM.Âæz/ âôÞs^\Èæz-2¾HÂqµn©Ë/ó¹DE.uù ÇìA….³ÙÜ0ƒàùºÌqtȯ¾ËçÁ+Š âôÞoéI[‘)[ø„[\Ÿ–Aþ–žDûmÞÙ é0¯~Œk!˜¶âß
+xÊ»ÎÁMlî˜Á4ï¡ g«QRª\CăÄ.J<Õ6 wÑÉ
+>
+鬧«Kœý_¼UÂÑÆeý’6ÀSxÛÿSl2þ/wÕè=he²~ù«ˆÓû•†v!”úÊb^®|4PÄéƒ-µð¸%À¬~L,-Œy©…DœºÄçž¹ÂævÚZä¹g.‰85R™7<H<y&4<ëT‘U1 ¼­ˆÓßÞqÿ}\n$ ÅïqzúÆÙ}؉WlÚ8»ŸˆÓTg•«§Ù‰÷ôþƒ$ïÐ''›ÇMÄ1S<»ˆÓxK™9üœwZñ"Ž€Òk_ágCµlk§‹8½¸ÂOμw\ðª8;ë|N݃3º±¹œÒR¼·ˆ;(´?‹
+-Õ6ù¶`©¯™ŠÒHÅuØC¬„æÛòˆS÷àÇžbrÏô\[xìY§Šúþ‡Š EdÅK‹8î@/¹ôßø?4О^RCâÏ”\$âThÓíÞî/aGH¼/âDªâ%œâ˜¥d^6ËÕÃÀ”Ç&½À~º©ïê!âÔ·)uà0?ñª‰Ã¶G%›FÊí®ÈæqQЯ*â.^Ü,Ñ‹£œÏýê8p+Êåwú1¶ˆ)ËktasËv1åµ¼FGwøÑ¢ÄSU¹¥çGÄ£׿Ókbø§"N³ø„Íõ@Ìç'^szú•:­À#UÖ¿Ó-¼ÞNĩ̧îü‰ÍM aRŒÙÛØܱbøÛÙ_K8îÒ*9m—q5pÁßñ8²îQÖQ¯2WZ\  Ê¡‹ ~PåX_$âÔ5ºmL-6·ì¶ëÜ6¦®„c
+Ùf´0§:–ÞÆ žQÄ©Ìg®¿ÜŒr¸~LÜ ¶ef®¿_Äi
+‹£²Ê±`®ˆSÖÕmqƒÍÿvALÝûoqª*çO}…ÏMÔ6)ïÍMð¹…ûãwE<†Ä¿,J<¶ 1‚¸>"l᳘ÞÃ#䣾xZÄ©…Ñy ¸©yx­cÇm>Íö—ë3b¸[çÓlCEœ*êÍÇÏñ¹‹§+~QÄ©ØŒ4 ²¹‘Ö-iqjß'׬Éæz³Q ¼¶ˆS©Ûû~y6×{Ü\ðJ"NOÿePs6×a‰]ðEÜÃ'³YôÉP©ûóìÄ=Õðû½†îù[Ðð\"Ž•‘>KÁMÍÃ++O>Ä
+íYQ¡¥¶ç€ä’–ê3è)73
+»q FzX*âÔD>aw×Û1›H}hÂŒcûÎÇD<~TÄ©Ðfø´—ëž7:'>Mq*óÙÊ×ás3¸ª#[ùú"Ž+™N”aó„\©\äDywPlÚˆ^ÍQ_˜Ü\ŸÍ6Bà:ä·ÜØxaò@§Úæ¾A·³¹m;MÜ7¨–ˆS™O·u/Ÿ»±`ŸÕÖ"N{É›Û7ÍHƒP?”wpÕÜÄr6·]„„R|‰ˆS¿nÐñóln86í»Pü¢ˆS©[´d›»n‚ZXÅwJ86È+¼Gôâ¨wQ0&â–? æõ?ëàƒ-˜?›ˆS#µzh)67‚KÌ/+á¨iGÌù ÜŒ„WVªM;‘z&ãrõ—#À¬â–ˆÓÌIæyß³yLo»ÿQÄ©Ìçûc›«î8}äûcšˆ{xq—D/Ž#ï|ò q½ (R±Ñq¾CÄéoÏØl¸Û~¼‹8øh§µ‰kw.gó„>d†Ùƒ{ùO7±”©x Gìýkw.%7¼Ì\1Büî.³.x ›ÇƒˆRŠoqZëõú«ln»XÊT|¾ˆSe•õðA>7öÉzø{wñâ–‰^•º‡žCuᘑ&Ôïl×Cþ¡ç® x°]gÙÀélŸ%â4Š|hO6wluÝC{ò‹8½¸cMÇòoNÀÇ‹8 Bsnd?ýïQ•rn|IÄ©ž¯Øï$qWÀ#Zõ­ŠŸqZÖ)±+'xĘ}R•Ø•[Ä©²2ÿ|Œxr‚=<ëb:Ô(Mû(>Lıeey6××M`«Òòþ"ŽØûmLâÉ)îð˜>‡û wE÷MTëÏåêÅüÞñ¹*56øû"NÒ*9'²¹Lu*>E±œg®ÙÉÎyÏ î7×|+âÔºO­f'^oø6À׈8µ2½ºÜÂ/uf“½ºqúÛ÷·kÆæq'ØÁ¾¿Ý"Nß{–.­Ù<¦².Þ^ă¶èƒEØ„oѺFž¾
+O¨ÿtÁ÷Š8½÷×7´ârõâ‚Û¬^9´„ÍÕBÆÀßq„EZý>?ñÉžw’¯–pœnßu#›»v0ÙؾëW"N“s»Úð³Îqq÷Ü®"n¡Ø´›äÓ_N}›xra%¼‰ôTׇ÷ÿPÀØõñN¤2¸áƃ½³[³¹?óþ ˆSû^èÁÓÍ SZèƒö"N½Ê
+ñl®û6¸n2>JÄ©•)ŸÁå:¾ :‹¿*âTU¶=ö‚€»ØGÝöûo÷¹Bk‰
+-5‘?ž¤ãuVrY'|òA¯
+á ³âCD×¾|žÍÕI‡û¿(âTên»x ÜŒÆãFÜ
+b6Þvñ¤ˆÓ7áx6×—ãPzU³œŽ³UͲ‹¸‰Äß-J<vûüò¸?ɺ^=F‡frÀ¯‹8•º îV6÷/>ß!â”ó_ÃÄKĉVõ;õÉ`ø«q1 G€Yc­MØÉÉÆСúì9Q|™ˆSM»sàQ.7bÁÍ>©{îjÁ~ºêÐ"²âM%«;%žJ]íþÕÀ­HÛóüÇ«B‹oÈ涃«:ï-⸶à“ZlîÙ6#™?©+âT]d˜»œÍõÎÊø[ŽØû©ŽÄØ\_µ™
+NmÌÀ殂*Ï,â¸|Ë]lîXØ«ø="N¥nj¦+à‘Vôcb*ñ6ø5§ï½/Å%ær¼¯ˆSYyË0p^]è`›Á©ÌÊ[†‹8M¼ÌØÍuü¼x! Çö¼õï`óX0g¥ø"N=«ÌþE<yÈ+lÊK‡ìòÔGƒ±Ì£×ÿ ¶3#—«ÑD‰¶3›ˆS©«3û;Qâ-ðDœ¾¸½kßb'>xQü]§fbùà3Ä“K™aSžl3ØÁ¾|ðo"Nã¸9Ç^ärÃ
+ÎI)þ’ˆSu‘ç•«à‘RýǸ–6òLM/â4íÓj>Øä$sx3áùÁd<ð»DœºFlær½‹­Ì[Dœúu׫ìàs ×I+¾G±˜ØfWkâѶ «ßéFÝÂ6»ÚK8bG›ÜÍæ ½É ¼±ˆS±ÙPRÏÓÚê¿ÒGÃýÝa\g1æ*7”Ü!â4©sê"ï7Rá“q=ŒC [çÔ_Žu™M%‹³¹íšØG½©ä­"NÍıKÙÜ0㸽îÀØ·$õ|Ö=?OD:Ä­§/úôÀOŠ85튎äs#ÈùvELj85™s¬bsKoÿPı*Ô'¹IÌ3£MqûaBTe…5©>ßI8îD.úç£lîOzqªmŒÞ›Àý&24ëüKăûeŒÞ[Dœ©Îµ°¹eZ¸ »síã"Ž  —°¹c èÇ2¾)⸅ü Íh#ýVó´•Ï¦qʺçæ¿Áæfp{âËDœŠÍ†R¿q¹úd];àçDœÚ¸"gK°o[ù¨xi §µÈ”ëó\Á¦ø)§Ú涩(uÉé¾ÐΉ Ûq±.3-½ˆSMûæLje(,Rh‡\wdlÛ
+øh§O¦Ôú¾àÑhõU]`çC©õDœ¿uÖ,6wçe¶Îš+âô½|g?ñh!bt·]†‹'âÔ»sÙÜ vy)qj"kdoÂæ‰à:*Å›Š8uÌî¿ý<ñdxœÿóâþw’Yß÷vöÿþÛ/‰8µï[2zàÑàú1:šxM§ªr_©)\®ªµàÞ}¥¦Š8ÍÛ´Ûo³¹aà~XÅÙYçs*6ÛŸ&É:„5ÞþûL§/îæKCÀ­(A™üÇ8A
+¢"}ñ¢ˆÓÓüá—«—nãzš¸"â4Éœ~0ÍYQh ð¹ß)NãJ8àñ—F3yüoW´(>NÄiîbʇèÆÿi öÒ¸ê’✔âuDœêù|-ÖÿÿÇÄëÐD1ð"NÅæ×ôŸ²¹¥º68?ñš#äã–ͺäžý7^_Ä©{Ðï:'zŠ;ÂÆ ýËÄƉ~×^p “OÜ‘›ÍU·Ì
+x¾ÿŸÞø›ëË6ðë"N_ÜÆN6wƒfBñ½Ž öYýlIâPzV¿¸ˆS‡|í¢“ŽáÀÚE§Eœ*«g_Ç6œ'¼s’ГØÙøìë3$+by¶7#r=Epž<[‹8=ýÊmKùÜÆZñ·DœÊüšqTUZɥЎ™¥W”°ßFñ"NO/|nñˆ­~ÀŠ`XøÜX§¾Í±:°¹¯bkâ±:I8›Ô|¶s¹
+a ºâ»%—¤_Cûi#mð’A)´øšn"NÅæó³#Øܲ9Pñ‘Ž+Ôs<—Ííà|œâ7K8žž÷Ûü¬³¨¨óîK/âÔ³:øuÈ#¬P¿ó?Úø5 Ç:ìçFƒG
+ݯ£7>Vĩлü0›ÛŽK̇]îþxjŽçŸes=qÁŸqA?X²3›ÇÒÖe,ÙUĩ븟†ÀêŽrùþ ÅÁ»xó;nþ‚Íõ» ¾YÄißŦ2)àѶ&êÇ×Ç+ÞL±ËkdÿûØÜSݪmê™Èæ ×Ãß^çȧqܱºõ¹ÜÔׄ?Üí2›ÛA0.ůŠ8ãÊTîË殉ûß(â1¼w~©óÒz•ÇêÞ!Êyªi ¶û˜xrz?¼[¨§÷ÛGñÏDœþöVm2±¹åz˜«lÕ&›ˆÓ ´g´2ɉÖðª2fÆÒNçõ¬ÓCÄ1å•e>9ù:³T‘q­4~M±i¤~®¹l®£ï[à EœVÄ2ÔºÁO|Ú1ê µ3ˆ8M°çkØ‚Ÿø †›â-ÿ öƒàhÕ¾™^ß÷x“OBû…úrÛ`çC‚§Dœú´=N·ár½Ë
++b=N·qjef÷¾Í¶€“³{? âÔ=xúõWØ\oŽÏqê˜Åz&ïHõlvø䃼Aݯ-âTU\õ—"L:Ùúf^.P|¹ˆÓP¨Öˆ8›[vm£ÖˆšŽnž¯Âåú’TŒã.<›„£?ÿÅëíÀ£mËÔÑ‘ÈÁ;Š8%¾øÀ"ÄÍHáïôïŒ`¢Uñ[Eœú´¯ÈËæ–ìxyu@~ÇŽ—oîes[UVØñòM §·¢Uðh‡÷ÕïÛCzE«n"N‰ïÕ?7—‰`9Oñ|"NÍÄ£·&Ã&Äuè–…VýNoT²žWÄ©Cþõâ\®¯öÅ)­¯oÜ*âˆåua;ŸÛ¶¬üxa·€›“RçË.l®>짭óeW§Wþ‡¬Ä­H™5¹8û¯xN§¡ÐŽ–}À#-&ú[;Ô´ŠqÌgÛ!àI)¾[Ä©ª,²½&q;ÒÒ†þc³…E¶×qŒLëøqÇ_Ú›öÑ¿S•%樧uüI±½Vi6W1AVk•>)â¸éã÷ØÜsPÏ+>FÄi$Õ|â
+b¸¥83•ÍUožŽÛ(>SÄi
+ÜaÛ7ĽHá2ô²JÂÁî>ÅwŠ8¤:^|ÍcVÿ_-âôÁölSÍUûŠ§÷lSYÄq9Ó³|îÓ¼E2½ âôÉÌÌmñ¹™Àø}fnWÄ©ÌÊXš_l‚k‰/ÿx“/v
+›«ÎFR;kNp¤J]Ñ“q#ÊÖý;Û *êÇŠ8 BÇí)nF¹fTÿÎqƒÕÿq{*H8ÎÇjŽÍ]Ç@Y¨u&§áÀ•¬YÙ<fà½+žSÀƒ÷~Ó¤K\®óÜ€ÿ%â4Ùøaõ؉·ƒ#äŠ.â´.Sé3 Bf”`Ú:VÂuQ]Túì!Ç2nŽßøÜN`ù>–㧿½X34R‰H‹‰ú1ž…pŠ×qjeR†WOrf*Ê·jÊâ–ƒï=e¸-á8È|õäf.×Ç?ÑD^=¹EÂéé/úŽxra%t¢U¯êظNZñŸE<¸}q+Z÷@%²c¨.²^&â4
+“J_/qšd~ïÙ›ˆÇ#pÓ¿s¸¿÷l&§Ú¦á/kÀ#mAû¡lŒaþò©„ãäB«Ûð dD«ÛqêQ?U/•Íõ´MÀïqÚí3ktM67u<ð:"NÅ桯æñ¹ãbù¡¯Š8M:½9¨*Ÿ[}¼9¨ºˆS±y¸¦}t Š(ŸL‡å€{"NOŸS°²€˜³šS°º„#ÚÆÓÜÅäqiÃo$âTæ+Ÿ?nF9r¢£z6øÞ+Ÿ¿,âôôšÙ
+q¹úd°]ñb"N_\É‚yÙ‰ˆ©x Ç×s_á'Þ–6®ç¾.âÔ1+ýÄx~âíà¢ÏÒOLp“·ï[À窌ƒ¿&áØéôÀ]Ùܶâ83òÀ=Eœª‹1moêS?&n;Ži[FÄé½—˜ß”ÍU‰¿½Äüæ"NŦ§yÙÜv‚Û¬*|š_ÄqCëú×ù<-lÂmë—ˆ8õ¬~ù.x0n%B›HKßkâäÂ/ßý%á(óÅëoâòä¢ø×"N½‹¶Ç÷7#]3ªg½JÅ‹8Úlµas#ˆÝ§xG§gf)n:‘²N_•yZÅ+ˆ85R£_œÅåúÊìòýâ§wá‰yìÄ«ñi/<±Pı"¶ª#›«íöQ¼³ˆÓ¼Í++óïËy¯¬|TÄé½ç?ô4q¡,|âÅÿ]p<ÿ¡"Nƒ‘R +1¹iz¶ß+^U±èn˜,J|ü DZÊì%·€ûSáÕ…½‡Ë.ß&âˆþHðHõc¬´ÀÂ×É!âôântûLÀ3àŸ‹x²Ì7¾tçwlîÕ…âgDœ&^z|ƒÍ=7†ø´½.ñdmÓ4ï1Ô6Éå¼Ðm–îšx´ˆ¬ø"Ž@£»OƒG[ÚP\µ¯&Âœî>+âTYU~k—뀓˜î«üÖH§§W¿¼—Ï-DEV|¿ˆS=ãÈcì¬K¸¸Zña"N ôÅ·ÙYg$lä/¾=V±E-Þk ;ëlõyÅÁÙO÷9}ï=*Ðò½åpß,¤¸§^;b¼T8#âTÏ/¨ˆV&yÄ,¼‘rýFÊß&âôÞs<´ŸÍc2+~HÄ©Ð6¸-;›ëã´øÍ"N=«¬o”¶ILñ„…¸…ŠWqJ|§¹\_Æeü/§¿}ÔG‡ØÜH Ò2ê£ïEœ:äY&ncs5øGÜÂ,wŠ8-ã¾Wçñä1«ðbó·¨QûþÞéE<Yl_vzƒ›Q.ŒÐ<á&¶&:‰8îÊì?•Ëõæú`Ÿ!â4~?ãÜÃN¼>tb§Š8UVo— È–gDÚ¨ã¹6¦>Þ.qBÄ©‰\¹µ/x´­‰–¾“8HüÊ­Dœ&
+um‹šå_ˆ~]¡®oˆ8õmržoÉæ–‰2¯x§ŽYó-¨.â»ÄÉë*Lð="Nngd7#-"[z!Õ¡×4_雸\"c/u]Ä)ñyz?!I<&™óô~RÄ©_W¼}O6WŸ«…{ÄÚ÷qúÛKlŸÄO¼m!~]‰íS%AÔ‡ßö&ûÅéõ|…ˆÓ”×ò2øÜÀýqŠoñ>™ô¢O†z•™ëÐrž¥R£ À¢–¹N§ÞÅ“ù»ƒÿÓÅÿ{ÀÍÒW;wm<™¿—„ãðìeþÿÇÄ«LƱÊ:WárS3Á+H8:äÙËô%žÔº¾p+Òq?ئƒñr+ù<¸~Nñ·DÜDâ{ŠO|êbÚ(å‡rŒÐHùA-ê]¤~•ˆñ¹k™·DÜBâß%ž†…?­ éÂÿ1.®O­Öµ—ë“ÿX›¨Öµ”ˆSÇì¾Ïop³û>7Eœ:f6Íggj&0ŠÌ°é G¿îó_;ò_œª.Lð."n£ØÜ.*6TUî:¿–xrY'ôƒU¿Ó½_/âôÅUu“G‰†éFÂ?½°b¡ÐVugI8v¼z¦2x¤Áˆ~LÂB¤ÅË‹8¤2<RÍ]Ë
+¤´Lá?]UÔ1ðûD<H|UQâ都1±)¸åÅéǸ.¦}RK¿ü›®lzù§tË=ØÜJ íÛrO& ÇmV7&6e½¸eÅðâ¬HAõïlÇÃÔlj)·ñ¹³ŠWqêýT£ ›fp­ðO5*ˆ8Õu †¤°ùß"B7r¯ˆ[xq•D/Ž¦yß.þq;Ò&1õ;ò…Þ{¾—k²yŠ˜â 7øå¢ÄÓH*{½6àV”¥ ý˜˜ƒ~]jîñ¿³¹¥wúƒŸ•pijÚv ›ÛB(^IÄ]d]KQÖÑwwÁÄ#Ê·þçÆì€?*âÔ!ÿå‹â|n!‚œâ¥Dœ&™¿[GøV¾[_ÄñÅ¥vcs=¡^åºÄœÃ-+¸–èJ¾ßDÜEâ–$áq ®ºÄáSúwžl€?0tœˆSßæ›O6q¹êYÅ°‹û›£ß²ŸnÛA]÷ÍÑÝ"NÕE“ ؉×{0 ð§aಠى×W¸yà‹DœºFmÏ×â'^¯Êß)âÔ«ÜpOvâUM‹î)&â
+íç¢BK<wÄ]11lë‚ÿUÙ¸àsDœžþÖÿ‚›Q6ÄêÇè -?+â´ó¡Çñãÿ3Õ©yÂÂf`Åk‹8uæ(ÌM¼7‰ï}îb"N£È¥…ßâgëçç?ð”7çNá'^õçMði"NMdæ\G‰ÇI¥Ô<CžäsÛÆvž!Oˆ8­Ã]Pÿ·QVo â.²î°(ë¨Ðö›sŒ¸¢¥²Šé«¬±1²ßœSŽAh‡‹o‚G€Çô¥Æ0Ûáâ;"Në2Eãù‰{f”0)úw†šàyǬR”¬A<nF9>¯§çh(tK |œÎS|ˆc›VÉj’Ä£ØL¹
+<ÒµƒþcÒFÓF~(â”øνRÜÃÑÂν‰8UÔ%?Éæz«”þ‹ˆS¡í^<ñÄ?mû‡&R_¤í ºè^ü§—«V p‚=lWÿÎ0ƒAh®Z-Eœ"Ê1—Íõ9ê€/qšŸÏzøi6×·¬âž‘Ãω8u̦?Ö‘ÍueIï}È°’îâ øaEDÜAâÛŠO½‹m“û.~”锞†·â¸}~DÛI"N +MÞþ ÜŒúOÿÎrâ8jtèôÛ\n¸Ž‹ƒ‡N/p[ÔvÄò ob·#V@Ä©‘Ê{¶°€#b¤âÅDÜÄ‹;#zqÔ¯›·u)q3ÒQ£äï ¬MÌÛº\Ä铱íõLîß[…ùyÛþBÄéé¿ÖëÈå:Ö
+m±âÛùÜvp¨³Xñ­"$¾­ ñAhß…æEp9/´[¨~æ_`Ÿle2dÝÏæV0õ¡ø·ø?E‰§€“O¥€[Q.öÕ±`#ôÅS–ˆÓ‹‹¿s7qÂÓ ïùÁ.«3åLÃ[Ø\‡ú°ÁóH8vïÇßi(J<U3oünFä:
+ypËÉo™øÜ@(oÅoñR”xêœl2~&®ÆäŽzœ6ᇻ´0é´É8#âô½ß~t/›ëPŸ&ø>§1ì³"¸©yx#å_üg¼ªˆÓ7lÆ66×'©Mð-"Ne¾g1š·1}÷I„¬óÿ'0SÚ³Øc"N¥îHóìàVD®'È1õq¤yf G§tWKZHUƒ»˜â¡Ë:úw6n»PüO§NilÛ<.÷ƒ‰›à¯‹8Õ´MËVaó„caYçÀàÜ|nãæ>ÅsŠx‰/+J<åü¥«´QJO9%»ù!\ÿÎ
+‚ë^­$âôÉ\ìTÜ´’ñɸ›àü.§ònï`,³4ï˜é£FqlI-ÿes6Ù.Îþ—ÿò^ G+Ó¨{k~â­ö7êÞ^Ä]dÝbQÖÑÓ D ëù“ðçé‹Èг^.›«®¶ë /—QÂ1Ù8`àqIâqù«5ƒÁ͈\¯#ÊÊž2w°¹úâÌ€×qʺékßç'ÞÂ]N_»ZÄé{oL#6wÒ°¿7¦‰ˆ/n€èÅÑ®r^!÷;'áÜo¢0ÁþÔW¸\µðÁ…POýð§ˆSmo÷;ñž… rŠ/qª.ÆþY›Íuò ðú"ŽÚ¦Ø]ì¬Ó£Èxc Ç@lúôÌœ—™>=«ˆÓ÷~õÐ6×Ã|›ˆS [ôRCI¡Åy™¢—‰8õmJ?v?Ÿ¸ÅLñÖ"˜(ª.¨^Ôe$ñ„aDj  L¤ø‹"NŦËêŽ%ì.«ßqÊù³Ž0¹¾ ¡¼?&âTÓæ9Ša`†w‰õïL¤Êst˜ˆSUÙåÕ\®—ï1õÑåÕ;Dœž^kmup^hõ 5Soí}HÀq Uñ¶Ží:µÖV%žšÈÄéd Q}¸.R÷€B†Q×èÑVuÙ<nÄPÓ>Úª¦ˆS]áûs‚Ä›ˆ[XáûK¢¿ÝDÖÍqªmÎœîwÌB§>,'/ˆ²rnäK"Neþ¥Õ´uÁrüê"t
+^œ…“ ßüà·£,aû¿³ C¡î¯ýÉæþ€ÿ.à¸S©ñµŒC¹\ÏÒß®øËÜJœºµ$Ÿ»8 ¬xÇIdõâLÑ‹£ï}YŽãÄ#-ë$ãÚ0»,ÇŽEäì7?eê#ù;3¥{Æs¹a«DÆÁ_qêßÒ7›'‚%-ųI8î Í~󢬣ªò¥>¹À£lA÷¹e«^ã¿ØÜs‚)n¯ñE Çü|Ñf}Ø\·Åqð"NOOi×’Ÿø`Ÿ•â­EœzÏ}¼‚ÿâôáð÷DÜE±É!)6h"s•îL<ÒxÿwºÐß?ò:›»n!Wüªˆ;H|{QâÑHå}“xr|øÓû*i(¤ø|§‹B®^_ÊçÂÛ*þžˆSÖ­~k ›ÇÝà´Î7dårSÿ_<“ˆ{HüW¢ÄÓ÷þêIÝ£Öׯ9¦cù!{CŸ®ª*D„~õd=§vÂX”ùäÂJxâý»¬¨}Wü¢„ã^à¡Þ÷;¥! +>OXV…†x_Äi7âè.÷³Î'â4Ùx¥Ï1âÉE¥ð¹Ž²âb×ÇMw.är}6ŽÏßtç<Qm“£+›'̽8ÅýÞÄØÑ“u¶…Ë°ï'âÔ=¸ðB'>·±"¦øÃ"n¢Øü(*6TÓþ9oñäbbÈÆ ý;Ãs± –š¯B:>n»HÍWþšˆSmóÀ‹Í6BF(qj&¾Ý^‡ËMÃÂ`Dñz"Žy›y_‹^ãîºü4x” ±þcœ´Ã>w]~NÄ©~ÿm*u~qôç$þ›þìV…Þ{§ˆSu1hMe÷À«‹8õë®VH€›Š;¡¬~Œƒ ¡¿KÄ©Øäÿ`—«â–Å'‹8 þ|q=›³C‹Ž^gÛï3ÔÙÇå:.¯ÏPgˆSÇ,×ó-ù‰bu*ÞVÄ©•9|ù6×k‘&xk§êâà©¢GUåžš5ò7cDùdL½Ÿ5Ÿq*6ÖÁâ+„[ªžÇQbÅ_qôm²7·Œäîì0nÚú
+Å 5øGM;-OY§Fja*².f:É#Âa\7åØ»0µ³ˆÓ'S¯ÑÃl®×RiüÞ}ð-\nè_zà¹Eœ
+íÐÍ=Ø\÷ÞGÄ©Øïõ›'‚àùŠŸqzúÐñÃØܳƒ¨ÈCÇ?%â.ŠM'Q±¡¿½X±ÝÄ=#ÚÔ‡÷÷ ÊÅŠíq …¾ßÊäúpŽÓ*¾]Ä©Wyùy B=ý¯"TVžá.ªÊËÏÏqM¼tWC>w9åHí3\nê¬÷ÀqšŸ¿vs#ÉßNcXÅqšæíõQNAâQÓ*žGÄ-¼¸ú¢~w p+êÓuð|¬ŒÜ=ˆÏ]Äîk|-ss6·]\S¢ÿ€(ñÿ°(ñ´u¡Ëâ>ln¸ L}tYÜ_©Цœy´››6ö*~§ˆc†<sÉ‹Ãw˹Ó/.XHm9w¶ˆÓêÀ¥†±¹ã"uê¿Èæ^îRñ‘"N}ÚG
+r‘F/"âÔL,íÓŸuú
+¸òÍäÞ!pûR#8×&¿ÅažÖš°‹ÊE—TÇMÖ„=,í»å@4™kŠ¹.c9`gq(ï?U¼¼-h¤ýa Ǭ›ñ´[8Ë{Ã*X\P¼a~‡1XÆÞEê,½ÊÞ7×R¹±‹óó½on`qh";E5"÷ÀÛŸöq—"á´O§¨fÇ;VT‰Ì½¡È‡¸¼äsäŠSNo0²„¼–ñ™øyI™;tó̇ç‹6ѹ¬ùøV‡ŽY~êûŒßŽQ‚—±8TÔ݃ï£sM÷ñáŽqé‘*™kº¹Å,=ÒÁâf¶y€“m0×ÛKmËyí/.¸$ÑmÇWWÿîE*—U¯)¼™Ãqãƒ{M6™ C!÷šy,O—1–Ìu3\ðñ,OßýD ýÕSäÈãY\Áló2+Û@#eIýpï2®SnïvùEÇÞEÏäþmtRÚ®`SÇ°8ÌÛå¾Eå²d&^ðwXÞüYuäÄ;}w. ™ÕÀâЧ}ð“27ö|èÈ?aq·æOEî]Dn¿{à–EóŒS­ùY,Ë#mt.~€y‡ã«·
+ž%sÕ |« ›Ãñ²ËNS¿oãjÛv»KZª÷ø&,2¦^eq(2ö鯑¹n¾ŽÅ¡È”÷D檢⸼ŸÎâçoÌë†Ü¿ /ªq®±™çoÌ‹dqxú/¶_È\M,†awíÌâЧ œ/“ùo®) œ¯³8Ä]œ­Æà:î to\FóŠ†ó´î/±8…Ö̦rã´ ŒdîR“ÃáX]䮼FN¼&ÆrxZæÊV‡ò¾:ÜNæb0‚«Ã£Y\Ål3”•m ¢®³f
+å]?‡ÎusòÁSŸÃâø7‡]%¿:·æ€7/x ‡ã›?2‚œx£#¡#Íâ4RsÝFæÆýo
+òî,õüõ”7È\–~=e;‹CM»¨ì ýÕÉxæƒà‡9gNvÆï¥Xó¾HÁ?dqh¤ö ?Ju*ÞÔ)øqÇß~:é<=Û˜«‚7s8>ýê)ú›wèx¶àû9wa×M¦'ÞÜN+ø4‡"ôz[X¦·Ùõ“;|õ|ÐëÍ,¯n]m/:7NïCÞ‡Åa¾®hFƒKxçBÑŒY&Üê_Z@æÆ1'0ñ2ôòkd®éx›à+X~û®h‰þÛ\Ò\aqøp5³†“¹SÓðY²¸Œ.‡õá Ž^³¹ìOP¨÷ï$‡dò"‡7_î<BåbçÄàrg-‹cp`T rÅßÄ«f˜–àCY#™sÇй‚‹ ‚'±84R=^ÙKæ²ì2ïSÏ“¹¤;p7nŒZÇáx×Æ•#è‰WU(q‚fq€—VØÉ\×]¸”YZÍâ0í2ô¯ôÄ+:Öu!CSXÜÌ6ÿbeÜÔÙypEöç¨OãïÄX2ùó,Ž³…wœdqþßQÏâÐÆ4ô%sE1›È ¾it®›çUõ}’Å!ÛX³É\ä9¬.¬Ùc9ª ñê"Y¯
+ì@ÏBàªäOˆšwÎËwÖ@O.‡ãi.|LäÆ n涋>eq¨.Â&ËŒÄ;ñÃ…MÖ9ëù°Œ+ ŽÇÛ
+~Å¡™°¬ÀÚF•ýYÆm8ñV#ËŠl‡iŸð7ߣrïñ82òÝ,¿86ˆ‘xŒöñü¤aýv y ‡ãœ•gY_òowkN<°Â³l
+ÇýÝ+—άëÃ1¶ð‹cVu=ê®I·#÷kùÞà¢!ǠЮI=Yª‹¸ÎÉ\÷]z×9”Å¡k4©ø&™{÷ë´ñ£¿ž§sÑ5R‘Ÿcq¨¬î¯}þæÍå{ÁËX*«ÔOóÈ\ôê°}OýôEÇÔín§s ‡‚ïdqøpÖ¯bäys’¹Ãú5,5mìRúÓMÃ)¯Ø¥ëXÜEæ«È@®³V—×ü::@ö^rŠ‡¨ þ‹Ãoÿ!¤šÌ¾C•ãŽ sã 8˜h;@ç*^ì+xG×0ñQ¬ÄÛ·õ«£¿:Ù¼#ÕÖ¯‘Å¡žïQ¹–ÌÅ\‹ìQ¹Å¡²ñ6=ש
+Þf5"â]‡7_7r™k
+n-|ƒãÆÆÄ&ûëd.*KM¼˜Ãq‚=<`.™ëš‚‹ áϱ8Ôó :ßKO¼®âºÌ‚α,ñ6ÅMÿæ”wìœ7Ñ ¬Á¡‘ªÝx'£Èàî‚÷aq +êìŠfnÌÁ9+]ÖüêË ²§±8..D>Jæ’f&þfd
+‹Cž?ùíTnÜ™ˆ“WþL~ºb,N ÆâЯ»¨G‘ïôsrQïÏâPd¦4xoÞ#è) q8î:ùmwևð̲³ÀÞÅÄö'Zuc²¥º”5°8|8Ûøtnþ|‹ã³“¹®(x YþÆT‡f¢Ùó#ë0ã ½öƒËx®Qèµ<‡Äg† §sÕ\ Ì I`q¨¬²N”‘¹¦cЈàåŽá:ÍžïY²MÌȽKØímd6cL°»W2¸ ¯Vš‡¹[—p-RiÆâ0’jN~’Ì]šûuÍÉ“XZ™^v'qÊK$^ÆÃ÷§N°·qøî–éñ˜xÅŸmÔÆÔ7žn™®²8d›àŒÉdn\±¢ ŸÎâ0Š¼mõwt®«Ð«ôôèWEç
+Î#øA‡6n–¶ŒÌIfòW9Ÿ¾¾ª˜Ìª¹û~}Õ6Wð€šÖÃd®™q‚W³8 J,!ô<ï;m£ÄbãpìYUÕž g ï—ü‹»±È4±Š <½0 ôœ’?GB'*œ¯+ +apó|ZëRœpsúu¤³÷ï$<Zðý,¿ÝÚ˜MåF3q•Öƹ,]£Øó[ɉW$ó΅دKÉOw·ÝßÆßeq¿…“x(q£[w_"sã{7ò[Ž£‰4wWzâ5w¨¥¹»±8Ô´yGƹjÆÓ
+>î÷ð–í‡ܼ¶ e{çéØLĤ‘‹ŒèB¹ÍàÀ´ù,³ 7XÕ…‚¼‹Ã@¬ËãŸÑ_j'l&s1ŠÄÅ{ÂÇÕÿÙ‹î£WF„òá,•ÕbûÆw—0¢u±=ƒÅÝøájYJܨµ8wáò3TÉ)ª*×&F­]ÌâÐDÖ'(t.;0p¢>Agq8{ÿFÖlä²?—&'Ë.s¦4k!‹C=?xÚ_¨\ Äpý]ð ,ßýäŒß®»qx)ã+úÓÍf?ÁâLüLVâáÍoNÆÑ„Kñ—kª¹[gsò;,•Õ”Ÿg“¹ñ3M>ÃqÚçð¹kdîPqýݺª€ÎEí@¾„ÅuLüVâáÃY`à„[öçÈãïtñ(“ïdqøp)¶¹C‘ñzšKÏ!sMÃÄ ^ÍâP`s†‘¹±Ùï =؃Åa(4‡Ê%·îÂå¼ø ù,n~¸õ¬•UÈxÈóÞ]®~L¸µÅ|à^àñ,Ž±w}Cæ’¦`ð€í®z‡yDžƒÊÅËS°¢ŽÈÄâðÛŽ¬ '^Ö\0 Óm¹‹üt§Œq‚k,EffÉ\úoW̳}f–Ìgq'¾ºrÖ«ƒ<ß¡úÀe¿Ûô>Fuc®ëPÃâëºY—’¹oUHðå,]âðÁÆV#!®¦äÝaü[ÞñÿqQÏâuøàÊÿá?9 FÚ^¦'^5¯ÒNØa§¿y]Ū2aG‹C¶Ih\ÆH<^C&ø«,í{Ò¹d:×4Yüo,vùýu¬\çDÞÈâðÛ÷ZHæ./<—Å¡žÿòt==ñÆéÿÈ¿]1odŽÜ´Ÿ‘xóFæÈM‡XÜ…¶€U`!Ï'>r¹÷hßöŽþ3þÌí; &ñ‘‡I§ïJvÒ¹êÂC¾+ÙÍâðÝ-™ó+þklü£if3aÉ\ÀáØ1³éGÉ\ÖÍ5›~œÃñÃŧ¿Hæ’ª`‰‹O‰Å¡•iÔ¿"sc_#Öqi ™ëª¹|i‹Ã‡³/^ÇH¼†—ßÙodqh&Æeî¡'Þk4.³‚Å!ñiÉEô<oN´
+þ‡ã”W}z&ýÕ)ª?Ãâ0[˜}ê<½Ä™Ûmofq˜ê<ýÔFâqï€à±¸ ìINÅHæ>Ø«T$¿&™§˜çÏ ¾’Åõ‰[¦IS¤.Æÿ{{ÇŽË°Rénã_úvì)…/º½·õꆋúgþsצ¨»ïþÇÈ^r–KNãzÞê+Eo¹w‹=¿ÿÔììƒâãçÌ™—•—ž?iffV|ú´4ãFK'þƒd
+˜?2¿ÅØ©S@‡ÜÀÀ€¨ªÏ¿V^±L[PSýhQÝé3Jï}Dz<UØ%¯ôžÇê²^8ÑtmêˆÃ=ß?½àÐÌoº ¹¶'ñzMDÞãA9—Z¬î˜½ “ZGæu÷œØtÅ3¯òòܼ'.L Þ:¶ÿ…”3ý=ìDØãúTÅ:þöc¡‰êi÷;LÚº´ÏÏ99‹>*>³·¼C×POôÓ!_÷¹î—ooûñè‡vÇþ©iZøÌÊ1ÓOŒk;_S±°pßÑMeSÌ:{nïŠÃ/Ox?sI™uT`Ú#gzOyѵcç'?«œ¼¹¥.beij¿ö‹ëû²Õ’¶]î:£vés±œ­±”~1þ½ZÛ†mzYÞ÷Dý©äÂýÅéçÎôú/H
+endstream
+endobj
+27 0 obj
+<<
+/Filter [/FlateDecode]
+/DL 788
+/Length 32 0 R
+>>
+stream
+xœ3hb0hbüÁÄÈhÀËÆ©ÕæÑö—‘‘••Á ÖPÂ@ .ÄÉ(ÆYéPœ­—šjÈmÀÉÆÊÂ&Ìäêj¨d 
+ðÔ0 ³{•–é{‹óšXšXšZF¸††FÆP.ÐIÊL,Ö}! â¼Æ@)CKc3cƒ(. Q²¢,Ì\Œ¬ E®³g?*270*42´0BSÄ
+endstream
+endobj
+28 0 obj
+<<
+/Filter [/FlateDecode]
+/DL 1258
+/Length 33 0 R
+>>
+stream
+xœ3hbyfÐÄ|n3#‹uŸ÷^6N­6¶ï¼ŒŒ¬¬ ±†bp!NF1΂ìL‡âl½ÔTCnN6æP6a&WWC%‡KXÒ1X!8µ¨$3-³¤85µ(37³8;µ8»´ØPÀ€¤†Y˜Ý«´´H7ØÛ@Nœ×ÀÐÀÂØÀÐÄHD‰óšX™A¹´¶¾‰Q ÙÃŒ¬ ÌMŒü @q.¦&FF†ÆB3;cök z…ëÊÜNŸ—Ü”`è6½íË ·%‡R]Ï_v¨y¥´B ÂøLÇÆË^ß’Ä«ã}¹ô.œïV~çÏä·û5ß©½É/dzÊôÚ>øÿ*åéôö3ëy¸8¤‚—+>´ð¾Ö,½v}Ê¡Ÿ2U=i¾iò\ìv˳§NnÝ)µaç‘ß¼‚ß¾^û)}\G{»Dà¿ÕßVx¬Ï±ö×ÿ㢻œZø‡@YãiÿßGÚÞò½(jrü•½˜GõD™g~Û¬v7O={ãÿ!çôÛÛ'?PjÒÛ÷5C£yçAëÌj…[~srî:Û_•³Séz7÷m™«QjѼ^=M¸0ÿŸé}{&fFÆÅMŒk€!²Â€z²ÂŒŒÿYX ˜PP $¤ÀÒÄÈ äp1+—6# ã9y`p4~3h¼ÀÆaeegb2h<,×x€!˜!ŠdC C&Cg3$a P<Ÿ!H–1<aÈaÈŠEA2¥ )@qG ~] úb ;Å„°‰ ‘L†\°Šl D–‚U'ÍKÊèõyã´?h ÈuÙ@Vf‚m‡˜—
+-6P„ûˆQL4£¤¤ÀJ_¿¼¼\œ,õ“ Šõ ´Aá"Ï¢b
+endstream
+endobj
+29 0 obj
+<<
+/Filter [/FlateDecode]
+/DL 998
+/Length 34 0 R
+>>
+stream
+xœ3hb~dÐÄtj3#‹ë<õU¼lœZmmßyYY b % ÄàBœŒbœÙ™ÅÙz©©†ÜœlÌ¡,lÂL®®†J
+ —°¤c°BpjQIfZfIqjjQfnfqvjqvi±¡€H ³0»Wii‘n°·œ8¯¹¡©¡‘©‰Y”8¯¡™…‘™¡‰‘±a”Aé–(ȃÔp K +(IMÍ+-NM11‚¸ƒÛÕÓè # +š•}ÏÈÊÀÜÄÈÏ
+¬ôõËËËõÀ)H?¹(§X? ˜@,= Ǭ2 0Ñ5ˆ°¬ªr_ü¤s½Ôy.‡åöùï_Öî3)àcc‘aÿ2gÿÕœÍ[æ)ÉËOñŽ¨êEK¾Ì x[$Xýãúä…o8Ø-l¸Ü•]W|òx¡©£³5fBy[ìýîÜøMá2Që­Ú4&t»ß;$[ò¥)In½ú•ï]
+œ£v™DNŒ™ê|p½‹Îɵ~wU”w¼fÔ7cûföô¶ãNF-“ð@íú“+Þ¼Óo:£%gù}‚áùî—Vü‹ÿ[âi/·vÇäOçöíÚ[6ùkÓÆÓ‡‹ÙÍ:·ïìlÓ–¶)c¸àæ¸+?mý¬mW4,òÏoÍ7^íþ#~õ"³ÜWÏwÇØÝÙð4Q¢põë+ œoŸš­Õž¼FÖiïŠckžåÿx𶾵êñ’3;¹•Ø„b¬§ï½<9t+
+endstream
+endobj
+30 0 obj
+0
+endobj
+31 0 obj
+312198
+endobj
+32 0 obj
+606
+endobj
+33 0 obj
+1013
+endobj
+34 0 obj
+909
+endobj
+xref
+0 2
+0000000000 65535 f
+0000075644 00000 n
+11 1
+0000084581 00000 n
+22 13
+0000076006 00000 n
+0000076160 00000 n
+0000076238 00000 n
+0000084819 00000 n
+0000084907 00000 n
+0000397197 00000 n
+0000397891 00000 n
+0000398993 00000 n
+0000399990 00000 n
+0000400008 00000 n
+0000400031 00000 n
+0000400051 00000 n
+0000400072 00000 n
+trailer
+<<
+/Size 35
+/Root 1 0 R
+/Info 7 0 R
+/ID [<63038667617ACEE5E29014FD3093D783> <63038667617ACEE5E29014FD3093D783>]
+/Prev 75328
+>>
+startxref
+400092
+%%EOF
+1 0 obj
+<<
+/Metadata 2 0 R
+/Outlines 3 0 R
+/OutputIntents [4 0 R]
+/PageLabels 5 0 R
+/Pages 6 0 R
+/Type /Catalog
+/Extensions <<
+/ESIC <<
+/BaseVersion /1.7
+/ExtensionLevel 2
+>>
+/LTUd <<
+/BaseVersion /1.7
+/ExtensionLevel 1
+>>
+/ADBE <<
+/BaseVersion /1.7
+/ExtensionLevel 5
+>>
+>>
+/AcroForm <<
+/Fields [18 0 R 22 0 R 35 0 R]
+/SigFlags 3
+>>
+/DSS 23 0 R
+/Version /1.7
+>>
+endobj
+35 0 obj
+<<
+/FT /Sig
+/F 132
+/T (padesDocumentTimeStamp_2)
+/Type /Annot
+/Subtype /Widget
+/V 36 0 R
+/P 11 0 R
+/Rect [0 0 0 0]
+/AP <<
+/N 37 0 R
+>>
+>>
+endobj
+36 0 obj
+<<
+/Type /DocTimeStamp
+/Filter /Adobe.PPKLite
+/SubFilter /ETSI.RFC3161
+/Contents <308006092A864886F70D010702A08030820DCD020103310F300D060960864801650304020105003081DE060B2A864886F70D0109100104A081CE0481CB3081C8020101060B2B0601040182AC180103013031300D060960864801650304020105000420313A5072F0F67C45A9B91780D1E1F424996CF7C1A2DE65DB8BB65959A004CB14020310A33B181332303134313131323133303134372E3432375A3004800200C8020860482CEA3941B545A059A4573055310B3009060355040613024C543110300E0603550407130756696C6E69757331163014060355040A130D42616C547374616D7020554142311C301A0603550403131342616C547374616D7020515453412054535532A0820A7C308204B73082039FA003020102020A160E4D35000000000387300D06092A864886F70D0101050500307F310B3009060355040613024C54312B3029060355040A1322536B6169746D656E696E696F20736572746966696B6176696D6F2063656E747261733120301E060355040B131743657274696669636174696F6E20417574686F726974793121301F06035504031318535343205175616C696669656420436C6173732033204341301E170D3132303531353131333435345A170D3232303531353131333435345A3055310B3009060355040613024C543110300E0603550407130756696C6E69757331163014060355040A130D42616C547374616D7020554142311C301A0603550403131342616C547374616D702051545341205453553230820122300D06092A864886F70D01010105000382010F003082010A0282010100821C4FA052C55A990B6B62E5D59054B5EB08B7324C6B6C29048070A931DD58C90E33D92FDED48AD39C697C230A854ED7B7D9303F3A835E9220E4F4EE0D62D78D675B8E4A75E2B7EF513C9B47F21F38E7BCCD2428CC88E8116DC42330E2464B20518C68D850881EA2EB46EDE52B3896AF2128397F07EAF1A27B5F1AE9551557EF10AA6F2C56E5C265A4B443A470388D75BD9827EB4F6214AB522D015954F3F4325BAAFDCB0F7F39407A57AC1F0C2D46C4CBA568ED1A5B997B590D064CBE24FD6C55C1DB6D8B874E49425C61A7DA30996F183F4D8F2F0279D2B8875FF2E7F1E47B4E49DCD6DDC886AA7DCCCF04D480674D6520ED7190E879E1B64A046C559DAA0D0203010001A382015D30820159301D0603551D0E0416041451F4B16D4E550EDF93975C83236513707DF6AF3F301F0603551D2304183016801408C941FFE79B5633DAF0D7B361B4485C15A31B5A30370603551D1F0430302E302CA02AA0288626687474703A2F2F6E63726C2E7373632E6C742F636C617373336E71632F636163726C2E63726C306C06082B060105050701010460305E303606082B06010505073002862A687474703A2F2F7777772E7373632E6C742F6361636572742F7373635F636C617373336E71632E637274302406082B060105050730018618687474703A2F2F6F6373702D336E71632E7373632E6C742F30090603551D1304023000300E0603551D0F0101FF04040302064030160603551D250101FF040C300A06082B06010505070308303D0603551D20043630343032060B2B0601040181AF650102003023302106082B060105050702011615687474703A2F2F7777772E7373632E6C742F637073300D06092A864886F70D010105050003820101003ABB17DBAAED138816BD95DEAF9EA9555D0F6A93678DFBC092B389A621A34E7D87556A83908CA18E838AEE89B28B04918A08B15DFD2DA1FE3D4FDA9EFCAC3220F4B5A562591FA9E4ED594D45E3CA4EC28F5EAD80B7971A8B109491107B14B4588C8C4C2E05FFD66FD14F791F000B9DAAC92E1D8ABD6B0645C0D7B0798ADC15726ECF3BFC202056E375D1DE74C4271216D74586A7BDA7266C6AA6679CD29773D791B9FF10AE92464C8DFC525740FAFDA4E40D2D067AC93855EFBADC4615D495FB95A87C660659FEC75185C9EF599BAC277BB9D3AF5922D46B8980C84949FD8A04B377D953FD3478176E509C8BC012C003BA00D11F27E20755DC9CA7AE18211BDA308205BD308203A5A00302010202105891669CC008CA254070B327FF9C069E300D06092A864886F70D01010505003074310B3009060355040613024C54312B3029060355040A1322536B6169746D656E696E696F20736572746966696B6176696D6F2063656E747261733120301E060355040B131743657274696669636174696F6E20417574686F72697479311630140603550403130D53534320526F6F742043412041301E170D3132303330333131303031375A170D3236313032353132303530305A307F310B3009060355040613024C54312B3029060355040A1322536B6169746D656E696E696F20736572746966696B6176696D6F2063656E747261733120301E060355040B131743657274696669636174696F6E20417574686F726974793121301F06035504031318535343205175616C696669656420436C617373203320434130820122300D06092A864886F70D01010105000382010F003082010A02820101009DF52784E64FA593EDECD8AD94C3DDB503E58A6E709468A6185A54615E3153F487953057DB98B3735EF9E16E6E4E5E63E76005CBCAD78D82B9D184C4C8DB15AA7C8A5FC893C3C5B0B5B90CA2EC7286E520AB80478DAEF5381846FF6699F5D9404C2C514942DDA8C2B1BAA4555DB3765F38929257D8BDA92B2F788F6F062787B34A23878FF1B665F4D402EDFC93FB08947FCC8389BD289630B61CE0FF6A49E20CD6486B6A3865FCFC534E013DE7ECCDDDB656594AD6883CEE2273248CA46445EA61F9933F69792752AFFD72C189CF424D32D6766351E79A1A768CEC893C7B3D86F21DE481156E519C8B2C426D4D9C0C3791F02A93483D3CACC3E611C6B806E7D30203010001A382013E3082013A306406082B0601050507010104583056303306082B060105050730028627687474703A2F2F7777772E7373632E6C742F6361636572742F7373635F726F6F745F612E637274301F06082B060105050730018613687474703A2F2F6F637370322E7373632E6C74301F0603551D23041830168014CCBFDEA79077626A1D78692E0A389B77515303F0300C0603551D13040530030101FF303D0603551D20043630343032060B2B0601040181AF650102003023302106082B060105050702011615687474703A2F2F7777772E7373632E6C742F63707330350603551D1F042E302C302AA028A0268624687474703A2F2F7777772E7373632E6C742F63726C2F7373635F726F6F745F612E63726C300E0603551D0F0101FF040403020186301D0603551D0E0416041408C941FFE79B5633DAF0D7B361B4485C15A31B5A300D06092A864886F70D010105050003820201005C035DE76F88FF65493FE6221771C14922301FFBAD77F09D77C8155BABF3FC26CDEBEA2724D4F7A3A6630DA3903426CC201D23FF328FC40A7A4A7463CC72B2526EE97D4C361826526623680DC3B7940F545AF923C63DBD3194792986AD78527D609C7CDD03A5657DEA1D4F1E96CB5DD021D5C9782E29286AC56B5B10EC419B90EC5C429173264D8CF1433CB500753EDF3AB93668016F759DC2A2A1471F491E96FCC61482A8ADCAFD11AC895101627C9585362E2B98ADE4C1E015203AEA03C3777618CDD569E4A66CC415A489D9CFC4628BB24980C9F0318EB98776CACA9D9C0AE8BF9288B1A04F379DBCA2BE015C71706F16B5E90531CE335165DEF3B5369773727601E409AC35BD20573591C0C4484DFFAE39A28DA836433206511BBD4C35DA54182DAE632E57C47D13EF075AA10937EF3FDC5B4AF81FEB2001ACB344E71DF7C00AFC79322EDFBF08B888A2533CDF0C07E50D3F90187DA3F49F17032B1C552C8056073931D189B1D4904EE6373337734511A6F7E6A16965D208EB7E04BD945D10D4D5C1D8949760CF5911ECECDF7647F809BDE7C31C73607FF386D506B1D6C0A6E8258F4D69AAE37C93810BA095869095D52FDD3E52593E4A37EF067C42A51CAC7E781BA6000FC52570017433CF6B1008E1CB310F3A1EE078D2111107178FA337DC884CD15B90EB558A4FBBF6A68B6D2954C2F3905A380112D755D78AE6E829318202543082025002010130818D307F310B3009060355040613024C54312B3029060355040A1322536B6169746D656E696E696F20736572746966696B6176696D6F2063656E747261733120301E060355040B131743657274696669636174696F6E20417574686F726974793121301F06035504031318535343205175616C696669656420436C6173732033204341020A160E4D35000000000387300D06096086480165030402010500A08198301A06092A864886F70D010903310D060B2A864886F70D0109100104301C06092A864886F70D010905310F170D3134313131323133303134375A302B060B2A864886F70D010910020C311C301A30183016041420A352E2CE2E73070BB3CF9DDE8A4EFEF0F0A35B302F06092A864886F70D0109043122042020E05DC47F569C22254622500EA640A2270476D484D5FFD44646D04BCA4EFC94300D06092A864886F70D0101010500048201000D6C4FBC93BDF02A2A93BB32D2B5D0A7F35E9FAC9E21249F6279020EEE1C37E623D0FCDAD3E4FA209B0B606BDBA2457EB475AE05262C907B19A41B69C99568E0C766E1018BD7761BFEC5852E267DA68CC110779A959073958FDCAB548AFCB1182AF85C53E81E755310D7684A6D380182FDD94F44B7FEACA9E4F307C3201E39BB51A0295DB65260703B499AD717B3834293B797CA7C17566496A828704BFB375309C50A58C711FF31531A823C66BBCCE4CF31D5B3E74BC70EB73A85A9301000C87E789D3A5E0903D6670402C64F496C3D071890AAC39732863FDDE517E4C78D401FE325B27389194E0223A7DCEEAB98902CD0DE0ED77E3B81632EE8E42D5139D700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000>
+/ByteRange [0 401203 409397 728]
+>>
+endobj
+11 0 obj
+<<
+/Contents 12 0 R
+/Parent 6 0 R
+/Resources <<
+/ColorSpace <<
+/CS0 [/ICCBased 13 0 R]
+>>
+/ExtGState <<
+/GS0 14 0 R
+>>
+/Font <<
+/TT0 15 0 R
+>>
+/ProcSet [/PDF /Text]
+/XObject <<
+>>
+>>
+/Type /Page
+/Annots [18 0 R 22 0 R 35 0 R]
+>>
+endobj
+37 0 obj
+<<
+/Subtype /Form
+/BBox [0 0 0 0]
+/Length 38 0 R
+>>
+stream
+
+endstream
+endobj
+38 0 obj
+0
+endobj
+xref
+0 2
+0000000000 65535 f
+0000400590 00000 n
+11 1
+0000409456 00000 n
+35 4
+0000400959 00000 n
+0000401113 00000 n
+0000409701 00000 n
+0000409789 00000 n
+trailer
+<<
+/Size 39
+/Root 1 0 R
+/Info 7 0 R
+/ID [<28FEE2FFDDF79E7D236ADEBEDEB883FE> <28FEE2FFDDF79E7D236ADEBEDEB883FE>]
+/Prev 400092
+>>
+startxref
+409807
+%%EOF
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/no-eof.pdf b/xmlsecurity/qa/unit/pdfsigning/data/no-eof.pdf
new file mode 100644
index 000000000..9ae7e23bb
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/no-eof.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/no.pdf b/xmlsecurity/qa/unit/pdfsigning/data/no.pdf
new file mode 100644
index 000000000..5d552421a
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/no.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/noeol.pdf b/xmlsecurity/qa/unit/pdfsigning/data/noeol.pdf
new file mode 100644
index 000000000..d870f896c
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/noeol.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/partial-in-between.pdf b/xmlsecurity/qa/unit/pdfsigning/data/partial-in-between.pdf
new file mode 100644
index 000000000..211a111cb
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/partial-in-between.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/partial.pdf b/xmlsecurity/qa/unit/pdfsigning/data/partial.pdf
new file mode 100644
index 000000000..890f56217
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/partial.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/pdf14adobe.pdf b/xmlsecurity/qa/unit/pdfsigning/data/pdf14adobe.pdf
new file mode 100644
index 000000000..58aadb492
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/pdf14adobe.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/pdf14lowin.pdf b/xmlsecurity/qa/unit/pdfsigning/data/pdf14lowin.pdf
new file mode 100644
index 000000000..5270151eb
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/pdf14lowin.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/pdf16adobe.pdf b/xmlsecurity/qa/unit/pdfsigning/data/pdf16adobe.pdf
new file mode 100644
index 000000000..ac1c5f37b
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/pdf16adobe.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/small.pdf b/xmlsecurity/qa/unit/pdfsigning/data/small.pdf
new file mode 100644
index 000000000..60675454f
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/small.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/tdf107149.pdf b/xmlsecurity/qa/unit/pdfsigning/data/tdf107149.pdf
new file mode 100644
index 000000000..db063f366
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/tdf107149.pdf
@@ -0,0 +1,97 @@
+%PDF-1.2
+%âãÏÓ
+3 0 obj
+<<
+/Length 61
+>>
+stream
+ BT
+ /F1 24 Tf
+ 1 0 0 1 260 254 Tm
+ (Hello Worl2)Tj
+ ET
+
+endstream
+endobj xref
+0 7
+0000000000 65535 f
+0000000312 00000 n
+0000000532 00000 n
+0000000015 00000 n
+0000000660 00000 n
+0000000578 00000 n
+0000000743 00000 n
+trailer
+
+<<
+/Root 6 0 R
+/Size 7
+>>
+1 0 obj
+<<
+/Resources 2 0 R
+/Contents 3 0 R
+/Parent 4 0 R
+/Type /Page
+/MediaBox [0 0 612 446]
+>>
+endobj
+3 0 obj
+<<
+/Length 61
+>>
+stream
+ BT
+ /F1 24 Tf
+ 1 0 0 1 260 254 Tm
+ (Hello World)Tj
+ ET
+
+endstream
+endobj
+2 0 obj
+<<
+/Font
+<<
+/F1 5 0 R
+>>
+>>
+endobj
+5 0 obj
+<<
+/Subtype /Type1
+/Name /F1
+/Type /Font
+/BaseFont /Helvetica
+>>
+endobj
+4 0 obj
+<<
+/Kids [1 0 R]
+/Type /Pages
+/MediaBox [0 0 612 446]
+/Count 1
+>>
+endobj
+6 0 obj
+<<
+/Type /Catalog
+/Pages 4 0 R
+>>
+endobj xref
+0 7
+0000000000 65535 f
+0000000015 00000 n
+0000000235 00000 n
+0000000121 00000 n
+0000000363 00000 n
+0000000281 00000 n
+0000000446 00000 n
+trailer
+
+<<
+/Size 7
+>>
+startxref
+128
+%%EOF
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/tdf107782.pdf b/xmlsecurity/qa/unit/pdfsigning/data/tdf107782.pdf
new file mode 100644
index 000000000..086e18eed
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/tdf107782.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/tdf114460.pdf b/xmlsecurity/qa/unit/pdfsigning/data/tdf114460.pdf
new file mode 100644
index 000000000..a736e5bb9
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/tdf114460.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/tdf145312.pdf b/xmlsecurity/qa/unit/pdfsigning/data/tdf145312.pdf
new file mode 100644
index 000000000..6ff43f87e
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/tdf145312.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
new file mode 100644
index 000000000..c4c5dcf07
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
@@ -0,0 +1,646 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <config_crypto.h>
+
+#if USE_CRYPTO_NSS
+#include <secoid.h>
+#endif
+
+#include <string_view>
+
+#include <com/sun/star/xml/crypto/SEInitializer.hpp>
+#include <com/sun/star/security/DocumentSignatureInformation.hpp>
+
+#include <osl/file.hxx>
+#include <sal/log.hxx>
+#include <test/bootstrapfixture.hxx>
+#include <unotest/macros_test.hxx>
+#include <tools/datetime.hxx>
+#include <unotools/streamwrap.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <vcl/filter/pdfdocument.hxx>
+#include <vcl/filter/PDFiumLibrary.hxx>
+
+#include <documentsignaturemanager.hxx>
+#include <pdfsignaturehelper.hxx>
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+using namespace com::sun::star;
+
+namespace
+{
+constexpr OUStringLiteral DATA_DIRECTORY = u"/xmlsecurity/qa/unit/pdfsigning/data/";
+}
+
+/// Testsuite for the PDF signing feature.
+class PDFSigningTest : public test::BootstrapFixture, public unotest::MacrosTest
+{
+protected:
+ /**
+ * Sign rInURL once and save the result as rOutURL, asserting that rInURL
+ * had nOriginalSignatureCount signatures.
+ */
+ bool sign(const OUString& rInURL, const OUString& rOutURL, size_t nOriginalSignatureCount);
+ /**
+ * Read a pdf and make sure that it has the expected number of valid
+ * signatures.
+ */
+ std::vector<SignatureInformation> verify(const OUString& rURL, size_t nCount);
+
+public:
+ PDFSigningTest();
+ void setUp() override;
+ void tearDown() override;
+};
+
+PDFSigningTest::PDFSigningTest() {}
+
+void PDFSigningTest::setUp()
+{
+ test::BootstrapFixture::setUp();
+ MacrosTest::setUpNssGpg(m_directories, "xmlsecurity_pdfsigning");
+
+ uno::Reference<xml::crypto::XSEInitializer> xSEInitializer
+ = xml::crypto::SEInitializer::create(mxComponentContext);
+ uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext
+ = xSEInitializer->createSecurityContext(OUString());
+#if USE_CRYPTO_NSS
+#ifdef NSS_USE_ALG_IN_ANY_SIGNATURE
+ // policy may disallow using SHA1 for signatures but unit test documents
+ // have such existing signatures (call this after createSecurityContext!)
+ NSS_SetAlgorithmPolicy(SEC_OID_SHA1, NSS_USE_ALG_IN_ANY_SIGNATURE, 0);
+#endif
+#endif
+}
+
+void PDFSigningTest::tearDown()
+{
+ MacrosTest::tearDownNssGpg();
+ test::BootstrapFixture::tearDown();
+}
+
+std::vector<SignatureInformation> PDFSigningTest::verify(const OUString& rURL, size_t nCount)
+{
+ uno::Reference<xml::crypto::XSEInitializer> xSEInitializer
+ = xml::crypto::SEInitializer::create(mxComponentContext);
+ uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext
+ = xSEInitializer->createSecurityContext(OUString());
+ std::vector<SignatureInformation> aRet;
+
+ SvFileStream aStream(rURL, StreamMode::READ);
+ PDFSignatureHelper aHelper;
+ CPPUNIT_ASSERT(aHelper.ReadAndVerifySignatureSvStream(aStream));
+
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (pPDFium)
+ {
+ CPPUNIT_ASSERT_EQUAL(nCount, aHelper.GetSignatureInformations().size());
+ }
+ for (size_t i = 0; i < aHelper.GetSignatureInformations().size(); ++i)
+ {
+ const SignatureInformation& rInfo = aHelper.GetSignatureInformations()[i];
+ aRet.push_back(rInfo);
+ }
+
+ return aRet;
+}
+
+bool PDFSigningTest::sign(const OUString& rInURL, const OUString& rOutURL,
+ size_t nOriginalSignatureCount)
+{
+ // Make sure that input has nOriginalSignatureCount signatures.
+ uno::Reference<xml::crypto::XSEInitializer> xSEInitializer
+ = xml::crypto::SEInitializer::create(mxComponentContext);
+ uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext
+ = xSEInitializer->createSecurityContext(OUString());
+ vcl::filter::PDFDocument aDocument;
+ {
+ SvFileStream aStream(rInURL, StreamMode::READ);
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+ std::vector<vcl::filter::PDFObjectElement*> aSignatures = aDocument.GetSignatureWidgets();
+ CPPUNIT_ASSERT_EQUAL(nOriginalSignatureCount, aSignatures.size());
+ }
+
+ bool bSignSuccessful = false;
+ // Sign it and write out the result.
+ {
+ uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment
+ = xSecurityContext->getSecurityEnvironment();
+ uno::Sequence<uno::Reference<security::XCertificate>> aCertificates
+ = xSecurityEnvironment->getPersonalCertificates();
+ DateTime now(DateTime::SYSTEM);
+ for (auto& cert : asNonConstRange(aCertificates))
+ {
+ css::util::DateTime aNotValidAfter = cert->getNotValidAfter();
+ css::util::DateTime aNotValidBefore = cert->getNotValidBefore();
+
+ // Only try certificates that are already active and not expired
+ if ((now > aNotValidAfter) || (now < aNotValidBefore))
+ {
+ SAL_WARN("xmlsecurity.qa",
+ "Skipping a certificate that is not yet valid or already not valid");
+ }
+ else
+ {
+ bool bSignResult = aDocument.Sign(cert, "test", /*bAdES=*/true);
+#ifdef _WIN32
+ if (!bSignResult)
+ {
+ DWORD dwErr = GetLastError();
+ if (HRESULT_FROM_WIN32(dwErr) == CRYPT_E_NO_KEY_PROPERTY)
+ {
+ SAL_WARN("xmlsecurity.qa", "Skipping a certificate without a private key");
+ continue; // The certificate does not have a private key - not a valid certificate
+ }
+ }
+#endif
+ CPPUNIT_ASSERT(bSignResult);
+ SvFileStream aOutStream(rOutURL, StreamMode::WRITE | StreamMode::TRUNC);
+ CPPUNIT_ASSERT(aDocument.Write(aOutStream));
+ bSignSuccessful = true;
+ break;
+ }
+ }
+ }
+
+ // This was nOriginalSignatureCount when PDFDocument::Sign() silently returned success, without doing anything.
+ if (bSignSuccessful)
+ verify(rOutURL, nOriginalSignatureCount + 1);
+
+ // May return false if NSS failed to parse its own profile or Windows has no valid certificates installed.
+ return bSignSuccessful;
+}
+
+/// Test adding a new signature to a previously unsigned file.
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDFAdd)
+{
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY);
+ OUString aInURL = aSourceDir + "no.pdf";
+ OUString aTargetDir
+ = m_directories.getURLFromWorkdir(u"/CppunitTest/xmlsecurity_pdfsigning.test.user/");
+ OUString aOutURL = aTargetDir + "add.pdf";
+ bool bHadCertificates = sign(aInURL, aOutURL, 0);
+
+ if (bHadCertificates)
+ {
+ // Assert that the SubFilter is not adbe.pkcs7.detached in the bAdES case.
+ std::vector<SignatureInformation> aInfos = verify(aOutURL, 1);
+ CPPUNIT_ASSERT(aInfos[0].bHasSigningCertificate);
+ // Make sure the timestamp is correct.
+ DateTime aDateTime(DateTime::SYSTEM);
+ // This was 0 (on Windows), as neither the /M key nor the PKCS#7 blob contained a timestamp.
+ CPPUNIT_ASSERT_EQUAL(aDateTime.GetYear(), aInfos[0].stDateTime.Year);
+ // Assert that the digest algorithm is not SHA-1 in the bAdES case.
+ CPPUNIT_ASSERT_EQUAL(xml::crypto::DigestID::SHA256, aInfos[0].nDigestID);
+ }
+}
+
+/// Test signing a previously unsigned file twice.
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDFAdd2)
+{
+ // Sign.
+ OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY);
+ OUString aInURL = aSourceDir + "no.pdf";
+ OUString aTargetDir
+ = m_directories.getURLFromWorkdir(u"/CppunitTest/xmlsecurity_pdfsigning.test.user/");
+ OUString aOutURL = aTargetDir + "add.pdf";
+ bool bHadCertificates = sign(aInURL, aOutURL, 0);
+
+ // Sign again.
+ aInURL = aTargetDir + "add.pdf";
+ aOutURL = aTargetDir + "add2.pdf";
+ // This failed with "second range end is not the end of the file" for the
+ // first signature.
+ if (bHadCertificates)
+ sign(aInURL, aOutURL, 1);
+}
+
+/// Test removing a signature from a previously signed file.
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDFRemove)
+{
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ // Make sure that good.pdf has 1 valid signature.
+ uno::Reference<xml::crypto::XSEInitializer> xSEInitializer
+ = xml::crypto::SEInitializer::create(mxComponentContext);
+ uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext
+ = xSEInitializer->createSecurityContext(OUString());
+ vcl::filter::PDFDocument aDocument;
+ OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY);
+ OUString aInURL = aSourceDir + "good.pdf";
+ {
+ SvFileStream aStream(aInURL, StreamMode::READ);
+ PDFSignatureHelper aHelper;
+ aHelper.ReadAndVerifySignatureSvStream(aStream);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aHelper.GetSignatureInformations().size());
+ }
+
+ // Remove the signature and write out the result as remove.pdf.
+ OUString aTargetDir
+ = m_directories.getURLFromWorkdir(u"/CppunitTest/xmlsecurity_pdfsigning.test.user/");
+ OUString aOutURL = aTargetDir + "remove.pdf";
+ osl::File::copy(aInURL, aOutURL);
+ {
+ uno::Reference<io::XInputStream> xInputStream;
+ std::unique_ptr<SvStream> pStream
+ = utl::UcbStreamHelper::CreateStream(aOutURL, StreamMode::READWRITE);
+ uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(std::move(pStream)));
+ xInputStream.set(xStream, uno::UNO_QUERY);
+ PDFSignatureHelper::RemoveSignature(xInputStream, 0);
+ }
+
+ // Read back the pdf and make sure that it no longer has signatures.
+ // This failed when PDFDocument::RemoveSignature() silently returned
+ // success, without doing anything.
+ verify(aOutURL, 0);
+}
+
+/// Test removing all signatures from a previously multi-signed file.
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDFRemoveAll)
+{
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ // Make sure that good2.pdf has 2 valid signatures. Unlike in
+ // testPDFRemove(), here intentionally test DocumentSignatureManager and
+ // PDFSignatureHelper code as well.
+ uno::Reference<xml::crypto::XSEInitializer> xSEInitializer
+ = xml::crypto::SEInitializer::create(mxComponentContext);
+ uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext
+ = xSEInitializer->createSecurityContext(OUString());
+
+ // Copy the test document to a temporary file, as it'll be modified.
+ OUString aTargetDir
+ = m_directories.getURLFromWorkdir(u"/CppunitTest/xmlsecurity_pdfsigning.test.user/");
+ OUString aOutURL = aTargetDir + "remove-all.pdf";
+ CPPUNIT_ASSERT_EQUAL(
+ osl::File::RC::E_None,
+ osl::File::copy(m_directories.getURLFromSrc(DATA_DIRECTORY) + "2good.pdf", aOutURL));
+ // Load the test document as a storage and read its two signatures.
+ DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content);
+ std::unique_ptr<SvStream> pStream
+ = utl::UcbStreamHelper::CreateStream(aOutURL, StreamMode::READ | StreamMode::WRITE);
+ uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(std::move(pStream)));
+ aManager.setSignatureStream(xStream);
+ aManager.read(/*bUseTempStream=*/false);
+ std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations();
+ // This was 1 when NSS_CMSSignerInfo_GetSigningCertificate() failed, which
+ // means that we only used the locally imported certificates for
+ // verification, not the ones provided in the PDF signature data.
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), rInformations.size());
+
+ // Request removal of the first signature, should imply removal of the
+ // second chained signature as well.
+ aManager.remove(0);
+ // This was 2, Manager didn't write anything to disk when removal succeeded
+ // (instead of doing that when removal failed).
+ // Then this was 1, when the chained signature wasn't removed.
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(0), rInformations.size());
+}
+
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testTdf107782)
+{
+ uno::Reference<xml::crypto::XSEInitializer> xSEInitializer
+ = xml::crypto::SEInitializer::create(mxComponentContext);
+ uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext
+ = xSEInitializer->createSecurityContext(OUString());
+
+ // Load the test document as a storage and read its signatures.
+ DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content);
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf107782.pdf";
+ std::unique_ptr<SvStream> pStream
+ = utl::UcbStreamHelper::CreateStream(aURL, StreamMode::READ | StreamMode::WRITE);
+ uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(std::move(pStream)));
+ aManager.setSignatureStream(xStream);
+ aManager.read(/*bUseTempStream=*/false);
+ CPPUNIT_ASSERT(aManager.hasPDFSignatureHelper());
+
+ // This failed with an std::bad_alloc exception on Windows.
+ aManager.getPDFSignatureHelper().GetDocumentSignatureInformations(
+ aManager.getSecurityEnvironment());
+}
+
+/// Test a PDF 1.4 document, signed by Adobe.
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDF14Adobe)
+{
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ // Two signatures, first is SHA1, the second is SHA256.
+ // This was 0, as we failed to find the Annots key's value when it was a
+ // reference-to-array, not an array.
+ std::vector<SignatureInformation> aInfos
+ = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "pdf14adobe.pdf", 2);
+ // This was 0, out-of-PKCS#7 signature date wasn't read.
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(2016), aInfos[1].stDateTime.Year);
+}
+
+/// Test a PDF 1.6 document, signed by Adobe.
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDF16Adobe)
+{
+ // Contains a cross-reference stream, object streams and a compressed
+ // stream with a predictor. And a valid signature.
+ // Found signatures was 0, as parsing failed due to lack of support for
+ // these features.
+ verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "pdf16adobe.pdf", 1);
+}
+
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testTdf145312)
+{
+ // Without the fix in place, this test would have crashed
+ verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf145312.pdf", 2);
+}
+
+/// Test adding a signature to a PDF 1.6 document.
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDF16Add)
+{
+ // Contains PDF 1.6 features, make sure we can add a signature using that
+ // markup correctly.
+ OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY);
+ OUString aInURL = aSourceDir + "pdf16adobe.pdf";
+ OUString aTargetDir
+ = m_directories.getURLFromWorkdir(u"/CppunitTest/xmlsecurity_pdfsigning.test.user/");
+ OUString aOutURL = aTargetDir + "add.pdf";
+ // This failed: verification broke as incorrect xref stream was written as
+ // part of the new signature.
+ bool bHadCertificates = sign(aInURL, aOutURL, 1);
+
+ // Sign again.
+ aInURL = aTargetDir + "add.pdf";
+ aOutURL = aTargetDir + "add2.pdf";
+ // This failed as non-compressed AcroForm wasn't handled.
+ if (bHadCertificates)
+ sign(aInURL, aOutURL, 2);
+}
+
+/// Test a PDF 1.4 document, signed by LO on Windows.
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDF14LOWin)
+{
+ // mscrypto used SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION as a digest
+ // algorithm when it meant SEC_OID_SHA1, make sure we tolerate that on all
+ // platforms.
+ // This failed, as NSS HASH_Create() didn't handle the sign algorithm.
+ verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "pdf14lowin.pdf", 1);
+}
+
+/// Test a PAdES document, signed by LO on Linux.
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDFPAdESGood)
+{
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ std::vector<SignatureInformation> aInfos
+ = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "good-pades.pdf", 1);
+ CPPUNIT_ASSERT(aInfos[0].bHasSigningCertificate);
+}
+
+/// Test a valid signature that does not cover the whole file.
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPartial)
+{
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ std::vector<SignatureInformation> aInfos
+ = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "partial.pdf", 1);
+ CPPUNIT_ASSERT(!aInfos.empty());
+ SignatureInformation& rInformation = aInfos[0];
+ CPPUNIT_ASSERT(rInformation.bPartialDocumentSignature);
+}
+
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPartialInBetween)
+{
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ std::vector<SignatureInformation> aInfos
+ = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "partial-in-between.pdf", 2);
+ CPPUNIT_ASSERT(!aInfos.empty());
+ SignatureInformation& rInformation = aInfos[0];
+ // Without the accompanying fix in place, this test would have failed, as unsigned incremental
+ // update between two signatures were not detected.
+ CPPUNIT_ASSERT(rInformation.bPartialDocumentSignature);
+}
+
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testBadCertP1)
+{
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ std::vector<SignatureInformation> aInfos
+ = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "bad-cert-p1.pdf", 1);
+ CPPUNIT_ASSERT(!aInfos.empty());
+ SignatureInformation& rInformation = aInfos[0];
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 0 (SecurityOperationStatus_UNKNOWN)
+ // - Actual : 1 (SecurityOperationStatus_OPERATION_SUCCEEDED)
+ // i.e. annotation after a P1 signature was not considered as a bad modification.
+ CPPUNIT_ASSERT_EQUAL(xml::crypto::SecurityOperationStatus::SecurityOperationStatus_UNKNOWN,
+ rInformation.nStatus);
+}
+
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testBadCertP3Stamp)
+{
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ std::vector<SignatureInformation> aInfos
+ = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "bad-cert-p3-stamp.pdf", 1);
+ CPPUNIT_ASSERT(!aInfos.empty());
+ SignatureInformation& rInformation = aInfos[0];
+
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 0 (SecurityOperationStatus_UNKNOWN)
+ // - Actual : 1 (SecurityOperationStatus_OPERATION_SUCCEEDED)
+ // i.e. adding a stamp annotation was not considered as a bad modification.
+ CPPUNIT_ASSERT_EQUAL(xml::crypto::SecurityOperationStatus::SecurityOperationStatus_UNKNOWN,
+ rInformation.nStatus);
+}
+
+/// Test writing a PAdES signature.
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testSigningCertificateAttribute)
+{
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ // Create a new signature.
+ OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY);
+ OUString aInURL = aSourceDir + "no.pdf";
+ OUString aTargetDir
+ = m_directories.getURLFromWorkdir(u"/CppunitTest/xmlsecurity_pdfsigning.test.user/");
+ OUString aOutURL = aTargetDir + "signing-certificate-attribute.pdf";
+ bool bHadCertificates = sign(aInURL, aOutURL, 0);
+ if (!bHadCertificates)
+ return;
+
+ // Verify it.
+ std::vector<SignatureInformation> aInfos = verify(aOutURL, 1);
+ CPPUNIT_ASSERT(!aInfos.empty());
+ SignatureInformation& rInformation = aInfos[0];
+ // Assert that it has a signed signingCertificateV2 attribute.
+ CPPUNIT_ASSERT(rInformation.bHasSigningCertificate);
+}
+
+/// Test that we accept files which are supposed to be good.
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testGood)
+{
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ const std::initializer_list<std::u16string_view> aNames = {
+ // We failed to determine if this is good or bad.
+ u"good-non-detached.pdf",
+ // Boolean value for dictionary key caused read error.
+ u"dict-bool.pdf",
+ };
+
+ for (const auto& rName : aNames)
+ {
+ std::vector<SignatureInformation> aInfos
+ = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + rName, 1);
+ CPPUNIT_ASSERT(!aInfos.empty());
+ SignatureInformation& rInformation = aInfos[0];
+ CPPUNIT_ASSERT_EQUAL(int(xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED),
+ static_cast<int>(rInformation.nStatus));
+ }
+}
+
+/// Test that we don't crash / loop while tokenizing these files.
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testTokenize)
+{
+ const std::initializer_list<std::u16string_view> aNames = {
+ // We looped on this broken input.
+ u"no-eof.pdf",
+ // ']' in a name token was mishandled.
+ u"name-bracket.pdf",
+ // %%EOF at the end wasn't followed by a newline.
+ u"noeol.pdf",
+ // File that's intentionally smaller than 1024 bytes.
+ u"small.pdf",
+ u"tdf107149.pdf",
+ // Nested parentheses were not handled.
+ u"tdf114460.pdf",
+ // Valgrind was unhappy about this.
+ u"forcepoint16.pdf",
+ };
+
+ for (const auto& rName : aNames)
+ {
+ SvFileStream aStream(m_directories.getURLFromSrc(DATA_DIRECTORY) + rName, StreamMode::READ);
+ vcl::filter::PDFDocument aDocument;
+ // Just make sure the tokenizer finishes without an error, don't look at the signature.
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+ if (rName == u"tdf107149.pdf")
+ // This failed, page list was empty.
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aDocument.GetPages().size());
+ }
+}
+
+/// Test handling of unknown SubFilter values.
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testUnknownSubFilter)
+{
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ // Tokenize the bugdoc.
+ uno::Reference<xml::crypto::XSEInitializer> xSEInitializer
+ = xml::crypto::SEInitializer::create(mxComponentContext);
+ uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext
+ = xSEInitializer->createSecurityContext(OUString());
+ std::unique_ptr<SvStream> pStream = utl::UcbStreamHelper::CreateStream(
+ m_directories.getURLFromSrc(DATA_DIRECTORY) + "cr-comment.pdf", StreamMode::STD_READ);
+ uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(std::move(pStream)));
+ DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content);
+ aManager.setSignatureStream(xStream);
+ aManager.read(/*bUseTempStream=*/false);
+
+ // Make sure we find both signatures, even if the second has unknown SubFilter.
+ std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations();
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), rInformations.size());
+}
+
+CPPUNIT_TEST_FIXTURE(PDFSigningTest, testGoodCustomMagic)
+{
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ // Tokenize the bugdoc.
+ uno::Reference<xml::crypto::XSEInitializer> xSEInitializer
+ = xml::crypto::SEInitializer::create(mxComponentContext);
+ uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext
+ = xSEInitializer->createSecurityContext(OUString());
+ std::unique_ptr<SvStream> pStream = utl::UcbStreamHelper::CreateStream(
+ m_directories.getURLFromSrc(DATA_DIRECTORY) + "good-custom-magic.pdf",
+ StreamMode::STD_READ);
+ uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(std::move(pStream)));
+ DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content);
+ aManager.setSignatureStream(xStream);
+ aManager.read(/*bUseTempStream=*/false);
+
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 1 (SecurityOperationStatus_OPERATION_SUCCEEDED)
+ // - Actual : 0 (SecurityOperationStatus_UNKNOWN)
+ // i.e. no signatures were found due to a custom non-comment magic after the header.
+ std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations();
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size());
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/qa/unit/signing/data/02_doc_macros_signed_by_attacker_manipulated.odt b/xmlsecurity/qa/unit/signing/data/02_doc_macros_signed_by_attacker_manipulated.odt
new file mode 100644
index 000000000..d63e4b6b7
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/02_doc_macros_signed_by_attacker_manipulated.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated.odt b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated.odt
new file mode 100644
index 000000000..0190abb00
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated2.odt b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated2.odt
new file mode 100644
index 000000000..f4b4198f9
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated2.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated_triple.odt b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated_triple.odt
new file mode 100644
index 000000000..558bdee47
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated_triple.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_trusted_person_manipulated.odt b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_trusted_person_manipulated.odt
new file mode 100644
index 000000000..4136b32e5
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_trusted_person_manipulated.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/add-visible-signature.pdf b/xmlsecurity/qa/unit/signing/data/add-visible-signature.pdf
new file mode 100644
index 000000000..8dedb6998
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/add-visible-signature.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/bad.docx b/xmlsecurity/qa/unit/signing/data/bad.docx
new file mode 100644
index 000000000..86d0eda49
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/bad.docx
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/bad.odt b/xmlsecurity/qa/unit/signing/data/bad.odt
new file mode 100644
index 000000000..75c39d5d8
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/bad.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/bad.pdf b/xmlsecurity/qa/unit/signing/data/bad.pdf
new file mode 100644
index 000000000..f3f056f2b
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/bad.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/badDsigGPG.odt b/xmlsecurity/qa/unit/signing/data/badDsigGPG.odt
new file mode 100644
index 000000000..032ddbf7a
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/badDsigGPG.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/badStreamGPG.odt b/xmlsecurity/qa/unit/signing/data/badStreamGPG.odt
new file mode 100644
index 000000000..252ea26b0
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/badStreamGPG.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/encryptedGPG.odt b/xmlsecurity/qa/unit/signing/data/encryptedGPG.odt
new file mode 100644
index 000000000..9490a0ce5
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/encryptedGPG.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/encryptedGPG_odf13.odt b/xmlsecurity/qa/unit/signing/data/encryptedGPG_odf13.odt
new file mode 100644
index 000000000..e738c2f6d
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/encryptedGPG_odf13.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/good-xades.odt b/xmlsecurity/qa/unit/signing/data/good-xades.odt
new file mode 100644
index 000000000..4f96d4bd8
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/good-xades.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/good.odt b/xmlsecurity/qa/unit/signing/data/good.odt
new file mode 100644
index 000000000..8c6019d0a
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/good.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/good.pdf b/xmlsecurity/qa/unit/signing/data/good.pdf
new file mode 100644
index 000000000..4a506c1e1
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/good.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/goodGPG.odt b/xmlsecurity/qa/unit/signing/data/goodGPG.odt
new file mode 100644
index 000000000..a02af3016
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/goodGPG.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/hide-and-replace-shadow-file-signed-2.pdf b/xmlsecurity/qa/unit/signing/data/hide-and-replace-shadow-file-signed-2.pdf
new file mode 100644
index 000000000..f2b1a7109
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/hide-and-replace-shadow-file-signed-2.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/multi.docx b/xmlsecurity/qa/unit/signing/data/multi.docx
new file mode 100644
index 000000000..aba69508e
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/multi.docx
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/no.odt b/xmlsecurity/qa/unit/signing/data/no.odt
new file mode 100644
index 000000000..22cf7683a
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/no.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/no.pdf b/xmlsecurity/qa/unit/signing/data/no.pdf
new file mode 100644
index 000000000..5d552421a
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/no.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/notype-xades.odt b/xmlsecurity/qa/unit/signing/data/notype-xades.odt
new file mode 100644
index 000000000..4f96d4bd8
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/notype-xades.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/odb_signed_macros.odb b/xmlsecurity/qa/unit/signing/data/odb_signed_macros.odb
new file mode 100644
index 000000000..3e90f4514
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/odb_signed_macros.odb
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/partial.docx b/xmlsecurity/qa/unit/signing/data/partial.docx
new file mode 100644
index 000000000..3d6ca4685
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/partial.docx
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/signatureline.docx b/xmlsecurity/qa/unit/signing/data/signatureline.docx
new file mode 100644
index 000000000..e1dae6698
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/signatureline.docx
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/signatureline.odt b/xmlsecurity/qa/unit/signing/data/signatureline.odt
new file mode 100644
index 000000000..d3a3e4671
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/signatureline.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odt b/xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odt
new file mode 100644
index 000000000..5e519dd8b
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/tdf42316.ott b/xmlsecurity/qa/unit/signing/data/tdf42316.ott
new file mode 100644
index 000000000..95162a627
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/tdf42316.ott
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/tdf42316_odt12.ott b/xmlsecurity/qa/unit/signing/data/tdf42316_odt12.ott
new file mode 100644
index 000000000..ecff48709
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/tdf42316_odt12.ott
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/tdf96097.ods b/xmlsecurity/qa/unit/signing/data/tdf96097.ods
new file mode 100644
index 000000000..58d1b2c77
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/tdf96097.ods
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/tdf96097.odt b/xmlsecurity/qa/unit/signing/data/tdf96097.odt
new file mode 100644
index 000000000..f0356513c
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/tdf96097.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/data/untrustedGoodGPG.odt b/xmlsecurity/qa/unit/signing/data/untrustedGoodGPG.odt
new file mode 100644
index 000000000..e1b36d544
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/data/untrustedGoodGPG.odt
Binary files differ
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx b/xmlsecurity/qa/unit/signing/signing.cxx
new file mode 100644
index 000000000..c3c5d254b
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -0,0 +1,1696 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <config_crypto.h>
+#include <config_features.h>
+#include <config_gpgme.h>
+
+#include <sal/config.h>
+
+#if USE_CRYPTO_NSS
+#include <secoid.h>
+#endif
+
+#include <test/bootstrapfixture.hxx>
+#include <unotest/macros_test.hxx>
+#include <test/xmltesttools.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/security/CertificateValidity.hpp>
+#include <com/sun/star/security/DocumentDigitalSignatures.hpp>
+#include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
+#include <com/sun/star/xml/crypto/SEInitializer.hpp>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <unotools/mediadescriptor.hxx>
+#include <unotools/tempfile.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <sfx2/sfxbasemodel.hxx>
+#include <sfx2/objsh.hxx>
+#include <osl/file.hxx>
+#include <osl/thread.hxx>
+#include <comphelper/ofopxmlhelper.hxx>
+#include <unotools/streamwrap.hxx>
+
+#include <documentsignaturehelper.hxx>
+#include <xmlsignaturehelper.hxx>
+#include <documentsignaturemanager.hxx>
+#include <biginteger.hxx>
+#include <certificate.hxx>
+#include <xsecctl.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <comphelper/configuration.hxx>
+#include <svx/signaturelinehelper.hxx>
+#include <sfx2/viewsh.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <vcl/filter/PDFiumLibrary.hxx>
+#include <vcl/scheduler.hxx>
+
+using namespace com::sun::star;
+
+namespace
+{
+constexpr OUStringLiteral DATA_DIRECTORY = u"/xmlsecurity/qa/unit/signing/data/";
+}
+
+/// Testsuite for the document signing feature.
+class SigningTest : public test::BootstrapFixture, public unotest::MacrosTest, public XmlTestTools
+{
+protected:
+ uno::Reference<lang::XComponent> mxComponent;
+ uno::Reference<xml::crypto::XSEInitializer> mxSEInitializer;
+ uno::Reference<xml::crypto::XXMLSecurityContext> mxSecurityContext;
+
+public:
+ SigningTest();
+ virtual void setUp() override;
+ virtual void tearDown() override;
+ void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) override;
+
+protected:
+ void createDoc(const OUString& rURL);
+ void createCalc(const OUString& rURL);
+ uno::Reference<security::XCertificate>
+ getCertificate(DocumentSignatureManager& rSignatureManager,
+ svl::crypto::SignatureMethodAlgorithm eAlgo);
+#if HAVE_FEATURE_GPGVERIFY
+ SfxObjectShell* assertDocument(const ::CppUnit::SourceLine aSrcLine,
+ const OUString& rFilterName, const SignatureState nDocSign,
+ const SignatureState nMacroSign, const OUString& sVersion);
+#endif
+};
+
+SigningTest::SigningTest() {}
+
+void SigningTest::setUp()
+{
+ test::BootstrapFixture::setUp();
+ MacrosTest::setUpNssGpg(m_directories, "xmlsecurity_signing");
+
+ // Initialize crypto after setting up the environment variables.
+ mxDesktop.set(frame::Desktop::create(mxComponentContext));
+ mxSEInitializer = xml::crypto::SEInitializer::create(mxComponentContext);
+ mxSecurityContext = mxSEInitializer->createSecurityContext(OUString());
+#if USE_CRYPTO_NSS
+#ifdef NSS_USE_ALG_IN_ANY_SIGNATURE
+ // policy may disallow using SHA1 for signatures but unit test documents
+ // have such existing signatures (call this after createSecurityContext!)
+ NSS_SetAlgorithmPolicy(SEC_OID_SHA1, NSS_USE_ALG_IN_ANY_SIGNATURE, 0);
+#endif
+#endif
+}
+
+void SigningTest::tearDown()
+{
+ if (mxComponent.is())
+ mxComponent->dispose();
+
+ MacrosTest::tearDownNssGpg();
+ test::BootstrapFixture::tearDown();
+}
+
+void SigningTest::createDoc(const OUString& rURL)
+{
+ if (mxComponent.is())
+ mxComponent->dispose();
+ if (rURL.isEmpty())
+ mxComponent = loadFromDesktop("private:factory/swriter", "com.sun.star.text.TextDocument");
+ else
+ mxComponent = loadFromDesktop(rURL, "com.sun.star.text.TextDocument");
+}
+
+void SigningTest::createCalc(const OUString& rURL)
+{
+ if (mxComponent.is())
+ mxComponent->dispose();
+ if (rURL.isEmpty())
+ mxComponent
+ = loadFromDesktop("private:factory/swriter", "com.sun.star.sheet.SpreadsheetDocument");
+ else
+ mxComponent = loadFromDesktop(rURL, "com.sun.star.sheet.SpreadsheetDocument");
+}
+
+uno::Reference<security::XCertificate>
+SigningTest::getCertificate(DocumentSignatureManager& rSignatureManager,
+ svl::crypto::SignatureMethodAlgorithm eAlgo)
+{
+ uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment
+ = rSignatureManager.getSecurityEnvironment();
+ const uno::Sequence<uno::Reference<security::XCertificate>> aCertificates
+ = xSecurityEnvironment->getPersonalCertificates();
+
+ for (const auto& xCertificate : aCertificates)
+ {
+ auto pCertificate = dynamic_cast<xmlsecurity::Certificate*>(xCertificate.get());
+ CPPUNIT_ASSERT(pCertificate);
+ if (pCertificate->getSignatureMethodAlgorithm() == eAlgo && IsValid(xCertificate))
+ return xCertificate;
+ }
+ return uno::Reference<security::XCertificate>();
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testDescription)
+{
+ // Create an empty document and store it to a tempfile, finally load it as a storage.
+ createDoc("");
+
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("writer8");
+ xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content);
+ CPPUNIT_ASSERT(aManager.init());
+ uno::Reference<embed::XStorage> xStorage
+ = comphelper::OStorageHelper::GetStorageOfFormatFromURL(
+ ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE);
+ CPPUNIT_ASSERT(xStorage.is());
+ aManager.setStore(xStorage);
+ aManager.getSignatureHelper().SetStorage(xStorage, "1.2");
+
+ // Then add a signature document.
+ uno::Reference<security::XCertificate> xCertificate
+ = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA);
+ if (!xCertificate.is())
+ return;
+ OUString aDescription("SigningTest::testDescription");
+ sal_Int32 nSecurityId;
+ aManager.add(xCertificate, mxSecurityContext, aDescription, nSecurityId, false);
+
+ // Read back the signature and make sure that the description survives the roundtrip.
+ aManager.read(/*bUseTempStream=*/true);
+ std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations();
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size());
+ CPPUNIT_ASSERT_EQUAL(aDescription, rInformations[0].ouDescription);
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testECDSA)
+{
+ // Create an empty document and store it to a tempfile, finally load it as a storage.
+ createDoc("");
+
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("writer8");
+ xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content);
+ CPPUNIT_ASSERT(aManager.init());
+ uno::Reference<embed::XStorage> xStorage
+ = comphelper::OStorageHelper::GetStorageOfFormatFromURL(
+ ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE);
+ CPPUNIT_ASSERT(xStorage.is());
+ aManager.setStore(xStorage);
+ aManager.getSignatureHelper().SetStorage(xStorage, "1.2");
+
+ // Then add a signature.
+ uno::Reference<security::XCertificate> xCertificate
+ = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::ECDSA);
+ if (!xCertificate.is())
+ return;
+ sal_Int32 nSecurityId;
+ aManager.add(xCertificate, mxSecurityContext, "", nSecurityId, false);
+
+ // Read back the signature and make sure that it's valid.
+ aManager.read(/*bUseTempStream=*/true);
+ std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations();
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size());
+ // This was SecurityOperationStatus_UNKNOWN, signing with an ECDSA key was
+ // broken.
+ CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED,
+ rInformations[0].nStatus);
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testECDSAOOXML)
+{
+ // Create an empty document and store it to a tempfile, finally load it as a storage.
+ createDoc("");
+
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("MS Word 2007 XML");
+ xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content);
+ CPPUNIT_ASSERT(aManager.init());
+ uno::Reference<embed::XStorage> xStorage
+ = comphelper::OStorageHelper::GetStorageOfFormatFromURL(
+ ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE);
+ CPPUNIT_ASSERT(xStorage.is());
+ aManager.setStore(xStorage);
+ aManager.getSignatureHelper().SetStorage(xStorage, "1.2");
+
+ // Then add a document signature.
+ uno::Reference<security::XCertificate> xCertificate
+ = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::ECDSA);
+ if (!xCertificate.is())
+ return;
+ sal_Int32 nSecurityId;
+ aManager.add(xCertificate, mxSecurityContext, "", nSecurityId,
+ /*bAdESCompliant=*/false);
+
+ // Read back the signature and make sure that it's valid.
+ aManager.read(/*bUseTempStream=*/true);
+ std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations();
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size());
+ // This was SecurityOperationStatus_UNKNOWN, signing with an ECDSA key was
+ // broken.
+ CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED,
+ rInformations[0].nStatus);
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testECDSAPDF)
+{
+ // Create an empty document and store it to a tempfile, finally load it as
+ // a stream.
+ createDoc("");
+
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content);
+ CPPUNIT_ASSERT(aManager.init());
+ std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(
+ aTempFile.GetURL(), StreamMode::READ | StreamMode::WRITE));
+ uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(*pStream));
+ CPPUNIT_ASSERT(xStream.is());
+ aManager.setSignatureStream(xStream);
+
+ // Then add a document signature.
+ uno::Reference<security::XCertificate> xCertificate
+ = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::ECDSA);
+ if (!xCertificate.is())
+ return;
+ sal_Int32 nSecurityId;
+ aManager.add(xCertificate, mxSecurityContext, "", nSecurityId,
+ /*bAdESCompliant=*/true);
+
+ // Read back the signature and make sure that it's valid.
+ aManager.read(/*bUseTempStream=*/false);
+ std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations();
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size());
+ // This was SecurityOperationStatus_UNKNOWN, signing with an ECDSA key was
+ // broken.
+ CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED,
+ rInformations[0].nStatus);
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLDescription)
+{
+ // Create an empty document and store it to a tempfile, finally load it as a storage.
+ createDoc("");
+
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("MS Word 2007 XML");
+ xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content);
+ CPPUNIT_ASSERT(aManager.init());
+ uno::Reference<embed::XStorage> xStorage
+ = comphelper::OStorageHelper::GetStorageOfFormatFromURL(
+ ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE);
+ CPPUNIT_ASSERT(xStorage.is());
+ aManager.setStore(xStorage);
+ aManager.getSignatureHelper().SetStorage(xStorage, "1.2");
+
+ // Then add a document signature.
+ uno::Reference<security::XCertificate> xCertificate
+ = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA);
+ if (!xCertificate.is())
+ return;
+ OUString aDescription("SigningTest::testDescription");
+ sal_Int32 nSecurityId;
+ aManager.add(xCertificate, mxSecurityContext, aDescription, nSecurityId, false);
+
+ // Read back the signature and make sure that the description survives the roundtrip.
+ aManager.read(/*bUseTempStream=*/true);
+ std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations();
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size());
+ CPPUNIT_ASSERT_EQUAL(aDescription, rInformations[0].ouDescription);
+}
+
+/// Test appending a new signature next to an existing one.
+CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLAppend)
+{
+ // Copy the test document to a temporary file, as it'll be modified.
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ OUString aURL = aTempFile.GetURL();
+ CPPUNIT_ASSERT_EQUAL(
+ osl::File::RC::E_None,
+ osl::File::copy(m_directories.getURLFromSrc(DATA_DIRECTORY) + "partial.docx", aURL));
+ // Load the test document as a storage and read its single signature.
+ DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content);
+ CPPUNIT_ASSERT(aManager.init());
+ uno::Reference<embed::XStorage> xStorage
+ = comphelper::OStorageHelper::GetStorageOfFormatFromURL(ZIP_STORAGE_FORMAT_STRING, aURL,
+ embed::ElementModes::READWRITE);
+ CPPUNIT_ASSERT(xStorage.is());
+ aManager.setStore(xStorage);
+ aManager.getSignatureHelper().SetStorage(xStorage, "1.2");
+ aManager.read(/*bUseTempStream=*/false);
+ std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations();
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size());
+
+ // Then add a second document signature.
+ uno::Reference<security::XCertificate> xCertificate
+ = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA);
+ if (!xCertificate.is())
+ return;
+ sal_Int32 nSecurityId;
+ aManager.add(xCertificate, mxSecurityContext, OUString(), nSecurityId, false);
+
+ // Read back the signatures and make sure that we have the expected amount.
+ aManager.read(/*bUseTempStream=*/true);
+ // This was 1: the original signature was lost.
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), rInformations.size());
+}
+
+/// Test removing a signature from existing ones.
+CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLRemove)
+{
+ // Load the test document as a storage and read its signatures: purpose1 and purpose2.
+ DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content);
+ CPPUNIT_ASSERT(aManager.init());
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ OUString aURL = aTempFile.GetURL();
+ CPPUNIT_ASSERT_EQUAL(
+ osl::File::RC::E_None,
+ osl::File::copy(m_directories.getURLFromSrc(DATA_DIRECTORY) + "multi.docx", aURL));
+ uno::Reference<embed::XStorage> xStorage
+ = comphelper::OStorageHelper::GetStorageOfFormatFromURL(ZIP_STORAGE_FORMAT_STRING, aURL,
+ embed::ElementModes::READWRITE);
+ CPPUNIT_ASSERT(xStorage.is());
+ aManager.setStore(xStorage);
+ aManager.getSignatureHelper().SetStorage(xStorage, "1.2");
+ aManager.read(/*bUseTempStream=*/false);
+ std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations();
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), rInformations.size());
+
+ // Then remove the last added signature.
+ uno::Reference<security::XCertificate> xCertificate
+ = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA);
+ if (!xCertificate.is())
+ return;
+ aManager.remove(0);
+
+ // Read back the signatures and make sure that only purpose1 is left.
+ aManager.read(/*bUseTempStream=*/true);
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size());
+ CPPUNIT_ASSERT_EQUAL(OUString("purpose1"), rInformations[0].ouDescription);
+}
+
+/// Test removing all signatures from a document.
+CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLRemoveAll)
+{
+ // Copy the test document to a temporary file, as it'll be modified.
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ OUString aURL = aTempFile.GetURL();
+ CPPUNIT_ASSERT_EQUAL(
+ osl::File::RC::E_None,
+ osl::File::copy(m_directories.getURLFromSrc(DATA_DIRECTORY) + "partial.docx", aURL));
+ // Load the test document as a storage and read its single signature.
+ DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content);
+ CPPUNIT_ASSERT(aManager.init());
+ uno::Reference<embed::XStorage> xStorage
+ = comphelper::OStorageHelper::GetStorageOfFormatFromURL(ZIP_STORAGE_FORMAT_STRING, aURL,
+ embed::ElementModes::READWRITE);
+ CPPUNIT_ASSERT(xStorage.is());
+ aManager.setStore(xStorage);
+ aManager.getSignatureHelper().SetStorage(xStorage, "1.2");
+ aManager.read(/*bUseTempStream=*/false);
+ std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations();
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size());
+
+ // Then remove the only signature in the document.
+ uno::Reference<security::XCertificate> xCertificate
+ = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA);
+ if (!xCertificate.is())
+ return;
+ aManager.remove(0);
+ aManager.read(/*bUseTempStream=*/true);
+ aManager.write(/*bXAdESCompliantIfODF=*/false);
+
+ // Make sure that the signature count is zero and the whole signature storage is removed completely.
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(0), rInformations.size());
+ CPPUNIT_ASSERT(!xStorage->hasByName("_xmlsignatures"));
+
+ // And that content types no longer contains signature types.
+ uno::Reference<io::XStream> xStream
+ = xStorage->openStreamElement("[Content_Types].xml", embed::ElementModes::READWRITE);
+ uno::Reference<io::XInputStream> xInputStream = xStream->getInputStream();
+ uno::Sequence<uno::Sequence<beans::StringPair>> aContentTypeInfo
+ = comphelper::OFOPXMLHelper::ReadContentTypeSequence(xInputStream, mxComponentContext);
+ const uno::Sequence<beans::StringPair>& rOverrides = aContentTypeInfo[1];
+ CPPUNIT_ASSERT(
+ std::none_of(rOverrides.begin(), rOverrides.end(), [](const beans::StringPair& rPair) {
+ return rPair.First.startsWith("/_xmlsignatures/sig");
+ }));
+}
+
+/// Test a typical ODF where all streams are signed.
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFGood)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "good.odt");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ // We expect NOTVALIDATED in case the root CA is not imported on the system, and OK otherwise, so accept both.
+ SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+ CPPUNIT_ASSERT_MESSAGE(
+ (OString::number(o3tl::to_underlying(nActual)).getStr()),
+ (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK));
+}
+
+/// Test a typical broken ODF signature where one stream is corrupted.
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFBroken)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "bad.odt");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::BROKEN),
+ static_cast<int>(pObjectShell->GetDocumentSignatureState()));
+}
+
+// Document has a signature stream, but no actual signatures.
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFNo)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "no.odt");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::NOSIGNATURES),
+ static_cast<int>(pObjectShell->GetDocumentSignatureState()));
+}
+
+// document has one signed timestamp and one unsigned timestamp
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFUnsignedTimestamp)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY)
+ + "02_doc_signed_by_trusted_person_manipulated.odt");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+ CPPUNIT_ASSERT_MESSAGE(
+ (OString::number(o3tl::to_underlying(nActual)).getStr()),
+ (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK));
+ uno::Sequence<security::DocumentSignatureInformation> const infos(
+ pObjectShell->GetDocumentSignatureInformation(false));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength());
+ // was: 66666666
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(20210126), infos[0].SignatureDate);
+ // was: 0
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(18183742), infos[0].SignatureTime);
+}
+
+// FIXME: For some unknown reason, this test fails on tml's Mac unless it is the only or the first
+// test that is run in this CppunitTest program. When using our patched bundled cppunit library (as
+// we obviously always do on macOS), the CPPUNIT_TEST_FIXTUREs are run in lexicographical order so
+// use a name for this test that makes it the first one to run.
+
+CPPUNIT_TEST_FIXTURE(SigningTest, aaa_testODFX509CertificateChain)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY)
+ + "signed_with_x509certificate_chain.odt");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+ CPPUNIT_ASSERT_MESSAGE(
+ (OString::number(o3tl::to_underlying(nActual)).getStr()),
+ (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK));
+ uno::Sequence<security::DocumentSignatureInformation> const infos(
+ pObjectShell->GetDocumentSignatureInformation(false));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength());
+ // check that the signing certificate was picked, not one of the 2 CA ones
+ CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::VALID, infos[0].CertificateStatus);
+ CPPUNIT_ASSERT(infos[0].Signer.is());
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("CN=Xmlsecurity RSA Test example Alice,O=Xmlsecurity RSA Test,ST=England,C=UK"),
+ // CryptoAPI puts a space after comma, NSS does not...
+ infos[0].Signer->getSubjectName().replaceAll(", ", ","));
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFDoubleX509Data)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY)
+ + "02_doc_signed_by_attacker_manipulated.odt");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+ CPPUNIT_ASSERT_MESSAGE(
+ (OString::number(o3tl::to_underlying(nActual)).getStr()),
+ (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK));
+ uno::Sequence<security::DocumentSignatureInformation> const infos(
+ pObjectShell->GetDocumentSignatureInformation(false));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength());
+ // the signature in this manipulated document is technically valid but we can't tell who signed
+ // it, so make sure no misleading info is shown to the user
+ CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, infos[0].CertificateStatus);
+ CPPUNIT_ASSERT(!infos[0].Signer.is());
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFTripleX509Data)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY)
+ + "02_doc_signed_by_attacker_manipulated_triple.odt");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+ // here, libxmlsec will pick the 1st X509Data but signing key is the 2nd
+ CPPUNIT_ASSERT_EQUAL_MESSAGE((OString::number(o3tl::to_underlying(nActual)).getStr()),
+ SignatureState::BROKEN, nActual);
+ uno::Sequence<security::DocumentSignatureInformation> const infos(
+ pObjectShell->GetDocumentSignatureInformation(false));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength());
+ // the signature in this manipulated document is technically valid but we can't tell who signed
+ // it, so make sure no misleading info is shown to the user
+ CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, infos[0].CertificateStatus);
+ CPPUNIT_ASSERT(!infos[0].Signer.is());
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFMacroDoubleX509Data)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY)
+ + "02_doc_macros_signed_by_attacker_manipulated.odt");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ SignatureState nActual = pObjectShell->GetScriptingSignatureState();
+ CPPUNIT_ASSERT_MESSAGE(
+ (OString::number(o3tl::to_underlying(nActual)).getStr()),
+ (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK));
+ uno::Sequence<security::DocumentSignatureInformation> const infos(
+ pObjectShell->GetDocumentSignatureInformation(true));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength());
+ // the signature in this manipulated document is technically valid but we can't tell who signed
+ // it, so make sure no misleading info is shown to the user
+ CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, infos[0].CertificateStatus);
+ CPPUNIT_ASSERT(!infos[0].Signer.is());
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFDoubleX509Certificate)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY)
+ + "02_doc_signed_by_attacker_manipulated2.odt");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+ bool const nTemp((nActual == SignatureState::NOTVALIDATED
+ || nActual == SignatureState::OK
+#if defined(_WIN32)
+ // oddly BCryptVerifySignature returns STATUS_INVALID_SIGNATURE
+ // while the same succeeds with NSS _SGN_VerifyPKCS1DigestInfo
+ || nActual == SignatureState::BROKEN
+#endif
+ ));
+ CPPUNIT_ASSERT_MESSAGE((OString::number(o3tl::to_underlying(nActual)).getStr()), nTemp);
+ uno::Sequence<security::DocumentSignatureInformation> const infos(
+ pObjectShell->GetDocumentSignatureInformation(false));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength());
+ // the signature in this manipulated document is technically valid but we can't tell who signed
+ // it, so make sure no misleading info is shown to the user
+ CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, infos[0].CertificateStatus);
+ CPPUNIT_ASSERT(!infos[0].Signer.is());
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testDNCompatibility)
+{
+ OUString const msDN("CN=\"\"\"ABC\"\".\", O=\"Enterprise \"\"ABC\"\"\"");
+ OUString const nssDN("CN=\\\"ABC\\\".,O=Enterprise \\\"ABC\\\"");
+ // this is just the status quo, possibly either NSS or CryptoAPI might change
+ CPPUNIT_ASSERT(!xmlsecurity::EqualDistinguishedNames(msDN, nssDN, xmlsecurity::NOCOMPAT));
+ CPPUNIT_ASSERT(!xmlsecurity::EqualDistinguishedNames(nssDN, msDN, xmlsecurity::NOCOMPAT));
+ // with compat flag it should work, with the string one 2nd and the native one 1st
+#ifdef _WIN32
+ CPPUNIT_ASSERT(xmlsecurity::EqualDistinguishedNames(msDN, nssDN, xmlsecurity::COMPAT_2ND));
+#else
+ CPPUNIT_ASSERT(xmlsecurity::EqualDistinguishedNames(nssDN, msDN, xmlsecurity::COMPAT_2ND));
+#endif
+}
+
+/// Test a typical OOXML where a number of (but not all) streams are signed.
+CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLPartial)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "partial.docx");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ // This was SignatureState::BROKEN due to missing RelationshipTransform and SHA-256 support.
+ // We expect NOTVALIDATED_PARTIAL_OK in case the root CA is not imported on the system, and PARTIAL_OK otherwise, so accept both.
+ // But reject NOTVALIDATED, hiding incompleteness is not OK.
+ SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+ CPPUNIT_ASSERT_MESSAGE((OString::number(o3tl::to_underlying(nActual)).getStr()),
+ (nActual == SignatureState::NOTVALIDATED_PARTIAL_OK
+ || nActual == SignatureState::PARTIAL_OK));
+}
+
+/// Test a typical broken OOXML signature where one stream is corrupted.
+CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLBroken)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "bad.docx");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ // This was SignatureState::NOTVALIDATED/PARTIAL_OK as we did not validate manifest references.
+ CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::BROKEN),
+ static_cast<int>(pObjectShell->GetDocumentSignatureState()));
+}
+
+#if HAVE_FEATURE_PDFIMPORT
+
+/// Test a typical PDF where the signature is good.
+CPPUNIT_TEST_FIXTURE(SigningTest, testPDFGood)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "good.pdf");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ // We expect NOTVALIDATED in case the root CA is not imported on the system, and OK otherwise, so accept both.
+ SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ CPPUNIT_ASSERT_MESSAGE(
+ (OString::number(o3tl::to_underlying(nActual)).getStr()),
+ (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK));
+}
+
+/// Test a typical PDF where the signature is bad.
+CPPUNIT_TEST_FIXTURE(SigningTest, testPDFBad)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "bad.pdf");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::BROKEN),
+ static_cast<int>(pObjectShell->GetDocumentSignatureState()));
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testPDFHideAndReplace)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY)
+ + "hide-and-replace-shadow-file-signed-2.pdf");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 2 (BROKEN)
+ // - Actual : 6 (NOTVALIDATED_PARTIAL_OK)
+ // i.e. a non-commenting update after a signature was not marked as invalid.
+ CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::BROKEN),
+ static_cast<int>(pObjectShell->GetDocumentSignatureState()));
+}
+
+/// Test a typical PDF which is not signed.
+CPPUNIT_TEST_FIXTURE(SigningTest, testPDFNo)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "no.pdf");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::NOSIGNATURES),
+ static_cast<int>(pObjectShell->GetDocumentSignatureState()));
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testPDFAddVisibleSignature)
+{
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ {
+ return;
+ }
+
+ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with
+ // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin.
+ if (!IsDefaultDPI())
+ return;
+ // Given: copy the test document to a temporary file, as it'll be modified.
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ OUString aSourceURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "add-visible-signature.pdf";
+ OUString aURL = aTempFile.GetURL();
+ osl::File::RC eRet = osl::File::copy(aSourceURL, aURL);
+ CPPUNIT_ASSERT_EQUAL(osl::File::RC::E_None, eRet);
+
+ // Open it.
+ uno::Sequence<beans::PropertyValue> aArgs = { comphelper::makePropertyValue("ReadOnly", true) };
+ mxComponent = loadFromDesktop(aURL, "com.sun.star.drawing.DrawingDocument", aArgs);
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+
+ // Add a signature line.
+ uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
+ uno::Reference<drawing::XShape> xShape(
+ xFactory->createInstance("com.sun.star.drawing.GraphicObjectShape"), uno::UNO_QUERY);
+ xShape->setPosition(awt::Point(1000, 15000));
+ xShape->setSize(awt::Size(10000, 10000));
+ uno::Reference<drawing::XDrawPagesSupplier> xSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPages> xDrawPages = xSupplier->getDrawPages();
+ uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->getByIndex(0), uno::UNO_QUERY);
+ xDrawPage->add(xShape);
+
+ // Select it and assign a certificate.
+ uno::Reference<view::XSelectionSupplier> xSelectionSupplier(pBaseModel->getCurrentController(),
+ uno::UNO_QUERY);
+ xSelectionSupplier->select(uno::Any(xShape));
+ uno::Sequence<uno::Reference<security::XCertificate>> aCertificates
+ = mxSecurityContext->getSecurityEnvironment()->getPersonalCertificates();
+ if (!aCertificates.hasElements())
+ {
+ return;
+ }
+ SdrView* pView = SfxViewShell::Current()->GetDrawView();
+ svx::SignatureLineHelper::setShapeCertificate(pView, aCertificates[0]);
+
+ // When: do the actual signing.
+ pObjectShell->SignDocumentContentUsingCertificate(aCertificates[0]);
+
+ // Then: count the # of shapes on the signature widget/annotation.
+ SvFileStream aFile(aTempFile.GetURL(), StreamMode::READ);
+ SvMemoryStream aMemory;
+ aMemory.WriteStream(aFile);
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
+ = pPDFium->openDocument(aMemory.GetData(), aMemory.GetSize(), OString());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getAnnotationCount());
+ std::unique_ptr<vcl::pdf::PDFiumAnnotation> pAnnot = pPdfPage->getAnnotation(/*nIndex=*/0);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 4
+ // - Actual : 0
+ // i.e. the signature was there, but it was empty / not visible.
+ CPPUNIT_ASSERT_EQUAL(4, pAnnot->getObjectCount());
+}
+
+#endif
+
+CPPUNIT_TEST_FIXTURE(SigningTest, test96097Calc)
+{
+ createCalc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf96097.ods");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT_MESSAGE("Failed to access document base model", pBaseModel);
+
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pObjectShell);
+
+ SignatureState nActual = pObjectShell->GetScriptingSignatureState();
+ CPPUNIT_ASSERT_MESSAGE((OString::number(o3tl::to_underlying(nActual)).getStr()),
+ (nActual == SignatureState::OK || nActual == SignatureState::NOTVALIDATED
+ || nActual == SignatureState::INVALID));
+
+ uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY_THROW);
+
+ // Save a copy
+ utl::TempFile aTempFileSaveCopy;
+ aTempFileSaveCopy.EnableKillingFile();
+ uno::Sequence<beans::PropertyValue> descSaveACopy(comphelper::InitPropertySequence(
+ { { "SaveACopy", uno::Any(true) }, { "FilterName", uno::Any(OUString("calc8")) } }));
+ xDocStorable->storeToURL(aTempFileSaveCopy.GetURL(), descSaveACopy);
+
+ try
+ {
+ // Save As
+ utl::TempFile aTempFileSaveAs;
+ aTempFileSaveAs.EnableKillingFile();
+ uno::Sequence<beans::PropertyValue> descSaveAs(
+ comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("calc8")) } }));
+ xDocStorable->storeAsURL(aTempFileSaveAs.GetURL(), descSaveAs);
+ }
+ catch (...)
+ {
+ CPPUNIT_FAIL("Fail to save as the document");
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, test96097Doc)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf96097.odt");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+
+ SignatureState nActual = pObjectShell->GetScriptingSignatureState();
+ CPPUNIT_ASSERT_MESSAGE((OString::number(o3tl::to_underlying(nActual)).getStr()),
+ (nActual == SignatureState::OK || nActual == SignatureState::NOTVALIDATED
+ || nActual == SignatureState::INVALID));
+
+ uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY_THROW);
+
+ // Save a copy
+ utl::TempFile aTempFileSaveCopy;
+ aTempFileSaveCopy.EnableKillingFile();
+ uno::Sequence<beans::PropertyValue> descSaveACopy(comphelper::InitPropertySequence(
+ { { "SaveACopy", uno::Any(true) }, { "FilterName", uno::Any(OUString("writer8")) } }));
+ xDocStorable->storeToURL(aTempFileSaveCopy.GetURL(), descSaveACopy);
+
+ try
+ {
+ // Save As
+ utl::TempFile aTempFileSaveAs;
+ aTempFileSaveAs.EnableKillingFile();
+ uno::Sequence<beans::PropertyValue> descSaveAs(
+ comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } }));
+ xDocStorable->storeAsURL(aTempFileSaveAs.GetURL(), descSaveAs);
+ }
+ catch (...)
+ {
+ CPPUNIT_FAIL("Fail to save as the document");
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testXAdESNotype)
+{
+ // Create a working copy.
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ OUString aURL = aTempFile.GetURL();
+ CPPUNIT_ASSERT_EQUAL(
+ osl::File::RC::E_None,
+ osl::File::copy(m_directories.getURLFromSrc(DATA_DIRECTORY) + "notype-xades.odt", aURL));
+
+ // Read existing signature.
+ DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content);
+ CPPUNIT_ASSERT(aManager.init());
+ uno::Reference<embed::XStorage> xStorage
+ = comphelper::OStorageHelper::GetStorageOfFormatFromURL(
+ ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE);
+ CPPUNIT_ASSERT(xStorage.is());
+ aManager.setStore(xStorage);
+ aManager.getSignatureHelper().SetStorage(xStorage, "1.2");
+ aManager.read(/*bUseTempStream=*/false);
+
+ // Create a new signature.
+ uno::Reference<security::XCertificate> xCertificate
+ = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA);
+ if (!xCertificate.is())
+ return;
+ sal_Int32 nSecurityId;
+ aManager.add(xCertificate, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId,
+ /*bAdESCompliant=*/true);
+
+ // Write to storage.
+ aManager.read(/*bUseTempStream=*/true);
+ aManager.write(/*bXAdESCompliantIfODF=*/true);
+ uno::Reference<embed::XTransactedObject> xTransactedObject(xStorage, uno::UNO_QUERY);
+ xTransactedObject->commit();
+
+ // Parse the resulting XML.
+ uno::Reference<embed::XStorage> xMetaInf
+ = xStorage->openStorageElement("META-INF", embed::ElementModes::READ);
+ uno::Reference<io::XInputStream> xInputStream(
+ xMetaInf->openStreamElement("documentsignatures.xml", embed::ElementModes::READ),
+ uno::UNO_QUERY);
+ std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get());
+
+ // Without the accompanying fix in place, this test would have failed with "unexpected 'Type'
+ // attribute", i.e. the signature without such an attribute was not preserved correctly.
+ assertXPathNoAttribute(pXmlDoc,
+ "/odfds:document-signatures/dsig:Signature[1]/dsig:SignedInfo/"
+ "dsig:Reference[starts-with(@URI, '#idSignedProperties')]",
+ "Type");
+
+ // New signature always has the Type attribute.
+ assertXPath(pXmlDoc,
+ "/odfds:document-signatures/dsig:Signature[2]/dsig:SignedInfo/"
+ "dsig:Reference[starts-with(@URI, '#idSignedProperties')]",
+ "Type", "http://uri.etsi.org/01903#SignedProperties");
+}
+
+/// Creates a XAdES signature from scratch.
+CPPUNIT_TEST_FIXTURE(SigningTest, testXAdES)
+{
+ // Create an empty document, store it to a tempfile and load it as a storage.
+ createDoc(OUString());
+
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("writer8");
+ xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content);
+ CPPUNIT_ASSERT(aManager.init());
+ uno::Reference<embed::XStorage> xStorage
+ = comphelper::OStorageHelper::GetStorageOfFormatFromURL(
+ ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE);
+ CPPUNIT_ASSERT(xStorage.is());
+ aManager.setStore(xStorage);
+ aManager.getSignatureHelper().SetStorage(xStorage, "1.2");
+
+ // Create a signature.
+ uno::Reference<security::XCertificate> xCertificate
+ = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA);
+ if (!xCertificate.is())
+ return;
+ sal_Int32 nSecurityId;
+ aManager.add(xCertificate, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId,
+ /*bAdESCompliant=*/true);
+
+ // Write to storage.
+ aManager.read(/*bUseTempStream=*/true);
+ aManager.write(/*bXAdESCompliantIfODF=*/true);
+ uno::Reference<embed::XTransactedObject> xTransactedObject(xStorage, uno::UNO_QUERY);
+ xTransactedObject->commit();
+
+ // Parse the resulting XML.
+ uno::Reference<embed::XStorage> xMetaInf
+ = xStorage->openStorageElement("META-INF", embed::ElementModes::READ);
+ uno::Reference<io::XInputStream> xInputStream(
+ xMetaInf->openStreamElement("documentsignatures.xml", embed::ElementModes::READ),
+ uno::UNO_QUERY);
+ std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get());
+
+ // Assert that the digest algorithm is SHA-256 in the bAdESCompliant case, not SHA-1.
+ assertXPath(pXmlDoc,
+ "/odfds:document-signatures/dsig:Signature/dsig:SignedInfo/"
+ "dsig:Reference[@URI='content.xml']/dsig:DigestMethod",
+ "Algorithm", ALGO_XMLDSIGSHA256);
+
+ // Assert that the digest of the signing certificate is included.
+ assertXPath(pXmlDoc, "//xd:CertDigest", 1);
+
+ // Assert that the Type attribute is set on all URI's that start with #idSignedProperties
+ assertXPath(pXmlDoc, "//dsig:Reference[starts-with(@URI, '#idSignedProperties')]", "Type",
+ "http://uri.etsi.org/01903#SignedProperties");
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testSigningMultipleTimes_ODT)
+{
+ createDoc("");
+
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("writer8");
+ xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ {
+ DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content);
+ CPPUNIT_ASSERT(aManager.init());
+ uno::Reference<embed::XStorage> xStorage
+ = comphelper::OStorageHelper::GetStorageOfFormatFromURL(
+ ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE);
+ CPPUNIT_ASSERT(xStorage.is());
+ aManager.setStore(xStorage);
+ aManager.getSignatureHelper().SetStorage(xStorage, "1.2");
+
+ // Create a signature.
+ uno::Reference<security::XCertificate> xCertificate
+ = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA);
+
+ if (!xCertificate.is())
+ return;
+ sal_Int32 nSecurityId;
+ aManager.add(xCertificate, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId,
+ /*bAdESCompliant=*/true);
+
+ // Read back the signature and make sure that it's valid.
+ aManager.read(/*bUseTempStream=*/true);
+ {
+ std::vector<SignatureInformation>& rInformations
+ = aManager.getCurrentSignatureInformations();
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size());
+ CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED,
+ rInformations[0].nStatus);
+ }
+
+ aManager.add(xCertificate, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId,
+ /*bAdESCompliant=*/true);
+ aManager.read(/*bUseTempStream=*/true);
+ {
+ std::vector<SignatureInformation>& rInformations
+ = aManager.getCurrentSignatureInformations();
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), rInformations.size());
+ CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED,
+ rInformations[1].nStatus);
+ }
+
+ aManager.add(xCertificate, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId,
+ /*bAdESCompliant=*/true);
+ aManager.read(/*bUseTempStream=*/true);
+ {
+ std::vector<SignatureInformation>& rInformations
+ = aManager.getCurrentSignatureInformations();
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(3), rInformations.size());
+ CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED,
+ rInformations[2].nStatus);
+ }
+
+ aManager.write(/*bXAdESCompliantIfODF=*/true);
+ uno::Reference<embed::XTransactedObject> xTransactedObject(xStorage, uno::UNO_QUERY);
+ xTransactedObject->commit();
+ }
+
+ Scheduler::ProcessEventsToIdle();
+
+ createDoc(aTempFile.GetURL());
+
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ CPPUNIT_ASSERT_EQUAL(SignatureState::OK, pObjectShell->GetDocumentSignatureState());
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testSigningMultipleTimes_OOXML)
+{
+ createDoc("");
+
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("MS Word 2007 XML");
+ xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ {
+ DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content);
+ CPPUNIT_ASSERT(aManager.init());
+ uno::Reference<embed::XStorage> xStorage
+ = comphelper::OStorageHelper::GetStorageOfFormatFromURL(
+ ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE);
+ CPPUNIT_ASSERT(xStorage.is());
+ aManager.setStore(xStorage);
+ aManager.getSignatureHelper().SetStorage(xStorage, "1.2");
+
+ // Create a signature.
+ uno::Reference<security::XCertificate> xCertificate
+ = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::ECDSA);
+ if (!xCertificate.is())
+ return;
+
+ sal_Int32 nSecurityId;
+ aManager.add(xCertificate, mxSecurityContext, "", nSecurityId, /*bAdESCompliant=*/false);
+ aManager.read(/*bUseTempStream=*/true);
+ {
+ std::vector<SignatureInformation>& rInformations
+ = aManager.getCurrentSignatureInformations();
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size());
+ CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED,
+ rInformations[0].nStatus);
+ }
+
+ aManager.add(xCertificate, mxSecurityContext, "", nSecurityId, /*bAdESCompliant=*/false);
+ aManager.read(/*bUseTempStream=*/true);
+ {
+ std::vector<SignatureInformation>& rInformations
+ = aManager.getCurrentSignatureInformations();
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), rInformations.size());
+ CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED,
+ rInformations[1].nStatus);
+ }
+
+ aManager.add(xCertificate, mxSecurityContext, "", nSecurityId, /*bAdESCompliant=*/false);
+ aManager.read(/*bUseTempStream=*/true);
+ {
+ std::vector<SignatureInformation>& rInformations
+ = aManager.getCurrentSignatureInformations();
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(3), rInformations.size());
+ CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED,
+ rInformations[2].nStatus);
+ }
+
+ aManager.write(/*bXAdESCompliantIfODF=*/true);
+ uno::Reference<embed::XTransactedObject> xTransactedObject(xStorage, uno::UNO_QUERY);
+ xTransactedObject->commit();
+ }
+
+ Scheduler::ProcessEventsToIdle();
+
+ createDoc(aTempFile.GetURL());
+
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ CPPUNIT_ASSERT_EQUAL(SignatureState::PARTIAL_OK, pObjectShell->GetDocumentSignatureState());
+}
+
+/// Works with an existing good XAdES signature.
+CPPUNIT_TEST_FIXTURE(SigningTest, testXAdESGood)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "good-xades.odt");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ // We expect NOTVALIDATED in case the root CA is not imported on the system, and OK otherwise, so accept both.
+ SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+ CPPUNIT_ASSERT_MESSAGE(
+ (OString::number(o3tl::to_underlying(nActual)).getStr()),
+ (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK));
+}
+
+/// Test importing of signature line
+CPPUNIT_TEST_FIXTURE(SigningTest, testSignatureLineOOXML)
+{
+ // Given: A document (docx) with a signature line and a valid signature
+ uno::Reference<security::XDocumentDigitalSignatures> xSignatures(
+ security::DocumentDigitalSignatures::createDefault(
+ comphelper::getProcessComponentContext()));
+
+ uno::Reference<embed::XStorage> xStorage
+ = comphelper::OStorageHelper::GetStorageOfFormatFromURL(
+ ZIP_STORAGE_FORMAT_STRING,
+ m_directories.getURLFromSrc(DATA_DIRECTORY) + "signatureline.docx",
+ embed::ElementModes::READ);
+ CPPUNIT_ASSERT(xStorage.is());
+
+ uno::Sequence<security::DocumentSignatureInformation> xSignatureInfo
+ = xSignatures->verifyScriptingContentSignatures(xStorage,
+ uno::Reference<io::XInputStream>());
+
+ CPPUNIT_ASSERT(xSignatureInfo.getLength());
+
+ // The signature should have a valid signature, and signature line with two valid images
+ CPPUNIT_ASSERT(xSignatureInfo[0].SignatureIsValid);
+ CPPUNIT_ASSERT_EQUAL(OUString("{DEE0514B-13E8-4674-A831-46E3CDB18BB4}"),
+ xSignatureInfo[0].SignatureLineId);
+ CPPUNIT_ASSERT(xSignatureInfo[0].ValidSignatureLineImage.is());
+ CPPUNIT_ASSERT(xSignatureInfo[0].InvalidSignatureLineImage.is());
+}
+
+CPPUNIT_TEST_FIXTURE(SigningTest, testSignatureLineODF)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "signatureline.odt");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+
+ uno::Sequence<security::DocumentSignatureInformation> xSignatureInfo
+ = pObjectShell->GetDocumentSignatureInformation(false);
+
+ CPPUNIT_ASSERT(xSignatureInfo.getLength());
+
+ CPPUNIT_ASSERT(xSignatureInfo[0].SignatureIsValid);
+ CPPUNIT_ASSERT_EQUAL(OUString("{41CF56EE-331B-4125-97D8-2F5669DD3AAC}"),
+ xSignatureInfo[0].SignatureLineId);
+ CPPUNIT_ASSERT(xSignatureInfo[0].ValidSignatureLineImage.is());
+ CPPUNIT_ASSERT(xSignatureInfo[0].InvalidSignatureLineImage.is());
+}
+
+#if HAVE_FEATURE_GPGVERIFY
+/// Test a typical ODF where all streams are GPG-signed.
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFGoodGPG)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "goodGPG.odt");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ // Our local gpg config fully trusts the signing cert, so in
+ // contrast to the X509 test we can fail on NOTVALIDATED here
+ SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE((OString::number(o3tl::to_underlying(nActual)).getStr()),
+ SignatureState::OK, nActual);
+}
+
+/// Test a typical ODF where all streams are GPG-signed, but we don't trust the signature.
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFUntrustedGoodGPG)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "untrustedGoodGPG.odt");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ // Our local gpg config does _not_ trust the signing cert, so in
+ // contrast to the X509 test we can fail everything but
+ // NOTVALIDATED here
+ SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE((OString::number(o3tl::to_underlying(nActual)).getStr()),
+ SignatureState::NOTVALIDATED, nActual);
+}
+
+/// Test a typical broken ODF signature where one stream is corrupted.
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFBrokenStreamGPG)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "badStreamGPG.odt");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::BROKEN),
+ static_cast<int>(pObjectShell->GetDocumentSignatureState()));
+}
+
+/// Test a typical broken ODF signature where the XML dsig hash is corrupted.
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFBrokenDsigGPG)
+{
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "badDsigGPG.odt");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+ CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::BROKEN),
+ static_cast<int>(pObjectShell->GetDocumentSignatureState()));
+}
+
+#if HAVE_GPGCONF_SOCKETDIR
+
+/// Test loading an encrypted ODF document
+CPPUNIT_TEST_FIXTURE(SigningTest, testODFEncryptedGPG)
+{
+ // ODF1.2 + loext flavour
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "encryptedGPG.odt");
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+
+ // ODF1.3 flavour
+ createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "encryptedGPG_odf13.odt");
+ pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+
+ // export and import again
+ utl::TempFile aTempFile;
+ {
+ uno::Sequence<beans::PropertyValue> props(
+ comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } }));
+ uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY);
+ xDocStorable->storeToURL(aTempFile.GetURL(), props);
+ }
+ validate(aTempFile.GetFileName(), test::ODF);
+
+ createDoc(aTempFile.GetURL());
+ pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT(pBaseModel);
+ pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT(pObjectShell);
+
+ aTempFile.EnableKillingFile();
+}
+
+#endif
+
+SfxObjectShell* SigningTest::assertDocument(const ::CppUnit::SourceLine aSrcLine,
+ const OUString& rFilterName,
+ const SignatureState nDocSign,
+ const SignatureState nMacroSign,
+ const OUString& sVersion)
+{
+ std::string sPos = aSrcLine.fileName() + ":" + OString::number(aSrcLine.lineNumber()).getStr();
+
+ SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+ CPPUNIT_ASSERT_MESSAGE(sPos, pBaseModel);
+ SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+ CPPUNIT_ASSERT_MESSAGE(sPos, pObjectShell);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sPos, rFilterName,
+ pObjectShell->GetMedium()->GetFilter()->GetFilterName());
+ SignatureState nActual = pObjectShell->GetDocumentSignatureState();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sPos, nDocSign, nActual);
+ nActual = pObjectShell->GetScriptingSignatureState();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sPos, nMacroSign, nActual);
+
+ OUString aODFVersion;
+ uno::Reference<beans::XPropertySet> xPropSet(pObjectShell->GetStorage(), uno::UNO_QUERY_THROW);
+ xPropSet->getPropertyValue("Version") >>= aODFVersion;
+ CPPUNIT_ASSERT_EQUAL(sVersion, aODFVersion);
+
+ return pObjectShell;
+}
+
+/// Test if a macro signature from a OTT 1.2 template is preserved for ODT 1.2
+CPPUNIT_TEST_FIXTURE(SigningTest, testPreserveMacroTemplateSignature12_ODF)
+{
+ const OUString aURL(m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf42316_odt12.ott");
+ const OUString sLoadMessage = "loading failed: " + aURL;
+
+ // load the template as-is to validate signatures
+ mxComponent = loadFromDesktop(
+ aURL, OUString(), comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } }));
+
+ // we are a template, and have a valid document and macro signature
+ assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::OK, SignatureState::OK,
+ ODFVER_012_TEXT);
+
+ // create new document from template
+ mxComponent->dispose();
+ mxComponent = mxDesktop->loadComponentFromURL(aURL, "_default", 0, {});
+ CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(),
+ mxComponent.is());
+
+ // we are somehow a template (?), and have just a valid macro signature
+ assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES,
+ SignatureState::OK, ODFVER_012_TEXT);
+
+ // save as new ODT document
+ utl::TempFile aTempFileSaveAsODT;
+ aTempFileSaveAsODT.EnableKillingFile();
+ try
+ {
+ uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> descSaveAs(
+ comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } }));
+ xDocStorable->storeAsURL(aTempFileSaveAsODT.GetURL(), descSaveAs);
+ }
+ catch (...)
+ {
+ CPPUNIT_FAIL("Failed to save ODT document");
+ }
+
+ // save as new OTT template
+ utl::TempFile aTempFileSaveAsOTT;
+ aTempFileSaveAsOTT.EnableKillingFile();
+ try
+ {
+ uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> descSaveAs(comphelper::InitPropertySequence(
+ { { "FilterName", uno::Any(OUString("writer8_template")) } }));
+ xDocStorable->storeAsURL(aTempFileSaveAsOTT.GetURL(), descSaveAs);
+ }
+ catch (...)
+ {
+ CPPUNIT_FAIL("Failed to save OTT template");
+ }
+
+ // load the saved OTT template as-is to validate signatures
+ mxComponent->dispose();
+ mxComponent
+ = loadFromDesktop(aTempFileSaveAsOTT.GetURL(), OUString(),
+ comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } }));
+
+ // the loaded document is a OTT with a valid macro signature
+ assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES,
+ SignatureState::OK, ODFVER_013_TEXT);
+
+ // load saved ODT document
+ createDoc(aTempFileSaveAsODT.GetURL());
+
+ // the loaded document is a ODT with a macro signature
+ assertDocument(CPPUNIT_SOURCELINE(), "writer8", SignatureState::NOSIGNATURES,
+ SignatureState::OK, ODFVER_013_TEXT);
+
+ // save as new OTT template
+ utl::TempFile aTempFileSaveAsODT_OTT;
+ aTempFileSaveAsODT_OTT.EnableKillingFile();
+ try
+ {
+ uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> descSaveAs(comphelper::InitPropertySequence(
+ { { "FilterName", uno::Any(OUString("writer8_template")) } }));
+ xDocStorable->storeAsURL(aTempFileSaveAsODT_OTT.GetURL(), descSaveAs);
+ }
+ catch (...)
+ {
+ CPPUNIT_FAIL("Failed to save OTT template");
+ }
+
+ // load the template as-is to validate signatures
+ mxComponent->dispose();
+ mxComponent
+ = loadFromDesktop(aTempFileSaveAsODT_OTT.GetURL(), OUString(),
+ comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } }));
+
+ // the loaded document is a OTT with a valid macro signature
+ assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES,
+ SignatureState::OK, ODFVER_013_TEXT);
+}
+
+/// Test if a macro signature from an OTT 1.0 is dropped for ODT 1.2
+CPPUNIT_TEST_FIXTURE(SigningTest, testDropMacroTemplateSignature)
+{
+ const OUString aURL(m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf42316.ott");
+ const OUString sLoadMessage = "loading failed: " + aURL;
+
+ // load the template as-is to validate signatures
+ mxComponent = loadFromDesktop(
+ aURL, OUString(), comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } }));
+
+ // we are a template, and have a non-invalid macro signature
+ assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES,
+ SignatureState::NOTVALIDATED, OUString());
+
+ // create new document from template
+ mxComponent->dispose();
+ mxComponent = mxDesktop->loadComponentFromURL(aURL, "_default", 0, {});
+ CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(),
+ mxComponent.is());
+
+ // we are somehow a template (?), and have just a valid macro signature
+ assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES,
+ SignatureState::NOTVALIDATED, OUString());
+
+ // save as new ODT document
+ utl::TempFile aTempFileSaveAs;
+ aTempFileSaveAs.EnableKillingFile();
+ try
+ {
+ uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> descSaveAs(
+ comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } }));
+ xDocStorable->storeAsURL(aTempFileSaveAs.GetURL(), descSaveAs);
+ }
+ catch (...)
+ {
+ CPPUNIT_FAIL("Failed to save ODT document");
+ }
+
+ // load saved document
+ createDoc(aTempFileSaveAs.GetURL());
+
+ // the loaded document is a 1.2 ODT without any signatures
+ assertDocument(CPPUNIT_SOURCELINE(), "writer8", SignatureState::NOSIGNATURES,
+ SignatureState::NOSIGNATURES, ODFVER_013_TEXT);
+
+ // load the template as-is to validate signatures
+ mxComponent->dispose();
+ mxComponent = loadFromDesktop(
+ aURL, OUString(), comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } }));
+
+ // we are a template, and have a non-invalid macro signature
+ assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES,
+ SignatureState::NOTVALIDATED, OUString());
+
+ // save as new OTT template
+ utl::TempFile aTempFileSaveAsOTT;
+ aTempFileSaveAsOTT.EnableKillingFile();
+ try
+ {
+ uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> descSaveAs(comphelper::InitPropertySequence(
+ { { "FilterName", uno::Any(OUString("writer8_template")) } }));
+ xDocStorable->storeAsURL(aTempFileSaveAsOTT.GetURL(), descSaveAs);
+ }
+ catch (...)
+ {
+ CPPUNIT_FAIL("Failed to save OTT template");
+ }
+
+ // load the template as-is to validate signatures
+ mxComponent->dispose();
+ mxComponent
+ = loadFromDesktop(aTempFileSaveAsOTT.GetURL(), OUString(),
+ comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } }));
+
+ // the loaded document is a 1.2 OTT without any signatures
+ assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES,
+ SignatureState::NOSIGNATURES, ODFVER_013_TEXT);
+}
+
+/// Test if a macro signature from a OTT 1.0 template is preserved for ODT 1.0
+CPPUNIT_TEST_FIXTURE(SigningTest, testPreserveMacroTemplateSignature10)
+{
+ // set ODF version 1.0 / 1.1 as default
+ Resetter _([]() {
+ std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Save::ODF::DefaultVersion::set(3, pBatch);
+ return pBatch->commit();
+ });
+ std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Save::ODF::DefaultVersion::set(2, pBatch);
+ pBatch->commit();
+
+ const OUString aURL(m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf42316.ott");
+ const OUString sLoadMessage = "loading failed: " + aURL;
+
+ // load the template as-is to validate signatures
+ mxComponent = loadFromDesktop(
+ aURL, OUString(), comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } }));
+
+ // we are a template, and have a non-invalid macro signature
+ assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES,
+ SignatureState::NOTVALIDATED, OUString());
+
+ // create new document from template
+ mxComponent->dispose();
+ mxComponent = mxDesktop->loadComponentFromURL(aURL, "_default", 0, {});
+ CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(),
+ mxComponent.is());
+
+ // we are somehow a template (?), and have just a valid macro signature
+ assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES,
+ SignatureState::NOTVALIDATED, OUString());
+
+ // save as new ODT document
+ utl::TempFile aTempFileSaveAsODT;
+ aTempFileSaveAsODT.EnableKillingFile();
+ try
+ {
+ uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> descSaveAs(
+ comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } }));
+ xDocStorable->storeAsURL(aTempFileSaveAsODT.GetURL(), descSaveAs);
+ }
+ catch (...)
+ {
+ CPPUNIT_FAIL("Failed to save ODT document");
+ }
+
+ // save as new OTT template
+ utl::TempFile aTempFileSaveAsOTT;
+ aTempFileSaveAsOTT.EnableKillingFile();
+ try
+ {
+ uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> descSaveAs(comphelper::InitPropertySequence(
+ { { "FilterName", uno::Any(OUString("writer8_template")) } }));
+ xDocStorable->storeAsURL(aTempFileSaveAsOTT.GetURL(), descSaveAs);
+ }
+ catch (...)
+ {
+ CPPUNIT_FAIL("Failed to save OTT template");
+ }
+
+ // load the saved OTT template as-is to validate signatures
+ mxComponent->dispose();
+ mxComponent
+ = loadFromDesktop(aTempFileSaveAsOTT.GetURL(), OUString(),
+ comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } }));
+
+ // the loaded document is a OTT with a non-invalid macro signature
+ assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES,
+ SignatureState::NOTVALIDATED, OUString());
+
+ // load saved ODT document
+ createDoc(aTempFileSaveAsODT.GetURL());
+
+ // the loaded document is a ODT with a non-invalid macro signature
+ assertDocument(CPPUNIT_SOURCELINE(), "writer8", SignatureState::NOSIGNATURES,
+ SignatureState::NOTVALIDATED, OUString());
+
+ // save as new OTT template
+ utl::TempFile aTempFileSaveAsODT_OTT;
+ aTempFileSaveAsODT_OTT.EnableKillingFile();
+ try
+ {
+ uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> descSaveAs(comphelper::InitPropertySequence(
+ { { "FilterName", uno::Any(OUString("writer8_template")) } }));
+ xDocStorable->storeAsURL(aTempFileSaveAsODT_OTT.GetURL(), descSaveAs);
+ }
+ catch (...)
+ {
+ CPPUNIT_FAIL("Failed to save OTT template");
+ }
+
+ // load the template as-is to validate signatures
+ mxComponent->dispose();
+ mxComponent
+ = loadFromDesktop(aTempFileSaveAsODT_OTT.GetURL(), OUString(),
+ comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } }));
+
+ // the loaded document is a OTT with a non-invalid macro signature
+ assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES,
+ SignatureState::NOTVALIDATED, OUString());
+}
+
+#endif
+
+void SigningTest::registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx)
+{
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("odfds"),
+ BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("dsig"),
+ BAD_CAST("http://www.w3.org/2000/09/xmldsig#"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("xd"), BAD_CAST("http://uri.etsi.org/01903/v1.3.2#"));
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/qa/unit/signing/signing2.cxx b/xmlsecurity/qa/unit/signing/signing2.cxx
new file mode 100644
index 000000000..a436711ca
--- /dev/null
+++ b/xmlsecurity/qa/unit/signing/signing2.cxx
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <test/bootstrapfixture.hxx>
+#include <unotest/macros_test.hxx>
+#include <test/xmltesttools.hxx>
+
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/xml/crypto/SEInitializer.hpp>
+
+#include <comphelper/propertysequence.hxx>
+#include <unotools/tempfile.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <osl/file.hxx>
+#include <osl/process.h>
+#include <osl/thread.hxx>
+
+using namespace css;
+
+namespace
+{
+constexpr OUStringLiteral DATA_DIRECTORY = u"/xmlsecurity/qa/unit/signing/data/";
+}
+
+/// Testsuite for the document signing feature.
+class SigningTest2 : public test::BootstrapFixture, public unotest::MacrosTest, public XmlTestTools
+{
+protected:
+ uno::Reference<lang::XComponent> mxComponent;
+ uno::Reference<xml::crypto::XSEInitializer> mxSEInitializer;
+ uno::Reference<xml::crypto::XXMLSecurityContext> mxSecurityContext;
+
+public:
+ SigningTest2();
+ virtual void setUp() override;
+ virtual void tearDown() override;
+ void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) override;
+};
+
+SigningTest2::SigningTest2() {}
+
+void SigningTest2::setUp()
+{
+ test::BootstrapFixture::setUp();
+
+ // Initialize crypto after setting up the environment variables.
+ mxDesktop.set(frame::Desktop::create(mxComponentContext));
+}
+
+void SigningTest2::tearDown()
+{
+ if (mxComponent.is())
+ {
+ css::uno::Reference<css::util::XCloseable> closer(mxComponent, css::uno::UNO_QUERY);
+ if (closer.is())
+ {
+ closer->close(true);
+ }
+ mxComponent->dispose();
+ }
+
+ test::BootstrapFixture::tearDown();
+}
+
+/// Test if a macro signature from a ODF Database is preserved when saving
+CPPUNIT_TEST_FIXTURE(SigningTest2, testPreserveMacroSignatureODB)
+{
+ const OUString aURL(m_directories.getURLFromSrc(DATA_DIRECTORY) + "odb_signed_macros.odb");
+
+ // load the file
+ mxComponent = loadFromDesktop(aURL, "com.sun.star.sdb.OfficeDatabaseDocument");
+
+ // save as ODB
+ utl::TempFile aTempFileSaveAsODB;
+ aTempFileSaveAsODB.EnableKillingFile();
+ try
+ {
+ uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> descSaveAs(comphelper::InitPropertySequence(
+ { { "FilterName", uno::Any(OUString("StarOffice XML (Base)")) } }));
+ xDocStorable->storeAsURL(aTempFileSaveAsODB.GetURL(), descSaveAs);
+ }
+ catch (...)
+ {
+ CPPUNIT_FAIL("Failed to save ODB file");
+ }
+
+ // Parse the resulting XML.
+ uno::Reference<embed::XStorage> xStorage
+ = comphelper::OStorageHelper::GetStorageOfFormatFromURL(
+ ZIP_STORAGE_FORMAT_STRING, aTempFileSaveAsODB.GetURL(), embed::ElementModes::READ);
+ CPPUNIT_ASSERT(xStorage.is());
+ uno::Reference<embed::XStorage> xMetaInf
+ = xStorage->openStorageElement("META-INF", embed::ElementModes::READ);
+ uno::Reference<io::XInputStream> xInputStream(
+ xMetaInf->openStreamElement("macrosignatures.xml", embed::ElementModes::READ),
+ uno::UNO_QUERY);
+ std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get());
+
+ // Make sure the signature is still there
+ assertXPath(pXmlDoc, "//dsig:Signature", "Id",
+ "ID_00a7002f009000bc00ce00f7004400460080002f002e00e400e0003700df00e8");
+}
+
+void SigningTest2::registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx)
+{
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("odfds"),
+ BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("dsig"),
+ BAD_CAST("http://www.w3.org/2000/09/xmldsig#"));
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("xd"), BAD_CAST("http://uri.etsi.org/01903/v1.3.2#"));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/qa/unit/xmlsecurity-dialogs-test.cxx b/xmlsecurity/qa/unit/xmlsecurity-dialogs-test.cxx
new file mode 100644
index 000000000..b5b16c3a7
--- /dev/null
+++ b/xmlsecurity/qa/unit/xmlsecurity-dialogs-test.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+#include <test/screenshot_test.hxx>
+#include <vcl/abstdlg.hxx>
+
+using namespace ::com::sun::star;
+
+/// Test opening a dialog in xmlsecurity
+class XmlsecurityDialogsTest : public ScreenshotTest
+{
+private:
+ /// helper method to populate KnownDialogs, called in setUp(). Needs to be
+ /// written and has to add entries to KnownDialogs
+ virtual void registerKnownDialogsByID(mapType& rKnownDialogs) override;
+
+ /// dialog creation for known dialogs by ID. Has to be implemented for
+ /// each registered known dialog
+ virtual VclPtr<VclAbstractDialog> createDialogByID(sal_uInt32 nID) override;
+
+public:
+ XmlsecurityDialogsTest();
+
+ // try to open a dialog
+ void openAnyDialog();
+
+ CPPUNIT_TEST_SUITE(XmlsecurityDialogsTest);
+ CPPUNIT_TEST(openAnyDialog);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+XmlsecurityDialogsTest::XmlsecurityDialogsTest() {}
+
+void XmlsecurityDialogsTest::registerKnownDialogsByID(mapType& /*rKnownDialogs*/)
+{
+ // fill map of known dialogs
+}
+
+VclPtr<VclAbstractDialog> XmlsecurityDialogsTest::createDialogByID(sal_uInt32 /*nID*/)
+{
+ return nullptr;
+}
+
+void XmlsecurityDialogsTest::openAnyDialog()
+{
+ /// process input file containing the UXMLDescriptions of the dialogs to dump
+ processDialogBatchFile(u"xmlsecurity/qa/unit/data/xmlsecurity-dialogs-test.txt");
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(XmlsecurityDialogsTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/component/certificatecontainer.cxx b/xmlsecurity/source/component/certificatecontainer.cxx
new file mode 100644
index 000000000..e230c7b2c
--- /dev/null
+++ b/xmlsecurity/source/component/certificatecontainer.cxx
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <map>
+
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/security/XCertificateContainer.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <cppuhelper/supportsservice.hxx>
+#include <rtl/ref.hxx>
+
+#include <sal/config.h>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+
+namespace {
+
+class CertificateContainer
+ : public ::cppu::WeakImplHelper<css::lang::XServiceInfo, css::security::XCertificateContainer>
+{
+private:
+ typedef std::map<OUString, OUString> Map;
+ Map certMap;
+ Map certTrustMap;
+
+ static bool searchMap(const OUString& url, std::u16string_view certificate_name, Map& _certMap);
+ /// @throws css::uno::RuntimeException
+ bool isTemporaryCertificate(const OUString& url, std::u16string_view certificate_name);
+ /// @throws css::uno::RuntimeException
+ bool isCertificateTrust(const OUString& url, std::u16string_view certificate_name);
+
+public:
+ explicit CertificateContainer(const uno::Reference<uno::XComponentContext>&) {}
+ virtual sal_Bool SAL_CALL addCertificate(const OUString& url, const OUString& certificate_name,
+ sal_Bool trust) override;
+ virtual css::security::CertificateContainerStatus SAL_CALL
+ hasCertificate(const OUString& url, const OUString& certificate_name) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+}
+
+bool
+CertificateContainer::searchMap( const OUString & url, std::u16string_view certificate_name, Map &_certMap )
+{
+ Map::iterator p = _certMap.find(url);
+
+ bool ret = false;
+
+ while( p != _certMap.end() )
+ {
+ ret = (*p).second == certificate_name;
+ if( ret )
+ break;
+ ++p;
+ }
+
+ return ret;
+}
+
+bool
+CertificateContainer::isTemporaryCertificate ( const OUString & url, std::u16string_view certificate_name )
+{
+ return searchMap( url, certificate_name, certMap);
+}
+
+bool
+CertificateContainer::isCertificateTrust ( const OUString & url, std::u16string_view certificate_name )
+{
+ return searchMap( url, certificate_name, certTrustMap);
+}
+
+sal_Bool
+CertificateContainer::addCertificate( const OUString & url, const OUString & certificate_name, sal_Bool trust )
+{
+ certMap.emplace( url, certificate_name );
+
+ //remember that the cert is trusted
+ if (trust)
+ certTrustMap.emplace( url, certificate_name );
+
+ return true;
+}
+
+::security::CertificateContainerStatus
+CertificateContainer::hasCertificate( const OUString & url, const OUString & certificate_name )
+{
+ if ( isTemporaryCertificate( url, certificate_name ) )
+ {
+ if ( isCertificateTrust( url, certificate_name ) )
+ return security::CertificateContainerStatus_TRUSTED;
+ else
+ return security::CertificateContainerStatus_UNTRUSTED;
+ } else
+ {
+ return security::CertificateContainerStatus_NOCERT;
+ }
+}
+
+OUString SAL_CALL
+CertificateContainer::getImplementationName( )
+{
+ return "com.sun.star.security.CertificateContainer";
+}
+
+sal_Bool SAL_CALL
+CertificateContainer::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService( this, ServiceName );
+}
+
+Sequence< OUString > SAL_CALL
+CertificateContainer::getSupportedServiceNames( )
+{
+ return { "com.sun.star.security.CertificateContainer" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_security_CertificateContainer_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ static rtl::Reference<CertificateContainer> gContainer = new CertificateContainer(context);
+ return cppu::acquire(gContainer.get());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx
new file mode 100644
index 000000000..990fa5dea
--- /dev/null
+++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx
@@ -0,0 +1,900 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <resourcemanager.hxx>
+
+#include <certificate.hxx>
+#include <certificatechooser.hxx>
+#include <certificateviewer.hxx>
+#include <digitalsignaturesdialog.hxx>
+#include <macrosecurity.hxx>
+#include <biginteger.hxx>
+#include <strings.hrc>
+#include <pdfsignaturehelper.hxx>
+#include <sax/tools/converter.hxx>
+
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/StorageFormats.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/ucb/XContent.hpp>
+#include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include <com/sun/star/ucb/XCommandProcessor.hpp>
+#include <com/sun/star/ucb/Command.hpp>
+#include <com/sun/star/uno/SecurityException.hpp>
+#include <vcl/weld.hxx>
+#include <vcl/svapp.hxx>
+#include <tools/date.hxx>
+#include <tools/time.hxx>
+#include <unotools/securityoptions.hxx>
+#include <com/sun/star/security/CertificateValidity.hpp>
+#include <com/sun/star/security/CertificateKind.hpp>
+#include <comphelper/base64.hxx>
+#include <comphelper/documentconstants.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/xmlsechelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <sal/log.hxx>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
+#include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp>
+#include <sfx2/digitalsignatures.hxx>
+
+#include <map>
+
+using namespace css;
+using namespace css::uno;
+using namespace css::lang;
+using namespace css::security;
+using namespace css::xml::crypto;
+
+namespace {
+class DocumentDigitalSignatures
+ : public cppu::WeakImplHelper<css::security::XDocumentDigitalSignatures,
+ css::lang::XInitialization, css::lang::XServiceInfo>,
+ public sfx2::DigitalSignatures
+{
+private:
+ css::uno::Reference<css::uno::XComponentContext> mxCtx;
+ css::uno::Reference<css::awt::XWindow> mxParentWindow;
+
+ /// will be set by XInitialization. If not we assume true. false means an earlier version (whatever that means,
+ /// this is a string, not a boolean).
+ /// Note that the code talks about "ODF version" even if this class is also used to sign OOXML.
+ OUString m_sODFVersion;
+ /// The number of arguments which were passed in XInitialization::initialize
+ int m_nArgumentsCount;
+ /// Indicates if the document already contains a document signature
+ bool m_bHasDocumentSignature;
+
+ /// @throws css::uno::RuntimeException
+ bool ImplViewSignatures(const css::uno::Reference<css::embed::XStorage>& rxStorage,
+ const css::uno::Reference<css::io::XStream>& xSignStream,
+ DocumentSignatureMode eMode, bool bReadOnly);
+ /// @throws css::uno::RuntimeException
+ void ImplViewSignatures(const css::uno::Reference<css::embed::XStorage>& rxStorage,
+ const css::uno::Reference<css::io::XInputStream>& xSignStream,
+ DocumentSignatureMode eMode, bool bReadOnly);
+ /// @throws css::uno::RuntimeException
+ css::uno::Sequence<css::security::DocumentSignatureInformation>
+ ImplVerifySignatures(const css::uno::Reference<css::embed::XStorage>& rxStorage,
+ const ::com::sun::star::uno::Reference<css::io::XInputStream>& xSignStream,
+ DocumentSignatureMode eMode);
+
+ css::uno::Sequence<css::uno::Reference<css::security::XCertificate>>
+ chooseCertificatesImpl(std::map<OUString, OUString>& rProperties, const UserAction eAction,
+ const CertificateKind certificateKind=CertificateKind_NONE);
+
+ bool
+ signWithCertificateImpl(const uno::Reference<frame::XModel>& /*xModel*/,
+ css::uno::Reference<css::security::XCertificate> const& xCertificate,
+ css::uno::Reference<css::embed::XStorage> const& xStorage,
+ css::uno::Reference<css::io::XStream> const& xStream,
+ DocumentSignatureMode eMode);
+
+public:
+ explicit DocumentDigitalSignatures(
+ const css::uno::Reference<css::uno::XComponentContext>& rxCtx);
+
+ //XInitialization
+ void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& aArguments) override;
+
+ OUString SAL_CALL getImplementationName() override;
+
+ sal_Bool SAL_CALL supportsService(OUString const& ServiceName) override;
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ // XDocumentDigitalSignatures
+ sal_Bool SAL_CALL
+ signDocumentContent(const css::uno::Reference<css::embed::XStorage>& xStorage,
+ const css::uno::Reference<css::io::XStream>& xSignStream) override;
+ sal_Bool SAL_CALL signSignatureLine(
+ const css::uno::Reference<css::embed::XStorage>& Storage,
+ const css::uno::Reference<css::io::XStream>& xSignStream, const OUString& aSignatureLineId,
+ const Reference<css::security::XCertificate>& xCertificate,
+ const Reference<css::graphic::XGraphic>& xValidGraphic,
+ const Reference<css::graphic::XGraphic>& xInvalidGraphic,
+ const OUString& aComment) override;
+ css::uno::Sequence<css::security::DocumentSignatureInformation>
+ SAL_CALL verifyDocumentContentSignatures(
+ const css::uno::Reference<css::embed::XStorage>& xStorage,
+ const css::uno::Reference<css::io::XInputStream>& xSignInStream) override;
+ void SAL_CALL showDocumentContentSignatures(
+ const css::uno::Reference<css::embed::XStorage>& xStorage,
+ const css::uno::Reference<css::io::XInputStream>& xSignInStream) override;
+ OUString SAL_CALL getDocumentContentSignatureDefaultStreamName() override;
+ sal_Bool SAL_CALL
+ signScriptingContent(const css::uno::Reference<css::embed::XStorage>& xStorage,
+ const css::uno::Reference<css::io::XStream>& xSignStream) override;
+ css::uno::Sequence<css::security::DocumentSignatureInformation>
+ SAL_CALL verifyScriptingContentSignatures(
+ const css::uno::Reference<css::embed::XStorage>& xStorage,
+ const css::uno::Reference<css::io::XInputStream>& xSignInStream) override;
+ void SAL_CALL showScriptingContentSignatures(
+ const css::uno::Reference<css::embed::XStorage>& xStorage,
+ const css::uno::Reference<css::io::XInputStream>& xSignInStream) override;
+ OUString SAL_CALL getScriptingContentSignatureDefaultStreamName() override;
+ sal_Bool SAL_CALL
+ signPackage(const css::uno::Reference<css::embed::XStorage>& Storage,
+ const css::uno::Reference<css::io::XStream>& xSignStream) override;
+ css::uno::Sequence<css::security::DocumentSignatureInformation>
+ SAL_CALL verifyPackageSignatures(
+ const css::uno::Reference<css::embed::XStorage>& Storage,
+ const css::uno::Reference<css::io::XInputStream>& xSignInStream) override;
+ void SAL_CALL
+ showPackageSignatures(const css::uno::Reference<css::embed::XStorage>& xStorage,
+ const css::uno::Reference<css::io::XInputStream>& xSignInStream) override;
+ OUString SAL_CALL getPackageSignatureDefaultStreamName() override;
+ void SAL_CALL
+ showCertificate(const css::uno::Reference<css::security::XCertificate>& Certificate) override;
+ void SAL_CALL manageTrustedSources() override;
+ sal_Bool SAL_CALL
+ isAuthorTrusted(const css::uno::Reference<css::security::XCertificate>& Author) override;
+ sal_Bool SAL_CALL isLocationTrusted(const OUString& Location) override;
+ void SAL_CALL addAuthorToTrustedSources(
+ const css::uno::Reference<css::security::XCertificate>& Author) override;
+ void SAL_CALL addLocationToTrustedSources(const OUString& Location) override;
+
+ css::uno::Reference<css::security::XCertificate>
+ SAL_CALL chooseCertificate(OUString& rDescription) override;
+ css::uno::Reference<css::security::XCertificate>
+ SAL_CALL chooseSigningCertificate(OUString& rDescription) override;
+ css::uno::Reference<css::security::XCertificate>
+ SAL_CALL selectSigningCertificate(OUString& rDescription) override;
+ css::uno::Reference<css::security::XCertificate>
+ SAL_CALL selectSigningCertificateWithType(const CertificateKind certificateKind,
+ OUString& rDescription) override;
+ css::uno::Sequence<css::uno::Reference<css::security::XCertificate>>
+ SAL_CALL chooseEncryptionCertificate() override;
+ css::uno::Reference<css::security::XCertificate> SAL_CALL chooseCertificateWithProps(
+ css::uno::Sequence<::com::sun::star::beans::PropertyValue>& Properties) override;
+
+ sal_Bool SAL_CALL signDocumentWithCertificate(
+ css::uno::Reference<css::security::XCertificate> const & xCertificate,
+ css::uno::Reference<css::embed::XStorage> const & xStoragexStorage,
+ css::uno::Reference<css::io::XStream> const & xStream) override;
+
+ sal_Bool SAL_CALL signPackageWithCertificate(
+ css::uno::Reference<css::security::XCertificate> const& xCertificate,
+ css::uno::Reference<css::embed::XStorage> const& xStoragexStorage,
+ css::uno::Reference<css::io::XStream> const& xStream) override;
+
+ sal_Bool SAL_CALL signScriptingContentWithCertificate(
+ css::uno::Reference<css::security::XCertificate> const& xCertificate,
+ css::uno::Reference<css::embed::XStorage> const& xStoragexStorage,
+ css::uno::Reference<css::io::XStream> const& xStream) override;
+
+ void SAL_CALL setParentWindow(const css::uno::Reference<css::awt::XWindow>& rParentwindow) override
+ {
+ mxParentWindow = rParentwindow;
+ }
+
+ /// See sfx2::DigitalSignatures::SignModelWithCertificate().
+ bool
+ SignModelWithCertificate(const css::uno::Reference<css::frame::XModel>& xModel,
+ const css::uno::Reference<css::security::XCertificate>& xCertificate,
+ const css::uno::Reference<css::embed::XStorage>& xStorage,
+ const css::uno::Reference<css::io::XStream>& xStream) override;
+};
+
+}
+
+DocumentDigitalSignatures::DocumentDigitalSignatures( const Reference< XComponentContext >& rxCtx ):
+ mxCtx(rxCtx),
+ m_sODFVersion(ODFVER_013_TEXT),
+ m_nArgumentsCount(0),
+ m_bHasDocumentSignature(false)
+{
+}
+
+void DocumentDigitalSignatures::initialize( const Sequence< Any >& aArguments)
+{
+ if (aArguments.getLength() > 2)
+ throw css::lang::IllegalArgumentException(
+ "DocumentDigitalSignatures::initialize requires zero, one, or two arguments",
+ static_cast<XInitialization*>(this), 0);
+
+ m_nArgumentsCount = aArguments.getLength();
+
+ if (!aArguments.hasElements())
+ return;
+
+ if (!(aArguments[0] >>= m_sODFVersion))
+ throw css::lang::IllegalArgumentException(
+ "DocumentDigitalSignatures::initialize: the first arguments must be a string",
+ static_cast<XInitialization*>(this), 0);
+
+ if (aArguments.getLength() == 2
+ && !(aArguments[1] >>= m_bHasDocumentSignature))
+ throw css::lang::IllegalArgumentException(
+ "DocumentDigitalSignatures::initialize: the second arguments must be a bool",
+ static_cast<XInitialization*>(this), 1);
+
+ //the Version is supported as of ODF1.2, so for and 1.1 document or older we will receive the
+ //an empty string. In this case we set it to ODFVER_010_TEXT. Then we can later check easily
+ //if initialize was called. Only then m_sODFVersion.getLength() is greater than 0
+ if (m_sODFVersion.isEmpty())
+ m_sODFVersion = ODFVER_010_TEXT;
+}
+
+OUString DocumentDigitalSignatures::getImplementationName()
+{
+ return "com.sun.star.security.DocumentDigitalSignatures";
+}
+
+sal_Bool DocumentDigitalSignatures::supportsService(
+ OUString const & ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+css::uno::Sequence<OUString>
+DocumentDigitalSignatures::getSupportedServiceNames()
+{
+ Sequence<OUString> aRet{ "com.sun.star.security.DocumentDigitalSignatures" };
+ return aRet;
+}
+
+sal_Bool DocumentDigitalSignatures::signDocumentContent(
+ const Reference< css::embed::XStorage >& rxStorage,
+ const Reference< css::io::XStream >& xSignStream)
+{
+ OSL_ENSURE(!m_sODFVersion.isEmpty(), "DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
+ return ImplViewSignatures( rxStorage, xSignStream, DocumentSignatureMode::Content, false );
+}
+
+sal_Bool DocumentDigitalSignatures::signSignatureLine(
+ const Reference<css::embed::XStorage>& rxStorage,
+ const Reference<css::io::XStream>& xSignStream,
+ const OUString& aSignatureLineId,
+ const Reference<css::security::XCertificate>& xCertificate,
+ const Reference<css::graphic::XGraphic>& xValidGraphic,
+ const Reference<css::graphic::XGraphic>& xInvalidGraphic,
+ const OUString& aComment)
+{
+ OSL_ENSURE(!m_sODFVersion.isEmpty(),
+ "DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
+
+ DocumentSignatureManager aSignatureManager(mxCtx, DocumentSignatureMode::Content);
+
+ if (!aSignatureManager.init())
+ return false;
+
+ aSignatureManager.setStore(rxStorage);
+ aSignatureManager.getSignatureHelper().SetStorage(rxStorage, m_sODFVersion);
+ aSignatureManager.setSignatureStream(xSignStream);
+
+ Reference<XXMLSecurityContext> xSecurityContext;
+ Reference<XServiceInfo> xServiceInfo(xCertificate, UNO_QUERY);
+ if (xServiceInfo->getImplementationName()
+ == "com.sun.star.xml.security.gpg.XCertificate_GpgImpl")
+ xSecurityContext = aSignatureManager.getGpgSecurityContext();
+ else
+ xSecurityContext = aSignatureManager.getSecurityContext();
+
+ sal_Int32 nSecurityId;
+ bool bSuccess = aSignatureManager.add(xCertificate, xSecurityContext, aComment, nSecurityId,
+ true, aSignatureLineId, xValidGraphic, xInvalidGraphic);
+ if (!bSuccess)
+ return false;
+
+ // Need to have this to verify the signature
+ aSignatureManager.read(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false);
+ aSignatureManager.write(true);
+
+ if (rxStorage.is() && !xSignStream.is())
+ {
+ uno::Reference<embed::XTransactedObject> xTrans(rxStorage, uno::UNO_QUERY);
+ xTrans->commit();
+ }
+
+ return true;
+}
+
+Sequence< css::security::DocumentSignatureInformation >
+DocumentDigitalSignatures::verifyDocumentContentSignatures(
+ const Reference< css::embed::XStorage >& rxStorage,
+ const Reference< css::io::XInputStream >& xSignInStream )
+{
+ OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
+ return ImplVerifySignatures( rxStorage, xSignInStream, DocumentSignatureMode::Content );
+}
+
+void DocumentDigitalSignatures::showDocumentContentSignatures(
+ const Reference< css::embed::XStorage >& rxStorage,
+ const Reference< css::io::XInputStream >& xSignInStream )
+{
+ OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
+ ImplViewSignatures( rxStorage, xSignInStream, DocumentSignatureMode::Content, true );
+}
+
+OUString DocumentDigitalSignatures::getDocumentContentSignatureDefaultStreamName()
+{
+ return DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName();
+}
+
+sal_Bool DocumentDigitalSignatures::signScriptingContent(
+ const Reference< css::embed::XStorage >& rxStorage,
+ const Reference< css::io::XStream >& xSignStream )
+{
+ OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
+ OSL_ENSURE(m_nArgumentsCount == 2, "DocumentDigitalSignatures: Service was not initialized properly");
+ return ImplViewSignatures( rxStorage, xSignStream, DocumentSignatureMode::Macros, false );
+}
+
+Sequence< css::security::DocumentSignatureInformation >
+DocumentDigitalSignatures::verifyScriptingContentSignatures(
+ const Reference< css::embed::XStorage >& rxStorage,
+ const Reference< css::io::XInputStream >& xSignInStream )
+{
+ OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
+ return ImplVerifySignatures( rxStorage, xSignInStream, DocumentSignatureMode::Macros );
+}
+
+void DocumentDigitalSignatures::showScriptingContentSignatures(
+ const Reference< css::embed::XStorage >& rxStorage,
+ const Reference< css::io::XInputStream >& xSignInStream )
+{
+ OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
+ ImplViewSignatures( rxStorage, xSignInStream, DocumentSignatureMode::Macros, true );
+}
+
+OUString DocumentDigitalSignatures::getScriptingContentSignatureDefaultStreamName()
+{
+ return DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName();
+}
+
+
+sal_Bool DocumentDigitalSignatures::signPackage(
+ const Reference< css::embed::XStorage >& rxStorage,
+ const Reference< css::io::XStream >& xSignStream )
+{
+ OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
+ return ImplViewSignatures( rxStorage, xSignStream, DocumentSignatureMode::Package, false );
+}
+
+Sequence< css::security::DocumentSignatureInformation >
+DocumentDigitalSignatures::verifyPackageSignatures(
+ const Reference< css::embed::XStorage >& rxStorage,
+ const Reference< css::io::XInputStream >& xSignInStream )
+{
+ OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
+ return ImplVerifySignatures( rxStorage, xSignInStream, DocumentSignatureMode::Package );
+}
+
+void DocumentDigitalSignatures::showPackageSignatures(
+ const Reference< css::embed::XStorage >& rxStorage,
+ const Reference< css::io::XInputStream >& xSignInStream )
+{
+ OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
+ ImplViewSignatures( rxStorage, xSignInStream, DocumentSignatureMode::Package, true );
+}
+
+OUString DocumentDigitalSignatures::getPackageSignatureDefaultStreamName( )
+{
+ return DocumentSignatureHelper::GetPackageSignatureDefaultStreamName();
+}
+
+
+void DocumentDigitalSignatures::ImplViewSignatures(
+ const Reference< css::embed::XStorage >& rxStorage,
+ const Reference< css::io::XInputStream >& xSignStream,
+ DocumentSignatureMode eMode, bool bReadOnly )
+{
+ Reference< io::XStream > xStream;
+ if ( xSignStream.is() )
+ xStream.set( xSignStream, UNO_QUERY );
+ ImplViewSignatures( rxStorage, xStream, eMode, bReadOnly );
+}
+
+bool DocumentDigitalSignatures::ImplViewSignatures(
+ const Reference< css::embed::XStorage >& rxStorage, const Reference< css::io::XStream >& xSignStream,
+ DocumentSignatureMode eMode, bool bReadOnly )
+{
+ bool bChanges = false;
+ auto xSignaturesDialog = std::make_shared<DigitalSignaturesDialog>(
+ Application::GetFrameWeld(mxParentWindow), mxCtx, eMode, bReadOnly, m_sODFVersion,
+ m_bHasDocumentSignature);
+ bool bInit = xSignaturesDialog->Init();
+ SAL_WARN_IF( !bInit, "xmlsecurity.comp", "Error initializing security context!" );
+ if ( bInit )
+ {
+ xSignaturesDialog->SetStorage(rxStorage);
+
+ xSignaturesDialog->SetSignatureStream( xSignStream );
+
+ if (bReadOnly)
+ {
+ xSignaturesDialog->beforeRun();
+ weld::DialogController::runAsync(xSignaturesDialog, [] (sal_Int32) {});
+ return false;
+ }
+ else if (xSignaturesDialog->run() == RET_OK)
+ {
+ if (xSignaturesDialog->SignaturesChanged())
+ {
+ bChanges = true;
+ // If we have a storage and no stream, we are responsible for commit
+ if ( rxStorage.is() && !xSignStream.is() )
+ {
+ uno::Reference< embed::XTransactedObject > xTrans( rxStorage, uno::UNO_QUERY );
+ xTrans->commit();
+ }
+ }
+ }
+ }
+ else
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(Application::GetFrameWeld(mxParentWindow),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ XsResId(RID_XMLSECWB_NO_MOZILLA_PROFILE)));
+ xBox->run();
+ }
+
+ return bChanges;
+}
+
+Sequence< css::security::DocumentSignatureInformation >
+DocumentDigitalSignatures::ImplVerifySignatures(
+ const Reference< css::embed::XStorage >& rxStorage,
+ const Reference< css::io::XInputStream >& xSignStream, DocumentSignatureMode eMode )
+{
+ DocumentSignatureManager aSignatureManager(mxCtx, eMode);
+
+ bool bInit = aSignatureManager.init();
+
+ SAL_WARN_IF(!bInit, "xmlsecurity.comp", "Error initializing security context!");
+
+ if (!bInit)
+ return {};
+
+ if (!rxStorage.is())
+ {
+ if (xSignStream.is())
+ {
+ // Something not ZIP-based, try PDF.
+ PDFSignatureHelper& rSignatureHelper = aSignatureManager.getPDFSignatureHelper();
+ if (rSignatureHelper.ReadAndVerifySignature(xSignStream))
+ return rSignatureHelper.GetDocumentSignatureInformations(aSignatureManager.getSecurityEnvironment());
+ }
+
+ SAL_WARN( "xmlsecurity.comp", "Error, no XStorage provided");
+ return Sequence<css::security::DocumentSignatureInformation>();
+ }
+ // First check for the InputStream, to avoid unnecessary initialization of the security environment...
+ SignatureStreamHelper aStreamHelper;
+ Reference< io::XInputStream > xInputStream = xSignStream;
+
+ if ( !xInputStream.is() )
+ {
+ aStreamHelper = DocumentSignatureHelper::OpenSignatureStream( rxStorage, embed::ElementModes::READ, eMode );
+ if ( aStreamHelper.xSignatureStream.is() )
+ xInputStream.set( aStreamHelper.xSignatureStream, UNO_QUERY );
+ }
+
+ if (!xInputStream.is() && aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
+ return {};
+
+
+ XMLSignatureHelper& rSignatureHelper = aSignatureManager.getSignatureHelper();
+ rSignatureHelper.SetStorage(rxStorage, m_sODFVersion);
+
+ rSignatureHelper.StartMission(aSignatureManager.getSecurityContext());
+
+ if (xInputStream.is())
+ rSignatureHelper.ReadAndVerifySignature(xInputStream);
+ else if (aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML)
+ rSignatureHelper.ReadAndVerifySignatureStorage(aStreamHelper.xSignatureStorage);
+
+ rSignatureHelper.EndMission();
+
+ uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = aSignatureManager.getSecurityEnvironment();
+ uno::Reference<xml::crypto::XSecurityEnvironment> xGpgSecEnv = aSignatureManager.getGpgSecurityEnvironment();
+
+ SignatureInformations aSignInfos = rSignatureHelper.GetSignatureInformations();
+ int nInfos = aSignInfos.size();
+ Sequence< css::security::DocumentSignatureInformation > aInfos(nInfos);
+ css::security::DocumentSignatureInformation* arInfos = aInfos.getArray();
+
+ for (int n = 0; n < nInfos; ++n)
+ {
+ DocumentSignatureAlgorithm mode
+ = DocumentSignatureHelper::getDocumentAlgorithm(m_sODFVersion, aSignInfos[n]);
+ const std::vector<OUString> aElementsToBeVerified
+ = DocumentSignatureHelper::CreateElementList(rxStorage, eMode, mode);
+
+ const SignatureInformation& rInfo = aSignInfos[n];
+ css::security::DocumentSignatureInformation& rSigInfo = arInfos[n];
+
+ if (!rInfo.X509Datas.empty()) // X.509
+ {
+ std::vector<uno::Reference<XCertificate>> certs(
+ rSignatureHelper.CheckAndUpdateSignatureInformation(
+ xSecEnv, rInfo));
+ if (certs.empty())
+ {
+ rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID;
+ }
+ else
+ {
+ rSigInfo.Signer = certs.back();
+ // get only intermediates
+ certs.pop_back();
+ // On Windows checking the certificate path is buggy. It does name matching (issuer, subject name)
+ // to find the parent certificate. It does not take into account that there can be several certificates
+ // with the same subject name.
+ try
+ {
+ rSigInfo.CertificateStatus = xSecEnv->verifyCertificate(
+ rSigInfo.Signer, comphelper::containerToSequence(certs));
+ }
+ catch (SecurityException&)
+ {
+ SAL_WARN("xmlsecurity.comp", "Verification of certificate failed");
+ rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID;
+ }
+ }
+ }
+ else if (!rInfo.ouGpgCertificate.isEmpty() && xGpgSecEnv.is()) // GPG
+ {
+ // TODO not ideal to retrieve cert by keyID, might
+ // collide, or PGPKeyID format might change - can't we
+ // keep the xCert itself in rInfo?
+ rSigInfo.Signer = xGpgSecEnv->getCertificate(
+ rInfo.ouGpgKeyID, xmlsecurity::numericStringToBigInteger(u""));
+ rSigInfo.CertificateStatus = xGpgSecEnv->verifyCertificate(
+ rSigInfo.Signer, Sequence<Reference<css::security::XCertificate>>());
+ }
+
+ // Time support again (#i38744#)
+ Date aDate(rInfo.stDateTime.Day, rInfo.stDateTime.Month, rInfo.stDateTime.Year);
+ tools::Time aTime(rInfo.stDateTime.Hours, rInfo.stDateTime.Minutes,
+ rInfo.stDateTime.Seconds, rInfo.stDateTime.NanoSeconds);
+ rSigInfo.SignatureDate = aDate.GetDate();
+ rSigInfo.SignatureTime = aTime.GetTime() / tools::Time::nanoPerCenti;
+
+ rSigInfo.SignatureIsValid
+ = (rInfo.nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
+
+ // Signature line info (ID + Images)
+ if (!rInfo.ouSignatureLineId.isEmpty())
+ rSigInfo.SignatureLineId = rInfo.ouSignatureLineId;
+
+ if (rInfo.aValidSignatureImage.is())
+ rSigInfo.ValidSignatureLineImage = rInfo.aValidSignatureImage;
+
+ if (rInfo.aInvalidSignatureImage.is())
+ rSigInfo.InvalidSignatureLineImage = rInfo.aInvalidSignatureImage;
+
+ // OOXML intentionally doesn't sign metadata.
+ if (rSigInfo.SignatureIsValid
+ && aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
+ {
+ rSigInfo.SignatureIsValid = DocumentSignatureHelper::checkIfAllFilesAreSigned(
+ aElementsToBeVerified, rInfo, mode);
+ }
+ if (eMode == DocumentSignatureMode::Content)
+ {
+ if (aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML)
+ rSigInfo.PartialDocumentSignature = true;
+ else
+ rSigInfo.PartialDocumentSignature
+ = !DocumentSignatureHelper::isOOo3_2_Signature(aSignInfos[n]);
+ }
+ }
+
+ return aInfos;
+
+}
+
+void DocumentDigitalSignatures::manageTrustedSources( )
+{
+ // MT: i45295
+ // SecEnv is only needed to display certificate information from trusted sources.
+ // Macro Security also has some options where no security environment is needed, so raise dialog anyway.
+ // Later I should change the code so the Dialog creates the SecEnv on demand...
+
+ Reference< css::xml::crypto::XSecurityEnvironment > xSecEnv;
+
+ DocumentSignatureManager aSignatureManager(mxCtx, {});
+ if (aSignatureManager.init())
+ xSecEnv = aSignatureManager.getSecurityEnvironment();
+
+ MacroSecurity aDlg(Application::GetFrameWeld(mxParentWindow), xSecEnv);
+ aDlg.run();
+}
+
+void DocumentDigitalSignatures::showCertificate(
+ const Reference< css::security::XCertificate >& Certificate )
+{
+ DocumentSignatureManager aSignatureManager(mxCtx, {});
+
+ bool bInit = aSignatureManager.init();
+
+ SAL_WARN_IF( !bInit, "xmlsecurity.comp", "Error initializing security context!" );
+
+ if ( bInit )
+ {
+ CertificateViewer aViewer(Application::GetFrameWeld(mxParentWindow), aSignatureManager.getSecurityEnvironment(), Certificate, false, nullptr);
+ aViewer.run();
+ }
+}
+
+sal_Bool DocumentDigitalSignatures::isAuthorTrusted(
+ const Reference<css::security::XCertificate>& xAuthor)
+{
+ if (!xAuthor.is())
+ {
+ return false;
+ }
+ OUString sSerialNum = xmlsecurity::bigIntegerToNumericString(xAuthor->getSerialNumber());
+
+ std::vector< SvtSecurityOptions::Certificate > aTrustedAuthors = SvtSecurityOptions::GetTrustedAuthors();
+
+ return std::any_of(aTrustedAuthors.begin(), aTrustedAuthors.end(),
+ [this, &xAuthor, &sSerialNum](const SvtSecurityOptions::Certificate& rAuthor) {
+ if (!xmlsecurity::EqualDistinguishedNames(rAuthor.SubjectName, xAuthor->getIssuerName(), xmlsecurity::NOCOMPAT))
+ return false;
+ if (rAuthor.SerialNumber != sSerialNum)
+ return false;
+
+ DocumentSignatureManager aSignatureManager(mxCtx, {});
+ if (!aSignatureManager.init())
+ return false;
+ uno::Reference<css::security::XCertificate> xCert = aSignatureManager.getSecurityEnvironment()->createCertificateFromAscii(rAuthor.RawData);
+
+ auto pAuthor = dynamic_cast<xmlsecurity::Certificate*>(xAuthor.get());
+ auto pCert = dynamic_cast<xmlsecurity::Certificate*>(xCert.get());
+ if (pAuthor && pCert)
+ return pCert->getSHA256Thumbprint() == pAuthor->getSHA256Thumbprint();
+
+ return xCert->getSHA1Thumbprint() == xAuthor->getSHA1Thumbprint();
+ });
+}
+
+uno::Sequence<Reference<css::security::XCertificate>>
+DocumentDigitalSignatures::chooseCertificatesImpl(std::map<OUString, OUString>& rProperties,
+ const UserAction eAction,
+ const CertificateKind certificateKind)
+{
+ std::vector< Reference< css::xml::crypto::XXMLSecurityContext > > xSecContexts;
+
+ DocumentSignatureManager aSignatureManager(mxCtx, {});
+ if (aSignatureManager.init()) {
+ xSecContexts.push_back(aSignatureManager.getSecurityContext());
+ // Don't include OpenPGP if only X.509 certs are requested
+ if (certificateKind == CertificateKind_NONE || certificateKind == CertificateKind_OPENPGP)
+ xSecContexts.push_back(aSignatureManager.getGpgSecurityContext());
+ }
+
+ CertificateChooser aChooser(Application::GetFrameWeld(mxParentWindow), std::move(xSecContexts), eAction);
+
+ if (aChooser.run() != RET_OK)
+ return { Reference< css::security::XCertificate >(nullptr) };
+
+ uno::Sequence< Reference< css::security::XCertificate > > xCerts = aChooser.GetSelectedCertificates();
+ rProperties["Description"] = aChooser.GetDescription();
+ rProperties["Usage"] = aChooser.GetUsageText();
+
+ return xCerts;
+}
+
+Reference< css::security::XCertificate > DocumentDigitalSignatures::chooseCertificate(OUString& rDescription)
+{
+ return chooseSigningCertificate( rDescription );
+}
+
+Reference< css::security::XCertificate > DocumentDigitalSignatures::chooseSigningCertificate(OUString& rDescription)
+{
+ std::map<OUString, OUString> aProperties;
+ Reference< css::security::XCertificate > xCert = chooseCertificatesImpl( aProperties, UserAction::Sign )[0];
+ rDescription = aProperties["Description"];
+ return xCert;
+}
+
+Reference< css::security::XCertificate > DocumentDigitalSignatures::selectSigningCertificate(OUString& rDescription)
+{
+ std::map<OUString, OUString> aProperties;
+ Reference< css::security::XCertificate > xCert = chooseCertificatesImpl( aProperties, UserAction::SelectSign )[0];
+ rDescription = aProperties["Description"];
+ return xCert;
+}
+
+Reference<css::security::XCertificate>
+DocumentDigitalSignatures::selectSigningCertificateWithType(const CertificateKind certificateKind,
+ OUString& rDescription)
+{
+ std::map<OUString, OUString> aProperties;
+ Reference<css::security::XCertificate> xCert
+ = chooseCertificatesImpl(aProperties, UserAction::SelectSign, certificateKind)[0];
+ rDescription = aProperties["Description"];
+ return xCert;
+}
+
+css::uno::Sequence< Reference< css::security::XCertificate > > DocumentDigitalSignatures::chooseEncryptionCertificate()
+{
+ std::map<OUString, OUString> aProperties;
+ uno::Sequence< Reference< css::security::XCertificate > > aCerts=
+ chooseCertificatesImpl( aProperties, UserAction::Encrypt );
+ if (aCerts.getLength() == 1 && !aCerts[0].is())
+ // our error case contract is: empty sequence, so map that!
+ return uno::Sequence< Reference< css::security::XCertificate > >();
+ else
+ return aCerts;
+}
+
+css::uno::Reference< css::security::XCertificate > DocumentDigitalSignatures::chooseCertificateWithProps(Sequence<::com::sun::star::beans::PropertyValue>& rProperties)
+{
+ std::map<OUString, OUString> aProperties;
+ auto xCert = chooseCertificatesImpl( aProperties, UserAction::Sign )[0];
+
+ std::vector<css::beans::PropertyValue> vec;
+ vec.reserve(aProperties.size());
+ for (const auto& pair : aProperties)
+ {
+ vec.emplace_back(comphelper::makePropertyValue(pair.first, pair.second));
+ }
+
+ rProperties = comphelper::containerToSequence(vec);
+ return xCert;
+}
+
+sal_Bool DocumentDigitalSignatures::isLocationTrusted( const OUString& Location )
+{
+ return SvtSecurityOptions::isTrustedLocationUri(Location);
+}
+
+void DocumentDigitalSignatures::addAuthorToTrustedSources(
+ const Reference< css::security::XCertificate >& Author )
+{
+ SvtSecurityOptions::Certificate aNewCert;
+ aNewCert.SubjectName = Author->getIssuerName();
+ aNewCert.SerialNumber = xmlsecurity::bigIntegerToNumericString( Author->getSerialNumber() );
+
+ OUStringBuffer aStrBuffer;
+ ::comphelper::Base64::encode(aStrBuffer, Author->getEncoded());
+ aNewCert.RawData = aStrBuffer.makeStringAndClear();
+
+ std::vector< SvtSecurityOptions::Certificate > aTrustedAuthors = SvtSecurityOptions::GetTrustedAuthors();
+ aTrustedAuthors.push_back( aNewCert );
+ SvtSecurityOptions::SetTrustedAuthors( aTrustedAuthors );
+}
+
+void DocumentDigitalSignatures::addLocationToTrustedSources( const OUString& Location )
+{
+ std::vector< OUString > aSecURLs = SvtSecurityOptions::GetSecureURLs();
+ aSecURLs.push_back(Location);
+
+ SvtSecurityOptions::SetSecureURLs( std::move(aSecURLs) );
+}
+
+sal_Bool DocumentDigitalSignatures::signDocumentWithCertificate(
+ css::uno::Reference<css::security::XCertificate> const & xCertificate,
+ css::uno::Reference<css::embed::XStorage> const & xStorage,
+ css::uno::Reference<css::io::XStream> const & xStream)
+{
+ uno::Reference<frame::XModel> xModel;
+ return signWithCertificateImpl(xModel, xCertificate, xStorage, xStream,
+ DocumentSignatureMode::Content);
+}
+
+bool DocumentDigitalSignatures::SignModelWithCertificate(
+ const uno::Reference<frame::XModel>& xModel,
+ const css::uno::Reference<css::security::XCertificate>& xCertificate,
+ const css::uno::Reference<css::embed::XStorage>& xStorage,
+ const css::uno::Reference<css::io::XStream>& xStream)
+{
+ return signWithCertificateImpl(xModel, xCertificate, xStorage, xStream,
+ DocumentSignatureMode::Content);
+}
+
+sal_Bool DocumentDigitalSignatures::signPackageWithCertificate(
+ css::uno::Reference<css::security::XCertificate> const& xCertificate,
+ css::uno::Reference<css::embed::XStorage> const& xStorage,
+ css::uno::Reference<css::io::XStream> const& xStream)
+{
+ uno::Reference<frame::XModel> xModel;
+ return signWithCertificateImpl(xModel, xCertificate, xStorage, xStream,
+ DocumentSignatureMode::Package);
+}
+
+sal_Bool DocumentDigitalSignatures::signScriptingContentWithCertificate(
+ css::uno::Reference<css::security::XCertificate> const& xCertificate,
+ css::uno::Reference<css::embed::XStorage> const& xStorage,
+ css::uno::Reference<css::io::XStream> const& xStream)
+{
+ uno::Reference<frame::XModel> xModel;
+ return signWithCertificateImpl(xModel, xCertificate, xStorage, xStream,
+ DocumentSignatureMode::Macros);
+}
+
+bool DocumentDigitalSignatures::signWithCertificateImpl(
+ const uno::Reference<frame::XModel>& xModel,
+ css::uno::Reference<css::security::XCertificate> const& xCertificate,
+ css::uno::Reference<css::embed::XStorage> const& xStorage,
+ css::uno::Reference<css::io::XStream> const& xStream, DocumentSignatureMode eMode)
+{
+ OSL_ENSURE(!m_sODFVersion.isEmpty(),
+ "DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2");
+
+ DocumentSignatureManager aSignatureManager(mxCtx, eMode);
+
+ if (!aSignatureManager.init())
+ return false;
+
+ aSignatureManager.setStore(xStorage);
+ aSignatureManager.getSignatureHelper().SetStorage(xStorage, m_sODFVersion);
+ aSignatureManager.setSignatureStream(xStream);
+ aSignatureManager.setModel(xModel);
+
+ Reference<XXMLSecurityContext> xSecurityContext = aSignatureManager.getSecurityContext();
+
+ sal_Int32 nSecurityId;
+
+ bool bSuccess = aSignatureManager.add(xCertificate, xSecurityContext, "", nSecurityId, true);
+ if (!bSuccess)
+ return false;
+
+ aSignatureManager.read(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false);
+ aSignatureManager.write(true);
+
+ if (xStorage.is() && !xStream.is())
+ {
+ uno::Reference<embed::XTransactedObject> xTransaction(xStorage, uno::UNO_QUERY);
+ xTransaction->commit();
+ }
+
+ return true;
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_security_DocumentDigitalSignatures_get_implementation(
+ uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(
+ new DocumentDigitalSignatures(uno::Reference<uno::XComponentContext>(pCtx)));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/dialogs/certificatechooser.cxx b/xmlsecurity/source/dialogs/certificatechooser.cxx
new file mode 100644
index 000000000..3ac503521
--- /dev/null
+++ b/xmlsecurity/source/dialogs/certificatechooser.cxx
@@ -0,0 +1,332 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <config_gpgme.h>
+#include <certificatechooser.hxx>
+#include <certificateviewer.hxx>
+#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
+#include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp>
+#include <comphelper/sequence.hxx>
+#include <comphelper/xmlsechelper.hxx>
+
+#include <com/sun/star/security/NoPasswordException.hpp>
+#include <com/sun/star/security/CertificateCharacters.hpp>
+
+#include <o3tl/safeint.hxx>
+#include <unotools/datetime.hxx>
+#include <unotools/useroptions.hxx>
+
+#include <resourcemanager.hxx>
+#include <strings.hrc>
+
+using namespace comphelper;
+using namespace css;
+
+CertificateChooser::CertificateChooser(weld::Window* _pParent,
+ std::vector< css::uno::Reference< css::xml::crypto::XXMLSecurityContext > > && rxSecurityContexts,
+ UserAction eAction)
+ : GenericDialogController(_pParent, "xmlsec/ui/selectcertificatedialog.ui", "SelectCertificateDialog")
+ , meAction(eAction)
+ , m_xFTSign(m_xBuilder->weld_label("sign"))
+ , m_xFTEncrypt(m_xBuilder->weld_label("encrypt"))
+ , m_xCertLB(m_xBuilder->weld_tree_view("signatures"))
+ , m_xViewBtn(m_xBuilder->weld_button("viewcert"))
+ , m_xOKBtn(m_xBuilder->weld_button("ok"))
+ , m_xFTDescription(m_xBuilder->weld_label("description-label"))
+ , m_xDescriptionED(m_xBuilder->weld_entry("description"))
+{
+ auto nControlWidth = m_xCertLB->get_approximate_digit_width() * 105;
+ m_xCertLB->set_size_request(nControlWidth, m_xCertLB->get_height_rows(12));
+
+ std::vector<int> aWidths
+ {
+ o3tl::narrowing<int>(30*nControlWidth/100),
+ o3tl::narrowing<int>(30*nControlWidth/100),
+ o3tl::narrowing<int>(10*nControlWidth/100),
+ o3tl::narrowing<int>(20*nControlWidth/100)
+ };
+ m_xCertLB->set_column_fixed_widths(aWidths);
+ m_xCertLB->connect_changed( LINK( this, CertificateChooser, CertificateHighlightHdl ) );
+ m_xCertLB->connect_row_activated( LINK( this, CertificateChooser, CertificateSelectHdl ) );
+ m_xViewBtn->connect_clicked( LINK( this, CertificateChooser, ViewButtonHdl ) );
+
+ mxSecurityContexts = std::move(rxSecurityContexts);
+ mbInitialized = false;
+
+ // disable buttons
+ CertificateHighlightHdl(*m_xCertLB);
+}
+
+CertificateChooser::~CertificateChooser()
+{
+}
+
+short CertificateChooser::run()
+{
+ // #i48432#
+ // We can't check for personal certificates before raising this dialog,
+ // because the mozilla implementation throws a NoPassword exception,
+ // if the user pressed cancel, and also if the database does not exist!
+ // But in the later case, the is no password query, and the user is confused
+ // that nothing happens when pressing "Add..." in the SignatureDialog.
+
+ // PostUserEvent( LINK( this, CertificateChooser, Initialize ) );
+
+ // PostUserLink behavior is too slow, so do it directly before Execute().
+ // Problem: This Dialog should be visible right now, and the parent should not be accessible.
+ // Show, Update, DisableInput...
+
+ m_xDialog->show();
+ ImplInitialize();
+ return GenericDialogController::run();
+}
+
+void CertificateChooser::HandleOneUsageBit(OUString& string, int& bits, int bit, TranslateId pResId)
+{
+ if (bits & bit)
+ {
+ if (!string.isEmpty())
+ string += ", ";
+ string += XsResId(pResId);
+ bits &= ~bit;
+ }
+}
+
+OUString CertificateChooser::UsageInClearText(int bits)
+{
+ OUString result;
+
+ HandleOneUsageBit(result, bits, 0x80, STR_DIGITAL_SIGNATURE);
+ HandleOneUsageBit(result, bits, 0x40, STR_NON_REPUDIATION);
+ HandleOneUsageBit(result, bits, 0x20, STR_KEY_ENCIPHERMENT);
+ HandleOneUsageBit(result, bits, 0x10, STR_DATA_ENCIPHERMENT);
+ HandleOneUsageBit(result, bits, 0x08, STR_KEY_AGREEMENT);
+ HandleOneUsageBit(result, bits, 0x04, STR_KEY_CERT_SIGN);
+ HandleOneUsageBit(result, bits, 0x02, STR_CRL_SIGN);
+ HandleOneUsageBit(result, bits, 0x01, STR_ENCIPHER_ONLY);
+
+ // Check for mystery leftover bits
+ if (bits != 0)
+ {
+ if (!result.isEmpty())
+ result += ", ";
+ result += "0x" + OUString::number(bits, 16);
+ }
+
+ return result;
+}
+
+void CertificateChooser::ImplInitialize()
+{
+ if ( mbInitialized )
+ return;
+
+ SvtUserOptions aUserOpts;
+
+ switch (meAction)
+ {
+ case UserAction::Sign:
+ m_xFTSign->show();
+ m_xOKBtn->set_label(XsResId(STR_SIGN));
+ msPreferredKey = aUserOpts.GetSigningKey();
+ break;
+
+ case UserAction::SelectSign:
+ m_xFTSign->show();
+ m_xOKBtn->set_label(XsResId(STR_SELECTSIGN));
+ msPreferredKey = aUserOpts.GetSigningKey();
+ break;
+
+ case UserAction::Encrypt:
+ m_xFTEncrypt->show();
+ m_xFTDescription->hide();
+ m_xDescriptionED->hide();
+ m_xCertLB->set_selection_mode(SelectionMode::Multiple);
+ m_xOKBtn->set_label(XsResId(STR_ENCRYPT));
+ msPreferredKey = aUserOpts.GetEncryptionKey();
+ break;
+
+ }
+
+ for (auto &secContext : mxSecurityContexts)
+ {
+ if (!secContext.is())
+ continue;
+ auto secEnvironment = secContext->getSecurityEnvironment();
+ if (!secEnvironment.is())
+ continue;
+
+ uno::Sequence< uno::Reference< security::XCertificate > > xCerts;
+ try
+ {
+ if ( meAction == UserAction::Sign || meAction == UserAction::SelectSign)
+ xCerts = secEnvironment->getPersonalCertificates();
+ else
+ xCerts = secEnvironment->getAllCertificates();
+ }
+ catch (security::NoPasswordException&)
+ {
+ }
+
+ for( sal_Int32 nCert = xCerts.getLength(); nCert; )
+ {
+ uno::Reference< security::XCertificate > xCert = xCerts[ --nCert ];
+ // Check if we have a private key for this...
+ tools::Long nCertificateCharacters = secEnvironment->getCertificateCharacters(xCert);
+
+ if (!(nCertificateCharacters & security::CertificateCharacters::HAS_PRIVATE_KEY))
+ {
+ ::comphelper::removeElementAt( xCerts, nCert );
+ }
+ }
+
+
+ // fill list of certificates; the first entry will be selected
+ for ( const auto& xCert : std::as_const(xCerts) )
+ {
+ std::shared_ptr<UserData> userData = std::make_shared<UserData>();
+ userData->xCertificate = xCert;
+ userData->xSecurityContext = secContext;
+ userData->xSecurityEnvironment = secEnvironment;
+ mvUserData.push_back(userData);
+
+ OUString sIssuer = xmlsec::GetContentPart( xCert->getIssuerName(), xCert->getCertificateKind());
+
+ m_xCertLB->append();
+ int nRow = m_xCertLB->n_children() - 1;
+ m_xCertLB->set_text(nRow, xmlsec::GetContentPart(xCert->getSubjectName(), xCert->getCertificateKind()), 0);
+ m_xCertLB->set_text(nRow, sIssuer, 1);
+ m_xCertLB->set_text(nRow, xmlsec::GetCertificateKind(xCert->getCertificateKind()), 2);
+ m_xCertLB->set_text(nRow, utl::GetDateString(xCert->getNotValidAfter()), 3);
+ m_xCertLB->set_text(nRow, UsageInClearText(xCert->getCertificateUsage()), 4);
+ OUString sId(weld::toId(userData.get()));
+ m_xCertLB->set_id(nRow, sId);
+
+#if HAVE_FEATURE_GPGME
+ // only GPG has preferred keys
+ if ( !sIssuer.isEmpty() && !msPreferredKey.isEmpty() ) {
+ if ( sIssuer == msPreferredKey )
+ {
+ if ( meAction == UserAction::Sign || meAction == UserAction::SelectSign )
+ m_xCertLB->select(nRow);
+ else if ( meAction == UserAction::Encrypt &&
+ aUserOpts.GetEncryptToSelf() )
+ mxEncryptToSelf = xCert;
+ }
+ }
+#endif
+ }
+ }
+
+ // enable/disable buttons
+ CertificateHighlightHdl(*m_xCertLB);
+ mbInitialized = true;
+}
+
+uno::Sequence<uno::Reference< css::security::XCertificate > > CertificateChooser::GetSelectedCertificates()
+{
+ std::vector< uno::Reference< css::security::XCertificate > > aRet;
+ if (meAction == UserAction::Encrypt)
+ {
+ // for encryption, multiselection is enabled
+ m_xCertLB->selected_foreach([this, &aRet](weld::TreeIter& rEntry){
+ UserData* userData = weld::fromId<UserData*>(m_xCertLB->get_id(rEntry));
+ aRet.push_back( userData->xCertificate );
+ return false;
+ });
+ }
+ else
+ {
+ uno::Reference< css::security::XCertificate > xCert;
+ int nSel = m_xCertLB->get_selected_index();
+ if (nSel != -1)
+ {
+ UserData* userData = weld::fromId<UserData*>(m_xCertLB->get_id(nSel));
+ xCert = userData->xCertificate;
+ }
+ aRet.push_back( xCert );
+ }
+
+#if HAVE_FEATURE_GPGME
+ if ( mxEncryptToSelf.is())
+ aRet.push_back( mxEncryptToSelf );
+#endif
+
+ return comphelper::containerToSequence(aRet);
+}
+
+uno::Reference<xml::crypto::XXMLSecurityContext> CertificateChooser::GetSelectedSecurityContext() const
+{
+ int nSel = m_xCertLB->get_selected_index();
+ if (nSel == -1)
+ return uno::Reference<xml::crypto::XXMLSecurityContext>();
+
+ UserData* userData = weld::fromId<UserData*>(m_xCertLB->get_id(nSel));
+ uno::Reference<xml::crypto::XXMLSecurityContext> xCert = userData->xSecurityContext;
+ return xCert;
+}
+
+OUString CertificateChooser::GetDescription() const
+{
+ return m_xDescriptionED->get_text();
+}
+
+OUString CertificateChooser::GetUsageText()
+{
+ uno::Sequence< uno::Reference<css::security::XCertificate> > xCerts =
+ GetSelectedCertificates();
+ return (xCerts.hasElements() && xCerts[0].is()) ?
+ UsageInClearText(xCerts[0]->getCertificateUsage()) : OUString();
+}
+
+IMPL_LINK_NOARG(CertificateChooser, CertificateHighlightHdl, weld::TreeView&, void)
+{
+ bool bEnable = m_xCertLB->get_selected_index() != -1;
+ m_xViewBtn->set_sensitive(bEnable);
+ m_xOKBtn->set_sensitive(bEnable);
+ m_xDescriptionED->set_sensitive(bEnable);
+}
+
+IMPL_LINK_NOARG(CertificateChooser, CertificateSelectHdl, weld::TreeView&, bool)
+{
+ m_xDialog->response(RET_OK);
+ return true;
+}
+
+IMPL_LINK_NOARG(CertificateChooser, ViewButtonHdl, weld::Button&, void)
+{
+ ImplShowCertificateDetails();
+}
+
+void CertificateChooser::ImplShowCertificateDetails()
+{
+ int nSel = m_xCertLB->get_selected_index();
+ if (nSel == -1)
+ return;
+
+ UserData* userData = weld::fromId<UserData*>(m_xCertLB->get_id(nSel));
+
+ if (!userData->xSecurityEnvironment.is() || !userData->xCertificate.is())
+ return;
+
+ CertificateViewer aViewer(m_xDialog.get(), userData->xSecurityEnvironment, userData->xCertificate, true, this);
+ aViewer.run();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/dialogs/certificateviewer.cxx b/xmlsecurity/source/dialogs/certificateviewer.cxx
new file mode 100644
index 000000000..1801cdf53
--- /dev/null
+++ b/xmlsecurity/source/dialogs/certificateviewer.cxx
@@ -0,0 +1,377 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <certificatechooser.hxx>
+#include <certificateviewer.hxx>
+#include <com/sun/star/security/XCertificate.hpp>
+
+#include <com/sun/star/security/CertificateCharacters.hpp>
+#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
+#include <com/sun/star/security/CertificateValidity.hpp>
+
+#include <unotools/localedatawrapper.hxx>
+#include <unotools/datetime.hxx>
+
+#include <strings.hrc>
+#include <resourcemanager.hxx>
+#include <comphelper/xmlsechelper.hxx>
+#include <tools/datetime.hxx>
+#include <bitmaps.hlst>
+
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace comphelper;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+CertificateViewer::CertificateViewer(weld::Window* _pParent,
+ const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& _rxSecurityEnvironment,
+ const css::uno::Reference< css::security::XCertificate >& _rXCert, bool bCheckForPrivateKey,
+ CertificateChooser* pParentChooser)
+ : GenericDialogController(_pParent, "xmlsec/ui/viewcertdialog.ui", "ViewCertDialog")
+ , mbCheckForPrivateKey(bCheckForPrivateKey)
+ , mpParentChooser(pParentChooser)
+ , mxTabCtrl(m_xBuilder->weld_notebook("tabcontrol"))
+{
+ mxTabCtrl->connect_enter_page(LINK(this, CertificateViewer, ActivatePageHdl));
+
+ mxSecurityEnvironment = _rxSecurityEnvironment;
+ mxCert = _rXCert;
+
+ mxGeneralPage.reset(new CertificateViewerGeneralTP(mxTabCtrl->get_page("general"), this));
+ mxDetailsPage.reset(new CertificateViewerDetailsTP(mxTabCtrl->get_page("details"), this));
+ if (!mxSecurityEnvironment->buildCertificatePath(mxCert).hasElements())
+ mxTabCtrl->remove_page("path");
+ else
+ mxPathId.reset(new CertificateViewerCertPathTP(mxTabCtrl->get_page("path"), this));
+ mxTabCtrl->set_current_page("general");
+}
+
+IMPL_LINK(CertificateViewer, ActivatePageHdl, const OString&, rPage, void)
+{
+ if (rPage == "path")
+ mxPathId->ActivatePage();
+}
+
+CertificateViewerTP::CertificateViewerTP(weld::Container* pParent, const OUString& rUIXMLDescription,
+ const OString& rID, CertificateViewer* pDlg)
+ : mxBuilder(Application::CreateBuilder(pParent, rUIXMLDescription))
+ , mxContainer(mxBuilder->weld_container(rID))
+ , mpDlg(pDlg)
+{
+}
+
+CertificateViewerGeneralTP::CertificateViewerGeneralTP(weld::Container* pParent, CertificateViewer* pDlg)
+ : CertificateViewerTP(pParent, "xmlsec/ui/certgeneral.ui", "CertGeneral", pDlg)
+ , m_xCertImg(mxBuilder->weld_image("certimage"))
+ , m_xHintNotTrustedFT(mxBuilder->weld_label("hintnotrust"))
+ , m_xIssuedToLabelFT(mxBuilder->weld_label("issued_to"))
+ , m_xIssuedToFT(mxBuilder->weld_label("issued_to_value"))
+ , m_xIssuedByLabelFT(mxBuilder->weld_label("issued_by"))
+ , m_xIssuedByFT(mxBuilder->weld_label("issued_by_value"))
+ , m_xValidFromDateFT(mxBuilder->weld_label("valid_from_value"))
+ , m_xValidToDateFT(mxBuilder->weld_label("valid_to_value"))
+ , m_xKeyImg(mxBuilder->weld_image("keyimage"))
+ , m_xHintCorrespPrivKeyFT(mxBuilder->weld_label("privatekey"))
+{
+ //Verify the certificate
+ sal_Int32 certStatus = mpDlg->mxSecurityEnvironment->verifyCertificate(mpDlg->mxCert,
+ Sequence<Reference<css::security::XCertificate> >());
+
+ bool bCertValid = certStatus == css::security::CertificateValidity::VALID;
+
+ if ( !bCertValid )
+ {
+ m_xCertImg->set_from_icon_name(BMP_STATE_NOT_VALIDATED);
+ m_xHintNotTrustedFT->set_label(XsResId(STR_CERTIFICATE_NOT_VALIDATED));
+ }
+
+ // insert data
+ css::uno::Reference< css::security::XCertificate > xCert = mpDlg->mxCert;
+
+ OUString sSubjectName(xmlsec::GetContentPart(xCert->getSubjectName(), xCert->getCertificateKind()));
+ if (!sSubjectName.isEmpty())
+ m_xIssuedToFT->set_label(sSubjectName);
+ else
+ m_xIssuedToLabelFT->hide();
+ OUString sIssuerName(xmlsec::GetContentPart(xCert->getIssuerName(), xCert->getCertificateKind()));
+ if (!sIssuerName.isEmpty())
+ m_xIssuedByFT->set_label(sIssuerName);
+ else
+ m_xIssuedByLabelFT->hide();
+
+ DateTime aDateTimeStart( DateTime::EMPTY );
+ DateTime aDateTimeEnd( DateTime::EMPTY );
+ utl::typeConvert( xCert->getNotValidBefore(), aDateTimeStart );
+ utl::typeConvert( xCert->getNotValidAfter(), aDateTimeEnd );
+
+ OUString sValidFromDate = Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTimeStart.GetDate()));
+ OUString sValidToDate = Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTimeEnd.GetDate()));
+
+ m_xValidFromDateFT->set_label(sValidFromDate);
+ m_xValidToDateFT->set_label(sValidToDate);
+
+ // Check if we have the private key...
+ bool bHasPrivateKey = false;
+ // #i41270# Check only if we have that certificate in our security environment
+ if (pDlg->mbCheckForPrivateKey)
+ {
+ tools::Long nCertificateCharacters = pDlg->mxSecurityEnvironment->getCertificateCharacters(xCert);
+ bHasPrivateKey = (nCertificateCharacters & security::CertificateCharacters::HAS_PRIVATE_KEY);
+ }
+ if (!bHasPrivateKey)
+ {
+ m_xKeyImg->hide();
+ m_xHintCorrespPrivKeyFT->hide();
+ }
+}
+
+void CertificateViewerDetailsTP::InsertElement(const OUString& rField, const OUString& rValue,
+ const OUString& rDetails, bool bFixedWidthFont)
+{
+ m_aUserData.emplace_back(std::make_unique<Details_UserDatat>(rDetails, bFixedWidthFont));
+ OUString sId(weld::toId(m_aUserData.back().get()));
+ m_xElementsLB->append(sId, rField);
+ m_xElementsLB->set_text(m_xElementsLB->n_children() -1, rValue, 1);
+}
+
+CertificateViewerDetailsTP::CertificateViewerDetailsTP(weld::Container* pParent, CertificateViewer* pDlg)
+ : CertificateViewerTP(pParent, "xmlsec/ui/certdetails.ui", "CertDetails", pDlg)
+ , m_xElementsLB(mxBuilder->weld_tree_view("tablecontainer"))
+ , m_xValueDetails(mxBuilder->weld_text_view("valuedetails"))
+{
+ const int nWidth = m_xElementsLB->get_approximate_digit_width() * 60;
+ const int nHeight = m_xElementsLB->get_height_rows(8);
+ m_xElementsLB->set_size_request(nWidth, nHeight);
+ m_xValueDetails->set_size_request(nWidth, nHeight);
+ m_xElementsLB->set_column_fixed_widths( { nWidth / 2 } );
+
+ // fill list box
+ Reference< security::XCertificate > xCert = mpDlg->mxCert;
+ sal_uInt16 nLineBreak = 16;
+ const char* const pHexSep = " ";
+ OUString aLBEntry;
+ OUString aDetails;
+ // Certificate Versions are reported wrong (#i35107#) - 0 == "V1", 1 == "V2", ..., n = "V(n+1)"
+ aLBEntry = "V" + OUString::number( xCert->getVersion() + 1 );
+ InsertElement( XsResId( STR_VERSION ), aLBEntry, aLBEntry );
+ Sequence< sal_Int8 > aSeq = xCert->getSerialNumber();
+ aLBEntry = xmlsec::GetHexString( aSeq, pHexSep );
+ aDetails = xmlsec::GetHexString( aSeq, pHexSep, nLineBreak );
+ InsertElement( XsResId( STR_SERIALNUM ), aLBEntry, aDetails, true );
+
+ std::pair< OUString, OUString> pairIssuer =
+ xmlsec::GetDNForCertDetailsView(xCert->getIssuerName());
+ aLBEntry = pairIssuer.first;
+ aDetails = pairIssuer.second;
+ InsertElement( XsResId( STR_ISSUER ), aLBEntry, aDetails );
+
+ DateTime aDateTime( DateTime::EMPTY );
+ utl::typeConvert( xCert->getNotValidBefore(), aDateTime );
+ aLBEntry = Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTime.GetDate())) + " ";
+ aLBEntry += Application::GetSettings().GetUILocaleDataWrapper().getTime(tools::Time(aDateTime.GetTime()));
+ InsertElement( XsResId( STR_VALIDFROM ), aLBEntry, aLBEntry );
+ utl::typeConvert( xCert->getNotValidAfter(), aDateTime );
+ aLBEntry = Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTime.GetDate()) ) + " ";
+ aLBEntry += Application::GetSettings().GetUILocaleDataWrapper().getTime(tools::Time(aDateTime.GetTime()));
+ InsertElement( XsResId( STR_VALIDTO ), aLBEntry, aLBEntry );
+
+ std::pair< OUString, OUString > pairSubject =
+ xmlsec::GetDNForCertDetailsView(xCert->getSubjectName());
+ aLBEntry = pairSubject.first;
+ aDetails = pairSubject.second;
+ InsertElement( XsResId( STR_SUBJECT ), aLBEntry, aDetails );
+
+ aLBEntry = aDetails = xCert->getSubjectPublicKeyAlgorithm();
+ InsertElement( XsResId( STR_SUBJECT_PUBKEY_ALGO ), aLBEntry, aDetails );
+ aSeq = xCert->getSubjectPublicKeyValue();
+ aLBEntry = xmlsec::GetHexString( aSeq, pHexSep );
+ aDetails = xmlsec::GetHexString( aSeq, pHexSep, nLineBreak );
+ InsertElement( XsResId( STR_SUBJECT_PUBKEY_VAL ), aLBEntry, aDetails, true );
+
+ aLBEntry = aDetails = xCert->getSignatureAlgorithm();
+ InsertElement( XsResId( STR_SIGNATURE_ALGO ), aLBEntry, aDetails );
+
+ CertificateChooser* pChooser = mpDlg->GetParentChooser();
+ if (pChooser)
+ {
+ aLBEntry = CertificateChooser::UsageInClearText( mpDlg->mxCert->getCertificateUsage() );
+ InsertElement( XsResId( STR_USE ), aLBEntry, aLBEntry );
+ }
+
+ aSeq = xCert->getSHA1Thumbprint();
+ aLBEntry = xmlsec::GetHexString( aSeq, pHexSep );
+ aDetails = xmlsec::GetHexString( aSeq, pHexSep, nLineBreak );
+ InsertElement( XsResId( STR_THUMBPRINT_SHA1 ), aLBEntry, aDetails, true );
+
+ aSeq = xCert->getMD5Thumbprint();
+ aLBEntry = xmlsec::GetHexString( aSeq, pHexSep );
+ aDetails = xmlsec::GetHexString( aSeq, pHexSep, nLineBreak );
+ InsertElement( XsResId( STR_THUMBPRINT_MD5 ), aLBEntry, aDetails, true );
+
+ m_xElementsLB->connect_changed(LINK(this, CertificateViewerDetailsTP, ElementSelectHdl));
+}
+
+IMPL_LINK_NOARG(CertificateViewerDetailsTP, ElementSelectHdl, weld::TreeView&, void)
+{
+ int nEntry = m_xElementsLB->get_selected_index();
+ OUString aElementText;
+ bool bFixedWidthFont;
+ if (nEntry != -1)
+ {
+ const Details_UserDatat* p = weld::fromId<Details_UserDatat*>(m_xElementsLB->get_id(nEntry));
+ aElementText = p->maTxt;
+ bFixedWidthFont = p->mbFixedWidthFont;
+ }
+ else
+ bFixedWidthFont = false;
+
+ m_xValueDetails->set_monospace(bFixedWidthFont);
+ m_xValueDetails->set_text(aElementText);
+}
+
+CertificateViewerCertPathTP::CertificateViewerCertPathTP(weld::Container* pParent, CertificateViewer* pDlg)
+ : CertificateViewerTP(pParent, "xmlsec/ui/certpage.ui", "CertPage", pDlg)
+ , mpParent(pDlg)
+ , mbFirstActivateDone(false)
+ , mxCertPathLB(mxBuilder->weld_tree_view("signatures"))
+ , mxScratchIter(mxCertPathLB->make_iterator())
+ , mxViewCertPB(mxBuilder->weld_button("viewcert"))
+ , mxCertStatusML(mxBuilder->weld_text_view("status"))
+ , mxCertOK(mxBuilder->weld_label("certok"))
+ , mxCertNotValidated(mxBuilder->weld_label("certnotok"))
+{
+ const int nWidth = mxCertPathLB->get_approximate_digit_width() * 60;
+ const int nHeight = mxCertPathLB->get_height_rows(6);
+ mxCertPathLB->set_size_request(nWidth, nHeight);
+ mxCertStatusML->set_size_request(nWidth, nHeight);
+
+ mxCertPathLB->connect_changed( LINK( this, CertificateViewerCertPathTP, CertSelectHdl ) );
+ mxViewCertPB->connect_clicked( LINK( this, CertificateViewerCertPathTP, ViewCertHdl ) );
+}
+
+CertificateViewerCertPathTP::~CertificateViewerCertPathTP()
+{
+ if (mxCertificateViewer)
+ mxCertificateViewer->response(RET_OK);
+}
+
+void CertificateViewerCertPathTP::ActivatePage()
+{
+ if ( mbFirstActivateDone )
+ return;
+
+ mbFirstActivateDone = true;
+ Sequence< Reference< security::XCertificate > > aCertPath =
+ mpParent->mxSecurityEnvironment->buildCertificatePath( mpParent->mxCert );
+ const Reference< security::XCertificate >* pCertPath = aCertPath.getConstArray();
+
+ sal_Int32 i, nCnt = aCertPath.getLength();
+ std::unique_ptr<weld::TreeIter> xParent;
+ for (i = nCnt-1; i >= 0; i--)
+ {
+ const Reference< security::XCertificate > rCert = pCertPath[ i ];
+ OUString sName = xmlsec::GetContentPart( rCert->getSubjectName(), rCert->getCertificateKind() );
+ //Verify the certificate
+ sal_Int32 certStatus = mpDlg->mxSecurityEnvironment->verifyCertificate(rCert,
+ Sequence<Reference<css::security::XCertificate> >());
+ bool bCertValid = certStatus == css::security::CertificateValidity::VALID;
+ InsertCert(xParent.get(), sName, rCert, bCertValid);
+ if (!xParent)
+ {
+ xParent = mxCertPathLB->make_iterator();
+ (void)mxCertPathLB->get_iter_first(*xParent);
+ }
+ else
+ {
+ (void)mxCertPathLB->iter_children(*xParent);
+ }
+ }
+
+ if (xParent)
+ mxCertPathLB->select(*xParent);
+ mxViewCertPB->set_sensitive(false); // Own certificate selected
+
+ while (xParent)
+ {
+ mxCertPathLB->expand_row(*xParent);
+ if (!mxCertPathLB->iter_parent(*xParent))
+ xParent.reset();
+ }
+
+ CertSelectHdl(*mxCertPathLB);
+}
+
+IMPL_LINK_NOARG(CertificateViewerCertPathTP, ViewCertHdl, weld::Button&, void)
+{
+ std::unique_ptr<weld::TreeIter> xIter = mxCertPathLB->make_iterator();
+ if (mxCertPathLB->get_selected(xIter.get()))
+ {
+ if (mxCertificateViewer)
+ mxCertificateViewer->response(RET_OK);
+
+ CertPath_UserData* pData = weld::fromId<CertPath_UserData*>(mxCertPathLB->get_id(*xIter));
+ mxCertificateViewer = std::make_shared<CertificateViewer>(mpDlg->getDialog(), mpDlg->mxSecurityEnvironment,
+ pData->mxCert, false, nullptr);
+ weld::DialogController::runAsync(mxCertificateViewer, [this] (sal_Int32) { mxCertificateViewer = nullptr; });
+ }
+}
+
+IMPL_LINK_NOARG(CertificateViewerCertPathTP, CertSelectHdl, weld::TreeView&, void)
+{
+ OUString sStatus;
+
+ std::unique_ptr<weld::TreeIter> xIter = mxCertPathLB->make_iterator();
+ bool bEntry = mxCertPathLB->get_selected(xIter.get());
+ if (bEntry)
+ {
+ CertPath_UserData* pData = weld::fromId<CertPath_UserData*>(mxCertPathLB->get_id(*xIter));
+ if (pData)
+ sStatus = pData->mbValid ? mxCertOK->get_label() : mxCertNotValidated->get_label();
+ }
+
+ mxCertStatusML->set_text(sStatus);
+
+ bool bSensitive = false;
+ if (bEntry)
+ {
+ // if has children, so not the last one in the chain
+ if (mxCertPathLB->iter_children(*xIter))
+ bSensitive = true;
+ }
+ mxViewCertPB->set_sensitive(bSensitive);
+}
+
+void CertificateViewerCertPathTP::InsertCert(const weld::TreeIter* pParent, const OUString& rName,
+ const css::uno::Reference< css::security::XCertificate >& rxCert,
+ bool bValid)
+{
+ auto const sImage = bValid ? std::u16string_view(u"" BMP_CERT_OK) : std::u16string_view(u"" BMP_CERT_NOT_OK);
+ maUserData.emplace_back(std::make_unique<CertPath_UserData>(rxCert, bValid));
+ OUString sId(weld::toId(maUserData.back().get()));
+ mxCertPathLB->insert(pParent, -1, &rName, &sId, nullptr, nullptr, false, mxScratchIter.get());
+ mxCertPathLB->set_image(*mxScratchIter, OUString(sImage));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
new file mode 100644
index 000000000..1d40e7562
--- /dev/null
+++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
@@ -0,0 +1,801 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <digitalsignaturesdialog.hxx>
+#include <certificatechooser.hxx>
+#include <certificateviewer.hxx>
+#include <biginteger.hxx>
+#include <sax/tools/converter.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/StorageFormats.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/security/NoPasswordException.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/security/CertificateValidity.hpp>
+#include <com/sun/star/packages/WrongPasswordException.hpp>
+#include <com/sun/star/security/CertificateKind.hpp>
+#include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
+#include <com/sun/star/system/SystemShellExecute.hpp>
+#include <com/sun/star/system/SystemShellExecuteFlags.hpp>
+#include <com/sun/star/system/SystemShellExecuteException.hpp>
+
+#include <osl/file.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/uri.hxx>
+#include <sal/log.hxx>
+
+#include <tools/date.hxx>
+#include <tools/time.hxx>
+#include <unotools/datetime.hxx>
+
+#include <bitmaps.hlst>
+#include <strings.hrc>
+#include <resourcemanager.hxx>
+#include <comphelper/lok.hxx>
+#include <comphelper/xmlsechelper.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include <vcl/weld.hxx>
+#include <vcl/svapp.hxx>
+#include <unotools/configitem.hxx>
+
+#ifdef _WIN32
+#include <o3tl/char16_t2wchar_t.hxx>
+#include <prewin.h>
+#include <Shlobj.h>
+#endif
+
+using namespace comphelper;
+using namespace css::security;
+using namespace css::uno;
+using namespace css;
+
+namespace
+{
+ class SaveODFItem: public utl::ConfigItem
+ {
+ private:
+ sal_Int16 m_nODF;
+
+ virtual void ImplCommit() override;
+
+ public:
+ virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override;
+ SaveODFItem();
+ //See group ODF in Common.xcs
+ bool isLessODF1_2() const
+ {
+ return m_nODF < 3;
+ }
+ };
+
+ void SaveODFItem::ImplCommit() {}
+ void SaveODFItem::Notify( const css::uno::Sequence< OUString >& ) {}
+
+ SaveODFItem::SaveODFItem(): utl::ConfigItem("Office.Common/Save"), m_nODF(0)
+ {
+ OUString sDef("ODF/DefaultVersion");
+ Sequence< css::uno::Any > aValues = GetProperties( Sequence<OUString>(&sDef,1) );
+ if ( aValues.getLength() != 1)
+ throw uno::RuntimeException(
+ "[xmlsecurity] Could not open property Office.Common/Save/ODF/DefaultVersion",
+ nullptr);
+
+ sal_Int16 nTmp = 0;
+ if ( !(aValues[0] >>= nTmp) )
+ throw uno::RuntimeException(
+ "[xmlsecurity]SaveODFItem::SaveODFItem(): Wrong Type!",
+ nullptr );
+
+ m_nODF = nTmp;
+ }
+}
+
+DigitalSignaturesDialog::DigitalSignaturesDialog(
+ weld::Window* pParent,
+ const uno::Reference< uno::XComponentContext >& rxCtx, DocumentSignatureMode eMode,
+ bool bReadOnly, const OUString& sODFVersion, bool bHasDocumentSignature)
+ : GenericDialogController(pParent, "xmlsec/ui/digitalsignaturesdialog.ui", "DigitalSignaturesDialog")
+ , maSignatureManager(rxCtx, eMode)
+ , m_sODFVersion (sODFVersion)
+ , m_bHasDocumentSignature(bHasDocumentSignature)
+ , m_bWarningShowSignMacro(false)
+ , m_xHintDocFT(m_xBuilder->weld_label("dochint"))
+ , m_xHintBasicFT(m_xBuilder->weld_label("macrohint"))
+ , m_xHintPackageFT(m_xBuilder->weld_label("packagehint"))
+ , m_xSignaturesLB(m_xBuilder->weld_tree_view("signatures"))
+ , m_xSigsValidImg(m_xBuilder->weld_image("validimg"))
+ , m_xSigsValidFI(m_xBuilder->weld_label("validft"))
+ , m_xSigsInvalidImg(m_xBuilder->weld_image("invalidimg"))
+ , m_xSigsInvalidFI(m_xBuilder->weld_label("invalidft"))
+ , m_xSigsNotvalidatedImg(m_xBuilder->weld_image("notvalidatedimg"))
+ , m_xSigsNotvalidatedFI(m_xBuilder->weld_label("notvalidatedft"))
+ , m_xSigsOldSignatureImg(m_xBuilder->weld_image("oldsignatureimg"))
+ , m_xSigsOldSignatureFI(m_xBuilder->weld_label("oldsignatureft"))
+ , m_xAdESCompliantCB(m_xBuilder->weld_check_button("adescompliant"))
+ , m_xViewBtn(m_xBuilder->weld_button("view"))
+ , m_xAddBtn(m_xBuilder->weld_button("sign"))
+ , m_xRemoveBtn(m_xBuilder->weld_button("remove"))
+ , m_xStartCertMgrBtn(m_xBuilder->weld_button("start_certmanager"))
+ , m_xCloseBtn(m_xBuilder->weld_button("close"))
+{
+ m_bAdESCompliant = !DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion);
+
+ auto nControlWidth = m_xSignaturesLB->get_approximate_digit_width() * 105;
+ m_xSignaturesLB->set_size_request(nControlWidth, m_xSignaturesLB->get_height_rows(10));
+
+ // Give the first column 6 percent, try to distribute the rest equally.
+ std::vector<int> aWidths;
+ aWidths.push_back(6*nControlWidth/100);
+ auto nColWidth = (nControlWidth - aWidths[0]) / 4;
+ aWidths.push_back(nColWidth);
+ aWidths.push_back(nColWidth);
+ aWidths.push_back(nColWidth);
+ m_xSignaturesLB->set_column_fixed_widths(aWidths);
+
+ mbVerifySignatures = true;
+ mbSignaturesChanged = false;
+
+ m_xSignaturesLB->connect_changed( LINK( this, DigitalSignaturesDialog, SignatureHighlightHdl ) );
+ m_xSignaturesLB->connect_row_activated( LINK( this, DigitalSignaturesDialog, SignatureSelectHdl ) );
+
+ m_xAdESCompliantCB->connect_toggled( LINK( this, DigitalSignaturesDialog, AdESCompliantCheckBoxHdl ) );
+ m_xAdESCompliantCB->set_active(m_bAdESCompliant);
+
+ m_xViewBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, ViewButtonHdl ) );
+ m_xViewBtn->set_sensitive(false);
+
+ m_xAddBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, AddButtonHdl ) );
+ if ( bReadOnly )
+ m_xAddBtn->set_sensitive(false);
+
+ m_xRemoveBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, RemoveButtonHdl ) );
+ m_xRemoveBtn->set_sensitive(false);
+
+ m_xStartCertMgrBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, CertMgrButtonHdl ) );
+
+ m_xCloseBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, OKButtonHdl) );
+
+ switch( maSignatureManager.getSignatureMode() )
+ {
+ case DocumentSignatureMode::Content:
+ m_xHintDocFT->show();
+ break;
+ case DocumentSignatureMode::Macros:
+ m_xHintBasicFT->show();
+ break;
+ case DocumentSignatureMode::Package:
+ m_xHintPackageFT->show();
+ break;
+ }
+
+ if (comphelper::LibreOfficeKit::isActive())
+ {
+ m_xAddBtn->hide();
+ m_xRemoveBtn->hide();
+ m_xStartCertMgrBtn->hide();
+ }
+}
+
+DigitalSignaturesDialog::~DigitalSignaturesDialog()
+{
+ if (m_xViewer)
+ m_xViewer->response(RET_OK);
+
+ if (m_xInfoBox)
+ m_xInfoBox->response(RET_OK);
+}
+
+bool DigitalSignaturesDialog::Init()
+{
+ bool bInit = maSignatureManager.init();
+
+ SAL_WARN_IF( !bInit, "xmlsecurity.dialogs", "Error initializing security context!" );
+
+ if ( bInit )
+ {
+ maSignatureManager.getSignatureHelper().SetStartVerifySignatureHdl( LINK( this, DigitalSignaturesDialog, StartVerifySignatureHdl ) );
+ }
+
+ return bInit;
+}
+
+void DigitalSignaturesDialog::SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStore )
+{
+ if (!rxStore.is())
+ {
+ // PDF supports AdES.
+ m_bAdESCompliant = true;
+ m_xAdESCompliantCB->set_active(m_bAdESCompliant);
+ return;
+ }
+
+ maSignatureManager.setStore(rxStore);
+ maSignatureManager.getSignatureHelper().SetStorage( maSignatureManager.getStore(), m_sODFVersion);
+}
+
+void DigitalSignaturesDialog::SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream )
+{
+ maSignatureManager.setSignatureStream(rxStream);
+}
+
+bool DigitalSignaturesDialog::canAddRemove()
+{
+ //FIXME: this func needs some cleanup, such as real split between
+ //'canAdd' and 'canRemove' case
+ bool ret = true;
+
+ uno::Reference<container::XNameAccess> xNameAccess = maSignatureManager.getStore();
+ if (xNameAccess.is() && xNameAccess->hasByName("[Content_Types].xml"))
+ // It's always possible to append an OOXML signature.
+ return ret;
+
+ if (!maSignatureManager.getStore().is())
+ // It's always possible to append a PDF signature.
+ return ret;
+
+ OSL_ASSERT(maSignatureManager.getStore().is());
+ bool bDoc1_1 = DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion);
+ SaveODFItem item;
+ bool bSave1_1 = item.isLessODF1_2();
+
+ // see specification
+ //cvs: specs/www/appwide/security/Electronic_Signatures_and_Security.sxw
+ //Paragraph 'Behavior with regard to ODF 1.2'
+ //For both, macro and document
+ if ( (!bSave1_1 && bDoc1_1) || (bSave1_1 && bDoc1_1) )
+ {
+ //#4
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ XsResId(STR_XMLSECDLG_OLD_ODF_FORMAT)));
+ xBox->run();
+ ret = false;
+ }
+
+ //As of OOo 3.2 the document signature includes in macrosignatures.xml. That is
+ //adding a macro signature will break an existing document signature.
+ //The sfx2 will remove the documentsignature when the user adds a macro signature
+ if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Macros
+ && ret)
+ {
+ if (m_bHasDocumentSignature && !m_bWarningShowSignMacro)
+ {
+ //The warning says that the document signatures will be removed if the user
+ //continues. He can then either press 'OK' or 'NO'
+ //It the user presses 'Add' or 'Remove' several times then, then the warning
+ //is shown every time until the user presses 'OK'. From then on, the warning
+ //is not displayed anymore as long as the signatures dialog is alive.
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ XsResId(STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN)));
+ if (xBox->run() == RET_NO)
+ ret = false;
+ else
+ m_bWarningShowSignMacro = true;
+
+ }
+ }
+ return ret;
+}
+
+bool DigitalSignaturesDialog::canAdd()
+{
+ return canAddRemove();
+}
+
+bool DigitalSignaturesDialog::canRemove()
+{
+ bool bRet = true;
+
+ if ( maSignatureManager.getSignatureMode() == DocumentSignatureMode::Content )
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Question, VclButtonsType::YesNo,
+ XsResId(STR_XMLSECDLG_QUERY_REALLYREMOVE)));
+ short nDlgRet = xBox->run();
+ bRet = ( nDlgRet == RET_YES );
+ }
+
+ return (bRet && canAddRemove());
+}
+
+void DigitalSignaturesDialog::beforeRun()
+{
+ // Verify Signatures and add certificates to ListBox...
+ mbVerifySignatures = true;
+ ImplGetSignatureInformations(/*bUseTempStream=*/false, /*bCacheLastSignature=*/true);
+ ImplFillSignaturesBox();
+
+ // FIXME: Disable the "Use XAdES compliant signatures" checkbox if it is irrelevant. If it is
+ // enabled, set its initial state based on existing signatures, if any.
+
+ // If it is OOXML, the checkbox is irrelevant.
+
+ // How to find out here whether it is OOXML? I don't want to create a SignatureStreamHelper and
+ // check its nStorageFormat as that seems overly complicated and seems to have weird indirect
+ // consequences, as I noticed when I tried to use DocumentSignatureManager::IsXAdESRelevant()
+ // (which now is in #if 0).
+
+ if (!maSignatureManager.getCurrentSignatureInformations().empty())
+ {
+ // If the document has only SHA-1 signatures we probably want it to stay that way?
+ }
+
+ // Only verify once, content will not change.
+ // But for refreshing signature information, StartVerifySignatureHdl will be called after each add/remove
+ mbVerifySignatures = false;
+}
+
+short DigitalSignaturesDialog::run()
+{
+ beforeRun();
+ return GenericDialogController::run();
+}
+
+IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureHighlightHdl, weld::TreeView&, void)
+{
+ bool bSel = m_xSignaturesLB->get_selected_index() != -1;
+ m_xViewBtn->set_sensitive( bSel );
+ if ( m_xAddBtn->get_sensitive() ) // not read only
+ m_xRemoveBtn->set_sensitive( bSel );
+}
+
+IMPL_LINK_NOARG(DigitalSignaturesDialog, OKButtonHdl, weld::Button&, void)
+{
+ if (mbSignaturesChanged)
+ maSignatureManager.write(m_bAdESCompliant);
+
+ m_xDialog->response(RET_OK);
+}
+
+IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureSelectHdl, weld::TreeView&, bool)
+{
+ ImplShowSignaturesDetails();
+ return true;
+}
+
+IMPL_LINK_NOARG(DigitalSignaturesDialog, AdESCompliantCheckBoxHdl, weld::Toggleable&, void)
+{
+ m_bAdESCompliant = m_xAdESCompliantCB->get_active();
+}
+
+IMPL_LINK_NOARG(DigitalSignaturesDialog, ViewButtonHdl, weld::Button&, void)
+{
+ ImplShowSignaturesDetails();
+}
+
+IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, weld::Button&, void)
+{
+ if( ! canAdd())
+ return;
+ try
+ {
+ std::vector<uno::Reference<xml::crypto::XXMLSecurityContext>> xSecContexts
+ {
+ maSignatureManager.getSecurityContext()
+ };
+ // Gpg signing is only possible with ODF >= 1.2 documents
+ if (DocumentSignatureHelper::CanSignWithGPG(maSignatureManager.getStore(), m_sODFVersion))
+ xSecContexts.push_back(maSignatureManager.getGpgSecurityContext());
+
+ CertificateChooser aChooser(m_xDialog.get(), std::move(xSecContexts), UserAction::Sign);
+ if (aChooser.run() == RET_OK)
+ {
+ sal_Int32 nSecurityId;
+ if (!maSignatureManager.add(aChooser.GetSelectedCertificates()[0], aChooser.GetSelectedSecurityContext(),
+ aChooser.GetDescription(), nSecurityId, m_bAdESCompliant))
+ return;
+ mbSignaturesChanged = true;
+
+ xml::crypto::SecurityOperationStatus nStatus = xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED;
+
+ if (maSignatureManager.getStore().is())
+ // In the PDF case the signature information is only available after parsing.
+ nStatus = maSignatureManager.getSignatureHelper().GetSignatureInformation( nSecurityId ).nStatus;
+
+ if ( nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED )
+ {
+ mbSignaturesChanged = true;
+
+ // Can't simply remember current information, need parsing for getting full information :(
+ // We need to verify the signatures again, otherwise the status in the signature information
+ // will not contain
+ // SecurityOperationStatus_OPERATION_SUCCEEDED
+ mbVerifySignatures = true;
+ ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false);
+ ImplFillSignaturesBox();
+ }
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "xmlsecurity.dialogs", "adding a signature!" );
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Error, VclButtonsType::Ok,
+ XsResId(STR_XMLSECDLG_SIGNING_FAILED)));
+ xBox->run();
+ // Don't keep invalid entries...
+ ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false);
+ ImplFillSignaturesBox();
+ }
+}
+
+IMPL_LINK_NOARG(DigitalSignaturesDialog, RemoveButtonHdl, weld::Button&, void)
+{
+ if (!canRemove())
+ return;
+ int nEntry = m_xSignaturesLB->get_selected_index();
+ if (nEntry == -1)
+ return;
+
+ try
+ {
+ sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32();
+ maSignatureManager.remove(nSelected);
+
+ mbSignaturesChanged = true;
+
+ ImplFillSignaturesBox();
+ }
+ catch ( uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "xmlsecurity.dialogs", "Exception while removing a signature!" );
+ // Don't keep invalid entries...
+ ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/true);
+ ImplFillSignaturesBox();
+ }
+}
+
+IMPL_LINK_NOARG(DigitalSignaturesDialog, CertMgrButtonHdl, weld::Button&, void)
+{
+#ifdef _WIN32
+ // FIXME: call GpgME::dirInfo("bindir") somewhere in
+ // SecurityEnvironmentGpg or whatnot
+ // FIXME: perhaps poke GpgME for uiserver, and hope it returns something useful?
+ static const std::u16string_view aGUIServers[] = { u"Gpg4win\\kleopatra.exe",
+ u"Gpg4win\\bin\\kleopatra.exe",
+ u"GNU\\GnuPG\\kleopatra.exe",
+ u"GNU\\GnuPG\\launch-gpa.exe",
+ u"GNU\\GnuPG\\gpa.exe",
+ u"GnuPG\\bin\\gpa.exe",
+ u"GNU\\GnuPG\\bin\\kleopatra.exe",
+ u"GNU\\GnuPG\\bin\\launch-gpa.exe",
+ u"GNU\\GnuPG\\bin\\gpa.exe",
+ };
+ static const OUString aPath = [] {
+ OUString sRet;
+ PWSTR sPath = nullptr;
+ HRESULT hr
+ = SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, KF_FLAG_DEFAULT, nullptr, &sPath);
+ if (SUCCEEDED(hr))
+ {
+ sRet = o3tl::toU(sPath);
+ CoTaskMemFree(sPath);
+ }
+ return sRet;
+ }();
+ if (aPath.isEmpty())
+ return;
+#else
+ static const std::u16string_view aGUIServers[] = { u"kleopatra", u"seahorse", u"gpa", u"kgpg" };
+ const char* cPath = getenv("PATH");
+ if (!cPath)
+ return;
+ OUString aPath(cPath, strlen(cPath), osl_getThreadTextEncoding());
+#endif
+
+ OUString sFoundGUIServer, sExecutable;
+
+ for ( auto const &rServer : aGUIServers )
+ {
+ osl::FileBase::RC searchError = osl::File::searchFileURL(OUString(rServer), aPath, sFoundGUIServer );
+ if (searchError == osl::FileBase::E_None)
+ {
+ osl::File::getSystemPathFromFileURL( sFoundGUIServer, sExecutable );
+ break;
+ }
+
+ }
+
+ if ( !sExecutable.isEmpty() )
+ {
+ uno::Reference< uno::XComponentContext > xContext =
+ ::comphelper::getProcessComponentContext();
+ uno::Reference< css::system::XSystemShellExecute > xSystemShell(
+ css::system::SystemShellExecute::create(xContext) );
+
+ xSystemShell->execute( sExecutable, OUString(),
+ css::system::SystemShellExecuteFlags::DEFAULTS );
+ }
+ else
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ XsResId(STR_XMLSECDLG_NO_CERT_MANAGER)));
+ xInfoBox->run();
+ }
+}
+
+IMPL_LINK_NOARG(DigitalSignaturesDialog, StartVerifySignatureHdl, LinkParamNone*, bool)
+{
+ return mbVerifySignatures;
+}
+
+void DigitalSignaturesDialog::ImplFillSignaturesBox()
+{
+ m_xSignaturesLB->clear();
+
+ size_t nInfos = maSignatureManager.getCurrentSignatureInformations().size();
+ size_t nValidSigs = 0, nValidCerts = 0;
+ bool bAllNewSignatures = true;
+ bool bSomePartial = false;
+
+ if( nInfos )
+ {
+ for( size_t n = 0; n < nInfos; ++n )
+ {
+ DocumentSignatureAlgorithm mode = DocumentSignatureHelper::getDocumentAlgorithm(
+ m_sODFVersion, maSignatureManager.getCurrentSignatureInformations()[n]);
+ std::vector< OUString > aElementsToBeVerified;
+ if (maSignatureManager.getStore().is())
+ aElementsToBeVerified = DocumentSignatureHelper::CreateElementList(maSignatureManager.getStore(), maSignatureManager.getSignatureMode(), mode);
+
+ const SignatureInformation& rInfo = maSignatureManager.getCurrentSignatureInformations()[n];
+ uno::Reference< css::security::XCertificate > xCert = getCertificate(rInfo);
+
+ OUString aSubject;
+ OUString aIssuer;
+ OUString aDateTimeStr;
+ OUString aDescription;
+ OUString aType;
+
+ bool bCertValid = false;
+ if( xCert.is() )
+ {
+ //check the validity of the cert
+ try {
+ sal_Int32 certResult = getSecurityEnvironmentForCertificate(xCert)->verifyCertificate(xCert,
+ Sequence<uno::Reference<security::XCertificate> >());
+
+ bCertValid = certResult == css::security::CertificateValidity::VALID;
+ if ( bCertValid )
+ nValidCerts++;
+
+ } catch (css::uno::SecurityException& ) {
+ OSL_FAIL("Verification of certificate failed");
+ bCertValid = false;
+ }
+
+ aSubject = xmlsec::GetContentPart( xCert->getSubjectName(), xCert->getCertificateKind() );
+ aIssuer = xmlsec::GetContentPart( xCert->getIssuerName(), xCert->getCertificateKind() );
+ }
+ else if (!rInfo.ouGpgCertificate.isEmpty())
+ {
+ // In case we don't have the gpg key locally, get some data from the document
+ aIssuer = rInfo.ouGpgOwner;
+ }
+
+ aDateTimeStr = utl::GetDateTimeString( rInfo.stDateTime );
+ aDescription = rInfo.ouDescription;
+
+ // Decide type string.
+ if (maSignatureManager.getStore().is())
+ {
+ // OpenPGP
+ if (!rInfo.ouGpgCertificate.isEmpty())
+ aType = "OpenPGP";
+ // XML based: XAdES or not.
+ else if (rInfo.GetSigningCertificate() && !rInfo.GetSigningCertificate()->CertDigest.isEmpty())
+ aType = "XAdES";
+ else
+ aType = "XML-DSig";
+ }
+ else
+ {
+ // Assume PDF: PAdES or not.
+ if (rInfo.bHasSigningCertificate)
+ aType = "PAdES";
+ else
+ aType = "PDF";
+ }
+
+ bool bSigValid = rInfo.nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED;
+
+ if ( bSigValid )
+ {
+ if (maSignatureManager.getStore().is())
+ {
+ // ZIP based.
+ bSigValid = DocumentSignatureHelper::checkIfAllFilesAreSigned(
+ aElementsToBeVerified, rInfo, mode);
+ }
+ else
+ {
+ // Assume PDF.
+ bSigValid = !rInfo.bPartialDocumentSignature;
+ }
+
+ if( bSigValid )
+ nValidSigs++;
+ else
+ {
+ bSomePartial = true;
+ }
+ }
+
+ OUString sImage;
+ if (!bSigValid)
+ {
+ sImage = BMP_SIG_INVALID;
+ }
+ else if (!bCertValid)
+ {
+ sImage = BMP_SIG_NOT_VALIDATED;
+ }
+ //Check if the signature is a "old" document signature, that is, which was created
+ //by a version of OOo previous to 3.2
+ // If there is no storage, then it's pointless to check storage
+ // stream references.
+ else if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Content
+ && (maSignatureManager.getStore().is() && !DocumentSignatureHelper::isOOo3_2_Signature(
+ maSignatureManager.getCurrentSignatureInformations()[n])))
+ {
+ sImage = BMP_SIG_NOT_VALIDATED;
+ bAllNewSignatures = false;
+ }
+ else if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Content
+ && DocumentSignatureHelper::isOOo3_2_Signature(
+ maSignatureManager.getCurrentSignatureInformations()[n]))
+ {
+ sImage = BMP_SIG_VALID;
+ }
+ else if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Macros)
+ {
+ sImage = BMP_SIG_VALID;
+ }
+
+ m_xSignaturesLB->insert(nullptr, n, nullptr, nullptr,
+ &sImage, nullptr, false, nullptr);
+ m_xSignaturesLB->set_text(n, aSubject, 1);
+ m_xSignaturesLB->set_text(n, aIssuer, 2);
+ m_xSignaturesLB->set_text(n, aDateTimeStr, 3);
+ m_xSignaturesLB->set_text(n, aDescription, 4);
+ m_xSignaturesLB->set_text(n, aType, 5);
+ m_xSignaturesLB->set_id(n, OUString::number(n)); // misuse user data as index
+ }
+ }
+
+ bool bAllSigsValid = (nValidSigs == nInfos);
+ bool bAllCertsValid = (nValidCerts == nInfos);
+ bool bShowValidState = nInfos && (bAllSigsValid && bAllCertsValid && bAllNewSignatures);
+
+ m_xSigsValidImg->set_visible( bShowValidState);
+ m_xSigsValidFI->set_visible( bShowValidState );
+
+ bool bShowInvalidState = nInfos && !bAllSigsValid;
+
+ m_xSigsInvalidImg->set_visible( bShowInvalidState && !bSomePartial);
+ m_xSigsInvalidFI->set_visible( bShowInvalidState && !bSomePartial);
+
+ bool bShowNotValidatedState = nInfos && bAllSigsValid && !bAllCertsValid;
+
+ m_xSigsNotvalidatedImg->set_visible(bShowNotValidatedState);
+ m_xSigsNotvalidatedFI->set_visible(bShowNotValidatedState);
+
+ //bAllNewSignatures is always true if we are not in document mode
+ bool bShowOldSignature = nInfos && bAllSigsValid && bAllCertsValid && !bAllNewSignatures;
+ m_xSigsOldSignatureImg->set_visible(bShowOldSignature || bSomePartial);
+ m_xSigsOldSignatureFI->set_visible(bShowOldSignature || bSomePartial);
+
+ SignatureHighlightHdl(*m_xSignaturesLB);
+}
+
+uno::Reference<security::XCertificate> DigitalSignaturesDialog::getCertificate(const SignatureInformation& rInfo)
+{
+ uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = maSignatureManager.getSecurityEnvironment();
+ uno::Reference<xml::crypto::XSecurityEnvironment> xGpgSecEnv = maSignatureManager.getGpgSecurityEnvironment();
+ uno::Reference<security::XCertificate> xCert;
+
+ //First we try to get the certificate which is embedded in the XML Signature
+ if (xSecEnv.is() && rInfo.GetSigningCertificate() && !rInfo.GetSigningCertificate()->X509Certificate.isEmpty())
+ xCert = xSecEnv->createCertificateFromAscii(rInfo.GetSigningCertificate()->X509Certificate);
+ else {
+ //There must be an embedded certificate because we use it to get the
+ //issuer name. We cannot use /Signature/KeyInfo/X509Data/X509IssuerName
+ //because it could be modified by an attacker. The issuer is displayed
+ //in the digital signature dialog.
+ //Comparing the X509IssuerName with the one from the X509Certificate in order
+ //to find out if the X509IssuerName was modified does not work. See #i62684
+ SAL_WARN( "xmlsecurity.dialogs", "Could not find embedded certificate!");
+ }
+
+ //In case there is no embedded certificate we try to get it from a local store
+ if (!xCert.is() && xSecEnv.is() && rInfo.GetSigningCertificate())
+ {
+ xCert = xSecEnv->getCertificate(rInfo.GetSigningCertificate()->X509IssuerName,
+ xmlsecurity::numericStringToBigInteger(rInfo.GetSigningCertificate()->X509SerialNumber));
+ }
+ if (!xCert.is() && xGpgSecEnv.is() && !rInfo.ouGpgKeyID.isEmpty())
+ xCert = xGpgSecEnv->getCertificate( rInfo.ouGpgKeyID, xmlsecurity::numericStringToBigInteger(u"") );
+
+ SAL_WARN_IF( !xCert.is(), "xmlsecurity.dialogs", "Certificate not found and can't be created!" );
+
+ return xCert;
+}
+
+uno::Reference<xml::crypto::XSecurityEnvironment> DigitalSignaturesDialog::getSecurityEnvironmentForCertificate(const uno::Reference<security::XCertificate>& xCert)
+{
+ if (xCert->getCertificateKind() == CertificateKind_OPENPGP)
+ return maSignatureManager.getGpgSecurityEnvironment();
+ else if (xCert->getCertificateKind() == CertificateKind_X509)
+ return maSignatureManager.getSecurityEnvironment();
+
+ throw RuntimeException("Unknown certificate kind");
+}
+
+//If bUseTempStream is true then the temporary signature stream is used.
+//Otherwise the real signature stream is used.
+void DigitalSignaturesDialog::ImplGetSignatureInformations(bool bUseTempStream, bool bCacheLastSignature)
+{
+ maSignatureManager.read(bUseTempStream, bCacheLastSignature);
+ mbVerifySignatures = false;
+}
+
+void DigitalSignaturesDialog::ImplShowSignaturesDetails()
+{
+ int nEntry = m_xSignaturesLB->get_selected_index();
+ if (nEntry == -1)
+ return;
+
+ sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32();
+ const SignatureInformation& rInfo = maSignatureManager.getCurrentSignatureInformations()[ nSelected ];
+ uno::Reference<security::XCertificate> xCert = getCertificate(rInfo);
+
+ if ( xCert.is() )
+ {
+ if (m_xViewer)
+ m_xViewer->response(RET_OK);
+
+ uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = getSecurityEnvironmentForCertificate(xCert);
+ m_xViewer = std::make_shared<CertificateViewer>(m_xDialog.get(), xSecEnv, xCert, false, nullptr);
+ weld::DialogController::runAsync(m_xViewer, [this] (sal_Int32) { m_xViewer = nullptr; });
+ }
+ else
+ {
+ if (m_xInfoBox)
+ m_xInfoBox->response(RET_OK);
+
+ m_xInfoBox = std::shared_ptr<weld::MessageDialog>(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ XsResId(STR_XMLSECDLG_NO_CERT_FOUND)));
+ m_xInfoBox->runAsync(m_xInfoBox, [this] (sal_Int32) { m_xInfoBox = nullptr; });
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/dialogs/macrosecurity.cxx b/xmlsecurity/source/dialogs/macrosecurity.cxx
new file mode 100644
index 000000000..bf82606f4
--- /dev/null
+++ b/xmlsecurity/source/dialogs/macrosecurity.cxx
@@ -0,0 +1,446 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include <macrosecurity.hxx>
+#include <certificateviewer.hxx>
+#include <biginteger.hxx>
+#include <resourcemanager.hxx>
+#include <strings.hrc>
+
+#include <o3tl/safeint.hxx>
+#include <osl/file.hxx>
+#include <sal/log.hxx>
+
+#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
+#include <comphelper/sequence.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/xmlsechelper.hxx>
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/ui/dialogs/FolderPicker.hpp>
+#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
+#include <sfx2/filedlghelper.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/urlobj.hxx>
+#include <unotools/datetime.hxx>
+
+#include <vcl/svapp.hxx>
+
+using namespace comphelper;
+using namespace ::com::sun::star;
+
+
+IMPL_LINK_NOARG(MacroSecurity, OkBtnHdl, weld::Button&, void)
+{
+ m_xLevelTP->ClosePage();
+ m_xTrustSrcTP->ClosePage();
+ m_xDialog->response(RET_OK);
+}
+
+MacroSecurity::MacroSecurity(weld::Window* pParent,
+ const css::uno::Reference<css::xml::crypto::XSecurityEnvironment>& rxSecurityEnvironment)
+ : GenericDialogController(pParent, "xmlsec/ui/macrosecuritydialog.ui", "MacroSecurityDialog")
+ , m_xSecurityEnvironment(rxSecurityEnvironment)
+ , m_xTabCtrl(m_xBuilder->weld_notebook("tabcontrol"))
+ , m_xOkBtn(m_xBuilder->weld_button("ok"))
+ , m_xResetBtn(m_xBuilder->weld_button("reset"))
+{
+ m_xTabCtrl->connect_enter_page(LINK(this, MacroSecurity, ActivatePageHdl));
+
+ m_xLevelTP.reset(new MacroSecurityLevelTP(m_xTabCtrl->get_page("SecurityLevelPage"), this));
+ m_xTrustSrcTP.reset(new MacroSecurityTrustedSourcesTP(m_xTabCtrl->get_page("SecurityTrustPage"), this));
+
+ m_xTabCtrl->set_current_page("SecurityLevelPage");
+ m_xOkBtn->connect_clicked(LINK(this, MacroSecurity, OkBtnHdl));
+}
+
+IMPL_LINK(MacroSecurity, ActivatePageHdl, const OString&, rPage, void)
+{
+ if (rPage == "SecurityLevelPage")
+ m_xLevelTP->ActivatePage();
+ else if (rPage == "SecurityTrustPage")
+ m_xTrustSrcTP->ActivatePage();
+}
+
+MacroSecurityTP::MacroSecurityTP(weld::Container* pParent, const OUString& rUIXMLDescription,
+ const OString& rID, MacroSecurity* pDlg)
+ : m_xBuilder(Application::CreateBuilder(pParent, rUIXMLDescription))
+ , m_xContainer(m_xBuilder->weld_container(rID))
+ , m_pDlg(pDlg)
+{
+}
+
+void MacroSecurityTP::ActivatePage()
+{
+}
+
+MacroSecurityTP::~MacroSecurityTP()
+{
+}
+
+MacroSecurityLevelTP::MacroSecurityLevelTP(weld::Container* pParent, MacroSecurity* pDlg)
+ : MacroSecurityTP(pParent, "xmlsec/ui/securitylevelpage.ui", "SecurityLevelPage", pDlg)
+ , m_xVeryHighRB(m_xBuilder->weld_radio_button("vhigh"))
+ , m_xHighRB(m_xBuilder->weld_radio_button("high"))
+ , m_xMediumRB(m_xBuilder->weld_radio_button("med"))
+ , m_xLowRB(m_xBuilder->weld_radio_button("low"))
+ , m_xVHighImg(m_xBuilder->weld_widget("vhighimg"))
+ , m_xHighImg(m_xBuilder->weld_widget("highimg"))
+ , m_xMedImg(m_xBuilder->weld_widget("medimg"))
+ , m_xLowImg(m_xBuilder->weld_widget("lowimg"))
+{
+ m_xLowRB->connect_toggled( LINK( this, MacroSecurityLevelTP, RadioButtonHdl ) );
+ m_xMediumRB->connect_toggled( LINK( this, MacroSecurityLevelTP, RadioButtonHdl ) );
+ m_xHighRB->connect_toggled( LINK( this, MacroSecurityLevelTP, RadioButtonHdl ) );
+ m_xVeryHighRB->connect_toggled( LINK( this, MacroSecurityLevelTP, RadioButtonHdl ) );
+
+ int nPrefWidth(std::max({m_xVeryHighRB->get_preferred_size().Width(),
+ m_xHighRB->get_preferred_size().Width(),
+ m_xMediumRB->get_preferred_size().Width(),
+ m_xLowRB->get_preferred_size().Width()}));
+ int nMaxWidth = m_xLowRB->get_approximate_digit_width() * 60;
+ if (nPrefWidth > nMaxWidth)
+ {
+ m_xLowRB->set_label_wrap(true);
+ m_xLowRB->set_size_request(nMaxWidth, -1);
+ m_xMediumRB->set_label_wrap(true);
+ m_xMediumRB->set_size_request(nMaxWidth, -1);
+ m_xHighRB->set_label_wrap(true);
+ m_xHighRB->set_size_request(nMaxWidth, -1);
+ m_xVeryHighRB->set_label_wrap(true);
+ m_xVeryHighRB->set_size_request(nMaxWidth, -1);
+ }
+
+ mnCurLevel = static_cast<sal_uInt16>(SvtSecurityOptions::GetMacroSecurityLevel());
+ bool bReadonly = SvtSecurityOptions::IsReadOnly( SvtSecurityOptions::EOption::MacroSecLevel );
+
+ weld::RadioButton* pCheck = nullptr;
+ weld::Widget* pImage = nullptr;
+ switch (mnCurLevel)
+ {
+ case 3:
+ pCheck = m_xVeryHighRB.get();
+ pImage = m_xVHighImg.get();
+ break;
+ case 2:
+ pCheck = m_xHighRB.get();
+ pImage = m_xHighImg.get();
+ break;
+ case 1:
+ pCheck = m_xMediumRB.get();
+ pImage = m_xMedImg.get();
+ break;
+ case 0:
+ pCheck = m_xLowRB.get();
+ pImage = m_xLowImg.get();
+ break;
+ }
+ if (pCheck)
+ pCheck->set_active(true);
+ else
+ {
+ OSL_FAIL("illegal macro security level");
+ }
+ if (bReadonly && pImage)
+ {
+ pImage->show();
+ m_xVeryHighRB->set_sensitive(false);
+ m_xHighRB->set_sensitive(false);
+ m_xMediumRB->set_sensitive(false);
+ m_xLowRB->set_sensitive(false);
+ }
+}
+
+IMPL_LINK_NOARG(MacroSecurityLevelTP, RadioButtonHdl, weld::Toggleable&, void)
+{
+ sal_uInt16 nNewLevel = 0;
+ if( m_xVeryHighRB->get_active() )
+ nNewLevel = 3;
+ else if( m_xHighRB->get_active() )
+ nNewLevel = 2;
+ else if( m_xMediumRB->get_active() )
+ nNewLevel = 1;
+
+ if ( nNewLevel != mnCurLevel )
+ {
+ mnCurLevel = nNewLevel;
+ m_pDlg->EnableReset();
+ }
+}
+
+void MacroSecurityLevelTP::ClosePage()
+{
+ SvtSecurityOptions::SetMacroSecurityLevel( mnCurLevel );
+}
+
+void MacroSecurityTrustedSourcesTP::ImplCheckButtons()
+{
+ bool bCertSelected = m_xTrustCertLB->get_selected_index() != -1;
+ m_xViewCertPB->set_sensitive( bCertSelected );
+ m_xRemoveCertPB->set_sensitive( bCertSelected && !mbAuthorsReadonly);
+
+ bool bLocationSelected = m_xTrustFileLocLB->get_selected_index() != -1;
+ m_xRemoveLocPB->set_sensitive( bLocationSelected && !mbURLsReadonly);
+}
+
+void MacroSecurityTrustedSourcesTP::ShowBrokenCertificateError(std::u16string_view rData)
+{
+ OUString aMsg = XsResId(STR_BROKEN_MACRO_CERTIFICATE_DATA);
+ aMsg = aMsg.replaceFirst("%{data}", rData);
+ std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_pDlg->getDialog(),
+ VclMessageType::Error, VclButtonsType::Ok, aMsg));
+ xErrorBox->run();
+}
+
+IMPL_LINK_NOARG(MacroSecurityTrustedSourcesTP, ViewCertPBHdl, weld::Button&, void)
+{
+ int nEntry = m_xTrustCertLB->get_selected_index();
+ if (nEntry == -1)
+ return;
+
+ const sal_uInt16 nSelected = m_xTrustCertLB->get_id(nEntry).toUInt32();
+ uno::Reference< css::security::XCertificate > xCert;
+ try
+ {
+ xCert = m_pDlg->m_xSecurityEnvironment->getCertificate(m_aTrustedAuthors[nSelected].SubjectName,
+ xmlsecurity::numericStringToBigInteger(m_aTrustedAuthors[nSelected].SerialNumber));
+ }
+ catch (...)
+ {
+ TOOLS_WARN_EXCEPTION("xmlsecurity.dialogs", "matching certificate not found for: " << m_aTrustedAuthors[nSelected].SubjectName);
+ }
+
+ if (!xCert.is())
+ {
+ try
+ {
+ xCert = m_pDlg->m_xSecurityEnvironment->createCertificateFromAscii(m_aTrustedAuthors[nSelected].RawData);
+ }
+ catch (...)
+ {
+ TOOLS_WARN_EXCEPTION("xmlsecurity.dialogs", "certificate data couldn't be parsed: " << m_aTrustedAuthors[nSelected].RawData);
+ }
+ }
+
+ if ( xCert.is() )
+ {
+ CertificateViewer aViewer(m_pDlg->getDialog(), m_pDlg->m_xSecurityEnvironment, xCert, false, nullptr);
+ aViewer.run();
+ }
+ else
+ // should never happen, as we parsed the certificate data when we added it!
+ ShowBrokenCertificateError(m_aTrustedAuthors[nSelected].RawData);
+}
+
+IMPL_LINK_NOARG(MacroSecurityTrustedSourcesTP, RemoveCertPBHdl, weld::Button&, void)
+{
+ int nEntry = m_xTrustCertLB->get_selected_index();
+ if (nEntry != -1)
+ {
+ sal_uInt16 nAuthor = m_xTrustCertLB->get_id(nEntry).toUInt32();
+ m_aTrustedAuthors.erase(m_aTrustedAuthors.begin() + nAuthor);
+
+ FillCertLB();
+ ImplCheckButtons();
+ }
+}
+
+IMPL_LINK_NOARG(MacroSecurityTrustedSourcesTP, AddLocPBHdl, weld::Button&, void)
+{
+ try
+ {
+ uno::Reference < uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
+ uno::Reference < ui::dialogs::XFolderPicker2 > xFolderPicker = sfx2::createFolderPicker(xContext, m_pDlg->getDialog());
+
+ short nRet = xFolderPicker->execute();
+
+ if( ui::dialogs::ExecutableDialogResults::OK != nRet )
+ return;
+
+ OUString aPathStr = xFolderPicker->getDirectory();
+ INetURLObject aNewObj( aPathStr );
+ aNewObj.removeFinalSlash();
+
+ // then the new path also a URL else system path
+ OUString aSystemFileURL = ( aNewObj.GetProtocol() != INetProtocol::NotValid ) ?
+ aPathStr : aNewObj.getFSysPath( FSysStyle::Detect );
+
+ OUString aNewPathStr(aSystemFileURL);
+
+ if ( osl::FileBase::getSystemPathFromFileURL( aSystemFileURL, aSystemFileURL ) == osl::FileBase::E_None )
+ aNewPathStr = aSystemFileURL;
+
+ if (m_xTrustFileLocLB->find_text(aNewPathStr) == -1)
+ m_xTrustFileLocLB->append_text(aNewPathStr);
+
+ ImplCheckButtons();
+ }
+ catch( uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "xmlsecurity.dialogs", "MacroSecurityTrustedSourcesTP::AddLocPBHdl(): exception from folder picker" );
+ }
+}
+
+IMPL_LINK_NOARG(MacroSecurityTrustedSourcesTP, RemoveLocPBHdl, weld::Button&, void)
+{
+ sal_Int32 nSel = m_xTrustFileLocLB->get_selected_index();
+ if (nSel == -1)
+ return;
+
+ m_xTrustFileLocLB->remove(nSel);
+ // Trusted Path could not be removed (#i33584#)
+ // after remove an entry, select another one if exists
+ int nNewCount = m_xTrustFileLocLB->n_children();
+ if (nNewCount > 0)
+ {
+ if (nSel >= nNewCount)
+ nSel = nNewCount - 1;
+ m_xTrustFileLocLB->select(nSel);
+ }
+ ImplCheckButtons();
+}
+
+IMPL_LINK_NOARG(MacroSecurityTrustedSourcesTP, TrustCertLBSelectHdl, weld::TreeView&, void)
+{
+ ImplCheckButtons();
+}
+
+IMPL_LINK_NOARG(MacroSecurityTrustedSourcesTP, TrustFileLocLBSelectHdl, weld::TreeView&, void)
+{
+ ImplCheckButtons();
+}
+
+void MacroSecurityTrustedSourcesTP::FillCertLB(const bool bShowWarnings)
+{
+ m_xTrustCertLB->clear();
+
+ sal_uInt32 nEntries = m_aTrustedAuthors.size();
+
+ if ( !(nEntries && m_pDlg->m_xSecurityEnvironment.is()) )
+ return;
+
+ for( sal_uInt32 nEntry = 0 ; nEntry < nEntries ; ++nEntry )
+ {
+ SvtSecurityOptions::Certificate& rEntry = m_aTrustedAuthors[ nEntry ];
+
+ try
+ {
+ // create from RawData
+ uno::Reference< css::security::XCertificate > xCert = m_pDlg->m_xSecurityEnvironment->createCertificateFromAscii(rEntry.RawData);
+ m_xTrustCertLB->append(OUString::number(nEntry), xmlsec::GetContentPart(xCert->getSubjectName(), xCert->getCertificateKind()));
+ m_xTrustCertLB->set_text(nEntry, xmlsec::GetContentPart(xCert->getIssuerName(), xCert->getCertificateKind()), 1);
+ m_xTrustCertLB->set_text(nEntry, utl::GetDateTimeString(xCert->getNotValidAfter()), 2);
+ }
+ catch (...)
+ {
+ if (bShowWarnings)
+ {
+ TOOLS_WARN_EXCEPTION("xmlsecurity.dialogs", "certificate data couldn't be parsed: " << rEntry.RawData);
+ OUString sData = rEntry.RawData;
+ css::uno::Any tools_warn_exception(DbgGetCaughtException());
+ OUString sException = OStringToOUString(exceptionToString(tools_warn_exception), RTL_TEXTENCODING_UTF8);
+ if (!sException.isEmpty())
+ sData += " / " + sException;
+ ShowBrokenCertificateError(sData);
+ }
+ }
+ }
+}
+
+MacroSecurityTrustedSourcesTP::MacroSecurityTrustedSourcesTP(weld::Container* pParent, MacroSecurity* pDlg)
+ : MacroSecurityTP(pParent, "xmlsec/ui/securitytrustpage.ui", "SecurityTrustPage", pDlg)
+ , m_xTrustCertROFI(m_xBuilder->weld_image("lockcertimg"))
+ , m_xTrustCertLB(m_xBuilder->weld_tree_view("certificates"))
+ , m_xViewCertPB(m_xBuilder->weld_button("viewcert"))
+ , m_xRemoveCertPB(m_xBuilder->weld_button("removecert"))
+ , m_xTrustFileROFI(m_xBuilder->weld_image("lockfileimg"))
+ , m_xTrustFileLocLB(m_xBuilder->weld_tree_view("locations"))
+ , m_xAddLocPB(m_xBuilder->weld_button("addfile"))
+ , m_xRemoveLocPB(m_xBuilder->weld_button("removefile"))
+{
+ auto nColWidth = m_xTrustCertLB->get_approximate_digit_width() * 12;
+ std::vector<int> aWidths
+ {
+ o3tl::narrowing<int>(nColWidth * 2),
+ o3tl::narrowing<int>(nColWidth * 2)
+ };
+ m_xTrustCertLB->set_column_fixed_widths(aWidths);
+ m_xTrustCertLB->set_size_request(nColWidth * 5.5, m_xTrustCertLB->get_height_rows(5));
+
+ m_xTrustCertLB->connect_changed( LINK( this, MacroSecurityTrustedSourcesTP, TrustCertLBSelectHdl ) );
+ m_xViewCertPB->connect_clicked( LINK( this, MacroSecurityTrustedSourcesTP, ViewCertPBHdl ) );
+ m_xViewCertPB->set_sensitive(false);
+ m_xRemoveCertPB->connect_clicked( LINK( this, MacroSecurityTrustedSourcesTP, RemoveCertPBHdl ) );
+ m_xRemoveCertPB->set_sensitive(false);
+
+ m_xTrustFileLocLB->connect_changed( LINK( this, MacroSecurityTrustedSourcesTP, TrustFileLocLBSelectHdl ) );
+ m_xTrustFileLocLB->set_size_request(nColWidth * 5, m_xTrustFileLocLB->get_height_rows(5));
+ m_xAddLocPB->connect_clicked( LINK( this, MacroSecurityTrustedSourcesTP, AddLocPBHdl ) );
+ m_xRemoveLocPB->connect_clicked( LINK( this, MacroSecurityTrustedSourcesTP, RemoveLocPBHdl ) );
+ m_xRemoveLocPB->set_sensitive(false);
+
+ m_aTrustedAuthors = SvtSecurityOptions::GetTrustedAuthors();
+ mbAuthorsReadonly = SvtSecurityOptions::IsReadOnly( SvtSecurityOptions::EOption::MacroTrustedAuthors );
+ m_xTrustCertROFI->set_visible(mbAuthorsReadonly);
+
+ FillCertLB(true);
+
+ std::vector< OUString > aSecureURLs = SvtSecurityOptions::GetSecureURLs();
+ mbURLsReadonly = SvtSecurityOptions::IsReadOnly( SvtSecurityOptions::EOption::SecureUrls );
+ m_xTrustFileROFI->set_visible(mbURLsReadonly);
+ m_xAddLocPB->set_sensitive(!mbURLsReadonly);
+
+ for (const auto& rSecureURL : aSecureURLs)
+ {
+ OUString aSystemFileURL( rSecureURL );
+ osl::FileBase::getSystemPathFromFileURL( aSystemFileURL, aSystemFileURL );
+ m_xTrustFileLocLB->append_text(aSystemFileURL);
+ }
+}
+
+void MacroSecurityTrustedSourcesTP::ActivatePage()
+{
+ m_pDlg->EnableReset( false );
+ FillCertLB();
+}
+
+void MacroSecurityTrustedSourcesTP::ClosePage()
+{
+ sal_Int32 nEntryCnt = m_xTrustFileLocLB->n_children();
+ if( nEntryCnt )
+ {
+ std::vector< OUString > aSecureURLs;
+ for (sal_Int32 i = 0; i < nEntryCnt; ++i)
+ {
+ OUString aURL(m_xTrustFileLocLB->get_text(i));
+ osl::FileBase::getFileURLFromSystemPath( aURL, aURL );
+ aSecureURLs.push_back(aURL);
+ }
+
+ SvtSecurityOptions::SetSecureURLs( std::move(aSecureURLs) );
+ }
+ // Trusted Path could not be removed (#i33584#)
+ // don't forget to remove the old saved SecureURLs
+ else
+ SvtSecurityOptions::SetSecureURLs( std::vector< OUString >() );
+
+ SvtSecurityOptions::SetTrustedAuthors( m_aTrustedAuthors );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/buffernode.cxx b/xmlsecurity/source/framework/buffernode.cxx
new file mode 100644
index 000000000..cc6c37c18
--- /dev/null
+++ b/xmlsecurity/source/framework/buffernode.cxx
@@ -0,0 +1,886 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include "elementmark.hxx"
+#include "elementcollector.hxx"
+#include "buffernode.hxx"
+#include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp>
+#include <osl/diagnose.h>
+#include <rtl/ustrbuf.hxx>
+
+BufferNode::BufferNode( const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& xXMLElement )
+ :m_pParent(nullptr),
+ m_pBlocker(nullptr),
+ m_bAllReceived(false),
+ m_xXMLElement(xXMLElement)
+{
+}
+
+bool BufferNode::isECOfBeforeModifyIncluded(sal_Int32 nIgnoredSecurityId) const
+/****** BufferNode/isECOfBeforeModifyIncluded ********************************
+ *
+ * NAME
+ * isECOfBeforeModifyIncluded -- checks whether there is some
+ * ElementCollector on this BufferNode, that has BEFORE-MODIFY priority.
+ *
+ * SYNOPSIS
+ * bExist = isECOfBeforeModifyIncluded(nIgnoredSecurityId);
+ *
+ * FUNCTION
+ * checks each ElementCollector on this BufferNode, if all following
+ * conditions are satisfied, then returns true:
+ * 1. the ElementCollector's priority is BEFOREMODIFY;
+ * 2. the ElementCollector's securityId can't be ignored.
+ * otherwise, returns false.
+ *
+ * INPUTS
+ * nIgnoredSecurityId - the security Id to be ignored. If it equals
+ * to UNDEFINEDSECURITYID, then no security Id
+ * will be ignored.
+ *
+ * RESULT
+ * bExist - true if a match found, false otherwise
+ ******************************************************************************/
+{
+ return std::any_of(m_vElementCollectors.cbegin(), m_vElementCollectors.cend(),
+ [nIgnoredSecurityId](const ElementCollector* pElementCollector) {
+ return (nIgnoredSecurityId == css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID ||
+ pElementCollector->getSecurityId() != nIgnoredSecurityId) &&
+ (pElementCollector->getPriority() == css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY);
+ });
+}
+
+void BufferNode::setReceivedAll()
+/****** BufferNode/setReceiveAll *********************************************
+ *
+ * NAME
+ * setReceivedAll -- indicates that the element in this BufferNode has
+ * been completely buffered.
+ *
+ * SYNOPSIS
+ * setReceivedAll();
+ *
+ * FUNCTION
+ * sets the all-received flag and launches ElementCollector's notify
+ * process.
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * empty
+ ******************************************************************************/
+{
+ m_bAllReceived = true;
+ elementCollectorNotify();
+}
+
+
+void BufferNode::addElementCollector(const ElementCollector* pElementCollector)
+/****** BufferNode/addElementCollector ***************************************
+ *
+ * NAME
+ * addElementCollector -- adds a new ElementCollector to this BufferNode.
+ *
+ * SYNOPSIS
+ * addElementCollector(pElementCollector);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pElementCollector - the ElementCollector to be added
+ *
+ * RESULT
+ * empty
+ ******************************************************************************/
+{
+ m_vElementCollectors.push_back( pElementCollector );
+ const_cast<ElementCollector*>(pElementCollector)->setBufferNode(this);
+}
+
+void BufferNode::removeElementCollector(const ElementCollector* pElementCollector)
+/****** BufferNode/removeElementCollector ************************************
+ *
+ * NAME
+ * removeElementCollector -- removes an ElementCollector from this
+ * BufferNode.
+ *
+ * SYNOPSIS
+ * removeElementCollector(pElementCollector);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pElementCollector - the ElementCollector to be removed
+ *
+ * RESULT
+ * empty
+ ******************************************************************************/
+{
+ auto ii = std::find(m_vElementCollectors.begin(), m_vElementCollectors.end(), pElementCollector);
+ if (ii != m_vElementCollectors.end())
+ {
+ m_vElementCollectors.erase( ii );
+ const_cast<ElementCollector*>(pElementCollector)->setBufferNode(nullptr);
+ }
+}
+
+
+void BufferNode::setBlocker(const ElementMark* pBlocker)
+/****** BufferNode/setBlocker ************************************************
+ *
+ * NAME
+ * setBlocker -- adds a blocker to this BufferNode.
+ *
+ * SYNOPSIS
+ * setBlocker(pBlocker);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pBlocker - the new blocker to be attached
+ *
+ * RESULT
+ * empty
+ *
+ * NOTES
+ * Because there is only one blocker permitted for a BufferNode, so the
+ * old blocker on this BufferNode, if there is one, will be overcasted.
+ ******************************************************************************/
+{
+ OSL_ASSERT(!(m_pBlocker != nullptr && pBlocker != nullptr));
+
+ m_pBlocker = const_cast<ElementMark*>(pBlocker);
+ if (m_pBlocker != nullptr)
+ {
+ m_pBlocker->setBufferNode(this);
+ }
+}
+
+OUString BufferNode::printChildren() const
+/****** BufferNode/printChildren *********************************************
+ *
+ * NAME
+ * printChildren -- prints children information into a string.
+ *
+ * SYNOPSIS
+ * result = printChildren();
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * result - the information string
+ ******************************************************************************/
+{
+ OUStringBuffer rc;
+
+ for( const ElementCollector* ii : m_vElementCollectors )
+ {
+ rc.append("BufID=" + OUString::number(ii->getBufferId()));
+
+ if (ii->getModify())
+ {
+ rc.append("[M]");
+ }
+
+ rc.append(",Pri=");
+
+ switch (ii->getPriority())
+ {
+ case css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY:
+ rc.append("BEFOREMODIFY");
+ break;
+ case css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY:
+ rc.append("AFTERMODIFY");
+ break;
+ default:
+ rc.append("UNKNOWN");
+ break;
+ }
+
+ rc.append("(SecID=" + OUString::number(ii->getSecurityId()) + ") ");
+ }
+
+ return rc.makeStringAndClear();
+}
+
+bool BufferNode::hasAnything() const
+/****** BufferNode/hasAnything ***********************************************
+ *
+ * NAME
+ * hasAnything -- checks whether there is any ElementCollector or blocker
+ * on this BufferNode.
+ *
+ * SYNOPSIS
+ * bExist = hasAnything();
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * bExist - true if there is, false otherwise.
+ ******************************************************************************/
+{
+ return (m_pBlocker || !m_vElementCollectors.empty());
+}
+
+bool BufferNode::hasChildren() const
+/****** BufferNode/hasChildren ***********************************************
+ *
+ * NAME
+ * hasChildren -- checks whether this BufferNode has any child
+ * BufferNode.
+ *
+ * SYNOPSIS
+ * bExist = hasChildren();
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * bExist - true if there is, false otherwise.
+ ******************************************************************************/
+{
+ return (!m_vChildren.empty());
+}
+
+std::vector< std::unique_ptr<BufferNode> > const & BufferNode::getChildren() const
+{
+ return m_vChildren;
+}
+
+std::vector< std::unique_ptr<BufferNode> > BufferNode::releaseChildren()
+{
+ return std::move(m_vChildren);
+}
+
+const BufferNode* BufferNode::getFirstChild() const
+/****** BufferNode/getFirstChild *********************************************
+ *
+ * NAME
+ * getFirstChild -- retrieves the first child BufferNode.
+ *
+ * SYNOPSIS
+ * child = getFirstChild();
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * child - the first child BufferNode, or NULL if there is no child
+ * BufferNode.
+ ******************************************************************************/
+{
+ BufferNode* rc = nullptr;
+
+ if (!m_vChildren.empty())
+ {
+ rc = m_vChildren.front().get();
+ }
+
+ return rc;
+}
+
+void BufferNode::addChild(std::unique_ptr<BufferNode> pChild, sal_Int32 nPosition)
+/****** BufferNode/addChild(pChild,nPosition) ********************************
+ *
+ * NAME
+ * addChild -- inserts a child BufferNode at specific position.
+ *
+ * SYNOPSIS
+ * addChild(pChild, nPosition);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pChild - the child BufferNode to be added.
+ * nPosition - the position where the new child locates.
+ *
+ * RESULT
+ * empty
+ *
+ * NOTES
+ * If the nPosition is -1, then the new child BufferNode is appended
+ * at the end.
+ ******************************************************************************/
+{
+ if (nPosition == -1)
+ {
+ m_vChildren.push_back( std::move(pChild) );
+ }
+ else
+ {
+ m_vChildren.insert(m_vChildren.begin() + nPosition, std::move(pChild));
+ }
+}
+
+void BufferNode::addChild(std::unique_ptr<BufferNode> pChild)
+/****** BufferNode/addChild() ************************************************
+ *
+ * NAME
+ * addChild -- add a new child BufferNode.
+ *
+ * SYNOPSIS
+ * addChild(pChild);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pChild - the child BufferNode to be added.
+ *
+ * RESULT
+ * empty
+ *
+ * NOTES
+ * The new child BufferNode is appended at the end.
+ ******************************************************************************/
+{
+ addChild(std::move(pChild), -1);
+}
+
+void BufferNode::removeChild(const BufferNode* pChild)
+/****** BufferNode/removeChild ***********************************************
+ *
+ * NAME
+ * removeChild -- removes and deletes a child BufferNode from the children list.
+ *
+ * SYNOPSIS
+ * removeChild(pChild);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pChild - the child BufferNode to be removed
+ *
+ * RESULT
+ * empty
+ ******************************************************************************/
+{
+ auto ii = std::find_if(m_vChildren.begin(), m_vChildren.end(),
+ [pChild] (const std::unique_ptr<BufferNode>& i)
+ { return i.get() == pChild; });
+ if (ii != m_vChildren.end())
+ m_vChildren.erase( ii );
+}
+
+sal_Int32 BufferNode::indexOfChild(const BufferNode* pChild) const
+/****** BufferNode/indexOfChild **********************************************
+ *
+ * NAME
+ * indexOfChild -- gets the index of a child BufferNode.
+ *
+ * SYNOPSIS
+ * index = indexOfChild(pChild);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pChild - the child BufferNode whose index to be gotten
+ *
+ * RESULT
+ * index - the index of that child BufferNode. If that child BufferNode
+ * is not found, -1 is returned.
+ ******************************************************************************/
+{
+ auto ii = std::find_if(m_vChildren.begin(), m_vChildren.end(),
+ [pChild] (const std::unique_ptr<BufferNode>& i)
+ { return i.get() == pChild; });
+ if (ii == m_vChildren.end())
+ return -1;
+
+ return std::distance(m_vChildren.begin(), ii);
+}
+
+
+void BufferNode::setParent(const BufferNode* pParent)
+{
+ m_pParent = const_cast<BufferNode*>(pParent);
+}
+
+const BufferNode* BufferNode::getNextSibling() const
+/****** BufferNode/getNextSibling ********************************************
+ *
+ * NAME
+ * getNextSibling -- retrieves the next sibling BufferNode.
+ *
+ * SYNOPSIS
+ * sibling = getNextSibling();
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * sibling - the next sibling BufferNode, or NULL if there is none.
+ ******************************************************************************/
+{
+ BufferNode* rc = nullptr;
+
+ if (m_pParent != nullptr)
+ {
+ rc = const_cast<BufferNode*>(m_pParent->getNextChild(this));
+ }
+
+ return rc;
+}
+
+const BufferNode* BufferNode::isAncestor(const BufferNode* pDescendant) const
+/****** BufferNode/isAncestor ************************************************
+ *
+ * NAME
+ * isAncestor -- checks whether this BufferNode is an ancestor of another
+ * BufferNode.
+ *
+ * SYNOPSIS
+ * bIs = isAncestor(pDescendant);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pDescendant - the BufferNode to be checked as a descendant
+ *
+ * RESULT
+ * bIs - true if this BufferNode is an ancestor of the pDescendant,
+ * false otherwise.
+ ******************************************************************************/
+{
+ BufferNode* rc = nullptr;
+
+ if (pDescendant != nullptr)
+ {
+ auto ii = std::find_if(m_vChildren.cbegin(), m_vChildren.cend(),
+ [&pDescendant](const std::unique_ptr<BufferNode>& pChild) {
+ return (pChild.get() == pDescendant) || (pChild->isAncestor(pDescendant) != nullptr);
+ });
+
+ if (ii != m_vChildren.end())
+ rc = ii->get();
+ }
+
+ return rc;
+}
+
+bool BufferNode::isPrevious(const BufferNode* pFollowing) const
+/****** BufferNode/isPrevious ************************************************
+ *
+ * NAME
+ * isPrevious -- checks whether this BufferNode is ahead of another
+ * BufferNode in the tree order.
+ *
+ * SYNOPSIS
+ * bIs = isPrevious(pFollowing);
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pFollowing - the BufferNode to be checked as a following
+ *
+ * RESULT
+ * bIs - true if this BufferNode is ahead in the tree order, false
+ * otherwise.
+ ******************************************************************************/
+{
+ bool rc = false;
+
+ BufferNode* pNextBufferNode = const_cast<BufferNode*>(getNextNodeByTreeOrder());
+ while (pNextBufferNode != nullptr)
+ {
+ if (pNextBufferNode == pFollowing)
+ {
+ rc = true;
+ break;
+ }
+
+ pNextBufferNode = const_cast<BufferNode*>(pNextBufferNode->getNextNodeByTreeOrder());
+ }
+
+ return rc;
+}
+
+const BufferNode* BufferNode::getNextNodeByTreeOrder() const
+/****** BufferNode/getNextNodeByTreeOrder ************************************
+ *
+ * NAME
+ * getNextNodeByTreeOrder -- retrieves the next BufferNode in the tree
+ * order.
+ *
+ * SYNOPSIS
+ * next = getNextNodeByTreeOrder();
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * next - the BufferNode following this BufferNode in the tree order,
+ * or NULL if there is none.
+ *
+ * NOTES
+ * The "next" node in tree order is defined as:
+ * 1. If a node has children, then the first child is;
+ * 2. otherwise, if it has a following sibling, then this sibling node is;
+ * 3. otherwise, if it has a parent node, the parent's next sibling
+ * node is;
+ * 4. otherwise, no "next" node exists.
+ ******************************************************************************/
+{
+ /*
+ * If this buffer node has m_vChildren, then return the first
+ * child.
+ */
+ if (hasChildren())
+ {
+ return getFirstChild();
+ }
+
+ /*
+ * Otherwise, it this buffer node has a following sibling,
+ * then return that sibling.
+ */
+ BufferNode* pNextSibling = const_cast<BufferNode*>(getNextSibling());
+ if (pNextSibling != nullptr)
+ {
+ return pNextSibling;
+ }
+
+ /*
+ * Otherwise, it this buffer node has parent, then return
+ * its parent's following sibling.
+ */
+ BufferNode* pNode = const_cast<BufferNode*>(this);
+ BufferNode* pParent;
+ BufferNode* pNextSiblingParent = nullptr;
+
+ do
+ {
+ if (pNode == nullptr)
+ {
+ break;
+ }
+
+ pParent = const_cast<BufferNode*>(pNode->getParent());
+ if (pParent != nullptr)
+ {
+ pNextSiblingParent = const_cast<BufferNode*>(pParent->getNextSibling());
+ }
+ pNode = pParent;
+
+ } while (pNextSiblingParent == nullptr);
+
+ return pNextSiblingParent;
+}
+
+
+void BufferNode::setXMLElement( const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& xXMLElement )
+{
+ m_xXMLElement = xXMLElement;
+}
+
+void BufferNode::notifyBranch()
+/****** BufferNode/notifyBranch **********************************************
+ *
+ * NAME
+ * notifyBranch -- notifies each BufferNode in the branch of this
+ * BufferNode in the tree order.
+ *
+ * SYNOPSIS
+ * notifyBranch();
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * empty
+ ******************************************************************************/
+{
+ for( std::unique_ptr<BufferNode>& pBufferNode : m_vChildren )
+ {
+ pBufferNode->elementCollectorNotify();
+ pBufferNode->notifyBranch();
+ }
+}
+
+void BufferNode::elementCollectorNotify()
+/****** BufferNode/elementCollectorNotify ************************************
+ *
+ * NAME
+ * elementCollectorNotify -- notifies this BufferNode.
+ *
+ * SYNOPSIS
+ * elementCollectorNotify();
+ *
+ * FUNCTION
+ * Notifies this BufferNode if the notification is not suppressed.
+ *
+ * INPUTS
+ * empty
+ *
+ * RESULT
+ * child - the first child BufferNode, or NULL if there is no child
+ * BufferNode.
+ ******************************************************************************/
+{
+ if (m_vElementCollectors.empty())
+ return;
+
+ css::xml::crypto::sax::ElementMarkPriority nMaxPriority = css::xml::crypto::sax::ElementMarkPriority_MINIMUM;
+ css::xml::crypto::sax::ElementMarkPriority nPriority;
+
+ /*
+ * get the max priority among ElementCollectors on this BufferNode
+ */
+ for( const ElementCollector* pElementCollector : m_vElementCollectors )
+ {
+ nPriority = pElementCollector->getPriority();
+ if (nPriority > nMaxPriority)
+ {
+ nMaxPriority = nPriority;
+ }
+ }
+
+ std::vector< const ElementCollector* > vElementCollectors( m_vElementCollectors );
+
+ for( const ElementCollector* ii : vElementCollectors )
+ {
+ ElementCollector* pElementCollector = const_cast<ElementCollector*>(ii);
+ nPriority = pElementCollector->getPriority();
+ bool bToModify = pElementCollector->getModify();
+
+ /*
+ * Only ElementCollector with the max priority can
+ * perform notify operation.
+ * Moreover, if any blocker exists in the subtree of
+ * this BufferNode, this ElementCollector can't do notify
+ * unless its priority is BEFOREMODIFY.
+ */
+ if (nPriority == nMaxPriority &&
+ (nPriority == css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY ||
+ !isBlockerInSubTreeIncluded(pElementCollector->getSecurityId())))
+ {
+ /*
+ * If this ElementCollector will modify the buffered element, then
+ * special attention must be paid.
+ *
+ * If there is any ElementCollector in the subtree or any ancestor
+ * ElementCollector with PRI_BEFPREMODIFY priority, this
+ * ElementCollector can't perform notify operation, otherwise, it
+ * will destroy the buffered element, in turn, ElementCollectors
+ * mentioned above can't perform their mission.
+ */
+ //if (!(nMaxPriority == css::xml::crypto::sax::ElementMarkPriority_PRI_MODIFY &&
+ if (!(bToModify &&
+ (isECInSubTreeIncluded(pElementCollector->getSecurityId()) ||
+ isECOfBeforeModifyInAncestorIncluded(pElementCollector->getSecurityId()))
+ ))
+ {
+ pElementCollector->notifyListener();
+ }
+ }
+ }
+}
+
+bool BufferNode::isECInSubTreeIncluded(sal_Int32 nIgnoredSecurityId) const
+/****** BufferNode/isECInSubTreeIncluded *************************************
+ *
+ * NAME
+ * isECInSubTreeIncluded -- checks whether there is any ElementCollector
+ * in the branch of this BufferNode.
+ *
+ * SYNOPSIS
+ * bExist = isECInSubTreeIncluded(nIgnoredSecurityId);
+ *
+ * FUNCTION
+ * checks each BufferNode in the branch of this BufferNode, if there is
+ * an ElementCollector whose signatureId is not ignored, then return
+ * true, otherwise, false returned.
+ *
+ * INPUTS
+ * nIgnoredSecurityId - the security Id to be ignored. If it equals
+ * to UNDEFINEDSECURITYID, then no security Id
+ * will be ignored.
+ *
+ * RESULT
+ * bExist - true if a match found, false otherwise.
+ ******************************************************************************/
+{
+ bool rc = std::any_of(m_vElementCollectors.begin(), m_vElementCollectors.end(),
+ [nIgnoredSecurityId](const ElementCollector* pElementCollector) {
+ return nIgnoredSecurityId == css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID ||
+ pElementCollector->getSecurityId() != nIgnoredSecurityId;
+ });
+
+ if ( !rc )
+ {
+ rc = std::any_of(m_vChildren.begin(), m_vChildren.end(),
+ [nIgnoredSecurityId](const std::unique_ptr<BufferNode>& pBufferNode) {
+ return pBufferNode->isECInSubTreeIncluded(nIgnoredSecurityId);
+ });
+ }
+
+ return rc;
+}
+
+bool BufferNode::isECOfBeforeModifyInAncestorIncluded(sal_Int32 nIgnoredSecurityId) const
+/****** BufferNode/isECOfBeforeModifyInAncestorIncluded **********************
+ *
+ * NAME
+ * isECOfBeforeModifyInAncestorIncluded -- checks whether there is some
+ * ancestor BufferNode which has ElementCollector with PRI_BEFPREMODIFY
+ * priority.
+ *
+ * SYNOPSIS
+ * bExist = isECOfBeforeModifyInAncestorIncluded(nIgnoredSecurityId);
+ *
+ * FUNCTION
+ * checks each ancestor BufferNode through the parent link, if there is
+ * an ElementCollector with PRI_BEFPREMODIFY priority and its
+ * signatureId is not ignored, then return true, otherwise, false
+ * returned.
+ *
+ * INPUTS
+ * nIgnoredSecurityId - the security Id to be ignored. If it equals
+ * to UNDEFINEDSECURITYID, then no security Id
+ * will be ignored.
+ *
+ * RESULT
+ * bExist - true if a match found, false otherwise.
+ ******************************************************************************/
+{
+ bool rc = false;
+
+ BufferNode* pParentNode = m_pParent;
+ while (pParentNode != nullptr)
+ {
+ if (pParentNode->isECOfBeforeModifyIncluded(nIgnoredSecurityId))
+ {
+ rc = true;
+ break;
+ }
+
+ pParentNode = const_cast<BufferNode*>(pParentNode->getParent());
+ }
+
+ return rc;
+}
+
+bool BufferNode::isBlockerInSubTreeIncluded(sal_Int32 nIgnoredSecurityId) const
+/****** BufferNode/isBlockerInSubTreeIncluded ********************************
+ *
+ * NAME
+ * isBlockerInSubTreeIncluded -- checks whether there is some BufferNode
+ * which has blocker on it
+ *
+ * SYNOPSIS
+ * bExist = isBlockerInSubTreeIncluded(nIgnoredSecurityId);
+ *
+ * FUNCTION
+ * checks each BufferNode in the branch of this BufferNode, if one has
+ * a blocker on it, and the blocker's securityId is not ignored, then
+ * returns true; otherwise, false returns.
+ *
+ * INPUTS
+ * nIgnoredSecurityId - the security Id to be ignored. If it equals
+ * to UNDEFINEDSECURITYID, then no security Id
+ * will be ignored.
+ *
+ * RESULT
+ * bExist - true if a match found, false otherwise.
+ ******************************************************************************/
+{
+ return std::any_of(m_vChildren.begin(), m_vChildren.end(),
+ [nIgnoredSecurityId](const std::unique_ptr<BufferNode>& pBufferNode) {
+ ElementMark* pBlocker = pBufferNode->getBlocker();
+ return (pBlocker != nullptr &&
+ (nIgnoredSecurityId == css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID ||
+ pBlocker->getSecurityId() != nIgnoredSecurityId )) ||
+ pBufferNode->isBlockerInSubTreeIncluded(nIgnoredSecurityId);
+ });
+}
+
+const BufferNode* BufferNode::getNextChild(const BufferNode* pChild) const
+/****** BufferNode/getNextChild **********************************************
+ *
+ * NAME
+ * getNextChild -- get the next child BufferNode.
+ *
+ * SYNOPSIS
+ * nextChild = getNextChild();
+ *
+ * FUNCTION
+ * see NAME
+ *
+ * INPUTS
+ * pChild - the child BufferNode whose next node is retrieved.
+ *
+ * RESULT
+ * nextChild - the next child BufferNode after the pChild, or NULL if
+ * there is none.
+ ******************************************************************************/
+{
+ BufferNode* rc = nullptr;
+ bool bChildFound = false;
+
+ for( std::unique_ptr<BufferNode> const & i : m_vChildren )
+ {
+ if (bChildFound)
+ {
+ rc = i.get();
+ break;
+ }
+
+ if( i.get() == pChild )
+ {
+ bChildFound = true;
+ }
+ }
+
+ return rc;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/buffernode.hxx b/xmlsecurity/source/framework/buffernode.hxx
new file mode 100644
index 000000000..0202195de
--- /dev/null
+++ b/xmlsecurity/source/framework/buffernode.hxx
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <memory>
+#include <vector>
+
+namespace com::sun::star::xml::wrapper
+{
+class XXMLElementWrapper;
+}
+
+class ElementMark;
+class ElementCollector;
+
+class BufferNode final
+/****** buffernode.hxx/CLASS BufferNode ***************************************
+ *
+ * NAME
+ * BufferNode -- Class to maintain the tree of buffered elements
+ *
+ * FUNCTION
+ * One BufferNode object represents a buffered element in the document
+ * wrapper component.
+ * All BufferNode objects construct a tree which has the same structure
+ * of all buffered elements. That is to say, if one buffered element is
+ * an ancestor of another buffered element, then the corresponding
+ * BufferNode objects are also in ancestor/descendant relationship.
+ * This class is used to manipulate the tree of buffered elements.
+ ******************************************************************************/
+{
+private:
+ /* the parent BufferNode */
+ BufferNode* m_pParent;
+
+ /* all child BufferNodes */
+ std::vector<std::unique_ptr<BufferNode>> m_vChildren;
+
+ /* all ElementCollector holding this BufferNode */
+ std::vector<const ElementCollector*> m_vElementCollectors;
+
+ /*
+ * the blocker holding this BufferNode, one BufferNode can have one
+ * blocker at most
+ */
+ ElementMark* m_pBlocker;
+
+ /*
+ * whether the element has completely buffered by the document wrapper
+ * component
+ */
+ bool m_bAllReceived;
+
+ /* the XMLElementWrapper of the buffered element */
+ css::uno::Reference<css::xml::wrapper::XXMLElementWrapper> m_xXMLElement;
+
+private:
+ bool isECInSubTreeIncluded(sal_Int32 nIgnoredSecurityId) const;
+ bool isECOfBeforeModifyInAncestorIncluded(sal_Int32 nIgnoredSecurityId) const;
+ bool isBlockerInSubTreeIncluded(sal_Int32 nIgnoredSecurityId) const;
+ const BufferNode* getNextChild(const BufferNode* pChild) const;
+
+public:
+ explicit BufferNode(
+ const css::uno::Reference<css::xml::wrapper::XXMLElementWrapper>& xXMLElement);
+
+ bool isECOfBeforeModifyIncluded(sal_Int32 nIgnoredSecurityId) const;
+ void setReceivedAll();
+ bool isAllReceived() const { return m_bAllReceived; }
+ void addElementCollector(const ElementCollector* pElementCollector);
+ void removeElementCollector(const ElementCollector* pElementCollector);
+ ElementMark* getBlocker() const { return m_pBlocker; }
+ void setBlocker(const ElementMark* pBlocker);
+ OUString printChildren() const;
+ bool hasAnything() const;
+ bool hasChildren() const;
+ std::vector<std::unique_ptr<BufferNode>> const& getChildren() const;
+ std::vector<std::unique_ptr<BufferNode>> releaseChildren();
+ const BufferNode* getFirstChild() const;
+ void addChild(std::unique_ptr<BufferNode> pChild, sal_Int32 nPosition);
+ void addChild(std::unique_ptr<BufferNode> pChild);
+ void removeChild(const BufferNode* pChild);
+ sal_Int32 indexOfChild(const BufferNode* pChild) const;
+ const BufferNode* getParent() const { return m_pParent; }
+ void setParent(const BufferNode* pParent);
+ const BufferNode* getNextSibling() const;
+ const BufferNode* isAncestor(const BufferNode* pDescendant) const;
+ bool isPrevious(const BufferNode* pFollowing) const;
+ const BufferNode* getNextNodeByTreeOrder() const;
+ const css::uno::Reference<css::xml::wrapper::XXMLElementWrapper>& getXMLElement() const
+ {
+ return m_xXMLElement;
+ }
+ void
+ setXMLElement(const css::uno::Reference<css::xml::wrapper::XXMLElementWrapper>& xXMLElement);
+ void notifyBranch();
+ void elementCollectorNotify();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/elementcollector.cxx b/xmlsecurity/source/framework/elementcollector.cxx
new file mode 100644
index 000000000..7801d6328
--- /dev/null
+++ b/xmlsecurity/source/framework/elementcollector.cxx
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include "elementmark.hxx"
+#include "elementcollector.hxx"
+#include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp>
+#include <com/sun/star/xml/crypto/sax/XReferenceResolvedListener.hpp>
+
+ElementCollector::ElementCollector(
+ sal_Int32 nBufferId,
+ css::xml::crypto::sax::ElementMarkPriority nPriority,
+ bool bToModify,
+ const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& xReferenceResolvedListener)
+ :ElementMark(css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID, nBufferId),
+ m_nPriority(nPriority),
+ m_bToModify(bToModify),
+ m_bAbleToNotify(false),
+ m_bNotified(false),
+ m_xReferenceResolvedListener(xReferenceResolvedListener)
+/****** ElementCollector/ElementCollector *************************************
+ *
+ * NAME
+ * ElementCollector -- constructor method
+ *
+ * SYNOPSIS
+ * ElementCollector(nSecurityId, nBufferId, nPriority, bToModify
+ * xReferenceResolvedListener);
+ *
+ * FUNCTION
+ * construct an ElementCollector object.
+ *
+ * INPUTS
+ * nSecurityId - represents which security entity the buffer node is
+ * related with. Either a signature or an encryption is
+ * a security entity.
+ * nBufferId - the id of the element buffered in the document
+ * wrapper component. The document wrapper component
+ * uses this id to search the particular buffered
+ * element.
+ * nPriority - the priority value. ElementCollector with lower
+ * priority value can't notify until all ElementCollectors
+ * with higher priority value have notified.
+ * bToModify - A flag representing whether this ElementCollector
+ * notification will cause the modification of its working
+ * element.
+ * xReferenceResolvedListener
+ * - the listener that this ElementCollector notifies to.
+ ******************************************************************************/
+{
+ m_type = css::xml::crypto::sax::ElementMarkType_ELEMENTCOLLECTOR;
+}
+
+
+void ElementCollector::notifyListener()
+/****** ElementCollector/notifyListener ***************************************
+ *
+ * NAME
+ * notifyListener -- enable the ability to notify the listener
+ *
+ * SYNOPSIS
+ * notifyListener();
+ *
+ * FUNCTION
+ * enable the ability to notify the listener and try to notify then.
+ ******************************************************************************/
+{
+ m_bAbleToNotify = true;
+ doNotify();
+}
+
+void ElementCollector::setReferenceResolvedListener(
+ const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& xReferenceResolvedListener)
+/****** ElementCollector/setReferenceResolvedListener *************************
+ *
+ * NAME
+ * setReferenceResolvedListener -- configures a listener for the buffer
+ * node in this object
+ *
+ * SYNOPSIS
+ * setReferenceResolvedListener(xReferenceResolvedListener);
+ *
+ * FUNCTION
+ * configures a new listener and try to notify then.
+ *
+ * INPUTS
+ * xReferenceResolvedListener - the new listener
+ ******************************************************************************/
+{
+ m_xReferenceResolvedListener = xReferenceResolvedListener;
+ doNotify();
+}
+
+void ElementCollector::doNotify()
+/****** ElementCollector/doNotify *********************************************
+ *
+ * NAME
+ * doNotify -- tries to notify the listener
+ *
+ * SYNOPSIS
+ * doNotify();
+ *
+ * FUNCTION
+ * notifies the listener when all below conditions are satisfied:
+ * the listener has not been notified;
+ * the notify right is granted;
+ * the listener has already been configured;
+ * the security id has already been configure
+ ******************************************************************************/
+{
+ if (!m_bNotified &&
+ m_bAbleToNotify &&
+ m_xReferenceResolvedListener.is() &&
+ m_nSecurityId != css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID)
+ {
+ m_bNotified = true;
+ m_xReferenceResolvedListener->referenceResolved(m_nBufferId);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/elementcollector.hxx b/xmlsecurity/source/framework/elementcollector.hxx
new file mode 100644
index 000000000..0f797572a
--- /dev/null
+++ b/xmlsecurity/source/framework/elementcollector.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include "elementmark.hxx"
+#include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+
+namespace com::sun::star::xml::crypto::sax { class XReferenceResolvedListener; }
+
+class ElementCollector : public ElementMark
+/****** elementcollector.hxx/CLASS ElementCollector ***************************
+ *
+ * NAME
+ * ElementCollector -- Class to manipulate an element collector
+ *
+ * FUNCTION
+ * This class is derived from the ElementMark class. Beyond the function
+ * of the ElementMark class, this class also maintains the priority, and
+ * manages the notify process
+ ******************************************************************************/
+{
+private:
+ /*
+ * the notify priority, is one of following values:
+ * AFTERMODIFY - this ElementCollector will notify after all
+ * internal modifications have finished.
+ * BEFOREMODIFY - this ElementCollector must notify before any
+ * internal modification happens.
+ */
+ css::xml::crypto::sax::ElementMarkPriority const m_nPriority;
+
+ /*
+ * the modify flag, representing whether which elementcollector will
+ * modify its data.
+ */
+ bool const m_bToModify;
+
+ /* the notify enable flag, see notifyListener method */
+ bool m_bAbleToNotify;
+
+ /* whether the listener has been notified */
+ bool m_bNotified;
+
+ /* the listener to be notified */
+ css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > m_xReferenceResolvedListener;
+
+public:
+ ElementCollector(
+ sal_Int32 nBufferId,
+ css::xml::crypto::sax::ElementMarkPriority nPriority,
+ bool bToModify,
+ const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& xReferenceResolvedListener);
+
+ css::xml::crypto::sax::ElementMarkPriority getPriority() const { return m_nPriority;}
+ bool getModify() const { return m_bToModify;}
+ void notifyListener();
+ void setReferenceResolvedListener(
+ const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& referenceResolvedListener);
+ void doNotify();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/elementmark.cxx b/xmlsecurity/source/framework/elementmark.cxx
new file mode 100644
index 000000000..71444d7cd
--- /dev/null
+++ b/xmlsecurity/source/framework/elementmark.cxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include "elementmark.hxx"
+
+ElementMark::ElementMark(sal_Int32 nSecurityId, sal_Int32 nBufferId)
+ :m_pBufferNode(nullptr),
+ m_nSecurityId(nSecurityId),
+ m_nBufferId(nBufferId),
+ m_type(css::xml::crypto::sax::ElementMarkType_ELEMENTMARK)
+/****** ElementMark/ElementMark ***********************************************
+ *
+ * NAME
+ * ElementMark -- constructor method
+ *
+ * SYNOPSIS
+ * ElementMark(nSecurityId, nBufferId);
+ *
+ * FUNCTION
+ * construct an ElementMark object.
+ *
+ * INPUTS
+ * nSecurityId - represents which security entity the buffer node is
+ * related with. Either a signature or an encryption is
+ * a security entity.
+ * nBufferId - the id of the element buffered in the document
+ * wrapper component. The document wrapper component
+ * uses this id to search the particular buffered
+ * element.
+ ******************************************************************************/
+{
+}
+
+
+void ElementMark::setBufferNode(const BufferNode* pBufferNode)
+{
+ m_pBufferNode = const_cast<BufferNode*>(pBufferNode);
+}
+
+
+void ElementMark::setSecurityId(sal_Int32 nSecurityId)
+{
+ m_nSecurityId = nSecurityId;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/elementmark.hxx b/xmlsecurity/source/framework/elementmark.hxx
new file mode 100644
index 000000000..94ca71fdf
--- /dev/null
+++ b/xmlsecurity/source/framework/elementmark.hxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/crypto/sax/ElementMarkType.hpp>
+
+class BufferNode;
+
+class ElementMark
+/****** elementmark.hxx/CLASS ElementMark *************************************
+ *
+ * NAME
+ * ElementMark -- Class to manipulate an element mark
+ *
+ * FUNCTION
+ * This class maintains the security id, buffer id and its type for a
+ * buffer node.
+ ******************************************************************************/
+{
+protected:
+ /* the BufferNode maintained by this object */
+ BufferNode* m_pBufferNode;
+
+ /* the security Id */
+ sal_Int32 m_nSecurityId;
+
+ /* the buffer Id */
+ sal_Int32 const m_nBufferId;
+
+ /*
+ * the type value, is one of following values:
+ * TYPEOFELEMENTMARK - the default value, represents a blocker if
+ * not changed
+ * TYPEOFELEMENTCOLLECTOR - represents an ElementCollector
+ */
+ css::xml::crypto::sax::ElementMarkType m_type;
+
+public:
+ ElementMark(sal_Int32 nSecurityId, sal_Int32 nBufferId);
+ virtual ~ElementMark(){};
+
+ BufferNode* getBufferNode() const { return m_pBufferNode; }
+ void setBufferNode(const BufferNode* pBufferNode);
+ sal_Int32 getSecurityId() const { return m_nSecurityId; }
+ void setSecurityId(sal_Int32 nSecurityId);
+ css::xml::crypto::sax::ElementMarkType getType() const { return m_type; }
+ sal_Int32 getBufferId() const { return m_nBufferId; }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/saxeventkeeperimpl.cxx b/xmlsecurity/source/framework/saxeventkeeperimpl.cxx
new file mode 100644
index 000000000..b5a7f0272
--- /dev/null
+++ b/xmlsecurity/source/framework/saxeventkeeperimpl.cxx
@@ -0,0 +1,1152 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include <framework/saxeventkeeperimpl.hxx>
+#include "buffernode.hxx"
+#include "elementmark.hxx"
+#include "elementcollector.hxx"
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp>
+#include <com/sun/star/xml/wrapper/XXMLDocumentWrapper.hpp>
+#include <com/sun/star/xml/csax/XCompressedDocumentHandler.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <osl/diagnose.h>
+#include <rtl/ustrbuf.hxx>
+
+#include <algorithm>
+
+SAXEventKeeperImpl::SAXEventKeeperImpl( )
+ :m_pCurrentBufferNode(nullptr),
+ m_nNextElementMarkId(1),
+ m_pNewBlocker(nullptr),
+ m_pCurrentBlockingBufferNode(nullptr),
+ m_bIsReleasing(false),
+ m_bIsForwarding(false)
+{
+ m_vElementMarkBuffers.reserve(2);
+ m_vNewElementCollectors.reserve(2);
+ m_vReleasedElementMarkBuffers.reserve(2);
+}
+
+SAXEventKeeperImpl::~SAXEventKeeperImpl()
+{
+ /*
+ * delete the BufferNode tree
+ */
+ m_pRootBufferNode.reset();
+
+ m_pCurrentBufferNode = m_pCurrentBlockingBufferNode = nullptr;
+
+ /*
+ * delete all unfreed ElementMarks
+ */
+ m_vNewElementCollectors.clear();
+ m_pNewBlocker = nullptr;
+}
+
+void SAXEventKeeperImpl::setCurrentBufferNode(BufferNode* pBufferNode)
+/****** SAXEventKeeperImpl/setCurrentBufferNode ******************************
+ *
+ * NAME
+ * setCurrentBufferNode -- set a new active BufferNode.
+ *
+ * SYNOPSIS
+ * setCurrentBufferNode( pBufferNode );
+ *
+ * FUNCTION
+ * connects this BufferNode into the BufferNode tree as a child of the
+ * current active BufferNode. Then makes this BufferNode as the current
+ * active BufferNode.
+ * If the previous active BufferNode points to the root
+ * BufferNode, which means that no buffering operation was proceeding,
+ * then notifies the status change listener that buffering operation
+ * will begin at once.
+ *
+ * INPUTS
+ * pBufferNode - a BufferNode which will be the new active BufferNode
+ ******************************************************************************/
+{
+ if (pBufferNode == m_pCurrentBufferNode)
+ return;
+
+ if ( m_pCurrentBufferNode == m_pRootBufferNode.get() &&
+ m_xSAXEventKeeperStatusChangeListener.is())
+ {
+ m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(true);
+ }
+
+ if (pBufferNode->getParent() == nullptr)
+ {
+ m_pCurrentBufferNode->addChild(std::unique_ptr<BufferNode>(pBufferNode));
+ pBufferNode->setParent(m_pCurrentBufferNode);
+ }
+
+ m_pCurrentBufferNode = pBufferNode;
+}
+
+BufferNode* SAXEventKeeperImpl::addNewElementMarkBuffers()
+/****** SAXEventKeeperImpl/addNewElementMarkBuffers **************************
+ *
+ * NAME
+ * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker.
+ *
+ * SYNOPSIS
+ * pBufferNode = addNewElementMarkBuffers( );
+ *
+ * FUNCTION
+ * if there are new ElementCollector or new Blocker to be added, then
+ * connect all of them with the current BufferNode. In case of the
+ * current BufferNode doesn't exist, creates one.
+ * Clears up the new ElementCollector list and the new Blocker pointer.
+ *
+ * RESULT
+ * pBufferNode - the BufferNode that has been connected with both new
+ * ElementCollectors and new Blocker.
+ ******************************************************************************/
+{
+ BufferNode* pBufferNode = nullptr;
+
+ if (m_pNewBlocker || !m_vNewElementCollectors.empty() )
+ {
+ /*
+ * When the current BufferNode is right pointing to the current
+ * working element in the XMLDocumentWrapper component, then
+ * no new BufferNode is needed to create.
+ * This situation can only happen in the "Forwarding" mode.
+ */
+ if ( (m_pCurrentBufferNode != nullptr) &&
+ (m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement())))
+ {
+ pBufferNode = m_pCurrentBufferNode;
+ }
+ else
+ {
+ pBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement());
+ }
+
+ if (m_pNewBlocker != nullptr)
+ {
+ pBufferNode->setBlocker(m_pNewBlocker);
+
+ /*
+ * If no blocking before, then notify the status change listener that
+ * the SAXEventKeeper has entered "blocking" status, during which, no
+ * SAX events will be forwarded to the next document handler.
+ */
+ if (m_pCurrentBlockingBufferNode == nullptr)
+ {
+ m_pCurrentBlockingBufferNode = pBufferNode;
+
+ if (m_xSAXEventKeeperStatusChangeListener.is())
+ {
+ m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(true);
+ }
+ }
+
+ m_pNewBlocker = nullptr;
+ }
+
+ for( const auto& i : m_vNewElementCollectors )
+ {
+ pBufferNode->addElementCollector(i);
+ }
+ m_vNewElementCollectors.clear();
+ }
+
+ return pBufferNode;
+}
+
+ElementMark* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId) const
+/****** SAXEventKeeperImpl/findElementMarkBuffer *****************************
+ *
+ * NAME
+ * findElementMarkBuffer -- finds an ElementMark.
+ *
+ * SYNOPSIS
+ * pElementMark = findElementMarkBuffer( nId );
+ *
+ * FUNCTION
+ * searches an ElementMark with the particular Id in the ElementMark
+ * list.
+ *
+ * INPUTS
+ * nId - the Id of the ElementMark to be searched.
+ *
+ * RESULT
+ * pElementMark - the ElementMark with the particular Id, or NULL when
+ * no such Id exists.
+ ******************************************************************************/
+{
+ ElementMark* pElementMark = nullptr;
+
+ for( auto&& ii : m_vElementMarkBuffers )
+ {
+ if ( nId == ii->getBufferId())
+ {
+ pElementMark = const_cast<ElementMark*>(ii.get());
+ break;
+ }
+ }
+
+ return pElementMark;
+}
+
+void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId)
+/****** SAXEventKeeperImpl/removeElementMarkBuffer ***************************
+ *
+ * NAME
+ * removeElementMarkBuffer -- removes an ElementMark
+ *
+ * SYNOPSIS
+ * removeElementMarkBuffer( nId );
+ *
+ * FUNCTION
+ * removes an ElementMark with the particular Id in the ElementMark list.
+ *
+ * INPUTS
+ * nId - the Id of the ElementMark to be removed.
+ ******************************************************************************/
+{
+ auto ii = std::find_if(m_vElementMarkBuffers.begin(), m_vElementMarkBuffers.end(),
+ [nId](std::unique_ptr<const ElementMark>& rElementMark) { return nId == rElementMark->getBufferId(); }
+ );
+ if (ii == m_vElementMarkBuffers.end())
+ return;
+
+ /*
+ * checks whether this ElementMark still in the new ElementCollect array
+ */
+ auto jj = std::find_if(m_vNewElementCollectors.begin(), m_vNewElementCollectors.end(),
+ [&ii](const ElementCollector* pElementCollector) { return ii->get() == pElementCollector; }
+ );
+ if (jj != m_vNewElementCollectors.end())
+ m_vNewElementCollectors.erase(jj);
+
+ /*
+ * checks whether this ElementMark is the new Blocker
+ */
+ if (ii->get() == m_pNewBlocker)
+ {
+ m_pNewBlocker = nullptr;
+ }
+
+ m_vElementMarkBuffers.erase( ii );
+}
+
+OUString SAXEventKeeperImpl::printBufferNode(
+ BufferNode const * pBufferNode, sal_Int32 nIndent) const
+/****** SAXEventKeeperImpl/printBufferNode ***********************************
+ *
+ * NAME
+ * printBufferNode -- retrieves the information of a BufferNode and its
+ * branch.
+ *
+ * SYNOPSIS
+ * info = printBufferNode( pBufferNode, nIndent );
+ *
+ * FUNCTION
+ * all retrieved information includes:
+ * 1. whether it is the current BufferNode;
+ * 2. whether it is the current blocking BufferNode;
+ * 3. the name of the parent element;
+ * 4. the name of this element;
+ * 5. all ElementCollectors working on this BufferNode;
+ * 6. the Blocker working on this BufferNode;
+ * 7. all child BufferNodes' information.
+ *
+ * INPUTS
+ * pBufferNode - the BufferNode from where information will be retrieved.
+ * nIndent - how many space characters prefixed before the output
+ * message.
+ *
+ * RESULT
+ * info - the information string
+ ******************************************************************************/
+{
+ OUStringBuffer rc;
+
+ for ( int i=0; i<nIndent; ++i )
+ {
+ rc.append(" ");
+ }
+
+ if (pBufferNode == m_pCurrentBufferNode)
+ {
+ rc.append("[%]");
+ }
+
+ if (pBufferNode == m_pCurrentBlockingBufferNode)
+ {
+ rc.append("[B]");
+ }
+
+ rc.append(" " + m_xXMLDocument->getNodeName(pBufferNode->getXMLElement()));
+
+ BufferNode* pParent = const_cast<BufferNode*>(pBufferNode->getParent());
+ if (pParent != nullptr)
+ {
+ rc.append("[" + m_xXMLDocument->getNodeName(pParent->getXMLElement()) + "]");
+ }
+
+ rc.append(":EC=" + pBufferNode->printChildren() + " BR=");
+
+ ElementMark * pBlocker = pBufferNode->getBlocker();
+ if (pBlocker != nullptr)
+ {
+ rc.append( OUString::number(pBlocker->getBufferId()) +
+ "(SecId=" + OUString::number( pBlocker->getSecurityId() ) + ") ");
+ }
+ rc.append("\n");
+
+ std::vector< std::unique_ptr<BufferNode> > const & vChildren = pBufferNode->getChildren();
+ for( const auto& jj : vChildren )
+ {
+ rc.append(printBufferNode(jj.get(), nIndent+4));
+ }
+
+ return rc.makeStringAndClear();
+}
+
+css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > >
+ SAXEventKeeperImpl::collectChildWorkingElement(BufferNode const * pBufferNode)
+/****** SAXEventKeeperImpl/collectChildWorkingElement ************************
+ *
+ * NAME
+ * collectChildWorkingElement -- collects a BufferNode's all child
+ * Elements.
+ *
+ * SYNOPSIS
+ * list = collectChildWorkingElement( pBufferNode );
+ *
+ * INPUTS
+ * pBufferNode - the BufferNode whose child Elements will be collected.
+ *
+ * RESULT
+ * list - the child Elements list.
+ ******************************************************************************/
+{
+ std::vector< std::unique_ptr<BufferNode> > const & vChildren = pBufferNode->getChildren();
+
+ css::uno::Sequence < css::uno::Reference<
+ css::xml::wrapper::XXMLElementWrapper > > aChildrenCollection ( vChildren.size());
+
+ std::transform(vChildren.begin(), vChildren.end(), aChildrenCollection.getArray(),
+ [](const auto& i) { return i->getXMLElement(); });
+
+ return aChildrenCollection;
+}
+
+void SAXEventKeeperImpl::smashBufferNode(
+ BufferNode* pBufferNode, bool bClearRoot) const
+/****** SAXEventKeeperImpl/smashBufferNode ***********************************
+ *
+ * NAME
+ * smashBufferNode -- removes a BufferNode along with its working
+ * element.
+ *
+ * SYNOPSIS
+ * smashBufferNode( pBufferNode, bClearRoot );
+ *
+ * FUNCTION
+ * removes the BufferNode's working element from the DOM document, while
+ * reserves all ancestor paths for its child BufferNodes.
+ * when any of the BufferNode's ancestor element is useless, removes it
+ * too.
+ * removes the BufferNode from the BufferNode tree.
+ *
+ * INPUTS
+ * pBufferNode - the BufferNode to be removed
+ * bClearRoot - whether the root element also needs to be cleared up.
+ *
+ * NOTES
+ * when removing a Blocker's BufferNode, the bClearRoot flag should be
+ * true. Because a Blocker can buffer many SAX events which are not used
+ * by any other ElementCollector or Blocker.
+ * When the bClearRoot is set to true, the root BufferNode will be first
+ * cleared, with a stop flag setting at the next Blocking BufferNode. This
+ * operation can delete all useless buffered SAX events which are only
+ * needed by the Blocker to be deleted.
+ ******************************************************************************/
+{
+ if (pBufferNode->hasAnything())
+ return;
+
+ BufferNode* pParent = const_cast<BufferNode*>(pBufferNode->getParent());
+
+ /*
+ * delete the XML data
+ */
+ if (pParent == m_pRootBufferNode.get())
+ {
+ bool bIsNotBlocking = (m_pCurrentBlockingBufferNode == nullptr);
+ bool bIsBlockInside = false;
+ bool bIsBlockingAfterward = false;
+
+ /*
+ * If this is a blocker, then remove any out-element data
+ * which caused by blocking. The removal process will stop
+ * at the next blocker to avoid removing any useful data.
+ */
+ if (bClearRoot)
+ {
+ css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > >
+ aChildElements = collectChildWorkingElement(m_pRootBufferNode.get());
+
+ /*
+ * the clearUselessData only clearup the content in the
+ * node, not the node itself.
+ */
+ m_xXMLDocument->clearUselessData(m_pRootBufferNode->getXMLElement(),
+ aChildElements,
+ bIsNotBlocking?nullptr:
+ (m_pCurrentBlockingBufferNode->getXMLElement()));
+
+ /*
+ * remove the node if it is empty, then if its parent is also
+ * empty, remove it, then if the next parent is also empty,
+ * remove it,..., until parent become null.
+ */
+ m_xXMLDocument->collapse( m_pRootBufferNode->getXMLElement() );
+ }
+
+ /*
+ * if blocking, check the relationship between this BufferNode and
+ * the current blocking BufferNode.
+ */
+ if ( !bIsNotBlocking )
+ {
+ /*
+ * the current blocking BufferNode is a descendant of this BufferNode.
+ */
+ bIsBlockInside = (nullptr != pBufferNode->isAncestor(m_pCurrentBlockingBufferNode));
+
+ /*
+ * the current blocking BufferNode locates behind this BufferNode in tree
+ * order.
+ */
+ bIsBlockingAfterward = pBufferNode->isPrevious(m_pCurrentBlockingBufferNode);
+ }
+
+ /*
+ * this BufferNode's working element needs to be deleted only when
+ * 1. there is no blocking, or
+ * 2. the current blocking BufferNode is a descendant of this BufferNode,
+ * (then in the BufferNode's working element, the useless data before the blocking
+ * element should be deleted.) or
+ * 3. the current blocking BufferNode is locates behind this BufferNode in tree,
+ * (then the useless data between the blocking element and the working element
+ * should be deleted.).
+ * Otherwise, this working element should not be deleted.
+ */
+ if ( bIsNotBlocking || bIsBlockInside || bIsBlockingAfterward )
+ {
+ css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > >
+ aChildElements = collectChildWorkingElement(pBufferNode);
+
+ /*
+ * the clearUselessData only clearup the content in the
+ * node, not the node itself.
+ */
+ m_xXMLDocument->clearUselessData(pBufferNode->getXMLElement(),
+ aChildElements,
+ bIsBlockInside?(m_pCurrentBlockingBufferNode->getXMLElement()):
+ nullptr);
+
+ /*
+ * remove the node if it is empty, then if its parent is also
+ * empty, remove it, then if the next parent is also empty,
+ * remove it,..., until parent become null.
+ */
+ m_xXMLDocument->collapse( pBufferNode->getXMLElement() );
+ }
+ }
+
+ sal_Int32 nIndex = pParent->indexOfChild(pBufferNode);
+
+ std::vector< std::unique_ptr<BufferNode> > vChildren = pBufferNode->releaseChildren();
+ pParent->removeChild(pBufferNode); // delete buffernode
+
+ for( auto& i : vChildren )
+ {
+ i->setParent(pParent);
+ pParent->addChild(std::move(i), nIndex);
+ nIndex++;
+ }
+}
+
+BufferNode* SAXEventKeeperImpl::findNextBlockingBufferNode(
+ BufferNode* pStartBufferNode)
+/****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************
+ *
+ * NAME
+ * findNextBlockingBufferNode -- finds the next blocking BufferNode
+ * behind the particular BufferNode.
+ *
+ * SYNOPSIS
+ * pBufferNode = findNextBlockingBufferNode( pStartBufferNode );
+ *
+ * INPUTS
+ * pStartBufferNode - the BufferNode from where to search the next
+ * blocking BufferNode.
+ *
+ * RESULT
+ * pBufferNode - the next blocking BufferNode, or NULL if no such
+ * BufferNode exists.
+ ******************************************************************************/
+{
+ BufferNode* pNext = nullptr;
+
+ if (pStartBufferNode != nullptr)
+ {
+ pNext = pStartBufferNode;
+
+ while (nullptr != (pNext = const_cast<BufferNode*>(pNext->getNextNodeByTreeOrder())))
+ {
+ if (pNext->getBlocker() != nullptr)
+ {
+ break;
+ }
+ }
+ }
+
+ return pNext;
+}
+
+void SAXEventKeeperImpl::diffuse(BufferNode* pBufferNode)
+/****** SAXEventKeeperImpl/diffuse *******************************************
+ *
+ * NAME
+ * diffuse -- diffuse the notification.
+ *
+ * SYNOPSIS
+ * diffuse( pBufferNode );
+ *
+ * FUNCTION
+ * diffuse the collecting completion notification from the specific
+ * BufferNode along its parent link, until an ancestor which is not
+ * completely received is met.
+ *
+ * INPUTS
+ * pBufferNode - the BufferNode from which the notification will be
+ * diffused.
+ ******************************************************************************/
+{
+ BufferNode* pParent = pBufferNode;
+
+ while(pParent->isAllReceived())
+ {
+ pParent->elementCollectorNotify();
+ pParent = const_cast<BufferNode*>(pParent->getParent());
+ }
+}
+
+void SAXEventKeeperImpl::releaseElementMarkBuffer()
+/****** SAXEventKeeperImpl/releaseElementMarkBuffer **************************
+ *
+ * NAME
+ * releaseElementMarkBuffer -- releases useless ElementMarks
+ *
+ * SYNOPSIS
+ * releaseElementMarkBuffer( );
+ *
+ * FUNCTION
+ * releases each ElementMark in the releasing list
+ * m_vReleasedElementMarkBuffers.
+ * The operation differs between an ElementCollector and a Blocker.
+ ******************************************************************************/
+{
+ m_bIsReleasing = true;
+ while (!m_vReleasedElementMarkBuffers.empty())
+ {
+ auto pId = m_vReleasedElementMarkBuffers.begin();
+ sal_Int32 nId = *pId;
+ m_vReleasedElementMarkBuffers.erase( pId );
+
+ ElementMark* pElementMark = findElementMarkBuffer(nId);
+
+ if (pElementMark != nullptr)
+ {
+ if (css::xml::crypto::sax::ElementMarkType_ELEMENTCOLLECTOR
+ == pElementMark->getType())
+ /*
+ * it is a EC
+ */
+ {
+ ElementCollector* pElementCollector = static_cast<ElementCollector*>(pElementMark);
+
+ css::xml::crypto::sax::ElementMarkPriority nPriority = pElementCollector->getPriority();
+ /*
+ * Delete the EC from the buffer node.
+ */
+ BufferNode* pBufferNode = pElementCollector->getBufferNode();
+ pBufferNode->removeElementCollector(pElementCollector);
+
+ if ( nPriority == css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY)
+ {
+ pBufferNode->notifyBranch();
+ }
+
+ /*
+ * delete the ElementMark
+ */
+ pElementCollector = nullptr;
+ pElementMark = nullptr;
+ removeElementMarkBuffer(nId);
+
+ /*
+ * delete the BufferNode
+ */
+ diffuse(pBufferNode);
+ smashBufferNode(pBufferNode, false);
+ }
+ else
+ /*
+ * it is a Blocker
+ */
+ {
+ /*
+ * Delete the TH from the buffer node.
+ */
+ BufferNode *pBufferNode = pElementMark->getBufferNode();
+ pBufferNode->setBlocker(nullptr);
+
+ /*
+ * If there is a following handler and no blocking now, then
+ * forward this event
+ */
+ if (m_pCurrentBlockingBufferNode == pBufferNode)
+ {
+ /*
+ * Before forwarding, the next blocking point needs to be
+ * found.
+ */
+ m_pCurrentBlockingBufferNode = findNextBlockingBufferNode(pBufferNode);
+
+ /*
+ * Forward the blocked events between these two STHs.
+ */
+ if (m_xNextHandler.is())
+ {
+ BufferNode* pTempCurrentBufferNode = m_pCurrentBufferNode;
+ BufferNode* pTempCurrentBlockingBufferNode = m_pCurrentBlockingBufferNode;
+
+ m_pCurrentBufferNode = pBufferNode;
+ m_pCurrentBlockingBufferNode = nullptr;
+
+ m_bIsForwarding = true;
+
+ m_xXMLDocument->generateSAXEvents(
+ m_xNextHandler,
+ this,
+ pBufferNode->getXMLElement(),
+ (pTempCurrentBlockingBufferNode == nullptr)?nullptr:(pTempCurrentBlockingBufferNode->getXMLElement()));
+
+ m_bIsForwarding = false;
+
+ m_pCurrentBufferNode = pTempCurrentBufferNode;
+ if (m_pCurrentBlockingBufferNode == nullptr)
+ {
+ m_pCurrentBlockingBufferNode = pTempCurrentBlockingBufferNode;
+ }
+ }
+
+ if (m_pCurrentBlockingBufferNode == nullptr &&
+ m_xSAXEventKeeperStatusChangeListener.is())
+ {
+ m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(false);
+ }
+ }
+
+ /*
+ * delete the ElementMark
+ */
+ pElementMark = nullptr;
+ removeElementMarkBuffer(nId);
+
+ /*
+ * delete the BufferNode
+ */
+ diffuse(pBufferNode);
+ smashBufferNode(pBufferNode, true);
+ }
+ }
+ }
+
+ m_bIsReleasing = false;
+
+ if (!m_pRootBufferNode->hasAnything() &&
+ !m_pRootBufferNode->hasChildren() &&
+ m_xSAXEventKeeperStatusChangeListener.is())
+ {
+ m_xSAXEventKeeperStatusChangeListener->bufferStatusChanged(true);
+ }
+}
+
+void SAXEventKeeperImpl::markElementMarkBuffer(sal_Int32 nId)
+/****** SAXEventKeeperImpl/markElementMarkBuffer *****************************
+ *
+ * NAME
+ * markElementMarkBuffer -- marks an ElementMark to be released
+ *
+ * SYNOPSIS
+ * markElementMarkBuffer( nId );
+ *
+ * FUNCTION
+ * puts the ElementMark with the particular Id into the releasing list,
+ * checks whether the releasing process is running, if not then launch
+ * this process.
+ *
+ * INPUTS
+ * nId - the Id of the ElementMark which will be released
+ ******************************************************************************/
+{
+ m_vReleasedElementMarkBuffers.push_back( nId );
+ if ( !m_bIsReleasing )
+ {
+ releaseElementMarkBuffer();
+ }
+}
+
+sal_Int32 SAXEventKeeperImpl::createElementCollector(
+ css::xml::crypto::sax::ElementMarkPriority nPriority,
+ bool bModifyElement,
+ const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& xReferenceResolvedListener)
+/****** SAXEventKeeperImpl/createElementCollector ****************************
+ *
+ * NAME
+ * createElementCollector -- creates a new ElementCollector on the
+ * incoming element.
+ *
+ * SYNOPSIS
+ * nId = createElementCollector( nSecurityId, nPriority,
+ * bModifyElement,
+ * xReferenceResolvedListener );
+ *
+ * FUNCTION
+ * allocs a new Id, then create an ElementCollector with this Id value.
+ * Add the new created ElementCollector to the new ElementCollecotor list.
+ *
+ * INPUTS
+ * nPriority - the priority of the new ElementCollector
+ * bModifyElement -whether this BufferNode will modify the content of
+ * the corresponding element it works on
+ * xReferenceResolvedListener - the listener for the new ElementCollector.
+ *
+ * RESULT
+ * nId - the Id of the new ElementCollector
+ ******************************************************************************/
+{
+ sal_Int32 nId = m_nNextElementMarkId;
+ m_nNextElementMarkId ++;
+
+ ElementCollector* pElementCollector
+ = new ElementCollector(
+ nId,
+ nPriority,
+ bModifyElement,
+ xReferenceResolvedListener);
+
+ m_vElementMarkBuffers.push_back(
+ std::unique_ptr<const ElementMark>(pElementCollector));
+
+ /*
+ * All the new EC to initial EC array.
+ */
+ m_vNewElementCollectors.push_back( pElementCollector );
+
+ return nId;
+}
+
+
+sal_Int32 SAXEventKeeperImpl::createBlocker()
+/****** SAXEventKeeperImpl/createBlocker *************************************
+ *
+ * NAME
+ * createBlocker -- creates a new Blocker on the incoming element.
+ *
+ * SYNOPSIS
+ * nId = createBlocker( nSecurityId );
+ *
+ * RESULT
+ * nId - the Id of the new Blocker
+ ******************************************************************************/
+{
+ sal_Int32 nId = m_nNextElementMarkId;
+ m_nNextElementMarkId ++;
+
+ OSL_ASSERT(m_pNewBlocker == nullptr);
+
+ m_pNewBlocker = new ElementMark(css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID, nId);
+ m_vElementMarkBuffers.push_back(
+ std::unique_ptr<const ElementMark>(m_pNewBlocker));
+
+ return nId;
+}
+
+/* XSAXEventKeeper */
+sal_Int32 SAL_CALL SAXEventKeeperImpl::addElementCollector( )
+{
+ return createElementCollector(
+ css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY,
+ false,
+ nullptr);
+}
+
+void SAL_CALL SAXEventKeeperImpl::removeElementCollector( sal_Int32 id )
+{
+ markElementMarkBuffer(id);
+}
+
+sal_Int32 SAL_CALL SAXEventKeeperImpl::addBlocker( )
+{
+ return createBlocker();
+}
+
+void SAL_CALL SAXEventKeeperImpl::removeBlocker( sal_Int32 id )
+{
+ markElementMarkBuffer(id);
+}
+
+sal_Bool SAL_CALL SAXEventKeeperImpl::isBlocking( )
+{
+ return (m_pCurrentBlockingBufferNode != nullptr);
+}
+
+css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL
+ SAXEventKeeperImpl::getElement( sal_Int32 id )
+{
+ css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > rc;
+
+ ElementMark* pElementMark = findElementMarkBuffer(id);
+ if (pElementMark != nullptr)
+ {
+ rc = pElementMark->getBufferNode()->getXMLElement();
+ }
+
+ return rc;
+}
+
+void SAL_CALL SAXEventKeeperImpl::setElement(
+ sal_Int32 id,
+ const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aElement )
+{
+ if (aElement.is())
+ {
+ m_xXMLDocument->rebuildIDLink(aElement);
+
+ ElementMark* pElementMark = findElementMarkBuffer(id);
+
+ if (pElementMark != nullptr)
+ {
+ BufferNode* pBufferNode = pElementMark->getBufferNode();
+ if (pBufferNode != nullptr)
+ {
+ const bool bIsCurrent = m_xXMLDocument->isCurrent(pBufferNode->getXMLElement());
+ pBufferNode->setXMLElement(aElement);
+
+ if (bIsCurrent)
+ {
+ m_xXMLDocument->setCurrentElement(aElement);
+ }
+ }
+ }
+ }
+ else
+ {
+ removeElementCollector( id );
+ }
+}
+
+css::uno::Reference< css::xml::sax::XDocumentHandler > SAL_CALL SAXEventKeeperImpl::setNextHandler(
+ const css::uno::Reference< css::xml::sax::XDocumentHandler >& xNewHandler )
+{
+ css::uno::Reference< css::xml::sax::XDocumentHandler > xOldHandler = m_xNextHandler;
+
+ m_xNextHandler = xNewHandler;
+ return xOldHandler;
+}
+
+OUString SAL_CALL SAXEventKeeperImpl::printBufferNodeTree()
+{
+ OUString rc = "ElementMarkBuffers: size = "
+ + OUString::number(m_vElementMarkBuffers.size())
+ + "\nCurrentBufferNode: "
+ + m_xXMLDocument->getNodeName(m_pCurrentBufferNode->getXMLElement())
+ + "\n" + printBufferNode(m_pRootBufferNode.get(), 0);
+
+ return rc;
+}
+
+css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL SAXEventKeeperImpl::getCurrentBlockingNode()
+{
+ css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > rc;
+
+ if (m_pCurrentBlockingBufferNode != nullptr)
+ {
+ rc = m_pCurrentBlockingBufferNode->getXMLElement();
+ }
+
+ return rc;
+}
+
+/* XSecuritySAXEventKeeper */
+sal_Int32 SAL_CALL SAXEventKeeperImpl::addSecurityElementCollector(
+ css::xml::crypto::sax::ElementMarkPriority priority,
+ sal_Bool modifyElement )
+{
+ return createElementCollector(
+ priority,
+ modifyElement,
+ nullptr);
+}
+
+void SAL_CALL SAXEventKeeperImpl::setSecurityId( sal_Int32 id, sal_Int32 securityId )
+{
+ ElementMark* pElementMark = findElementMarkBuffer(id);
+ if (pElementMark != nullptr)
+ {
+ pElementMark->setSecurityId(securityId);
+ }
+}
+
+
+/* XReferenceResolvedBroadcaster */
+void SAL_CALL SAXEventKeeperImpl::addReferenceResolvedListener(
+ sal_Int32 referenceId,
+ const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& listener )
+{
+ ElementCollector* pElementCollector = static_cast<ElementCollector*>(findElementMarkBuffer(referenceId));
+ if (pElementCollector != nullptr)
+ {
+ pElementCollector->setReferenceResolvedListener(listener);
+ }
+}
+
+void SAL_CALL SAXEventKeeperImpl::removeReferenceResolvedListener(
+ sal_Int32 /*referenceId*/,
+ const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >&)
+{
+}
+
+/* XSAXEventKeeperStatusChangeBroadcaster */
+void SAL_CALL SAXEventKeeperImpl::addSAXEventKeeperStatusChangeListener(
+ const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >& listener )
+{
+ m_xSAXEventKeeperStatusChangeListener = listener;
+}
+
+void SAL_CALL SAXEventKeeperImpl::removeSAXEventKeeperStatusChangeListener(
+ const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >&)
+{
+}
+
+/* XDocumentHandler */
+void SAL_CALL SAXEventKeeperImpl::startDocument( )
+{
+ if ( m_xNextHandler.is())
+ {
+ m_xNextHandler->startDocument();
+ }
+}
+
+void SAL_CALL SAXEventKeeperImpl::endDocument( )
+{
+ if ( m_xNextHandler.is())
+ {
+ m_xNextHandler->endDocument();
+ }
+}
+
+void SAL_CALL SAXEventKeeperImpl::startElement(
+ const OUString& aName,
+ const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs )
+{
+ /*
+ * If there is a following handler and no blocking now, then
+ * forward this event
+ */
+ if ((m_pCurrentBlockingBufferNode == nullptr) &&
+ (m_xNextHandler.is()) &&
+ (!m_bIsForwarding) &&
+ (m_pNewBlocker == nullptr))
+ {
+ m_xNextHandler->startElement(aName, xAttribs);
+ }
+ /*
+ * If not forwarding, buffer this startElement.
+ */
+ if (!m_bIsForwarding)
+ {
+ sal_Int32 nLength = xAttribs->getLength();
+ css::uno::Sequence< css::xml::csax::XMLAttribute > aAttributes (nLength);
+ auto aAttributesRange = asNonConstRange(aAttributes);
+
+ for ( int i = 0; i<nLength; ++i )
+ {
+ aAttributesRange[i].sName = xAttribs->getNameByIndex(static_cast<short>(i));
+ aAttributesRange[i].sValue =xAttribs->getValueByIndex(static_cast<short>(i));
+ }
+
+ m_xCompressedDocumentHandler->compressedStartElement(aName, aAttributes);
+ }
+
+ BufferNode* pBufferNode = addNewElementMarkBuffers();
+ if (pBufferNode != nullptr)
+ {
+ setCurrentBufferNode(pBufferNode);
+ }
+}
+
+void SAL_CALL SAXEventKeeperImpl::endElement( const OUString& aName )
+{
+ const bool bIsCurrent = m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement());
+
+ /*
+ * If there is a following handler and no blocking now, then
+ * forward this event
+ */
+ if ((m_pCurrentBlockingBufferNode == nullptr) &&
+ (m_xNextHandler.is()) &&
+ (!m_bIsForwarding))
+ {
+ m_xNextHandler->endElement(aName);
+ }
+
+ if ((m_pCurrentBlockingBufferNode != nullptr) ||
+ (m_pCurrentBufferNode != m_pRootBufferNode.get()) ||
+ (!m_xXMLDocument->isCurrentElementEmpty()))
+ {
+ if (!m_bIsForwarding)
+ {
+ m_xCompressedDocumentHandler->compressedEndElement(aName);
+ }
+
+ /*
+ * If the current buffer node has not notified yet, and
+ * the current buffer node is waiting for the current element,
+ * then let it notify.
+ */
+ if (bIsCurrent && (m_pCurrentBufferNode != m_pRootBufferNode.get()))
+ {
+ BufferNode* pOldCurrentBufferNode = m_pCurrentBufferNode;
+ m_pCurrentBufferNode = const_cast<BufferNode*>(m_pCurrentBufferNode->getParent());
+
+ pOldCurrentBufferNode->setReceivedAll();
+
+ if ((m_pCurrentBufferNode == m_pRootBufferNode.get()) &&
+ m_xSAXEventKeeperStatusChangeListener.is())
+ {
+ m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(false);
+ }
+ }
+ }
+ else
+ {
+ if (!m_bIsForwarding)
+ {
+ m_xXMLDocument->removeCurrentElement();
+ }
+ }
+}
+
+void SAL_CALL SAXEventKeeperImpl::characters( const OUString& aChars )
+{
+ if (m_bIsForwarding)
+ return;
+
+ if ((m_pCurrentBlockingBufferNode == nullptr) && m_xNextHandler.is())
+ {
+ m_xNextHandler->characters(aChars);
+ }
+
+ if ((m_pCurrentBlockingBufferNode != nullptr) ||
+ (m_pCurrentBufferNode != m_pRootBufferNode.get()))
+ {
+ m_xCompressedDocumentHandler->compressedCharacters(aChars);
+ }
+}
+
+void SAL_CALL SAXEventKeeperImpl::ignorableWhitespace( const OUString& aWhitespaces )
+{
+ characters( aWhitespaces );
+}
+
+void SAL_CALL SAXEventKeeperImpl::processingInstruction(
+ const OUString& aTarget, const OUString& aData )
+{
+ if (m_bIsForwarding)
+ return;
+
+ if ((m_pCurrentBlockingBufferNode == nullptr) && m_xNextHandler.is())
+ {
+ m_xNextHandler->processingInstruction(aTarget, aData);
+ }
+
+ if ((m_pCurrentBlockingBufferNode != nullptr) ||
+ (m_pCurrentBufferNode != m_pRootBufferNode.get()))
+ {
+ m_xCompressedDocumentHandler->compressedProcessingInstruction(aTarget, aData);
+ }
+}
+
+void SAL_CALL SAXEventKeeperImpl::setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >&)
+{
+}
+
+/* XInitialization */
+void SAL_CALL SAXEventKeeperImpl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
+{
+ OSL_ASSERT(aArguments.getLength() == 1);
+
+ aArguments[0] >>= m_xXMLDocument;
+ m_xDocumentHandler.set( m_xXMLDocument, css::uno::UNO_QUERY );
+ m_xCompressedDocumentHandler.set( m_xXMLDocument, css::uno::UNO_QUERY );
+
+ m_pRootBufferNode.reset( new BufferNode(m_xXMLDocument->getCurrentElement()) );
+ m_pCurrentBufferNode = m_pRootBufferNode.get();
+}
+
+OUString SAXEventKeeperImpl_getImplementationName ()
+{
+ return "com.sun.star.xml.security.framework.SAXEventKeeperImpl";
+}
+
+css::uno::Sequence< OUString > SAXEventKeeperImpl_getSupportedServiceNames( )
+{
+ return { "com.sun.star.xml.crypto.sax.SAXEventKeeper" };
+}
+
+/* XServiceInfo */
+OUString SAL_CALL SAXEventKeeperImpl::getImplementationName( )
+{
+ return SAXEventKeeperImpl_getImplementationName();
+}
+
+sal_Bool SAL_CALL SAXEventKeeperImpl::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL SAXEventKeeperImpl::getSupportedServiceNames( )
+{
+ return SAXEventKeeperImpl_getSupportedServiceNames();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/securityengine.cxx b/xmlsecurity/source/framework/securityengine.cxx
new file mode 100644
index 000000000..e276163d4
--- /dev/null
+++ b/xmlsecurity/source/framework/securityengine.cxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include <framework/securityengine.hxx>
+
+
+SecurityEngine::SecurityEngine()
+ :m_nIdOfTemplateEC(-1),
+ m_nNumOfResolvedReferences(0),
+ m_nIdOfKeyEC(-1),
+ m_bMissionDone(false),
+ m_nSecurityId(-1),
+ m_nStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN)
+{
+}
+
+/* XReferenceResolvedListener */
+void SAL_CALL SecurityEngine::referenceResolved( sal_Int32 /*referenceId*/)
+{
+ m_nNumOfResolvedReferences++;
+ tryToPerform();
+}
+
+/* XKeyCollector */
+void SAL_CALL SecurityEngine::setKeyId( sal_Int32 id )
+{
+ m_nIdOfKeyEC = id;
+ tryToPerform();
+}
+
+/* XMissionTaker */
+sal_Bool SAL_CALL SecurityEngine::endMission( )
+{
+ bool rc = m_bMissionDone;
+
+ if (!rc)
+ {
+ clearUp( );
+
+ notifyResultListener();
+ m_bMissionDone = true;
+ }
+
+ m_xResultListener = nullptr;
+ m_xSAXEventKeeper = nullptr;
+
+ return rc;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/signaturecreatorimpl.cxx b/xmlsecurity/source/framework/signaturecreatorimpl.cxx
new file mode 100644
index 000000000..4371b7ae6
--- /dev/null
+++ b/xmlsecurity/source/framework/signaturecreatorimpl.cxx
@@ -0,0 +1,175 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include <framework/signaturecreatorimpl.hxx>
+#include <framework/xmlsignaturetemplateimpl.hxx>
+#include <com/sun/star/xml/crypto/XXMLSignatureTemplate.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <osl/diagnose.h>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::xml::wrapper { class XXMLElementWrapper; }
+
+using namespace com::sun::star::uno;
+
+SignatureCreatorImpl::SignatureCreatorImpl()
+ : m_nIdOfBlocker(-1)
+{
+}
+
+SignatureCreatorImpl::~SignatureCreatorImpl( )
+{
+}
+
+void SignatureCreatorImpl::notifyResultListener() const
+/****** SignatureCreatorImpl/notifyResultListener *****************************
+ *
+ * NAME
+ * notifyResultListener -- notifies the listener about the signature
+ * creation result.
+ ******************************************************************************/
+{
+ css::uno::Reference< css::xml::crypto::sax::XSignatureCreationResultListener >
+ xSignatureCreationResultListener ( m_xResultListener , css::uno::UNO_QUERY ) ;
+
+ xSignatureCreationResultListener->signatureCreated( m_nSecurityId, m_nStatus );
+}
+
+void SignatureCreatorImpl::startEngine(const rtl::Reference<XMLSignatureTemplateImpl>& xSignatureTemplate)
+/****** SignatureCreatorImpl/startEngine *************************************
+ *
+ * NAME
+ * startEngine -- generates the signature.
+ *
+ * FUNCTION
+ * generates the signature element, then if succeeds, updates the link
+ * of old template element to the new signature element in
+ * SAXEventKeeper.
+ *
+ * INPUTS
+ * xSignatureTemplate - the signature template (along with all referenced
+ * elements) to be signed.
+ ******************************************************************************/
+{
+ css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > xResultTemplate;
+ try
+ {
+ xResultTemplate = m_xXMLSignature->generate(css::uno::Reference<css::xml::crypto::XXMLSignatureTemplate>(xSignatureTemplate), m_xSecurityEnvironment);
+ m_nStatus = xResultTemplate->getStatus();
+ }
+ catch( css::uno::Exception& )
+ {
+ m_nStatus = css::xml::crypto::SecurityOperationStatus_RUNTIMEERROR_FAILED;
+ }
+
+ if (m_nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED)
+ {
+ css::uno::Reference < css::xml::wrapper::XXMLElementWrapper > xResultSignature = xResultTemplate->getTemplate();
+ m_xSAXEventKeeper->setElement(m_nIdOfTemplateEC, xResultSignature);
+ }
+}
+
+void SignatureCreatorImpl::clearUp() const
+/****** SignatureCreatorImpl/clearUp *****************************************
+ *
+ * NAME
+ * clearUp -- clear up all resources used by the signature generation.
+ *
+ * SYNOPSIS
+ * clearUp( );
+ *
+ * FUNCTION
+ * cleaning resources up includes:
+ * 1. SignatureEngine's clearing up;
+ * 2. releases the Blocker for the signature template element.
+ ******************************************************************************/
+{
+ SignatureEngine::clearUp();
+
+ if (m_nIdOfBlocker != -1)
+ {
+ m_xSAXEventKeeper->removeBlocker(m_nIdOfBlocker);
+ }
+}
+
+/* XBlockerMonitor */
+void SAL_CALL SignatureCreatorImpl::setBlockerId( sal_Int32 id )
+{
+ m_nIdOfBlocker = id;
+ tryToPerform();
+}
+
+/* XSignatureCreationResultBroadcaster */
+void SAL_CALL SignatureCreatorImpl::addSignatureCreationResultListener(
+ const css::uno::Reference< css::xml::crypto::sax::XSignatureCreationResultListener >& listener )
+{
+ m_xResultListener = listener;
+ tryToPerform();
+}
+
+void SAL_CALL SignatureCreatorImpl::removeSignatureCreationResultListener(
+ const css::uno::Reference< css::xml::crypto::sax::XSignatureCreationResultListener >&)
+{
+}
+
+/* XInitialization */
+void SAL_CALL SignatureCreatorImpl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
+{
+ OSL_ASSERT(aArguments.getLength() == 5);
+
+ OUString ouTempString;
+
+ aArguments[0] >>= ouTempString;
+ m_nSecurityId = ouTempString.toInt32();
+ aArguments[1] >>= m_xSAXEventKeeper;
+ aArguments[2] >>= ouTempString;
+ m_nIdOfTemplateEC = ouTempString.toInt32();
+ aArguments[3] >>= m_xSecurityEnvironment;
+ aArguments[4] >>= m_xXMLSignature;
+}
+
+
+OUString SignatureCreatorImpl_getImplementationName ()
+{
+ return "com.sun.star.xml.security.framework.SignatureCreatorImpl";
+}
+
+css::uno::Sequence< OUString > SignatureCreatorImpl_getSupportedServiceNames( )
+{
+ return { "com.sun.star.xml.crypto.sax.SignatureCreator" };
+}
+
+/* XServiceInfo */
+OUString SAL_CALL SignatureCreatorImpl::getImplementationName( )
+{
+ return SignatureCreatorImpl_getImplementationName();
+}
+
+sal_Bool SAL_CALL SignatureCreatorImpl::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL SignatureCreatorImpl::getSupportedServiceNames( )
+{
+ return SignatureCreatorImpl_getSupportedServiceNames();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/signatureengine.cxx b/xmlsecurity/source/framework/signatureengine.cxx
new file mode 100644
index 000000000..0390ea7e6
--- /dev/null
+++ b/xmlsecurity/source/framework/signatureengine.cxx
@@ -0,0 +1,197 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include <framework/signatureengine.hxx>
+#include <framework/xmlsignaturetemplateimpl.hxx>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::xml::wrapper { class XXMLElementWrapper; }
+
+using namespace com::sun::star::uno;
+
+SignatureEngine::SignatureEngine()
+ : m_nTotalReferenceNumber(-1)
+{
+}
+
+bool SignatureEngine::checkReady() const
+/****** SignatureEngine/checkReady *******************************************
+ *
+ * NAME
+ * checkReady -- checks the conditions for the main operation.
+ *
+ * SYNOPSIS
+ * bReady = checkReady( );
+ *
+ * FUNCTION
+ * checks whether all following conditions are satisfied:
+ * 1. the main operation has't begun yet;
+ * 2. the key material is known;
+ * 3. the amount of reference is known;
+ * 4. all of referenced elements, the key element and the signature
+ * template are buffered.
+ *
+ * RESULT
+ * bReady - true if all conditions are satisfied, false otherwise
+ ******************************************************************************/
+{
+ bool rc = true;
+
+ sal_Int32 nKeyInc = 0;
+ if (m_nIdOfKeyEC != 0)
+ {
+ nKeyInc = 1;
+ }
+
+ if (m_bMissionDone ||
+ m_nIdOfKeyEC == -1 ||
+ m_nTotalReferenceNumber == -1 ||
+ m_nTotalReferenceNumber+1+nKeyInc > m_nNumOfResolvedReferences)
+ {
+ rc = false;
+ }
+
+ return rc;
+}
+
+void SignatureEngine::tryToPerform( )
+/****** SignatureEngine/tryToPerform *****************************************
+ *
+ * NAME
+ * tryToPerform -- tries to perform the signature operation.
+ *
+ * FUNCTION
+ * if the situation is ready, perform following operations.
+ * 1. prepares a signature template;
+ * 2. calls the signature bridge component;
+ * 3. clears up all used resources;
+ * 4. notifies the result listener;
+ * 5. sets the "accomplishment" flag.
+ ******************************************************************************/
+{
+ if (!checkReady())
+ return;
+
+ rtl::Reference<XMLSignatureTemplateImpl> xSignatureTemplate = new XMLSignatureTemplateImpl();
+
+ css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >
+ xXMLElement = m_xSAXEventKeeper->getElement( m_nIdOfTemplateEC );
+
+ xSignatureTemplate->setTemplate(xXMLElement);
+
+ for( const auto i : m_vReferenceIds )
+ {
+ xXMLElement = m_xSAXEventKeeper->getElement( i );
+ xSignatureTemplate->setTarget(xXMLElement);
+ }
+
+ /*
+ * set the Uri binding
+ */
+ xSignatureTemplate->setBinding( this );
+
+ startEngine(xSignatureTemplate);
+
+ /*
+ * done
+ */
+ clearUp( );
+
+ notifyResultListener();
+
+ m_bMissionDone = true;
+}
+
+void SignatureEngine::clearUp( ) const
+/****** SignatureEngine/clearUp **********************************************
+ *
+ * NAME
+ * clearUp -- clear up all resources used by this operation.
+ *
+ * FUNCTION
+ * cleaning resources up includes:
+ * 1. releases the ElementCollector for the signature template element;
+ * 2. releases ElementCollectors for referenced elements;
+ * 3. releases the ElementCollector for the key element, if there is one.
+ ******************************************************************************/
+{
+ css::uno::Reference < css::xml::crypto::sax::XReferenceResolvedBroadcaster >
+ xReferenceResolvedBroadcaster( m_xSAXEventKeeper, css::uno::UNO_QUERY );
+ xReferenceResolvedBroadcaster->removeReferenceResolvedListener(
+ m_nIdOfTemplateEC,
+ static_cast<const css::uno::Reference < css::xml::crypto::sax::XReferenceResolvedListener > >(static_cast<SecurityEngine *>(const_cast<SignatureEngine *>(this))));
+
+ m_xSAXEventKeeper->removeElementCollector(m_nIdOfTemplateEC);
+
+ for( const auto& i : m_vReferenceIds )
+ {
+ xReferenceResolvedBroadcaster->removeReferenceResolvedListener(
+ i,
+ static_cast<const css::uno::Reference < css::xml::crypto::sax::XReferenceResolvedListener > >(static_cast<SecurityEngine *>(const_cast<SignatureEngine *>(this))));
+ m_xSAXEventKeeper->removeElementCollector(i);
+ }
+
+ if (m_nIdOfKeyEC != 0 && m_nIdOfKeyEC != -1)
+ {
+ m_xSAXEventKeeper->removeElementCollector(m_nIdOfKeyEC);
+ }
+}
+
+/* XReferenceCollector */
+void SAL_CALL SignatureEngine::setReferenceCount( sal_Int32 count )
+{
+ m_nTotalReferenceNumber = count;
+ tryToPerform();
+}
+
+void SAL_CALL SignatureEngine::setReferenceId( sal_Int32 id )
+{
+ m_vReferenceIds.push_back( id );
+}
+
+/* XUriBinding */
+void SAL_CALL SignatureEngine::setUriBinding(
+ const OUString& uri,
+ const css::uno::Reference< css::io::XInputStream >& aInputStream )
+{
+ m_vUris.push_back(uri);
+ m_vXInputStreams.push_back(aInputStream);
+}
+
+css::uno::Reference< css::io::XInputStream > SAL_CALL SignatureEngine::getUriBinding( const OUString& uri )
+{
+ css::uno::Reference< css::io::XInputStream > xInputStream;
+
+ int size = m_vUris.size();
+
+ for( int i=0; i<size; ++i)
+ {
+ if (m_vUris[i] == uri)
+ {
+ xInputStream = m_vXInputStreams[i];
+ break;
+ }
+ }
+
+ return xInputStream;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/signatureverifierimpl.cxx b/xmlsecurity/source/framework/signatureverifierimpl.cxx
new file mode 100644
index 000000000..44e9e4c0a
--- /dev/null
+++ b/xmlsecurity/source/framework/signatureverifierimpl.cxx
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include <framework/signatureverifierimpl.hxx>
+#include <framework/xmlsignaturetemplateimpl.hxx>
+#include <com/sun/star/xml/crypto/XXMLSignatureTemplate.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <osl/diagnose.h>
+#include <rtl/ref.hxx>
+
+
+SignatureVerifierImpl::SignatureVerifierImpl()
+{
+}
+
+SignatureVerifierImpl::~SignatureVerifierImpl()
+{
+}
+
+void SignatureVerifierImpl::notifyResultListener() const
+/****** SignatureVerifierImpl/notifyResultListener ***************************
+ *
+ * NAME
+ * notifyResultListener -- notifies the listener about the verify result.
+ ******************************************************************************/
+{
+ css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultListener >
+ xSignatureVerifyResultListener ( m_xResultListener , css::uno::UNO_QUERY ) ;
+
+ xSignatureVerifyResultListener->signatureVerified( m_nSecurityId, m_nStatus );
+}
+
+void SignatureVerifierImpl::startEngine( const rtl::Reference<XMLSignatureTemplateImpl>& xSignatureTemplate)
+/****** SignatureVerifierImpl/startEngine ************************************
+ *
+ * NAME
+ * startEngine -- verifies the signature.
+ *
+ * INPUTS
+ * xSignatureTemplate - the signature template (along with all referenced
+ * elements) to be verified.
+ ******************************************************************************/
+{
+ css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > xResultTemplate;
+ try
+ {
+ xResultTemplate = m_xXMLSignature->validate(css::uno::Reference<css::xml::crypto::XXMLSignatureTemplate>(xSignatureTemplate), m_xXMLSecurityContext);
+ m_nStatus = xResultTemplate->getStatus();
+ }
+ catch( css::uno::Exception& )
+ {
+ m_nStatus = css::xml::crypto::SecurityOperationStatus_RUNTIMEERROR_FAILED;
+ }
+}
+
+/* XSignatureVerifyResultBroadcaster */
+void SAL_CALL SignatureVerifierImpl::addSignatureVerifyResultListener(
+ const css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultListener >& listener )
+{
+ m_xResultListener = listener;
+ tryToPerform();
+}
+
+void SAL_CALL SignatureVerifierImpl::removeSignatureVerifyResultListener(
+ const css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultListener >&)
+{
+}
+
+/* XInitialization */
+void SAL_CALL SignatureVerifierImpl::initialize(
+ const css::uno::Sequence< css::uno::Any >& aArguments )
+{
+ OSL_ASSERT(aArguments.getLength() == 5);
+
+ OUString ouTempString;
+
+ aArguments[0] >>= ouTempString;
+ m_nSecurityId = ouTempString.toInt32();
+ aArguments[1] >>= m_xSAXEventKeeper;
+ aArguments[2] >>= ouTempString;
+ m_nIdOfTemplateEC = ouTempString.toInt32();
+ aArguments[3] >>= m_xXMLSecurityContext;
+ aArguments[4] >>= m_xXMLSignature;
+}
+
+
+OUString SignatureVerifierImpl_getImplementationName ()
+{
+ return "com.sun.star.xml.security.framework.SignatureVerifierImpl";
+}
+
+css::uno::Sequence< OUString > SignatureVerifierImpl_getSupportedServiceNames( )
+{
+ return { "com.sun.star.xml.crypto.sax.SignatureVerifier" };
+}
+
+/* XServiceInfo */
+OUString SAL_CALL SignatureVerifierImpl::getImplementationName( )
+{
+ return SignatureVerifierImpl_getImplementationName();
+}
+
+sal_Bool SAL_CALL SignatureVerifierImpl::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL SignatureVerifierImpl::getSupportedServiceNames( )
+{
+ return SignatureVerifierImpl_getSupportedServiceNames();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx b/xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx
new file mode 100644
index 000000000..203f0fea2
--- /dev/null
+++ b/xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+#include <rtl/ustring.hxx>
+#include <framework/xmlsignaturetemplateimpl.hxx>
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+using namespace ::com::sun::star::uno ;
+using ::com::sun::star::lang::XMultiServiceFactory ;
+
+using ::com::sun::star::xml::wrapper::XXMLElementWrapper ;
+using ::com::sun::star::xml::crypto::XXMLSignatureTemplate ;
+
+XMLSignatureTemplateImpl::XMLSignatureTemplateImpl()
+ :m_nStatus ( css::xml::crypto::SecurityOperationStatus_UNKNOWN )
+{
+}
+
+XMLSignatureTemplateImpl::~XMLSignatureTemplateImpl() {
+}
+
+/* XXMLSignatureTemplate */
+void SAL_CALL XMLSignatureTemplateImpl::setTemplate( const Reference< XXMLElementWrapper >& aTemplate )
+{
+ m_xTemplate = aTemplate ;
+}
+
+/* XXMLSignatureTemplate */
+Reference< XXMLElementWrapper > SAL_CALL XMLSignatureTemplateImpl::getTemplate()
+{
+ return m_xTemplate ;
+}
+
+void SAL_CALL XMLSignatureTemplateImpl::setTarget( const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aXmlElement )
+{
+ targets.push_back( aXmlElement );
+}
+
+css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > SAL_CALL XMLSignatureTemplateImpl::getTargets()
+{
+ return comphelper::containerToSequence(targets);
+}
+
+void SAL_CALL XMLSignatureTemplateImpl::setBinding(
+ const css::uno::Reference< css::xml::crypto::XUriBinding >& aUriBinding )
+{
+ m_xUriBinding = aUriBinding;
+}
+
+css::uno::Reference< css::xml::crypto::XUriBinding > SAL_CALL XMLSignatureTemplateImpl::getBinding()
+{
+ return m_xUriBinding;
+}
+
+void SAL_CALL XMLSignatureTemplateImpl::setStatus(
+ css::xml::crypto::SecurityOperationStatus status )
+{
+ m_nStatus = status;
+}
+
+css::xml::crypto::SecurityOperationStatus SAL_CALL XMLSignatureTemplateImpl::getStatus( )
+{
+ return m_nStatus;
+}
+
+/* XServiceInfo */
+OUString SAL_CALL XMLSignatureTemplateImpl::getImplementationName() {
+ return impl_getImplementationName() ;
+}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL XMLSignatureTemplateImpl::supportsService( const OUString& serviceName) {
+ return cppu::supportsService(this, serviceName);
+}
+
+/* XServiceInfo */
+Sequence< OUString > SAL_CALL XMLSignatureTemplateImpl::getSupportedServiceNames() {
+ return impl_getSupportedServiceNames() ;
+}
+
+//Helper for XServiceInfo
+Sequence< OUString > XMLSignatureTemplateImpl::impl_getSupportedServiceNames() {
+ Sequence<OUString> seqServiceNames { "com.sun.star.xml.crypto.XMLSignatureTemplate" };
+ return seqServiceNames ;
+}
+
+OUString XMLSignatureTemplateImpl::impl_getImplementationName() {
+ return "com.sun.star.xml.security.framework.XMLSignatureTemplateImpl" ;
+}
+
+//Helper for registry
+Reference< XInterface > XMLSignatureTemplateImpl::impl_createInstance( const Reference< XMultiServiceFactory >& ) {
+ return Reference< XInterface >( *new XMLSignatureTemplateImpl ) ;
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/gpg/CertificateImpl.cxx b/xmlsecurity/source/gpg/CertificateImpl.cxx
new file mode 100644
index 000000000..a0a08fc80
--- /dev/null
+++ b/xmlsecurity/source/gpg/CertificateImpl.cxx
@@ -0,0 +1,261 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <config_gpgme.h>
+
+#include "CertificateImpl.hxx"
+
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <com/sun/star/security/KeyUsage.hpp>
+#include <officecfg/Office/Common.hxx>
+#include <svl/sigstruct.hxx>
+
+#include <context.h>
+#include <data.h>
+
+using namespace css;
+using namespace css::uno;
+using namespace css::security;
+using namespace css::util;
+
+CertificateImpl::CertificateImpl()
+{
+}
+
+CertificateImpl::~CertificateImpl()
+{
+}
+
+//Methods from XCertificateImpl
+sal_Int16 SAL_CALL CertificateImpl::getVersion()
+{
+ return 0;
+}
+
+Sequence< sal_Int8 > SAL_CALL CertificateImpl::getSerialNumber()
+{
+ // TODO: perhaps map to subkey's cardSerialNumber - if you have
+ // one to test
+ return Sequence< sal_Int8 >();
+}
+
+OUString SAL_CALL CertificateImpl::getIssuerName()
+{
+ const GpgME::UserID userId = m_pKey.userID(0);
+ if (userId.isNull())
+ return OUString();
+
+ return OStringToOUString(userId.id(), RTL_TEXTENCODING_UTF8);
+}
+
+OUString SAL_CALL CertificateImpl::getSubjectName()
+{
+ // Same as issuer name (user ID)
+ return getIssuerName();
+}
+
+namespace {
+ DateTime convertUnixTimeToDateTime(time_t time)
+ {
+ DateTime dateTime;
+ struct tm *timeStruct = gmtime(&time);
+ dateTime.Year = timeStruct->tm_year + 1900;
+ dateTime.Month = timeStruct->tm_mon + 1;
+ dateTime.Day = timeStruct->tm_mday;
+ dateTime.Hours = timeStruct->tm_hour;
+ dateTime.Minutes = timeStruct->tm_min;
+ dateTime.Seconds = timeStruct->tm_sec;
+ return dateTime;
+ }
+}
+
+DateTime SAL_CALL CertificateImpl::getNotValidBefore()
+{
+ const GpgME::Subkey subkey = m_pKey.subkey(0);
+ if (subkey.isNull())
+ return DateTime();
+
+ return convertUnixTimeToDateTime(m_pKey.subkey(0).creationTime());
+}
+
+DateTime SAL_CALL CertificateImpl::getNotValidAfter()
+{
+ const GpgME::Subkey subkey = m_pKey.subkey(0);
+ if (subkey.isNull() || subkey.neverExpires())
+ return DateTime();
+
+ return convertUnixTimeToDateTime(m_pKey.subkey(0).expirationTime());
+}
+
+Sequence< sal_Int8 > SAL_CALL CertificateImpl::getIssuerUniqueID()
+{
+ // Empty for gpg
+ return Sequence< sal_Int8 > ();
+}
+
+Sequence< sal_Int8 > SAL_CALL CertificateImpl::getSubjectUniqueID()
+{
+ // Empty for gpg
+ return Sequence< sal_Int8 > ();
+}
+
+Sequence< Reference< XCertificateExtension > > SAL_CALL CertificateImpl::getExtensions()
+{
+ // Empty for gpg
+ return Sequence< Reference< XCertificateExtension > > ();
+}
+
+Reference< XCertificateExtension > SAL_CALL CertificateImpl::findCertificateExtension( const Sequence< sal_Int8 >& /*oid*/ )
+{
+ // Empty for gpg
+ return Reference< XCertificateExtension > ();
+}
+
+Sequence< sal_Int8 > SAL_CALL CertificateImpl::getEncoded()
+{
+ // Export key to base64Empty for gpg
+ return m_aBits;
+}
+
+OUString SAL_CALL CertificateImpl::getSubjectPublicKeyAlgorithm()
+{
+ const GpgME::Subkey subkey = m_pKey.subkey(0);
+ if (subkey.isNull())
+ return OUString();
+
+ return OStringToOUString(subkey.publicKeyAlgorithmAsString(), RTL_TEXTENCODING_UTF8);
+}
+
+Sequence< sal_Int8 > SAL_CALL CertificateImpl::getSubjectPublicKeyValue()
+{
+ return Sequence< sal_Int8 > ();
+}
+
+OUString SAL_CALL CertificateImpl::getSignatureAlgorithm()
+{
+ const GpgME::UserID userId = m_pKey.userID(0);
+ if (userId.isNull())
+ return OUString();
+
+ const GpgME::UserID::Signature signature = userId.signature(0);
+ if (signature.isNull())
+ return OUString();
+
+ return OStringToOUString(signature.algorithmAsString(), RTL_TEXTENCODING_UTF8);
+}
+
+Sequence< sal_Int8 > SAL_CALL CertificateImpl::getSHA1Thumbprint()
+{
+ // This is mapped to the fingerprint for gpg
+ const char* keyId = m_pKey.primaryFingerprint();
+ return comphelper::arrayToSequence<sal_Int8>(
+ keyId, strlen(keyId)+1);
+}
+
+Sequence<sal_Int8> CertificateImpl::getSHA256Thumbprint()
+{
+ // This is mapped to the fingerprint for gpg (though that's only
+ // SHA1 actually)
+ const char* keyId = m_pKey.primaryFingerprint();
+ return comphelper::arrayToSequence<sal_Int8>(
+ keyId, strlen(keyId)+1);
+}
+
+svl::crypto::SignatureMethodAlgorithm CertificateImpl::getSignatureMethodAlgorithm()
+{
+ return svl::crypto::SignatureMethodAlgorithm::RSA;
+}
+
+Sequence< sal_Int8 > SAL_CALL CertificateImpl::getMD5Thumbprint()
+{
+ // This is mapped to the shorter keyID for gpg
+ const char* keyId = m_pKey.keyID();
+ return comphelper::arrayToSequence<sal_Int8>(
+ keyId, strlen(keyId)+1);
+}
+
+CertificateKind SAL_CALL CertificateImpl::getCertificateKind()
+{
+ return CertificateKind_OPENPGP;
+}
+
+sal_Int32 SAL_CALL CertificateImpl::getCertificateUsage()
+{
+ return KeyUsage::DIGITAL_SIGNATURE | KeyUsage::NON_REPUDIATION | KeyUsage::KEY_ENCIPHERMENT | KeyUsage::DATA_ENCIPHERMENT;
+}
+
+/* XUnoTunnel */
+sal_Int64 SAL_CALL CertificateImpl::getSomething(const Sequence< sal_Int8 >& aIdentifier)
+{
+ return comphelper::getSomethingImpl(aIdentifier, this);
+}
+
+/* XUnoTunnel extension */
+
+const Sequence< sal_Int8>& CertificateImpl::getUnoTunnelId() {
+ static const comphelper::UnoIdInit theCertificateImplUnoTunnelId;
+ return theCertificateImplUnoTunnelId.getSeq();
+}
+
+void CertificateImpl::setCertificate(GpgME::Context* ctx, const GpgME::Key& key)
+{
+ m_pKey = key;
+
+ // extract key data, store into m_aBits
+ GpgME::Data data_out;
+ ctx->setArmor(false); // caller will base64-encode anyway
+ GpgME::Error err = ctx->exportPublicKeys(
+ key.primaryFingerprint(),
+ data_out,
+ officecfg::Office::Common::Security::OpenPGP::MinimalKeyExport::get()
+ ? GpgME::Context::ExportMinimal : 0
+ );
+
+ if (err)
+ throw RuntimeException("The GpgME library failed to retrieve the public key");
+
+ off_t result = data_out.seek(0,SEEK_SET);
+ (void) result;
+ assert(result == 0);
+ int len=0, curr=0; char buf;
+ while( (curr=data_out.read(&buf, 1)) )
+ len += curr;
+
+ // write bits to sequence of bytes
+ m_aBits.realloc(len);
+ result = data_out.seek(0,SEEK_SET);
+ assert(result == 0);
+ if( data_out.read(m_aBits.getArray(), len) != len )
+ throw RuntimeException("The GpgME library failed to read the key");
+}
+
+const GpgME::Key* CertificateImpl::getCertificate() const
+{
+ return &m_pKey;
+}
+
+/* XServiceInfo */
+OUString SAL_CALL CertificateImpl::getImplementationName()
+{
+ return "com.sun.star.xml.security.gpg.XCertificate_GpgImpl";
+}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL CertificateImpl::supportsService(const OUString& serviceName)
+{
+ return cppu::supportsService(this, serviceName);
+}
+
+/* XServiceInfo */
+Sequence<OUString> SAL_CALL CertificateImpl::getSupportedServiceNames() { return { OUString() }; }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/gpg/CertificateImpl.hxx b/xmlsecurity/source/gpg/CertificateImpl.hxx
new file mode 100644
index 000000000..b6c50cb2e
--- /dev/null
+++ b/xmlsecurity/source/gpg/CertificateImpl.hxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <certificate.hxx>
+
+#include <sal/types.h>
+#include <sal/config.h>
+#include <rtl/ustring.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/security/CertificateKind.hpp>
+#include <com/sun/star/security/XCertificate.hpp>
+
+#if defined _MSC_VER && defined __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wundef"
+#endif
+#include <key.h>
+#if defined _MSC_VER && defined __clang__
+#pragma clang diagnostic pop
+#endif
+
+class CertificateImpl : public cppu::WeakImplHelper< css::security::XCertificate,
+ css::lang::XUnoTunnel,
+ css::lang::XServiceInfo >,
+ public xmlsecurity::Certificate
+{
+private:
+ GpgME::Key m_pKey;
+ css::uno::Sequence< sal_Int8 > m_aBits;
+
+public:
+ CertificateImpl();
+ virtual ~CertificateImpl() override;
+
+ //Methods from XCertificate
+ virtual sal_Int16 SAL_CALL getVersion() override;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSerialNumber() override;
+
+ virtual OUString SAL_CALL getIssuerName() override;
+ virtual OUString SAL_CALL getSubjectName() override;
+
+ virtual css::util::DateTime SAL_CALL getNotValidBefore() override;
+ virtual css::util::DateTime SAL_CALL getNotValidAfter() override;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getIssuerUniqueID() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectUniqueID() override;
+
+ virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL getExtensions() override;
+
+ virtual css::uno::Reference< css::security::XCertificateExtension > SAL_CALL findCertificateExtension(const css::uno::Sequence< sal_Int8 >& oid) override;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getEncoded() override;
+
+ virtual OUString SAL_CALL getSubjectPublicKeyAlgorithm() override;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectPublicKeyValue() override;
+
+ virtual OUString SAL_CALL getSignatureAlgorithm() override;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSHA1Thumbprint() override;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getMD5Thumbprint() override;
+
+ virtual sal_Int32 SAL_CALL getCertificateUsage() override;
+
+ //Methods from XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething(const css::uno::Sequence< sal_Int8 >& aIdentifier) override;
+
+ static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId();
+
+ /// @see xmlsecurity::Certificate::getSHA256Thumbprint().
+ virtual css::uno::Sequence<sal_Int8> getSHA256Thumbprint() override;
+ /// @see xmlsecurity::Certificate::getSignatureMethodAlgorithm().
+ virtual svl::crypto::SignatureMethodAlgorithm getSignatureMethodAlgorithm() override;
+ virtual css::security::CertificateKind SAL_CALL getCertificateKind() override;
+
+ // Helper methods
+ void setCertificate(GpgME::Context* ctx, const GpgME::Key& key);
+ const GpgME::Key* getCertificate() const;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+} ;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/gpg/CipherContext.cxx b/xmlsecurity/source/gpg/CipherContext.cxx
new file mode 100644
index 000000000..291db0ba6
--- /dev/null
+++ b/xmlsecurity/source/gpg/CipherContext.cxx
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "CipherContext.hxx"
+
+using namespace css;
+using namespace css::uno;
+using namespace css::lang;
+
+Sequence<sal_Int8>
+ SAL_CALL CipherContext::convertWithCipherContext(const Sequence<sal_Int8>& /*aData*/)
+{
+ return Sequence<sal_Int8>();
+}
+
+uno::Sequence<sal_Int8> SAL_CALL CipherContext::finalizeCipherContextAndDispose()
+{
+ return Sequence<sal_Int8>();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/gpg/CipherContext.hxx b/xmlsecurity/source/gpg/CipherContext.hxx
new file mode 100644
index 000000000..2c0ffcdc9
--- /dev/null
+++ b/xmlsecurity/source/gpg/CipherContext.hxx
@@ -0,0 +1,26 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/crypto/XCipherContext.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+class CipherContext : public cppu::WeakImplHelper<css::xml::crypto::XCipherContext>
+{
+private:
+public:
+ // XCipherContext
+ virtual css::uno::Sequence<::sal_Int8>
+ SAL_CALL convertWithCipherContext(const css::uno::Sequence<::sal_Int8>& aData) override;
+ virtual css::uno::Sequence<::sal_Int8> SAL_CALL finalizeCipherContextAndDispose() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/gpg/DigestContext.cxx b/xmlsecurity/source/gpg/DigestContext.cxx
new file mode 100644
index 000000000..4864191bb
--- /dev/null
+++ b/xmlsecurity/source/gpg/DigestContext.cxx
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "DigestContext.hxx"
+
+using namespace css;
+using namespace css::uno;
+using namespace css::lang;
+
+void SAL_CALL DigestContext::updateDigest(const Sequence<sal_Int8>& /*aData*/) {}
+
+uno::Sequence<sal_Int8> SAL_CALL DigestContext::finalizeDigestAndDispose()
+{
+ return Sequence<sal_Int8>();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/gpg/DigestContext.hxx b/xmlsecurity/source/gpg/DigestContext.hxx
new file mode 100644
index 000000000..2d48daf34
--- /dev/null
+++ b/xmlsecurity/source/gpg/DigestContext.hxx
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/crypto/XDigestContext.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+class DigestContext : public cppu::WeakImplHelper<css::xml::crypto::XDigestContext>
+{
+public:
+ // XDigestContext
+ virtual void SAL_CALL updateDigest(const css::uno::Sequence<::sal_Int8>& aData) override;
+ virtual css::uno::Sequence<::sal_Int8> SAL_CALL finalizeDigestAndDispose() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/gpg/SEInitializer.cxx b/xmlsecurity/source/gpg/SEInitializer.cxx
new file mode 100644
index 000000000..5cfe325aa
--- /dev/null
+++ b/xmlsecurity/source/gpg/SEInitializer.cxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <cppuhelper/supportsservice.hxx>
+#include <gpg/SEInitializer.hxx>
+#include "SecurityEnvironment.hxx"
+#include "XMLSecurityContext.hxx"
+
+#include <global.h>
+
+namespace com::sun::star::uno
+{
+class XComponentContext;
+}
+
+using namespace css;
+using namespace css::lang;
+using namespace css::uno;
+using namespace css::xml::crypto;
+
+SEInitializerGpg::SEInitializerGpg()
+{
+ // Also init GpgME while we're at it
+ GpgME::initializeLibrary();
+}
+
+SEInitializerGpg::~SEInitializerGpg() {}
+
+/* XSEInitializer */
+Reference<XXMLSecurityContext> SAL_CALL SEInitializerGpg::createSecurityContext(const OUString&)
+{
+ try
+ {
+ /* Build XML Security Context */
+ Reference<XXMLSecurityContext> xSecCtx(new XMLSecurityContextGpg());
+
+ Reference<XSecurityEnvironment> xSecEnv(new SecurityEnvironmentGpg());
+ sal_Int32 n = xSecCtx->addSecurityEnvironment(xSecEnv);
+ //originally the SecurityEnvironment with the internal slot was set as default
+ xSecCtx->setDefaultSecurityEnvironmentIndex(n);
+ return xSecCtx;
+ }
+ catch (const uno::Exception&)
+ {
+ return nullptr;
+ }
+}
+
+void SAL_CALL SEInitializerGpg::freeSecurityContext(const uno::Reference<XXMLSecurityContext>&) {}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL SEInitializerGpg::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL SEInitializerGpg::getSupportedServiceNames()
+{
+ return { "com.sun.star.xml.crypto.GPGSEInitializer" };
+}
+
+OUString SAL_CALL SEInitializerGpg::getImplementationName()
+{
+ return "com.sun.star.xml.security.SEInitializer_Gpg";
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_xml_security_SEInitializer_Gpg_get_implementation(
+ uno::XComponentContext* /*pCtx*/, uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new SEInitializerGpg());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/gpg/SecurityEnvironment.cxx b/xmlsecurity/source/gpg/SecurityEnvironment.cxx
new file mode 100644
index 000000000..da2310765
--- /dev/null
+++ b/xmlsecurity/source/gpg/SecurityEnvironment.cxx
@@ -0,0 +1,232 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "SecurityEnvironment.hxx"
+#include "CertificateImpl.hxx"
+
+#include <com/sun/star/security/CertificateCharacters.hpp>
+#include <com/sun/star/security/CertificateValidity.hpp>
+
+#include <comphelper/servicehelper.hxx>
+#include <vector>
+#include <rtl/ref.hxx>
+
+#ifdef _WIN32
+#include <config_folders.h>
+#include <osl/file.hxx>
+#include <osl/process.h>
+#include <rtl/bootstrap.hxx>
+#include <tools/urlobj.hxx>
+#endif
+
+#include <key.h>
+#include <keylistresult.h>
+#include <xmlsec-wrapper.h>
+
+#if defined _MSC_VER && defined __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wundef"
+#endif
+#include <gpgme.h>
+#if defined _MSC_VER && defined __clang__
+#pragma clang diagnostic pop
+#endif
+#include <context.h>
+
+using namespace css;
+using namespace css::security;
+using namespace css::uno;
+using namespace css::lang;
+
+SecurityEnvironmentGpg::SecurityEnvironmentGpg()
+{
+#ifdef _WIN32
+ // On Windows, gpgme expects gpgme-w32spawn.exe to be in the same directory as the current
+ // process executable. This assumption might be wrong, e.g., for bundled python, which is
+ // in instdir/program/python-core-x.y.z/bin, while gpgme-w32spawn.exe is in instdir/program.
+ // If we can't find gpgme-w32spawn.exe in the current executable location, then try to find
+ // the spawn executable, and inform gpgme about actual location using gpgme_set_global_flag.
+ [[maybe_unused]] static bool bSpawnPathInitialized = [] {
+ auto accessUrl = [](const INetURLObject& url) {
+ osl::File file(url.GetMainURL(INetURLObject::DecodeMechanism::NONE));
+ return file.open(osl_File_OpenFlag_Read) == osl::FileBase::E_None;
+ };
+ OUString sPath;
+ osl_getExecutableFile(&sPath.pData);
+ INetURLObject aPathUrl(sPath);
+ aPathUrl.setName(u"gpgme-w32spawn.exe");
+ if (!accessUrl(aPathUrl))
+ {
+ sPath = "$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER "/gpgme-w32spawn.exe";
+ rtl::Bootstrap::expandMacros(sPath);
+ aPathUrl.SetURL(sPath);
+ if (accessUrl(aPathUrl))
+ {
+ aPathUrl.removeSegment();
+ GpgME::setGlobalFlag("w32-inst-dir",
+ aPathUrl.getFSysPath(FSysStyle::Dos).toUtf8().getStr());
+ }
+ }
+ return true;
+ }();
+#endif
+ GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP);
+ if (err)
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ m_ctx.reset( GpgME::Context::createForProtocol(GpgME::OpenPGP) );
+ if (m_ctx == nullptr)
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+ m_ctx->setArmor(false);
+}
+
+SecurityEnvironmentGpg::~SecurityEnvironmentGpg()
+{
+}
+
+/* XUnoTunnel */
+sal_Int64 SAL_CALL SecurityEnvironmentGpg::getSomething( const Sequence< sal_Int8 >& aIdentifier )
+{
+ return comphelper::getSomethingImpl(aIdentifier, this);
+}
+
+/* XUnoTunnel extension */
+
+namespace
+{
+}
+
+const Sequence< sal_Int8>& SecurityEnvironmentGpg::getUnoTunnelId() {
+ static const comphelper::UnoIdInit theSecurityEnvironmentUnoTunnelId;
+ return theSecurityEnvironmentUnoTunnelId.getSeq();
+}
+
+OUString SecurityEnvironmentGpg::getSecurityEnvironmentInformation()
+{
+ return OUString();
+}
+
+Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::getCertificatesImpl( bool bPrivateOnly )
+{
+ std::vector< GpgME::Key > keyList;
+ std::vector< rtl::Reference<CertificateImpl> > certsList;
+
+ m_ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL);
+ GpgME::Error err = m_ctx->startKeyListing("", bPrivateOnly );
+ while (!err) {
+ GpgME::Key k = m_ctx->nextKey(err);
+ if (err)
+ break;
+ if (!k.isRevoked() && !k.isExpired() && !k.isDisabled() && !k.isInvalid()) {
+ // We can't create CertificateImpl here as CertificateImpl::setCertificate uses GpgME API
+ // which interrupts our key listing here. So first get the keys from GpgME, then create the CertificateImpls
+ keyList.push_back(k);
+ }
+ }
+ m_ctx->endKeyListing();
+
+ for (auto const& key : keyList) {
+ rtl::Reference<CertificateImpl> xCert = new CertificateImpl();
+ xCert->setCertificate(m_ctx.get(),key);
+ certsList.push_back(xCert);
+ }
+
+ Sequence< Reference< XCertificate > > xCertificateSequence(certsList.size());
+ auto xCertificateSequenceRange = asNonConstRange(xCertificateSequence);
+ int i = 0;
+ for (const auto& cert : certsList) {
+ xCertificateSequenceRange[i++] = cert;
+ }
+
+ return xCertificateSequence;
+}
+
+Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::getPersonalCertificates()
+{
+ return getCertificatesImpl( true );
+}
+
+Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::getAllCertificates()
+{
+ return getCertificatesImpl( false );
+}
+
+Reference< XCertificate > SecurityEnvironmentGpg::getCertificate( const OUString& keyId, const Sequence< sal_Int8 >& /*serialNumber*/ )
+{
+ //xmlChar* pSignatureValue=xmlNodeGetContent(cur);
+ OString ostr = OUStringToOString( keyId , RTL_TEXTENCODING_UTF8 );
+ const xmlChar* strKeyId = reinterpret_cast<const xmlChar*>(ostr.getStr());
+ if(xmlSecBase64Decode(strKeyId, const_cast<xmlSecByte*>(strKeyId), xmlStrlen(strKeyId)) < 0)
+ throw RuntimeException("Base64 decode failed");
+
+ m_ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL);
+ GpgME::Error err = m_ctx->startKeyListing("", false);
+ while (!err) {
+ GpgME::Key k = m_ctx->nextKey(err);
+ if (err)
+ break;
+ if (!k.isInvalid() && strcmp(k.primaryFingerprint(), reinterpret_cast<const char*>(strKeyId)) == 0) {
+ rtl::Reference<CertificateImpl> xCert = new CertificateImpl();
+ xCert->setCertificate(m_ctx.get(), k);
+ m_ctx->endKeyListing();
+ return xCert;
+ }
+ }
+ m_ctx->endKeyListing();
+
+ return nullptr;
+}
+
+Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::buildCertificatePath( const Reference< XCertificate >& /*begin*/ )
+{
+ return Sequence< Reference < XCertificate > >();
+}
+
+Reference< XCertificate > SecurityEnvironmentGpg::createCertificateFromRaw( const Sequence< sal_Int8 >& /*rawCertificate*/ )
+{
+ return nullptr;
+}
+
+Reference< XCertificate > SecurityEnvironmentGpg::createCertificateFromAscii( const OUString& /*asciiCertificate*/ )
+{
+ return nullptr;
+}
+
+sal_Int32 SecurityEnvironmentGpg::verifyCertificate( const Reference< XCertificate >& aCert,
+ const Sequence< Reference< XCertificate > >& /*intermediateCerts*/ )
+{
+ const CertificateImpl* xCert = dynamic_cast<CertificateImpl*>(aCert.get());
+ if (xCert == nullptr) {
+ // Can't find the key locally -> unknown owner
+ return security::CertificateValidity::ISSUER_UNKNOWN;
+ }
+
+ const GpgME::Key* key = xCert->getCertificate();
+ if (key->ownerTrust() == GpgME::Key::OwnerTrust::Marginal ||
+ key->ownerTrust() == GpgME::Key::OwnerTrust::Full ||
+ key->ownerTrust() == GpgME::Key::OwnerTrust::Ultimate)
+ {
+ return security::CertificateValidity::VALID;
+ }
+
+ return security::CertificateValidity::ISSUER_UNTRUSTED;
+}
+
+sal_Int32 SecurityEnvironmentGpg::getCertificateCharacters(
+ const Reference< XCertificate >& aCert)
+{
+ if (comphelper::getFromUnoTunnel<CertificateImpl>(aCert) == nullptr)
+ throw RuntimeException();
+
+ // we only listed private keys anyway, up in
+ // SecurityEnvironmentGpg::getPersonalCertificates
+ return CertificateCharacters::HAS_PRIVATE_KEY;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/gpg/SecurityEnvironment.hxx b/xmlsecurity/source/gpg/SecurityEnvironment.hxx
new file mode 100644
index 000000000..262578682
--- /dev/null
+++ b/xmlsecurity/source/gpg/SecurityEnvironment.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include <rtl/ustring.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+
+namespace com::sun::star::security { class XCertificate; }
+namespace GpgME { class Context; }
+
+class SecurityEnvironmentGpg : public cppu::WeakImplHelper< css::xml::crypto::XSecurityEnvironment,
+ css::lang::XUnoTunnel >
+{
+ std::unique_ptr<GpgME::Context> m_ctx;
+
+public:
+ SecurityEnvironmentGpg();
+ virtual ~SecurityEnvironmentGpg() override;
+
+ //Methods from XSecurityEnvironment
+ virtual ::sal_Int32 SAL_CALL verifyCertificate(
+ const css::uno::Reference<
+ css::security::XCertificate >& xCert,
+ const css::uno::Sequence<
+ css::uno::Reference< css::security::XCertificate > > &
+ intermediateCerts) override;
+
+ virtual ::sal_Int32 SAL_CALL getCertificateCharacters( const css::uno::Reference< css::security::XCertificate >& xCert ) override;
+
+ virtual OUString SAL_CALL getSecurityEnvironmentInformation() override;
+
+ //Methods from XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override;
+
+ static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId() ;
+
+ virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getPersonalCertificates() override;
+
+ /** We reinterpret the first parameter (originally issuerName) as keyId. We have no other way to identify a gpg key. */
+ virtual css::uno::Reference< css::security::XCertificate > SAL_CALL getCertificate( const OUString& keyId, const css::uno::Sequence< sal_Int8 >& serialNumber ) override;
+
+ virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL buildCertificatePath(
+ const css::uno::Reference< css::security::XCertificate >& beginCert ) override;
+
+ virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromRaw(
+ const css::uno::Sequence< sal_Int8 >& rawCertificate ) override;
+ virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromAscii(
+ const OUString& asciiCertificate ) override;
+
+ GpgME::Context& getGpgContext() { return *m_ctx; }
+ virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getAllCertificates() override;
+
+private:
+ css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > getCertificatesImpl( bool bPrivateOnly );
+} ;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/gpg/XMLEncryption.cxx b/xmlsecurity/source/gpg/XMLEncryption.cxx
new file mode 100644
index 000000000..65083ff68
--- /dev/null
+++ b/xmlsecurity/source/gpg/XMLEncryption.cxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "XMLEncryption.hxx"
+
+using namespace css::uno;
+using namespace css::lang;
+using namespace css::xml::wrapper;
+using namespace css::xml::crypto;
+
+XMLEncryptionGpg::XMLEncryptionGpg() {
+}
+
+XMLEncryptionGpg::~XMLEncryptionGpg() {
+}
+
+/* XXMLEncryption */
+Reference< XXMLEncryptionTemplate > SAL_CALL XMLEncryptionGpg::encrypt(const Reference< XXMLEncryptionTemplate >& /*aTemplate*/,
+ const Reference< XSecurityEnvironment >& /*aEnvironment*/)
+{
+ return nullptr;
+}
+
+/* XXMLEncryption */
+Reference< XXMLEncryptionTemplate > SAL_CALL XMLEncryptionGpg::decrypt(const Reference< XXMLEncryptionTemplate >& /*aTemplate*/,
+ const Reference< XXMLSecurityContext >& /*aSecurityCtx*/)
+{
+ return nullptr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/gpg/XMLEncryption.hxx b/xmlsecurity/source/gpg/XMLEncryption.hxx
new file mode 100644
index 000000000..4ff47ccc4
--- /dev/null
+++ b/xmlsecurity/source/gpg/XMLEncryption.hxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sal/config.h>
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/xml/crypto/XXMLEncryption.hpp>
+
+namespace com::sun::star::xml::crypto { class XXMLEncryptionTemplate; }
+namespace com::sun::star::xml::crypto { class XXMLSecurityContext; }
+
+class XMLEncryptionGpg : public cppu::WeakImplHelper< css::xml::crypto::XXMLEncryption >
+{
+public:
+ explicit XMLEncryptionGpg();
+ virtual ~XMLEncryptionGpg() override;
+
+ // XXMLEncryption
+ virtual css::uno::Reference< css::xml::crypto::XXMLEncryptionTemplate > SAL_CALL encrypt(
+ const css::uno::Reference< css::xml::crypto::XXMLEncryptionTemplate >& aTemplate,
+ const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aEnvironment) override;
+
+ virtual css::uno::Reference< css::xml::crypto::XXMLEncryptionTemplate > SAL_CALL decrypt(
+ const css::uno::Reference< css::xml::crypto::XXMLEncryptionTemplate >& aTemplate,
+ const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& aContext) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/gpg/XMLSecurityContext.cxx b/xmlsecurity/source/gpg/XMLSecurityContext.cxx
new file mode 100644
index 000000000..1fb407113
--- /dev/null
+++ b/xmlsecurity/source/gpg/XMLSecurityContext.cxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "XMLSecurityContext.hxx"
+
+#include <cppuhelper/supportsservice.hxx>
+#include <o3tl/safeint.hxx>
+
+using namespace css::uno;
+using namespace css::lang;
+using namespace css::xml::crypto;
+
+XMLSecurityContextGpg::XMLSecurityContextGpg()
+ : m_nDefaultEnvIndex(-1)
+{
+}
+
+XMLSecurityContextGpg::~XMLSecurityContextGpg() {}
+
+sal_Int32 SAL_CALL XMLSecurityContextGpg::addSecurityEnvironment(
+ const Reference<XSecurityEnvironment>& aSecurityEnvironment)
+{
+ if (!aSecurityEnvironment.is())
+ throw RuntimeException("Invalid SecurityEnvironment given!");
+
+ m_vSecurityEnvironments.push_back(aSecurityEnvironment);
+ return m_vSecurityEnvironments.size() - 1;
+}
+
+sal_Int32 SAL_CALL XMLSecurityContextGpg::getSecurityEnvironmentNumber()
+{
+ return m_vSecurityEnvironments.size();
+}
+
+Reference<XSecurityEnvironment>
+ SAL_CALL XMLSecurityContextGpg::getSecurityEnvironmentByIndex(sal_Int32 index)
+{
+ if (index < 0 || o3tl::make_unsigned(index) >= m_vSecurityEnvironments.size())
+ throw RuntimeException("Invalid index");
+
+ return m_vSecurityEnvironments[index];
+}
+
+Reference<XSecurityEnvironment> SAL_CALL XMLSecurityContextGpg::getSecurityEnvironment()
+{
+ if (m_nDefaultEnvIndex < 0
+ || o3tl::make_unsigned(m_nDefaultEnvIndex) >= m_vSecurityEnvironments.size())
+ throw RuntimeException("Invalid index");
+
+ return getSecurityEnvironmentByIndex(m_nDefaultEnvIndex);
+}
+
+sal_Int32 SAL_CALL XMLSecurityContextGpg::getDefaultSecurityEnvironmentIndex()
+{
+ return m_nDefaultEnvIndex;
+}
+
+void SAL_CALL XMLSecurityContextGpg::setDefaultSecurityEnvironmentIndex(sal_Int32 nDefaultEnvIndex)
+{
+ m_nDefaultEnvIndex = nDefaultEnvIndex;
+}
+
+/* XServiceInfo */
+OUString SAL_CALL XMLSecurityContextGpg::getImplementationName()
+{
+ return "com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl";
+}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL XMLSecurityContextGpg::supportsService(const OUString& serviceName)
+{
+ return cppu::supportsService(this, serviceName);
+}
+
+/* XServiceInfo */
+Sequence<OUString> SAL_CALL XMLSecurityContextGpg::getSupportedServiceNames()
+{
+ return { OUString("com.sun.star.xml.crypto.XMLSecurityContext") };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/gpg/XMLSecurityContext.hxx b/xmlsecurity/source/gpg/XMLSecurityContext.hxx
new file mode 100644
index 000000000..e3dea7310
--- /dev/null
+++ b/xmlsecurity/source/gpg/XMLSecurityContext.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sal/config.h>
+#include <rtl/ustring.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp>
+
+#include <vector>
+
+namespace com::sun::star::xml::crypto { class XSecurityEnvironment; }
+
+class XMLSecurityContextGpg : public cppu::WeakImplHelper< css::xml::crypto::XXMLSecurityContext,
+ css::lang::XServiceInfo>
+{
+private:
+ std::vector< css::uno::Reference< css::xml::crypto::XSecurityEnvironment > > m_vSecurityEnvironments;
+
+ sal_Int32 m_nDefaultEnvIndex;
+
+public:
+ XMLSecurityContextGpg();
+ virtual ~XMLSecurityContextGpg() override;
+
+ // XXMLSecurityContext
+ virtual sal_Int32 SAL_CALL addSecurityEnvironment(
+ const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aSecurityEnvironment) override;
+
+ virtual ::sal_Int32 SAL_CALL getSecurityEnvironmentNumber() override;
+
+ virtual css::uno::Reference<css::xml::crypto::XSecurityEnvironment > SAL_CALL getSecurityEnvironmentByIndex(sal_Int32 index) override;
+
+ virtual css::uno::Reference<css::xml::crypto::XSecurityEnvironment > SAL_CALL getSecurityEnvironment() override;
+
+ virtual sal_Int32 SAL_CALL getDefaultSecurityEnvironmentIndex() override;
+
+ virtual void SAL_CALL setDefaultSecurityEnvironmentIndex( sal_Int32 nDefaultEnvIndex ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override ;
+
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override ;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override ;
+} ;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx b/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx
new file mode 100644
index 000000000..3b4e138ae
--- /dev/null
+++ b/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx
@@ -0,0 +1,527 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+#include <xmlsec-wrapper.h>
+#include <cppuhelper/supportsservice.hxx>
+#include <gpg/xmlsignature_gpgimpl.hxx>
+
+#if defined _MSC_VER && defined __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wundef"
+#endif
+#include <gpgme.h>
+#if defined _MSC_VER && defined __clang__
+#pragma clang diagnostic pop
+#endif
+#include <context.h>
+#include <key.h>
+#include <data.h>
+#include <signingresult.h>
+#include <importresult.h>
+
+#include <xmlelementwrapper_xmlsecimpl.hxx>
+#include <xmlsec/xmlstreamio.hxx>
+#include <xmlsec/errorcallback.hxx>
+
+#include "SecurityEnvironment.hxx"
+
+using namespace css::uno;
+using namespace css::lang;
+using namespace css::xml::wrapper;
+using namespace css::xml::crypto;
+
+XMLSignature_GpgImpl::XMLSignature_GpgImpl() {
+}
+
+XMLSignature_GpgImpl::~XMLSignature_GpgImpl() {
+}
+
+/* XXMLSignature */
+Reference< XXMLSignatureTemplate >
+SAL_CALL XMLSignature_GpgImpl::generate(
+ const Reference< XXMLSignatureTemplate >& aTemplate ,
+ const Reference< XSecurityEnvironment >& aEnvironment
+)
+{
+ xmlSecDSigCtxPtr pDsigCtx = nullptr ;
+ xmlNodePtr pNode = nullptr ;
+
+ if( !aTemplate.is() )
+ throw RuntimeException() ;
+
+ if( !aEnvironment.is() )
+ throw RuntimeException() ;
+
+ //Get the xml node
+ Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
+ if( !xElement.is() ) {
+ throw RuntimeException() ;
+ }
+
+ XMLElementWrapper_XmlSecImpl* pElement =
+ dynamic_cast<XMLElementWrapper_XmlSecImpl*>(xElement.get());
+ if( pElement == nullptr ) {
+ throw RuntimeException() ;
+ }
+
+ pNode = pElement->getNativeElement() ;
+
+ //Get the stream/URI binding
+ Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ;
+ if( xUriBinding.is() ) {
+ //Register the stream input callbacks into libxml2
+ if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 )
+ throw RuntimeException() ;
+ }
+
+ //Get Keys Manager
+ SecurityEnvironmentGpg* pSecEnv =
+ dynamic_cast<SecurityEnvironmentGpg*>(aEnvironment.get());
+ if( pSecEnv == nullptr )
+ throw RuntimeException() ;
+
+ setErrorRecorder();
+
+ //Create Signature context
+ pDsigCtx = xmlSecDSigCtxCreate( nullptr ) ;
+ if( pDsigCtx == nullptr )
+ {
+ clearErrorRecorder();
+ return aTemplate;
+ }
+
+ // set intended operation to sign - several asserts inside libxmlsec
+ // wanting that for digest / transforms
+ pDsigCtx->operation = xmlSecTransformOperationSign;
+
+ // we default to SHA512 for all digests - nss crypto does not have it...
+ //pDsigCtx->defDigestMethodId = xmlSecTransformSha512Id;
+
+ // Calculate digest for all references
+ xmlNodePtr cur = xmlSecGetNextElementNode(pNode->children);
+ if( cur != nullptr )
+ cur = xmlSecGetNextElementNode(cur->children);
+ while( cur != nullptr )
+ {
+ // some of those children I suppose should be reference elements
+ if( xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs) )
+ {
+ xmlSecDSigReferenceCtxPtr pDsigRefCtx =
+ xmlSecDSigReferenceCtxCreate(pDsigCtx,
+ xmlSecDSigReferenceOriginSignedInfo);
+ if(pDsigRefCtx == nullptr)
+ throw RuntimeException();
+
+ // add this one to the list
+ if( xmlSecPtrListAdd(&(pDsigCtx->signedInfoReferences),
+ pDsigRefCtx) < 0 )
+ {
+ // TODO resource handling
+ xmlSecDSigReferenceCtxDestroy(pDsigRefCtx);
+ throw RuntimeException();
+ }
+
+ if( xmlSecDSigReferenceCtxProcessNode(pDsigRefCtx, cur) < 0 )
+ throw RuntimeException();
+
+ // final check - all good?
+ if(pDsigRefCtx->status != xmlSecDSigStatusSucceeded)
+ {
+ pDsigCtx->status = xmlSecDSigStatusInvalid;
+ return aTemplate; // TODO - harder error?
+ }
+ }
+
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ // get me a digestible buffer from the signature template!
+ // -------------------------------------------------------
+
+ // run the transformations over SignedInfo element (first child of
+ // pNode)
+ xmlSecNodeSetPtr nodeset = nullptr;
+ cur = xmlSecGetNextElementNode(pNode->children);
+ // TODO assert that...
+ nodeset = xmlSecNodeSetGetChildren(pNode->doc, cur, 1, 0);
+ if(nodeset == nullptr)
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ if( xmlSecTransformCtxXmlExecute(&(pDsigCtx->transformCtx), nodeset) < 0 )
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ // now extract the keyid from PGPData
+ // walk xml tree to PGPData node - go to children, first is
+ // SignedInfo, 2nd is signaturevalue, 3rd is KeyInfo
+ // 1st child is PGPData, 1st grandchild is PGPKeyID
+ cur = xmlSecGetNextElementNode(pNode->children);
+ // TODO error handling
+ cur = xmlSecGetNextElementNode(cur->next);
+ cur = xmlSecGetNextElementNode(cur->next);
+ cur = xmlSecGetNextElementNode(cur->children);
+ // check that this is now PGPData
+ if(!xmlSecCheckNodeName(cur, xmlSecNodePGPData, xmlSecDSigNs))
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+ // check that this is now PGPKeyID
+ cur = xmlSecGetNextElementNode(cur->children);
+ static const xmlChar xmlSecNodePGPKeyID[] = "PGPKeyID";
+ if(!xmlSecCheckNodeName(cur, xmlSecNodePGPKeyID, xmlSecDSigNs))
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ GpgME::Context& rCtx=pSecEnv->getGpgContext();
+ rCtx.setKeyListMode(GPGME_KEYLIST_MODE_LOCAL);
+ GpgME::Error err;
+ xmlChar* pKey=xmlNodeGetContent(cur);
+ if(xmlSecBase64Decode(pKey, reinterpret_cast<xmlSecByte*>(pKey), xmlStrlen(pKey)) < 0)
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+ if( rCtx.addSigningKey(
+ rCtx.key(
+ reinterpret_cast<char*>(pKey), err, true)) )
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ xmlFree(pKey);
+
+ // good, ctx is setup now, let's sign the lot
+ GpgME::Data data_in(
+ reinterpret_cast<char*>(xmlSecBufferGetData(pDsigCtx->transformCtx.result)),
+ xmlSecBufferGetSize(pDsigCtx->transformCtx.result), false);
+ GpgME::Data data_out;
+
+ SAL_INFO("xmlsecurity.xmlsec.gpg", "Generating signature for: " << xmlSecBufferGetData(pDsigCtx->transformCtx.result));
+
+ // we base64-encode anyway
+ rCtx.setArmor(false);
+ GpgME::SigningResult sign_res=rCtx.sign(data_in, data_out,
+ GpgME::Detached);
+ off_t result = data_out.seek(0,SEEK_SET);
+ (void) result;
+ assert(result == 0);
+ int len=0, curr=0; char buf;
+ while( (curr=data_out.read(&buf, 1)) )
+ len += curr;
+
+ if(sign_res.error() || !len)
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ // write signed data to xml
+ xmlChar* signature = static_cast<xmlChar*>(xmlMalloc(len + 1));
+ if(signature == nullptr)
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+ result = data_out.seek(0,SEEK_SET);
+ assert(result == 0);
+ if( data_out.read(signature, len) != len )
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ // conversion to base64
+ xmlChar* signatureEncoded=nullptr;
+ if( !(signatureEncoded=xmlSecBase64Encode(reinterpret_cast<xmlSecByte*>(signature), len, 79)) )
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+ xmlFree(signature);
+
+ // walk xml tree to sign value node - go to children, first is
+ // SignedInfo, 2nd is signaturevalue
+ cur = xmlSecGetNextElementNode(pNode->children);
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ // TODO some assert would be good...
+ xmlNodeSetContentLen(cur, signatureEncoded, xmlStrlen(signatureEncoded));
+ xmlFree(signatureEncoded);
+
+ aTemplate->setStatus(SecurityOperationStatus_OPERATION_SUCCEEDED);
+
+ // done
+ xmlSecDSigCtxDestroy( pDsigCtx ) ;
+
+ //Unregistered the stream/URI binding
+ if( xUriBinding.is() )
+ xmlUnregisterStreamInputCallbacks() ;
+
+ clearErrorRecorder();
+ return aTemplate ;
+}
+
+/* XXMLSignature */
+Reference< XXMLSignatureTemplate >
+SAL_CALL XMLSignature_GpgImpl::validate(
+ const Reference< XXMLSignatureTemplate >& aTemplate ,
+ const Reference< XXMLSecurityContext >& aSecurityCtx
+) {
+ xmlSecDSigCtxPtr pDsigCtx = nullptr ;
+ xmlNodePtr pNode = nullptr ;
+
+ if( !aTemplate.is() )
+ throw RuntimeException() ;
+
+ if( !aSecurityCtx.is() )
+ throw RuntimeException() ;
+
+ //Get the xml node
+ Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
+ if( !xElement.is() )
+ throw RuntimeException() ;
+
+ XMLElementWrapper_XmlSecImpl* pElement =
+ dynamic_cast<XMLElementWrapper_XmlSecImpl*>(xElement.get());
+ if( pElement == nullptr )
+ throw RuntimeException() ;
+
+ pNode = pElement->getNativeElement() ;
+
+ //Get the stream/URI binding
+ Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ;
+ if( xUriBinding.is() ) {
+ //Register the stream input callbacks into libxml2
+ if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 )
+ throw RuntimeException() ;
+ }
+
+ setErrorRecorder();
+
+ sal_Int32 nSecurityEnvironment = aSecurityCtx->getSecurityEnvironmentNumber();
+ sal_Int32 i;
+
+ for (i=0; i<nSecurityEnvironment; ++i)
+ {
+ Reference< XSecurityEnvironment > aEnvironment = aSecurityCtx->getSecurityEnvironmentByIndex(i);
+
+ SecurityEnvironmentGpg* pSecEnv =
+ dynamic_cast<SecurityEnvironmentGpg*>(aEnvironment.get());
+ if( pSecEnv == nullptr )
+ throw RuntimeException() ;
+
+ // TODO figure out key from pSecEnv!
+ // unclear how/where that is transported in nss impl...
+
+ //Create Signature context
+ pDsigCtx = xmlSecDSigCtxCreate( nullptr ) ;
+ if( pDsigCtx == nullptr )
+ {
+ clearErrorRecorder();
+ return aTemplate;
+ }
+
+ // set intended operation to verify - several asserts inside libxmlsec
+ // wanting that for digest / transforms
+ pDsigCtx->operation = xmlSecTransformOperationVerify;
+
+ // reset status - to be set later
+ pDsigCtx->status = xmlSecDSigStatusUnknown;
+
+ // get me a digestible buffer from the SignatureInfo node!
+ // -------------------------------------------------------
+
+ // run the transformations - first child node is required to
+ // be SignatureInfo
+ xmlSecNodeSetPtr nodeset = nullptr;
+ xmlNodePtr cur = xmlSecGetNextElementNode(pNode->children);
+ // TODO assert that...
+ nodeset = xmlSecNodeSetGetChildren(pNode->doc, cur, 1, 0);
+ if(nodeset == nullptr)
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ // TODO assert we really have the SignatureInfo here?
+ if( xmlSecTransformCtxXmlExecute(&(pDsigCtx->transformCtx), nodeset) < 0 )
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ // Validate the template via gpgme
+ GpgME::Context& rCtx=pSecEnv->getGpgContext();
+
+ GpgME::Data data_text(
+ reinterpret_cast<char*>(xmlSecBufferGetData(pDsigCtx->transformCtx.result)),
+ xmlSecBufferGetSize(pDsigCtx->transformCtx.result), false);
+
+ SAL_INFO("xmlsecurity.xmlsec.gpg", "Validating SignatureInfo: " << xmlSecBufferGetData(pDsigCtx->transformCtx.result));
+
+ // walk xml tree to sign value node - go to children, first is
+ // SignedInfo, 2nd is signaturevalue
+ cur = xmlSecGetNextElementNode(pNode->children);
+ cur = xmlSecGetNextElementNode(cur->next);
+
+ if(!xmlSecCheckNodeName(cur, xmlSecNodeSignatureValue, xmlSecDSigNs))
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+ xmlChar* pSignatureValue=xmlNodeGetContent(cur);
+ int nSigSize = xmlSecBase64Decode(pSignatureValue, reinterpret_cast<xmlSecByte*>(pSignatureValue), xmlStrlen(pSignatureValue));
+ if( nSigSize < 0)
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ GpgME::Data data_signature(
+ reinterpret_cast<char*>(pSignatureValue),
+ nSigSize, false);
+
+ GpgME::VerificationResult verify_res=rCtx.verifyDetachedSignature(
+ data_signature, data_text);
+
+ // TODO: needs some more error handling, needs checking _all_ signatures
+ if( verify_res.isNull() || verify_res.numSignatures() == 0
+ // there is at least 1 signature and it is anything else than fully valid
+ || ( (verify_res.numSignatures() > 0)
+ && verify_res.signature(0).status().encodedError() > 0 ) )
+ {
+ // let's try again, but this time import the public key
+ // payload (avoiding that in a first cut for being a bit
+ // speedier. also prevents all too easy poisoning/sha1
+ // fingerprint collision attacks)
+
+ // walk xml tree to PGPData node - go to children, first is
+ // SignedInfo, 2nd is signaturevalue, 3rd is KeyInfo
+ // 1st child is PGPData, 1st or 2nd grandchild is PGPKeyPacket
+ cur = xmlSecGetNextElementNode(pNode->children);
+ // TODO error handling
+ cur = xmlSecGetNextElementNode(cur->next);
+ cur = xmlSecGetNextElementNode(cur->next);
+ cur = xmlSecGetNextElementNode(cur->children);
+ // check that this is now PGPData
+ if(!xmlSecCheckNodeName(cur, xmlSecNodePGPData, xmlSecDSigNs))
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+ // check that this is now PGPKeyPacket
+ cur = xmlSecGetNextElementNode(cur->children);
+ static const xmlChar xmlSecNodePGPKeyPacket[] = "PGPKeyPacket";
+ if(!xmlSecCheckNodeName(cur, xmlSecNodePGPKeyPacket, xmlSecDSigNs))
+ {
+ // not this one, maybe the next?
+ cur = xmlSecGetNextElementNode(cur->next);
+ if(!xmlSecCheckNodeName(cur, xmlSecNodePGPKeyPacket, xmlSecDSigNs))
+ {
+ // ok, giving up
+ clearErrorRecorder();
+ xmlFree(pSignatureValue);
+
+ return aTemplate;
+ }
+ }
+
+ // got a key packet, import & re-validate
+ xmlChar* pKeyPacket=xmlNodeGetContent(cur);
+ int nKeyLen = xmlSecBase64Decode(pKeyPacket, reinterpret_cast<xmlSecByte*>(pKeyPacket), xmlStrlen(pKeyPacket));
+ if( nKeyLen < 0)
+ throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol.");
+
+ GpgME::Data data_key(
+ reinterpret_cast<char*>(pKeyPacket),
+ nKeyLen, false);
+
+ rCtx.importKeys(data_key);
+ xmlFree(pKeyPacket);
+
+ // and re-run (rewind text and signature streams to position 0)
+ (void)data_text.seek(0,SEEK_SET);
+ (void)data_signature.seek(0,SEEK_SET);
+ verify_res=rCtx.verifyDetachedSignature(data_signature, data_text);
+
+ // TODO: needs some more error handling, needs checking _all_ signatures
+ if( verify_res.isNull() || verify_res.numSignatures() == 0
+ // there is at least 1 signature and it is anything else than valid
+ || ( (verify_res.numSignatures() > 0)
+ && verify_res.signature(0).status().encodedError() > 0 ) )
+ {
+ clearErrorRecorder();
+ xmlFree(pSignatureValue);
+
+ return aTemplate;
+ }
+ }
+
+ xmlFree(pSignatureValue);
+
+ // now verify digest for all references
+ cur = xmlSecGetNextElementNode(pNode->children);
+ if( cur != nullptr )
+ cur = xmlSecGetNextElementNode(cur->children);
+ while( cur != nullptr )
+ {
+ // some of those children I suppose should be reference elements
+ if( xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs) )
+ {
+ xmlSecDSigReferenceCtxPtr pDsigRefCtx =
+ xmlSecDSigReferenceCtxCreate(pDsigCtx,
+ xmlSecDSigReferenceOriginSignedInfo);
+ if(pDsigRefCtx == nullptr)
+ throw RuntimeException();
+
+ // add this one to the list
+ if( xmlSecPtrListAdd(&(pDsigCtx->signedInfoReferences),
+ pDsigRefCtx) < 0 )
+ {
+ // TODO resource handling
+ xmlSecDSigReferenceCtxDestroy(pDsigRefCtx);
+ throw RuntimeException();
+ }
+
+ if( xmlSecDSigReferenceCtxProcessNode(pDsigRefCtx, cur) < 0 )
+ throw RuntimeException();
+
+ // final check - all good?
+ if(pDsigRefCtx->status != xmlSecDSigStatusSucceeded)
+ {
+ pDsigCtx->status = xmlSecDSigStatusInvalid;
+ return aTemplate; // TODO - harder error?
+ }
+ }
+
+ cur = xmlSecGetNextElementNode(cur->next);
+ }
+
+ // TODO - also verify manifest (only relevant for ooxml)?
+ aTemplate->setStatus(SecurityOperationStatus_OPERATION_SUCCEEDED);
+
+ // done
+ xmlSecDSigCtxDestroy( pDsigCtx ) ;
+ }
+
+ //Unregistered the stream/URI binding
+ if( xUriBinding.is() )
+ xmlUnregisterStreamInputCallbacks() ;
+
+ clearErrorRecorder();
+ return aTemplate ;
+}
+
+/* XServiceInfo */
+OUString SAL_CALL XMLSignature_GpgImpl::getImplementationName() {
+ return impl_getImplementationName() ;
+}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL XMLSignature_GpgImpl::supportsService( const OUString& serviceName) {
+ return cppu::supportsService(this, serviceName);
+}
+
+/* XServiceInfo */
+Sequence< OUString > SAL_CALL XMLSignature_GpgImpl::getSupportedServiceNames() {
+ return impl_getSupportedServiceNames() ;
+}
+
+//Helper for XServiceInfo
+Sequence< OUString > XMLSignature_GpgImpl::impl_getSupportedServiceNames() {
+ Sequence<OUString> seqServiceNames { "com.sun.star.xml.crypto.XMLSignature" };
+ return seqServiceNames ;
+}
+
+OUString XMLSignature_GpgImpl::impl_getImplementationName() {
+ return "com.sun.star.xml.security.bridge.xmlsec.XMLSignature_GpgImpl" ;
+}
+
+//Helper for registry
+Reference< XInterface > XMLSignature_GpgImpl::impl_createInstance( const Reference< XMultiServiceFactory >& ) {
+ return Reference< XInterface >( *new XMLSignature_GpgImpl ) ;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/helper/UriBindingHelper.cxx b/xmlsecurity/source/helper/UriBindingHelper.cxx
new file mode 100644
index 000000000..f6c36d2c8
--- /dev/null
+++ b/xmlsecurity/source/helper/UriBindingHelper.cxx
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <UriBindingHelper.hxx>
+
+#include <tools/solar.h>
+#include <unotools/streamhelper.hxx>
+
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <osl/diagnose.h>
+#include <rtl/uri.hxx>
+#include <sal/log.hxx>
+
+using namespace com::sun::star;
+
+// XUriBinding
+
+UriBindingHelper::UriBindingHelper()
+{
+}
+
+UriBindingHelper::UriBindingHelper( const css::uno::Reference < css::embed::XStorage >& rxStorage )
+{
+ mxStorage = rxStorage;
+}
+
+void SAL_CALL UriBindingHelper::setUriBinding( const OUString& /*uri*/, const uno::Reference< io::XInputStream >&)
+{
+}
+
+uno::Reference< io::XInputStream > SAL_CALL UriBindingHelper::getUriBinding( const OUString& uri )
+{
+ uno::Reference< io::XInputStream > xInputStream;
+ if ( mxStorage.is() )
+ {
+ xInputStream = OpenInputStream( mxStorage, uri );
+ }
+ else
+ {
+ SvFileStream* pStream = new SvFileStream( uri, StreamMode::READ );
+ sal_uInt64 nBytes = pStream->TellEnd();
+ SvLockBytesRef xLockBytes = new SvLockBytes( pStream, true );
+ xInputStream = new utl::OInputStreamHelper( xLockBytes, nBytes );
+ }
+ return xInputStream;
+}
+
+uno::Reference < io::XInputStream > UriBindingHelper::OpenInputStream( const uno::Reference < embed::XStorage >& rxStore, const OUString& rURI )
+{
+ OSL_ASSERT(!rURI.isEmpty());
+ uno::Reference < io::XInputStream > xInStream;
+
+ OUString aURI(rURI);
+ // Ignore leading slash, don't attempt to open a storage with name "".
+ if (aURI.startsWith("/"))
+ aURI = aURI.copy(1);
+ // Ignore query part of the URI.
+ sal_Int32 nQueryPos = aURI.indexOf('?');
+ if (nQueryPos != -1)
+ aURI = aURI.copy(0, nQueryPos);
+
+
+ sal_Int32 nSepPos = aURI.indexOf( '/' );
+ if ( nSepPos == -1 )
+ {
+ // Cloning because of I can't keep all storage references open
+ // MBA with think about a better API...
+ const OUString sName = ::rtl::Uri::decode(
+ aURI, rtl_UriDecodeStrict, rtl_UriCharClassRelSegment);
+ if (sName.isEmpty() && !aURI.isEmpty())
+ throw uno::Exception("Could not decode URI for stream element.", nullptr);
+
+ uno::Reference< io::XStream > xStream;
+ if (!rxStore->hasByName(sName))
+ SAL_WARN("xmlsecurity.helper", "expected stream, but not found: " << sName);
+ else
+ xStream = rxStore->cloneStreamElement( sName );
+ if ( !xStream.is() )
+ throw uno::RuntimeException();
+ xInStream = xStream->getInputStream();
+ }
+ else
+ {
+ const OUString aStoreName = ::rtl::Uri::decode(
+ aURI.copy( 0, nSepPos ), rtl_UriDecodeStrict, rtl_UriCharClassRelSegment);
+ if (aStoreName.isEmpty() && !aURI.isEmpty())
+ throw uno::Exception("Could not decode URI for stream element.", nullptr);
+
+ OUString aElement = aURI.copy( nSepPos+1 );
+ uno::Reference < embed::XStorage > xSubStore = rxStore->openStorageElement( aStoreName, embed::ElementModes::READ );
+ xInStream = OpenInputStream( xSubStore, aElement );
+ }
+ return xInStream;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/helper/documentsignaturehelper.cxx b/xmlsecurity/source/helper/documentsignaturehelper.cxx
new file mode 100644
index 000000000..af3d51154
--- /dev/null
+++ b/xmlsecurity/source/helper/documentsignaturehelper.cxx
@@ -0,0 +1,650 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include <documentsignaturehelper.hxx>
+
+#include <algorithm>
+#include <functional>
+#include <string_view>
+
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/StorageFormats.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/beans/StringPair.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+
+#include <comphelper/documentconstants.hxx>
+#include <comphelper/ofopxmlhelper.hxx>
+#include <comphelper/processfactory.hxx>
+#include <osl/diagnose.h>
+#include <rtl/ref.hxx>
+#include <rtl/uri.hxx>
+#include <sal/log.hxx>
+#include <svx/xoutbmp.hxx>
+#include <tools/diagnose_ex.h>
+#include <xmloff/attrlist.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <xsecctl.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace css::xml::sax;
+
+namespace
+{
+OUString getElement(OUString const & version, ::sal_Int32 * index)
+{
+ while (*index < version.getLength() && version[*index] == '0') {
+ ++*index;
+ }
+ return version.getToken(0, '.', *index);
+}
+
+
+// Return 1 if version1 is greater than version 2, 0 if they are equal
+//and -1 if version1 is less version 2
+int compareVersions(
+ OUString const & version1, OUString const & version2)
+{
+ for (::sal_Int32 i1 = 0, i2 = 0; i1 >= 0 || i2 >= 0;) {
+ OUString e1(getElement(version1, &i1));
+ OUString e2(getElement(version2, &i2));
+ if (e1.getLength() < e2.getLength()) {
+ return -1;
+ } else if (e1.getLength() > e2.getLength()) {
+ return 1;
+ } else if (e1 < e2) {
+ return -1;
+ } else if (e1 > e2) {
+ return 1;
+ }
+ }
+ return 0;
+}
+}
+
+static void ImplFillElementList(
+ std::vector< OUString >& rList, const Reference < css::embed::XStorage >& rxStore,
+ std::u16string_view rRootStorageName, const bool bRecursive,
+ const DocumentSignatureAlgorithm mode)
+{
+ const Sequence< OUString > aElements = rxStore->getElementNames();
+
+ for ( const auto& rName : aElements )
+ {
+ if (rName == "[Content_Types].xml")
+ // OOXML
+ continue;
+
+ // If the user enabled validating according to OOo 3.0
+ // then mimetype and all content of META-INF must be excluded.
+ if (mode != DocumentSignatureAlgorithm::OOo3_2
+ && (rName == "META-INF" || rName == "mimetype"))
+ {
+ continue;
+ }
+ else
+ {
+ OUString sEncName = ::rtl::Uri::encode(
+ rName, rtl_UriCharClassRelSegment,
+ rtl_UriEncodeStrict, RTL_TEXTENCODING_UTF8);
+ if (sEncName.isEmpty() && !rName.isEmpty())
+ throw css::uno::RuntimeException("Failed to encode element name of XStorage", nullptr);
+
+ if ( rxStore->isStreamElement( rName ) )
+ {
+ //Exclude documentsignatures.xml!
+ if (rName ==
+ DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName())
+ continue;
+ OUString aFullName( rRootStorageName + sEncName );
+ rList.push_back(aFullName);
+ }
+ else if ( bRecursive && rxStore->isStorageElement( rName ) )
+ {
+ Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( rName, css::embed::ElementModes::READ );
+ OUString aFullRootName( rRootStorageName + sEncName + "/" );
+ ImplFillElementList(rList, xSubStore, aFullRootName, bRecursive, mode);
+ }
+ }
+ }
+}
+
+
+bool DocumentSignatureHelper::isODFPre_1_2(const OUString & sVersion)
+{
+ //The property version exists only if the document is at least version 1.2
+ //That is, if the document has version 1.1 and sVersion is empty.
+ //The constant is defined in comphelper/documentconstants.hxx
+ return compareVersions(sVersion, ODFVER_012_TEXT) == -1;
+}
+
+bool DocumentSignatureHelper::isOOo3_2_Signature(const SignatureInformation & sigInfo)
+{
+ return std::any_of(sigInfo.vSignatureReferenceInfors.cbegin(),
+ sigInfo.vSignatureReferenceInfors.cend(),
+ [](const SignatureReferenceInformation& info) { return info.ouURI == "META-INF/manifest.xml"; });
+}
+
+DocumentSignatureAlgorithm
+DocumentSignatureHelper::getDocumentAlgorithm(
+ const OUString & sODFVersion, const SignatureInformation & sigInfo)
+{
+ OSL_ASSERT(!sODFVersion.isEmpty());
+ DocumentSignatureAlgorithm mode = DocumentSignatureAlgorithm::OOo3_2;
+ if (!isOOo3_2_Signature(sigInfo))
+ {
+ if (isODFPre_1_2(sODFVersion))
+ mode = DocumentSignatureAlgorithm::OOo2;
+ else
+ mode = DocumentSignatureAlgorithm::OOo3_0;
+ }
+ return mode;
+}
+
+//The function creates a list of files which are to be signed or for which
+//the signature is to be validated. The strings are UTF8 encoded URIs which
+//contain '/' as path separators.
+//
+//The algorithm how document signatures are created and validated has
+//changed over time. The change affects only which files within the document
+//are changed. Document signatures created by OOo 2.x only used particular files. Since
+//OOo 3.0 everything except "mimetype" and "META-INF" are signed. As of OOo 3.2 everything
+//except META-INF/documentsignatures.xml is signed.
+//Signatures are validated according to the algorithm which was then used for validation.
+//That is, when validating a signature which was created by OOo 3.0, then mimetype and
+//META-INF are not used.
+//
+//When a signature is created then we always use the latest algorithm. That is, we use
+//that of OOo 3.2
+std::vector< OUString >
+DocumentSignatureHelper::CreateElementList(
+ const Reference < css::embed::XStorage >& rxStore,
+ DocumentSignatureMode eMode,
+ const DocumentSignatureAlgorithm mode)
+{
+ std::vector< OUString > aElements;
+ OUString aSep( "/" );
+
+ switch ( eMode )
+ {
+ case DocumentSignatureMode::Content:
+ {
+ if (mode == DocumentSignatureAlgorithm::OOo2) //that is, ODF 1.0, 1.1
+ {
+ // 1) Main content
+ ImplFillElementList(aElements, rxStore, std::u16string_view(), false, mode);
+
+ // 2) Pictures...
+ OUString aSubStorageName( "Pictures" );
+ try
+ {
+ Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ );
+ ImplFillElementList(
+ aElements, xSubStore, OUStringConcatenation(aSubStorageName+aSep), true, mode);
+ }
+ catch(css::io::IOException& )
+ {
+ ; // Doesn't have to exist...
+ }
+ // 3) OLE...
+ aSubStorageName = "ObjectReplacements";
+ try
+ {
+ Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ );
+ ImplFillElementList(
+ aElements, xSubStore, OUStringConcatenation(aSubStorageName+aSep), true, mode);
+ xSubStore.clear();
+
+ // Object folders...
+ const Sequence< OUString > aElementNames = rxStore->getElementNames();
+ for ( const auto& rName : aElementNames )
+ {
+ if ( ( rName.match( "Object " ) ) && rxStore->isStorageElement( rName ) )
+ {
+ Reference < css::embed::XStorage > xTmpSubStore = rxStore->openStorageElement( rName, css::embed::ElementModes::READ );
+ ImplFillElementList(
+ aElements, xTmpSubStore, OUStringConcatenation(rName+aSep), true, mode);
+ }
+ }
+ }
+ catch( css::io::IOException& )
+ {
+ ; // Doesn't have to exist...
+ }
+ }
+ else
+ {
+ // Everything except META-INF
+ ImplFillElementList(aElements, rxStore, std::u16string_view(), true, mode);
+ }
+ }
+ break;
+ case DocumentSignatureMode::Macros:
+ {
+ // 1) Macros
+ OUString aSubStorageName( "Basic" );
+ try
+ {
+ Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ );
+ ImplFillElementList(
+ aElements, xSubStore, OUStringConcatenation(aSubStorageName+aSep), true, mode);
+ }
+ catch( css::io::IOException& )
+ {
+ ; // Doesn't have to exist...
+ }
+
+ // 2) Dialogs
+ aSubStorageName = "Dialogs";
+ try
+ {
+ Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ );
+ ImplFillElementList(
+ aElements, xSubStore, OUStringConcatenation(aSubStorageName+aSep), true, mode);
+ }
+ catch( css::io::IOException& )
+ {
+ ; // Doesn't have to exist...
+ }
+ // 3) Scripts
+ aSubStorageName = "Scripts";
+ try
+ {
+ Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ );
+ ImplFillElementList(
+ aElements, xSubStore, OUStringConcatenation(aSubStorageName+aSep), true, mode);
+ }
+ catch( css::io::IOException& )
+ {
+ ; // Doesn't have to exist...
+ }
+ }
+ break;
+ case DocumentSignatureMode::Package:
+ {
+ // Everything except META-INF
+ ImplFillElementList(aElements, rxStore, std::u16string_view(), true, mode);
+ }
+ break;
+ }
+
+ return aElements;
+}
+
+void DocumentSignatureHelper::AppendContentTypes(const uno::Reference<embed::XStorage>& xStorage, std::vector<OUString>& rElements)
+{
+ if (!xStorage.is() || !xStorage->hasByName("[Content_Types].xml"))
+ // ODF
+ return;
+
+ uno::Reference<io::XInputStream> xRelStream(xStorage->openStreamElement("[Content_Types].xml", embed::ElementModes::READ), uno::UNO_QUERY);
+ uno::Sequence< uno::Sequence<beans::StringPair> > aContentTypeInfo = comphelper::OFOPXMLHelper::ReadContentTypeSequence(xRelStream, comphelper::getProcessComponentContext());
+ if (aContentTypeInfo.getLength() < 2)
+ {
+ SAL_WARN("xmlsecurity.helper", "no defaults or overrides in aContentTypeInfo");
+ return;
+ }
+ const uno::Sequence<beans::StringPair>& rDefaults = aContentTypeInfo[0];
+ const uno::Sequence<beans::StringPair>& rOverrides = aContentTypeInfo[1];
+
+ for (OUString& rElement : rElements)
+ {
+ auto it = std::find_if(rOverrides.begin(), rOverrides.end(), [&](const beans::StringPair& rPair)
+ {
+ return rPair.First == OUStringConcatenation("/" + rElement);
+ });
+
+ if (it != rOverrides.end())
+ {
+ rElement = "/" + rElement + "?ContentType=" + it->Second;
+ continue;
+ }
+
+ it = std::find_if(rDefaults.begin(), rDefaults.end(), [&](const beans::StringPair& rPair)
+ {
+ return rElement.endsWith(OUStringConcatenation("." + rPair.First));
+ });
+
+ if (it != rDefaults.end())
+ {
+ rElement = "/" + rElement + "?ContentType=" + it->Second;
+ continue;
+ }
+ SAL_WARN("xmlsecurity.helper", "found no content type for " << rElement);
+ }
+
+ std::sort(rElements.begin(), rElements.end());
+}
+
+SignatureStreamHelper DocumentSignatureHelper::OpenSignatureStream(
+ const Reference < css::embed::XStorage >& rxStore, sal_Int32 nOpenMode, DocumentSignatureMode eDocSigMode )
+{
+ sal_Int32 nSubStorageOpenMode = css::embed::ElementModes::READ;
+ if ( nOpenMode & css::embed::ElementModes::WRITE )
+ nSubStorageOpenMode = css::embed::ElementModes::WRITE;
+
+ SignatureStreamHelper aHelper;
+
+ if (!rxStore.is())
+ return aHelper;
+
+ if (rxStore->hasByName("META-INF"))
+ {
+ try
+ {
+ aHelper.xSignatureStorage = rxStore->openStorageElement( "META-INF", nSubStorageOpenMode );
+ if ( aHelper.xSignatureStorage.is() )
+ {
+ OUString aSIGStreamName;
+ if ( eDocSigMode == DocumentSignatureMode::Content )
+ aSIGStreamName = DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName();
+ else if ( eDocSigMode == DocumentSignatureMode::Macros )
+ aSIGStreamName = DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName();
+ else
+ aSIGStreamName = DocumentSignatureHelper::GetPackageSignatureDefaultStreamName();
+
+#ifdef SAL_LOG_INFO
+ aHelper.xSignatureStream
+ = aHelper.xSignatureStorage->openStreamElement(aSIGStreamName, nOpenMode);
+ SAL_INFO("xmlsecurity.helper",
+ "DocumentSignatureHelper::OpenSignatureStream: stream name is '"
+ << aSIGStreamName << "'");
+ if (aHelper.xSignatureStream.is())
+ {
+ uno::Reference<io::XInputStream> xInputStream(aHelper.xSignatureStream,
+ uno::UNO_QUERY);
+ sal_Int64 nSize = 0;
+ uno::Reference<beans::XPropertySet> xPropertySet(xInputStream, uno::UNO_QUERY);
+ xPropertySet->getPropertyValue("Size") >>= nSize;
+ if (nSize >= 0 || nSize < SAL_MAX_INT32)
+ {
+ uno::Sequence<sal_Int8> aData;
+ xInputStream->readBytes(aData, nSize);
+ SAL_INFO("xmlsecurity.helper",
+ "DocumentSignatureHelper::OpenSignatureStream: stream content is '"
+ << OString(reinterpret_cast<const char*>(aData.getArray()),
+ aData.getLength())
+ << "'");
+ }
+ }
+ aHelper.xSignatureStream.clear();
+#endif
+
+ aHelper.xSignatureStream = aHelper.xSignatureStorage->openStreamElement( aSIGStreamName, nOpenMode );
+ }
+ }
+ catch(css::io::IOException& )
+ {
+ // Doesn't have to exist...
+ SAL_WARN_IF( nOpenMode != css::embed::ElementModes::READ, "xmlsecurity.helper", "Error creating signature stream..." );
+ }
+ }
+ else if(rxStore->hasByName("[Content_Types].xml"))
+ {
+ try
+ {
+ if (rxStore->hasByName("_xmlsignatures") && (nOpenMode & embed::ElementModes::TRUNCATE))
+ // Truncate, then all signatures will be written -> remove previous ones.
+ rxStore->removeElement("_xmlsignatures");
+
+ aHelper.xSignatureStorage = rxStore->openStorageElement("_xmlsignatures", nSubStorageOpenMode);
+ aHelper.nStorageFormat = embed::StorageFormats::OFOPXML;
+ }
+ catch (const io::IOException&)
+ {
+ TOOLS_WARN_EXCEPTION_IF(nOpenMode != css::embed::ElementModes::READ, "xmlsecurity.helper", "DocumentSignatureHelper::OpenSignatureStream:");
+ }
+ }
+
+ return aHelper;
+}
+
+/** Check whether the current file can be signed with GPG (only ODF >= 1.2 can currently) */
+bool DocumentSignatureHelper::CanSignWithGPG(
+ const Reference < css::embed::XStorage >& rxStore,
+ const OUString& sOdfVersion)
+{
+ if (!rxStore.is())
+ return false;
+
+ if (rxStore->hasByName("META-INF")) // ODF
+ {
+ return !isODFPre_1_2(sOdfVersion);
+ }
+
+ return false;
+}
+
+
+
+//sElementList contains all files which are expected to be signed. Only those files must me signed,
+//no more, no less.
+//The DocumentSignatureAlgorithm indicates if the document was created with OOo 2.x. Then
+//the uri s in the Reference elements in the signature, were not properly encoded.
+// For example: <Reference URI="ObjectReplacements/Object 1">
+bool DocumentSignatureHelper::checkIfAllFilesAreSigned(
+ const ::std::vector< OUString > & sElementList,
+ const SignatureInformation & sigInfo,
+ const DocumentSignatureAlgorithm alg)
+{
+ // Can only be valid if ALL streams are signed, which means real stream count == signed stream count
+ unsigned int nRealCount = 0;
+ std::function<OUString(const OUString&)> fEncode = [](const OUString& rStr) { return rStr; };
+ if (alg == DocumentSignatureAlgorithm::OOo2)
+ //Comparing URIs is a difficult. Therefore we kind of normalize
+ //it before comparing. We assume that our URI do not have a leading "./"
+ //and fragments at the end (...#...)
+ fEncode = [](const OUString& rStr) {
+ return rtl::Uri::encode(rStr, rtl_UriCharClassPchar, rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_UTF8);
+ };
+
+ for ( int i = sigInfo.vSignatureReferenceInfors.size(); i; )
+ {
+ const SignatureReferenceInformation& rInf = sigInfo.vSignatureReferenceInfors[--i];
+ // There is also an extra entry of type SignatureReferenceType::SAMEDOCUMENT because of signature date.
+ if ( ( rInf.nType == SignatureReferenceType::BINARYSTREAM ) || ( rInf.nType == SignatureReferenceType::XMLSTREAM ) )
+ {
+ //find the file in the element list
+ if (std::any_of(sElementList.cbegin(), sElementList.cend(),
+ [&fEncode, &rInf](const OUString& rElement) { return fEncode(rElement) == fEncode(rInf.ouURI); }))
+ nRealCount++;
+ }
+ }
+ return sElementList.size() == nRealCount;
+}
+
+/*Compares the Uri which are obtained from CreateElementList with
+ the path obtained from the manifest.xml.
+ Returns true if both strings are equal.
+*/
+bool DocumentSignatureHelper::equalsReferenceUriManifestPath(
+ std::u16string_view rUri, std::u16string_view rPath)
+{
+ //split up the uri and path into segments. Both are separated by '/'
+ std::vector<OUString> vUriSegments;
+ for (sal_Int32 nIndex = 0; nIndex >= 0; )
+ vUriSegments.push_back(OUString(o3tl::getToken(rUri, 0, '/', nIndex )));
+
+ std::vector<OUString> vPathSegments;
+ for (sal_Int32 nIndex = 0; nIndex >= 0; )
+ vPathSegments.push_back(OUString(o3tl::getToken(rPath, 0, '/', nIndex )));
+
+ if (vUriSegments.size() != vPathSegments.size())
+ return false;
+
+ //Now compare each segment of the uri with its counterpart from the path
+ return std::equal(
+ vUriSegments.cbegin(), vUriSegments.cend(), vPathSegments.cbegin(),
+ [](const OUString& rUriSegment, const OUString& rPathSegment) {
+ //Decode the uri segment, so that %20 becomes ' ', etc.
+ OUString sDecUri = rtl::Uri::decode(rUriSegment, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
+ return sDecUri == rPathSegment;
+ });
+}
+
+OUString DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName()
+{
+ return "documentsignatures.xml";
+}
+
+OUString DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName()
+{
+ return "macrosignatures.xml";
+}
+
+OUString DocumentSignatureHelper::GetPackageSignatureDefaultStreamName()
+{
+ return "packagesignatures.xml";
+}
+
+void DocumentSignatureHelper::writeDigestMethod(
+ const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler)
+{
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("Algorithm", ALGO_XMLDSIGSHA256);
+ xDocumentHandler->startElement("DigestMethod", uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+ xDocumentHandler->endElement("DigestMethod");
+}
+
+static void WriteXadesCert(
+ uno::Reference<xml::sax::XDocumentHandler> const& xDocumentHandler,
+ SignatureInformation::X509CertInfo const& rCertInfo)
+{
+ xDocumentHandler->startElement("xd:Cert", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ xDocumentHandler->startElement("xd:CertDigest", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ DocumentSignatureHelper::writeDigestMethod(xDocumentHandler);
+ xDocumentHandler->startElement("DigestValue", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ assert(!rCertInfo.CertDigest.isEmpty());
+ xDocumentHandler->characters(rCertInfo.CertDigest);
+ xDocumentHandler->endElement("DigestValue");
+ xDocumentHandler->endElement("xd:CertDigest");
+ xDocumentHandler->startElement("xd:IssuerSerial", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ xDocumentHandler->startElement("X509IssuerName", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ xDocumentHandler->characters(rCertInfo.X509IssuerName);
+ xDocumentHandler->endElement("X509IssuerName");
+ xDocumentHandler->startElement("X509SerialNumber", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ xDocumentHandler->characters(rCertInfo.X509SerialNumber);
+ xDocumentHandler->endElement("X509SerialNumber");
+ xDocumentHandler->endElement("xd:IssuerSerial");
+ xDocumentHandler->endElement("xd:Cert");
+}
+
+void DocumentSignatureHelper::writeSignedProperties(
+ const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler,
+ const SignatureInformation& signatureInfo,
+ const OUString& sDate, const bool bWriteSignatureLineData)
+{
+ {
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("Id", "idSignedProperties_" + signatureInfo.ouSignatureId);
+ xDocumentHandler->startElement("xd:SignedProperties", uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+ }
+
+ xDocumentHandler->startElement("xd:SignedSignatureProperties", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ xDocumentHandler->startElement("xd:SigningTime", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ xDocumentHandler->characters(sDate);
+ xDocumentHandler->endElement("xd:SigningTime");
+ xDocumentHandler->startElement("xd:SigningCertificate", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ assert(signatureInfo.GetSigningCertificate() || !signatureInfo.ouGpgKeyID.isEmpty());
+ if (signatureInfo.GetSigningCertificate())
+ {
+ // how should this deal with multiple X509Data elements?
+ // for now, let's write all of the certificates ...
+ for (auto const& rData : signatureInfo.X509Datas)
+ {
+ for (auto const& it : rData)
+ {
+ WriteXadesCert(xDocumentHandler, it);
+ }
+ }
+ }
+ else
+ {
+ // for PGP, write empty mandatory X509IssuerName, X509SerialNumber
+ SignatureInformation::X509CertInfo temp;
+ temp.CertDigest = signatureInfo.ouGpgKeyID;
+ WriteXadesCert(xDocumentHandler, temp);
+ }
+ xDocumentHandler->endElement("xd:SigningCertificate");
+ xDocumentHandler->startElement("xd:SignaturePolicyIdentifier", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ xDocumentHandler->startElement("xd:SignaturePolicyImplied", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ xDocumentHandler->endElement("xd:SignaturePolicyImplied");
+ xDocumentHandler->endElement("xd:SignaturePolicyIdentifier");
+
+ if (bWriteSignatureLineData && !signatureInfo.ouSignatureLineId.isEmpty()
+ && signatureInfo.aValidSignatureImage.is() && signatureInfo.aInvalidSignatureImage.is())
+ {
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute(
+ "xmlns:loext", "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0");
+ xDocumentHandler->startElement(
+ "loext:SignatureLine",
+ Reference<XAttributeList>(pAttributeList));
+
+ {
+ // Write SignatureLineId element
+ xDocumentHandler->startElement(
+ "loext:SignatureLineId",
+ Reference<XAttributeList>(new SvXMLAttributeList()));
+ xDocumentHandler->characters(signatureInfo.ouSignatureLineId);
+ xDocumentHandler->endElement("loext:SignatureLineId");
+ }
+
+ {
+ // Write SignatureLineValidImage element
+ xDocumentHandler->startElement(
+ "loext:SignatureLineValidImage",
+ Reference<XAttributeList>(new SvXMLAttributeList()));
+
+ OUString aGraphicInBase64;
+ Graphic aGraphic(signatureInfo.aValidSignatureImage);
+ if (!XOutBitmap::GraphicToBase64(aGraphic, aGraphicInBase64, false))
+ SAL_WARN("xmlsecurity.helper", "could not convert graphic to base64");
+
+ xDocumentHandler->characters(aGraphicInBase64);
+ xDocumentHandler->endElement("loext:SignatureLineValidImage");
+ }
+
+ {
+ // Write SignatureLineInvalidImage element
+ xDocumentHandler->startElement(
+ "loext:SignatureLineInvalidImage",
+ Reference<XAttributeList>(new SvXMLAttributeList()));
+ OUString aGraphicInBase64;
+ Graphic aGraphic(signatureInfo.aInvalidSignatureImage);
+ if (!XOutBitmap::GraphicToBase64(aGraphic, aGraphicInBase64, false))
+ SAL_WARN("xmlsecurity.helper", "could not convert graphic to base64");
+ xDocumentHandler->characters(aGraphicInBase64);
+ xDocumentHandler->endElement("loext:SignatureLineInvalidImage");
+ }
+
+ xDocumentHandler->endElement("loext:SignatureLine");
+ }
+
+ xDocumentHandler->endElement("xd:SignedSignatureProperties");
+
+ xDocumentHandler->endElement("xd:SignedProperties");
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/helper/documentsignaturemanager.cxx b/xmlsecurity/source/helper/documentsignaturemanager.cxx
new file mode 100644
index 000000000..83606dc96
--- /dev/null
+++ b/xmlsecurity/source/helper/documentsignaturemanager.cxx
@@ -0,0 +1,705 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <documentsignaturemanager.hxx>
+#include <config_gpgme.h>
+
+#include <gpg/SEInitializer.hxx>
+
+#include <com/sun/star/embed/StorageFormats.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/io/TempFile.hpp>
+#include <com/sun/star/io/XTruncate.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/xml/crypto/SEInitializer.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/packages/manifest/ManifestReader.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/xml/sax/XWriter.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+
+#include <comphelper/base64.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <tools/datetime.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <certificate.hxx>
+#include <biginteger.hxx>
+
+#include <xmlsec/xmlsec_init.hxx>
+
+#include <pdfsignaturehelper.hxx>
+
+#include <memory>
+
+using namespace css;
+using namespace css::graphic;
+using namespace css::uno;
+
+DocumentSignatureManager::DocumentSignatureManager(
+ const uno::Reference<uno::XComponentContext>& xContext, DocumentSignatureMode eMode)
+ : mxContext(xContext)
+ , maSignatureHelper(xContext)
+ , meSignatureMode(eMode)
+{
+}
+
+DocumentSignatureManager::~DocumentSignatureManager() { deInitXmlSec(); }
+
+bool DocumentSignatureManager::init()
+{
+ SAL_WARN_IF(mxSEInitializer.is(), "xmlsecurity.helper",
+ "DocumentSignatureManager::Init - mxSEInitializer already set!");
+ SAL_WARN_IF(mxSecurityContext.is(), "xmlsecurity.helper",
+ "DocumentSignatureManager::Init - mxSecurityContext already set!");
+ SAL_WARN_IF(mxGpgSEInitializer.is(), "xmlsecurity.helper",
+ "DocumentSignatureManager::Init - mxGpgSEInitializer already set!");
+
+ // xmlsec is needed by both services, so init before those
+ initXmlSec();
+
+ mxSEInitializer = xml::crypto::SEInitializer::create(mxContext);
+#if HAVE_FEATURE_GPGME
+ mxGpgSEInitializer.set(new SEInitializerGpg());
+#endif
+
+ if (mxSEInitializer.is())
+ mxSecurityContext = mxSEInitializer->createSecurityContext(OUString());
+
+#if HAVE_FEATURE_GPGME
+ if (mxGpgSEInitializer.is())
+ mxGpgSecurityContext = mxGpgSEInitializer->createSecurityContext(OUString());
+
+ return mxSecurityContext.is() || mxGpgSecurityContext.is();
+#else
+ return mxSecurityContext.is();
+#endif
+}
+
+PDFSignatureHelper& DocumentSignatureManager::getPDFSignatureHelper()
+{
+ bool bInit = true;
+ if (!mxSecurityContext.is())
+ bInit = init();
+
+ SAL_WARN_IF(!bInit, "xmlsecurity.comp", "Error initializing security context!");
+
+ if (!mpPDFSignatureHelper)
+ mpPDFSignatureHelper = std::make_unique<PDFSignatureHelper>();
+
+ return *mpPDFSignatureHelper;
+}
+
+#if 0 // For some reason does not work
+bool DocumentSignatureManager::IsXAdESRelevant()
+{
+ if (mxStore.is())
+ {
+ // ZIP-based: ODF or OOXML.
+ maSignatureHelper.StartMission();
+
+ SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(embed::ElementModes::READ, /*bUseTempStream=*/true);
+ if (aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML)
+ {
+ maSignatureHelper.EndMission();
+ return false;
+ }
+ // FIXME: How to figure out if it is ODF 1.2?
+ maSignatureHelper.EndMission();
+ return true;
+ }
+ return false;
+}
+#endif
+
+bool DocumentSignatureManager::readManifest()
+{
+ // Check if manifest was already read
+ if (m_manifest.hasElements())
+ return true;
+
+ if (!mxContext.is())
+ return false;
+
+ if (!mxStore.is())
+ return false;
+
+ uno::Reference<packages::manifest::XManifestReader> xReader
+ = packages::manifest::ManifestReader::create(mxContext);
+
+ if (mxStore->hasByName("META-INF"))
+ {
+ //Get the manifest.xml
+ uno::Reference<embed::XStorage> xSubStore(
+ mxStore->openStorageElement("META-INF", embed::ElementModes::READ), UNO_SET_THROW);
+
+ uno::Reference<io::XInputStream> xStream(
+ xSubStore->openStreamElement("manifest.xml", css::embed::ElementModes::READ),
+ UNO_QUERY_THROW);
+
+ m_manifest = xReader->readManifestSequence(xStream);
+ }
+ return true;
+}
+
+/* Using the zip storage, we cannot get the properties "MediaType" and "IsEncrypted"
+ We use the manifest to find out if a file is xml and if it is encrypted.
+ The parameter is an encoded uri. However, the manifest contains paths. Therefore
+ the path is encoded as uri, so they can be compared.
+*/
+bool DocumentSignatureManager::isXML(std::u16string_view rURI)
+{
+ SAL_WARN_IF(!mxStore.is(), "xmlsecurity.helper", "empty storage reference");
+
+ bool bIsXML = false;
+ bool bPropsAvailable = false;
+ static const OUStringLiteral sPropFullPath(u"FullPath");
+ static const OUStringLiteral sPropMediaType(u"MediaType");
+ static const OUStringLiteral sPropDigest(u"Digest");
+
+ if (readManifest())
+ {
+ for (const uno::Sequence<beans::PropertyValue>& entry : std::as_const(m_manifest))
+ {
+ OUString sPath;
+ OUString sMediaType;
+ bool bEncrypted = false;
+ for (const beans::PropertyValue& prop : entry)
+ {
+ if (prop.Name == sPropFullPath)
+ prop.Value >>= sPath;
+ else if (prop.Name == sPropMediaType)
+ prop.Value >>= sMediaType;
+ else if (prop.Name == sPropDigest)
+ bEncrypted = true;
+ }
+ if (DocumentSignatureHelper::equalsReferenceUriManifestPath(rURI, sPath))
+ {
+ bIsXML = sMediaType == "text/xml" && !bEncrypted;
+ bPropsAvailable = true;
+ break;
+ }
+ }
+ }
+ if (!bPropsAvailable)
+ {
+ //This would be the case for at least mimetype, META-INF/manifest.xml
+ //META-INF/macrosignatures.xml.
+ //Files can only be encrypted if they are in the manifest.xml.
+ //That is, the current file cannot be encrypted, otherwise bPropsAvailable
+ //would be true.
+ size_t nSep = rURI.rfind('.');
+ if (nSep != std::u16string_view::npos)
+ {
+ std::u16string_view aExt = rURI.substr(nSep + 1);
+ if (o3tl::equalsIgnoreAsciiCase(aExt, u"XML"))
+ bIsXML = true;
+ }
+ }
+ return bIsXML;
+}
+
+//If bTempStream is true, then a temporary stream is return. If it is false then, the actual
+//signature stream is used.
+//Every time the user presses Add a new temporary stream is created.
+//We keep the temporary stream as member because ImplGetSignatureInformations
+//will later access the stream to create DocumentSignatureInformation objects
+//which are stored in maCurrentSignatureInformations.
+SignatureStreamHelper DocumentSignatureManager::ImplOpenSignatureStream(sal_Int32 nStreamOpenMode,
+ bool bTempStream)
+{
+ SignatureStreamHelper aHelper;
+ if (mxStore.is() && mxStore->hasByName("[Content_Types].xml"))
+ aHelper.nStorageFormat = embed::StorageFormats::OFOPXML;
+
+ if (bTempStream)
+ {
+ if (nStreamOpenMode & embed::ElementModes::TRUNCATE)
+ {
+ //We write always into a new temporary stream.
+ mxTempSignatureStream.set(io::TempFile::create(mxContext), uno::UNO_QUERY_THROW);
+ if (aHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
+ aHelper.xSignatureStream = mxTempSignatureStream;
+ else
+ {
+ mxTempSignatureStorage = comphelper::OStorageHelper::GetStorageOfFormatFromStream(
+ ZIP_STORAGE_FORMAT_STRING, mxTempSignatureStream);
+ aHelper.xSignatureStorage = mxTempSignatureStorage;
+ }
+ }
+ else
+ {
+ //When we read from the temp stream, then we must have previously
+ //created one.
+ SAL_WARN_IF(!mxTempSignatureStream.is(), "xmlsecurity.helper",
+ "empty temp. signature stream reference");
+ }
+ aHelper.xSignatureStream = mxTempSignatureStream;
+ if (aHelper.nStorageFormat == embed::StorageFormats::OFOPXML)
+ aHelper.xSignatureStorage = mxTempSignatureStorage;
+ }
+ else
+ {
+ //No temporary stream
+ if (!mxSignatureStream.is())
+ {
+ //We may not have a dedicated stream for writing the signature
+ //So we take one directly from the storage
+ //Or DocumentDigitalSignatures::showDocumentContentSignatures was called,
+ //in which case Add/Remove is not allowed. This is done, for example, if the
+ //document is readonly
+ aHelper = DocumentSignatureHelper::OpenSignatureStream(mxStore, nStreamOpenMode,
+ meSignatureMode);
+ }
+ else
+ {
+ aHelper.xSignatureStream = mxSignatureStream;
+ }
+ }
+
+ if (nStreamOpenMode & embed::ElementModes::TRUNCATE)
+ {
+ if (aHelper.xSignatureStream.is()
+ && aHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
+ {
+ uno::Reference<io::XTruncate> xTruncate(aHelper.xSignatureStream, uno::UNO_QUERY_THROW);
+ xTruncate->truncate();
+ }
+ }
+ else if (bTempStream || mxSignatureStream.is())
+ {
+ //In case we read the signature stream from the storage directly,
+ //which is the case when DocumentDigitalSignatures::showDocumentContentSignatures
+ //then XSeakable is not supported
+ uno::Reference<io::XSeekable> xSeek(aHelper.xSignatureStream, uno::UNO_QUERY_THROW);
+ xSeek->seek(0);
+ }
+
+ return aHelper;
+}
+
+bool DocumentSignatureManager::add(
+ const uno::Reference<security::XCertificate>& xCert,
+ const uno::Reference<xml::crypto::XXMLSecurityContext>& xSecurityContext,
+ const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant,
+ const OUString& rSignatureLineId, const Reference<XGraphic>& xValidGraphic,
+ const Reference<XGraphic>& xInvalidGraphic)
+{
+ if (!xCert.is())
+ {
+ SAL_WARN("xmlsecurity.helper", "no certificate selected");
+ return false;
+ }
+
+ // GPG or X509 key?
+ uno::Reference<lang::XServiceInfo> xServiceInfo(xSecurityContext, uno::UNO_QUERY);
+ if (xServiceInfo->getImplementationName()
+ == "com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl")
+ {
+ // GPG keys only really have PGPKeyId and PGPKeyPacket
+ if (!mxStore.is())
+ {
+ SAL_WARN("xmlsecurity.helper", "cannot sign pdfs with GPG keys");
+ return false;
+ }
+
+ maSignatureHelper.StartMission(xSecurityContext);
+
+ nSecurityId = maSignatureHelper.GetNewSecurityId();
+
+ OUStringBuffer aStrBuffer;
+ comphelper::Base64::encode(aStrBuffer, xCert->getEncoded());
+
+ OUString aKeyId;
+ if (auto pCertificate = dynamic_cast<xmlsecurity::Certificate*>(xCert.get()))
+ {
+ OUStringBuffer aBuffer;
+ comphelper::Base64::encode(aBuffer, pCertificate->getSHA256Thumbprint());
+ aKeyId = aBuffer.makeStringAndClear();
+ }
+ else
+ SAL_WARN("xmlsecurity.helper",
+ "XCertificate implementation without an xmlsecurity::Certificate one");
+
+ maSignatureHelper.SetGpgCertificate(nSecurityId, aKeyId, aStrBuffer.makeStringAndClear(),
+ xCert->getIssuerName());
+ }
+ else
+ {
+ OUString aCertSerial = xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber());
+ if (aCertSerial.isEmpty())
+ {
+ SAL_WARN("xmlsecurity.helper", "Error in Certificate, problem with serial number!");
+ return false;
+ }
+
+ if (!mxStore.is())
+ {
+ // Something not ZIP based, try PDF.
+ nSecurityId = getPDFSignatureHelper().GetNewSecurityId();
+ getPDFSignatureHelper().SetX509Certificate(xCert);
+ getPDFSignatureHelper().SetDescription(rDescription);
+ uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY);
+ if (!getPDFSignatureHelper().Sign(mxModel, xInputStream, bAdESCompliant))
+ {
+ SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::Sign() failed");
+ return false;
+ }
+ return true;
+ }
+
+ maSignatureHelper.StartMission(xSecurityContext);
+
+ nSecurityId = maSignatureHelper.GetNewSecurityId();
+
+ OUStringBuffer aStrBuffer;
+ comphelper::Base64::encode(aStrBuffer, xCert->getEncoded());
+
+ OUString aCertDigest;
+ svl::crypto::SignatureMethodAlgorithm eAlgorithmID
+ = svl::crypto::SignatureMethodAlgorithm::RSA;
+ if (auto pCertificate = dynamic_cast<xmlsecurity::Certificate*>(xCert.get()))
+ {
+ OUStringBuffer aBuffer;
+ comphelper::Base64::encode(aBuffer, pCertificate->getSHA256Thumbprint());
+ aCertDigest = aBuffer.makeStringAndClear();
+
+ eAlgorithmID = pCertificate->getSignatureMethodAlgorithm();
+ }
+ else
+ SAL_WARN("xmlsecurity.helper",
+ "XCertificate implementation without an xmlsecurity::Certificate one");
+
+ maSignatureHelper.SetX509Certificate(nSecurityId, xCert->getIssuerName(), aCertSerial,
+ aStrBuffer.makeStringAndClear(), aCertDigest,
+ eAlgorithmID);
+ }
+
+ const uno::Sequence<uno::Reference<security::XCertificate>> aCertPath
+ = xSecurityContext->getSecurityEnvironment()->buildCertificatePath(xCert);
+
+ OUStringBuffer aStrBuffer;
+ for (uno::Reference<security::XCertificate> const& rxCertificate : aCertPath)
+ {
+ comphelper::Base64::encode(aStrBuffer, rxCertificate->getEncoded());
+ OUString aString = aStrBuffer.makeStringAndClear();
+ maSignatureHelper.AddEncapsulatedX509Certificate(aString);
+ }
+
+ std::vector<OUString> aElements = DocumentSignatureHelper::CreateElementList(
+ mxStore, meSignatureMode, DocumentSignatureAlgorithm::OOo3_2);
+ DocumentSignatureHelper::AppendContentTypes(mxStore, aElements);
+
+ for (OUString const& rUri : aElements)
+ {
+ bool bBinaryMode = !isXML(rUri);
+ maSignatureHelper.AddForSigning(nSecurityId, rUri, bBinaryMode, bAdESCompliant);
+ }
+
+ maSignatureHelper.SetDateTime(nSecurityId, DateTime(DateTime::SYSTEM));
+ maSignatureHelper.SetDescription(nSecurityId, rDescription);
+
+ if (!rSignatureLineId.isEmpty())
+ maSignatureHelper.SetSignatureLineId(nSecurityId, rSignatureLineId);
+
+ if (xValidGraphic.is())
+ maSignatureHelper.SetSignatureLineValidGraphic(nSecurityId, xValidGraphic);
+
+ if (xInvalidGraphic.is())
+ maSignatureHelper.SetSignatureLineInvalidGraphic(nSecurityId, xInvalidGraphic);
+
+ // We open a signature stream in which the existing and the new
+ //signature is written. ImplGetSignatureInformation (later in this function) will
+ //then read the stream and fill maCurrentSignatureInformations. The final signature
+ //is written when the user presses OK. Then only maCurrentSignatureInformation and
+ //a sax writer are used to write the information.
+ SignatureStreamHelper aStreamHelper
+ = ImplOpenSignatureStream(embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE, true);
+
+ if (aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
+ {
+ uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream,
+ uno::UNO_QUERY_THROW);
+ uno::Reference<xml::sax::XWriter> xSaxWriter
+ = maSignatureHelper.CreateDocumentHandlerWithHeader(xOutputStream);
+
+ // Export old signatures...
+ uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter,
+ uno::UNO_QUERY_THROW);
+ std::size_t nInfos = maCurrentSignatureInformations.size();
+ for (std::size_t n = 0; n < nInfos; n++)
+ XMLSignatureHelper::ExportSignature(xDocumentHandler, maCurrentSignatureInformations[n],
+ bAdESCompliant);
+
+ // Create a new one...
+ maSignatureHelper.CreateAndWriteSignature(xDocumentHandler, bAdESCompliant);
+
+ // That's it...
+ XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler);
+ }
+ else
+ {
+ // OOXML
+
+ // Handle relations.
+ maSignatureHelper.EnsureSignaturesRelation(mxStore, /*bAdd=*/true);
+ // Old signatures + the new one.
+ int nSignatureCount = maCurrentSignatureInformations.size() + 1;
+ maSignatureHelper.ExportSignatureRelations(aStreamHelper.xSignatureStorage,
+ nSignatureCount);
+
+ // Export old signatures.
+ for (std::size_t i = 0; i < maCurrentSignatureInformations.size(); ++i)
+ maSignatureHelper.ExportOOXMLSignature(mxStore, aStreamHelper.xSignatureStorage,
+ maCurrentSignatureInformations[i], i + 1);
+
+ // Create a new signature.
+ maSignatureHelper.CreateAndWriteOOXMLSignature(mxStore, aStreamHelper.xSignatureStorage,
+ nSignatureCount);
+
+ // Flush objects.
+ uno::Reference<embed::XTransactedObject> xTransact(aStreamHelper.xSignatureStorage,
+ uno::UNO_QUERY);
+ xTransact->commit();
+ uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream,
+ uno::UNO_QUERY);
+ xOutputStream->closeOutput();
+
+ uno::Reference<io::XTempFile> xTempFile(aStreamHelper.xSignatureStream, uno::UNO_QUERY);
+ SAL_INFO("xmlsecurity.helper",
+ "DocumentSignatureManager::add temporary storage at " << xTempFile->getUri());
+ }
+
+ maSignatureHelper.EndMission();
+ return true;
+}
+
+void DocumentSignatureManager::remove(sal_uInt16 nPosition)
+{
+ if (!mxStore.is())
+ {
+ // Something not ZIP based, try PDF.
+ uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY);
+ if (!PDFSignatureHelper::RemoveSignature(xInputStream, nPosition))
+ {
+ SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::RemoveSignature() failed");
+ return;
+ }
+
+ // Only erase when the removal was successful, it may fail for PDF.
+ // Also, erase the requested and all following signatures, as PDF signatures are always chained.
+ maCurrentSignatureInformations.erase(maCurrentSignatureInformations.begin() + nPosition,
+ maCurrentSignatureInformations.end());
+ return;
+ }
+
+ maCurrentSignatureInformations.erase(maCurrentSignatureInformations.begin() + nPosition);
+
+ // Export all other signatures...
+ SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
+ embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE, /*bTempStream=*/true);
+
+ if (aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
+ {
+ uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream,
+ uno::UNO_QUERY_THROW);
+ uno::Reference<xml::sax::XWriter> xSaxWriter
+ = maSignatureHelper.CreateDocumentHandlerWithHeader(xOutputStream);
+
+ uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter,
+ uno::UNO_QUERY_THROW);
+ std::size_t nInfos = maCurrentSignatureInformations.size();
+ for (std::size_t n = 0; n < nInfos; ++n)
+ XMLSignatureHelper::ExportSignature(xDocumentHandler, maCurrentSignatureInformations[n],
+ false /* ??? */);
+
+ XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler);
+ }
+ else
+ {
+ // OOXML
+
+ // Handle relations.
+ int nSignatureCount = maCurrentSignatureInformations.size();
+ maSignatureHelper.ExportSignatureRelations(aStreamHelper.xSignatureStorage,
+ nSignatureCount);
+
+ // Export old signatures.
+ for (std::size_t i = 0; i < maCurrentSignatureInformations.size(); ++i)
+ maSignatureHelper.ExportOOXMLSignature(mxStore, aStreamHelper.xSignatureStorage,
+ maCurrentSignatureInformations[i], i + 1);
+
+ // Flush objects.
+ uno::Reference<embed::XTransactedObject> xTransact(aStreamHelper.xSignatureStorage,
+ uno::UNO_QUERY);
+ xTransact->commit();
+ uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream,
+ uno::UNO_QUERY);
+ xOutputStream->closeOutput();
+
+ uno::Reference<io::XTempFile> xTempFile(aStreamHelper.xSignatureStream, uno::UNO_QUERY);
+ SAL_INFO("xmlsecurity.helper", "DocumentSignatureManager::remove: temporary storage is at "
+ << xTempFile->getUri());
+ }
+}
+
+void DocumentSignatureManager::read(bool bUseTempStream, bool bCacheLastSignature)
+{
+ maCurrentSignatureInformations.clear();
+
+ if (mxStore.is())
+ {
+ // ZIP-based: ODF or OOXML.
+ maSignatureHelper.StartMission(mxSecurityContext);
+
+ SignatureStreamHelper aStreamHelper
+ = ImplOpenSignatureStream(embed::ElementModes::READ, bUseTempStream);
+ if (aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML
+ && aStreamHelper.xSignatureStream.is())
+ {
+ uno::Reference<io::XInputStream> xInputStream(aStreamHelper.xSignatureStream,
+ uno::UNO_QUERY);
+ maSignatureHelper.ReadAndVerifySignature(xInputStream);
+ }
+ else if (aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML
+ && aStreamHelper.xSignatureStorage.is())
+ maSignatureHelper.ReadAndVerifySignatureStorage(aStreamHelper.xSignatureStorage,
+ bCacheLastSignature);
+ maSignatureHelper.EndMission();
+
+ // this parses the XML independently from ImplVerifySignatures() - check
+ // certificates here too ...
+ for (auto const& it : maSignatureHelper.GetSignatureInformations())
+ {
+ if (!it.X509Datas.empty())
+ {
+ uno::Reference<xml::crypto::XSecurityEnvironment> const xSecEnv(
+ getSecurityEnvironment());
+ getSignatureHelper().CheckAndUpdateSignatureInformation(xSecEnv, it);
+ }
+ }
+
+ maCurrentSignatureInformations = maSignatureHelper.GetSignatureInformations();
+ }
+ else
+ {
+ // Something not ZIP based, try PDF.
+ uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY);
+ if (getPDFSignatureHelper().ReadAndVerifySignature(xInputStream))
+ maCurrentSignatureInformations = getPDFSignatureHelper().GetSignatureInformations();
+ }
+}
+
+void DocumentSignatureManager::write(bool bXAdESCompliantIfODF)
+{
+ if (!mxStore.is())
+ {
+ // Something not ZIP based, assume PDF, which is written directly in add() already.
+ return;
+ }
+
+ // Export all other signatures...
+ SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(
+ embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE, false);
+
+ if (aStreamHelper.xSignatureStream.is()
+ && aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
+ {
+ // ODF
+ uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream,
+ uno::UNO_QUERY);
+ uno::Reference<xml::sax::XWriter> xSaxWriter
+ = maSignatureHelper.CreateDocumentHandlerWithHeader(xOutputStream);
+
+ uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter,
+ uno::UNO_QUERY_THROW);
+ std::size_t nInfos = maCurrentSignatureInformations.size();
+ for (std::size_t n = 0; n < nInfos; ++n)
+ XMLSignatureHelper::ExportSignature(xDocumentHandler, maCurrentSignatureInformations[n],
+ bXAdESCompliantIfODF);
+
+ XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler);
+ }
+ else if (aStreamHelper.xSignatureStorage.is()
+ && aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML)
+ {
+ // OOXML
+ std::size_t nSignatureCount = maCurrentSignatureInformations.size();
+ maSignatureHelper.ExportSignatureContentTypes(mxStore, nSignatureCount);
+ if (nSignatureCount > 0)
+ maSignatureHelper.ExportSignatureRelations(aStreamHelper.xSignatureStorage,
+ nSignatureCount);
+ else
+ {
+ // Removing all signatures: then need to remove the signature relation as well.
+ maSignatureHelper.EnsureSignaturesRelation(mxStore, /*bAdd=*/false);
+ // Also remove the whole signature sub-storage: release our read-write reference + remove the element.
+ aStreamHelper = SignatureStreamHelper();
+ mxStore->removeElement("_xmlsignatures");
+ }
+
+ for (std::size_t i = 0; i < nSignatureCount; ++i)
+ maSignatureHelper.ExportOOXMLSignature(mxStore, aStreamHelper.xSignatureStorage,
+ maCurrentSignatureInformations[i], i + 1);
+ }
+
+ // If stream was not provided, we are responsible for committing it...
+ if (!mxSignatureStream.is() && aStreamHelper.xSignatureStorage.is())
+ {
+ uno::Reference<embed::XTransactedObject> xTrans(aStreamHelper.xSignatureStorage,
+ uno::UNO_QUERY);
+ xTrans->commit();
+ }
+}
+
+uno::Reference<xml::crypto::XSecurityEnvironment> DocumentSignatureManager::getSecurityEnvironment()
+{
+ return mxSecurityContext.is() ? mxSecurityContext->getSecurityEnvironment()
+ : uno::Reference<xml::crypto::XSecurityEnvironment>();
+}
+
+uno::Reference<xml::crypto::XSecurityEnvironment>
+DocumentSignatureManager::getGpgSecurityEnvironment()
+{
+ return mxGpgSecurityContext.is() ? mxGpgSecurityContext->getSecurityEnvironment()
+ : uno::Reference<xml::crypto::XSecurityEnvironment>();
+}
+
+uno::Reference<xml::crypto::XXMLSecurityContext> const&
+DocumentSignatureManager::getSecurityContext() const
+{
+ return mxSecurityContext;
+}
+
+uno::Reference<xml::crypto::XXMLSecurityContext> const&
+DocumentSignatureManager::getGpgSecurityContext() const
+{
+ return mxGpgSecurityContext;
+}
+
+void DocumentSignatureManager::setModel(const uno::Reference<frame::XModel>& xModel)
+{
+ mxModel = xModel;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/helper/ooxmlsecexporter.cxx b/xmlsecurity/source/helper/ooxmlsecexporter.cxx
new file mode 100644
index 000000000..2294af680
--- /dev/null
+++ b/xmlsecurity/source/helper/ooxmlsecexporter.cxx
@@ -0,0 +1,558 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ooxmlsecexporter.hxx"
+
+#include <algorithm>
+#include <memory>
+#include <string_view>
+
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XHierarchicalStorageAccess.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/beans/StringPair.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+
+#include <comphelper/ofopxmlhelper.hxx>
+#include <o3tl/string_view.hxx>
+#include <rtl/ref.hxx>
+#include <sal/log.hxx>
+#include <svx/xoutbmp.hxx>
+#include <unotools/datetime.hxx>
+#include <vcl/salctype.hxx>
+#include <xmloff/attrlist.hxx>
+
+#include <documentsignaturehelper.hxx>
+#include <xsecctl.hxx>
+
+using namespace com::sun::star;
+using namespace css::xml::sax;
+
+struct OOXMLSecExporter::Impl
+{
+private:
+ const uno::Reference<uno::XComponentContext>& m_xComponentContext;
+ const uno::Reference<embed::XStorage>& m_xRootStorage;
+ const uno::Reference<xml::sax::XDocumentHandler>& m_xDocumentHandler;
+ const SignatureInformation& m_rInformation;
+ OUString m_aSignatureTimeValue;
+
+public:
+ Impl(const uno::Reference<uno::XComponentContext>& xComponentContext,
+ const uno::Reference<embed::XStorage>& xRootStorage,
+ const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler,
+ const SignatureInformation& rInformation)
+ : m_xComponentContext(xComponentContext)
+ , m_xRootStorage(xRootStorage)
+ , m_xDocumentHandler(xDocumentHandler)
+ , m_rInformation(rInformation)
+ {
+ }
+
+ /// Should we intentionally not sign this stream?
+ static bool isOOXMLDenylist(std::u16string_view rStreamName);
+ /// Should we intentionally not sign this relation type?
+ static bool isOOXMLRelationDenylist(const OUString& rRelationName);
+
+ const uno::Reference<xml::sax::XDocumentHandler>& getDocumentHandler() const
+ {
+ return m_xDocumentHandler;
+ }
+
+ void writeSignature();
+ void writeSignedInfo();
+ void writeCanonicalizationMethod();
+ void writeCanonicalizationTransform();
+ void writeSignatureMethod();
+ void writeSignedInfoReferences();
+ void writeSignatureValue();
+ void writeKeyInfo();
+ void writePackageObject();
+ void writeManifest();
+ void writeRelationshipTransform(const OUString& rURI);
+ /// Writes <SignatureProperties> inside idPackageObject.
+ void writePackageObjectSignatureProperties();
+ /// Writes a single <Reference> inside <Manifest>.
+ void writeManifestReference(const SignatureReferenceInformation& rReference);
+ void writeOfficeObject();
+ /// Writes <SignatureInfoV1>.
+ void writeSignatureInfo();
+ void writePackageSignature();
+ void writeSignatureLineImages();
+};
+
+bool OOXMLSecExporter::Impl::isOOXMLDenylist(std::u16string_view rStreamName)
+{
+ static const std::initializer_list<std::u16string_view> vDenylist
+ = { u"/%5BContent_Types%5D.xml", u"/docProps/app.xml", u"/docProps/core.xml",
+ // Don't attempt to sign other signatures for now.
+ u"/_xmlsignatures" };
+ // Just check the prefix, as we don't care about the content type part of the stream name.
+ return std::any_of(vDenylist.begin(), vDenylist.end(),
+ [&](const std::u16string_view& rLiteral) {
+ return o3tl::starts_with(rStreamName, rLiteral);
+ });
+}
+
+bool OOXMLSecExporter::Impl::isOOXMLRelationDenylist(const OUString& rRelationName)
+{
+ static const std::initializer_list<std::u16string_view> vDenylist = {
+ u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
+ u"http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
+ u"http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin"
+ };
+ return std::find(vDenylist.begin(), vDenylist.end(), rRelationName) != vDenylist.end();
+}
+
+void OOXMLSecExporter::Impl::writeSignedInfo()
+{
+ m_xDocumentHandler->startElement(
+ "SignedInfo", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+
+ writeCanonicalizationMethod();
+ writeSignatureMethod();
+ writeSignedInfoReferences();
+
+ m_xDocumentHandler->endElement("SignedInfo");
+}
+
+void OOXMLSecExporter::Impl::writeCanonicalizationMethod()
+{
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("Algorithm", ALGO_C14N);
+ m_xDocumentHandler->startElement("CanonicalizationMethod",
+ uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+ m_xDocumentHandler->endElement("CanonicalizationMethod");
+}
+
+void OOXMLSecExporter::Impl::writeCanonicalizationTransform()
+{
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("Algorithm", ALGO_C14N);
+ m_xDocumentHandler->startElement("Transform",
+ uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+ m_xDocumentHandler->endElement("Transform");
+}
+
+void OOXMLSecExporter::Impl::writeSignatureMethod()
+{
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+
+ if (m_rInformation.eAlgorithmID == svl::crypto::SignatureMethodAlgorithm::ECDSA)
+ pAttributeList->AddAttribute("Algorithm", ALGO_ECDSASHA256);
+ else
+ pAttributeList->AddAttribute("Algorithm", ALGO_RSASHA256);
+
+ m_xDocumentHandler->startElement("SignatureMethod",
+ uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+ m_xDocumentHandler->endElement("SignatureMethod");
+}
+
+void OOXMLSecExporter::Impl::writeSignedInfoReferences()
+{
+ const SignatureReferenceInformations& rReferences = m_rInformation.vSignatureReferenceInfors;
+ for (const SignatureReferenceInformation& rReference : rReferences)
+ {
+ if (rReference.nType == SignatureReferenceType::SAMEDOCUMENT)
+ {
+ {
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ if (!rReference.ouURI.startsWith("idSignedProperties"))
+ pAttributeList->AddAttribute("Type",
+ "http://www.w3.org/2000/09/xmldsig#Object");
+ else
+ pAttributeList->AddAttribute("Type",
+ "http://uri.etsi.org/01903#SignedProperties");
+ pAttributeList->AddAttribute("URI", "#" + rReference.ouURI);
+ m_xDocumentHandler->startElement(
+ "Reference", uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+ }
+ if (rReference.ouURI.startsWith("idSignedProperties"))
+ {
+ m_xDocumentHandler->startElement(
+ "Transforms",
+ uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ writeCanonicalizationTransform();
+ m_xDocumentHandler->endElement("Transforms");
+ }
+
+ DocumentSignatureHelper::writeDigestMethod(m_xDocumentHandler);
+ m_xDocumentHandler->startElement(
+ "DigestValue", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->characters(rReference.ouDigestValue);
+ m_xDocumentHandler->endElement("DigestValue");
+ m_xDocumentHandler->endElement("Reference");
+ }
+ }
+}
+
+void OOXMLSecExporter::Impl::writeSignatureValue()
+{
+ m_xDocumentHandler->startElement(
+ "SignatureValue", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->characters(m_rInformation.ouSignatureValue);
+ m_xDocumentHandler->endElement("SignatureValue");
+}
+
+void OOXMLSecExporter::Impl::writeKeyInfo()
+{
+ m_xDocumentHandler->startElement(
+ "KeyInfo", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ assert(m_rInformation.GetSigningCertificate());
+ for (auto const& rData : m_rInformation.X509Datas)
+ {
+ m_xDocumentHandler->startElement(
+ "X509Data", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ for (auto const& it : rData)
+ {
+ m_xDocumentHandler->startElement(
+ "X509Certificate",
+ uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->characters(it.X509Certificate);
+ m_xDocumentHandler->endElement("X509Certificate");
+ }
+ m_xDocumentHandler->endElement("X509Data");
+ }
+ m_xDocumentHandler->endElement("KeyInfo");
+}
+
+void OOXMLSecExporter::Impl::writePackageObject()
+{
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("Id", "idPackageObject_" + m_rInformation.ouSignatureId);
+ m_xDocumentHandler->startElement("Object",
+ uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+
+ writeManifest();
+ writePackageObjectSignatureProperties();
+
+ m_xDocumentHandler->endElement("Object");
+}
+
+void OOXMLSecExporter::Impl::writeManifest()
+{
+ m_xDocumentHandler->startElement(
+ "Manifest", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ const SignatureReferenceInformations& rReferences = m_rInformation.vSignatureReferenceInfors;
+ for (const SignatureReferenceInformation& rReference : rReferences)
+ {
+ if (rReference.nType != SignatureReferenceType::SAMEDOCUMENT)
+ {
+ if (OOXMLSecExporter::Impl::isOOXMLDenylist(rReference.ouURI))
+ continue;
+
+ writeManifestReference(rReference);
+ }
+ }
+ m_xDocumentHandler->endElement("Manifest");
+}
+
+void OOXMLSecExporter::Impl::writeRelationshipTransform(const OUString& rURI)
+{
+ uno::Reference<embed::XHierarchicalStorageAccess> xHierarchicalStorageAccess(m_xRootStorage,
+ uno::UNO_QUERY);
+ uno::Reference<io::XInputStream> xRelStream(
+ xHierarchicalStorageAccess->openStreamElementByHierarchicalName(rURI,
+ embed::ElementModes::READ),
+ uno::UNO_QUERY);
+ {
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("Algorithm", ALGO_RELATIONSHIP);
+ m_xDocumentHandler->startElement("Transform",
+ uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+ }
+
+ const uno::Sequence<uno::Sequence<beans::StringPair>> aRelationsInfo
+ = comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(xRelStream, rURI,
+ m_xComponentContext);
+ for (const uno::Sequence<beans::StringPair>& rPairs : aRelationsInfo)
+ {
+ OUString aId;
+ OUString aType;
+ for (const beans::StringPair& rPair : rPairs)
+ {
+ if (rPair.First == "Id")
+ aId = rPair.Second;
+ else if (rPair.First == "Type")
+ aType = rPair.Second;
+ }
+
+ if (OOXMLSecExporter::Impl::isOOXMLRelationDenylist(aType))
+ continue;
+
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("xmlns:mdssi", NS_MDSSI);
+ pAttributeList->AddAttribute("SourceId", aId);
+ m_xDocumentHandler->startElement("mdssi:RelationshipReference",
+ uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+ m_xDocumentHandler->endElement("mdssi:RelationshipReference");
+ }
+
+ m_xDocumentHandler->endElement("Transform");
+}
+
+void OOXMLSecExporter::Impl::writePackageObjectSignatureProperties()
+{
+ m_xDocumentHandler->startElement(
+ "SignatureProperties", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ {
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("Id", "idSignatureTime_" + m_rInformation.ouSignatureId);
+ pAttributeList->AddAttribute("Target", "#" + m_rInformation.ouSignatureId);
+ m_xDocumentHandler->startElement("SignatureProperty",
+ uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+ }
+ {
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("xmlns:mdssi", NS_MDSSI);
+ m_xDocumentHandler->startElement("mdssi:SignatureTime",
+ uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+ }
+ m_xDocumentHandler->startElement(
+ "mdssi:Format", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->characters("YYYY-MM-DDThh:mm:ssTZD");
+ m_xDocumentHandler->endElement("mdssi:Format");
+
+ m_xDocumentHandler->startElement(
+ "mdssi:Value", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ if (!m_rInformation.ouDateTime.isEmpty())
+ m_aSignatureTimeValue = m_rInformation.ouDateTime;
+ else
+ {
+ m_aSignatureTimeValue = utl::toISO8601(m_rInformation.stDateTime);
+ // Ignore sub-seconds.
+ sal_Int32 nCommaPos = m_aSignatureTimeValue.indexOf(',');
+ if (nCommaPos != -1)
+ {
+ m_aSignatureTimeValue
+ = OUString::Concat(m_aSignatureTimeValue.subView(0, nCommaPos)) + "Z";
+ }
+ }
+ m_xDocumentHandler->characters(m_aSignatureTimeValue);
+ m_xDocumentHandler->endElement("mdssi:Value");
+
+ m_xDocumentHandler->endElement("mdssi:SignatureTime");
+ m_xDocumentHandler->endElement("SignatureProperty");
+ m_xDocumentHandler->endElement("SignatureProperties");
+}
+
+void OOXMLSecExporter::Impl::writeManifestReference(const SignatureReferenceInformation& rReference)
+{
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("URI", rReference.ouURI);
+ m_xDocumentHandler->startElement("Reference",
+ uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+
+ // Transforms
+ if (rReference.ouURI.endsWith(
+ "?ContentType=application/vnd.openxmlformats-package.relationships+xml"))
+ {
+ OUString aURI = rReference.ouURI;
+ // Ignore leading slash.
+ if (aURI.startsWith("/"))
+ aURI = aURI.copy(1);
+ // Ignore query part of the URI.
+ sal_Int32 nQueryPos = aURI.indexOf('?');
+ if (nQueryPos != -1)
+ aURI = aURI.copy(0, nQueryPos);
+
+ m_xDocumentHandler->startElement(
+ "Transforms", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+
+ writeRelationshipTransform(aURI);
+ writeCanonicalizationTransform();
+
+ m_xDocumentHandler->endElement("Transforms");
+ }
+
+ DocumentSignatureHelper::writeDigestMethod(m_xDocumentHandler);
+ m_xDocumentHandler->startElement(
+ "DigestValue", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->characters(rReference.ouDigestValue);
+ m_xDocumentHandler->endElement("DigestValue");
+ m_xDocumentHandler->endElement("Reference");
+}
+
+void OOXMLSecExporter::Impl::writeOfficeObject()
+{
+ {
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("Id", "idOfficeObject_" + m_rInformation.ouSignatureId);
+ m_xDocumentHandler->startElement("Object",
+ uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+ }
+ m_xDocumentHandler->startElement(
+ "SignatureProperties", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ {
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("Id", "idOfficeV1Details_" + m_rInformation.ouSignatureId);
+ pAttributeList->AddAttribute("Target", "#" + m_rInformation.ouSignatureId);
+ m_xDocumentHandler->startElement("SignatureProperty",
+ uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+ }
+ writeSignatureInfo();
+ m_xDocumentHandler->endElement("SignatureProperty");
+ m_xDocumentHandler->endElement("SignatureProperties");
+ m_xDocumentHandler->endElement("Object");
+}
+
+void OOXMLSecExporter::Impl::writeSignatureInfo()
+{
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("xmlns", "http://schemas.microsoft.com/office/2006/digsig");
+ m_xDocumentHandler->startElement("SignatureInfoV1",
+ uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+
+ m_xDocumentHandler->startElement(
+ "SetupID", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->characters(m_rInformation.ouSignatureLineId);
+ m_xDocumentHandler->endElement("SetupID");
+ m_xDocumentHandler->startElement(
+ "SignatureText", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->endElement("SignatureText");
+ m_xDocumentHandler->startElement(
+ "SignatureImage", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->endElement("SignatureImage");
+ m_xDocumentHandler->startElement(
+ "SignatureComments", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->characters(m_rInformation.ouDescription);
+ m_xDocumentHandler->endElement("SignatureComments");
+ // Just hardcode something valid according to [MS-OFFCRYPTO].
+ m_xDocumentHandler->startElement(
+ "WindowsVersion", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->characters("6.1");
+ m_xDocumentHandler->endElement("WindowsVersion");
+ m_xDocumentHandler->startElement(
+ "OfficeVersion", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->characters("16.0");
+ m_xDocumentHandler->endElement("OfficeVersion");
+ m_xDocumentHandler->startElement(
+ "ApplicationVersion", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->characters("16.0");
+ m_xDocumentHandler->endElement("ApplicationVersion");
+ m_xDocumentHandler->startElement(
+ "Monitors", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->characters("1");
+ m_xDocumentHandler->endElement("Monitors");
+ m_xDocumentHandler->startElement(
+ "HorizontalResolution", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->characters("1280");
+ m_xDocumentHandler->endElement("HorizontalResolution");
+ m_xDocumentHandler->startElement(
+ "VerticalResolution", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->characters("800");
+ m_xDocumentHandler->endElement("VerticalResolution");
+ m_xDocumentHandler->startElement(
+ "ColorDepth", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->characters("32");
+ m_xDocumentHandler->endElement("ColorDepth");
+ m_xDocumentHandler->startElement(
+ "SignatureProviderId", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->characters("{00000000-0000-0000-0000-000000000000}");
+ m_xDocumentHandler->endElement("SignatureProviderId");
+ m_xDocumentHandler->startElement(
+ "SignatureProviderUrl", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->endElement("SignatureProviderUrl");
+ m_xDocumentHandler->startElement(
+ "SignatureProviderDetails",
+ uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->characters(
+ "9"); // This is what MSO 2016 writes, though [MS-OFFCRYPTO] doesn't document what the value means.
+ m_xDocumentHandler->endElement("SignatureProviderDetails");
+ m_xDocumentHandler->startElement(
+ "SignatureType", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ m_xDocumentHandler->characters("2");
+ m_xDocumentHandler->endElement("SignatureType");
+
+ m_xDocumentHandler->endElement("SignatureInfoV1");
+}
+
+void OOXMLSecExporter::Impl::writePackageSignature()
+{
+ m_xDocumentHandler->startElement(
+ "Object", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ {
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("xmlns:xd", NS_XD);
+ pAttributeList->AddAttribute("Target", "#" + m_rInformation.ouSignatureId);
+ m_xDocumentHandler->startElement("xd:QualifyingProperties",
+ uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+ }
+
+ DocumentSignatureHelper::writeSignedProperties(m_xDocumentHandler, m_rInformation,
+ m_aSignatureTimeValue, false);
+
+ m_xDocumentHandler->endElement("xd:QualifyingProperties");
+ m_xDocumentHandler->endElement("Object");
+}
+
+void OOXMLSecExporter::Impl::writeSignatureLineImages()
+{
+ if (m_rInformation.aValidSignatureImage.is())
+ {
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("Id", "idValidSigLnImg");
+ m_xDocumentHandler->startElement("Object",
+ uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+ OUString aGraphicInBase64;
+ Graphic aGraphic(m_rInformation.aValidSignatureImage);
+ if (!XOutBitmap::GraphicToBase64(aGraphic, aGraphicInBase64, false, ConvertDataFormat::EMF))
+ SAL_WARN("xmlsecurity.helper", "could not convert graphic to base64");
+ m_xDocumentHandler->characters(aGraphicInBase64);
+ m_xDocumentHandler->endElement("Object");
+ }
+ if (!m_rInformation.aInvalidSignatureImage.is())
+ return;
+
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("Id", "idInvalidSigLnImg");
+ m_xDocumentHandler->startElement("Object",
+ uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+ OUString aGraphicInBase64;
+ Graphic aGraphic(m_rInformation.aInvalidSignatureImage);
+ if (!XOutBitmap::GraphicToBase64(aGraphic, aGraphicInBase64, false, ConvertDataFormat::EMF))
+ SAL_WARN("xmlsecurity.helper", "could not convert graphic to base64");
+ m_xDocumentHandler->characters(aGraphicInBase64);
+ m_xDocumentHandler->endElement("Object");
+}
+
+void OOXMLSecExporter::Impl::writeSignature()
+{
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("xmlns", NS_XMLDSIG);
+ pAttributeList->AddAttribute("Id", m_rInformation.ouSignatureId);
+ getDocumentHandler()->startElement("Signature",
+ uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+
+ writeSignedInfo();
+ writeSignatureValue();
+ writeKeyInfo();
+ writePackageObject();
+ writeOfficeObject();
+ writePackageSignature();
+ writeSignatureLineImages();
+
+ getDocumentHandler()->endElement("Signature");
+}
+
+OOXMLSecExporter::OOXMLSecExporter(
+ const uno::Reference<uno::XComponentContext>& xComponentContext,
+ const uno::Reference<embed::XStorage>& xRootStorage,
+ const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler,
+ const SignatureInformation& rInformation)
+ : m_pImpl(
+ std::make_unique<Impl>(xComponentContext, xRootStorage, xDocumentHandler, rInformation))
+{
+}
+
+OOXMLSecExporter::~OOXMLSecExporter() = default;
+
+void OOXMLSecExporter::writeSignature() { m_pImpl->writeSignature(); }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/helper/ooxmlsecexporter.hxx b/xmlsecurity/source/helper/ooxmlsecexporter.hxx
new file mode 100644
index 000000000..77ea7c484
--- /dev/null
+++ b/xmlsecurity/source/helper/ooxmlsecexporter.hxx
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <svl/sigstruct.hxx>
+
+namespace com::sun::star
+{
+namespace embed
+{
+class XStorage;
+}
+namespace uno
+{
+class XComponentContext;
+}
+namespace xml::sax
+{
+class XDocumentHandler;
+}
+}
+
+/// Writes a single OOXML digital signature.
+class OOXMLSecExporter
+{
+ struct Impl;
+ std::unique_ptr<Impl> m_pImpl;
+
+public:
+ OOXMLSecExporter(const css::uno::Reference<css::uno::XComponentContext>& xComponentContext,
+ const css::uno::Reference<css::embed::XStorage>& xRootStorage,
+ const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler,
+ const SignatureInformation& rInformation);
+ ~OOXMLSecExporter();
+ void writeSignature();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/helper/ooxmlsecparser.cxx b/xmlsecurity/source/helper/ooxmlsecparser.cxx
new file mode 100644
index 000000000..2692190cc
--- /dev/null
+++ b/xmlsecurity/source/helper/ooxmlsecparser.cxx
@@ -0,0 +1,1352 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+
+#include "ooxmlsecparser.hxx"
+#include <xmlsignaturehelper.hxx>
+#include <xsecctl.hxx>
+
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltkmap.hxx>
+#include <xmloff/xmlimp.hxx>
+
+#include <com/sun/star/xml/sax/SAXException.hpp>
+
+#include <sal/log.hxx>
+
+using namespace com::sun::star;
+
+class OOXMLSecParser::Context
+{
+ protected:
+ friend class OOXMLSecParser;
+ OOXMLSecParser & m_rParser;
+ private:
+ std::optional<SvXMLNamespaceMap> m_pOldNamespaceMap;
+
+ public:
+ Context(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : m_rParser(rParser)
+ , m_pOldNamespaceMap(std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual ~Context() = default;
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/)
+ {
+ }
+
+ virtual void EndElement()
+ {
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/);
+
+ virtual void Characters(OUString const& /*rChars*/)
+ {
+ }
+};
+
+// it's possible that an unsupported element has an Id attribute and a
+// ds:Reference digesting it - probably this means XSecController needs to know
+// about it. (For known elements, the Id attribute is only processed according
+// to the schema.)
+class OOXMLSecParser::UnknownContext
+ : public OOXMLSecParser::Context
+{
+ public:
+ UnknownContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ m_rParser.HandleIdAttr(xAttrs);
+ }
+};
+
+auto OOXMLSecParser::Context::CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/)
+-> std::unique_ptr<Context>
+{
+ // default: create new base context
+ return std::make_unique<UnknownContext>(m_rParser, std::move(pOldNamespaceMap));
+}
+
+/**
+note: anything in ds:Object should be trusted *only* if there is a ds:Reference
+ to it so it is signed (exception: the xades:EncapsulatedX509Certificate).
+ ds:SignedInfo precedes all ds:Object.
+
+ There may be multiple ds:Signature for purpose of counter-signatures
+ but the way XAdES describes these, only the ds:SignatureValue element
+ would be referenced, so requiring a ds:Reference for anything in
+ ds:Object shouldn't cause issues.
+ */
+class OOXMLSecParser::ReferencedContextImpl
+ : public OOXMLSecParser::Context
+{
+ protected:
+ bool m_isReferenced;
+
+ public:
+ ReferencedContextImpl(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_isReferenced(isReferenced)
+ {
+ }
+
+ OUString CheckIdAttrReferenced(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs)
+ {
+ OUString const id(m_rParser.HandleIdAttr(xAttrs));
+ if (!id.isEmpty() && m_rParser.m_pXSecController->haveReferenceForId(id))
+ {
+ m_isReferenced = true;
+ }
+ return id;
+ }
+};
+
+class OOXMLSecParser::DsX509CertificateContext
+ : public OOXMLSecParser::Context
+{
+ private:
+ OUString & m_rValue;
+
+ public:
+ DsX509CertificateContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString& rValue)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rValue(rValue)
+ {
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_rValue += rChars;
+ }
+};
+
+class OOXMLSecParser::DsX509SerialNumberContext
+ : public OOXMLSecParser::Context
+{
+ private:
+ OUString & m_rValue;
+
+ public:
+ DsX509SerialNumberContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString& rValue)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rValue(rValue)
+ {
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_rValue += rChars;
+ }
+};
+
+class OOXMLSecParser::DsX509IssuerNameContext
+ : public OOXMLSecParser::Context
+{
+ private:
+ OUString & m_rValue;
+
+ public:
+ DsX509IssuerNameContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString& rValue)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rValue(rValue)
+ {
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_rValue += rChars;
+ }
+};
+
+class OOXMLSecParser::DsX509IssuerSerialContext
+ : public OOXMLSecParser::Context
+{
+ private:
+ OUString & m_rX509IssuerName;
+ OUString & m_rX509SerialNumber;
+
+ public:
+ DsX509IssuerSerialContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString& rIssuerName, OUString& rSerialNumber)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rX509IssuerName(rIssuerName)
+ , m_rX509SerialNumber(rSerialNumber)
+ {
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerName")
+ {
+ return std::make_unique<DsX509IssuerNameContext>(m_rParser, std::move(pOldNamespaceMap), m_rX509IssuerName);
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "X509SerialNumber")
+ {
+ return std::make_unique<DsX509SerialNumberContext>(m_rParser, std::move(pOldNamespaceMap), m_rX509SerialNumber);
+ }
+ // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+/// can't be sure what is supposed to happen here because the spec is clear as mud
+class OOXMLSecParser::DsX509DataContext
+ : public OOXMLSecParser::Context
+{
+ private:
+ // sigh... "No ordering is implied by the above constraints."
+ // so store the ball of mud in vectors and try to figure it out later.
+ std::vector<std::pair<OUString, OUString>> m_X509IssuerSerials;
+ std::vector<OUString> m_X509Certificates;
+
+ public:
+ DsX509DataContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void EndElement() override
+ {
+ m_rParser.m_pXSecController->setX509Data(m_X509IssuerSerials, m_X509Certificates);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerSerial")
+ {
+ m_X509IssuerSerials.emplace_back();
+ return std::make_unique<DsX509IssuerSerialContext>(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerSerials.back().first, m_X509IssuerSerials.back().second);
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "X509Certificate")
+ {
+ m_X509Certificates.emplace_back();
+ return std::make_unique<DsX509CertificateContext>(m_rParser, std::move(pOldNamespaceMap), m_X509Certificates.back());
+ }
+ // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class OOXMLSecParser::DsKeyInfoContext
+ : public OOXMLSecParser::Context
+{
+ public:
+ DsKeyInfoContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ m_rParser.HandleIdAttr(xAttrs);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "X509Data")
+ {
+ return std::make_unique<DsX509DataContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ // missing: ds:PGPData
+ // missing: ds:KeyName, ds:KeyValue, ds:RetrievalMethod, ds:SPKIData, ds:MgmtData
+ // (old code would read ds:Transform inside ds:RetrievalMethod but
+ // presumably that was a bug)
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+
+};
+
+class OOXMLSecParser::DsSignatureValueContext
+ : public OOXMLSecParser::Context
+{
+ private:
+ OUString m_Value;
+
+ public:
+ DsSignatureValueContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ m_rParser.HandleIdAttr(xAttrs);
+ }
+
+ virtual void EndElement() override
+ {
+ m_rParser.m_pXSecController->setSignatureValue(m_Value);
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_Value += rChars;
+ }
+};
+
+class OOXMLSecParser::DsDigestValueContext
+ : public OOXMLSecParser::Context
+{
+ private:
+ OUString & m_rValue;
+
+ public:
+ DsDigestValueContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString & rValue)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rValue(rValue)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/) override
+ {
+ m_rValue.clear();
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_rValue += rChars;
+ }
+};
+
+class OOXMLSecParser::DsDigestMethodContext
+ : public OOXMLSecParser::Context
+{
+ private:
+ sal_Int32 & m_rReferenceDigestID;
+
+ public:
+ DsDigestMethodContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_Int32& rReferenceDigestID)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rReferenceDigestID(rReferenceDigestID)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ OUString ouAlgorithm = xAttrs->getValueByName("Algorithm");
+
+ SAL_WARN_IF( ouAlgorithm.isEmpty(), "xmlsecurity.helper", "no Algorithm in Reference" );
+ if (ouAlgorithm.isEmpty())
+ return;
+
+ SAL_WARN_IF( ouAlgorithm != ALGO_XMLDSIGSHA1
+ && ouAlgorithm != ALGO_XMLDSIGSHA256
+ && ouAlgorithm != ALGO_XMLDSIGSHA512,
+ "xmlsecurity.helper", "Algorithm neither SHA1, SHA256 nor SHA512");
+ if (ouAlgorithm == ALGO_XMLDSIGSHA1)
+ m_rReferenceDigestID = css::xml::crypto::DigestID::SHA1;
+ else if (ouAlgorithm == ALGO_XMLDSIGSHA256)
+ m_rReferenceDigestID = css::xml::crypto::DigestID::SHA256;
+ else if (ouAlgorithm == ALGO_XMLDSIGSHA512)
+ m_rReferenceDigestID = css::xml::crypto::DigestID::SHA512;
+ else
+ m_rReferenceDigestID = 0;
+ }
+};
+
+class OOXMLSecParser::DsTransformContext
+ : public OOXMLSecParser::Context
+{
+ private:
+ bool & m_rIsC14N;
+
+ public:
+ DsTransformContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool& rIsC14N)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rIsC14N(rIsC14N)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ OUString aAlgorithm = xAttrs->getValueByName("Algorithm");
+
+ if (aAlgorithm == ALGO_RELATIONSHIP)
+ {
+ m_rIsC14N = true;
+ }
+ }
+};
+
+class OOXMLSecParser::DsTransformsContext
+ : public OOXMLSecParser::Context
+{
+ private:
+ bool & m_rIsC14N;
+
+ public:
+ DsTransformsContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool& rIsC14N)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rIsC14N(rIsC14N)
+ {
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "Transform")
+ {
+ return std::make_unique<DsTransformContext>(m_rParser, std::move(pOldNamespaceMap), m_rIsC14N);
+ }
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class OOXMLSecParser::DsReferenceContext
+ : public OOXMLSecParser::Context
+{
+ private:
+ OUString m_URI;
+ OUString m_Type;
+ OUString m_DigestValue;
+ bool m_IsC14N = false;
+ // Relevant for ODF. The digest algorithm selected by the DigestMethod
+ // element's Algorithm attribute. @see css::xml::crypto::DigestID.
+ sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA256;
+
+ public:
+ DsReferenceContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ m_rParser.HandleIdAttr(xAttrs);
+
+ m_URI = xAttrs->getValueByName("URI");
+ SAL_WARN_IF(m_URI.isEmpty(), "xmlsecurity.helper", "URI is empty");
+ // Remember the type of this reference.
+ m_Type = xAttrs->getValueByName("Type");
+ }
+
+ virtual void EndElement() override
+ {
+ if (m_URI.startsWith("#"))
+ {
+ /*
+ * remove the first character '#' from the attribute value
+ */
+ m_rParser.m_pXSecController->addReference(m_URI.copy(1), m_nReferenceDigestID, m_Type);
+ }
+ else
+ {
+ if (m_IsC14N) // this is determined by nested ds:Transform
+ {
+ m_rParser.m_pXSecController->addStreamReference(m_URI, false, m_nReferenceDigestID);
+ }
+ else
+ /*
+ * it must be an octet stream
+ */
+ {
+ m_rParser.m_pXSecController->addStreamReference(m_URI, true, m_nReferenceDigestID);
+ }
+ }
+
+ m_rParser.m_pXSecController->setDigestValue(m_nReferenceDigestID, m_DigestValue);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "Transforms")
+ {
+ return std::make_unique<DsTransformsContext>(m_rParser, std::move(pOldNamespaceMap), m_IsC14N);
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod")
+ {
+ return std::make_unique<DsDigestMethodContext>(m_rParser, std::move(pOldNamespaceMap), m_nReferenceDigestID);
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue")
+ {
+ return std::make_unique<DsDigestValueContext>(m_rParser, std::move(pOldNamespaceMap), m_DigestValue);
+ }
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class OOXMLSecParser::DsSignatureMethodContext
+ : public OOXMLSecParser::Context
+{
+ public:
+ DsSignatureMethodContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ OUString ouAlgorithm = xAttrs->getValueByName("Algorithm");
+ if (ouAlgorithm == ALGO_ECDSASHA1 || ouAlgorithm == ALGO_ECDSASHA256
+ || ouAlgorithm == ALGO_ECDSASHA512)
+ {
+ m_rParser.m_pXSecController->setSignatureMethod(svl::crypto::SignatureMethodAlgorithm::ECDSA);
+ }
+ }
+};
+
+class OOXMLSecParser::DsSignedInfoContext
+ : public OOXMLSecParser::Context
+{
+ public:
+ DsSignedInfoContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ m_rParser.HandleIdAttr(xAttrs);
+ }
+
+ virtual void EndElement() override
+ {
+ m_rParser.m_pXSecController->setReferenceCount();
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureMethod")
+ {
+ return std::make_unique<DsSignatureMethodContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "Reference")
+ {
+ return std::make_unique<DsReferenceContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ // missing: ds:CanonicalizationMethod
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class OOXMLSecParser::XadesCertDigestContext
+ : public OOXMLSecParser::Context
+{
+ private:
+ OUString & m_rDigestValue;
+ sal_Int32 & m_rReferenceDigestID;
+
+ public:
+ XadesCertDigestContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString& rDigestValue, sal_Int32& rReferenceDigestID)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rDigestValue(rDigestValue)
+ , m_rReferenceDigestID(rReferenceDigestID)
+ {
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod")
+ {
+ return std::make_unique<DsDigestMethodContext>(m_rParser, std::move(pOldNamespaceMap), m_rReferenceDigestID);
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue")
+ {
+ return std::make_unique<DsDigestValueContext>(m_rParser, std::move(pOldNamespaceMap), m_rDigestValue);
+ }
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class OOXMLSecParser::XadesCertContext
+ : public OOXMLSecParser::ReferencedContextImpl
+{
+ private:
+ sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA1;
+ OUString m_CertDigest;
+ OUString m_X509IssuerName;
+ OUString m_X509SerialNumber;
+
+ public:
+ XadesCertContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void EndElement() override
+ {
+ if (m_isReferenced)
+ {
+ m_rParser.m_pXSecController->setX509CertDigest(m_CertDigest, m_nReferenceDigestID, m_X509IssuerName, m_X509SerialNumber);
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.helper", "ignoring unsigned xades:Cert");
+ }
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertDigest")
+ {
+ return std::make_unique<XadesCertDigestContext>(m_rParser, std::move(pOldNamespaceMap), m_CertDigest, m_nReferenceDigestID);
+ }
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "IssuerSerial")
+ {
+ return std::make_unique<DsX509IssuerSerialContext>(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerName, m_X509SerialNumber);
+ }
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class OOXMLSecParser::XadesSigningCertificateContext
+ : public OOXMLSecParser::ReferencedContextImpl
+{
+ public:
+ XadesSigningCertificateContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "Cert")
+ {
+ return std::make_unique<XadesCertContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class OOXMLSecParser::XadesSigningTimeContext
+ : public OOXMLSecParser::ReferencedContextImpl
+{
+ private:
+ OUString m_Value;
+
+ public:
+ XadesSigningTimeContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void EndElement() override
+ {
+ if (m_isReferenced)
+ {
+ m_rParser.m_pXSecController->setDate("", m_Value);
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.helper", "ignoring unsigned SigningTime");
+ }
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_Value += rChars;
+ }
+};
+
+class OOXMLSecParser::XadesSignedSignaturePropertiesContext
+ : public OOXMLSecParser::ReferencedContextImpl
+{
+ public:
+ XadesSignedSignaturePropertiesContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ CheckIdAttrReferenced(xAttrs);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningTime")
+ {
+ return std::make_unique<XadesSigningTimeContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningCertificate")
+ {
+ return std::make_unique<XadesSigningCertificateContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ // missing: xades:SignaturePolicyIdentifier, xades:SignatureProductionPlace, xades:SignerRole
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class OOXMLSecParser::XadesSignedPropertiesContext
+ : public OOXMLSecParser::ReferencedContextImpl
+{
+ public:
+ XadesSignedPropertiesContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ CheckIdAttrReferenced(xAttrs);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedSignatureProperties")
+ {
+ return std::make_unique<XadesSignedSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ // missing: xades:SignedDataObjectProperties
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class OOXMLSecParser::XadesQualifyingPropertiesContext
+ : public OOXMLSecParser::ReferencedContextImpl
+{
+ public:
+ XadesQualifyingPropertiesContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ CheckIdAttrReferenced(xAttrs);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedProperties")
+ {
+ return std::make_unique<XadesSignedPropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ // missing: xades:UnsignedSignatureProperties
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class OOXMLSecParser::MsodigsigSetupIDContext
+ : public OOXMLSecParser::Context
+{
+ private:
+ OUString & m_rValue;
+
+ public:
+ MsodigsigSetupIDContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString& rValue)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rValue(rValue)
+ {
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_rValue += rChars;
+ }
+};
+
+class OOXMLSecParser::MsodigsigSignatureCommentsContext
+ : public OOXMLSecParser::Context
+{
+ private:
+ OUString & m_rValue;
+
+ public:
+ MsodigsigSignatureCommentsContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString& rValue)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rValue(rValue)
+ {
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_rValue += rChars;
+ }
+};
+
+class OOXMLSecParser::MsodigsigSignatureInfoV1Context
+ : public OOXMLSecParser::ReferencedContextImpl
+{
+ private:
+ OUString m_SetupID;
+ OUString m_SignatureComments;
+
+ public:
+ MsodigsigSignatureInfoV1Context(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ CheckIdAttrReferenced(xAttrs);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SetupID")
+ {
+ return std::make_unique<MsodigsigSetupIDContext>(m_rParser, std::move(pOldNamespaceMap), m_SetupID);
+ }
+ if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SignatureComments")
+ {
+ return std::make_unique<MsodigsigSignatureCommentsContext>(m_rParser, std::move(pOldNamespaceMap), m_SignatureComments);
+ }
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+
+ virtual void EndElement() override
+ {
+ if (m_isReferenced)
+ {
+ if (!m_SetupID.isEmpty())
+ {
+ m_rParser.m_pXSecController->setSignatureLineId(m_SetupID);
+ }
+ if (!m_SignatureComments.isEmpty())
+ {
+ m_rParser.m_pXSecController->setDescription("", m_SignatureComments);
+
+ }
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureInfoV1");
+ }
+ }
+};
+
+class OOXMLSecParser::MdssiValueContext
+ : public OOXMLSecParser::Context
+{
+ private:
+ OUString & m_rValue;
+
+ public:
+ MdssiValueContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString& rValue)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rValue(rValue)
+ {
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_rValue += rChars;
+ }
+};
+
+class OOXMLSecParser::MdssiSignatureTimeContext
+ : public OOXMLSecParser::Context
+{
+ private:
+ OUString & m_rValue;
+
+ public:
+ MdssiSignatureTimeContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString& rValue)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rValue(rValue)
+ {
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_MDSSI && rName == "Value")
+ {
+ return std::make_unique<MdssiValueContext>(m_rParser, std::move(pOldNamespaceMap), m_rValue);
+ }
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+
+class OOXMLSecParser::DsSignaturePropertyContext
+ : public OOXMLSecParser::ReferencedContextImpl
+{
+ private:
+ enum class SignatureProperty { Unknown, Date, Info };
+ SignatureProperty m_Property = SignatureProperty::Unknown;
+ OUString m_Id;
+ OUString m_Value;
+
+ public:
+ DsSignaturePropertyContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ m_Id = CheckIdAttrReferenced(xAttrs);
+ }
+
+ virtual void EndElement() override
+ {
+ if (m_isReferenced)
+ {
+ switch (m_Property)
+ {
+ case SignatureProperty::Unknown:
+ SAL_INFO("xmlsecurity.helper", "Unknown property in ds:Object ignored");
+ break;
+ case SignatureProperty::Info:
+ break; // handled by child context
+ case SignatureProperty::Date:
+ m_rParser.m_pXSecController->setDate(m_Id, m_Value);
+ break;
+ }
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureProperty");
+ }
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_MDSSI && rName == "SignatureTime")
+ {
+ m_Property = SignatureProperty::Date;
+ return std::make_unique<MdssiSignatureTimeContext>(m_rParser, std::move(pOldNamespaceMap), m_Value);
+ }
+ if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SignatureInfoV1")
+ {
+ return std::make_unique<MsodigsigSignatureInfoV1Context>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class OOXMLSecParser::DsSignaturePropertiesContext
+ : public OOXMLSecParser::ReferencedContextImpl
+{
+ public:
+ DsSignaturePropertiesContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ CheckIdAttrReferenced(xAttrs);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperty")
+ {
+ return std::make_unique<DsSignaturePropertyContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class OOXMLSecParser::DsManifestContext
+ : public OOXMLSecParser::ReferencedContextImpl
+{
+ public:
+ DsManifestContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ CheckIdAttrReferenced(xAttrs);
+ }
+
+#if 0
+ ???
+ virtual void EndElement() override
+ {
+ m_rParser.m_pXSecController->setReferenceCount();
+ }
+#endif
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "Reference")
+ {
+ return std::make_unique<DsReferenceContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ // missing: ds:CanonicalizationMethod
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class OOXMLSecParser::DsObjectContext
+ : public OOXMLSecParser::ReferencedContextImpl
+{
+ enum class Mode { Default, ValidSignatureLineImage, InvalidSignatureLineImage };
+ Mode m_Mode = Mode::Default;
+ OUString m_Value;
+
+ public:
+ DsObjectContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ // init with "false" here - the Signature element can't be referenced by its child
+ : OOXMLSecParser::ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), false)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ OUString const id(CheckIdAttrReferenced(xAttrs));
+ if (id == "idValidSigLnImg")
+ {
+ m_Mode = Mode::ValidSignatureLineImage;
+ }
+ else if (id == "idInvalidSigLnImg")
+ {
+ m_Mode = Mode::InvalidSignatureLineImage;
+ }
+ }
+
+ virtual void EndElement() override
+ {
+ switch (m_Mode)
+ {
+ case Mode::ValidSignatureLineImage:
+ if (m_isReferenced)
+ {
+ m_rParser.m_pXSecController->setValidSignatureImage(m_Value);
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineValidImage");
+ }
+ break;
+ case Mode::InvalidSignatureLineImage:
+ if (m_isReferenced)
+ {
+ m_rParser.m_pXSecController->setInvalidSignatureImage(m_Value);
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineInvalidImage");
+ }
+ break;
+ case Mode::Default:
+ break;
+ }
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_Value += rChars;
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperties")
+ {
+ return std::make_unique<DsSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "QualifyingProperties")
+ {
+ return std::make_unique<XadesQualifyingPropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "Manifest")
+ {
+ return std::make_unique<DsManifestContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class OOXMLSecParser::DsSignatureContext
+ : public OOXMLSecParser::Context
+{
+ public:
+ DsSignatureContext(OOXMLSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ OUString const ouIdAttr(m_rParser.HandleIdAttr(xAttrs));
+ m_rParser.m_rXMLSignatureHelper.StartVerifySignatureElement();
+ m_rParser.m_pXSecController->addSignature();
+ if (!ouIdAttr.isEmpty())
+ {
+ m_rParser.m_pXSecController->setId( ouIdAttr );
+ }
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "SignedInfo")
+ {
+ return std::make_unique<DsSignedInfoContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureValue")
+ {
+ return std::make_unique<DsSignatureValueContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "KeyInfo")
+ {
+ return std::make_unique<DsKeyInfoContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "Object")
+ {
+ return std::make_unique<DsObjectContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+
+OOXMLSecParser::OOXMLSecParser(XMLSignatureHelper& rXMLSignatureHelper, XSecController* pXSecController)
+ : m_pNamespaceMap(SvXMLNamespaceMap())
+ , m_pXSecController(pXSecController)
+ ,m_rXMLSignatureHelper(rXMLSignatureHelper)
+{
+ using namespace xmloff::token;
+ m_pNamespaceMap->Add( GetXMLToken(XML_XML), GetXMLToken(XML_N_XML), XML_NAMESPACE_XML );
+ m_pNamespaceMap->Add( "_ds", GetXMLToken(XML_N_DS), XML_NAMESPACE_DS );
+ m_pNamespaceMap->Add( "_xades132", GetXMLToken(XML_N_XADES132), XML_NAMESPACE_XADES132);
+ m_pNamespaceMap->Add( "_xades141", GetXMLToken(XML_N_XADES141), XML_NAMESPACE_XADES141);
+ m_pNamespaceMap->Add( "_dc", GetXMLToken(XML_N_DC), XML_NAMESPACE_DC );
+ m_pNamespaceMap->Add( "_mdssi", NS_MDSSI, XML_NAMESPACE_MDSSI );
+ m_pNamespaceMap->Add( "_msodigsig", "http://schemas.microsoft.com/office/2006/digsig", XML_NAMESPACE_MSODIGSIG );
+ m_pNamespaceMap->Add( "_office_libo",
+ GetXMLToken(XML_N_LO_EXT), XML_NAMESPACE_LO_EXT);
+}
+
+OOXMLSecParser::~OOXMLSecParser()
+{
+}
+
+OUString OOXMLSecParser::HandleIdAttr(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs)
+{
+ OUString const aId = xAttrs->getValueByName("Id");
+ if (!aId.isEmpty())
+ {
+ m_pXSecController->collectToVerify(aId);
+ }
+ return aId;
+}
+
+void SAL_CALL OOXMLSecParser::startDocument()
+{
+ if (m_xNextHandler.is())
+ m_xNextHandler->startDocument();
+}
+
+void SAL_CALL OOXMLSecParser::endDocument()
+{
+ if (m_xNextHandler.is())
+ m_xNextHandler->endDocument();
+}
+
+void SAL_CALL OOXMLSecParser::startElement(const OUString& rName, const uno::Reference<xml::sax::XAttributeList>& xAttribs)
+{
+ assert(m_pNamespaceMap);
+ std::optional<SvXMLNamespaceMap> pRewindMap(
+ SvXMLImport::processNSAttributes(m_pNamespaceMap, nullptr, xAttribs));
+
+ OUString localName;
+ sal_uInt16 const nPrefix(m_pNamespaceMap->GetKeyByAttrName(rName, &localName));
+
+ std::unique_ptr<Context> pContext;
+
+ if (m_ContextStack.empty())
+ {
+ if (nPrefix != XML_NAMESPACE_DS || localName != "Signature")
+ {
+ throw css::xml::sax::SAXException(
+ "xmlsecurity: unexpected root element", nullptr,
+ css::uno::Any());
+ }
+
+ pContext.reset(new DsSignatureContext(*this, std::move(pRewindMap)));
+
+ }
+ else
+ {
+ pContext = m_ContextStack.top()->CreateChildContext(
+ std::move(pRewindMap), nPrefix, localName);
+ }
+
+ m_ContextStack.push(std::move(pContext));
+
+ m_ContextStack.top()->StartElement(xAttribs);
+
+ if (m_xNextHandler.is())
+ {
+ m_xNextHandler->startElement(rName, xAttribs);
+ }
+
+}
+
+void SAL_CALL OOXMLSecParser::endElement(const OUString& rName)
+{
+ assert(!m_ContextStack.empty()); // this should be checked by sax parser?
+
+ m_ContextStack.top()->EndElement();
+
+ if (m_xNextHandler.is())
+ {
+ m_xNextHandler->endElement(rName);
+ }
+
+ if (m_ContextStack.top()->m_pOldNamespaceMap)
+ {
+ m_pNamespaceMap = std::move(m_ContextStack.top()->m_pOldNamespaceMap);
+ }
+ m_ContextStack.pop();
+}
+
+void SAL_CALL OOXMLSecParser::characters(const OUString& rChars)
+{
+ assert(!m_ContextStack.empty()); // this should be checked by sax parser?
+ m_ContextStack.top()->Characters(rChars);
+
+ if (m_xNextHandler.is())
+ m_xNextHandler->characters(rChars);
+}
+
+void SAL_CALL OOXMLSecParser::ignorableWhitespace(const OUString& rWhitespace)
+{
+ if (m_xNextHandler.is())
+ m_xNextHandler->ignorableWhitespace(rWhitespace);
+}
+
+void SAL_CALL OOXMLSecParser::processingInstruction(const OUString& rTarget, const OUString& rData)
+{
+ if (m_xNextHandler.is())
+ m_xNextHandler->processingInstruction(rTarget, rData);
+}
+
+void SAL_CALL OOXMLSecParser::setDocumentLocator(const uno::Reference<xml::sax::XLocator>& xLocator)
+{
+ if (m_xNextHandler.is())
+ m_xNextHandler->setDocumentLocator(xLocator);
+}
+
+void SAL_CALL OOXMLSecParser::initialize(const uno::Sequence<uno::Any>& rArguments)
+{
+ rArguments[0] >>= m_xNextHandler;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/helper/ooxmlsecparser.hxx b/xmlsecurity/source/helper/ooxmlsecparser.hxx
new file mode 100644
index 000000000..1ac72a46f
--- /dev/null
+++ b/xmlsecurity/source/helper/ooxmlsecparser.hxx
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <xmloff/namespacemap.hxx>
+
+#include <memory>
+#include <optional>
+#include <stack>
+
+class XSecController;
+class XMLSignatureHelper;
+
+/// Parses an OOXML digital signature.
+class OOXMLSecParser: public cppu::WeakImplHelper
+ <
+ css::xml::sax::XDocumentHandler,
+ css::lang::XInitialization
+ >
+{
+public:
+ class Context;
+private:
+ class UnknownContext;
+ class ReferencedContextImpl;
+ class DsX509CertificateContext;
+ class DsX509SerialNumberContext;
+ class DsX509IssuerNameContext;
+ class DsX509IssuerSerialContext;
+ class DsX509DataContext;
+ class DsKeyInfoContext;
+ class DsSignatureValueContext;
+ class DsDigestValueContext;
+ class DsDigestMethodContext;
+ class DsTransformContext;
+ class DsTransformsContext;
+ class DsReferenceContext;
+ class DsSignatureMethodContext;
+ class DsSignedInfoContext;
+ class XadesEncapsulatedX509CertificateContext;
+ class XadesCertificateValuesContext;
+ class XadesUnsignedSignaturePropertiesContext;
+ class XadesUnsignedPropertiesContext;
+ class XadesCertDigestContext;
+ class XadesCertContext;
+ class XadesSigningCertificateContext;
+ class XadesSigningTimeContext;
+ class XadesSignedSignaturePropertiesContext;
+ class XadesSignedPropertiesContext;
+ class XadesQualifyingPropertiesContext;
+ class MdssiValueContext;
+ class MdssiSignatureTimeContext;
+ class MsodigsigSetupIDContext;
+ class MsodigsigSignatureCommentsContext;
+ class MsodigsigSignatureInfoV1Context;
+ class DsSignaturePropertyContext;
+ class DsSignaturePropertiesContext;
+ class DsManifestContext;
+ class DsObjectContext;
+ class DsSignatureContext;
+ class DsigSignaturesContext;
+
+ std::stack<std::unique_ptr<Context>> m_ContextStack;
+ std::optional<SvXMLNamespaceMap> m_pNamespaceMap;
+
+ XSecController* m_pXSecController;
+ css::uno::Reference<css::xml::sax::XDocumentHandler> m_xNextHandler;
+
+ XMLSignatureHelper& m_rXMLSignatureHelper;
+
+ OUString HandleIdAttr(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs);
+
+public:
+ explicit OOXMLSecParser(XMLSignatureHelper& rXMLSignatureHelper, XSecController* pXSecController);
+ virtual ~OOXMLSecParser() override;
+
+ // XDocumentHandler
+ virtual void SAL_CALL startDocument() override;
+
+ virtual void SAL_CALL endDocument() override;
+
+ virtual void SAL_CALL startElement(const OUString& aName, const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
+
+ virtual void SAL_CALL endElement(const OUString& aName) override;
+
+ virtual void SAL_CALL characters(const OUString& aChars) override;
+
+ virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) override;
+
+ virtual void SAL_CALL processingInstruction(const OUString& aTarget, const OUString& aData) override;
+
+ virtual void SAL_CALL setDocumentLocator(const css::uno::Reference<css::xml::sax::XLocator>& xLocator) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& rArguments) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/helper/pdfsignaturehelper.cxx b/xmlsecurity/source/helper/pdfsignaturehelper.cxx
new file mode 100644
index 000000000..48d5c7f2d
--- /dev/null
+++ b/xmlsecurity/source/helper/pdfsignaturehelper.cxx
@@ -0,0 +1,626 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <pdfsignaturehelper.hxx>
+
+#include <memory>
+
+#include <com/sun/star/io/XTruncate.hpp>
+#include <com/sun/star/io/XStream.hpp>
+#include <com/sun/star/security/CertificateValidity.hpp>
+#include <com/sun/star/uno/SecurityException.hpp>
+#include <com/sun/star/security/DocumentSignatureInformation.hpp>
+#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/XDrawView.hpp>
+
+#include <comphelper/propertysequence.hxx>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+#include <unotools/mediadescriptor.hxx>
+#include <unotools/streamwrap.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <vcl/filter/pdfdocument.hxx>
+#include <vcl/checksum.hxx>
+#include <svl/cryptosign.hxx>
+#include <vcl/filter/PDFiumLibrary.hxx>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+/// Gets the current page of the current view from xModel and puts it to the 1-based rPage.
+bool GetSignatureLinePage(const uno::Reference<frame::XModel>& xModel, sal_Int32& rPage)
+{
+ uno::Reference<drawing::XDrawView> xController(xModel->getCurrentController(), uno::UNO_QUERY);
+ if (!xController.is())
+ {
+ return false;
+ }
+
+ uno::Reference<beans::XPropertySet> xPage(xController->getCurrentPage(), uno::UNO_QUERY);
+ if (!xPage.is())
+ {
+ return false;
+ }
+
+ return xPage->getPropertyValue("Number") >>= rPage;
+}
+
+/// If the currently selected shape is a Draw signature line, export that to PDF.
+void GetSignatureLineShape(const uno::Reference<frame::XModel>& xModel, sal_Int32& rPage,
+ std::vector<sal_Int8>& rSignatureLineShape)
+{
+ if (!xModel.is())
+ {
+ return;
+ }
+
+ if (!GetSignatureLinePage(xModel, rPage))
+ {
+ return;
+ }
+
+ uno::Reference<drawing::XShapes> xShapes(xModel->getCurrentSelection(), uno::UNO_QUERY);
+ if (!xShapes.is() || xShapes->getCount() < 1)
+ {
+ return;
+ }
+
+ uno::Reference<beans::XPropertySet> xShapeProps(xShapes->getByIndex(0), uno::UNO_QUERY);
+ if (!xShapeProps.is())
+ {
+ return;
+ }
+
+ comphelper::SequenceAsHashMap aMap(xShapeProps->getPropertyValue("InteropGrabBag"));
+ auto it = aMap.find("SignatureCertificate");
+ if (it == aMap.end())
+ {
+ return;
+ }
+
+ // We know that we add a signature line shape to an existing PDF at this point.
+
+ uno::Reference<frame::XStorable> xStorable(xModel, uno::UNO_QUERY);
+ if (!xStorable.is())
+ {
+ return;
+ }
+
+ // Export just the signature line.
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("draw_pdf_Export");
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xStream(new utl::OStreamWrapper(aStream));
+ aMediaDescriptor["OutputStream"] <<= xStream;
+ uno::Sequence<beans::PropertyValue> aFilterData(
+ comphelper::InitPropertySequence({ { "Selection", uno::Any(xShapes) } }));
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList());
+ xStream->flush();
+
+ aStream.Seek(0);
+ rSignatureLineShape = std::vector<sal_Int8>(aStream.GetSize());
+ aStream.ReadBytes(rSignatureLineShape.data(), rSignatureLineShape.size());
+}
+
+/// Represents a parsed signature.
+struct Signature
+{
+ std::unique_ptr<vcl::pdf::PDFiumSignature> m_pSignature;
+ /// Offset+length pairs.
+ std::vector<std::pair<size_t, size_t>> m_aByteRanges;
+};
+
+/// Turns an array of floats into offset + length pairs.
+void GetByteRangesFromPDF(const std::unique_ptr<vcl::pdf::PDFiumSignature>& pSignature,
+ std::vector<std::pair<size_t, size_t>>& rByteRanges)
+{
+ std::vector<int> aByteRange = pSignature->getByteRange();
+ if (aByteRange.empty())
+ {
+ SAL_WARN("xmlsecurity.helper", "GetByteRangesFromPDF: no byte ranges");
+ return;
+ }
+
+ size_t nByteRangeOffset = 0;
+ for (size_t i = 0; i < aByteRange.size(); ++i)
+ {
+ if (i % 2 == 0)
+ {
+ nByteRangeOffset = aByteRange[i];
+ continue;
+ }
+
+ size_t nLength = aByteRange[i];
+ rByteRanges.emplace_back(nByteRangeOffset, nLength);
+ }
+}
+
+/// Determines the last position that is covered by a signature.
+bool GetEOFOfSignature(const Signature& rSignature, size_t& rEOF)
+{
+ if (rSignature.m_aByteRanges.size() < 2)
+ {
+ return false;
+ }
+
+ rEOF = rSignature.m_aByteRanges[1].first + rSignature.m_aByteRanges[1].second;
+ return true;
+}
+
+/**
+ * Get the value of the "modification detection and prevention" permission:
+ * Valid values are 1, 2 and 3: only 3 allows annotations after signing.
+ */
+int GetMDPPerm(const std::vector<Signature>& rSignatures)
+{
+ int nRet = 3;
+
+ if (rSignatures.empty())
+ {
+ return nRet;
+ }
+
+ for (const auto& rSignature : rSignatures)
+ {
+ int nPerm = rSignature.m_pSignature->getDocMDPPermission();
+ if (nPerm != 0)
+ {
+ return nPerm;
+ }
+ }
+
+ return nRet;
+}
+
+/// Checks if there are unsigned incremental updates between the signatures or after the last one.
+bool IsCompleteSignature(SvStream& rStream, const Signature& rSignature,
+ const std::set<unsigned int>& rSignedEOFs,
+ const std::vector<unsigned int>& rAllEOFs)
+{
+ size_t nSignatureEOF = 0;
+ if (!GetEOFOfSignature(rSignature, nSignatureEOF))
+ {
+ return false;
+ }
+
+ bool bFoundOwn = false;
+ for (const auto& rEOF : rAllEOFs)
+ {
+ if (rEOF == nSignatureEOF)
+ {
+ bFoundOwn = true;
+ continue;
+ }
+
+ if (!bFoundOwn)
+ {
+ continue;
+ }
+
+ if (rSignedEOFs.find(rEOF) == rSignedEOFs.end())
+ {
+ // Unsigned incremental update found.
+ return false;
+ }
+ }
+
+ // Make sure we find the incremental update of the signature itself.
+ if (!bFoundOwn)
+ {
+ return false;
+ }
+
+ // No additional content after the last incremental update.
+ rStream.Seek(STREAM_SEEK_TO_END);
+ size_t nFileEnd = rStream.Tell();
+ return std::find(rAllEOFs.begin(), rAllEOFs.end(), nFileEnd) != rAllEOFs.end();
+}
+
+/**
+ * Contains checksums of a PDF page, which is rendered without annotations. It also contains
+ * the geometry of a few dangerous annotation types.
+ */
+struct PageChecksum
+{
+ BitmapChecksum m_nPageContent;
+ std::vector<basegfx::B2DRectangle> m_aAnnotations;
+ bool operator==(const PageChecksum& rChecksum) const;
+};
+
+bool PageChecksum::operator==(const PageChecksum& rChecksum) const
+{
+ if (m_nPageContent != rChecksum.m_nPageContent)
+ {
+ return false;
+ }
+
+ return m_aAnnotations == rChecksum.m_aAnnotations;
+}
+
+/// Collects the checksum of each page of one version of the PDF.
+void AnalyizeSignatureStream(SvMemoryStream& rStream, std::vector<PageChecksum>& rPageChecksums,
+ int nMDPPerm)
+{
+ auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
+ = pPdfium->openDocument(rStream.GetData(), rStream.GetSize(), OString());
+ if (!pPdfDocument)
+ {
+ return;
+ }
+
+ int nPageCount = pPdfDocument->getPageCount();
+ for (int nPage = 0; nPage < nPageCount; ++nPage)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(nPage);
+ if (!pPdfPage)
+ {
+ return;
+ }
+
+ PageChecksum aPageChecksum;
+ aPageChecksum.m_nPageContent = pPdfPage->getChecksum(nMDPPerm);
+ for (int i = 0; i < pPdfPage->getAnnotationCount(); ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumAnnotation> pPdfAnnotation = pPdfPage->getAnnotation(i);
+ if (!pPdfAnnotation)
+ {
+ SAL_WARN("xmlsecurity.helper", "Cannot get PDFiumAnnotation");
+ continue;
+ }
+ vcl::pdf::PDFAnnotationSubType eType = pPdfAnnotation->getSubType();
+ switch (eType)
+ {
+ case vcl::pdf::PDFAnnotationSubType::Unknown:
+ case vcl::pdf::PDFAnnotationSubType::FreeText:
+ case vcl::pdf::PDFAnnotationSubType::Stamp:
+ case vcl::pdf::PDFAnnotationSubType::Redact:
+ aPageChecksum.m_aAnnotations.push_back(pPdfAnnotation->getRectangle());
+ break;
+ default:
+ break;
+ }
+ }
+ rPageChecksums.push_back(aPageChecksum);
+ }
+}
+
+/**
+ * Checks if incremental updates after singing performed valid modifications only.
+ * nMDPPerm decides if annotations/commenting is OK, other changes are always not.
+ */
+bool IsValidSignature(SvStream& rStream, const Signature& rSignature, int nMDPPerm)
+{
+ size_t nSignatureEOF = 0;
+ if (!GetEOFOfSignature(rSignature, nSignatureEOF))
+ {
+ return false;
+ }
+
+ SvMemoryStream aSignatureStream;
+ sal_uInt64 nPos = rStream.Tell();
+ rStream.Seek(0);
+ aSignatureStream.WriteStream(rStream, nSignatureEOF);
+ rStream.Seek(nPos);
+ aSignatureStream.Seek(0);
+ std::vector<PageChecksum> aSignedPages;
+ AnalyizeSignatureStream(aSignatureStream, aSignedPages, nMDPPerm);
+
+ SvMemoryStream aFullStream;
+ nPos = rStream.Tell();
+ rStream.Seek(0);
+ aFullStream.WriteStream(rStream);
+ rStream.Seek(nPos);
+ aFullStream.Seek(0);
+ std::vector<PageChecksum> aAllPages;
+ AnalyizeSignatureStream(aFullStream, aAllPages, nMDPPerm);
+
+ // Fail if any page looks different after signing and at the end. Annotations/commenting doesn't
+ // count, though.
+ return aSignedPages == aAllPages;
+}
+
+/**
+ * @param rInformation The actual result.
+ * @param rDocument the parsed document to see if the signature is partial.
+ * @return If we can determinate a result.
+ */
+bool ValidateSignature(SvStream& rStream, const Signature& rSignature,
+ SignatureInformation& rInformation, int nMDPPerm,
+ const std::set<unsigned int>& rSignatureEOFs,
+ const std::vector<unsigned int>& rTrailerEnds)
+{
+ std::vector<unsigned char> aContents = rSignature.m_pSignature->getContents();
+ if (aContents.empty())
+ {
+ SAL_WARN("xmlsecurity.helper", "ValidateSignature: no contents");
+ return false;
+ }
+
+ OString aSubFilter = rSignature.m_pSignature->getSubFilter();
+
+ const bool bNonDetached = aSubFilter == "adbe.pkcs7.sha1";
+ if (aSubFilter.isEmpty()
+ || (aSubFilter != "adbe.pkcs7.detached" && !bNonDetached
+ && aSubFilter != "ETSI.CAdES.detached"))
+ {
+ if (aSubFilter.isEmpty())
+ SAL_WARN("xmlsecurity.helper", "ValidateSignature: missing sub-filter");
+ else
+ SAL_WARN("xmlsecurity.helper",
+ "ValidateSignature: unsupported sub-filter: '" << aSubFilter << "'");
+ return false;
+ }
+
+ // Reason / comment / description is optional.
+ rInformation.ouDescription = rSignature.m_pSignature->getReason();
+
+ // Date: used only when the time of signing is not available in the
+ // signature.
+ rInformation.stDateTime = rSignature.m_pSignature->getTime();
+
+ // Detect if the byte ranges don't cover everything, but the signature itself.
+ if (rSignature.m_aByteRanges.size() < 2)
+ {
+ SAL_WARN("xmlsecurity.helper", "ValidateSignature: expected 2 byte ranges");
+ return false;
+ }
+ if (rSignature.m_aByteRanges[0].first != 0)
+ {
+ SAL_WARN("xmlsecurity.helper", "ValidateSignature: first range start is not 0");
+ return false;
+ }
+ // Binary vs hex dump and 2 is the leading "<" and the trailing ">" around the hex string.
+ size_t nSignatureLength = aContents.size() * 2 + 2;
+ if (rSignature.m_aByteRanges[1].first
+ != (rSignature.m_aByteRanges[0].second + nSignatureLength))
+ {
+ SAL_WARN("xmlsecurity.helper",
+ "ValidateSignature: second range start is not the end of the signature");
+ return false;
+ }
+ rInformation.bPartialDocumentSignature
+ = !IsCompleteSignature(rStream, rSignature, rSignatureEOFs, rTrailerEnds);
+ if (!IsValidSignature(rStream, rSignature, nMDPPerm))
+ {
+ SAL_WARN("xmlsecurity.helper", "ValidateSignature: invalid incremental update detected");
+ return false;
+ }
+
+ // At this point there is no obviously missing info to validate the
+ // signature.
+ return svl::crypto::Signing::Verify(rStream, rSignature.m_aByteRanges, bNonDetached, aContents,
+ rInformation);
+}
+}
+
+PDFSignatureHelper::PDFSignatureHelper() = default;
+
+bool PDFSignatureHelper::ReadAndVerifySignature(
+ const uno::Reference<io::XInputStream>& xInputStream)
+{
+ if (!xInputStream.is())
+ {
+ SAL_WARN("xmlsecurity.helper", "input stream missing");
+ return false;
+ }
+
+ std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
+ return ReadAndVerifySignatureSvStream(*pStream);
+}
+
+bool PDFSignatureHelper::ReadAndVerifySignatureSvStream(SvStream& rStream)
+{
+ auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPdfium)
+ {
+ return true;
+ }
+
+ SvMemoryStream aStream;
+ sal_uInt64 nPos = rStream.Tell();
+ rStream.Seek(0);
+ aStream.WriteStream(rStream);
+ rStream.Seek(nPos);
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
+ = pPdfium->openDocument(aStream.GetData(), aStream.GetSize(), OString());
+ if (!pPdfDocument)
+ {
+ SAL_WARN("xmlsecurity.helper", "failed to read the document");
+ return false;
+ }
+
+ int nSignatureCount = pPdfDocument->getSignatureCount();
+ if (nSignatureCount <= 0)
+ {
+ return true;
+ }
+ std::vector<Signature> aSignatures(nSignatureCount);
+ for (int i = 0; i < nSignatureCount; ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumSignature> pSignature = pPdfDocument->getSignature(i);
+ std::vector<std::pair<size_t, size_t>> aByteRanges;
+ GetByteRangesFromPDF(pSignature, aByteRanges);
+ aSignatures[i] = Signature{ std::move(pSignature), aByteRanges };
+ }
+
+ std::set<unsigned int> aSignatureEOFs;
+ for (const auto& rSignature : aSignatures)
+ {
+ size_t nEOF = 0;
+ if (GetEOFOfSignature(rSignature, nEOF))
+ {
+ aSignatureEOFs.insert(nEOF);
+ }
+ }
+
+ std::vector<unsigned int> aTrailerEnds = pPdfDocument->getTrailerEnds();
+
+ m_aSignatureInfos.clear();
+
+ int nMDPPerm = GetMDPPerm(aSignatures);
+
+ for (size_t i = 0; i < aSignatures.size(); ++i)
+ {
+ SignatureInformation aInfo(i);
+
+ if (!ValidateSignature(rStream, aSignatures[i], aInfo, nMDPPerm, aSignatureEOFs,
+ aTrailerEnds))
+ {
+ SAL_WARN("xmlsecurity.helper", "failed to determine digest match");
+ }
+
+ m_aSignatureInfos.push_back(aInfo);
+ }
+
+ return true;
+}
+
+SignatureInformations const& PDFSignatureHelper::GetSignatureInformations() const
+{
+ return m_aSignatureInfos;
+}
+
+uno::Sequence<security::DocumentSignatureInformation>
+PDFSignatureHelper::GetDocumentSignatureInformations(
+ const uno::Reference<xml::crypto::XSecurityEnvironment>& xSecEnv) const
+{
+ uno::Sequence<security::DocumentSignatureInformation> aRet(m_aSignatureInfos.size());
+ auto aRetRange = asNonConstRange(aRet);
+
+ for (size_t i = 0; i < m_aSignatureInfos.size(); ++i)
+ {
+ const SignatureInformation& rInternal = m_aSignatureInfos[i];
+ security::DocumentSignatureInformation& rExternal = aRetRange[i];
+ rExternal.SignatureIsValid
+ = rInternal.nStatus == xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED;
+ if (rInternal.GetSigningCertificate()
+ && !rInternal.GetSigningCertificate()->X509Certificate.isEmpty())
+ {
+ rExternal.Signer = xSecEnv->createCertificateFromAscii(
+ rInternal.GetSigningCertificate()->X509Certificate);
+ }
+ rExternal.PartialDocumentSignature = rInternal.bPartialDocumentSignature;
+
+ // Verify certificate.
+ if (rExternal.Signer.is())
+ {
+ try
+ {
+ rExternal.CertificateStatus = xSecEnv->verifyCertificate(rExternal.Signer, {});
+ }
+ catch (const uno::SecurityException&)
+ {
+ DBG_UNHANDLED_EXCEPTION("xmlsecurity.helper", "failed to verify certificate");
+ rExternal.CertificateStatus = security::CertificateValidity::INVALID;
+ }
+ }
+ else
+ rExternal.CertificateStatus = security::CertificateValidity::INVALID;
+ }
+
+ return aRet;
+}
+
+sal_Int32 PDFSignatureHelper::GetNewSecurityId() const { return m_aSignatureInfos.size(); }
+
+void PDFSignatureHelper::SetX509Certificate(
+ const uno::Reference<security::XCertificate>& xCertificate)
+{
+ m_xCertificate = xCertificate;
+}
+
+void PDFSignatureHelper::SetDescription(const OUString& rDescription)
+{
+ m_aDescription = rDescription;
+}
+
+bool PDFSignatureHelper::Sign(const uno::Reference<frame::XModel>& xModel,
+ const uno::Reference<io::XInputStream>& xInputStream, bool bAdES)
+{
+ std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
+ vcl::filter::PDFDocument aDocument;
+ if (!aDocument.Read(*pStream))
+ {
+ SAL_WARN("xmlsecurity.helper", "failed to read the document");
+ return false;
+ }
+
+ sal_Int32 nPage = 0;
+ std::vector<sal_Int8> aSignatureLineShape;
+ GetSignatureLineShape(xModel, nPage, aSignatureLineShape);
+ if (nPage > 0)
+ {
+ // UNO page number is 1-based.
+ aDocument.SetSignaturePage(nPage - 1);
+ }
+ if (!aSignatureLineShape.empty())
+ {
+ aDocument.SetSignatureLine(std::move(aSignatureLineShape));
+ }
+
+ if (!aDocument.Sign(m_xCertificate, m_aDescription, bAdES))
+ {
+ SAL_WARN("xmlsecurity.helper", "failed to sign");
+ return false;
+ }
+
+ uno::Reference<io::XStream> xStream(xInputStream, uno::UNO_QUERY);
+ std::unique_ptr<SvStream> pOutStream(utl::UcbStreamHelper::CreateStream(xStream, true));
+ if (!aDocument.Write(*pOutStream))
+ {
+ SAL_WARN("xmlsecurity.helper", "failed to write signed data");
+ return false;
+ }
+
+ return true;
+}
+
+bool PDFSignatureHelper::RemoveSignature(const uno::Reference<io::XInputStream>& xInputStream,
+ sal_uInt16 nPosition)
+{
+ std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
+ vcl::filter::PDFDocument aDocument;
+ if (!aDocument.Read(*pStream))
+ {
+ SAL_WARN("xmlsecurity.helper", "failed to read the document");
+ return false;
+ }
+
+ if (!aDocument.RemoveSignature(nPosition))
+ {
+ SAL_WARN("xmlsecurity.helper", "failed to remove signature");
+ return false;
+ }
+
+ uno::Reference<io::XStream> xStream(xInputStream, uno::UNO_QUERY);
+ uno::Reference<io::XTruncate> xTruncate(xStream, uno::UNO_QUERY);
+ if (!xTruncate.is())
+ {
+ SAL_WARN("xmlsecurity.helper", "failed to truncate");
+ return false;
+ }
+ xTruncate->truncate();
+ std::unique_ptr<SvStream> pOutStream(utl::UcbStreamHelper::CreateStream(xStream, true));
+ if (!aDocument.Write(*pOutStream))
+ {
+ SAL_WARN("xmlsecurity.helper", "failed to write without signature");
+ return false;
+ }
+
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/helper/xmlsignaturehelper.cxx b/xmlsecurity/source/helper/xmlsignaturehelper.cxx
new file mode 100644
index 000000000..0d9755d0e
--- /dev/null
+++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx
@@ -0,0 +1,714 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include <xmlsignaturehelper.hxx>
+#include <documentsignaturehelper.hxx>
+#include <xsecctl.hxx>
+#include <biginteger.hxx>
+
+#include <UriBindingHelper.hxx>
+
+#include <tools/datetime.hxx>
+
+#include <xmloff/attrlist.hxx>
+
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XTruncate.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/StringPair.hpp>
+#include <com/sun/star/xml/sax/Parser.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/StorageFormats.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+
+#include <comphelper/ofopxmlhelper.hxx>
+#include <comphelper/sequence.hxx>
+#include <tools/diagnose_ex.h>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+
+#include <optional>
+
+constexpr OUStringLiteral NS_DOCUMENTSIGNATURES = u"http://openoffice.org/2004/documentsignatures";
+constexpr OUStringLiteral NS_DOCUMENTSIGNATURES_ODF_1_2 = u"urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0";
+constexpr OUStringLiteral OOXML_SIGNATURE_ORIGIN = u"http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin";
+constexpr OUStringLiteral OOXML_SIGNATURE_SIGNATURE = u"http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/signature";
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::graphic;
+using namespace ::com::sun::star::uno;
+
+XMLSignatureHelper::XMLSignatureHelper( const uno::Reference< uno::XComponentContext >& rxCtx)
+ : mxCtx(rxCtx), mbODFPre1_2(false)
+{
+ mpXSecController = new XSecController(rxCtx);
+ mbError = false;
+}
+
+XMLSignatureHelper::~XMLSignatureHelper()
+{
+}
+
+void XMLSignatureHelper::SetStorage(
+ const Reference < css::embed::XStorage >& rxStorage,
+ const OUString& sODFVersion)
+{
+ SAL_WARN_IF( mxUriBinding.is(), "xmlsecurity.helper", "SetStorage - UriBinding already set!" );
+ mxUriBinding = new UriBindingHelper( rxStorage );
+ SAL_WARN_IF(!rxStorage.is(), "xmlsecurity.helper", "SetStorage - empty storage!");
+ mbODFPre1_2 = DocumentSignatureHelper::isODFPre_1_2(sODFVersion);
+}
+
+
+void XMLSignatureHelper::SetStartVerifySignatureHdl( const Link<LinkParamNone*,bool>& rLink )
+{
+ maStartVerifySignatureHdl = rLink;
+}
+
+
+void XMLSignatureHelper::StartMission(const uno::Reference<xml::crypto::XXMLSecurityContext>& xSecurityContext)
+{
+ if ( !mxUriBinding.is() )
+ mxUriBinding = new UriBindingHelper();
+
+ mpXSecController->startMission(mxUriBinding, xSecurityContext);
+}
+
+void XMLSignatureHelper::EndMission()
+{
+ mpXSecController->endMission();
+}
+
+sal_Int32 XMLSignatureHelper::GetNewSecurityId()
+{
+ return mpXSecController->getNewSecurityId();
+}
+
+void XMLSignatureHelper::SetX509Certificate(
+ sal_Int32 nSecurityId,
+ const OUString& ouX509IssuerName,
+ const OUString& ouX509SerialNumber,
+ const OUString& ouX509Cert,
+ const OUString& ouX509CertDigest,
+ svl::crypto::SignatureMethodAlgorithm eAlgorithmID)
+{
+ mpXSecController->setX509Certificate(
+ nSecurityId,
+ ouX509IssuerName,
+ ouX509SerialNumber,
+ ouX509Cert,
+ ouX509CertDigest,
+ eAlgorithmID);
+}
+
+void XMLSignatureHelper::AddEncapsulatedX509Certificate(const OUString& ouEncapsulatedX509Certificate)
+{
+ mpXSecController->addEncapsulatedX509Certificate(ouEncapsulatedX509Certificate);
+}
+
+void XMLSignatureHelper::SetGpgCertificate(sal_Int32 nSecurityId,
+ const OUString& ouGpgCertDigest,
+ const OUString& ouGpgCert,
+ const OUString& ouGpgOwner)
+{
+ mpXSecController->setGpgCertificate(
+ nSecurityId,
+ ouGpgCertDigest,
+ ouGpgCert,
+ ouGpgOwner);
+}
+
+void XMLSignatureHelper::SetDateTime( sal_Int32 nSecurityId, const ::DateTime& rDateTime )
+{
+ css::util::DateTime stDateTime = rDateTime.GetUNODateTime();
+ mpXSecController->setDate( nSecurityId, stDateTime );
+}
+
+void XMLSignatureHelper::SetDescription(sal_Int32 nSecurityId, const OUString& rDescription)
+{
+ mpXSecController->setDescription(nSecurityId, rDescription);
+}
+
+void XMLSignatureHelper::SetSignatureLineId(sal_Int32 nSecurityId, const OUString& rSignatureLineId)
+{
+ mpXSecController->setSignatureLineId(nSecurityId, rSignatureLineId);
+}
+
+void XMLSignatureHelper::SetSignatureLineValidGraphic(
+ sal_Int32 nSecurityId, const css::uno::Reference<XGraphic>& xValidGraphic)
+{
+ mpXSecController->setSignatureLineValidGraphic(nSecurityId, xValidGraphic);
+}
+
+void XMLSignatureHelper::SetSignatureLineInvalidGraphic(
+ sal_Int32 nSecurityId, const css::uno::Reference<XGraphic>& xInvalidGraphic)
+{
+ mpXSecController->setSignatureLineInvalidGraphic(nSecurityId, xInvalidGraphic);
+}
+
+void XMLSignatureHelper::AddForSigning( sal_Int32 nSecurityId, const OUString& uri, bool bBinary, bool bXAdESCompliantIfODF )
+{
+ mpXSecController->signAStream( nSecurityId, uri, bBinary, bXAdESCompliantIfODF );
+}
+
+
+uno::Reference<xml::sax::XWriter> XMLSignatureHelper::CreateDocumentHandlerWithHeader(
+ const css::uno::Reference< css::io::XOutputStream >& xOutputStream )
+{
+ /*
+ * get SAX writer component
+ */
+ uno::Reference< xml::sax::XWriter > xSaxWriter = xml::sax::Writer::create(mxCtx);
+
+ /*
+ * connect XML writer to output stream
+ */
+ xSaxWriter->setOutputStream( xOutputStream );
+
+ /*
+ * write the xml context for signatures
+ */
+ rtl::Reference<SvXMLAttributeList> pAttributeList = new SvXMLAttributeList();
+ OUString sNamespace;
+ if (mbODFPre1_2)
+ sNamespace = NS_DOCUMENTSIGNATURES;
+ else
+ sNamespace = NS_DOCUMENTSIGNATURES_ODF_1_2;
+
+ pAttributeList->AddAttribute(
+ "xmlns",
+ sNamespace);
+
+ xSaxWriter->startDocument();
+ xSaxWriter->startElement(
+ "document-signatures",
+ pAttributeList);
+
+ return xSaxWriter;
+}
+
+void XMLSignatureHelper::CloseDocumentHandler( const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler )
+{
+ xDocumentHandler->endElement( "document-signatures" );
+ xDocumentHandler->endDocument();
+}
+
+void XMLSignatureHelper::ExportSignature(
+ const uno::Reference< xml::sax::XDocumentHandler >& xDocumentHandler,
+ const SignatureInformation& signatureInfo,
+ bool bXAdESCompliantIfODF )
+{
+ XSecController::exportSignature(xDocumentHandler, signatureInfo, bXAdESCompliantIfODF);
+}
+
+void XMLSignatureHelper::ExportOOXMLSignature(const uno::Reference<embed::XStorage>& xRootStorage, const uno::Reference<embed::XStorage>& xSignatureStorage, const SignatureInformation& rInformation, int nSignatureIndex)
+{
+ uno::Reference<io::XOutputStream> xOutputStream(xSignatureStorage->openStreamElement("sig" + OUString::number(nSignatureIndex) + ".xml", embed::ElementModes::READWRITE), uno::UNO_QUERY);
+
+ if (rInformation.aSignatureBytes.hasElements())
+ // This is a signature roundtrip, just write back the signature as-is.
+ xOutputStream->writeBytes(rInformation.aSignatureBytes);
+ else
+ {
+ uno::Reference<xml::sax::XWriter> xSaxWriter = xml::sax::Writer::create(mxCtx);
+ xSaxWriter->setOutputStream(xOutputStream);
+ xSaxWriter->startDocument();
+
+ mpXSecController->exportOOXMLSignature(xRootStorage, xSaxWriter, rInformation);
+
+ xSaxWriter->endDocument();
+ }
+}
+
+void XMLSignatureHelper::CreateAndWriteSignature( const uno::Reference< xml::sax::XDocumentHandler >& xDocumentHandler, bool bXAdESCompliantIfODF )
+{
+ mbError = false;
+
+ if ( !mpXSecController->WriteSignature( xDocumentHandler, bXAdESCompliantIfODF ) )
+ {
+ mbError = true;
+ }
+}
+
+bool XMLSignatureHelper::ReadAndVerifySignature( const css::uno::Reference< css::io::XInputStream >& xInputStream )
+{
+ mbError = false;
+
+ SAL_WARN_IF(!xInputStream.is(), "xmlsecurity.helper", "input stream missing");
+
+ // prepare ParserInputSource
+ xml::sax::InputSource aParserInput;
+ aParserInput.aInputStream = xInputStream;
+
+ // get SAX parser component
+ uno::Reference< xml::sax::XParser > xParser = xml::sax::Parser::create(mxCtx);
+
+ // create a signature reader
+ uno::Reference< xml::sax::XDocumentHandler > xHandler
+ = mpXSecController->createSignatureReader(*this);
+
+ // setup the connection:
+ // Parser -> SignatureReader
+ xParser->setDocumentHandler( xHandler );
+
+ // Parse the stream.
+ try
+ {
+ xParser->parseStream( aParserInput );
+ }
+ catch( uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("xmlsecurity.helper");
+ mbError = true;
+ }
+
+ // release the signature reader
+ mpXSecController->releaseSignatureReader( );
+
+ return !mbError;
+}
+
+SignatureInformation XMLSignatureHelper::GetSignatureInformation( sal_Int32 nSecurityId ) const
+{
+ return mpXSecController->getSignatureInformation( nSecurityId );
+}
+
+SignatureInformations XMLSignatureHelper::GetSignatureInformations() const
+{
+ return mpXSecController->getSignatureInformations();
+}
+
+void XMLSignatureHelper::StartVerifySignatureElement()
+{
+ if ( !maStartVerifySignatureHdl.IsSet() || maStartVerifySignatureHdl.Call(nullptr) )
+ {
+ sal_Int32 nSignatureId = mpXSecController->getNewSecurityId();
+ mpXSecController->addSignature( nSignatureId );
+ }
+}
+
+namespace
+{
+bool lcl_isSignatureType(const beans::StringPair& rPair)
+{
+ return rPair.First == "Type" && rPair.Second == OOXML_SIGNATURE_SIGNATURE;
+}
+bool lcl_isSignatureOriginType(const beans::StringPair& rPair)
+{
+ return rPair.First == "Type" && rPair.Second == OOXML_SIGNATURE_ORIGIN;
+}
+}
+
+bool XMLSignatureHelper::ReadAndVerifySignatureStorage(const uno::Reference<embed::XStorage>& xStorage, bool bCacheLastSignature)
+{
+ sal_Int32 nOpenMode = embed::ElementModes::READ;
+ if (xStorage.is() && !xStorage->hasByName("_rels"))
+ {
+ SAL_WARN("xmlsecurity.helper", "expected stream, in signature storage but not found: _rels");
+ return false;
+ }
+
+ uno::Reference<embed::XStorage> xSubStorage = xStorage->openStorageElement("_rels", nOpenMode);
+ uno::Reference<io::XInputStream> xRelStream(xSubStorage->openStreamElement("origin.sigs.rels", nOpenMode), uno::UNO_QUERY);
+ uno::Sequence< uno::Sequence<beans::StringPair> > aRelationsInfo = comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(xRelStream, u"origin.sigs.rels", mxCtx);
+
+ for (sal_Int32 i = 0; i < aRelationsInfo.getLength(); ++i)
+ {
+ const uno::Sequence<beans::StringPair>& rRelation = aRelationsInfo[i];
+ if (std::any_of(rRelation.begin(), rRelation.end(), lcl_isSignatureType))
+ {
+ auto it = std::find_if(rRelation.begin(), rRelation.end(), [](const beans::StringPair& rPair) { return rPair.First == "Target"; });
+ if (it != rRelation.end())
+ {
+ if (xStorage.is() && !xStorage->hasByName(it->Second))
+ {
+ SAL_WARN("xmlsecurity.helper", "expected stream, but not found: " << it->Second);
+ continue;
+ }
+
+ uno::Reference<io::XInputStream> xInputStream(xStorage->openStreamElement(it->Second, nOpenMode), uno::UNO_QUERY);
+ if (!ReadAndVerifySignatureStorageStream(xInputStream))
+ return false;
+
+ // By default, we cache. If it's requested, then we don't cache the last signature.
+ bool bCache = true;
+ if (!bCacheLastSignature && i == aRelationsInfo.getLength() - 1)
+ bCache = false;
+
+ if (!bCache)
+ continue;
+ // Store the contents of the stream as is, in case we need to write it back later.
+ xInputStream.clear();
+ xInputStream.set(xStorage->openStreamElement(it->Second, nOpenMode), uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xPropertySet(xInputStream, uno::UNO_QUERY);
+ if (!xPropertySet.is())
+ continue;
+
+ sal_Int64 nSize = 0;
+ xPropertySet->getPropertyValue("Size") >>= nSize;
+ if (nSize < 0 || nSize > SAL_MAX_INT32)
+ {
+ SAL_WARN("xmlsecurity.helper", "bogus signature size: " << nSize);
+ continue;
+ }
+ uno::Sequence<sal_Int8> aData;
+ xInputStream->readBytes(aData, nSize);
+ mpXSecController->setSignatureBytes(aData);
+ }
+ }
+ }
+
+ return true;
+}
+
+bool XMLSignatureHelper::ReadAndVerifySignatureStorageStream(const css::uno::Reference<css::io::XInputStream>& xInputStream)
+{
+ mbError = false;
+
+ // Create the input source.
+ xml::sax::InputSource aParserInput;
+ aParserInput.aInputStream = xInputStream;
+
+ // Create the sax parser.
+ uno::Reference<xml::sax::XParser> xParser = xml::sax::Parser::create(mxCtx);
+
+ // Create the signature reader.
+ uno::Reference<xml::sax::XDocumentHandler> xHandler = mpXSecController->createSignatureReader(*this, embed::StorageFormats::OFOPXML);
+
+ // Parser -> signature reader.
+ xParser->setDocumentHandler(xHandler);
+
+ // Parse the stream.
+ try
+ {
+ xParser->parseStream(aParserInput);
+ }
+ catch(const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("xmlsecurity.helper");
+ mbError = true;
+ }
+
+ // release the signature reader
+ mpXSecController->releaseSignatureReader();
+
+ return !mbError;
+}
+
+void XMLSignatureHelper::EnsureSignaturesRelation(const css::uno::Reference<css::embed::XStorage>& xStorage, bool bAdd)
+{
+ sal_Int32 nOpenMode = embed::ElementModes::READWRITE;
+ uno::Reference<embed::XStorage> xSubStorage = xStorage->openStorageElement("_rels", nOpenMode);
+ uno::Reference<io::XInputStream> xRelStream(xSubStorage->openStreamElement(".rels", nOpenMode), uno::UNO_QUERY);
+ std::vector< uno::Sequence<beans::StringPair> > aRelationsInfo = comphelper::sequenceToContainer< std::vector< uno::Sequence<beans::StringPair> > >(comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(xRelStream, u".rels", mxCtx));
+
+ // Do we have a relation already?
+ bool bHaveRelation = false;
+ int nCount = 0;
+ for (const uno::Sequence<beans::StringPair>& rRelation : aRelationsInfo)
+ {
+ auto aRelation = comphelper::sequenceToContainer< std::vector<beans::StringPair> >(rRelation);
+ if (std::any_of(aRelation.begin(), aRelation.end(), lcl_isSignatureOriginType))
+ {
+ bHaveRelation = true;
+ break;
+ }
+ ++nCount;
+ }
+
+ if (!bHaveRelation && bAdd)
+ {
+ // No, and have to add one.
+ std::vector<beans::StringPair> aRelation;
+ aRelation.emplace_back("Id", "rId" + OUString::number(++nCount));
+ aRelation.emplace_back("Type", OOXML_SIGNATURE_ORIGIN);
+ aRelation.emplace_back("Target", "_xmlsignatures/origin.sigs");
+ aRelationsInfo.push_back(comphelper::containerToSequence(aRelation));
+ }
+ else if (bHaveRelation && !bAdd)
+ {
+ // Yes, and need to remove it.
+ for (std::vector< uno::Sequence<beans::StringPair> >::iterator it = aRelationsInfo.begin(); it != aRelationsInfo.end();)
+ {
+ auto aRelation = comphelper::sequenceToContainer< std::vector<beans::StringPair> >(*it);
+ if (std::any_of(aRelation.begin(), aRelation.end(), lcl_isSignatureOriginType))
+ it = aRelationsInfo.erase(it);
+ else
+ ++it;
+ }
+ }
+
+ // Write it back.
+ uno::Reference<io::XTruncate> xTruncate(xRelStream, uno::UNO_QUERY);
+ xTruncate->truncate();
+ uno::Reference<io::XOutputStream> xOutputStream(xRelStream, uno::UNO_QUERY);
+ comphelper::OFOPXMLHelper::WriteRelationsInfoSequence(xOutputStream, comphelper::containerToSequence(aRelationsInfo), mxCtx);
+
+ // Commit it.
+ uno::Reference<embed::XTransactedObject> xTransact(xSubStorage, uno::UNO_QUERY);
+ xTransact->commit();
+ xTransact.set(xStorage, uno::UNO_QUERY);
+ xTransact->commit();
+}
+
+void XMLSignatureHelper::ExportSignatureRelations(const css::uno::Reference<css::embed::XStorage>& xStorage, int nSignatureCount)
+{
+ // Write the empty file, its relations will be the signatures.
+ sal_Int32 nOpenMode = embed::ElementModes::READWRITE;
+ uno::Reference<io::XOutputStream> xOriginStream(xStorage->openStreamElement("origin.sigs", nOpenMode), uno::UNO_QUERY);
+ uno::Reference<io::XTruncate> xTruncate(xOriginStream, uno::UNO_QUERY);
+ xTruncate->truncate();
+ xOriginStream->closeOutput();
+
+ // Write the relations.
+ uno::Reference<embed::XStorage> xSubStorage = xStorage->openStorageElement("_rels", nOpenMode);
+ uno::Reference<io::XOutputStream> xRelStream(xSubStorage->openStreamElement("origin.sigs.rels", nOpenMode), uno::UNO_QUERY);
+ std::vector< uno::Sequence<beans::StringPair> > aRelations;
+ for (int i = 0; i < nSignatureCount; ++i)
+ {
+ std::vector<beans::StringPair> aRelation;
+ aRelation.emplace_back("Id", "rId" + OUString::number(i + 1));
+ aRelation.emplace_back("Type", OOXML_SIGNATURE_SIGNATURE);
+ aRelation.emplace_back("Target", "sig" + OUString::number(i + 1) + ".xml");
+ aRelations.push_back(comphelper::containerToSequence(aRelation));
+ }
+ comphelper::OFOPXMLHelper::WriteRelationsInfoSequence(xRelStream, comphelper::containerToSequence(aRelations), mxCtx);
+ uno::Reference<embed::XTransactedObject> xTransact(xSubStorage, uno::UNO_QUERY);
+ xTransact->commit();
+}
+
+void XMLSignatureHelper::ExportSignatureContentTypes(const css::uno::Reference<css::embed::XStorage>& xStorage, int nSignatureCount)
+{
+ uno::Reference<io::XStream> xStream = xStorage->openStreamElement("[Content_Types].xml", embed::ElementModes::READWRITE);
+ uno::Reference<io::XInputStream> xInputStream = xStream->getInputStream();
+ uno::Sequence< uno::Sequence<beans::StringPair> > aContentTypeInfo = comphelper::OFOPXMLHelper::ReadContentTypeSequence(xInputStream, mxCtx);
+ if (aContentTypeInfo.getLength() < 2)
+ {
+ SAL_WARN("xmlsecurity.helper", "no defaults or overrides in aContentTypeInfo");
+ return;
+ }
+ auto pContentTypeInfo = aContentTypeInfo.getArray();
+
+ // Append rels and sigs to defaults, if it's not there already.
+ uno::Sequence<beans::StringPair>& rDefaults = pContentTypeInfo[0];
+ auto aDefaults = comphelper::sequenceToContainer< std::vector<beans::StringPair> >(rDefaults);
+ if (std::none_of(std::cbegin(rDefaults), std::cend(rDefaults), [](const beans::StringPair& rPair) { return rPair.First == "rels"; }))
+ aDefaults.emplace_back("rels", "application/vnd.openxmlformats-package.relationships+xml");
+
+ if (std::none_of(std::cbegin(rDefaults), std::cend(rDefaults), [](const beans::StringPair& rPair) { return rPair.First == "sigs"; }))
+ aDefaults.emplace_back("sigs", "application/vnd.openxmlformats-package.digital-signature-origin");
+ rDefaults = comphelper::containerToSequence(aDefaults);
+
+ // Remove existing signature overrides.
+ uno::Sequence<beans::StringPair>& rOverrides = pContentTypeInfo[1];
+ auto aOverrides = comphelper::sequenceToContainer< std::vector<beans::StringPair> >(rOverrides);
+ aOverrides.erase(std::remove_if(aOverrides.begin(), aOverrides.end(), [](const beans::StringPair& rPair)
+ {
+ return rPair.First.startsWith("/_xmlsignatures/sig");
+ }), aOverrides.end());
+
+ // Add our signature overrides.
+ for (int i = 1; i <= nSignatureCount; ++i)
+ aOverrides.emplace_back("/_xmlsignatures/sig" + OUString::number(i) + ".xml", "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml");
+
+ rOverrides = comphelper::containerToSequence(aOverrides);
+ uno::Reference<io::XOutputStream> xOutputStream = xStream->getOutputStream();
+ uno::Reference <io::XTruncate> xTruncate(xOutputStream, uno::UNO_QUERY);
+ xTruncate->truncate();
+ comphelper::OFOPXMLHelper::WriteContentSequence(xOutputStream, rDefaults, rOverrides, mxCtx);
+ uno::Reference<embed::XTransactedObject> xTransact(xStorage, uno::UNO_QUERY);
+ xTransact->commit();
+}
+void XMLSignatureHelper::CreateAndWriteOOXMLSignature(const uno::Reference<embed::XStorage>& xRootStorage, const uno::Reference<embed::XStorage>& xSignatureStorage, int nSignatureIndex)
+{
+ uno::Reference<io::XOutputStream> xOutputStream(xSignatureStorage->openStreamElement("sig" + OUString::number(nSignatureIndex) + ".xml", embed::ElementModes::READWRITE), uno::UNO_QUERY);
+ uno::Reference<xml::sax::XWriter> xSaxWriter = xml::sax::Writer::create(mxCtx);
+ xSaxWriter->setOutputStream(xOutputStream);
+ xSaxWriter->startDocument();
+
+ mbError = false;
+ if (!mpXSecController->WriteOOXMLSignature(xRootStorage, xSaxWriter))
+ mbError = true;
+
+ xSaxWriter->endDocument();
+}
+
+/** check this constraint from xmldsig-core 4.5.4:
+
+ All certificates appearing in an X509Data element MUST relate to the
+ validation key by either containing it or being part of a certification
+ chain that terminates in a certificate containing the validation key.
+ */
+static auto CheckX509Data(
+ uno::Reference<xml::crypto::XSecurityEnvironment> const& xSecEnv,
+ std::vector<SignatureInformation::X509CertInfo> const& rX509CertInfos,
+ std::vector<uno::Reference<security::XCertificate>> & rCerts,
+ std::vector<SignatureInformation::X509CertInfo> & rSorted) -> bool
+{
+ assert(rCerts.empty());
+ assert(rSorted.empty());
+ if (rX509CertInfos.empty())
+ {
+ SAL_WARN("xmlsecurity.comp", "no X509Data");
+ return false;
+ }
+ std::vector<uno::Reference<security::XCertificate>> certs;
+ for (SignatureInformation::X509CertInfo const& it : rX509CertInfos)
+ {
+ if (!it.X509Certificate.isEmpty())
+ {
+ certs.emplace_back(xSecEnv->createCertificateFromAscii(it.X509Certificate));
+ }
+ else
+ {
+ certs.emplace_back(xSecEnv->getCertificate(
+ it.X509IssuerName,
+ xmlsecurity::numericStringToBigInteger(it.X509SerialNumber)));
+ }
+ if (!certs.back().is())
+ {
+ SAL_WARN("xmlsecurity.comp", "X509Data cannot be parsed");
+ return false;
+ }
+ }
+
+ // first, search one whose issuer isn't in the list, or a self-signed one
+ std::optional<size_t> start;
+ for (size_t i = 0; i < certs.size(); ++i)
+ {
+ for (size_t j = 0; ; ++j)
+ {
+ if (j == certs.size())
+ {
+ if (start)
+ {
+ SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate has no issuer but already have start of chain: " << certs[i]->getSubjectName());
+ return false;
+ }
+ start = i; // issuer isn't in the list
+ break;
+ }
+ if (xmlsecurity::EqualDistinguishedNames(certs[i]->getIssuerName(), certs[j]->getSubjectName(), xmlsecurity::NOCOMPAT))
+ {
+ if (i == j) // self signed
+ {
+ if (start)
+ {
+ SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate is self-signed but already have start of chain: " << certs[i]->getSubjectName());
+ return false;
+ }
+ start = i;
+ }
+ break;
+ }
+ }
+ }
+ std::vector<size_t> chain;
+ if (!start)
+ {
+ // this can only be a cycle?
+ SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: cycle detected");
+ return false;
+ }
+ chain.emplace_back(*start);
+
+ // second, check that there is a chain, no tree or cycle...
+ for (size_t i = 0; i < certs.size(); ++i)
+ {
+ assert(chain.size() == i + 1);
+ for (size_t j = 0; j < certs.size(); ++j)
+ {
+ if (chain[i] != j)
+ {
+ if (xmlsecurity::EqualDistinguishedNames(
+ certs[chain[i]]->getSubjectName(), certs[j]->getIssuerName(), xmlsecurity::NOCOMPAT))
+ {
+ if (chain.size() != i + 1) // already found issue?
+ {
+ SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate issued 2 others: " << certs[chain[i]]->getSubjectName());
+ return false;
+ }
+ chain.emplace_back(j);
+ }
+ }
+ }
+ if (i == certs.size() - 1)
+ { // last one: must be a leaf
+ if (chain.size() != i + 1)
+ {
+ SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate in cycle: " << certs[chain[i]]->getSubjectName());
+ return false;
+ }
+ }
+ else if (chain.size() != i + 2)
+ { // not issuer of another?
+ SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate issued 0 others: " << certs[chain[i]]->getSubjectName());
+ return false;
+ }
+ }
+
+ // success
+ assert(chain.size() == rX509CertInfos.size());
+ for (auto const& it : chain)
+ {
+ rSorted.emplace_back(rX509CertInfos[it]);
+ rCerts.emplace_back(certs[it]);
+ }
+ return true;
+}
+
+std::vector<uno::Reference<security::XCertificate>>
+XMLSignatureHelper::CheckAndUpdateSignatureInformation(
+ uno::Reference<xml::crypto::XSecurityEnvironment> const& xSecEnv,
+ SignatureInformation const& rInfo)
+{
+ // if the check fails, it's not possible to determine which X509Data
+ // contained the signing certificate - the UI cannot display something
+ // useful in this case, so prevent anything misleading by clearing the
+ // X509Datas.
+
+ std::vector<uno::Reference<security::XCertificate>> certs;
+ std::vector<SignatureInformation::X509Data> datas;
+ // TODO: for now, just merge all X509Datas together for checking...
+ // (this will probably break round-trip of signature with multiple X509Data,
+ // no idea if that is a problem)
+ SignatureInformation::X509Data temp;
+ SignatureInformation::X509Data tempResult;
+ for (auto const& rData : rInfo.X509Datas)
+ {
+ for (auto const& it : rData)
+ {
+ temp.emplace_back(it);
+ }
+ }
+ if (CheckX509Data(xSecEnv, temp, certs, tempResult))
+ {
+ datas.emplace_back(tempResult);
+ }
+
+ // rInfo is a copy, update the original
+ mpXSecController->UpdateSignatureInformation(rInfo.nSecurityId, std::move(datas));
+ return certs;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/helper/xsecctl.cxx b/xmlsecurity/source/helper/xsecctl.cxx
new file mode 100644
index 000000000..5a9bf57ec
--- /dev/null
+++ b/xmlsecurity/source/helper/xsecctl.cxx
@@ -0,0 +1,1004 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <config_gpgme.h>
+
+#include <xsecctl.hxx>
+#include <documentsignaturehelper.hxx>
+#include <framework/saxeventkeeperimpl.hxx>
+#include <xmlsec/xmldocumentwrapper_xmlsecimpl.hxx>
+#if HAVE_FEATURE_GPGME
+# include <gpg/xmlsignature_gpgimpl.hxx>
+#endif
+
+#include <com/sun/star/xml/crypto/sax/XMissionTaker.hpp>
+#include <com/sun/star/xml/crypto/SecurityOperationStatus.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/xml/sax/XParser.hpp>
+#include <com/sun/star/xml/crypto/XXMLSignature.hpp>
+
+#include <xmloff/attrlist.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ref.hxx>
+#include <sal/log.hxx>
+#include <unotools/datetime.hxx>
+#include "ooxmlsecexporter.hxx"
+#include <UriBindingHelper.hxx>
+
+using namespace com::sun::star;
+
+namespace
+{
+OUString getDigestURI(sal_Int32 nID)
+{
+ switch( nID )
+ {
+ case css::xml::crypto::DigestID::SHA1:
+ return ALGO_XMLDSIGSHA1;
+ case css::xml::crypto::DigestID::SHA256:
+ return ALGO_XMLDSIGSHA256;
+ case css::xml::crypto::DigestID::SHA512:
+ return ALGO_XMLDSIGSHA512;
+ default:
+ return ALGO_XMLDSIGSHA1;
+ }
+}
+OUString getSignatureURI(svl::crypto::SignatureMethodAlgorithm eAlgorithm, sal_Int32 nDigestID)
+{
+ OUString aRet;
+
+ if (eAlgorithm == svl::crypto::SignatureMethodAlgorithm::ECDSA)
+ {
+ switch (nDigestID)
+ {
+ case css::xml::crypto::DigestID::SHA1:
+ aRet = ALGO_ECDSASHA1;
+ break;
+ case css::xml::crypto::DigestID::SHA256:
+ aRet = ALGO_ECDSASHA256;
+ break;
+ case css::xml::crypto::DigestID::SHA512:
+ aRet = ALGO_ECDSASHA512;
+ break;
+ default:
+ aRet = ALGO_ECDSASHA1;
+ break;
+ }
+ }
+ if (!aRet.isEmpty())
+ return aRet;
+
+ switch (nDigestID)
+ {
+ case css::xml::crypto::DigestID::SHA1:
+ return ALGO_RSASHA1;
+ case css::xml::crypto::DigestID::SHA256:
+ return ALGO_RSASHA256;
+ case css::xml::crypto::DigestID::SHA512:
+ return ALGO_RSASHA512;
+ default:
+ return ALGO_RSASHA1;
+ }
+}
+}
+
+XSecController::XSecController( const css::uno::Reference<css::uno::XComponentContext>& rxCtx )
+ : mxCtx(rxCtx)
+ , m_nNextSecurityId(1)
+ , m_bIsPreviousNodeInitializable(false)
+ , m_bIsSAXEventKeeperConnected(false)
+ , m_bIsCollectingElement(false)
+ , m_bIsBlocking(false)
+ , m_eStatusOfSecurityComponents(InitializationState::UNINITIALIZED)
+ , m_bIsSAXEventKeeperSticky(false)
+ , m_nReservedSignatureId(0)
+ , m_bVerifyCurrentSignature(false)
+{
+}
+
+XSecController::~XSecController()
+{
+}
+
+
+/*
+ * private methods
+ */
+int XSecController::findSignatureInfor( sal_Int32 nSecurityId) const
+/****** XSecController/findSignatureInfor *************************************
+ *
+ * NAME
+ * findSignatureInfor -- find SignatureInformation struct for a particular
+ * signature
+ *
+ * SYNOPSIS
+ * index = findSignatureInfor( nSecurityId );
+ *
+ * INPUTS
+ * nSecurityId - the signature's id
+ *
+ * RESULT
+ * index - the index of the signature, or -1 when no such signature
+ * existing
+ ******************************************************************************/
+{
+ int i;
+ int size = m_vInternalSignatureInformations.size();
+
+ for (i=0; i<size; ++i)
+ {
+ if (m_vInternalSignatureInformations[i].signatureInfor.nSecurityId == nSecurityId)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+void XSecController::createXSecComponent( )
+/****** XSecController/createXSecComponent ************************************
+ *
+ * NAME
+ * bResult = createXSecComponent -- creates xml security components
+ *
+ * FUNCTION
+ * Creates xml security components, including:
+ * 1. an xml signature bridge component
+ * 2. an XMLDocumentWrapper component
+ * 3. a SAXEventKeeper component
+ ******************************************************************************/
+{
+ /*
+ * marks all security components are not available.
+ */
+ m_eStatusOfSecurityComponents = InitializationState::FAILTOINITIALIZED;
+ m_xXMLSignature = nullptr;
+ m_xXMLDocumentWrapper = nullptr;
+ m_xSAXEventKeeper = nullptr;
+
+ css::uno::Reference< css::lang::XMultiComponentFactory > xMCF( mxCtx->getServiceManager() );
+
+#if HAVE_FEATURE_GPGME
+ uno::Reference< lang::XServiceInfo > xServiceInfo( m_xSecurityContext, css::uno::UNO_QUERY );
+ if (xServiceInfo->getImplementationName() == "com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl")
+ m_xXMLSignature.set(new XMLSignature_GpgImpl());
+ else // xmlsec or mscrypt
+#endif
+ m_xXMLSignature.set(xMCF->createInstanceWithContext("com.sun.star.xml.crypto.XMLSignature", mxCtx), css::uno::UNO_QUERY);
+
+ bool bSuccess = m_xXMLSignature.is();
+ if ( bSuccess )
+ /*
+ * XMLSignature created successfully.
+ */
+ m_xXMLDocumentWrapper = new XMLDocumentWrapper_XmlSecImpl();
+
+ bSuccess &= m_xXMLDocumentWrapper.is();
+ if ( bSuccess )
+ m_xSAXEventKeeper = new SAXEventKeeperImpl();
+
+ bSuccess &= m_xSAXEventKeeper.is();
+
+ if (!bSuccess)
+ /*
+ * SAXEventKeeper created successfully.
+ */
+ return;
+
+ css::uno::Sequence <css::uno::Any> arg{ css::uno::Any(
+ uno::Reference<xml::wrapper::XXMLDocumentWrapper>(m_xXMLDocumentWrapper)) };
+ m_xSAXEventKeeper->initialize(arg);
+
+ css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >
+ xStatusChangeListener = this;
+
+ m_xSAXEventKeeper->addSAXEventKeeperStatusChangeListener( xStatusChangeListener );
+
+ m_eStatusOfSecurityComponents = InitializationState::INITIALIZED;
+}
+
+bool XSecController::chainOn()
+/****** XSecController/chainOn ************************************************
+ *
+ * NAME
+ * chainOn -- tries to connect the SAXEventKeeper with the SAX chain.
+ *
+ * SYNOPSIS
+ * bJustChainingOn = chainOn();
+ *
+ * FUNCTION
+ * First, checks whether the SAXEventKeeper is on the SAX chain. If not,
+ * creates xml security components, and chains the SAXEventKeeper into
+ * the SAX chain.
+ * Before being chained in, the SAXEventKeeper needs to receive all
+ * missed key SAX events, which can promise the DOM tree buffered by the
+ * SAXEventKeeper has the same structure with the original document.
+ *
+ * RESULT
+ * bJustChainingOn - whether the SAXEventKeeper is just chained into the
+ * SAX chain.
+ *
+ * NOTES
+ * Sometimes, the last key SAX event can't be transferred to the
+ * SAXEventKeeper together.
+ * For instance, at the time a referenced element is detected, the
+ * startElement event has already been reserved by the ElementStackKeeper.
+ * Meanwhile, an ElementCollector needs to be created before the
+ * SAXEventKeeper receives that startElement event.
+ * So for the SAXEventKeeper, it needs to receive all missed key SAX
+ * events except that startElement event, then adds a new
+ * ElementCollector, then receives that startElement event.
+ ******************************************************************************/
+{
+ bool rc = false;
+
+ if (!m_bIsSAXEventKeeperSticky && !m_bIsSAXEventKeeperConnected)
+ {
+ if ( m_eStatusOfSecurityComponents == InitializationState::UNINITIALIZED )
+ {
+ createXSecComponent();
+ }
+
+ if ( m_eStatusOfSecurityComponents == InitializationState::INITIALIZED )
+ /*
+ * if all security components are ready, chains on the SAXEventKeeper
+ */
+ {
+ /*
+ * disconnect the SAXEventKeeper with its current output handler,
+ * to make sure no SAX event is forwarded during the connecting
+ * phase.
+ */
+ m_xSAXEventKeeper->setNextHandler( nullptr );
+
+ css::uno::Reference< css::xml::sax::XDocumentHandler > xSEKHandler(m_xSAXEventKeeper);
+
+ /*
+ * connects the previous document handler on the SAX chain
+ */
+ if ( m_xPreviousNodeOnSAXChain.is() )
+ {
+ if ( m_bIsPreviousNodeInitializable )
+ {
+ css::uno::Reference< css::lang::XInitialization > xInitialization
+ (m_xPreviousNodeOnSAXChain, css::uno::UNO_QUERY);
+
+ xInitialization->initialize({ css::uno::Any(xSEKHandler) });
+ }
+ else
+ {
+ css::uno::Reference< css::xml::sax::XParser > xParser
+ (m_xPreviousNodeOnSAXChain, css::uno::UNO_QUERY);
+ xParser->setDocumentHandler( xSEKHandler );
+ }
+ }
+
+ /*
+ * connects the next document handler on the SAX chain
+ */
+ m_xSAXEventKeeper->setNextHandler(uno::Reference<xml::sax::XDocumentHandler>());
+
+ m_bIsSAXEventKeeperConnected = true;
+
+ rc = true;
+ }
+ }
+
+ return rc;
+}
+
+void XSecController::chainOff()
+/****** XSecController/chainOff ***********************************************
+ *
+ * NAME
+ * chainOff -- disconnects the SAXEventKeeper from the SAX chain.
+ ******************************************************************************/
+{
+ if (m_bIsSAXEventKeeperSticky )
+ return;
+
+ if (!m_bIsSAXEventKeeperConnected)
+ return;
+
+ m_xSAXEventKeeper->setNextHandler( nullptr );
+
+ if ( m_xPreviousNodeOnSAXChain.is() )
+ {
+ if ( m_bIsPreviousNodeInitializable )
+ {
+ css::uno::Reference< css::lang::XInitialization > xInitialization
+ (m_xPreviousNodeOnSAXChain, css::uno::UNO_QUERY);
+
+ css::uno::Sequence<css::uno::Any> aArgs{ css::uno::Any(
+ uno::Reference<xml::sax::XDocumentHandler>()) };
+ xInitialization->initialize(aArgs);
+ }
+ else
+ {
+ css::uno::Reference< css::xml::sax::XParser > xParser(m_xPreviousNodeOnSAXChain, css::uno::UNO_QUERY);
+ xParser->setDocumentHandler(uno::Reference<xml::sax::XDocumentHandler>());
+ }
+ }
+
+ m_bIsSAXEventKeeperConnected = false;
+}
+
+void XSecController::checkChainingStatus()
+/****** XSecController/checkChainingStatus ************************************
+ *
+ * NAME
+ * checkChainingStatus -- connects or disconnects the SAXEventKeeper
+ * according to the current situation.
+ *
+ * SYNOPSIS
+ * checkChainingStatus( );
+ *
+ * FUNCTION
+ * The SAXEventKeeper is chained into the SAX chain, when:
+ * 1. some element is being collected, or
+ * 2. the SAX event stream is blocking.
+ * Otherwise, chain off the SAXEventKeeper.
+ ******************************************************************************/
+{
+ if ( m_bIsCollectingElement || m_bIsBlocking )
+ {
+ chainOn();
+ }
+ else
+ {
+ chainOff();
+ }
+}
+
+void XSecController::initializeSAXChain()
+/****** XSecController/initializeSAXChain *************************************
+ *
+ * NAME
+ * initializeSAXChain -- initializes the SAX chain according to the
+ * current setting.
+ *
+ * FUNCTION
+ * Initializes the SAX chain, if the SAXEventKeeper is asked to be always
+ * on the SAX chain, chains it on. Otherwise, starts the
+ * ElementStackKeeper to reserve key SAX events.
+ ******************************************************************************/
+{
+ m_bIsSAXEventKeeperConnected = false;
+ m_bIsCollectingElement = false;
+ m_bIsBlocking = false;
+
+ chainOff();
+}
+
+css::uno::Reference< css::io::XInputStream >
+ XSecController::getObjectInputStream( const OUString& objectURL )
+/****** XSecController/getObjectInputStream ************************************
+ *
+ * NAME
+ * getObjectInputStream -- get a XInputStream interface from a SotStorage
+ *
+ * SYNOPSIS
+ * xInputStream = getObjectInputStream( objectURL );
+ *
+ * INPUTS
+ * objectURL - the object uri
+ *
+ * RESULT
+ * xInputStream - the XInputStream interface
+ ******************************************************************************/
+{
+ css::uno::Reference< css::io::XInputStream > xObjectInputStream;
+
+ SAL_WARN_IF( !m_xUriBinding.is(), "xmlsecurity.helper", "Need XUriBinding!" );
+
+ xObjectInputStream = m_xUriBinding->getUriBinding(objectURL);
+
+ return xObjectInputStream;
+}
+
+/*
+ * public methods
+ */
+
+sal_Int32 XSecController::getNewSecurityId( )
+{
+ sal_Int32 nId = m_nNextSecurityId;
+ m_nNextSecurityId++;
+ return nId;
+}
+
+void XSecController::startMission(const rtl::Reference<UriBindingHelper>& xUriBinding, const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& xSecurityContext )
+/****** XSecController/startMission *******************************************
+ *
+ * NAME
+ * startMission -- starts a new security mission.
+ *
+ * FUNCTION
+ * get ready for a new mission.
+ *
+ * INPUTS
+ * xUriBinding - the Uri binding that provide maps between uris and
+ * XInputStreams
+ * xSecurityContext - the security context component which can provide
+ * cryptoken
+ ******************************************************************************/
+{
+ m_xUriBinding = xUriBinding;
+
+ m_eStatusOfSecurityComponents = InitializationState::UNINITIALIZED;
+ m_xSecurityContext = xSecurityContext;
+
+ m_vInternalSignatureInformations.clear();
+
+ m_bVerifyCurrentSignature = false;
+}
+
+void XSecController::setSAXChainConnector(const css::uno::Reference< css::lang::XInitialization >& xInitialization)
+/****** XSecController/setSAXChainConnector ***********************************
+ *
+ * NAME
+ * setSAXChainConnector -- configures the components which will
+ * collaborate with the SAXEventKeeper on the SAX chain.
+ *
+ * SYNOPSIS
+ * setSAXChainConnector(xInitialization);
+ *
+ * INPUTS
+ * xInitialization - the previous node on the SAX chain
+ ******************************************************************************/
+{
+ m_bIsPreviousNodeInitializable = true;
+ m_xPreviousNodeOnSAXChain = xInitialization;
+
+ initializeSAXChain( );
+}
+
+void XSecController::clearSAXChainConnector()
+/****** XSecController/clearSAXChainConnector *********************************
+ *
+ * NAME
+ * clearSAXChainConnector -- resets the collaborating components.
+ ******************************************************************************/
+{
+ chainOff();
+
+ m_xPreviousNodeOnSAXChain = nullptr;
+}
+
+void XSecController::endMission()
+/****** XSecController/endMission *********************************************
+ *
+ * NAME
+ * endMission -- forces to end all missions
+ *
+ * FUNCTION
+ * Deletes all signature information and forces all missions to an end.
+ ******************************************************************************/
+{
+ sal_Int32 size = m_vInternalSignatureInformations.size();
+
+ for (int i=0; i<size; ++i)
+ {
+ if ( m_eStatusOfSecurityComponents == InitializationState::INITIALIZED )
+ /*
+ * ResolvedListener only exist when the security components are created.
+ */
+ {
+ css::uno::Reference< css::xml::crypto::sax::XMissionTaker > xMissionTaker
+ ( m_vInternalSignatureInformations[i].xReferenceResolvedListener, css::uno::UNO_QUERY );
+
+ /*
+ * asks the SignatureCreator/SignatureVerifier to release
+ * all resources it uses.
+ */
+ xMissionTaker->endMission();
+ }
+ }
+
+ m_xUriBinding = nullptr;
+ m_xSecurityContext = nullptr;
+
+ /*
+ * free the status change listener reference to this object
+ */
+ if (m_xSAXEventKeeper.is())
+ m_xSAXEventKeeper->addSAXEventKeeperStatusChangeListener( nullptr );
+}
+
+namespace
+{
+void writeUnsignedProperties(
+ const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler,
+ const SignatureInformation& signatureInfo)
+{
+ {
+ rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList());
+ pAttributeList->AddAttribute("Id", "idUnsignedProperties_" + signatureInfo.ouSignatureId);
+ xDocumentHandler->startElement("xd:UnsignedProperties", uno::Reference<xml::sax::XAttributeList>(pAttributeList));
+ }
+
+ {
+ xDocumentHandler->startElement("xd:UnsignedSignatureProperties", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+
+ {
+ xDocumentHandler->startElement("xd:CertificateValues", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+
+ {
+ for (const auto& i: signatureInfo.maEncapsulatedX509Certificates)
+ {
+ xDocumentHandler->startElement("xd:EncapsulatedX509Certificate", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList()));
+ xDocumentHandler->characters(i);
+ xDocumentHandler->endElement("xd:EncapsulatedX509Certificate");
+ }
+ }
+
+ xDocumentHandler->endElement("xd:CertificateValues");
+ }
+
+ xDocumentHandler->endElement("xd:UnsignedSignatureProperties");
+ }
+
+ xDocumentHandler->endElement("xd:UnsignedProperties");
+}
+
+}
+
+void XSecController::exportSignature(
+ const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler,
+ const SignatureInformation& signatureInfo,
+ bool bXAdESCompliantIfODF )
+/****** XSecController/exportSignature ****************************************
+ *
+ * NAME
+ * exportSignature -- export a signature structure to an XDocumentHandler
+ *
+ * SYNOPSIS
+ * exportSignature( xDocumentHandler, signatureInfo);
+ *
+ * INPUTS
+ * xDocumentHandler - the document handler to receive the signature
+ * signatureInfo - signature to be exported
+ ******************************************************************************/
+{
+ const SignatureReferenceInformations& vReferenceInfors = signatureInfo.vSignatureReferenceInfors;
+ rtl::Reference<SvXMLAttributeList> pAttributeList;
+
+ /*
+ * Write Signature element
+ */
+ pAttributeList = new SvXMLAttributeList();
+ pAttributeList->AddAttribute(
+ "xmlns",
+ NS_XMLDSIG);
+
+ if (!signatureInfo.ouSignatureId.isEmpty())
+ {
+ pAttributeList->AddAttribute(
+ "Id",
+ signatureInfo.ouSignatureId);
+ }
+
+ xDocumentHandler->startElement( "Signature", pAttributeList);
+ {
+ /* Write SignedInfo element */
+ xDocumentHandler->startElement(
+ "SignedInfo",
+ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList()));
+ {
+ /* Write CanonicalizationMethod element */
+ pAttributeList = new SvXMLAttributeList();
+ pAttributeList->AddAttribute(
+ "Algorithm",
+ ALGO_C14N);
+ xDocumentHandler->startElement( "CanonicalizationMethod", pAttributeList );
+ xDocumentHandler->endElement( "CanonicalizationMethod" );
+
+ /* Write SignatureMethod element */
+ pAttributeList = new SvXMLAttributeList();
+
+ // TODO: actually roundtrip this value from parsing documentsignatures.xml - entirely
+ // broken to assume this would in any way relate to the 1st reference's digest algo
+
+ // Assume that all Reference elements use the same DigestMethod:Algorithm, and that the
+ // SignatureMethod:Algorithm should be the corresponding one.
+ pAttributeList->AddAttribute(
+ "Algorithm",
+ getSignatureURI(signatureInfo.eAlgorithmID, vReferenceInfors[0].nDigestID));
+ xDocumentHandler->startElement( "SignatureMethod", pAttributeList );
+ xDocumentHandler->endElement( "SignatureMethod" );
+
+ /* Write Reference element */
+ int j;
+ int refNum = vReferenceInfors.size();
+
+ for(j=0; j<refNum; ++j)
+ {
+ const SignatureReferenceInformation& refInfor = vReferenceInfors[j];
+
+ pAttributeList = new SvXMLAttributeList();
+ if ( refInfor.nType != SignatureReferenceType::SAMEDOCUMENT )
+ /*
+ * stream reference
+ */
+ {
+ pAttributeList->AddAttribute(
+ "URI",
+ refInfor.ouURI);
+ }
+ else
+ /*
+ * same-document reference
+ */
+ {
+ if (refInfor.ouURI.startsWith("idSignedProperties"))
+ {
+ pAttributeList->AddAttribute("URI", "#idSignedProperties_" + signatureInfo.ouSignatureId);
+ if (bXAdESCompliantIfODF && !refInfor.ouType.isEmpty())
+ {
+ // The reference which points to the SignedProperties
+ // shall have this specific type.
+ pAttributeList->AddAttribute("Type", refInfor.ouType);
+ }
+ }
+ else
+ {
+ pAttributeList->AddAttribute(
+ "URI",
+ "#" + refInfor.ouURI);
+ }
+ }
+
+ xDocumentHandler->startElement( "Reference", pAttributeList );
+ {
+ /* Write Transforms element */
+ if (refInfor.nType == SignatureReferenceType::XMLSTREAM)
+ /*
+ * xml stream, so c14n transform is needed
+ */
+ {
+ xDocumentHandler->startElement(
+ "Transforms",
+ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList()));
+ {
+ pAttributeList = new SvXMLAttributeList();
+ pAttributeList->AddAttribute(
+ "Algorithm",
+ ALGO_C14N);
+ xDocumentHandler->startElement(
+ "Transform",
+ pAttributeList );
+ xDocumentHandler->endElement( "Transform" );
+ }
+ xDocumentHandler->endElement( "Transforms" );
+ }
+
+ /* Write DigestMethod element */
+ pAttributeList = new SvXMLAttributeList();
+ pAttributeList->AddAttribute(
+ "Algorithm",
+ getDigestURI(refInfor.nDigestID));
+ xDocumentHandler->startElement(
+ "DigestMethod",
+ pAttributeList );
+ xDocumentHandler->endElement( "DigestMethod" );
+
+ /* Write DigestValue element */
+ xDocumentHandler->startElement(
+ "DigestValue",
+ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList()));
+ xDocumentHandler->characters( refInfor.ouDigestValue );
+ xDocumentHandler->endElement( "DigestValue" );
+ }
+ xDocumentHandler->endElement( "Reference" );
+ }
+ }
+ xDocumentHandler->endElement( "SignedInfo" );
+
+ /* Write SignatureValue element */
+ xDocumentHandler->startElement(
+ "SignatureValue",
+ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList()));
+ xDocumentHandler->characters( signatureInfo.ouSignatureValue );
+ xDocumentHandler->endElement( "SignatureValue" );
+
+ /* Write KeyInfo element */
+ xDocumentHandler->startElement(
+ "KeyInfo",
+ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList()));
+ {
+ // GPG or X509 key?
+ if (!signatureInfo.ouGpgCertificate.isEmpty())
+ {
+ pAttributeList = new SvXMLAttributeList();
+ pAttributeList->AddAttribute("xmlns:loext", NS_LOEXT);
+ /* Write PGPData element */
+ xDocumentHandler->startElement(
+ "PGPData",
+ pAttributeList);
+ {
+ /* Write keyid element */
+ xDocumentHandler->startElement(
+ "PGPKeyID",
+ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList()));
+ xDocumentHandler->characters(signatureInfo.ouGpgKeyID);
+ xDocumentHandler->endElement( "PGPKeyID" );
+
+ /* Write PGPKeyPacket element */
+ if (!signatureInfo.ouGpgCertificate.isEmpty())
+ {
+ xDocumentHandler->startElement(
+ "PGPKeyPacket",
+ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList()));
+ xDocumentHandler->characters( signatureInfo.ouGpgCertificate );
+ xDocumentHandler->endElement( "PGPKeyPacket" );
+ }
+
+ /* Write PGPOwner element */
+ xDocumentHandler->startElement(
+ "loext:PGPOwner",
+ css::uno::Reference< css::xml::sax::XAttributeList >(new SvXMLAttributeList()));
+ xDocumentHandler->characters( signatureInfo.ouGpgOwner );
+ xDocumentHandler->endElement( "loext:PGPOwner" );
+ }
+ xDocumentHandler->endElement( "PGPData" );
+ }
+ else
+ {
+ assert(signatureInfo.GetSigningCertificate());
+ for (auto const& rData : signatureInfo.X509Datas)
+ {
+ /* Write X509Data element */
+ xDocumentHandler->startElement(
+ "X509Data",
+ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList()));
+ {
+ for (auto const& it : rData)
+ {
+ /* Write X509IssuerSerial element */
+ xDocumentHandler->startElement(
+ "X509IssuerSerial",
+ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList()));
+ {
+ /* Write X509IssuerName element */
+ xDocumentHandler->startElement(
+ "X509IssuerName",
+ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList()));
+ xDocumentHandler->characters(it.X509IssuerName);
+ xDocumentHandler->endElement( "X509IssuerName" );
+
+ /* Write X509SerialNumber element */
+ xDocumentHandler->startElement(
+ "X509SerialNumber",
+ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList()));
+ xDocumentHandler->characters(it.X509SerialNumber);
+ xDocumentHandler->endElement( "X509SerialNumber" );
+ }
+ xDocumentHandler->endElement( "X509IssuerSerial" );
+
+ /* Write X509Certificate element */
+ if (!it.X509Certificate.isEmpty())
+ {
+ xDocumentHandler->startElement(
+ "X509Certificate",
+ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList()));
+ xDocumentHandler->characters(it.X509Certificate);
+ xDocumentHandler->endElement( "X509Certificate" );
+ }
+ }
+ }
+ xDocumentHandler->endElement( "X509Data" );
+ }
+ }
+ }
+ xDocumentHandler->endElement( "KeyInfo" );
+
+ OUString sDate;
+
+ /* Write Object element */
+ xDocumentHandler->startElement(
+ "Object",
+ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList()));
+ {
+ /* Write SignatureProperties element */
+ xDocumentHandler->startElement(
+ "SignatureProperties",
+ css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList()));
+ {
+ /* Write SignatureProperty element */
+ pAttributeList = new SvXMLAttributeList();
+ pAttributeList->AddAttribute(
+ "Id",
+ signatureInfo.ouDateTimePropertyId);
+ pAttributeList->AddAttribute(
+ "Target",
+ "#" + signatureInfo.ouSignatureId);
+ xDocumentHandler->startElement(
+ "SignatureProperty",
+ pAttributeList);
+ {
+ /* Write timestamp element */
+
+ pAttributeList = new SvXMLAttributeList();
+ pAttributeList->AddAttribute(
+ "xmlns:dc",
+ NS_DC);
+
+ xDocumentHandler->startElement(
+ "dc:date",
+ pAttributeList);
+
+ OUStringBuffer buffer;
+ //If the xml signature was already contained in the document,
+ //then we use the original date and time string, rather than the
+ //converted one. This avoids writing a different string due to
+ //e.g. rounding issues and thus breaking the signature.
+ if (!signatureInfo.ouDateTime.isEmpty())
+ buffer = signatureInfo.ouDateTime;
+ else
+ {
+ buffer = utl::toISO8601(signatureInfo.stDateTime);
+ // xsd:dateTime must use period as separator for fractional seconds, while
+ // utl::toISO8601 uses comma (as allowed, and even recommended, by ISO8601).
+ buffer.replace(',', '.');
+ }
+ sDate = buffer.makeStringAndClear();
+ xDocumentHandler->characters( sDate );
+
+ xDocumentHandler->endElement(
+ "dc:date");
+ }
+ xDocumentHandler->endElement( "SignatureProperty" );
+ }
+
+ // Write signature description.
+ if (!signatureInfo.ouDescription.isEmpty())
+ {
+ // SignatureProperty element.
+ pAttributeList = new SvXMLAttributeList();
+ pAttributeList->AddAttribute("Id", signatureInfo.ouDescriptionPropertyId);
+ pAttributeList->AddAttribute("Target", "#" + signatureInfo.ouSignatureId);
+ xDocumentHandler->startElement("SignatureProperty", pAttributeList);
+
+ {
+ // Description element.
+ pAttributeList = new SvXMLAttributeList();
+ pAttributeList->AddAttribute("xmlns:dc", NS_DC);
+
+ xDocumentHandler->startElement("dc:description", pAttributeList);
+ xDocumentHandler->characters(signatureInfo.ouDescription);
+ xDocumentHandler->endElement("dc:description");
+ }
+
+ xDocumentHandler->endElement("SignatureProperty");
+ }
+
+ xDocumentHandler->endElement( "SignatureProperties" );
+ }
+ xDocumentHandler->endElement( "Object" );
+
+ // In XAdES, write another Object element for the QualifyingProperties
+ if (bXAdESCompliantIfODF)
+ {
+ pAttributeList = new SvXMLAttributeList();
+ pAttributeList->AddAttribute("xmlns:xd", NS_XD);
+ xDocumentHandler->startElement(
+ "Object",
+ pAttributeList);
+ {
+ pAttributeList = new SvXMLAttributeList();
+ pAttributeList->AddAttribute("Target", "#" + signatureInfo.ouSignatureId);
+ xDocumentHandler->startElement(
+ "xd:QualifyingProperties",
+ pAttributeList);
+ DocumentSignatureHelper::writeSignedProperties(xDocumentHandler, signatureInfo, sDate, true);
+ writeUnsignedProperties(xDocumentHandler, signatureInfo);
+ xDocumentHandler->endElement( "xd:QualifyingProperties" );
+ }
+ xDocumentHandler->endElement( "Object" );
+ }
+ }
+ xDocumentHandler->endElement( "Signature" );
+}
+
+void XSecController::exportOOXMLSignature(const uno::Reference<embed::XStorage>& xRootStorage, const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler, const SignatureInformation& rInformation)
+{
+ OOXMLSecExporter aExporter(mxCtx, xRootStorage, xDocumentHandler, rInformation);
+ aExporter.writeSignature();
+}
+
+void XSecController::UpdateSignatureInformation(sal_Int32 const nSecurityId,
+ std::vector<SignatureInformation::X509Data> && rDatas)
+{
+ int const nIndex = findSignatureInfor(nSecurityId);
+ assert(nIndex != -1); // nothing should touch this between parsing and verify
+ m_vInternalSignatureInformations[nIndex].signatureInfor.X509Datas = std::move(rDatas);
+}
+
+SignatureInformation XSecController::getSignatureInformation( sal_Int32 nSecurityId ) const
+{
+ SignatureInformation aInf( 0 );
+ int nIndex = findSignatureInfor(nSecurityId);
+ SAL_WARN_IF( nIndex == -1, "xmlsecurity.helper", "getSignatureInformation - SecurityId is invalid!" );
+ if ( nIndex != -1)
+ {
+ aInf = m_vInternalSignatureInformations[nIndex].signatureInfor;
+ }
+ return aInf;
+}
+
+SignatureInformations XSecController::getSignatureInformations() const
+{
+ SignatureInformations vInfors;
+ int sigNum = m_vInternalSignatureInformations.size();
+
+ for (int i=0; i<sigNum; ++i)
+ {
+ SignatureInformation si = m_vInternalSignatureInformations[i].signatureInfor;
+ vInfors.push_back(si);
+ }
+
+ return vInfors;
+}
+
+/*
+ * XSAXEventKeeperStatusChangeListener
+ */
+
+void SAL_CALL XSecController::blockingStatusChanged( sal_Bool isBlocking )
+{
+ m_bIsBlocking = isBlocking;
+ checkChainingStatus();
+}
+
+void SAL_CALL XSecController::collectionStatusChanged(
+ sal_Bool isInsideCollectedElement )
+{
+ m_bIsCollectingElement = isInsideCollectedElement;
+ checkChainingStatus();
+}
+
+void SAL_CALL XSecController::bufferStatusChanged( sal_Bool /*isBufferEmpty*/)
+{
+
+}
+
+/*
+ * XSignatureCreationResultListener
+ */
+void SAL_CALL XSecController::signatureCreated( sal_Int32 securityId, css::xml::crypto::SecurityOperationStatus nResult )
+{
+ int index = findSignatureInfor(securityId);
+ assert(index != -1 && "Signature Not Found!");
+ SignatureInformation& signatureInfor = m_vInternalSignatureInformations.at(index).signatureInfor;
+ signatureInfor.nStatus = nResult;
+}
+
+/*
+ * XSignatureVerifyResultListener
+ */
+void SAL_CALL XSecController::signatureVerified( sal_Int32 securityId, css::xml::crypto::SecurityOperationStatus nResult )
+{
+ int index = findSignatureInfor(securityId);
+ assert(index != -1 && "Signature Not Found!");
+ SignatureInformation& signatureInfor = m_vInternalSignatureInformations.at(index).signatureInfor;
+ signatureInfor.nStatus = nResult;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/helper/xsecparser.cxx b/xmlsecurity/source/helper/xsecparser.cxx
new file mode 100644
index 000000000..af3562f46
--- /dev/null
+++ b/xmlsecurity/source/helper/xsecparser.cxx
@@ -0,0 +1,1632 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include "xsecparser.hxx"
+#include <xsecctl.hxx>
+#include <xmlsignaturehelper.hxx>
+
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltkmap.hxx>
+#include <xmloff/xmlimp.hxx>
+
+#include <com/sun/star/xml/sax/SAXException.hpp>
+#include <cppuhelper/exc_hlp.hxx>
+#include <sal/log.hxx>
+
+class XSecParser::Context
+{
+ protected:
+ friend class XSecParser;
+ XSecParser & m_rParser;
+ private:
+ std::optional<SvXMLNamespaceMap> m_pOldNamespaceMap;
+
+ public:
+ Context(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : m_rParser(rParser)
+ , m_pOldNamespaceMap(std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual ~Context() = default;
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/)
+ {
+ }
+
+ virtual void EndElement()
+ {
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/);
+
+ virtual void Characters(OUString const& /*rChars*/)
+ {
+ }
+};
+
+// it's possible that an unsupported element has an Id attribute and a
+// ds:Reference digesting it - probably this means XSecController needs to know
+// about it. (For known elements, the Id attribute is only processed according
+// to the schema.)
+class XSecParser::UnknownContext
+ : public XSecParser::Context
+{
+ public:
+ UnknownContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ m_rParser.HandleIdAttr(xAttrs);
+ }
+};
+
+auto XSecParser::Context::CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/)
+-> std::unique_ptr<Context>
+{
+ // default: create new base context
+ return std::make_unique<UnknownContext>(m_rParser, std::move(pOldNamespaceMap));
+}
+
+/**
+note: anything in ds:Object should be trusted *only* if there is a ds:Reference
+ to it so it is signed (exception: the xades:EncapsulatedX509Certificate).
+ ds:SignedInfo precedes all ds:Object.
+
+ There may be multiple ds:Signature for purpose of counter-signatures
+ but the way XAdES describes these, only the ds:SignatureValue element
+ would be referenced, so requiring a ds:Reference for anything in
+ ds:Object shouldn't cause issues.
+ */
+class XSecParser::ReferencedContextImpl
+ : public XSecParser::Context
+{
+ protected:
+ bool m_isReferenced;
+
+ public:
+ ReferencedContextImpl(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_isReferenced(isReferenced)
+ {
+ }
+
+ OUString CheckIdAttrReferenced(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs)
+ {
+ OUString const id(m_rParser.HandleIdAttr(xAttrs));
+ if (!id.isEmpty() && m_rParser.m_pXSecController->haveReferenceForId(id))
+ {
+ m_isReferenced = true;
+ }
+ return id;
+ }
+};
+
+class XSecParser::LoPGPOwnerContext
+ : public XSecParser::Context
+{
+ private:
+ OUString m_Value;
+
+ public:
+ LoPGPOwnerContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void EndElement() override
+ {
+ m_rParser.m_pXSecController->setGpgOwner(m_Value);
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_Value += rChars;
+ }
+};
+
+class XSecParser::DsPGPKeyPacketContext
+ : public XSecParser::Context
+{
+ private:
+ OUString m_Value;
+
+ public:
+ DsPGPKeyPacketContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void EndElement() override
+ {
+ m_rParser.m_pXSecController->setGpgCertificate(m_Value);
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_Value += rChars;
+ }
+};
+
+class XSecParser::DsPGPKeyIDContext
+ : public XSecParser::Context
+{
+ private:
+ OUString m_Value;
+
+ public:
+ DsPGPKeyIDContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void EndElement() override
+ {
+ m_rParser.m_pXSecController->setGpgKeyID(m_Value);
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_Value += rChars;
+ }
+};
+
+class XSecParser::DsPGPDataContext
+ : public XSecParser::Context
+{
+ public:
+ DsPGPDataContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/) override
+ {
+ m_rParser.m_pXSecController->switchGpgSignature();
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "PGPKeyID")
+ {
+ return std::make_unique<DsPGPKeyIDContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "PGPKeyPacket")
+ {
+ return std::make_unique<DsPGPKeyPacketContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "PGPOwner")
+ {
+ return std::make_unique<LoPGPOwnerContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::DsX509CertificateContext
+ : public XSecParser::Context
+{
+ private:
+ OUString & m_rValue;
+
+ public:
+ DsX509CertificateContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString& rValue)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rValue(rValue)
+ {
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_rValue += rChars;
+ }
+};
+
+class XSecParser::DsX509SerialNumberContext
+ : public XSecParser::Context
+{
+ private:
+ OUString & m_rValue;
+
+ public:
+ DsX509SerialNumberContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString& rValue)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rValue(rValue)
+ {
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_rValue += rChars;
+ }
+};
+
+class XSecParser::DsX509IssuerNameContext
+ : public XSecParser::Context
+{
+ private:
+ OUString & m_rValue;
+
+ public:
+ DsX509IssuerNameContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString& rValue)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rValue(rValue)
+ {
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_rValue += rChars;
+ }
+};
+
+class XSecParser::DsX509IssuerSerialContext
+ : public XSecParser::Context
+{
+ private:
+ OUString & m_rX509IssuerName;
+ OUString & m_rX509SerialNumber;
+
+ public:
+ DsX509IssuerSerialContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString& rIssuerName, OUString& rSerialNumber)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rX509IssuerName(rIssuerName)
+ , m_rX509SerialNumber(rSerialNumber)
+ {
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerName")
+ {
+ return std::make_unique<DsX509IssuerNameContext>(m_rParser, std::move(pOldNamespaceMap), m_rX509IssuerName);
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "X509SerialNumber")
+ {
+ return std::make_unique<DsX509SerialNumberContext>(m_rParser, std::move(pOldNamespaceMap), m_rX509SerialNumber);
+ }
+ // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+/// can't be sure what is supposed to happen here because the spec is clear as mud
+class XSecParser::DsX509DataContext
+ : public XSecParser::Context
+{
+ private:
+ // sigh... "No ordering is implied by the above constraints."
+ // so store the ball of mud in vectors and try to figure it out later.
+ std::vector<std::pair<OUString, OUString>> m_X509IssuerSerials;
+ std::vector<OUString> m_X509Certificates;
+
+ public:
+ DsX509DataContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void EndElement() override
+ {
+ m_rParser.m_pXSecController->setX509Data(m_X509IssuerSerials, m_X509Certificates);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerSerial")
+ {
+ m_X509IssuerSerials.emplace_back();
+ return std::make_unique<DsX509IssuerSerialContext>(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerSerials.back().first, m_X509IssuerSerials.back().second);
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "X509Certificate")
+ {
+ m_X509Certificates.emplace_back();
+ return std::make_unique<DsX509CertificateContext>(m_rParser, std::move(pOldNamespaceMap), m_X509Certificates.back());
+ }
+ // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::DsKeyInfoContext
+ : public XSecParser::Context
+{
+ public:
+ DsKeyInfoContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ m_rParser.HandleIdAttr(xAttrs);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "X509Data")
+ {
+ return std::make_unique<DsX509DataContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "PGPData")
+ {
+ return std::make_unique<DsPGPDataContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ // missing: ds:KeyName, ds:KeyValue, ds:RetrievalMethod, ds:SPKIData, ds:MgmtData
+ // (old code would read ds:Transform inside ds:RetrievalMethod but
+ // presumably that was a bug)
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+
+};
+
+class XSecParser::DsSignatureValueContext
+ : public XSecParser::Context
+{
+ private:
+ OUString m_Value;
+
+ public:
+ DsSignatureValueContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ m_rParser.HandleIdAttr(xAttrs);
+ }
+
+ virtual void EndElement() override
+ {
+ m_rParser.m_pXSecController->setSignatureValue(m_Value);
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_Value += rChars;
+ }
+};
+
+class XSecParser::DsDigestValueContext
+ : public XSecParser::Context
+{
+ private:
+ OUString & m_rValue;
+
+ public:
+ DsDigestValueContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString& rValue)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rValue(rValue)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/) override
+ {
+ m_rValue.clear();
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_rValue += rChars;
+ }
+};
+
+class XSecParser::DsDigestMethodContext
+ : public XSecParser::Context
+{
+ private:
+ sal_Int32 & m_rReferenceDigestID;
+
+ public:
+ DsDigestMethodContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_Int32& rReferenceDigestID)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rReferenceDigestID(rReferenceDigestID)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ OUString ouAlgorithm = xAttrs->getValueByName("Algorithm");
+
+ SAL_WARN_IF( ouAlgorithm.isEmpty(), "xmlsecurity.helper", "no Algorithm in Reference" );
+ if (ouAlgorithm.isEmpty())
+ return;
+
+ SAL_WARN_IF( ouAlgorithm != ALGO_XMLDSIGSHA1
+ && ouAlgorithm != ALGO_XMLDSIGSHA256
+ && ouAlgorithm != ALGO_XMLDSIGSHA512,
+ "xmlsecurity.helper", "Algorithm neither SHA1, SHA256 nor SHA512");
+ if (ouAlgorithm == ALGO_XMLDSIGSHA1)
+ m_rReferenceDigestID = css::xml::crypto::DigestID::SHA1;
+ else if (ouAlgorithm == ALGO_XMLDSIGSHA256)
+ m_rReferenceDigestID = css::xml::crypto::DigestID::SHA256;
+ else if (ouAlgorithm == ALGO_XMLDSIGSHA512)
+ m_rReferenceDigestID = css::xml::crypto::DigestID::SHA512;
+ else
+ m_rReferenceDigestID = 0;
+ }
+};
+
+class XSecParser::DsTransformContext
+ : public XSecParser::Context
+{
+ private:
+ bool & m_rIsC14N;
+
+ public:
+ DsTransformContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool& rIsC14N)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rIsC14N(rIsC14N)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ OUString ouAlgorithm = xAttrs->getValueByName("Algorithm");
+
+ if (ouAlgorithm == ALGO_C14N)
+ /*
+ * a xml stream
+ */
+ {
+ m_rIsC14N = true;
+ }
+ }
+};
+
+class XSecParser::DsTransformsContext
+ : public XSecParser::Context
+{
+ private:
+ bool & m_rIsC14N;
+
+ public:
+ DsTransformsContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool& rIsC14N)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rIsC14N(rIsC14N)
+ {
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "Transform")
+ {
+ return std::make_unique<DsTransformContext>(m_rParser, std::move(pOldNamespaceMap), m_rIsC14N);
+ }
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::DsReferenceContext
+ : public XSecParser::Context
+{
+ private:
+ OUString m_URI;
+ OUString m_Type;
+ OUString m_DigestValue;
+ bool m_IsC14N = false;
+ // Relevant for ODF. The digest algorithm selected by the DigestMethod
+ // element's Algorithm attribute. @see css::xml::crypto::DigestID.
+ sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA1;
+
+ public:
+ DsReferenceContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ m_rParser.HandleIdAttr(xAttrs);
+
+ m_URI = xAttrs->getValueByName("URI");
+ SAL_WARN_IF(m_URI.isEmpty(), "xmlsecurity.helper", "URI is empty");
+ // Remember the type of this reference.
+ m_Type = xAttrs->getValueByName("Type");
+ }
+
+ virtual void EndElement() override
+ {
+ if (m_URI.startsWith("#"))
+ {
+ /*
+ * remove the first character '#' from the attribute value
+ */
+ m_rParser.m_pXSecController->addReference(m_URI.copy(1), m_nReferenceDigestID, m_Type);
+ }
+ else
+ {
+ if (m_IsC14N) // this is determined by nested ds:Transform
+ {
+ m_rParser.m_pXSecController->addStreamReference(m_URI, false, m_nReferenceDigestID);
+ }
+ else
+ /*
+ * it must be an octet stream
+ */
+ {
+ m_rParser.m_pXSecController->addStreamReference(m_URI, true, m_nReferenceDigestID);
+ }
+ }
+
+ m_rParser.m_pXSecController->setDigestValue(m_nReferenceDigestID, m_DigestValue);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "Transforms")
+ {
+ return std::make_unique<DsTransformsContext>(m_rParser, std::move(pOldNamespaceMap), m_IsC14N);
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod")
+ {
+ return std::make_unique<DsDigestMethodContext>(m_rParser, std::move(pOldNamespaceMap), m_nReferenceDigestID);
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue")
+ {
+ return std::make_unique<DsDigestValueContext>(m_rParser, std::move(pOldNamespaceMap), m_DigestValue);
+ }
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::DsSignatureMethodContext
+ : public XSecParser::Context
+{
+ public:
+ DsSignatureMethodContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ OUString ouAlgorithm = xAttrs->getValueByName("Algorithm");
+ if (ouAlgorithm == ALGO_ECDSASHA1 || ouAlgorithm == ALGO_ECDSASHA256
+ || ouAlgorithm == ALGO_ECDSASHA512)
+ {
+ m_rParser.m_pXSecController->setSignatureMethod(svl::crypto::SignatureMethodAlgorithm::ECDSA);
+ }
+ }
+};
+
+class XSecParser::DsSignedInfoContext
+ : public XSecParser::Context
+{
+ public:
+ DsSignedInfoContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ m_rParser.HandleIdAttr(xAttrs);
+ }
+
+ virtual void EndElement() override
+ {
+ m_rParser.m_pXSecController->setReferenceCount();
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureMethod")
+ {
+ return std::make_unique<DsSignatureMethodContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "Reference")
+ {
+ return std::make_unique<DsReferenceContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ // missing: ds:CanonicalizationMethod
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::XadesEncapsulatedX509CertificateContext
+ : public XSecParser::Context
+{
+ private:
+ OUString m_Value;
+
+ public:
+ XadesEncapsulatedX509CertificateContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ m_rParser.HandleIdAttr(xAttrs);
+ }
+
+ virtual void EndElement() override
+ {
+ m_rParser.m_pXSecController->addEncapsulatedX509Certificate(m_Value);
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_Value += rChars;
+ }
+};
+
+class XSecParser::XadesCertificateValuesContext
+ : public XSecParser::Context
+{
+ public:
+ XadesCertificateValuesContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ m_rParser.HandleIdAttr(xAttrs);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "EncapsulatedX509Certificate")
+ {
+ return std::make_unique<XadesEncapsulatedX509CertificateContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ // missing: xades:OtherCertificate
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::XadesUnsignedSignaturePropertiesContext
+ : public XSecParser::Context
+{
+ public:
+ XadesUnsignedSignaturePropertiesContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ m_rParser.HandleIdAttr(xAttrs);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertificateValues")
+ {
+ return std::make_unique<XadesCertificateValuesContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ // missing:
+ // xades:CounterSignature
+ // ^ old code would read a ds:Signature inside it?
+ // xades:SignatureTimeStamp
+ // xades:CompleteCertificateRefs
+ // xades:CompleteRevocationRefs
+ // xades:AttributeCertificateRefs
+ // xades:AttributeRevocationRefs
+ // xades:SigAndRefsTimeStamp
+ // xades:RefsOnlyTimeStamp
+ // xades:RevocationValues
+ // xades:AttrAuthoritiesCertValues
+ // ^ old code: was equivalent to CertificateValues ???
+ // xades:AttributeRevocationValues
+ // xades:ArchiveTimeStamp
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::XadesUnsignedPropertiesContext
+ : public XSecParser::Context
+{
+ public:
+ XadesUnsignedPropertiesContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ m_rParser.HandleIdAttr(xAttrs);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "UnsignedSignatureProperties")
+ {
+ return std::make_unique<XadesUnsignedSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ // missing: xades:UnsignedDataObjectProperties
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::LoSignatureLineIdContext
+ : public XSecParser::ReferencedContextImpl
+{
+ private:
+ OUString m_Value;
+
+ public:
+ LoSignatureLineIdContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void EndElement() override
+ {
+ if (m_isReferenced)
+ {
+ m_rParser.m_pXSecController->setSignatureLineId(m_Value);
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineId");
+ }
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_Value += rChars;
+ }
+};
+
+class XSecParser::LoSignatureLineValidImageContext
+ : public XSecParser::ReferencedContextImpl
+{
+ private:
+ OUString m_Value;
+
+ public:
+ LoSignatureLineValidImageContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void EndElement() override
+ {
+ if (m_isReferenced)
+ {
+ m_rParser.m_pXSecController->setValidSignatureImage(m_Value);
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineValidImage");
+ }
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_Value += rChars;
+ }
+};
+
+class XSecParser::LoSignatureLineInvalidImageContext
+ : public XSecParser::ReferencedContextImpl
+{
+ private:
+ OUString m_Value;
+
+ public:
+ LoSignatureLineInvalidImageContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void EndElement() override
+ {
+ if (m_isReferenced)
+ {
+ m_rParser.m_pXSecController->setInvalidSignatureImage(m_Value);
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineInvalidImage");
+ }
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_Value += rChars;
+ }
+};
+
+class XSecParser::LoSignatureLineContext
+ : public XSecParser::ReferencedContextImpl
+{
+ public:
+ LoSignatureLineContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineId")
+ {
+ return std::make_unique<LoSignatureLineIdContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineValidImage")
+ {
+ return std::make_unique<LoSignatureLineValidImageContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineInvalidImage")
+ {
+ return std::make_unique<LoSignatureLineInvalidImageContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::XadesCertDigestContext
+ : public XSecParser::Context
+{
+ private:
+ OUString & m_rDigestValue;
+ sal_Int32 & m_rReferenceDigestID;
+
+ public:
+ XadesCertDigestContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString& rDigestValue, sal_Int32& rReferenceDigestID)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rDigestValue(rDigestValue)
+ , m_rReferenceDigestID(rReferenceDigestID)
+ {
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod")
+ {
+ return std::make_unique<DsDigestMethodContext>(m_rParser, std::move(pOldNamespaceMap), m_rReferenceDigestID);
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue")
+ {
+ return std::make_unique<DsDigestValueContext>(m_rParser, std::move(pOldNamespaceMap), m_rDigestValue);
+ }
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::XadesCertContext
+ : public XSecParser::ReferencedContextImpl
+{
+ private:
+ sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA1;
+ OUString m_CertDigest;
+ OUString m_X509IssuerName;
+ OUString m_X509SerialNumber;
+
+ public:
+ XadesCertContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void EndElement() override
+ {
+ if (m_isReferenced)
+ {
+ m_rParser.m_pXSecController->setX509CertDigest(m_CertDigest, m_nReferenceDigestID, m_X509IssuerName, m_X509SerialNumber);
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.helper", "ignoring unsigned xades:Cert");
+ }
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertDigest")
+ {
+ return std::make_unique<XadesCertDigestContext>(m_rParser, std::move(pOldNamespaceMap), m_CertDigest, m_nReferenceDigestID);
+ }
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "IssuerSerial")
+ {
+ return std::make_unique<DsX509IssuerSerialContext>(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerName, m_X509SerialNumber);
+ }
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::XadesSigningCertificateContext
+ : public XSecParser::ReferencedContextImpl
+{
+ public:
+ XadesSigningCertificateContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "Cert")
+ {
+ return std::make_unique<XadesCertContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::XadesSigningTimeContext
+ : public XSecParser::ReferencedContextImpl
+{
+ private:
+ OUString m_Value;
+
+ public:
+ XadesSigningTimeContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void EndElement() override
+ {
+ if (m_isReferenced)
+ {
+ m_rParser.m_pXSecController->setDate("", m_Value);
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.helper", "ignoring unsigned SigningTime");
+ }
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_Value += rChars;
+ }
+};
+
+class XSecParser::XadesSignedSignaturePropertiesContext
+ : public XSecParser::ReferencedContextImpl
+{
+ public:
+ XadesSignedSignaturePropertiesContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ CheckIdAttrReferenced(xAttrs);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningTime")
+ {
+ return std::make_unique<XadesSigningTimeContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningCertificate")
+ {
+ return std::make_unique<XadesSigningCertificateContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLine")
+ {
+ return std::make_unique<LoSignatureLineContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ // missing: xades:SignaturePolicyIdentifier, xades:SignatureProductionPlace, xades:SignerRole
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::XadesSignedPropertiesContext
+ : public XSecParser::ReferencedContextImpl
+{
+ public:
+ XadesSignedPropertiesContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ CheckIdAttrReferenced(xAttrs);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedSignatureProperties")
+ {
+ return std::make_unique<XadesSignedSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ // missing: xades:SignedDataObjectProperties
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::XadesQualifyingPropertiesContext
+ : public XSecParser::ReferencedContextImpl
+{
+ public:
+ XadesQualifyingPropertiesContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ CheckIdAttrReferenced(xAttrs);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedProperties")
+ {
+ return std::make_unique<XadesSignedPropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "UnsignedProperties")
+ {
+ return std::make_unique<XadesUnsignedPropertiesContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::DcDateContext
+ : public XSecParser::Context
+{
+ private:
+ OUString & m_rValue;
+
+ public:
+ DcDateContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString& rValue)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rValue(rValue)
+ {
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_rValue += rChars;
+ }
+};
+
+class XSecParser::DcDescriptionContext
+ : public XSecParser::Context
+{
+ private:
+ OUString & m_rValue;
+
+ public:
+ DcDescriptionContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ OUString& rValue)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ , m_rValue(rValue)
+ {
+ }
+
+ virtual void Characters(OUString const& rChars) override
+ {
+ m_rValue += rChars;
+ }
+};
+
+class XSecParser::DsSignaturePropertyContext
+ : public XSecParser::ReferencedContextImpl
+{
+ private:
+ enum class SignatureProperty { Unknown, Date, Description };
+ SignatureProperty m_Property = SignatureProperty::Unknown;
+ OUString m_Id;
+ OUString m_Value;
+
+ public:
+ DsSignaturePropertyContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ m_Id = CheckIdAttrReferenced(xAttrs);
+ }
+
+ virtual void EndElement() override
+ {
+ if (m_isReferenced)
+ {
+ switch (m_Property)
+ {
+ case SignatureProperty::Unknown:
+ SAL_INFO("xmlsecurity.helper", "Unknown property in ds:Object ignored");
+ break;
+ case SignatureProperty::Date:
+ m_rParser.m_pXSecController->setDate(m_Id, m_Value);
+ break;
+ case SignatureProperty::Description:
+ m_rParser.m_pXSecController->setDescription(m_Id, m_Value);
+ break;
+ }
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureProperty");
+ }
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DC && rName == "date")
+ {
+ m_Property = SignatureProperty::Date;
+ return std::make_unique<DcDateContext>(m_rParser, std::move(pOldNamespaceMap), m_Value);
+ }
+ if (nNamespace == XML_NAMESPACE_DC && rName == "description")
+ {
+ m_Property = SignatureProperty::Description;
+ return std::make_unique<DcDescriptionContext>(m_rParser, std::move(pOldNamespaceMap), m_Value);
+ }
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::DsSignaturePropertiesContext
+ : public XSecParser::ReferencedContextImpl
+{
+ public:
+ DsSignaturePropertiesContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ bool const isReferenced)
+ : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ CheckIdAttrReferenced(xAttrs);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperty")
+ {
+ return std::make_unique<DsSignaturePropertyContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::DsObjectContext
+ : public XSecParser::ReferencedContextImpl
+{
+ public:
+ DsObjectContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ // init with "false" here - the Signature element can't be referenced by its child
+ : XSecParser::ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), false)
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ CheckIdAttrReferenced(xAttrs);
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperties")
+ {
+ return std::make_unique<DsSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ if (nNamespace == XML_NAMESPACE_XADES132 && rName == "QualifyingProperties")
+ {
+ return std::make_unique<XadesQualifyingPropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
+ }
+ // missing: ds:Manifest
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::DsSignatureContext
+ : public XSecParser::Context
+{
+ public:
+ DsSignatureContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual void StartElement(
+ css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
+ {
+ OUString const ouIdAttr(m_rParser.HandleIdAttr(xAttrs));
+ m_rParser.m_rXMLSignatureHelper.StartVerifySignatureElement();
+ m_rParser.m_pXSecController->addSignature();
+ if (!ouIdAttr.isEmpty())
+ {
+ m_rParser.m_pXSecController->setId( ouIdAttr );
+ }
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "SignedInfo")
+ {
+ return std::make_unique<DsSignedInfoContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureValue")
+ {
+ return std::make_unique<DsSignatureValueContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "KeyInfo")
+ {
+ return std::make_unique<DsKeyInfoContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ if (nNamespace == XML_NAMESPACE_DS && rName == "Object")
+ {
+ return std::make_unique<DsObjectContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+class XSecParser::DsigSignaturesContext
+ : public XSecParser::Context
+{
+ public:
+ DsigSignaturesContext(XSecParser& rParser,
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
+ : XSecParser::Context(rParser, std::move(pOldNamespaceMap))
+ {
+ }
+
+ virtual std::unique_ptr<Context> CreateChildContext(
+ std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
+ sal_uInt16 const nNamespace, OUString const& rName) override
+ {
+ if (nNamespace == XML_NAMESPACE_DS && rName == "Signature")
+ {
+ return std::make_unique<DsSignatureContext>(m_rParser, std::move(pOldNamespaceMap));
+ }
+ return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
+ }
+};
+
+
+XSecParser::XSecParser(XMLSignatureHelper& rXMLSignatureHelper,
+ XSecController* pXSecController)
+ : m_pNamespaceMap(SvXMLNamespaceMap())
+ , m_pXSecController(pXSecController)
+ , m_rXMLSignatureHelper(rXMLSignatureHelper)
+{
+ using namespace xmloff::token;
+ m_pNamespaceMap->Add( GetXMLToken(XML_XML), GetXMLToken(XML_N_XML), XML_NAMESPACE_XML );
+ m_pNamespaceMap->Add( "_dsig_ooo", GetXMLToken(XML_N_DSIG_OOO), XML_NAMESPACE_DSIG_OOO );
+ m_pNamespaceMap->Add( "_dsig", GetXMLToken(XML_N_DSIG), XML_NAMESPACE_DSIG );
+ m_pNamespaceMap->Add( "_ds", GetXMLToken(XML_N_DS), XML_NAMESPACE_DS );
+ m_pNamespaceMap->Add( "_xades132", GetXMLToken(XML_N_XADES132), XML_NAMESPACE_XADES132);
+ m_pNamespaceMap->Add( "_xades141", GetXMLToken(XML_N_XADES141), XML_NAMESPACE_XADES141);
+ m_pNamespaceMap->Add( "_dc", GetXMLToken(XML_N_DC), XML_NAMESPACE_DC );
+ m_pNamespaceMap->Add( "_office_libo",
+ GetXMLToken(XML_N_LO_EXT), XML_NAMESPACE_LO_EXT);
+}
+
+OUString XSecParser::HandleIdAttr(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs)
+{
+ OUString ouIdAttr = getIdAttr(xAttrs);
+ if (!ouIdAttr.isEmpty())
+ {
+ m_pXSecController->collectToVerify( ouIdAttr );
+ }
+ return ouIdAttr;
+}
+
+OUString XSecParser::getIdAttr(const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs )
+{
+ OUString ouIdAttr = xAttribs->getValueByName("id");
+
+ if (ouIdAttr.isEmpty())
+ {
+ ouIdAttr = xAttribs->getValueByName("Id");
+ }
+
+ return ouIdAttr;
+}
+
+/*
+ * XDocumentHandler
+ */
+void SAL_CALL XSecParser::startDocument( )
+{
+ if (m_xNextHandler.is())
+ {
+ m_xNextHandler->startDocument();
+ }
+}
+
+void SAL_CALL XSecParser::endDocument( )
+{
+ if (m_xNextHandler.is())
+ {
+ m_xNextHandler->endDocument();
+ }
+}
+
+void SAL_CALL XSecParser::startElement(
+ const OUString& rName,
+ const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs )
+{
+ assert(m_pNamespaceMap);
+ std::optional<SvXMLNamespaceMap> pRewindMap(
+ SvXMLImport::processNSAttributes(m_pNamespaceMap, nullptr, xAttribs));
+
+ OUString localName;
+ sal_uInt16 const nPrefix(m_pNamespaceMap->GetKeyByAttrName(rName, &localName));
+
+ std::unique_ptr<Context> pContext;
+
+ if (m_ContextStack.empty())
+ {
+ if ((nPrefix != XML_NAMESPACE_DSIG && nPrefix != XML_NAMESPACE_DSIG_OOO)
+ || localName != "document-signatures")
+ {
+ throw css::xml::sax::SAXException(
+ "xmlsecurity: unexpected root element", nullptr,
+ css::uno::Any());
+ }
+
+ pContext.reset(new DsigSignaturesContext(*this, std::move(pRewindMap)));
+
+ }
+ else
+ {
+ pContext = m_ContextStack.top()->CreateChildContext(
+ std::move(pRewindMap), nPrefix, localName);
+ }
+
+ m_ContextStack.push(std::move(pContext));
+
+ try
+ {
+ m_ContextStack.top()->StartElement(xAttribs);
+
+ if (m_xNextHandler.is())
+ {
+ m_xNextHandler->startElement(rName, xAttribs);
+ }
+ }
+ catch (css::uno::Exception& )
+ {//getCaughtException MUST be the first line in the catch block
+ css::uno::Any exc = cppu::getCaughtException();
+ throw css::xml::sax::SAXException(
+ "xmlsecurity: Exception in XSecParser::startElement",
+ nullptr, exc);
+ }
+ catch (...)
+ {
+ throw css::xml::sax::SAXException(
+ "xmlsecurity: unexpected exception in XSecParser::startElement", nullptr,
+ css::uno::Any());
+ }
+}
+
+void SAL_CALL XSecParser::endElement(const OUString& rName)
+{
+ assert(!m_ContextStack.empty()); // this should be checked by sax parser?
+
+ try
+ {
+ m_ContextStack.top()->EndElement();
+
+ if (m_xNextHandler.is())
+ {
+ m_xNextHandler->endElement(rName);
+ }
+ }
+ catch (css::uno::Exception& )
+ {//getCaughtException MUST be the first line in the catch block
+ css::uno::Any exc = cppu::getCaughtException();
+ throw css::xml::sax::SAXException(
+ "xmlsecurity: Exception in XSecParser::endElement",
+ nullptr, exc);
+ }
+ catch (...)
+ {
+ throw css::xml::sax::SAXException(
+ "xmlsecurity: unexpected exception in XSecParser::endElement", nullptr,
+ css::uno::Any());
+ }
+
+ if (m_ContextStack.top()->m_pOldNamespaceMap)
+ {
+ m_pNamespaceMap = std::move(m_ContextStack.top()->m_pOldNamespaceMap);
+ }
+ m_ContextStack.pop();
+}
+
+void SAL_CALL XSecParser::characters(const OUString& rChars)
+{
+ assert(!m_ContextStack.empty()); // this should be checked by sax parser?
+ m_ContextStack.top()->Characters(rChars);
+
+ if (m_xNextHandler.is())
+ {
+ m_xNextHandler->characters(rChars);
+ }
+}
+
+void SAL_CALL XSecParser::ignorableWhitespace( const OUString& aWhitespaces )
+{
+ if (m_xNextHandler.is())
+ {
+ m_xNextHandler->ignorableWhitespace( aWhitespaces );
+ }
+}
+
+void SAL_CALL XSecParser::processingInstruction( const OUString& aTarget, const OUString& aData )
+{
+ if (m_xNextHandler.is())
+ {
+ m_xNextHandler->processingInstruction(aTarget, aData);
+ }
+}
+
+void SAL_CALL XSecParser::setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >& xLocator )
+{
+ if (m_xNextHandler.is())
+ {
+ m_xNextHandler->setDocumentLocator( xLocator );
+ }
+}
+
+/*
+ * XInitialization
+ */
+void SAL_CALL XSecParser::initialize(
+ const css::uno::Sequence< css::uno::Any >& aArguments )
+{
+ aArguments[0] >>= m_xNextHandler;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/helper/xsecparser.hxx b/xmlsecurity/source/helper/xsecparser.hxx
new file mode 100644
index 000000000..6279d6543
--- /dev/null
+++ b/xmlsecurity/source/helper/xsecparser.hxx
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <xmloff/namespacemap.hxx>
+
+#include <memory>
+#include <optional>
+#include <stack>
+
+class XMLSignatureHelper;
+class XSecController;
+
+class XSecParser: public cppu::WeakImplHelper
+<
+ css::xml::sax::XDocumentHandler,
+ css::lang::XInitialization
+>
+/****** XSecController.hxx/CLASS XSecParser ***********************************
+ *
+ * NAME
+ * XSecParser -- a SAX parser that can detect security elements
+ *
+ * FUNCTION
+ * The XSecParser object is connected on the SAX chain and detects
+ * security elements in the SAX event stream, then notifies
+ * the XSecController.
+ *
+ * NOTES
+ * This class is used when importing a document.
+ ******************************************************************************/
+{
+ friend class XSecController;
+public:
+ class Context;
+private:
+ class UnknownContext;
+ class ReferencedContextImpl;
+ class LoPGPOwnerContext;
+ class DsPGPKeyPacketContext;
+ class DsPGPKeyIDContext;
+ class DsPGPDataContext;
+ class DsX509CertificateContext;
+ class DsX509SerialNumberContext;
+ class DsX509IssuerNameContext;
+ class DsX509IssuerSerialContext;
+ class DsX509DataContext;
+ class DsKeyInfoContext;
+ class DsSignatureValueContext;
+ class DsDigestValueContext;
+ class DsDigestMethodContext;
+ class DsTransformContext;
+ class DsTransformsContext;
+ class DsReferenceContext;
+ class DsSignatureMethodContext;
+ class DsSignedInfoContext;
+ class XadesEncapsulatedX509CertificateContext;
+ class XadesCertificateValuesContext;
+ class XadesUnsignedSignaturePropertiesContext;
+ class XadesUnsignedPropertiesContext;
+ class LoSignatureLineIdContext;
+ class LoSignatureLineValidImageContext;
+ class LoSignatureLineInvalidImageContext;
+ class LoSignatureLineContext;
+ class XadesCertDigestContext;
+ class XadesCertContext;
+ class XadesSigningCertificateContext;
+ class XadesSigningTimeContext;
+ class XadesSignedSignaturePropertiesContext;
+ class XadesSignedPropertiesContext;
+ class XadesQualifyingPropertiesContext;
+ class DcDateContext;
+ class DcDescriptionContext;
+ class DsSignaturePropertyContext;
+ class DsSignaturePropertiesContext;
+ class DsObjectContext;
+ class DsSignatureContext;
+ class DsigSignaturesContext;
+
+ std::stack<std::unique_ptr<Context>> m_ContextStack;
+ std::optional<SvXMLNamespaceMap> m_pNamespaceMap;
+
+ /*
+ * the XSecController collaborating with XSecParser
+ */
+ XSecController* m_pXSecController;
+
+ /*
+ * the next XDocumentHandler on the SAX chain
+ */
+ css::uno::Reference<
+ css::xml::sax::XDocumentHandler > m_xNextHandler;
+
+ XMLSignatureHelper& m_rXMLSignatureHelper;
+
+ OUString HandleIdAttr(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs);
+ static OUString getIdAttr(const css::uno::Reference<
+ css::xml::sax::XAttributeList >& xAttribs );
+
+public:
+ XSecParser(XMLSignatureHelper& rXMLSignatureHelper, XSecController* pXSecController);
+
+ /*
+ * XDocumentHandler
+ */
+ virtual void SAL_CALL startDocument( ) override;
+
+ virtual void SAL_CALL endDocument( ) override;
+
+ virtual void SAL_CALL startElement(
+ const OUString& aName,
+ const css::uno::Reference<
+ css::xml::sax::XAttributeList >& xAttribs ) override;
+
+ virtual void SAL_CALL endElement( const OUString& aName ) override;
+
+ virtual void SAL_CALL characters( const OUString& aChars ) override;
+
+ virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) override;
+
+ virtual void SAL_CALL processingInstruction(
+ const OUString& aTarget,
+ const OUString& aData ) override;
+
+ virtual void SAL_CALL setDocumentLocator(
+ const css::uno::Reference<
+ css::xml::sax::XLocator >& xLocator ) override;
+
+ /*
+ * XInitialization
+ */
+ virtual void SAL_CALL initialize(
+ const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/helper/xsecsign.cxx b/xmlsecurity/source/helper/xsecsign.cxx
new file mode 100644
index 000000000..5634ed502
--- /dev/null
+++ b/xmlsecurity/source/helper/xsecsign.cxx
@@ -0,0 +1,460 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include <xsecctl.hxx>
+
+#include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp>
+#include <com/sun/star/embed/StorageFormats.hpp>
+#include <rtl/uuid.h>
+#include <sal/log.hxx>
+
+#include <framework/signaturecreatorimpl.hxx>
+#include <framework/saxeventkeeperimpl.hxx>
+
+namespace com::sun::star::graphic { class XGraphic; }
+
+using namespace css;
+using namespace css::uno;
+using namespace css::graphic;
+
+/* protected: for signature generation */
+OUString XSecController::createId()
+{
+ sal_uInt8 aSeq[16];
+ rtl_createUuid( aSeq, nullptr, true );
+
+ char str[68]="ID_";
+ int length = 3;
+ for (sal_uInt8 i : aSeq)
+ {
+ length += sprintf(str+length, "%04x", i);
+ }
+
+ return OUString::createFromAscii(str);
+}
+
+css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > XSecController::prepareSignatureToWrite(
+ InternalSignatureInformation& internalSignatureInfor,
+ sal_Int32 nStorageFormat,
+ bool bXAdESCompliantIfODF)
+{
+ sal_Int32 nSecurityId = internalSignatureInfor.signatureInfor.nSecurityId;
+ SignatureReferenceInformations& vReferenceInfors = internalSignatureInfor.signatureInfor.vSignatureReferenceInfors;
+
+ sal_Int32 nIdOfSignatureElementCollector;
+
+ nIdOfSignatureElementCollector =
+ m_xSAXEventKeeper->addSecurityElementCollector( css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY, true );
+
+ m_xSAXEventKeeper->setSecurityId(nIdOfSignatureElementCollector, nSecurityId);
+
+ rtl::Reference<SignatureCreatorImpl> xSignatureCreator(new SignatureCreatorImpl);
+
+ css::uno::Sequence<css::uno::Any> args
+ {
+ Any(OUString::number(nSecurityId)),
+ Any(uno::Reference<xml::crypto::sax::XSecuritySAXEventKeeper>(m_xSAXEventKeeper)),
+ Any(OUString::number(nIdOfSignatureElementCollector)),
+
+ //for nss, the internal module is used for signing, which needs to be improved later
+ Any(m_xSecurityContext->getSecurityEnvironment()),
+ Any(m_xXMLSignature)
+ };
+ xSignatureCreator->initialize(args);
+
+ sal_Int32 nBlockerId = m_xSAXEventKeeper->addBlocker();
+ m_xSAXEventKeeper->setSecurityId(nBlockerId, nSecurityId);
+
+ xSignatureCreator->setBlockerId(nBlockerId);
+
+ xSignatureCreator->addSignatureCreationResultListener(this);
+
+ m_xSAXEventKeeper->addReferenceResolvedListener(nIdOfSignatureElementCollector, xSignatureCreator);
+
+ int size = vReferenceInfors.size();
+ sal_Int32 nReferenceCount = 0;
+
+ for(int i=0; i<size; ++i)
+ {
+ sal_Int32 keeperId = internalSignatureInfor.vKeeperIds[i];
+
+ if ( keeperId != -1)
+ {
+ m_xSAXEventKeeper->setSecurityId(keeperId, nSecurityId);
+ m_xSAXEventKeeper->addReferenceResolvedListener( keeperId, xSignatureCreator);
+ xSignatureCreator->setReferenceId( keeperId );
+ nReferenceCount++;
+ }
+ }
+
+ xSignatureCreator->setReferenceCount( nReferenceCount );
+
+ /*
+ * adds all URI binding
+ */
+ for(int i=0; i<size; ++i)
+ {
+ const SignatureReferenceInformation& refInfor = vReferenceInfors[i];
+
+ css::uno::Reference< css::io::XInputStream > xInputStream
+ = getObjectInputStream( refInfor.ouURI );
+
+ if (xInputStream.is())
+ xSignatureCreator->setUriBinding(refInfor.ouURI,xInputStream);
+ }
+
+ xSignatureCreator->setKeyId(0);
+
+ // use sha512 for gpg signing unconditionally
+ const sal_Int32 digestID = !internalSignatureInfor.signatureInfor.ouGpgCertificate.isEmpty()?
+ css::xml::crypto::DigestID::SHA512 : (bXAdESCompliantIfODF ? css::xml::crypto::DigestID::SHA256 : css::xml::crypto::DigestID::SHA1);
+
+ if (nStorageFormat != embed::StorageFormats::OFOPXML)
+ {
+ internalSignatureInfor.signatureInfor.ouSignatureId = createId();
+ internalSignatureInfor.signatureInfor.ouDateTimePropertyId = createId();
+ internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, internalSignatureInfor.signatureInfor.ouDateTimePropertyId, -1, OUString() );
+ size++;
+
+ if (bXAdESCompliantIfODF)
+ {
+ OUString aId = "idSignedProperties_" + internalSignatureInfor.signatureInfor.ouSignatureId;
+ // We write a new reference, so it's possible to use the correct type URI.
+ internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, aId, -1, "http://uri.etsi.org/01903#SignedProperties");
+ size++;
+ }
+
+ if (!internalSignatureInfor.signatureInfor.ouDescription.isEmpty())
+ {
+ // Only mention the hash of the description in the signature if it's non-empty.
+ internalSignatureInfor.signatureInfor.ouDescriptionPropertyId = createId();
+ internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, internalSignatureInfor.signatureInfor.ouDescriptionPropertyId, -1, OUString());
+ size++;
+ }
+ }
+ else // OOXML
+ {
+ OUString aID = createId();
+ internalSignatureInfor.signatureInfor.ouSignatureId = aID;
+
+ internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idPackageObject_" + aID, -1, OUString());
+ size++;
+ internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idOfficeObject_" + aID, -1, OUString());
+ size++;
+ internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idSignedProperties_" + aID, -1, OUString());
+ size++;
+ }
+
+ /*
+ * replace both digestValues and signatureValue to " "
+ */
+ for(int i=0; i<size; ++i)
+ {
+ SignatureReferenceInformation& refInfor = vReferenceInfors[i];
+ refInfor.ouDigestValue = " ";
+ }
+
+ internalSignatureInfor.signatureInfor.ouSignatureValue = " ";
+
+ return xSignatureCreator;
+}
+
+void XSecController::signAStream( sal_Int32 securityId, const OUString& uri, bool isBinary, bool bXAdESCompliantIfODF)
+{
+ const SignatureReferenceType type = isBinary ? SignatureReferenceType::BINARYSTREAM : SignatureReferenceType::XMLSTREAM;
+ sal_Int32 digestID = bXAdESCompliantIfODF ? css::xml::crypto::DigestID::SHA256 : css::xml::crypto::DigestID::SHA1;
+
+ int index = findSignatureInfor( securityId );
+
+ if (index == -1)
+ {
+ InternalSignatureInformation isi(securityId, nullptr);
+ isi.addReference(type, digestID, uri, -1, OUString());
+ m_vInternalSignatureInformations.push_back( isi );
+ }
+ else
+ {
+ // use sha512 for gpg signing unconditionally
+ if (!m_vInternalSignatureInformations[index].signatureInfor.ouGpgCertificate.isEmpty())
+ digestID = css::xml::crypto::DigestID::SHA512;
+ m_vInternalSignatureInformations[index].addReference(type, digestID, uri, -1, OUString());
+ }
+}
+
+// note: this is called when creating a new signature from scratch
+void XSecController::setX509Certificate(
+ sal_Int32 nSecurityId,
+ const OUString& ouX509IssuerName,
+ const OUString& ouX509SerialNumber,
+ const OUString& ouX509Cert,
+ const OUString& ouX509CertDigest,
+ svl::crypto::SignatureMethodAlgorithm eAlgorithmID)
+{
+ int index = findSignatureInfor( nSecurityId );
+
+ if ( index == -1 )
+ {
+ InternalSignatureInformation isi(nSecurityId, nullptr);
+ isi.signatureInfor.X509Datas.clear();
+ isi.signatureInfor.X509Datas.emplace_back();
+ isi.signatureInfor.X509Datas.back().emplace_back();
+ isi.signatureInfor.X509Datas.back().back().X509IssuerName = ouX509IssuerName;
+ isi.signatureInfor.X509Datas.back().back().X509SerialNumber = ouX509SerialNumber;
+ isi.signatureInfor.X509Datas.back().back().X509Certificate = ouX509Cert;
+ isi.signatureInfor.X509Datas.back().back().CertDigest = ouX509CertDigest;
+ isi.signatureInfor.eAlgorithmID = eAlgorithmID;
+ m_vInternalSignatureInformations.push_back( isi );
+ }
+ else
+ {
+ SignatureInformation &si
+ = m_vInternalSignatureInformations[index].signatureInfor;
+ si.X509Datas.clear();
+ si.X509Datas.emplace_back();
+ si.X509Datas.back().emplace_back();
+ si.X509Datas.back().back().X509IssuerName = ouX509IssuerName;
+ si.X509Datas.back().back().X509SerialNumber = ouX509SerialNumber;
+ si.X509Datas.back().back().X509Certificate = ouX509Cert;
+ si.X509Datas.back().back().CertDigest = ouX509CertDigest;
+ }
+}
+
+void XSecController::setGpgCertificate(
+ sal_Int32 nSecurityId,
+ const OUString& ouKeyDigest,
+ const OUString& ouCert,
+ const OUString& ouOwner)
+{
+ int index = findSignatureInfor( nSecurityId );
+
+ if ( index == -1 )
+ {
+ InternalSignatureInformation isi(nSecurityId, nullptr);
+ isi.signatureInfor.ouGpgCertificate = ouCert;
+ isi.signatureInfor.ouGpgOwner = ouOwner;
+ isi.signatureInfor.ouGpgKeyID = ouKeyDigest;
+ m_vInternalSignatureInformations.push_back( isi );
+ }
+ else
+ {
+ SignatureInformation &si
+ = m_vInternalSignatureInformations[index].signatureInfor;
+ si.X509Datas.clear(); // it is a PGP signature now
+ si.ouGpgCertificate = ouCert;
+ si.ouGpgOwner = ouOwner;
+ si.ouGpgKeyID = ouKeyDigest;
+ }
+}
+
+void XSecController::setDate(
+ sal_Int32 nSecurityId,
+ const css::util::DateTime& rDateTime )
+{
+ int index = findSignatureInfor( nSecurityId );
+
+ if ( index == -1 )
+ {
+ InternalSignatureInformation isi(nSecurityId, nullptr);
+ isi.signatureInfor.stDateTime = rDateTime;
+ m_vInternalSignatureInformations.push_back( isi );
+ }
+ else
+ {
+ SignatureInformation &si
+ = m_vInternalSignatureInformations[index].signatureInfor;
+ si.stDateTime = rDateTime;
+ }
+}
+
+void XSecController::setDescription(sal_Int32 nSecurityId, const OUString& rDescription)
+{
+ int nIndex = findSignatureInfor(nSecurityId);
+
+ if (nIndex == -1)
+ {
+ InternalSignatureInformation aInformation(nSecurityId, nullptr);
+ aInformation.signatureInfor.ouDescription = rDescription;
+ m_vInternalSignatureInformations.push_back(aInformation);
+ }
+ else
+ {
+ SignatureInformation& rInformation = m_vInternalSignatureInformations[nIndex].signatureInfor;
+ rInformation.ouDescription = rDescription;
+ }
+}
+
+void XSecController::setSignatureLineId(sal_Int32 nSecurityId, const OUString& rSignatureLineId)
+{
+ int nIndex = findSignatureInfor(nSecurityId);
+
+ if (nIndex == -1)
+ {
+ InternalSignatureInformation aInformation(nSecurityId, nullptr);
+ aInformation.signatureInfor.ouSignatureLineId = rSignatureLineId;
+ m_vInternalSignatureInformations.push_back(aInformation);
+ }
+ else
+ {
+ SignatureInformation& rInformation = m_vInternalSignatureInformations[nIndex].signatureInfor;
+ rInformation.ouSignatureLineId = rSignatureLineId;
+ }
+}
+
+void XSecController::setSignatureLineValidGraphic(sal_Int32 nSecurityId,
+ const Reference<XGraphic>& xValidGraphic)
+{
+ int nIndex = findSignatureInfor(nSecurityId);
+
+ if (nIndex == -1)
+ {
+ InternalSignatureInformation aInformation(nSecurityId, nullptr);
+ aInformation.signatureInfor.aValidSignatureImage = xValidGraphic;
+ m_vInternalSignatureInformations.push_back(aInformation);
+ }
+ else
+ {
+ SignatureInformation& rInformation
+ = m_vInternalSignatureInformations[nIndex].signatureInfor;
+ rInformation.aValidSignatureImage = xValidGraphic;
+ }
+}
+
+void XSecController::setSignatureLineInvalidGraphic(
+ sal_Int32 nSecurityId, const Reference<XGraphic>& xInvalidGraphic)
+{
+ int nIndex = findSignatureInfor(nSecurityId);
+
+ if (nIndex == -1)
+ {
+ InternalSignatureInformation aInformation(nSecurityId, nullptr);
+ aInformation.signatureInfor.aInvalidSignatureImage = xInvalidGraphic;
+ m_vInternalSignatureInformations.push_back(aInformation);
+ }
+ else
+ {
+ SignatureInformation& rInformation
+ = m_vInternalSignatureInformations[nIndex].signatureInfor;
+ rInformation.aInvalidSignatureImage = xInvalidGraphic;
+ }
+}
+
+bool XSecController::WriteSignature(
+ const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler,
+ bool bXAdESCompliantIfODF )
+{
+ bool rc = false;
+
+ SAL_WARN_IF( !xDocumentHandler.is(), "xmlsecurity.helper", "I really need a document handler!" );
+
+ /*
+ * chain the SAXEventKeeper to the SAX chain
+ */
+ chainOn();
+
+ if ( m_eStatusOfSecurityComponents == InitializationState::INITIALIZED )
+ /*
+ * if all security components are ready, add the signature
+ * stream.
+ */
+ {
+ m_bIsSAXEventKeeperSticky = true;
+ m_xSAXEventKeeper->setNextHandler(xDocumentHandler);
+
+ try
+ {
+ /*
+ * export the signature template
+ */
+ css::uno::Reference<css::xml::sax::XDocumentHandler> xSEKHandler(m_xSAXEventKeeper);
+
+ int i;
+ int sigNum = m_vInternalSignatureInformations.size();
+
+ for (i=0; i<sigNum; ++i)
+ {
+ InternalSignatureInformation &isi = m_vInternalSignatureInformations[i];
+
+ // Prepare the signature creator.
+ // 0 is not a documented value of embed::StorageFormats, ugh
+ isi.xReferenceResolvedListener = prepareSignatureToWrite( isi, 0, bXAdESCompliantIfODF );
+
+ exportSignature( xSEKHandler, isi.signatureInfor, bXAdESCompliantIfODF );
+ }
+
+ m_bIsSAXEventKeeperSticky = false;
+ chainOff();
+
+ rc = true;
+ }
+ catch( css::uno::Exception& )
+ {
+ }
+
+ m_xSAXEventKeeper->setNextHandler( nullptr );
+ m_bIsSAXEventKeeperSticky = false;
+ }
+
+ return rc;
+}
+
+bool XSecController::WriteOOXMLSignature(const uno::Reference<embed::XStorage>& xRootStorage, const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler)
+{
+ bool bRet = false;
+
+ SAL_WARN_IF(!xDocumentHandler.is(), "xmlsecurity.helper", "empty xDocumentHandler reference");
+
+ // Chain the SAXEventKeeper to the SAX chain.
+ chainOn();
+
+ if (m_eStatusOfSecurityComponents == InitializationState::INITIALIZED)
+ {
+ m_bIsSAXEventKeeperSticky = true;
+ m_xSAXEventKeeper->setNextHandler(xDocumentHandler);
+
+ try
+ {
+ // Export the signature template.
+ css::uno::Reference<xml::sax::XDocumentHandler> xSEKHandler(m_xSAXEventKeeper);
+
+ for (InternalSignatureInformation & rInformation : m_vInternalSignatureInformations)
+ {
+ // Prepare the signature creator.
+ rInformation.xReferenceResolvedListener = prepareSignatureToWrite(rInformation, embed::StorageFormats::OFOPXML, false);
+
+ exportOOXMLSignature(xRootStorage, xSEKHandler, rInformation.signatureInfor);
+ }
+
+ m_bIsSAXEventKeeperSticky = false;
+ chainOff();
+
+ bRet = true;
+ }
+ catch(const uno::Exception&)
+ {
+ }
+
+ m_xSAXEventKeeper->setNextHandler(nullptr);
+ m_bIsSAXEventKeeperSticky = false;
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/helper/xsecverify.cxx b/xmlsecurity/source/helper/xsecverify.cxx
new file mode 100644
index 000000000..c45bece5f
--- /dev/null
+++ b/xmlsecurity/source/helper/xsecverify.cxx
@@ -0,0 +1,630 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <config_gpgme.h>
+
+#include <xsecctl.hxx>
+#include "xsecparser.hxx"
+#include "ooxmlsecparser.hxx"
+#include <biginteger.hxx>
+#include <framework/signatureverifierimpl.hxx>
+#include <framework/saxeventkeeperimpl.hxx>
+#include <gpg/xmlsignature_gpgimpl.hxx>
+#include <gpg/SEInitializer.hxx>
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/xml/crypto/sax/XKeyCollector.hpp>
+#include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp>
+#include <com/sun/star/xml/crypto/sax/XReferenceCollector.hpp>
+#include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultBroadcaster.hpp>
+#include <com/sun/star/xml/crypto/XSEInitializer.hpp>
+#include <com/sun/star/graphic/GraphicProvider.hpp>
+#include <com/sun/star/embed/StorageFormats.hpp>
+#include <sal/log.hxx>
+#include <unotools/datetime.hxx>
+#include <comphelper/base64.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/seqstream.hxx>
+
+namespace com::sun::star::graphic { class XGraphic; }
+
+using namespace css;
+using namespace css::uno;
+using namespace css::beans;
+
+/* protected: for signature verify */
+css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > XSecController::prepareSignatureToRead(
+ sal_Int32 nSecurityId)
+{
+ if ( m_eStatusOfSecurityComponents != InitializationState::INITIALIZED )
+ {
+ return nullptr;
+ }
+
+ sal_Int32 nIdOfSignatureElementCollector;
+ css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener;
+
+ nIdOfSignatureElementCollector =
+ m_xSAXEventKeeper->addSecurityElementCollector( css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY, false);
+
+ m_xSAXEventKeeper->setSecurityId(nIdOfSignatureElementCollector, nSecurityId);
+
+ /*
+ * create a SignatureVerifier
+ */
+ xReferenceResolvedListener = new SignatureVerifierImpl;
+
+ css::uno::Reference<css::lang::XInitialization> xInitialization(xReferenceResolvedListener, css::uno::UNO_QUERY);
+
+ css::uno::Sequence<css::uno::Any> args
+ {
+ Any(OUString::number(nSecurityId)),
+ Any(uno::Reference<xml::crypto::sax::XSecuritySAXEventKeeper>(m_xSAXEventKeeper)),
+ Any(OUString::number(nIdOfSignatureElementCollector)),
+ Any(m_xSecurityContext),
+ Any(m_xXMLSignature)
+ };
+ xInitialization->initialize(args);
+
+ css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultBroadcaster >
+ signatureVerifyResultBroadcaster(xReferenceResolvedListener, css::uno::UNO_QUERY);
+
+ signatureVerifyResultBroadcaster->addSignatureVerifyResultListener( this );
+
+ m_xSAXEventKeeper->addReferenceResolvedListener(
+ nIdOfSignatureElementCollector,
+ xReferenceResolvedListener);
+
+ css::uno::Reference<css::xml::crypto::sax::XKeyCollector> keyCollector (xReferenceResolvedListener, css::uno::UNO_QUERY);
+ keyCollector->setKeyId(0);
+
+ return xReferenceResolvedListener;
+}
+
+void XSecController::addSignature()
+{
+ css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener;
+ sal_Int32 nSignatureId = 0;
+
+
+ if (m_bVerifyCurrentSignature)
+ {
+ chainOn();
+ xReferenceResolvedListener = prepareSignatureToRead( m_nReservedSignatureId );
+ m_bVerifyCurrentSignature = false;
+ nSignatureId = m_nReservedSignatureId;
+ }
+
+ InternalSignatureInformation isi( nSignatureId, xReferenceResolvedListener );
+ m_vInternalSignatureInformations.push_back( isi );
+}
+
+void XSecController::setSignatureMethod(svl::crypto::SignatureMethodAlgorithm eAlgorithmID)
+{
+ if (m_vInternalSignatureInformations.empty())
+ return;
+
+ m_vInternalSignatureInformations.back().signatureInfor.eAlgorithmID = eAlgorithmID;
+}
+
+void XSecController::switchGpgSignature()
+{
+#if HAVE_FEATURE_GPGME
+ // swap signature verifier for the Gpg one
+ m_xXMLSignature.set(new XMLSignature_GpgImpl());
+ if (m_vInternalSignatureInformations.empty())
+ return;
+
+ SignatureVerifierImpl* pImpl=
+ dynamic_cast<SignatureVerifierImpl*>(
+ m_vInternalSignatureInformations.back().xReferenceResolvedListener.get());
+ if (pImpl)
+ {
+ css::uno::Reference<css::xml::crypto::XSEInitializer> xGpgSEInitializer(
+ new SEInitializerGpg());
+ pImpl->updateSignature(new XMLSignature_GpgImpl(),
+ xGpgSEInitializer->createSecurityContext(OUString()));
+ }
+#else
+ (void) this;
+#endif
+}
+
+bool XSecController::haveReferenceForId(std::u16string_view rId) const
+{
+ if (m_vInternalSignatureInformations.empty())
+ {
+ SAL_INFO("xmlsecurity.helper","XSecController::haveReferenceForId: no signature");
+ return false;
+ }
+ InternalSignatureInformation const& rIsi(m_vInternalSignatureInformations.back());
+ for (SignatureReferenceInformation const& rSri : rIsi.signatureInfor.vSignatureReferenceInfors)
+ {
+ if (rSri.nType == SignatureReferenceType::SAMEDOCUMENT
+ && rSri.ouURI == rId) // ouUri has # stripped
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void XSecController::addReference( const OUString& ouUri, sal_Int32 nDigestID, const OUString& ouType )
+{
+ if (m_vInternalSignatureInformations.empty())
+ {
+ SAL_INFO("xmlsecurity.helper","XSecController::addReference: no signature");
+ return;
+ }
+ InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
+ isi.addReference(SignatureReferenceType::SAMEDOCUMENT, nDigestID, ouUri, -1, ouType );
+}
+
+void XSecController::addStreamReference(
+ const OUString& ouUri,
+ bool isBinary,
+ sal_Int32 nDigestID )
+{
+ SignatureReferenceType type = (isBinary?SignatureReferenceType::BINARYSTREAM:SignatureReferenceType::XMLSTREAM);
+
+ if (m_vInternalSignatureInformations.empty())
+ {
+ SAL_INFO("xmlsecurity.helper","XSecController::addStreamReference: no signature");
+ return;
+ }
+ InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
+
+ if ( isi.xReferenceResolvedListener.is() )
+ {
+ /*
+ * get the input stream
+ */
+ css::uno::Reference< css::io::XInputStream > xObjectInputStream
+ = getObjectInputStream( ouUri );
+
+ if ( xObjectInputStream.is() )
+ {
+ css::uno::Reference<css::xml::crypto::XUriBinding> xUriBinding
+ (isi.xReferenceResolvedListener, css::uno::UNO_QUERY);
+ xUriBinding->setUriBinding(ouUri, xObjectInputStream);
+ }
+ }
+
+ isi.addReference(type, nDigestID, ouUri, -1, OUString());
+}
+
+void XSecController::setReferenceCount() const
+{
+ if (m_vInternalSignatureInformations.empty())
+ {
+ SAL_INFO("xmlsecurity.helper","XSecController::setReferenceCount: no signature");
+ return;
+ }
+ const InternalSignatureInformation &isi =
+ m_vInternalSignatureInformations.back();
+
+ if ( !isi.xReferenceResolvedListener.is() )
+ return;
+
+ const SignatureReferenceInformations &refInfors = isi.signatureInfor.vSignatureReferenceInfors;
+
+ int refNum = refInfors.size();
+ sal_Int32 referenceCount = 0;
+
+ for(int i=0 ; i<refNum; ++i)
+ {
+ if (refInfors[i].nType == SignatureReferenceType::SAMEDOCUMENT )
+ /*
+ * same-document reference
+ */
+ {
+ referenceCount++;
+ }
+ }
+
+ css::uno::Reference<css::xml::crypto::sax::XReferenceCollector> xReferenceCollector
+ (isi.xReferenceResolvedListener, css::uno::UNO_QUERY);
+ xReferenceCollector->setReferenceCount( referenceCount );
+}
+
+void XSecController::setX509Data(
+ std::vector<std::pair<OUString, OUString>> & rX509IssuerSerials,
+ std::vector<OUString> const& rX509Certificates)
+{
+ if (m_vInternalSignatureInformations.empty())
+ {
+ SAL_INFO("xmlsecurity.helper","XSecController::setX509IssuerName: no signature");
+ return;
+ }
+ InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
+ SignatureInformation::X509Data data;
+ // due to the excessive flexibility of the spec it's possible that there
+ // is both a reference to a cert and the cert itself in one X509Data
+ for (OUString const& it : rX509Certificates)
+ {
+ try
+ {
+ data.emplace_back();
+ data.back().X509Certificate = it;
+ uno::Reference<xml::crypto::XSecurityEnvironment> const xSecEnv(m_xSecurityContext->getSecurityEnvironment());
+ uno::Reference<security::XCertificate> const xCert(xSecEnv->createCertificateFromAscii(it));
+ if (!xCert.is())
+ {
+ SAL_INFO("xmlsecurity.helper", "cannot parse X509Certificate");
+ continue; // will be handled in CheckX509Data
+ }
+ OUString const issuerName(xCert->getIssuerName());
+ OUString const serialNumber(xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber()));
+ auto const iter = std::find_if(rX509IssuerSerials.begin(), rX509IssuerSerials.end(),
+ [&](auto const& rX509IssuerSerial) {
+ return xmlsecurity::EqualDistinguishedNames(issuerName, rX509IssuerSerial.first, xmlsecurity::COMPAT_2ND)
+ && serialNumber == rX509IssuerSerial.second;
+ });
+ if (iter != rX509IssuerSerials.end())
+ {
+ data.back().X509IssuerName = iter->first;
+ data.back().X509SerialNumber = iter->second;
+ rX509IssuerSerials.erase(iter);
+ }
+ }
+ catch (uno::Exception const&)
+ {
+ SAL_INFO("xmlsecurity.helper", "cannot parse X509Certificate");
+ }
+ }
+ // now handle any that are left...
+ for (auto const& it : rX509IssuerSerials)
+ {
+ data.emplace_back();
+ data.back().X509IssuerName = it.first;
+ data.back().X509SerialNumber = it.second;
+ }
+ if (!data.empty())
+ {
+ isi.signatureInfor.X509Datas.push_back(data);
+ }
+}
+
+void XSecController::setSignatureValue( OUString const & ouSignatureValue )
+{
+ if (m_vInternalSignatureInformations.empty())
+ {
+ SAL_INFO("xmlsecurity.helper","XSecController::setSignatureValue: no signature");
+ return;
+ }
+ InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
+ isi.signatureInfor.ouSignatureValue = ouSignatureValue;
+}
+
+void XSecController::setDigestValue( sal_Int32 nDigestID, OUString const & ouDigestValue )
+{
+ if (m_vInternalSignatureInformations.empty())
+ {
+ SAL_INFO("xmlsecurity.helper","XSecController::setDigestValue: no signature");
+ return;
+ }
+ InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
+ if (isi.signatureInfor.vSignatureReferenceInfors.empty())
+ {
+ SAL_INFO("xmlsecurity.helper","XSecController::setDigestValue: no signature reference");
+ return;
+ }
+ SignatureReferenceInformation &reference =
+ isi.signatureInfor.vSignatureReferenceInfors.back();
+ reference.nDigestID = nDigestID;
+ reference.ouDigestValue = ouDigestValue;
+}
+
+void XSecController::setGpgKeyID( OUString const & ouKeyID )
+{
+ if (m_vInternalSignatureInformations.empty())
+ {
+ SAL_INFO("xmlsecurity.helper","XSecController::setGpgKeyID: no signature");
+ return;
+ }
+ InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
+ isi.signatureInfor.ouGpgKeyID = ouKeyID;
+}
+
+void XSecController::setGpgCertificate( OUString const & ouGpgCert )
+{
+ if (m_vInternalSignatureInformations.empty())
+ {
+ SAL_INFO("xmlsecurity.helper","XSecController::setGpgCertificate: no signature");
+ return;
+ }
+ InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
+ isi.signatureInfor.ouGpgCertificate = ouGpgCert;
+}
+
+void XSecController::setGpgOwner( OUString const & ouGpgOwner )
+{
+ if (m_vInternalSignatureInformations.empty())
+ {
+ SAL_INFO("xmlsecurity.helper","XSecController::setGpgOwner: no signature");
+ return;
+ }
+ InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
+ isi.signatureInfor.ouGpgOwner = ouGpgOwner;
+}
+
+void XSecController::setDate(OUString const& rId, OUString const& ouDate)
+{
+ if (m_vInternalSignatureInformations.empty())
+ {
+ SAL_INFO("xmlsecurity.helper","XSecController::setDate: no signature");
+ return;
+ }
+ InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
+ // there may be multiple timestamps in a signature - check them for consistency
+ if (!isi.signatureInfor.ouDateTime.isEmpty()
+ && isi.signatureInfor.ouDateTime != ouDate)
+ {
+ isi.signatureInfor.hasInconsistentSigningTime = true;
+ }
+ (void)utl::ISO8601parseDateTime( ouDate, isi.signatureInfor.stDateTime);
+ isi.signatureInfor.ouDateTime = ouDate;
+ if (!rId.isEmpty())
+ {
+ isi.signatureInfor.ouDateTimePropertyId = rId;
+ }
+}
+
+void XSecController::setDescription(OUString const& rId, OUString const& rDescription)
+{
+ if (m_vInternalSignatureInformations.empty())
+ return;
+
+ InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back();
+ rInformation.signatureInfor.ouDescription = rDescription;
+ if (!rId.isEmpty())
+ {
+ rInformation.signatureInfor.ouDescriptionPropertyId = rId;
+ }
+}
+
+void XSecController::setSignatureBytes(const uno::Sequence<sal_Int8>& rBytes)
+{
+ if (m_vInternalSignatureInformations.empty())
+ return;
+
+ InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back();
+ rInformation.signatureInfor.aSignatureBytes = rBytes;
+}
+
+void XSecController::setX509CertDigest(
+ OUString const& rCertDigest, sal_Int32 const /*TODO nReferenceDigestID*/,
+ std::u16string_view const& rX509IssuerName, std::u16string_view const& rX509SerialNumber)
+{
+ if (m_vInternalSignatureInformations.empty())
+ return;
+
+ InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back();
+ for (auto & rData : rInformation.signatureInfor.X509Datas)
+ {
+ for (auto & it : rData)
+ {
+ if (xmlsecurity::EqualDistinguishedNames(it.X509IssuerName, rX509IssuerName, xmlsecurity::COMPAT_BOTH)
+ && it.X509SerialNumber == rX509SerialNumber)
+ {
+ it.CertDigest = rCertDigest;
+ return;
+ }
+ }
+ }
+ // fall-back: read the actual certificates
+ for (auto & rData : rInformation.signatureInfor.X509Datas)
+ {
+ for (auto & it : rData)
+ {
+ if (!it.X509Certificate.isEmpty())
+ {
+ try
+ {
+ uno::Reference<xml::crypto::XSecurityEnvironment> const xSecEnv(m_xSecurityContext->getSecurityEnvironment());
+ uno::Reference<security::XCertificate> const xCert(xSecEnv->createCertificateFromAscii(it.X509Certificate));
+ if (!xCert.is())
+ {
+ SAL_INFO("xmlsecurity.helper", "cannot parse X509Certificate");
+ }
+ else if (xmlsecurity::EqualDistinguishedNames(xCert->getIssuerName(), rX509IssuerName, xmlsecurity::COMPAT_2ND)
+ && xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber()) == rX509SerialNumber)
+ {
+ it.CertDigest = rCertDigest;
+ // note: testInsertCertificate_PEM_DOCX requires these!
+ it.X509SerialNumber = rX509SerialNumber;
+ it.X509IssuerName = rX509IssuerName;
+ return;
+ }
+ }
+ catch (uno::Exception const&)
+ {
+ SAL_INFO("xmlsecurity.helper", "cannot parse X509Certificate");
+ }
+ }
+ }
+ }
+ if (!rInformation.signatureInfor.ouGpgCertificate.isEmpty())
+ {
+ SAL_INFO_IF(rCertDigest != rInformation.signatureInfor.ouGpgKeyID,
+ "xmlsecurity.helper", "PGPKeyID vs CertDigest mismatch");
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.helper", "cannot find X509Data for CertDigest");
+ }
+}
+
+namespace {
+Reference<css::graphic::XGraphic> lcl_getGraphicFromString(std::u16string_view rImage)
+{
+ Sequence<sal_Int8> seq;
+ comphelper::Base64::decode(seq, rImage);
+
+ Reference< graphic::XGraphic > xGraphic;
+ if( !seq.hasElements() )
+ return Reference<css::graphic::XGraphic>();
+
+ Reference< graphic::XGraphicProvider > xGraphicProvider(
+ graphic::GraphicProvider::create(comphelper::getProcessComponentContext()) );
+ Reference< io::XInputStream > xInputStream( new ::comphelper::SequenceInputStream( seq ) );
+
+ Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue("InputStream", xInputStream) };
+ xGraphic = xGraphicProvider->queryGraphic(aArgs);
+
+ return xGraphic;
+}
+}
+
+void XSecController::setValidSignatureImage(std::u16string_view rValidSigImg)
+{
+ if (m_vInternalSignatureInformations.empty() || rValidSigImg.empty())
+ return;
+
+ InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back();
+ rInformation.signatureInfor.aValidSignatureImage = lcl_getGraphicFromString(rValidSigImg);
+}
+
+void XSecController::setInvalidSignatureImage(std::u16string_view rInvalidSigImg)
+{
+ if (m_vInternalSignatureInformations.empty() || rInvalidSigImg.empty())
+ return;
+
+ InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back();
+ rInformation.signatureInfor.aInvalidSignatureImage = lcl_getGraphicFromString(rInvalidSigImg);
+}
+
+void XSecController::setSignatureLineId(const OUString& rSignatureLineId)
+{
+ if (m_vInternalSignatureInformations.empty())
+ return;
+
+ InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back();
+ rInformation.signatureInfor.ouSignatureLineId = rSignatureLineId;
+}
+
+void XSecController::addEncapsulatedX509Certificate(const OUString& rEncapsulatedX509Certificate)
+{
+ if (m_vInternalSignatureInformations.empty())
+ return;
+
+ if (rEncapsulatedX509Certificate.isEmpty())
+ return;
+
+ InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back();
+ rInformation.signatureInfor.maEncapsulatedX509Certificates.insert(rEncapsulatedX509Certificate);
+}
+
+void XSecController::setId( OUString const & ouId )
+{
+ if (m_vInternalSignatureInformations.empty())
+ {
+ SAL_INFO("xmlsecurity.helper","XSecController::setId: no signature");
+ return;
+ }
+ InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
+ isi.signatureInfor.ouSignatureId = ouId;
+}
+
+/* public: for signature verify */
+void XSecController::collectToVerify( std::u16string_view referenceId )
+{
+ /* SAL_WARN_IF( !m_xSAXEventKeeper.is(), "xmlsecurity", "the SAXEventKeeper is NULL" ); */
+
+ if ( m_eStatusOfSecurityComponents != InitializationState::INITIALIZED )
+ /*
+ * if all security components are ready, verify the signature.
+ */
+ return;
+
+ bool bJustChainingOn = false;
+ css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler;
+
+ int i,j;
+ int sigNum = m_vInternalSignatureInformations.size();
+
+ for (i=0; i<sigNum; ++i)
+ {
+ InternalSignatureInformation& isi = m_vInternalSignatureInformations[i];
+ SignatureReferenceInformations& vReferenceInfors = isi.signatureInfor.vSignatureReferenceInfors;
+ int refNum = vReferenceInfors.size();
+
+ for (j=0; j<refNum; ++j)
+ {
+ SignatureReferenceInformation &refInfor = vReferenceInfors[j];
+
+ if (refInfor.ouURI == referenceId)
+ {
+ if (chainOn())
+ {
+ bJustChainingOn = true;
+ xHandler = m_xSAXEventKeeper->setNextHandler(nullptr);
+ }
+
+ sal_Int32 nKeeperId = m_xSAXEventKeeper->addSecurityElementCollector(
+ css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY, false );
+
+ css::uno::Reference<css::xml::crypto::sax::XReferenceCollector> xReferenceCollector
+ ( isi.xReferenceResolvedListener, css::uno::UNO_QUERY );
+
+ m_xSAXEventKeeper->setSecurityId(nKeeperId, isi.signatureInfor.nSecurityId);
+ m_xSAXEventKeeper->addReferenceResolvedListener( nKeeperId, isi.xReferenceResolvedListener);
+ xReferenceCollector->setReferenceId( nKeeperId );
+
+ isi.vKeeperIds[j] = nKeeperId;
+ break;
+ }
+ }
+ }
+
+ if ( bJustChainingOn )
+ {
+ m_xSAXEventKeeper->setNextHandler(xHandler);
+ }
+}
+
+void XSecController::addSignature( sal_Int32 nSignatureId )
+{
+ SAL_WARN_IF( !m_xSecParser.is(), "xmlsecurity.helper", "No XSecParser initialized" );
+
+ m_nReservedSignatureId = nSignatureId;
+ m_bVerifyCurrentSignature = true;
+}
+
+css::uno::Reference< css::xml::sax::XDocumentHandler > const & XSecController::createSignatureReader(XMLSignatureHelper& rXMLSignatureHelper, sal_Int32 nType)
+{
+ if (nType == embed::StorageFormats::OFOPXML)
+ m_xSecParser = new OOXMLSecParser(rXMLSignatureHelper, this);
+ else
+ m_xSecParser = new XSecParser(rXMLSignatureHelper, this);
+ css::uno::Reference< css::lang::XInitialization > xInitialization(m_xSecParser, uno::UNO_QUERY);
+
+ setSAXChainConnector(xInitialization);
+
+ return m_xSecParser;
+}
+
+void XSecController::releaseSignatureReader()
+{
+ clearSAXChainConnector( );
+ m_xSecParser.clear();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/biginteger.cxx b/xmlsecurity/source/xmlsec/biginteger.cxx
new file mode 100644
index 000000000..1a4ab6fd9
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/biginteger.cxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include <biginteger.hxx>
+
+#include <xmlsec-wrapper.h>
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <comphelper/sequence.hxx>
+
+using namespace ::com::sun::star::uno ;
+
+namespace xmlsecurity
+{
+Sequence< sal_Int8 > numericStringToBigInteger ( std::u16string_view numeral )
+{
+ xmlChar* chNumeral ;
+ const xmlSecByte* bnInteger ;
+ xmlSecSize length ;
+ xmlSecBn bn ;
+
+ OString onumeral = OUStringToOString( numeral , RTL_TEXTENCODING_ASCII_US ) ;
+
+ chNumeral = xmlStrndup( reinterpret_cast<const xmlChar*>(onumeral.getStr()), static_cast<int>(onumeral.getLength()) ) ;
+
+ if( xmlSecBnInitialize( &bn, 0 ) < 0 ) {
+ xmlFree( chNumeral ) ;
+ return Sequence< sal_Int8 >();
+ }
+
+ if( xmlSecBnFromDecString( &bn, chNumeral ) < 0 ) {
+ xmlFree( chNumeral ) ;
+ xmlSecBnFinalize( &bn ) ;
+ return Sequence< sal_Int8 >();
+ }
+
+ xmlFree( chNumeral ) ;
+
+ length = xmlSecBnGetSize( &bn ) ;
+ if( length <= 0 ) {
+ xmlSecBnFinalize( &bn ) ;
+ return Sequence< sal_Int8 >();
+ }
+
+ bnInteger = xmlSecBnGetData( &bn ) ;
+ if( bnInteger == nullptr ) {
+ xmlSecBnFinalize( &bn ) ;
+ return Sequence< sal_Int8 >();
+ }
+
+ Sequence< sal_Int8 > integer = comphelper::arrayToSequence<sal_Int8>(bnInteger, length);
+
+ xmlSecBnFinalize( &bn ) ;
+ return integer ;
+}
+
+OUString bigIntegerToNumericString ( const Sequence< sal_Int8 >& integer )
+{
+ OUString aRet ;
+
+ if( integer.hasElements() ) {
+ xmlSecBn bn ;
+ xmlChar* chNumeral ;
+
+ if( xmlSecBnInitialize( &bn, 0 ) < 0 )
+ return aRet ;
+
+ if( xmlSecBnSetData( &bn, reinterpret_cast<const unsigned char*>(integer.getConstArray()), integer.getLength() ) < 0 ) {
+ xmlSecBnFinalize( &bn ) ;
+ return aRet ;
+ }
+
+ chNumeral = xmlSecBnToDecString( &bn ) ;
+ if( chNumeral == nullptr ) {
+ xmlSecBnFinalize( &bn ) ;
+ return aRet ;
+ }
+
+ aRet = OUString::createFromAscii( reinterpret_cast<char*>(chNumeral) ) ;
+
+ xmlSecBnFinalize( &bn ) ;
+ xmlFree( chNumeral ) ;
+ }
+
+ return aRet ;
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/certificateextension_certextn.cxx b/xmlsecurity/source/xmlsec/certificateextension_certextn.cxx
new file mode 100644
index 000000000..d7325759d
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/certificateextension_certextn.cxx
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include "certificateextension_certextn.hxx"
+
+#include <comphelper/sequence.hxx>
+
+CertificateExtension_CertExtn::CertificateExtension_CertExtn()
+ : m_critical(false)
+{
+}
+
+void CertificateExtension_CertExtn::setCertExtn(const unsigned char* value, unsigned int vlen,
+ const unsigned char* id, unsigned int idlen, bool critical)
+{
+ if( value != nullptr && vlen != 0 ) {
+ m_xExtnValue = comphelper::arrayToSequence<sal_Int8>(value, vlen);
+ } else {
+ m_xExtnValue = css::uno::Sequence<sal_Int8>();
+ }
+
+ if( id != nullptr && idlen != 0 ) {
+ m_xExtnId = comphelper::arrayToSequence<sal_Int8>(id, idlen);
+ } else {
+ m_xExtnId = css::uno::Sequence<sal_Int8>();
+ }
+
+ m_critical = critical ;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/certificateextension_certextn.hxx b/xmlsecurity/source/xmlsec/certificateextension_certextn.hxx
new file mode 100644
index 000000000..ac84596c8
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/certificateextension_certextn.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+#include <com/sun/star/uno/Sequence.hxx>
+
+struct CertificateExtension_CertExtn
+{
+ bool m_critical;
+ css::uno::Sequence<sal_Int8> m_xExtnId;
+ css::uno::Sequence<sal_Int8> m_xExtnValue;
+
+ CertificateExtension_CertExtn();
+ void setCertExtn(unsigned char const* value, unsigned int vlen, unsigned char const* id,
+ unsigned int idlen, bool critical);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.hxx b/xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.hxx
new file mode 100644
index 000000000..9db5867fc
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/security/XCertificateExtension.hpp>
+#include "certificateextension_certextn.hxx"
+
+class CertificateExtension_XmlSecImpl : public ::cppu::WeakImplHelper<
+ css::security::XCertificateExtension >
+{
+ private:
+ CertificateExtension_CertExtn m_Extn;
+
+ public:
+ //Methods from XCertificateExtension
+ virtual sal_Bool SAL_CALL isCritical() override
+ {
+ return m_Extn.m_critical;
+ }
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionId() override
+ {
+ return m_Extn.m_xExtnId;
+ }
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionValue() override
+ {
+ return m_Extn.m_xExtnValue;
+ }
+
+ void setCertExtn(unsigned char const * value, unsigned int vlen, unsigned char const * id, unsigned int idlen, bool critical)
+ {
+ m_Extn.setCertExtn(value, vlen, id, idlen, critical);
+ }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/errorcallback.cxx b/xmlsecurity/source/xmlsec/errorcallback.cxx
new file mode 100644
index 000000000..a535ffa77
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/errorcallback.cxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+#include <xmlsec-wrapper.h>
+
+#include <xmlsec/errorcallback.hxx>
+
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+
+#ifdef _WIN32
+#include <prewin.h>
+#include <postwin.h>
+#include <comphelper/windowserrorstring.hxx>
+#endif
+
+extern "C" {
+
+static void errorCallback(const char* file,
+ int line,
+ const char* func,
+ const char* errorObject,
+ const char* errorSubject,
+ int reason,
+ const char* msg)
+{
+ const char* pErrorObject = errorObject ? errorObject : "";
+ const char* pErrorSubject = errorSubject ? errorSubject : "";
+ const char* pMsg = msg ? msg : "";
+ OUString systemErrorString;
+
+#ifdef _WIN32
+ systemErrorString = " " + WindowsErrorString(GetLastError());
+#endif
+
+ SAL_WARN("xmlsecurity.xmlsec", file << ":" << line << ": " << func << "() '" << pErrorObject << "' '" << pErrorSubject << "' " << reason << " '" << pMsg << "'" << systemErrorString);
+}
+
+}
+
+void setErrorRecorder()
+{
+ xmlSecErrorsSetCallback(errorCallback);
+}
+
+void clearErrorRecorder()
+{
+ xmlSecErrorsSetCallback(nullptr);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx b/xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx
new file mode 100644
index 000000000..ec3cecd4a
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx
@@ -0,0 +1,229 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+#include <xmlsec-wrapper.h>
+
+#include "akmngr.hxx"
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/transforms.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/mscng/crypto.h>
+#include <xmlsec/mscng/keysstore.h>
+#include <xmlsec/mscng/x509.h>
+#include <svl/cryptosign.hxx>
+
+namespace xmlsecurity
+{
+
+/**
+ * MSCryptoAppliedKeysMngrCreate:
+ *
+ * Create and load key store and certificate database into keys manager
+ *
+ * Returns keys manager pointer on success or NULL otherwise.
+ */
+xmlSecKeysMngrPtr MSCryptoAppliedKeysMngrCreate()
+{
+ xmlSecKeysMngrPtr keyMngr = nullptr ;
+ xmlSecKeyStorePtr keyStore = nullptr ;
+
+ keyStore = xmlSecKeyStoreCreate(xmlSecMSCngKeysStoreId);
+ if (keyStore == nullptr)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ nullptr,
+ "xmlSecKeyStoreCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE) ;
+ return nullptr ;
+ }
+
+ keyMngr = xmlSecKeysMngrCreate() ;
+ if (keyMngr == nullptr)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ nullptr,
+ "xmlSecKeysMngrCreate",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE) ;
+
+ xmlSecKeyStoreDestroy(keyStore) ;
+ return nullptr ;
+ }
+
+ /*-
+ * Add key store to manager, from now on keys manager destroys the store if
+ * needed
+ */
+ if (xmlSecKeysMngrAdoptKeysStore(keyMngr, keyStore) < 0)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyStoreGetName(keyStore)),
+ "xmlSecKeysMngrAdoptKeyStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE) ;
+
+ xmlSecKeyStoreDestroy(keyStore) ;
+ xmlSecKeysMngrDestroy(keyMngr) ;
+ return nullptr ;
+ }
+
+ /*-
+ * Initialize crypto library specific data in keys manager
+ */
+ if (xmlSecMSCngKeysMngrInit(keyMngr) < 0)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ nullptr,
+ "xmlSecMSCngKeysMngrInit",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+
+ xmlSecKeysMngrDestroy(keyMngr);
+ return nullptr;
+ }
+
+ /*-
+ * Set certificate database to X509 key data store
+ */
+ /*-
+ * At present, MS Crypto engine do not provide a way to setup a cert store.
+ */
+
+ /*-
+ * Set the getKey callback
+ */
+ keyMngr->getKey = xmlSecKeysMngrGetKey ;
+
+ return keyMngr ;
+}
+
+int
+MSCryptoAppliedKeysMngrAdoptKeyStore(
+ xmlSecKeysMngrPtr mngr,
+ HCERTSTORE keyStore
+)
+{
+ xmlSecKeyDataStorePtr x509Store ;
+
+ xmlSecAssert2(mngr != nullptr, -1) ;
+ xmlSecAssert2(keyStore != nullptr, -1) ;
+
+ x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecMSCngX509StoreId);
+ if (x509Store == nullptr)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ nullptr,
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE) ;
+ return -1 ;
+ }
+
+ if (xmlSecMSCngX509StoreAdoptKeyStore(x509Store, keyStore) < 0)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(x509Store)),
+ "xmlSecMSCngX509StoreAdoptKeyStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return -1;
+ }
+
+ return 0 ;
+}
+
+int
+MSCryptoAppliedKeysMngrAdoptTrustedStore(
+ xmlSecKeysMngrPtr mngr,
+ HCERTSTORE trustedStore
+)
+{
+ xmlSecKeyDataStorePtr x509Store ;
+
+ xmlSecAssert2(mngr != nullptr, -1) ;
+ xmlSecAssert2(trustedStore != nullptr, -1) ;
+
+ x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecMSCngX509StoreId);
+ if (x509Store == nullptr)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ nullptr,
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE) ;
+ return -1 ;
+ }
+
+ if (xmlSecMSCngX509StoreAdoptTrustedStore(x509Store, trustedStore) < 0)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(x509Store)),
+ "xmlSecMSCngX509StoreAdoptKeyStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return -1;
+ }
+
+ return 0 ;
+}
+
+int
+MSCryptoAppliedKeysMngrAdoptUntrustedStore(
+ xmlSecKeysMngrPtr mngr,
+ HCERTSTORE untrustedStore
+)
+{
+ xmlSecKeyDataStorePtr x509Store ;
+
+ xmlSecAssert2(mngr != nullptr, -1) ;
+ xmlSecAssert2(untrustedStore != nullptr, -1) ;
+
+ x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecMSCngX509StoreId);
+ if (x509Store == nullptr)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ nullptr,
+ "xmlSecKeysMngrGetDataStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE) ;
+ return -1 ;
+ }
+
+ if (xmlSecMSCngX509StoreAdoptUntrustedStore(x509Store, untrustedStore) < 0)
+ {
+ xmlSecError(XMLSEC_ERRORS_HERE,
+ xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(x509Store)),
+ "xmlSecMSCngX509StoreAdoptKeyStore",
+ XMLSEC_ERRORS_R_XMLSEC_FAILED,
+ XMLSEC_ERRORS_NO_MESSAGE);
+ return -1;
+ }
+
+ return 0 ;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx b/xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx
new file mode 100644
index 000000000..e5942ba2a
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+#pragma once
+
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <wincrypt.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+
+namespace xmlsecurity
+{
+
+xmlSecKeysMngrPtr MSCryptoAppliedKeysMngrCreate();
+
+int
+MSCryptoAppliedKeysMngrAdoptKeyStore(
+ xmlSecKeysMngrPtr mngr,
+ HCERTSTORE keyStore
+) ;
+
+int
+MSCryptoAppliedKeysMngrAdoptTrustedStore(
+ xmlSecKeysMngrPtr mngr,
+ HCERTSTORE trustedStore
+) ;
+
+int
+MSCryptoAppliedKeysMngrAdoptUntrustedStore(
+ xmlSecKeysMngrPtr mngr,
+ HCERTSTORE untrustedStore
+) ;
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/oid.hxx b/xmlsecurity/source/xmlsec/mscrypt/oid.hxx
new file mode 100644
index 000000000..ce573d882
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/oid.hxx
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <sal/macros.h>
+
+typedef struct {
+ char const *oid;
+ char const *desc;
+} OIDItem;
+
+OIDItem OIDs[] = {
+ {"1.2.840.113549", "RSA Data Security Inc."},
+ {"1.2.840.113549.1", "PKCS"},
+ {"1.2.840.113549.2", "RSA digest algorithm"},
+ {"1.2.840.113549.3", "RSA cipher algorithm"},
+ {"1.2.840.113549.1.1", "PKCS #1"},
+ {"1.2.840.113549.1.2", "Unknown"},
+ {"1.2.840.113549.1.3", "Unknown"},
+ {"1.2.840.113549.1.4", "Unknown"},
+ {"1.2.840.113549.1.5", "PKCS #5"},
+ {"1.2.840.113549.1.6", "Unknown"},
+ {"1.2.840.113549.1.7", "PKCS #7"},
+ {"1.2.840.113549.1.8", "Unknown"},
+ {"1.2.840.113549.1.9", "PKCS #9"},
+ {"1.2.840.113549.1.10", "Unknown"},
+ {"1.2.840.113549.1.12", "PKCS #12"},
+ {"1.2.840.113549.1.1.2", "PKCS #1 MD2 With RSA Encryption"},
+ {"1.2.840.113549.1.1.3", "PKCS #1 MD4 With RSA Encryption"},
+ {"1.2.840.113549.1.1.4", "PKCS #1 MD5 With RSA Encryption"},
+ {"1.2.840.113549.1.1.1", "PKCS #1 RSA Encryption"},
+ {"1.2.840.113549.1.1.2", "PKCS #1 MD2 With RSA Encryption"},
+ {"1.2.840.113549.1.1.3", "PKCS #1 MD4 With RSA Encryption"},
+ {"1.2.840.113549.1.1.4", "PKCS #1 MD5 With RSA Encryption"},
+ {"1.2.840.113549.1.1.5", "PKCS #1 SHA-1 With RSA Encryption"},
+ {"1.2.840.113549.1.1.5", "PKCS #1 SHA-1 With RSA Encryption"},
+ {"1.2.840.113549.1.3.1", "Unknown"},
+ {"1.2.840.113549.1.7.1", "PKCS #7 Data"},
+ {"1.2.840.113549.1.7.2", "PKCS #7 Signed Data"},
+ {"1.2.840.113549.1.7.3", "PKCS #7 Enveloped Data"},
+ {"1.2.840.113549.1.7.4", "PKCS #7 Signed and Enveloped Data"},
+ {"1.2.840.113549.1.7.5", "PKCS #7 Digested Data"},
+ {"1.2.840.113549.1.7.6", "PKCS #7 Encrypted Data"},
+ {"1.2.840.113549.1.9.1", "PKCS #9 Email Address"},
+ {"1.2.840.113549.1.9.2", "PKCS #9 Unstructured Name"},
+ {"1.2.840.113549.1.9.3", "PKCS #9 Content Type"},
+ {"1.2.840.113549.1.9.4", "PKCS #9 Message Digest"},
+ {"1.2.840.113549.1.9.5", "PKCS #9 Signing Time"},
+ {"1.2.840.113549.1.9.6", "PKCS #9 Counter Signature"},
+ {"1.2.840.113549.1.9.7", "PKCS #9 Challenge Password"},
+ {"1.2.840.113549.1.9.8", "PKCS #9 Unstructured Address"},
+ {"1.2.840.113549.1.9.9", "PKCS #9 Extended Certificate Attributes"},
+ {"1.2.840.113549.1.9.15", "PKCS #9 S/MIME Capabilities"},
+ {"1.2.840.113549.1.9.15.1", "Unknown"},
+ {"1.2.840.113549.3.2", "RC2-CBC"},
+ {"1.2.840.113549.3.4", "RC4"},
+ {"1.2.840.113549.3.7", "DES-EDE3-CBC"},
+ {"1.2.840.113549.3.9", "RC5-CBCPad"},
+ {"1.2.840.10046", "ANSI X9.42"},
+ {"1.2.840.10046.2.1", "Diffie-Hellman Public Key Algorithm"},
+ {"1.2.840.10040", "ANSI X9.57"},
+ {"1.2.840.10040.4.1", "ANSI X9.57 DSA Signature"},
+ {"1.2.840.10040.4.3", "ANSI X9.57 Algorithm DSA Signature with SHA-1 Digest"},
+ {"2.5", "Directory"},
+ {"2.5.8", "X.500-defined algorithms"},
+ {"2.5.8.1", "X.500-defined encryption algorithms"},
+ {"2.5.8.2", "Unknown"},
+ {"2.5.8.3", "Unknown"},
+ {"2.5.8.1.1", "RSA Encryption Algorithm"},
+ {"1.3.14", "Open Systems Implementors Workshop"},
+ {"1.3.14.3.2", "OIW SECSIG Algorithm"},
+ {"1.3.14.3.2.2", "Unknown"},
+ {"1.3.14.3.2.3", "Unknown"},
+ {"1.3.14.3.2.4", "Unknown"},
+ {"1.3.14.3.2.6", "DES-ECB"},
+ {"1.3.14.3.2.7", "DES-CBC"},
+ {"1.3.14.3.2.8", "DES-OFB"},
+ {"1.3.14.3.2.9", "DES-CFB"},
+ {"1.3.14.3.2.10", "DES-MAC"},
+ {"1.3.14.3.2.11", "Unknown"},
+ {"1.3.14.3.2.12", "Unknown"},
+ {"1.3.14.3.2.13", "Unknown"},
+ {"1.3.14.3.2.14", "Unknown"},
+ {"1.3.14.3.2.15", "ISO SHA with RSA Signature"},
+ {"1.3.14.3.2.16", "Unknown"},
+ {"1.3.14.3.2.17", "DES-EDE"},
+ {"1.3.14.3.2.18", "Unknown"},
+ {"1.3.14.3.2.19", "Unknown"},
+ {"1.3.14.3.2.20", "Unknown"},
+ {"1.3.14.3.2.21", "Unknown"},
+ {"1.3.14.3.2.22", "Unknown"},
+ {"1.3.14.3.2.23", "Unknown"},
+ {"1.3.14.3.2.24", "Unknown"},
+ {"1.3.14.3.2.25", "Unknown"},
+ {"1.3.14.3.2.26", "SHA-1"},
+ {"1.3.14.3.2.27", "Forgezza DSA Signature with SHA-1 Digest"},
+ {"1.3.14.3.2.28", "Unknown"},
+ {"1.3.14.3.2.29", "Unknown"},
+ {"1.3.14.7.2", "Unknown"},
+ {"1.3.14.7.2.1", "Unknown"},
+ {"1.3.14.7.2.2", "Unknown"},
+ {"1.3.14.7.2.3", "Unknown"},
+ {"1.3.14.7.2.2.1", "Unknown"},
+ {"1.3.14.7.2.3.1", "Unknown"},
+ {"2.16.840.1.101.2.1", "US DOD Infosec"},
+ {"2.16.840.1.101.2.1.1.1", "Unknown"},
+ {"2.16.840.1.101.2.1.1.2", "MISSI DSS Algorithm (Old)"},
+ {"2.16.840.1.101.2.1.1.3", "Unknown"},
+ {"2.16.840.1.101.2.1.1.4", "Skipjack CBC64"},
+ {"2.16.840.1.101.2.1.1.5", "Unknown"},
+ {"2.16.840.1.101.2.1.1.6", "Unknown"},
+ {"2.16.840.1.101.2.1.1.7", "Unknown"},
+ {"2.16.840.1.101.2.1.1.8", "Unknown"},
+ {"2.16.840.1.101.2.1.1.9", "Unknown"},
+ {"2.16.840.1.101.2.1.1.10", "MISSI KEA Algorithm"},
+ {"2.16.840.1.101.2.1.1.11", "Unknown"},
+ {"2.16.840.1.101.2.1.1.12", "MISSI KEA and DSS Algorithm (Old)"},
+ {"2.16.840.1.101.2.1.1.13", "Unknown"},
+ {"2.16.840.1.101.2.1.1.14", "Unknown"},
+ {"2.16.840.1.101.2.1.1.15", "Unknown"},
+ {"2.16.840.1.101.2.1.1.16", "Unknown"},
+ {"2.16.840.1.101.2.1.1.17", "Unknown"},
+ {"2.16.840.1.101.2.1.1.18", "Unknown"},
+ {"2.16.840.1.101.2.1.1.19", "MISSI DSS Algorithm"},
+ {"2.16.840.1.101.2.1.1.20", "MISSI KEA and DSS Algorithm"},
+ {"2.16.840.1.101.2.1.1.21", "Unknown"},
+ {"1.2.643.2.2.35.0", "GOST_R_34.10-2001_Test"},
+ {"1.2.643.2.2.35.1", "GOST_R_34.10-2001_Sign_DH_PRO"},
+ {"1.2.643.2.2.35.2", "GOST_R_34.10-2001_Sign_DH_CARD"},
+ {"1.2.643.2.2.35.3", "GOST_R_34.10-2001_Sign_DH"},
+ {"1.2.643.2.2.36.0", "GOST_R_34.10-2001_Sign_DH_PRO"}
+};
+
+const int nOID = SAL_N_ELEMENTS(OIDs);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx
new file mode 100644
index 000000000..6ded5fa0c
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include <rtl/uuid.h>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/security/ExtAltNameType.hpp>
+#include <com/sun/star/security/CertAltNameEntry.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <comphelper/sequence.hxx>
+#include <o3tl/char16_t2wchar_t.hxx>
+
+#include "sanextension_mscryptimpl.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno ;
+using namespace ::com::sun::star::security ;
+
+using ::com::sun::star::security::XCertificateExtension ;
+
+
+SanExtensionImpl::SanExtensionImpl() :
+ m_critical( false )
+{
+}
+
+SanExtensionImpl::~SanExtensionImpl() {
+}
+
+
+//Methods from XCertificateExtension
+sal_Bool SAL_CALL SanExtensionImpl::isCritical() {
+ return m_critical ;
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL SanExtensionImpl::getExtensionId() {
+ return m_xExtnId ;
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL SanExtensionImpl::getExtensionValue() {
+ return m_xExtnValue ;
+}
+
+//Methods from XSanExtension
+css::uno::Sequence< css::security::CertAltNameEntry > SAL_CALL SanExtensionImpl::getAlternativeNames(){
+
+ if (!m_Entries.hasElements())
+ {
+ CERT_ALT_NAME_INFO *subjectName;
+ DWORD size;
+ CryptDecodeObjectEx(X509_ASN_ENCODING, X509_ALTERNATE_NAME, reinterpret_cast<unsigned char*>(m_xExtnValue.getArray()), m_xExtnValue.getLength(), CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, nullptr,&subjectName, &size);
+
+ auto arrCertAltNameEntry = std::make_unique<CertAltNameEntry[]>(subjectName->cAltEntry);
+
+ for (unsigned int i = 0; i < static_cast<unsigned int>(subjectName->cAltEntry); i++){
+ PCERT_ALT_NAME_ENTRY pEntry = &subjectName->rgAltEntry[i];
+
+ switch(pEntry->dwAltNameChoice) {
+ case CERT_ALT_NAME_OTHER_NAME :
+ {
+ arrCertAltNameEntry[i].Type = ExtAltNameType_OTHER_NAME;
+ PCERT_OTHER_NAME pOtherName = pEntry->pOtherName;
+
+ css::beans::NamedValue otherNameProp;
+ otherNameProp.Name = OUString::createFromAscii(pOtherName->pszObjId);
+
+ Sequence< sal_Int8 > otherName( comphelper::arrayToSequence<sal_Int8>(
+ pOtherName->Value.pbData, pOtherName->Value.cbData) );
+ otherNameProp.Value <<= otherName;
+
+ arrCertAltNameEntry[i].Value <<= otherNameProp;
+ break;
+ }
+ case CERT_ALT_NAME_RFC822_NAME :
+ arrCertAltNameEntry[i].Type = ExtAltNameType_RFC822_NAME;
+ arrCertAltNameEntry[i].Value <<= OUString(o3tl::toU(pEntry->pwszRfc822Name));
+ break;
+ case CERT_ALT_NAME_DNS_NAME :
+ arrCertAltNameEntry[i].Type = ExtAltNameType_DNS_NAME;
+ arrCertAltNameEntry[i].Value <<= OUString(o3tl::toU(pEntry->pwszDNSName));
+ break;
+ case CERT_ALT_NAME_DIRECTORY_NAME :
+ {
+ arrCertAltNameEntry[i].Type = ExtAltNameType_DIRECTORY_NAME;
+ break;
+ }
+ case CERT_ALT_NAME_URL :
+ arrCertAltNameEntry[i].Type = ExtAltNameType_URL;
+ arrCertAltNameEntry[i].Value <<= OUString(o3tl::toU(pEntry->pwszURL));
+ break;
+ case CERT_ALT_NAME_IP_ADDRESS :
+ {
+ arrCertAltNameEntry[i].Type = ExtAltNameType_IP_ADDRESS;
+
+ Sequence< sal_Int8 > ipAddress( comphelper::arrayToSequence<sal_Int8>(
+ pEntry->IPAddress.pbData, pEntry->IPAddress.cbData) );
+ arrCertAltNameEntry[i].Value <<= ipAddress;
+ break;
+ }
+ case CERT_ALT_NAME_REGISTERED_ID :
+ arrCertAltNameEntry[i].Type = ExtAltNameType_REGISTERED_ID;
+ arrCertAltNameEntry[i].Value <<= OUString::createFromAscii(pEntry->pszRegisteredID);
+ break;
+ }
+ }
+ m_Entries = ::comphelper::arrayToSequence< css::security::CertAltNameEntry >(arrCertAltNameEntry.get(), subjectName->cAltEntry);
+ }
+
+ return m_Entries;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx
new file mode 100644
index 000000000..6c65c84f8
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <Windows.h>
+#include <WinCrypt.h>
+#include <sal/config.h>
+#include <rtl/ustring.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/uno/SecurityException.hpp>
+#include <com/sun/star/security/XCertificateExtension.hpp>
+#include <com/sun/star/security/XSanExtension.hpp>
+#include <com/sun/star/security/CertAltNameEntry.hpp>
+
+class SanExtensionImpl : public ::cppu::WeakImplHelper<
+ css::security::XSanExtension >
+{
+ private:
+ bool m_critical ;
+ css::uno::Sequence< sal_Int8 > m_xExtnId ;
+ css::uno::Sequence< sal_Int8 > m_xExtnValue ;
+
+ css::uno::Sequence< css::security::CertAltNameEntry > m_Entries;
+
+ public:
+ SanExtensionImpl() ;
+ virtual ~SanExtensionImpl() override;
+
+ //Methods from XCertificateExtension
+ virtual sal_Bool SAL_CALL isCritical() override;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionId() override;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionValue() override;
+
+ //Methods from XSanExtension
+
+ virtual css::uno::Sequence< css::security::CertAltNameEntry > SAL_CALL getAlternativeNames() override;
+
+ //Helper method
+ void setCertExtn( unsigned char* value, unsigned int vlen, unsigned char* id, unsigned int idlen, bool critical ) ;
+} ;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx
new file mode 100644
index 000000000..f198f839f
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx
@@ -0,0 +1,1118 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+
+#include <cstddef>
+#include <string.h>
+
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <Windows.h>
+#include <WinCrypt.h>
+#include <sal/macros.h>
+#include <osl/thread.h>
+#include "securityenvironment_mscryptimpl.hxx"
+
+#include "x509certificate_mscryptimpl.hxx"
+#include <comphelper/servicehelper.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <xmlsec-wrapper.h>
+#include "akmngr.hxx"
+
+#include <biginteger.hxx>
+
+#include <comphelper/windowserrorstring.hxx>
+#include <sal/log.hxx>
+#include <rtl/locale.h>
+#include <rtl/ref.hxx>
+#include <osl/nlsupport.h>
+#include <osl/process.h>
+#include <o3tl/char16_t2wchar_t.hxx>
+#include <svl/cryptosign.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang ;
+using ::com::sun::star::lang::XMultiServiceFactory ;
+using ::com::sun::star::lang::XSingleServiceFactory ;
+
+using ::com::sun::star::xml::crypto::XSecurityEnvironment ;
+using ::com::sun::star::security::XCertificate ;
+
+static rtl::Reference<X509Certificate_MSCryptImpl> MswcryCertContextToXCert( PCCERT_CONTEXT cert ) ;
+
+namespace {
+
+struct CertErrorToString{
+ DWORD error;
+ char const * name;
+};
+
+}
+
+CertErrorToString const arErrStrings[] =
+{
+ { 0x00000000, "CERT_TRUST_NO_ERROR"},
+ { 0x00000001, "CERT_TRUST_IS_NOT_TIME_VALID"},
+ { 0x00000002, "CERT_TRUST_IS_NOT_TIME_NESTED"},
+ { 0x00000004, "CERT_TRUST_IS_REVOKED" },
+ { 0x00000008, "CERT_TRUST_IS_NOT_SIGNATURE_VALID" },
+ { 0x00000010, "CERT_TRUST_IS_NOT_SIGNATURE_VALID"},
+ { 0x00000020, "CERT_TRUST_IS_UNTRUSTED_ROOT"},
+ { 0x00000040, "CERT_TRUST_REVOCATION_STATUS_UNKNOWN"},
+ { 0x00000080, "CERT_TRUST_IS_CYCLIC"},
+ { 0x00000100, "CERT_TRUST_INVALID_EXTENSION"},
+ { 0x00000200, "CERT_TRUST_INVALID_POLICY_CONSTRAINTS"},
+ { 0x00000400, "CERT_TRUST_INVALID_BASIC_CONSTRAINTS"},
+ { 0x00000800, "CERT_TRUST_INVALID_NAME_CONSTRAINTS"},
+ { 0x00001000, "CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT"},
+ { 0x00002000, "CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT"},
+ { 0x00004000, "CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT"},
+ { 0x00008000, "CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT"},
+ { 0x01000000, "CERT_TRUST_IS_OFFLINE_REVOCATION"},
+ { 0x02000000, "CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY"},
+ { 0x04000000, "CERT_TRUST_IS_EXPLICIT_DISTRUST"},
+ { 0x08000000, "CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT"},
+ //Chain errors
+ { 0x00010000, "CERT_TRUST_IS_PARTIAL_CHAIN"},
+ { 0x00020000, "CERT_TRUST_CTL_IS_NOT_TIME_VALID"},
+ { 0x00040000, "CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID"},
+ { 0x00080000, "CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE"}
+};
+
+static void traceTrustStatus(DWORD err)
+{
+ if (err == 0)
+ SAL_INFO("xmlsecurity.xmlsec", " " << arErrStrings[0].name);
+ for (std::size_t i = 1; i < SAL_N_ELEMENTS(arErrStrings); i++)
+ {
+ if (arErrStrings[i].error & err)
+ SAL_INFO("xmlsecurity.xmlsec", " " << arErrStrings[i].name);
+ }
+}
+
+SecurityEnvironment_MSCryptImpl::SecurityEnvironment_MSCryptImpl( const uno::Reference< uno::XComponentContext >& xContext ) : m_hProv( 0 ) , m_pszContainer( nullptr ) , m_hKeyStore( nullptr ), m_hCertStore( nullptr ), m_hMySystemStore(nullptr), m_hRootSystemStore(nullptr), m_hTrustSystemStore(nullptr), m_hCaSystemStore(nullptr), m_bEnableDefault( false ){
+
+ m_xServiceManager.set(xContext, uno::UNO_QUERY);
+}
+
+SecurityEnvironment_MSCryptImpl::~SecurityEnvironment_MSCryptImpl() {
+
+ if( m_hProv != 0 ) {
+ CryptReleaseContext( m_hProv, 0 ) ;
+ m_hProv = 0 ;
+ }
+
+ if( m_pszContainer != nullptr ) {
+ //TODO: Don't know whether or not it should be released now.
+ m_pszContainer = nullptr ;
+ }
+
+ if( m_hCertStore != nullptr ) {
+ CertCloseStore( m_hCertStore, CERT_CLOSE_STORE_FORCE_FLAG ) ;
+ m_hCertStore = nullptr ;
+ }
+
+ if( m_hKeyStore != nullptr ) {
+ CertCloseStore( m_hKeyStore, CERT_CLOSE_STORE_FORCE_FLAG ) ;
+ m_hKeyStore = nullptr ;
+ }
+
+ //i120675, close the store handles
+ if( m_hMySystemStore != nullptr ) {
+ CertCloseStore( m_hMySystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
+ m_hMySystemStore = nullptr ;
+ }
+
+ if( m_hRootSystemStore != nullptr ) {
+ CertCloseStore( m_hRootSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
+ m_hRootSystemStore = nullptr ;
+ }
+
+ if( m_hTrustSystemStore != nullptr ) {
+ CertCloseStore( m_hTrustSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
+ m_hTrustSystemStore = nullptr ;
+ }
+
+ if( m_hCaSystemStore != nullptr ) {
+ CertCloseStore( m_hCaSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
+ m_hCaSystemStore = nullptr ;
+ }
+}
+
+/* XServiceInfo */
+OUString SAL_CALL SecurityEnvironment_MSCryptImpl::getImplementationName() {
+ return "com.sun.star.xml.crypto.SecurityEnvironment";
+}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL SecurityEnvironment_MSCryptImpl::supportsService( const OUString& serviceName) {
+ return cppu::supportsService(this, serviceName);
+}
+/* XServiceInfo */
+uno::Sequence< OUString > SAL_CALL SecurityEnvironment_MSCryptImpl::getSupportedServiceNames() {
+ return { "com.sun.star.xml.crypto.SecurityEnvironment" };
+}
+
+/* XUnoTunnel */
+UNO3_GETIMPLEMENTATION_IMPL(SecurityEnvironment_MSCryptImpl);
+
+HCRYPTPROV SecurityEnvironment_MSCryptImpl::getCryptoProvider() {
+ return m_hProv ;
+}
+
+void SecurityEnvironment_MSCryptImpl::setCryptoProvider( HCRYPTPROV aProv ) {
+ if( m_hProv != 0 ) {
+ CryptReleaseContext( m_hProv, 0 ) ;
+ m_hProv = 0 ;
+ }
+
+ if( aProv != 0 ) {
+ m_hProv = aProv ;
+ }
+}
+
+LPCTSTR SecurityEnvironment_MSCryptImpl::getKeyContainer() {
+ return m_pszContainer ;
+}
+
+void SecurityEnvironment_MSCryptImpl::setKeyContainer( LPCTSTR aKeyContainer ) {
+ //TODO: Don't know whether or not it should be copied.
+ m_pszContainer = aKeyContainer ;
+}
+
+
+HCERTSTORE SecurityEnvironment_MSCryptImpl::getCryptoSlot() {
+ return m_hKeyStore ;
+}
+
+void SecurityEnvironment_MSCryptImpl::setCryptoSlot( HCERTSTORE aSlot) {
+ if( m_hKeyStore != nullptr ) {
+ CertCloseStore( m_hKeyStore, CERT_CLOSE_STORE_FORCE_FLAG ) ;
+ m_hKeyStore = nullptr ;
+ }
+
+ if( aSlot != nullptr ) {
+ m_hKeyStore = CertDuplicateStore( aSlot ) ;
+ }
+}
+
+HCERTSTORE SecurityEnvironment_MSCryptImpl::getCertDb() {
+ return m_hCertStore ;
+}
+
+void SecurityEnvironment_MSCryptImpl::setCertDb( HCERTSTORE aCertDb ) {
+ if( m_hCertStore != nullptr ) {
+ CertCloseStore( m_hCertStore, CERT_CLOSE_STORE_FORCE_FLAG ) ;
+ m_hCertStore = nullptr ;
+ }
+
+ if( aCertDb != nullptr ) {
+ m_hCertStore = CertDuplicateStore( aCertDb ) ;
+ }
+}
+
+#ifdef SAL_LOG_INFO
+
+// Based on sample code from MSDN
+
+static OUString get_system_name(const void *pvSystemStore,
+ DWORD dwFlags)
+{
+ LPCWSTR ppwszSystemName;
+ if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
+ {
+ _CERT_SYSTEM_STORE_RELOCATE_PARA const * pRelocatePara;
+ pRelocatePara = static_cast<_CERT_SYSTEM_STORE_RELOCATE_PARA const *>(pvSystemStore);
+ ppwszSystemName = pRelocatePara->pwszSystemStore;
+ }
+ else
+ {
+ ppwszSystemName = static_cast<LPCWSTR>(pvSystemStore);
+ }
+ return OUString(o3tl::toU(ppwszSystemName));
+}
+
+extern "C" {
+
+static BOOL WINAPI cert_enum_physical_store_callback(const void *,
+ DWORD dwFlags,
+ LPCWSTR pwszStoreName,
+ PCERT_PHYSICAL_STORE_INFO,
+ void *,
+ void *)
+{
+ OUString name(o3tl::toU(pwszStoreName));
+ if (dwFlags & CERT_PHYSICAL_STORE_PREDEFINED_ENUM_FLAG)
+ name += " (implicitly created)";
+ SAL_INFO("xmlsecurity.xmlsec", " Physical store: " << name);
+
+ return TRUE;
+}
+
+static BOOL WINAPI cert_enum_system_store_callback(const void *pvSystemStore,
+ DWORD dwFlags,
+ PCERT_SYSTEM_STORE_INFO,
+ void *,
+ void *)
+{
+ SAL_INFO("xmlsecurity.xmlsec", "System store: " << get_system_name(pvSystemStore, dwFlags));
+
+ if (!CertEnumPhysicalStore(pvSystemStore,
+ dwFlags,
+ nullptr,
+ cert_enum_physical_store_callback))
+ {
+ DWORD dwErr = GetLastError();
+ if (!(ERROR_FILE_NOT_FOUND == dwErr ||
+ ERROR_NOT_SUPPORTED == dwErr))
+ {
+ SAL_WARN("xmlsecurity.xmlsec", "CertEnumPhysicalStore failed:" << WindowsErrorString(GetLastError()));
+ }
+ }
+ return TRUE;
+}
+
+}
+
+#endif
+
+//Methods from XSecurityEnvironment
+uno::Sequence< uno::Reference < XCertificate > > SecurityEnvironment_MSCryptImpl::getPersonalCertificates()
+{
+ sal_Int32 length ;
+ rtl::Reference<X509Certificate_MSCryptImpl> xcert ;
+ std::vector< rtl::Reference<X509Certificate_MSCryptImpl> > certsList ;
+ PCCERT_CONTEXT pCertContext = nullptr;
+
+ //firstly, we try to find private keys in given key store.
+ if( m_hKeyStore != nullptr ) {
+ pCertContext = CertEnumCertificatesInStore( m_hKeyStore, pCertContext );
+ while (pCertContext)
+ {
+ xcert = MswcryCertContextToXCert( pCertContext ) ;
+ if( xcert.is() )
+ certsList.push_back( xcert ) ;
+ pCertContext = CertEnumCertificatesInStore( m_hKeyStore, pCertContext );
+ }
+ }
+
+ //Thirdly, we try to find certificate from system default key store.
+ if( m_bEnableDefault ) {
+ HCERTSTORE hSystemKeyStore ;
+ DWORD dwKeySpec;
+ NCRYPT_KEY_HANDLE hCryptKey;
+
+#ifdef SAL_LOG_INFO
+ CertEnumSystemStore(CERT_SYSTEM_STORE_CURRENT_USER, nullptr, nullptr, cert_enum_system_store_callback);
+#endif
+
+ hSystemKeyStore = CertOpenSystemStoreW( 0, L"MY" ) ;
+ if( hSystemKeyStore != nullptr ) {
+ pCertContext = CertEnumCertificatesInStore( hSystemKeyStore, pCertContext );
+ while (pCertContext)
+ {
+ // for checking whether the certificate is a personal certificate or not.
+ DWORD dwFlags = CRYPT_ACQUIRE_COMPARE_KEY_FLAG | CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG;
+ HCRYPTPROV_OR_NCRYPT_KEY_HANDLE* phCryptProvOrNCryptKey = &hCryptKey;
+ if(!(CryptAcquireCertificatePrivateKey(pCertContext,
+ dwFlags,
+ nullptr,
+ phCryptProvOrNCryptKey,
+ &dwKeySpec,
+ nullptr)))
+ {
+ // Not Privatekey found. SKIP this one.
+ pCertContext = CertEnumCertificatesInStore( hSystemKeyStore, pCertContext );
+ continue;
+ }
+ // then TODO : Check the personal cert is valid or not.
+
+ xcert = MswcryCertContextToXCert( pCertContext ) ;
+ if( xcert.is() )
+ certsList.push_back( xcert ) ;
+ pCertContext = CertEnumCertificatesInStore( hSystemKeyStore, pCertContext );
+ }
+ }
+
+ CertCloseStore( hSystemKeyStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
+ }
+
+ length = certsList.size() ;
+ if( length != 0 ) {
+ int i = 0;
+ uno::Sequence< uno::Reference< XCertificate > > certSeq( length ) ;
+ auto pcertSeq = certSeq.getArray();
+
+ for( const auto& rXCert : certsList ) {
+ pcertSeq[i] = rXCert ;
+ ++i;
+ }
+
+ return certSeq ;
+ }
+
+ return uno::Sequence< uno::Reference< XCertificate > >() ;
+}
+
+
+uno::Reference< XCertificate > SecurityEnvironment_MSCryptImpl::getCertificate( const OUString& issuerName, const uno::Sequence< sal_Int8 >& serialNumber ) {
+ unsigned int i ;
+ rtl::Reference<X509Certificate_MSCryptImpl> xcert ;
+ PCCERT_CONTEXT pCertContext = nullptr ;
+ HCERTSTORE hCertStore = nullptr ;
+ CRYPT_INTEGER_BLOB cryptSerialNumber ;
+ CERT_INFO certInfo ;
+
+ // for correct encoding
+ rtl_Locale *pLocale = nullptr ;
+ osl_getProcessLocale( &pLocale ) ;
+
+ //Create cert info from issue and serial
+ LPCWSTR pszName = o3tl::toW( issuerName.getStr() );
+
+ if( ! ( CertStrToNameW(
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
+ pszName ,
+ CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG,
+ nullptr ,
+ nullptr ,
+ &certInfo.Issuer.cbData, nullptr ) )
+ ) {
+ return nullptr ;
+ }
+
+ certInfo.Issuer.pbData = static_cast<BYTE*>(malloc( certInfo.Issuer.cbData ));
+ if(!certInfo.Issuer.pbData)
+ throw uno::RuntimeException() ;
+
+ if( ! ( CertStrToNameW(
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
+ pszName ,
+ CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG,
+ nullptr ,
+ certInfo.Issuer.pbData ,
+ &certInfo.Issuer.cbData, nullptr ) )
+ ) {
+ free( certInfo.Issuer.pbData ) ;
+ return nullptr ;
+ }
+
+ //Get the SerialNumber
+ cryptSerialNumber.cbData = serialNumber.getLength() ;
+ cryptSerialNumber.pbData = static_cast<BYTE*>(malloc( cryptSerialNumber.cbData));
+ if (!cryptSerialNumber.pbData)
+ {
+ free( certInfo.Issuer.pbData ) ;
+ throw uno::RuntimeException() ;
+ }
+ for( i = 0; i < cryptSerialNumber.cbData; i ++ )
+ cryptSerialNumber.pbData[i] = serialNumber[ cryptSerialNumber.cbData - i - 1 ] ;
+
+ certInfo.SerialNumber.cbData = cryptSerialNumber.cbData ;
+ certInfo.SerialNumber.pbData = cryptSerialNumber.pbData ;
+
+ // Get the Cert from all store.
+ for( i = 0 ; i < 6 ; i ++ )
+ {
+ switch(i)
+ {
+ case 0:
+ if(m_hKeyStore == nullptr) continue ;
+ hCertStore = m_hKeyStore ;
+ break;
+ case 1:
+ if(m_hCertStore == nullptr) continue ;
+ hCertStore = m_hCertStore ;
+ break;
+ case 2:
+ hCertStore = CertOpenSystemStoreW( 0, L"MY" ) ;
+ if(hCertStore == nullptr || !m_bEnableDefault) continue ;
+ break;
+ case 3:
+ hCertStore = CertOpenSystemStoreW( 0, L"Root" ) ;
+ if(hCertStore == nullptr || !m_bEnableDefault) continue ;
+ break;
+ case 4:
+ hCertStore = CertOpenSystemStoreW( 0, L"Trust" ) ;
+ if(hCertStore == nullptr || !m_bEnableDefault) continue ;
+ break;
+ case 5:
+ hCertStore = CertOpenSystemStoreW( 0, L"CA" ) ;
+ if(hCertStore == nullptr || !m_bEnableDefault) continue ;
+ break;
+ default:
+ i=6;
+ continue;
+ }
+
+/*******************************************************************************
+ * This code reserved for remind us there are another way to find one cert by
+ * IssuerName&serialnumber. You can use the code to replaced the function
+ * CertFindCertificateInStore IF and ONLY IF you must find one special cert in
+ * certStore but can not be found by CertFindCertificateInStore , then , you
+ * should also change the same part in libxmlsec/.../src/mscrypto/x509vfy.c#875.
+ * By Chandler Peng(chandler.peng@sun.com)
+ *****/
+/*******************************************************************************
+ pCertContext = NULL ;
+ found = 0;
+ do{
+ // 1. enum the certs has same string in the issuer string.
+ pCertContext = CertEnumCertificatesInStore( hCertStore , pCertContext ) ;
+ if( pCertContext != NULL )
+ {
+ // 2. check the cert's issuer name .
+ char* issuer = NULL ;
+ DWORD cbIssuer = 0 ;
+
+ cbIssuer = CertNameToStr(
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
+ &( pCertContext->pCertInfo->Issuer ),
+ CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
+ NULL, 0
+ ) ;
+
+ if( cbIssuer == 0 ) continue ; // discard this cert;
+
+ issuer = (char *)malloc( cbIssuer ) ;
+ if( issuer == NULL ) // discard this cert;
+ {
+ free( cryptSerialNumber.pbData) ;
+ free( certInfo.Issuer.pbData ) ;
+ CertFreeCertificateContext( pCertContext ) ;
+ if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
+ throw RuntimeException() ;
+ }
+
+ cbIssuer = CertNameToStr(
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
+ &( pCertContext->pCertInfo->Issuer ),
+ CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
+ issuer, cbIssuer
+ ) ;
+
+ if( cbIssuer <= 0 )
+ {
+ free( issuer ) ;
+ continue ;// discard this cert;
+ }
+
+ if(strncmp(pszName , issuer , cbIssuer) != 0)
+ {
+ free( issuer ) ;
+ continue ;// discard this cert;
+ }
+ free( issuer ) ;
+
+ // 3. check the serial number.
+ if( memcmp( cryptSerialNumber.pbData , pCertContext->pCertInfo->SerialNumber.pbData , cryptSerialNumber.cbData ) != 0 )
+ {
+ continue ;// discard this cert;
+ }
+
+ // 4. confirm and break;
+ found = 1;
+ break ;
+ }
+
+ }while(pCertContext);
+
+ if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
+ if( found != 0 ) break; // Found the certificate.
+********************************************************************************/
+
+ pCertContext = CertFindCertificateInStore(
+ hCertStore,
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ 0,
+ CERT_FIND_SUBJECT_CERT,
+ &certInfo,
+ nullptr
+ ) ;
+
+ if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
+ if( pCertContext != nullptr ) break ; // Found the certificate.
+
+ }
+
+ free(cryptSerialNumber.pbData);
+ free(certInfo.Issuer.pbData);
+
+ if( pCertContext != nullptr ) {
+ xcert = MswcryCertContextToXCert(pCertContext);
+ CertFreeCertificateContext(pCertContext);
+ }
+
+ return xcert ;
+}
+
+uno::Reference< XCertificate > SecurityEnvironment_MSCryptImpl::getCertificate( const OUString& issuerName, const OUString& serialNumber ) {
+ uno::Sequence< sal_Int8 > serial = xmlsecurity::numericStringToBigInteger( serialNumber ) ;
+ return getCertificate( issuerName, serial ) ;
+}
+
+uno::Sequence< uno::Reference < XCertificate > > SecurityEnvironment_MSCryptImpl::buildCertificatePath( const uno::Reference< XCertificate >& begin ) {
+ PCCERT_CHAIN_CONTEXT pChainContext ;
+ PCCERT_CONTEXT pCertContext ;
+
+ CERT_ENHKEY_USAGE enhKeyUsage ;
+ CERT_USAGE_MATCH certUsage ;
+ CERT_CHAIN_PARA chainPara ;
+
+ enhKeyUsage.cUsageIdentifier = 0 ;
+ enhKeyUsage.rgpszUsageIdentifier = nullptr ;
+ certUsage.dwType = USAGE_MATCH_TYPE_AND ;
+ certUsage.Usage = enhKeyUsage ;
+ chainPara.cbSize = sizeof( CERT_CHAIN_PARA ) ;
+ chainPara.RequestedUsage = certUsage ;
+
+ uno::Reference< XUnoTunnel > xCertTunnel( begin, uno::UNO_QUERY_THROW ) ;
+ const auto* xcert = comphelper::getFromUnoTunnel<X509Certificate_MSCryptImpl>(xCertTunnel);
+ if( xcert == nullptr ) {
+ throw uno::RuntimeException() ;
+ }
+
+ pCertContext = xcert->getMswcryCert() ;
+
+ pChainContext = nullptr ;
+
+ bool bChain = false;
+ if( pCertContext != nullptr )
+ {
+ HCERTSTORE hAdditionalStore = nullptr;
+ HCERTSTORE hCollectionStore = nullptr;
+ if (m_hCertStore && m_hKeyStore)
+ {
+ //Merge m_hCertStore and m_hKeyStore into one store.
+ hCollectionStore = CertOpenStore(
+ CERT_STORE_PROV_COLLECTION ,
+ 0 ,
+ 0 ,
+ 0 ,
+ nullptr
+ ) ;
+ if (hCollectionStore != nullptr)
+ {
+ CertAddStoreToCollection (
+ hCollectionStore ,
+ m_hCertStore ,
+ CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG ,
+ 0) ;
+ CertAddStoreToCollection (
+ hCollectionStore ,
+ m_hKeyStore,
+ CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG ,
+ 0) ;
+ hAdditionalStore = hCollectionStore;
+ }
+
+ }
+
+ //if the merge of both stores failed then we add only m_hCertStore
+ if (hAdditionalStore == nullptr && m_hCertStore)
+ hAdditionalStore = m_hCertStore;
+ else if (hAdditionalStore == nullptr && m_hKeyStore)
+ hAdditionalStore = m_hKeyStore;
+ else
+ hAdditionalStore = nullptr;
+
+ //CertGetCertificateChain searches by default in MY, CA, ROOT and TRUST
+ bChain = CertGetCertificateChain(
+ nullptr ,
+ pCertContext ,
+ nullptr , //use current system time
+ hAdditionalStore,
+ &chainPara ,
+ CERT_CHAIN_REVOCATION_CHECK_CHAIN | CERT_CHAIN_TIMESTAMP_TIME ,
+ nullptr ,
+ &pChainContext);
+ if (!bChain)
+ pChainContext = nullptr;
+
+ //Close the additional store
+ CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_CHECK_FLAG);
+ }
+
+ if(bChain && pChainContext != nullptr && pChainContext->cChain > 0 )
+ {
+ PCCERT_CONTEXT pCertInChain ;
+ PCERT_SIMPLE_CHAIN pCertChain ;
+ rtl::Reference<X509Certificate_MSCryptImpl> pCert ;
+
+ pCertChain = pChainContext->rgpChain[0] ;
+ if( pCertChain->cElement ) {
+ uno::Sequence< uno::Reference< XCertificate > > xCertChain( pCertChain->cElement ) ;
+ auto pxCertChain = xCertChain.getArray();
+
+ for( unsigned int i = 0 ; i < pCertChain->cElement ; i ++ ) {
+ if( pCertChain->rgpElement[i] )
+ pCertInChain = pCertChain->rgpElement[i]->pCertContext ;
+ else
+ pCertInChain = nullptr ;
+
+ if( pCertInChain != nullptr ) {
+ pCert = MswcryCertContextToXCert( pCertInChain ) ;
+ if( pCert.is() )
+ pxCertChain[i] = pCert ;
+ }
+ }
+
+ CertFreeCertificateChain( pChainContext ) ;
+ pChainContext = nullptr ;
+
+ return xCertChain ;
+ }
+ }
+ if (pChainContext)
+ CertFreeCertificateChain(pChainContext);
+
+ return uno::Sequence< uno::Reference < XCertificate > >();
+}
+
+uno::Reference< XCertificate > SecurityEnvironment_MSCryptImpl::createCertificateFromRaw( const uno::Sequence< sal_Int8 >& rawCertificate ) {
+ rtl::Reference<X509Certificate_MSCryptImpl> xcert ;
+
+ if( rawCertificate.getLength() > 0 ) {
+ xcert = new X509Certificate_MSCryptImpl() ;
+ xcert->setRawCert( rawCertificate ) ;
+ }
+
+ return xcert ;
+}
+
+uno::Reference< XCertificate > SecurityEnvironment_MSCryptImpl::createCertificateFromAscii( const OUString& asciiCertificate ) {
+
+ OString oscert = OUStringToOString( asciiCertificate , RTL_TEXTENCODING_ASCII_US ) ;
+
+ xmlChar* chCert = xmlStrndup( reinterpret_cast<const xmlChar*>(oscert.getStr()), static_cast<int>(oscert.getLength()) ) ;
+
+ xmlSecSize certSize = xmlSecBase64Decode( chCert, chCert, xmlStrlen( chCert ) ) ;
+
+ uno::Sequence< sal_Int8 > rawCert( certSize ) ;
+ auto rawCertRange = asNonConstRange(rawCert);
+ for( xmlSecSize i = 0 ; i < certSize ; i ++ )
+ rawCertRange[i] = *( chCert + i ) ;
+
+ xmlFree( chCert ) ;
+
+ return createCertificateFromRaw( rawCert ) ;
+}
+
+
+static HCERTSTORE getCertStoreForIntermediatCerts(
+ const uno::Sequence< uno::Reference< css::security::XCertificate > >& seqCerts)
+{
+ HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 0, nullptr);
+ if (store == nullptr)
+ return nullptr;
+
+ for (int i = 0; i < seqCerts.getLength(); i++)
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Added temporary certificate: " << seqCerts[i]->getSubjectName());
+
+ uno::Sequence<sal_Int8> data = seqCerts[i]->getEncoded();
+ PCCERT_CONTEXT cert = CertCreateCertificateContext(
+ X509_ASN_ENCODING, reinterpret_cast<const BYTE*>(&data[0]), data.getLength());
+ //Adding the certificate creates a copy and not just increases the ref count
+ //Therefore we free later the certificate that we now add
+ CertAddCertificateContextToStore(store, cert, CERT_STORE_ADD_ALWAYS, nullptr);
+ CertFreeCertificateContext(cert);
+ }
+ return store;
+}
+
+static bool CheckUnitTestStore(PCCERT_CHAIN_CONTEXT const pChainContext, DWORD ignoreFlags)
+{
+ bool ret = false;
+ static char const*const pVar = getenv("LIBO_TEST_CRYPTOAPI_PKCS7");
+ if (!pVar)
+ {
+ return ret;
+ }
+ if (pChainContext->cChain == 0)
+ {
+ return ret;
+ }
+ PCERT_SIMPLE_CHAIN pSimpleChain = pChainContext->rgpChain[0];
+ // check if untrusted root is the only problem
+ if (pSimpleChain->TrustStatus.dwErrorStatus & ~(CERT_TRUST_IS_UNTRUSTED_ROOT | ignoreFlags))
+ {
+ return ret;
+ }
+
+ // leak this store, re-opening is a waste of time in tests
+ static HCERTSTORE const hExtra = CertOpenStore(
+ CERT_STORE_PROV_FILENAME_A,
+ PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+ 0,
+ CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG,
+ OString(OString::Concat(pVar) + "/test.p7b").getStr());
+ assert(hExtra != nullptr);
+ if (pSimpleChain->cElement < 1)
+ {
+ SAL_WARN("xmlsecurity.xmlsec", "unexpected empty chain");
+ return ret;
+ }
+ PCCERT_CONTEXT const pRoot(pSimpleChain->rgpElement[pSimpleChain->cElement-1]->pCertContext);
+ PCCERT_CONTEXT const pIssuerCert = CertFindCertificateInStore(
+ hExtra,
+ PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+ 0,
+ CERT_FIND_SUBJECT_NAME,
+ &pRoot->pCertInfo->Subject,
+ nullptr);
+ if (pIssuerCert)
+ {
+ // check that it signed itself
+ DWORD flags = CERT_STORE_SIGNATURE_FLAG;
+ bool result = CertVerifySubjectCertificateContext(pRoot, pIssuerCert, &flags);
+ if (result && flags == 0)
+ {
+ ret = true;
+ }
+ }
+ CertFreeCertificateContext(pIssuerCert);
+ return ret;
+}
+
+//We return only valid or invalid, as long as the API documentation expresses
+//explicitly that all validation steps are carried out even if one or several
+//errors occur. See also
+//http://wiki.openoffice.org/wiki/Certificate_Path_Validation#Validation_status
+sal_Int32 SecurityEnvironment_MSCryptImpl::verifyCertificate(
+ const uno::Reference< css::security::XCertificate >& aCert,
+ const uno::Sequence< uno::Reference< css::security::XCertificate > >& seqCerts)
+{
+ sal_Int32 validity = css::security::CertificateValidity::INVALID;
+ PCCERT_CHAIN_CONTEXT pChainContext = nullptr;
+ PCCERT_CONTEXT pCertContext = nullptr;
+
+ uno::Reference< XUnoTunnel > xCertTunnel( aCert, uno::UNO_QUERY_THROW ) ;
+
+ SAL_INFO("xmlsecurity.xmlsec", "Start verification of certificate: " << aCert->getSubjectName());
+
+ const auto* xcert = comphelper::getFromUnoTunnel<X509Certificate_MSCryptImpl>(xCertTunnel);
+ if( xcert == nullptr ) {
+ throw uno::RuntimeException() ;
+ }
+
+ pCertContext = xcert->getMswcryCert() ;
+
+ CERT_ENHKEY_USAGE enhKeyUsage ;
+ CERT_USAGE_MATCH certUsage ;
+ CERT_CHAIN_PARA chainPara = {};
+
+ //Prepare parameter for CertGetCertificateChain
+ enhKeyUsage.cUsageIdentifier = 0 ;
+ enhKeyUsage.rgpszUsageIdentifier = nullptr ;
+ certUsage.dwType = USAGE_MATCH_TYPE_AND ;
+ certUsage.Usage = enhKeyUsage ;
+ chainPara.cbSize = sizeof( CERT_CHAIN_PARA ) ;
+ chainPara.RequestedUsage = certUsage ;
+
+
+ HCERTSTORE hCollectionStore = nullptr;
+ HCERTSTORE hIntermediateCertsStore = nullptr;
+ bool bChain = false;
+ if( pCertContext != nullptr )
+ {
+ hIntermediateCertsStore =
+ getCertStoreForIntermediatCerts(seqCerts);
+
+ //Merge m_hCertStore and m_hKeyStore and the store of the intermediate
+ //certificates into one store.
+ hCollectionStore = CertOpenStore(
+ CERT_STORE_PROV_COLLECTION ,
+ 0 ,
+ 0 ,
+ 0 ,
+ nullptr
+ ) ;
+ if (hCollectionStore != nullptr)
+ {
+ CertAddStoreToCollection (
+ hCollectionStore ,
+ m_hCertStore ,
+ CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG ,
+ 0) ;
+ CertAddStoreToCollection (
+ hCollectionStore ,
+ m_hKeyStore,
+ CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG ,
+ 0) ;
+ CertAddStoreToCollection (
+ hCollectionStore,
+ hIntermediateCertsStore,
+ CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG,
+ 0);
+
+ }
+
+ //CertGetCertificateChain searches by default in MY, CA, ROOT and TRUST
+ //We do not check revocation of the root. In most cases there are none.
+ //Then we would get CERT_TRUST_REVOCATION_STATUS_UNKNOWN
+ SAL_INFO("xmlsecurity.xmlsec", "Verifying cert using revocation information.");
+ bChain = CertGetCertificateChain(
+ nullptr ,
+ pCertContext ,
+ nullptr , //use current system time
+ hCollectionStore,
+ &chainPara ,
+ CERT_CHAIN_REVOCATION_CHECK_CHAIN | CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
+ nullptr ,
+ &pChainContext);
+
+ if (bChain && pChainContext->cChain > 0)
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Overall error status (all chains):");
+ traceTrustStatus(pChainContext->TrustStatus.dwErrorStatus);
+ //highest quality chains come first
+ PCERT_SIMPLE_CHAIN pSimpleChain = pChainContext->rgpChain[0];
+ SAL_INFO("xmlsecurity.xmlsec", "Error status of first chain:");
+ traceTrustStatus(pSimpleChain->TrustStatus.dwErrorStatus);
+
+ //CERT_TRUST_REVOCATION_STATUS_UNKNOWN is also set if a certificate
+ //has no AIA(OCSP) or CRLDP extension and there is no CRL locally installed.
+ DWORD revocationFlags = CERT_TRUST_REVOCATION_STATUS_UNKNOWN |
+ CERT_TRUST_IS_OFFLINE_REVOCATION;
+ DWORD otherErrorsMask = ~revocationFlags;
+ if (!(pSimpleChain->TrustStatus.dwErrorStatus & otherErrorsMask)
+ || CheckUnitTestStore(pChainContext, revocationFlags))
+
+ {
+ //No errors except maybe those caused by missing revocation information
+ //Check if there are errors
+ if ( pSimpleChain->TrustStatus.dwErrorStatus & revocationFlags)
+ {
+ //No revocation information. Because MSDN documentation is not
+ //clear about if all other tests are performed if an error occurs,
+ //we test again, without requiring revocation checking.
+ CertFreeCertificateChain(pChainContext);
+ pChainContext = nullptr;
+ SAL_INFO("xmlsecurity.xmlsec", "Checking again but without requiring revocation information.");
+ bChain = CertGetCertificateChain(
+ nullptr ,
+ pCertContext ,
+ nullptr , //use current system time
+ hCollectionStore,
+ &chainPara ,
+ 0,
+ nullptr ,
+ &pChainContext);
+ if (bChain
+ && pChainContext->cChain > 0
+ && pChainContext->rgpChain[0]->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR)
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Certificate is valid.");
+ validity = css::security::CertificateValidity::VALID;
+ }
+ else if (CheckUnitTestStore(pChainContext, 0))
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "root certificate found in extra test store");
+ validity = css::security::CertificateValidity::VALID;
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Certificate is invalid.");
+ }
+ }
+ else
+ {
+ //valid and revocation information available
+ SAL_INFO("xmlsecurity.xmlsec", "Certificate is valid.");
+ validity = css::security::CertificateValidity::VALID;
+ }
+ }
+ else
+ {
+ //invalid
+ SAL_INFO("xmlsecurity.xmlsec", "Certificate is invalid.");
+ validity = css::security::CertificateValidity::INVALID ;
+ }
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "CertGetCertificateChain failed.");
+ }
+ }
+
+ if (pChainContext)
+ {
+ CertFreeCertificateChain(pChainContext);
+ pChainContext = nullptr;
+ }
+
+ //Close the additional store, do not destroy the contained certs
+ CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_CHECK_FLAG);
+ //Close the temporary store containing the intermediate certificates and make
+ //sure all certificates are deleted.
+ CertCloseStore(hIntermediateCertsStore, CERT_CLOSE_STORE_CHECK_FLAG);
+
+ return validity ;
+}
+
+sal_Int32 SecurityEnvironment_MSCryptImpl::getCertificateCharacters( const css::uno::Reference< css::security::XCertificate >& aCert ) {
+ sal_Int32 characters ;
+ PCCERT_CONTEXT pCertContext ;
+
+ uno::Reference< XUnoTunnel > xCertTunnel( aCert, uno::UNO_QUERY_THROW ) ;
+ const auto* xcert = comphelper::getFromUnoTunnel<X509Certificate_MSCryptImpl>(xCertTunnel);
+ if( xcert == nullptr ) {
+ throw uno::RuntimeException() ;
+ }
+
+ pCertContext = xcert->getMswcryCert() ;
+
+ characters = 0x00000000 ;
+
+ //Firstly, make sentence whether or not the cert is self-signed.
+ if( CertCompareCertificateName( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &(pCertContext->pCertInfo->Subject), &(pCertContext->pCertInfo->Issuer) ) ) {
+ characters |= css::security::CertificateCharacters::SELF_SIGNED ;
+ } else {
+ characters &= ~ css::security::CertificateCharacters::SELF_SIGNED ;
+ }
+
+ //Secondly, make sentence whether or not the cert has a private key.
+ {
+ BOOL fCallerFreeProv ;
+ DWORD dwKeySpec ;
+ NCRYPT_KEY_HANDLE hKey = 0;
+ DWORD dwFlags = CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG;
+ HCRYPTPROV_OR_NCRYPT_KEY_HANDLE* phCryptProvOrNCryptKey = &hKey;
+ if( CryptAcquireCertificatePrivateKey( pCertContext ,
+ dwFlags,
+ nullptr ,
+ phCryptProvOrNCryptKey,
+ &dwKeySpec,
+ &fCallerFreeProv )
+ ) {
+ characters |= css::security::CertificateCharacters::HAS_PRIVATE_KEY ;
+
+ if (hKey && fCallerFreeProv)
+ NCryptFreeObject(hKey);
+ } else {
+ characters &= ~ css::security::CertificateCharacters::HAS_PRIVATE_KEY ;
+ }
+ }
+ return characters ;
+}
+
+void SecurityEnvironment_MSCryptImpl::enableDefaultCrypt( bool enable ) {
+ m_bEnableDefault = enable ;
+}
+
+bool SecurityEnvironment_MSCryptImpl::defaultEnabled() {
+ return m_bEnableDefault ;
+}
+
+static rtl::Reference<X509Certificate_MSCryptImpl> MswcryCertContextToXCert( PCCERT_CONTEXT cert )
+{
+ rtl::Reference<X509Certificate_MSCryptImpl> xcert ;
+
+ if( cert != nullptr ) {
+ xcert = new X509Certificate_MSCryptImpl() ;
+ xcert->setMswcryCert( cert ) ;
+ }
+
+ return xcert ;
+}
+
+OUString SecurityEnvironment_MSCryptImpl::getSecurityEnvironmentInformation()
+{
+ return "Microsoft Crypto API";
+}
+
+xmlSecKeysMngrPtr SecurityEnvironment_MSCryptImpl::createKeysManager() {
+
+ /*-
+ * The following lines is based on the of xmlsec-mscrypto crypto engine
+ */
+ xmlSecKeysMngrPtr pKeysMngr = xmlsecurity::MSCryptoAppliedKeysMngrCreate() ;
+ if( pKeysMngr == nullptr )
+ throw uno::RuntimeException() ;
+
+ /*-
+ * Adopt system default certificate store.
+ */
+ if( defaultEnabled() ) {
+ //Add system key store into the keys manager.
+ m_hMySystemStore = CertOpenSystemStoreW( 0, L"MY" ) ;
+ if( m_hMySystemStore != nullptr ) {
+ if( xmlsecurity::MSCryptoAppliedKeysMngrAdoptKeyStore( pKeysMngr, m_hMySystemStore ) < 0 ) {
+ CertCloseStore( m_hMySystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
+ m_hMySystemStore = nullptr;
+ throw uno::RuntimeException() ;
+ }
+ m_hMySystemStore = nullptr;
+ }
+
+ //Add system root store into the keys manager.
+ m_hRootSystemStore = CertOpenSystemStoreW( 0, L"Root" ) ;
+ if( m_hRootSystemStore != nullptr ) {
+ if( xmlsecurity::MSCryptoAppliedKeysMngrAdoptTrustedStore( pKeysMngr, m_hRootSystemStore ) < 0 ) {
+ CertCloseStore( m_hRootSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
+ m_hRootSystemStore = nullptr;
+ throw uno::RuntimeException() ;
+ }
+ m_hRootSystemStore = nullptr;
+ }
+
+ //Add system trusted store into the keys manager.
+ m_hTrustSystemStore = CertOpenSystemStoreW( 0, L"Trust" ) ;
+ if( m_hTrustSystemStore != nullptr ) {
+ if( xmlsecurity::MSCryptoAppliedKeysMngrAdoptUntrustedStore( pKeysMngr, m_hTrustSystemStore ) < 0 ) {
+ CertCloseStore( m_hTrustSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
+ m_hTrustSystemStore = nullptr;
+ throw uno::RuntimeException() ;
+ }
+ m_hTrustSystemStore = nullptr;
+ }
+
+ //Add system CA store into the keys manager.
+ m_hCaSystemStore = CertOpenSystemStoreW( 0, L"CA" ) ;
+ if( m_hCaSystemStore != nullptr ) {
+ if( xmlsecurity::MSCryptoAppliedKeysMngrAdoptUntrustedStore( pKeysMngr, m_hCaSystemStore ) < 0 ) {
+ CertCloseStore( m_hCaSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ;
+ m_hCaSystemStore = nullptr;
+ throw uno::RuntimeException() ;
+ }
+ m_hCaSystemStore = nullptr;
+ }
+ }
+
+ return pKeysMngr ;
+}
+void SecurityEnvironment_MSCryptImpl::destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr) {
+ if( pKeysMngr != nullptr ) {
+ xmlSecKeysMngrDestroy( pKeysMngr ) ;
+ }
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_xml_crypto_SecurityEnvironment_get_implementation(
+ uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new SecurityEnvironment_MSCryptImpl(pCtx));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.hxx
new file mode 100644
index 000000000..a4ae45742
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.hxx
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <wincrypt.h>
+#include <sal/config.h>
+#include <rtl/ustring.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/uno/Exception.hpp>
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
+#include <com/sun/star/security/XCertificate.hpp>
+#include <com/sun/star/security/CertificateCharacters.hpp>
+#include <com/sun/star/security/CertificateValidity.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+
+#include <vector>
+#include <xmlsec-wrapper.h>
+
+#include <sal/types.h>
+
+
+class SecurityEnvironment_MSCryptImpl : public ::cppu::WeakImplHelper<
+ css::xml::crypto::XSecurityEnvironment ,
+ css::lang::XServiceInfo,
+ css::lang::XUnoTunnel >
+{
+ private:
+ //crypto provider and key container
+ HCRYPTPROV m_hProv ;
+ LPCTSTR m_pszContainer ;
+
+ //Key store
+ HCERTSTORE m_hKeyStore ;
+
+ //Certificate store
+ HCERTSTORE m_hCertStore ;
+
+ // i120675, save the store handles
+ HCERTSTORE m_hMySystemStore;
+ HCERTSTORE m_hRootSystemStore;
+ HCERTSTORE m_hTrustSystemStore;
+ HCERTSTORE m_hCaSystemStore;
+
+ //Enable default system cryptography setting
+ bool m_bEnableDefault ;
+
+ //Service manager
+ css::uno::Reference< css::lang::XMultiServiceFactory > m_xServiceManager ;
+
+ public:
+ explicit SecurityEnvironment_MSCryptImpl( const css::uno::Reference< css::uno::XComponentContext >& xContext ) ;
+ virtual ~SecurityEnvironment_MSCryptImpl() override;
+
+ //Methods from XSecurityEnvironment
+ virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getPersonalCertificates() override;
+ virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getAllCertificates() override
+ { return css::uno::Sequence< css::uno::Reference< css::security::XCertificate > >(); }
+
+ virtual css::uno::Reference< css::security::XCertificate > SAL_CALL getCertificate(
+ const OUString& issuerName,
+ const css::uno::Sequence< sal_Int8 >& serialNumber ) override;
+
+ /// @throws css::uno::SecurityException
+ /// @throws css::uno::RuntimeException
+ virtual css::uno::Reference< css::security::XCertificate > getCertificate(
+ const OUString& issuerName,
+ const OUString& serialNumber ) ;
+
+ virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL buildCertificatePath(
+ const css::uno::Reference< css::security::XCertificate >& beginCert ) override;
+
+ virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromRaw(
+ const css::uno::Sequence< sal_Int8 >& rawCertificate ) override;
+
+ virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromAscii(
+ const OUString& asciiCertificate ) override;
+
+ virtual ::sal_Int32 SAL_CALL verifyCertificate(
+ const css::uno::Reference< css::security::XCertificate >& xCert,
+ const css::uno::Sequence< css::uno::Reference<
+ css::security::XCertificate > >& intermediateCertificates) override;
+
+ virtual ::sal_Int32 SAL_CALL getCertificateCharacters(
+ const css::uno::Reference< css::security::XCertificate >& xCert ) override;
+
+ virtual OUString SAL_CALL getSecurityEnvironmentInformation( ) override;
+
+
+ //Methods from XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(
+ const OUString& ServiceName
+ ) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ //Methods from XUnoTunnel
+ UNO3_GETIMPLEMENTATION_DECL(SecurityEnvironment_MSCryptImpl)
+
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ HCRYPTPROV getCryptoProvider() ;
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ void setCryptoProvider( HCRYPTPROV aProv ) ;
+
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ LPCTSTR getKeyContainer() ;
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ void setKeyContainer( LPCTSTR aKeyContainer ) ;
+
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ HCERTSTORE getCryptoSlot() ;
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ void setCryptoSlot( HCERTSTORE aKeyStore ) ;
+
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ HCERTSTORE getCertDb() ;
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ void setCertDb( HCERTSTORE aCertDb ) ;
+
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ void enableDefaultCrypt( bool enable ) ;
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ bool defaultEnabled() ;
+
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ xmlSecKeysMngrPtr createKeysManager() ;
+
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ static void destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr) ;
+} ;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx
new file mode 100644
index 000000000..08143f992
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+#include <xmlsec-wrapper.h>
+
+#include "seinitializer_mscryptimpl.hxx"
+
+#include "securityenvironment_mscryptimpl.hxx"
+
+#include <xmlsec/mscng/app.h>
+#include <com/sun/star/xml/crypto/SecurityEnvironment.hpp>
+#include <com/sun/star/xml/crypto/XMLSecurityContext.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <o3tl/char16_t2wchar_t.hxx>
+#include <svl/cryptosign.hxx>
+
+using namespace com::sun::star;
+namespace cssl = com::sun::star::lang;
+namespace cssxc = com::sun::star::xml::crypto;
+
+SEInitializer_MSCryptImpl::SEInitializer_MSCryptImpl(
+ const uno::Reference< uno::XComponentContext > &rxContext)
+ :mxContext( rxContext )
+{
+}
+
+SEInitializer_MSCryptImpl::~SEInitializer_MSCryptImpl()
+{
+}
+
+/* XSEInitializer */
+uno::Reference< cssxc::XXMLSecurityContext > SAL_CALL
+ SEInitializer_MSCryptImpl::createSecurityContext(
+ const OUString& sCertDB )
+{
+ const char* n_pCertStore ;
+ HCERTSTORE n_hStoreHandle ;
+ OString sCertDir;
+
+ //Initialize the crypto engine
+ if( sCertDB.getLength() > 0 )
+ {
+ sCertDir = OString(sCertDB.getStr(), sCertDB.getLength(), RTL_TEXTENCODING_ASCII_US);
+ n_pCertStore = sCertDir.getStr();
+ n_hStoreHandle = CertOpenSystemStoreW( 0, o3tl::toW(sCertDB.getStr())) ;
+ if( n_hStoreHandle == nullptr )
+ {
+ return nullptr;
+ }
+ }
+ else
+ {
+ n_pCertStore = nullptr ;
+ n_hStoreHandle = nullptr ;
+ }
+
+ xmlSecMSCngAppInit(n_pCertStore);
+
+ try {
+ /* Build Security Environment */
+ uno::Reference< cssxc::XSecurityEnvironment > xSecEnv = cssxc::SecurityEnvironment::create( mxContext );
+
+ /* Setup key slot and certDb */
+ uno::Reference< cssl::XUnoTunnel > xSecEnvTunnel( xSecEnv, uno::UNO_QUERY_THROW );
+ SecurityEnvironment_MSCryptImpl* pSecEnv = comphelper::getFromUnoTunnel<SecurityEnvironment_MSCryptImpl>(xSecEnvTunnel);
+ if( pSecEnv == nullptr )
+ {
+ if( n_hStoreHandle != nullptr )
+ {
+ CertCloseStore( n_hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG ) ;
+ }
+
+ xmlSecMSCngAppShutdown();
+ return nullptr;
+ }
+
+ if( n_hStoreHandle != nullptr )
+ {
+ pSecEnv->setCryptoSlot( n_hStoreHandle ) ;
+ pSecEnv->setCertDb( n_hStoreHandle ) ;
+ }
+ else
+ {
+ pSecEnv->enableDefaultCrypt( true ) ;
+ }
+
+ /* Build XML Security Context */
+ uno::Reference< cssxc::XXMLSecurityContext > xSecCtx = cssxc::XMLSecurityContext::create( mxContext );
+
+ xSecCtx->setDefaultSecurityEnvironmentIndex(xSecCtx->addSecurityEnvironment( xSecEnv )) ;
+ return xSecCtx;
+ }
+ catch( uno::Exception& )
+ {
+ if( n_hStoreHandle != nullptr )
+ {
+ CertCloseStore( n_hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG ) ;
+ }
+
+ xmlSecMSCngAppShutdown();
+ return nullptr;
+ }
+}
+
+void SAL_CALL SEInitializer_MSCryptImpl::freeSecurityContext( const uno::Reference< cssxc::XXMLSecurityContext >&)
+{
+ /*
+ uno::Reference< cssxc::XSecurityEnvironment > xSecEnv
+ = securityContext->getSecurityEnvironment();
+
+ if( xSecEnv.is() )
+ {
+ uno::Reference< cssl::XUnoTunnel > xEnvTunnel( xSecEnv , uno::UNO_QUERY ) ;
+ if (auto pSecEnv = comphelper::getFromUnoTunnel<SecurityEnvironment_MSCryptImpl>(xEnvTunnel))
+ {
+ HCERTSTORE n_hStoreHandle = pSecEnv->getCryptoSlot();
+
+ if( n_hStoreHandle != NULL )
+ {
+ CertCloseStore( n_hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG ) ;
+ pSecEnv->setCryptoSlot( NULL ) ;
+ pSecEnv->setCertDb( NULL ) ;
+ }
+
+ xmlSecMSCryptoAppShutdown() ;
+ }
+ }
+ */
+
+ xmlSecMSCngAppShutdown();
+}
+
+/* XServiceInfo */
+OUString SAL_CALL SEInitializer_MSCryptImpl::getImplementationName()
+{
+ return "com.sun.star.xml.crypto.SEInitializer";
+}
+
+sal_Bool SAL_CALL SEInitializer_MSCryptImpl::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService( this, rServiceName );
+}
+
+uno::Sequence< OUString > SAL_CALL SEInitializer_MSCryptImpl::getSupportedServiceNames()
+{
+ return { "com.sun.star.xml.crypto.SEInitializer" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_xml_crypto_SEInitializer_get_implementation(
+ uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new SEInitializer_MSCryptImpl(pCtx));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.hxx
new file mode 100644
index 000000000..182ba5e5a
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp>
+#include <com/sun/star/xml/crypto/XSEInitializer.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <cppuhelper/implbase.hxx>
+
+#include <libxml/tree.h>
+
+class SEInitializer_MSCryptImpl : public cppu::WeakImplHelper
+<
+ css::xml::crypto::XSEInitializer,
+ css::lang::XServiceInfo
+>
+/****** SEInitializer_MSCryptImpl.hxx/CLASS SEInitializer_MSCryptImpl ***********
+ *
+ * NAME
+ * SEInitializer_MSCryptImpl -- Class to initialize a Security Context
+ * instance
+ *
+ * FUNCTION
+ * Use this class to initialize a XmlSec based Security Context
+ * instance. After this instance is used up, use this class to free this
+ * instance.
+ ******************************************************************************/
+{
+private:
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+
+public:
+ explicit SEInitializer_MSCryptImpl(const css::uno::Reference< css::uno::XComponentContext > &rxContext);
+ virtual ~SEInitializer_MSCryptImpl() override;
+
+ /* XSEInitializer */
+ virtual css::uno::Reference< css::xml::crypto::XXMLSecurityContext >
+ SAL_CALL createSecurityContext( const OUString& certDB ) override;
+
+ virtual void SAL_CALL freeSecurityContext( const css::uno::Reference<
+ css::xml::crypto::XXMLSecurityContext >& securityContext ) override;
+
+ /* XServiceInfo */
+ virtual OUString SAL_CALL getImplementationName( ) override;
+
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx
new file mode 100644
index 000000000..5e0ca9094
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx
@@ -0,0 +1,786 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <string.h>
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/windowserrorstring.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include "x509certificate_mscryptimpl.hxx"
+#include <certificateextension_xmlsecimpl.hxx>
+#include <biginteger.hxx>
+#include "sanextension_mscryptimpl.hxx"
+
+#include "oid.hxx"
+
+#include <rtl/locale.h>
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <osl/nlsupport.h>
+#include <osl/process.h>
+#include <o3tl/char16_t2wchar_t.hxx>
+
+#include <memory>
+#include <string_view>
+#include <utility>
+#include <vector>
+#include <tools/time.hxx>
+#include <svl/sigstruct.hxx>
+
+using namespace com::sun::star;
+using namespace ::com::sun::star::uno ;
+using namespace ::com::sun::star::security ;
+
+using ::com::sun::star::security::XCertificate ;
+using ::com::sun::star::util::DateTime ;
+
+/*Returns the index within rRawString where sTypeName starts and where it ends.
+ The starting index is pair.first. The ending index in pair.second points
+ one char after the last character of the type.
+ sTypeName can be
+ "S" or "CN" (without ""). Do not use spaces at the beginning of the type name.
+ If the type name is not found then pair.first and pair.second are -1.
+*/
+static std::pair< sal_Int32, sal_Int32 >
+findTypeInDN(const OUString& rRawString, std::u16string_view sTypeName)
+{
+ std::pair< sal_Int32, sal_Int32 > retVal;
+ bool bInEscape = false;
+ bool bInValue = false;
+ bool bFound = false;
+ sal_Int32 nTypeNameStart = 0;
+ sal_Int32 length = rRawString.getLength();
+
+ for (sal_Int32 i = 0; i < length; i++)
+ {
+ sal_Unicode c = rRawString[i];
+
+ if (c == '=')
+ {
+ if (! bInValue)
+ {
+ OUString sType = rRawString.copy(nTypeNameStart, i - nTypeNameStart);
+ sType = sType.trim();
+ if (sType.equalsIgnoreAsciiCase(sTypeName))
+ {
+ bFound = true;
+ break;
+ }
+ }
+ }
+ else if (c == '"')
+ {
+ if (!bInEscape)
+ {
+ //If this is the quote is the first of the couple which enclose the
+ //whole value, because the value contains special characters
+ //then we just drop it. That is, this character must be followed by
+ //a character which is not '"'.
+ if ( i + 1 < length && rRawString[i+1] == '"')
+ bInEscape = true;
+ else
+ bInValue = !bInValue; //value is enclosed in " "
+ }
+ else
+ {
+ //This quote is escaped by a preceding quote and therefore is
+ //part of the value
+ bInEscape = false;
+ }
+ }
+ else if (c == ',' || c == '+')
+ {
+ //The comma separate the attribute value pairs.
+ //If the comma is not part of a value (the value would then be enclosed in '"'),
+ //then we have reached the end of the value
+ if (!bInValue)
+ {
+ //The next char is the start of the new type
+ nTypeNameStart = i + 1;
+ }
+ }
+ }
+
+ //Found the Type Name, but there can still be spaces after the last comma
+ //and the beginning of the type.
+ if (bFound)
+ {
+ while (true)
+ {
+ sal_Unicode c = rRawString[nTypeNameStart];
+ if (c != ' ' && c != '\t')
+ //found
+ break;
+ nTypeNameStart ++;
+ }
+ // search end (one after last letter)
+ sal_Int32 nTypeNameEnd = nTypeNameStart;
+ nTypeNameEnd++;
+ while (true)
+ {
+ sal_Unicode c = rRawString[nTypeNameEnd];
+ if (c == ' ' || c == '\t' || c == '=')
+ break;
+ nTypeNameEnd++;
+ }
+ retVal = std::make_pair(nTypeNameStart, nTypeNameEnd);
+ }
+ else
+ {
+ retVal = std::make_pair(-1, -1);
+ }
+ return retVal;
+}
+
+
+/*
+ MS Crypto uses the 'S' tag (equal to the 'ST' tag in NSS), but the NSS can't recognise
+ it, so the 'S' tag should be changed to 'ST' tag. However I am not sure if this is necessary
+ anymore, because we provide always the signers certificate when signing. So libmlsec can find
+ the private key based on the provided certificate (X509Certificate element) and does not need
+ the issuer name (X509IssuerName element). The issuer name in the xml signature has also no
+ effect for the signature nor the certificate validation.
+ In many RFCs, for example 4519, on speaks of 'ST'. However, the certificate does not contain
+ strings for type names. Instead it uses OIDs.
+ */
+
+static OUString replaceTagSWithTagST(OUString const & oldDN)
+{
+ std::pair<sal_Int32, sal_Int32 > pairIndex = findTypeInDN(oldDN, u"S");
+
+ if (pairIndex.first != -1)
+ {
+ return OUString::Concat(oldDN.subView(0, pairIndex.first))+"ST"
+ +oldDN.subView(pairIndex.second);
+ }
+ return oldDN;
+}
+/* end */
+
+X509Certificate_MSCryptImpl::X509Certificate_MSCryptImpl() :
+ m_pCertContext( nullptr )
+{
+}
+
+X509Certificate_MSCryptImpl::~X509Certificate_MSCryptImpl() {
+ if( m_pCertContext != nullptr ) {
+ CertFreeCertificateContext( m_pCertContext ) ;
+ }
+}
+
+//Methods from XCertificate
+sal_Int16 SAL_CALL X509Certificate_MSCryptImpl::getVersion() {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) {
+ return static_cast<char>(m_pCertContext->pCertInfo->dwVersion) ;
+ } else {
+ return -1 ;
+ }
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getSerialNumber() {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) {
+ Sequence< sal_Int8 > serial( m_pCertContext->pCertInfo->SerialNumber.cbData ) ;
+ auto serialRange = asNonConstRange(serial);
+ for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->SerialNumber.cbData ; i ++ )
+ serialRange[i] = *( m_pCertContext->pCertInfo->SerialNumber.pbData + m_pCertContext->pCertInfo->SerialNumber.cbData - i - 1 ) ;
+
+ return serial ;
+ } else {
+ return Sequence< sal_Int8 >();
+ }
+}
+
+OUString SAL_CALL X509Certificate_MSCryptImpl::getIssuerName() {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) {
+ DWORD cchIssuer = CertNameToStrW(
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
+ &( m_pCertContext->pCertInfo->Issuer ),
+ CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
+ nullptr, 0
+ ) ;
+
+ // Here the cbIssuer count the last 0x00 , take care.
+ if( cchIssuer != 0 ) {
+ auto issuer = std::make_unique<wchar_t[]>(cchIssuer);
+
+ cchIssuer = CertNameToStrW(
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
+ &( m_pCertContext->pCertInfo->Issuer ),
+ CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
+ issuer.get(), cchIssuer
+ ) ;
+
+ if( cchIssuer <= 0 ) {
+ throw RuntimeException() ;
+ }
+
+ if(issuer.get()[cchIssuer -1] == 0) cchIssuer--; //delimit the last 0x00;
+ OUString xIssuer(o3tl::toU(issuer.get()), cchIssuer) ;
+
+ return replaceTagSWithTagST(xIssuer);
+ } else {
+ return OUString() ;
+ }
+ } else {
+ return OUString() ;
+ }
+}
+
+OUString SAL_CALL X509Certificate_MSCryptImpl::getSubjectName()
+{
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr )
+ {
+ DWORD cchSubject = CertNameToStrW(
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
+ &( m_pCertContext->pCertInfo->Subject ),
+ CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
+ nullptr, 0
+ ) ;
+
+ if( cchSubject != 0 )
+ {
+ auto subject = std::make_unique<wchar_t[]>(cchSubject);
+
+ cchSubject = CertNameToStrW(
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
+ &( m_pCertContext->pCertInfo->Subject ),
+ CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG ,
+ subject.get(), cchSubject
+ ) ;
+
+ if( cchSubject <= 0 ) {
+ throw RuntimeException() ;
+ }
+
+ OUString xSubject(o3tl::toU(subject.get()));
+
+ return replaceTagSWithTagST(xSubject);
+ } else
+ {
+ return OUString() ;
+ }
+ }
+ else
+ {
+ return OUString() ;
+ }
+}
+
+css::util::DateTime SAL_CALL X509Certificate_MSCryptImpl::getNotValidBefore() {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) {
+ SYSTEMTIME explTime ;
+ DateTime dateTime ;
+ FILETIME localFileTime;
+
+ if (FileTimeToLocalFileTime(&( m_pCertContext->pCertInfo->NotBefore ), &localFileTime))
+ {
+ if( FileTimeToSystemTime( &localFileTime, &explTime ) ) {
+ //Convert the time to readable local time
+ dateTime.NanoSeconds = explTime.wMilliseconds * ::tools::Time::nanoPerMilli ;
+ dateTime.Seconds = explTime.wSecond ;
+ dateTime.Minutes = explTime.wMinute ;
+ dateTime.Hours = explTime.wHour ;
+ dateTime.Day = explTime.wDay ;
+ dateTime.Month = explTime.wMonth ;
+ dateTime.Year = explTime.wYear ;
+ }
+ }
+
+ return dateTime ;
+ } else {
+ return DateTime() ;
+ }
+}
+
+css::util::DateTime SAL_CALL X509Certificate_MSCryptImpl::getNotValidAfter() {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) {
+ SYSTEMTIME explTime ;
+ DateTime dateTime ;
+ FILETIME localFileTime;
+
+ if (FileTimeToLocalFileTime(&( m_pCertContext->pCertInfo->NotAfter ), &localFileTime))
+ {
+ if( FileTimeToSystemTime( &localFileTime, &explTime ) ) {
+ //Convert the time to readable local time
+ dateTime.NanoSeconds = explTime.wMilliseconds * ::tools::Time::nanoPerMilli ;
+ dateTime.Seconds = explTime.wSecond ;
+ dateTime.Minutes = explTime.wMinute ;
+ dateTime.Hours = explTime.wHour ;
+ dateTime.Day = explTime.wDay ;
+ dateTime.Month = explTime.wMonth ;
+ dateTime.Year = explTime.wYear ;
+ }
+ }
+
+ return dateTime ;
+ } else {
+ return DateTime() ;
+ }
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getIssuerUniqueID() {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) {
+ Sequence< sal_Int8 > issuerUid( m_pCertContext->pCertInfo->IssuerUniqueId.cbData ) ;
+ auto issuerUidRange = asNonConstRange(issuerUid);
+ for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->IssuerUniqueId.cbData; i ++ )
+ issuerUidRange[i] = *( m_pCertContext->pCertInfo->IssuerUniqueId.pbData + i ) ;
+
+ return issuerUid ;
+ } else {
+ return Sequence< sal_Int8 >();
+ }
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getSubjectUniqueID() {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) {
+ Sequence< sal_Int8 > subjectUid( m_pCertContext->pCertInfo->SubjectUniqueId.cbData ) ;
+ auto subjectUidRange = asNonConstRange(subjectUid);
+ for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->SubjectUniqueId.cbData; i ++ )
+ subjectUidRange[i] = *( m_pCertContext->pCertInfo->SubjectUniqueId.pbData + i ) ;
+
+ return subjectUid ;
+ } else {
+ return Sequence< sal_Int8 >();
+ }
+}
+
+css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL X509Certificate_MSCryptImpl::getExtensions() {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr && m_pCertContext->pCertInfo->cExtension != 0 ) {
+ rtl::Reference<CertificateExtension_XmlSecImpl> xExtn ;
+ Sequence< Reference< XCertificateExtension > > xExtns( m_pCertContext->pCertInfo->cExtension ) ;
+ auto pExtns = xExtns.getArray();
+
+ for( unsigned int i = 0; i < m_pCertContext->pCertInfo->cExtension; i++ ) {
+ CERT_EXTENSION* pExtn = &(m_pCertContext->pCertInfo->rgExtension[i]) ;
+
+
+ OUString objId = OUString::createFromAscii( pExtn->pszObjId );
+
+ if ( objId == "2.5.29.17" )
+ xExtn = reinterpret_cast<CertificateExtension_XmlSecImpl*>(new SanExtensionImpl());
+ else
+ xExtn = new CertificateExtension_XmlSecImpl;
+
+ xExtn->setCertExtn( pExtn->Value.pbData, pExtn->Value.cbData, reinterpret_cast<unsigned char*>(pExtn->pszObjId), strlen( pExtn->pszObjId ), pExtn->fCritical ) ;
+
+ pExtns[i] = xExtn ;
+ }
+
+ return xExtns ;
+ } else {
+ return Sequence< Reference< XCertificateExtension > >();
+ }
+}
+
+css::uno::Reference< css::security::XCertificateExtension > SAL_CALL X509Certificate_MSCryptImpl::findCertificateExtension( const css::uno::Sequence< sal_Int8 >& /*oid*/ ) {
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr && m_pCertContext->pCertInfo->cExtension != 0 ) {
+ rtl::Reference<CertificateExtension_XmlSecImpl> xExtn ;
+
+ for( unsigned int i = 0; i < m_pCertContext->pCertInfo->cExtension; i++ ) {
+ CERT_EXTENSION* pExtn = &( m_pCertContext->pCertInfo->rgExtension[i] ) ;
+
+ //TODO: Compare the oid
+ if( false ) {
+ xExtn = new CertificateExtension_XmlSecImpl;
+ xExtn->setCertExtn( pExtn->Value.pbData, pExtn->Value.cbData, reinterpret_cast<unsigned char*>(pExtn->pszObjId), strlen( pExtn->pszObjId ), pExtn->fCritical ) ;
+ }
+ }
+
+ return xExtn ;
+ } else {
+ return nullptr ;
+ }
+}
+
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getEncoded() {
+ if( m_pCertContext != nullptr && m_pCertContext->cbCertEncoded > 0 ) {
+ Sequence< sal_Int8 > rawCert( m_pCertContext->cbCertEncoded ) ;
+ auto prawCert = rawCert.getArray();
+
+ for( unsigned int i = 0 ; i < m_pCertContext->cbCertEncoded ; i ++ )
+ prawCert[i] = *( m_pCertContext->pbCertEncoded + i ) ;
+
+ return rawCert ;
+ } else {
+ return Sequence< sal_Int8 >();
+ }
+}
+
+//Helper methods
+void X509Certificate_MSCryptImpl::setMswcryCert( const CERT_CONTEXT* cert ) {
+ if( m_pCertContext != nullptr ) {
+ CertFreeCertificateContext( m_pCertContext ) ;
+ m_pCertContext = nullptr ;
+ }
+
+ if( cert != nullptr ) {
+ m_pCertContext = CertDuplicateCertificateContext( cert ) ;
+ }
+}
+
+const CERT_CONTEXT* X509Certificate_MSCryptImpl::getMswcryCert() const {
+ if( m_pCertContext != nullptr ) {
+ return m_pCertContext ;
+ } else {
+ return nullptr ;
+ }
+}
+
+void X509Certificate_MSCryptImpl::setRawCert( Sequence< sal_Int8 > const & rawCert ) {
+ if( m_pCertContext != nullptr ) {
+ CertFreeCertificateContext( m_pCertContext ) ;
+ m_pCertContext = nullptr ;
+ }
+
+ if( rawCert.getLength() != 0 ) {
+ m_pCertContext = CertCreateCertificateContext( X509_ASN_ENCODING, reinterpret_cast<const sal_uInt8*>(&rawCert[0]), rawCert.getLength() ) ;
+ }
+}
+
+/* XUnoTunnel */
+UNO3_GETIMPLEMENTATION_IMPL(X509Certificate_MSCryptImpl);
+
+static OUString findOIDDescription(char const *oid)
+{
+ OUString ouOID = OUString::createFromAscii( oid );
+ for (int i=0; i<nOID; i++)
+ {
+ OUString item = OUString::createFromAscii( OIDs[i].oid );
+ if (ouOID == item)
+ {
+ return OUString::createFromAscii( OIDs[i].desc );
+ }
+ }
+
+ return OUString() ;
+}
+
+static css::uno::Sequence< sal_Int8 > getThumbprint(const CERT_CONTEXT* pCertContext, DWORD dwPropId)
+{
+ if( pCertContext != nullptr )
+ {
+ DWORD cbData = dwPropId == CERT_SHA256_HASH_PROP_ID ? 32 : 20;
+ unsigned char fingerprint[32];
+ if (CertGetCertificateContextProperty(pCertContext, dwPropId, fingerprint, &cbData))
+ {
+ Sequence< sal_Int8 > thumbprint( cbData ) ;
+ auto pthumbprint = thumbprint.getArray();
+ for( unsigned int i = 0 ; i < cbData ; i ++ )
+ {
+ pthumbprint[i] = fingerprint[i];
+ }
+
+ return thumbprint;
+ }
+ else
+ {
+ DWORD e = GetLastError();
+ cbData = e;
+ }
+ }
+
+ return Sequence< sal_Int8 >();
+}
+
+OUString SAL_CALL X509Certificate_MSCryptImpl::getSubjectPublicKeyAlgorithm()
+{
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr )
+ {
+ CRYPT_ALGORITHM_IDENTIFIER algorithm = m_pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm;
+ return findOIDDescription( algorithm.pszObjId ) ;
+ }
+ else
+ {
+ return OUString() ;
+ }
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getSubjectPublicKeyValue()
+{
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr )
+ {
+ CRYPT_BIT_BLOB publicKey = m_pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey;
+
+ Sequence< sal_Int8 > key( publicKey.cbData ) ;
+ auto keyRange = asNonConstRange(key);
+ for( unsigned int i = 0 ; i < publicKey.cbData ; i++ )
+ {
+ keyRange[i] = *(publicKey.pbData + i) ;
+ }
+
+ return key;
+ }
+ else
+ {
+ return Sequence< sal_Int8 >();
+ }
+}
+
+OUString SAL_CALL X509Certificate_MSCryptImpl::getSignatureAlgorithm()
+{
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr )
+ {
+ CRYPT_ALGORITHM_IDENTIFIER algorithm = m_pCertContext->pCertInfo->SignatureAlgorithm;
+ return findOIDDescription( algorithm.pszObjId ) ;
+ }
+ else
+ {
+ return OUString() ;
+ }
+}
+
+uno::Sequence<sal_Int8> X509Certificate_MSCryptImpl::getSHA256Thumbprint()
+{
+ return getThumbprint(m_pCertContext, CERT_SHA256_HASH_PROP_ID);
+}
+
+svl::crypto::SignatureMethodAlgorithm X509Certificate_MSCryptImpl::getSignatureMethodAlgorithm()
+{
+ svl::crypto::SignatureMethodAlgorithm nRet = svl::crypto::SignatureMethodAlgorithm::RSA;
+
+ if (!m_pCertContext || !m_pCertContext->pCertInfo)
+ return nRet;
+
+ CRYPT_ALGORITHM_IDENTIFIER algorithm = m_pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm;
+ OString aObjId(algorithm.pszObjId);
+ if (aObjId == szOID_ECC_PUBLIC_KEY)
+ nRet = svl::crypto::SignatureMethodAlgorithm::ECDSA;
+
+ return nRet;
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getSHA1Thumbprint()
+{
+ return getThumbprint(m_pCertContext, CERT_SHA1_HASH_PROP_ID);
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getMD5Thumbprint()
+{
+ return getThumbprint(m_pCertContext, CERT_MD5_HASH_PROP_ID);
+}
+
+CertificateKind SAL_CALL X509Certificate_MSCryptImpl::getCertificateKind()
+{
+ return CertificateKind_X509;
+}
+
+sal_Int32 SAL_CALL X509Certificate_MSCryptImpl::getCertificateUsage( )
+{
+ sal_Int32 usage =
+ CERT_DATA_ENCIPHERMENT_KEY_USAGE |
+ CERT_DIGITAL_SIGNATURE_KEY_USAGE |
+ CERT_KEY_AGREEMENT_KEY_USAGE |
+ CERT_KEY_CERT_SIGN_KEY_USAGE |
+ CERT_KEY_ENCIPHERMENT_KEY_USAGE |
+ CERT_NON_REPUDIATION_KEY_USAGE |
+ CERT_OFFLINE_CRL_SIGN_KEY_USAGE;
+
+ if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr && m_pCertContext->pCertInfo->cExtension != 0 )
+ {
+ CERT_EXTENSION* pExtn = CertFindExtension(
+ szOID_KEY_USAGE,
+ m_pCertContext->pCertInfo->cExtension,
+ m_pCertContext->pCertInfo->rgExtension);
+
+ if (pExtn != nullptr)
+ {
+ DWORD length = 0;
+ bool rc = CryptDecodeObject(
+ X509_ASN_ENCODING,
+ X509_KEY_USAGE,
+ pExtn->Value.pbData,
+ pExtn->Value.cbData,
+ 0,
+ nullptr,
+ &length);
+
+ if (!rc)
+ SAL_WARN("xmlsecurity.xmlsec", "CryptDecodeObject failed: " << WindowsErrorString(GetLastError()));
+ else
+ {
+ std::vector<char>buffer(length);
+
+ rc = CryptDecodeObject(
+ X509_ASN_ENCODING,
+ X509_KEY_USAGE,
+ pExtn->Value.pbData,
+ pExtn->Value.cbData,
+ 0,
+ buffer.data(),
+ &length);
+
+ CRYPT_BIT_BLOB *blob = reinterpret_cast<CRYPT_BIT_BLOB*>(buffer.data());
+ if (!rc)
+ SAL_WARN("xmlsecurity.xmlsec", "CryptDecodeObject failed: " << WindowsErrorString(GetLastError()));
+ else if (blob->cbData == 1)
+ usage = blob->pbData[0];
+ else
+ SAL_WARN("xmlsecurity.xmlsec", "CryptDecodeObject(X509_KEY_USAGE) returned unexpected amount of data: " << blob->cbData);
+ }
+ }
+ }
+
+ return usage;
+}
+
+/* XServiceInfo */
+OUString SAL_CALL X509Certificate_MSCryptImpl::getImplementationName()
+{
+ return "com.sun.star.xml.security.gpg.XCertificate_MsCryptImpl";
+}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL X509Certificate_MSCryptImpl::supportsService(const OUString& serviceName)
+{
+ return cppu::supportsService(this, serviceName);
+}
+
+/* XServiceInfo */
+Sequence<OUString> SAL_CALL X509Certificate_MSCryptImpl::getSupportedServiceNames()
+{
+ return { OUString() };
+}
+
+namespace xmlsecurity {
+
+// based on some guesswork and:
+// https://datatracker.ietf.org/doc/html/rfc1485
+// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certnametostra#CERT_X500_NAME_STR
+// the main problem appears to be that in values NSS uses \ escapes but CryptoAPI requires " quotes around value
+static OUString CompatDNNSS(OUString const& rDN)
+{
+ OUStringBuffer buf(rDN.getLength());
+ enum { DEFAULT, INVALUE, INQUOTE } state(DEFAULT);
+ for (sal_Int32 i = 0; i < rDN.getLength(); ++i)
+ {
+ if (state == DEFAULT)
+ {
+ buf.append(rDN[i]);
+ if (rDN[i] == '=')
+ {
+ if (rDN.getLength() == i+1)
+ {
+ break; // invalid?
+ }
+ else
+ {
+ buf.append('"');
+ state = INVALUE;
+ }
+ }
+ }
+ else if (state == INVALUE)
+ {
+ if (rDN[i] == '+' || rDN[i] == ',' || rDN[i] == ';')
+ {
+ buf.append('"');
+ buf.append(rDN[i]);
+ state = DEFAULT;
+ }
+ else if (rDN[i] == '\\')
+ {
+ if (rDN.getLength() == i+1)
+ {
+ break; // invalid?
+ }
+ if (rDN[i+1] == '"')
+ {
+ buf.append('"');
+ }
+ buf.append(rDN[i+1]);
+ ++i;
+ }
+ else
+ {
+ buf.append(rDN[i]);
+ }
+ if (i+1 == rDN.getLength())
+ {
+ buf.append('"');
+ state = DEFAULT;
+ }
+ }
+ }
+ return buf.makeStringAndClear();
+}
+
+static bool EncodeDistinguishedName(std::u16string_view const rName, CERT_NAME_BLOB & rBlob)
+{
+ LPCWSTR pszError;
+ if (!CertStrToNameW(X509_ASN_ENCODING,
+ reinterpret_cast<LPCWSTR>(rName.data()), CERT_X500_NAME_STR,
+ nullptr, nullptr, &rBlob.cbData, &pszError))
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "CertStrToNameW failed: " << WindowsErrorString(GetLastError()) << "; " << OUString(o3tl::toU(pszError)));
+ return false;
+ }
+ rBlob.pbData = new BYTE[rBlob.cbData];
+ if (!CertStrToNameW(X509_ASN_ENCODING,
+ reinterpret_cast<LPCWSTR>(rName.data()), CERT_X500_NAME_STR,
+ nullptr, rBlob.pbData, &rBlob.cbData, &pszError))
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "CertStrToNameW failed: " << WindowsErrorString(GetLastError()) << "; " << OUString(o3tl::toU(pszError)));
+ return false;
+ }
+ return true;
+}
+
+bool EqualDistinguishedNames(
+ std::u16string_view const rName1, std::u16string_view const rName2,
+ EqualMode const eMode)
+{
+ if (eMode == COMPAT_BOTH && !rName1.empty() && rName1 == rName2)
+ { // handle case where both need to be converted
+ return true;
+ }
+ CERT_NAME_BLOB blob1;
+ if (!EncodeDistinguishedName(rName1, blob1))
+ {
+ return false;
+ }
+ CERT_NAME_BLOB blob2;
+ bool ret(false);
+ if (EncodeDistinguishedName(rName2, blob2))
+ {
+ ret = CertCompareCertificateName(X509_ASN_ENCODING,
+ &blob1, &blob2) == TRUE;
+ delete[] blob2.pbData;
+ }
+ if (!ret && eMode == COMPAT_2ND)
+ {
+ CERT_NAME_BLOB blob2compat;
+ if (!EncodeDistinguishedName(CompatDNNSS(OUString(rName2)), blob2compat))
+ {
+ delete[] blob1.pbData;
+ return false;
+ }
+ ret = CertCompareCertificateName(X509_ASN_ENCODING,
+ &blob1, &blob2compat) == TRUE;
+ delete[] blob2compat.pbData;
+ }
+ delete[] blob1.pbData;
+ return ret;
+}
+
+} // namespace xmlsecurity
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx
new file mode 100644
index 000000000..9bd6a34ce
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <Windows.h>
+#include <WinCrypt.h>
+#include <sal/config.h>
+#include <rtl/ustring.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/SecurityException.hpp>
+#include <com/sun/star/security/CertificateKind.hpp>
+#include <com/sun/star/security/XCertificate.hpp>
+#include <certificate.hxx>
+
+class X509Certificate_MSCryptImpl : public ::cppu::WeakImplHelper<
+ css::security::XCertificate ,
+ css::lang::XUnoTunnel,
+ css::lang::XServiceInfo > , public xmlsecurity::Certificate
+{
+ private:
+ const CERT_CONTEXT* m_pCertContext ;
+
+ public:
+ X509Certificate_MSCryptImpl() ;
+ virtual ~X509Certificate_MSCryptImpl() override;
+
+ //Methods from XCertificate
+ virtual sal_Int16 SAL_CALL getVersion() override;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSerialNumber() override;
+ virtual OUString SAL_CALL getIssuerName() override;
+ virtual OUString SAL_CALL getSubjectName() override;
+ virtual css::util::DateTime SAL_CALL getNotValidBefore() override;
+ virtual css::util::DateTime SAL_CALL getNotValidAfter() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getIssuerUniqueID() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectUniqueID() override;
+ virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL getExtensions() override;
+ virtual css::uno::Reference< css::security::XCertificateExtension > SAL_CALL findCertificateExtension( const css::uno::Sequence< sal_Int8 >& oid ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getEncoded() override;
+ virtual OUString SAL_CALL getSubjectPublicKeyAlgorithm() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectPublicKeyValue() override;
+ virtual OUString SAL_CALL getSignatureAlgorithm() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSHA1Thumbprint() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getMD5Thumbprint() override;
+ virtual css::security::CertificateKind SAL_CALL getCertificateKind() override;
+
+
+ virtual sal_Int32 SAL_CALL getCertificateUsage( ) override;
+
+ //Methods from XUnoTunnel
+ UNO3_GETIMPLEMENTATION_DECL(X509Certificate_MSCryptImpl)
+
+ /// @see xmlsecurity::Certificate::getSHA256Thumbprint().
+ virtual css::uno::Sequence<sal_Int8> getSHA256Thumbprint() override;
+
+ /// @see xmlsecurity::Certificate::getSignatureMethodAlgorithm().
+ virtual svl::crypto::SignatureMethodAlgorithm getSignatureMethodAlgorithm() override;
+
+ //Helper methods
+ void setMswcryCert( const CERT_CONTEXT* cert ) ;
+ const CERT_CONTEXT* getMswcryCert() const ;
+ /// @throws css::uno::RuntimeException
+ void setRawCert( css::uno::Sequence< sal_Int8 > const & rawCert ) ;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+} ;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx
new file mode 100644
index 000000000..7d71d4863
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+#include <xmlsec-wrapper.h>
+
+#include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp>
+#include "securityenvironment_mscryptimpl.hxx"
+
+#include <xmlsec/xmlstreamio.hxx>
+#include "akmngr.hxx"
+
+#include <cppuhelper/supportsservice.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang ;
+using ::com::sun::star::lang::XMultiServiceFactory ;
+using ::com::sun::star::lang::XSingleServiceFactory ;
+
+using ::com::sun::star::xml::crypto::XSecurityEnvironment ;
+using ::com::sun::star::xml::crypto::XXMLSecurityContext ;
+
+namespace {
+
+class XMLSecurityContext_MSCryptImpl : public ::cppu::WeakImplHelper<
+ css::xml::crypto::XXMLSecurityContext ,
+ css::lang::XServiceInfo >
+{
+ private:
+ //xmlSecKeysMngrPtr m_pKeysMngr ;
+ css::uno::Reference< css::xml::crypto::XSecurityEnvironment > m_xSecurityEnvironment ;
+
+ public:
+ XMLSecurityContext_MSCryptImpl();
+
+ //Methods from XXMLSecurityContext
+ virtual sal_Int32 SAL_CALL addSecurityEnvironment(
+ const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aSecurityEnvironment
+ ) override;
+
+ virtual ::sal_Int32 SAL_CALL getSecurityEnvironmentNumber( ) override;
+
+ virtual css::uno::Reference<
+ css::xml::crypto::XSecurityEnvironment > SAL_CALL
+ getSecurityEnvironmentByIndex( ::sal_Int32 index ) override;
+
+ virtual css::uno::Reference<
+ css::xml::crypto::XSecurityEnvironment > SAL_CALL
+ getSecurityEnvironment( ) override;
+
+ virtual ::sal_Int32 SAL_CALL getDefaultSecurityEnvironmentIndex( ) override;
+
+ virtual void SAL_CALL setDefaultSecurityEnvironmentIndex( sal_Int32 nDefaultEnvIndex ) override;
+
+
+ //Methods from XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(
+ const OUString& ServiceName
+ ) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+}
+
+XMLSecurityContext_MSCryptImpl::XMLSecurityContext_MSCryptImpl()
+{
+}
+
+sal_Int32 SAL_CALL XMLSecurityContext_MSCryptImpl::addSecurityEnvironment(
+ const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aSecurityEnvironment)
+{
+ if( !aSecurityEnvironment.is() )
+ {
+ throw uno::RuntimeException() ;
+ }
+
+ m_xSecurityEnvironment = aSecurityEnvironment;
+
+ return 0;
+}
+
+
+sal_Int32 SAL_CALL XMLSecurityContext_MSCryptImpl::getSecurityEnvironmentNumber( )
+{
+ return 1;
+}
+
+css::uno::Reference< css::xml::crypto::XSecurityEnvironment > SAL_CALL
+ XMLSecurityContext_MSCryptImpl::getSecurityEnvironmentByIndex( sal_Int32 index )
+{
+ if (index != 0)
+ {
+ throw uno::RuntimeException() ;
+ }
+ return m_xSecurityEnvironment;
+}
+
+css::uno::Reference< css::xml::crypto::XSecurityEnvironment > SAL_CALL
+ XMLSecurityContext_MSCryptImpl::getSecurityEnvironment( )
+{
+ return m_xSecurityEnvironment;
+}
+
+sal_Int32 SAL_CALL XMLSecurityContext_MSCryptImpl::getDefaultSecurityEnvironmentIndex( )
+{
+ return 0;
+}
+
+void SAL_CALL XMLSecurityContext_MSCryptImpl::setDefaultSecurityEnvironmentIndex( sal_Int32 /*nDefaultEnvIndex*/ )
+{
+ //dummy
+}
+
+/* XServiceInfo */
+OUString SAL_CALL XMLSecurityContext_MSCryptImpl::getImplementationName() {
+ return "com.sun.star.xml.crypto.XMLSecurityContext" ;
+}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL XMLSecurityContext_MSCryptImpl::supportsService( const OUString& serviceName) {
+ return cppu::supportsService(this, serviceName);
+}
+
+/* XServiceInfo */
+uno::Sequence< OUString > SAL_CALL XMLSecurityContext_MSCryptImpl::getSupportedServiceNames() {
+ return { "com.sun.star.xml.crypto.XMLSecurityContext" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_xml_crypto_XMLSecurityContext_get_implementation(
+ uno::XComponentContext* /*pCtx*/, uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new XMLSecurityContext_MSCryptImpl);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx
new file mode 100644
index 000000000..87af0f040
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx
@@ -0,0 +1,312 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+#include <rtl/uuid.h>
+#include <xmlsec-wrapper.h>
+
+#include <xmlsec/mscng/x509.h>
+
+#include <com/sun/star/xml/crypto/SecurityOperationStatus.hpp>
+#include <com/sun/star/xml/crypto/XXMLSignature.hpp>
+
+#include "securityenvironment_mscryptimpl.hxx"
+
+#include <xmlsec/xmldocumentwrapper_xmlsecimpl.hxx>
+#include <xmlelementwrapper_xmlsecimpl.hxx>
+#include <xmlsec/xmlstreamio.hxx>
+#include <xmlsec/errorcallback.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno ;
+using namespace ::com::sun::star::lang ;
+using ::com::sun::star::lang::XMultiServiceFactory ;
+using ::com::sun::star::lang::XSingleServiceFactory ;
+
+using ::com::sun::star::xml::wrapper::XXMLElementWrapper ;
+using ::com::sun::star::xml::wrapper::XXMLDocumentWrapper ;
+using ::com::sun::star::xml::crypto::XSecurityEnvironment ;
+using ::com::sun::star::xml::crypto::XXMLSignature ;
+using ::com::sun::star::xml::crypto::XXMLSignatureTemplate ;
+using ::com::sun::star::xml::crypto::XXMLSecurityContext ;
+using ::com::sun::star::xml::crypto::XUriBinding ;
+
+namespace {
+
+class XMLSignature_MSCryptImpl : public ::cppu::WeakImplHelper<
+ css::xml::crypto::XXMLSignature ,
+ css::lang::XServiceInfo >
+{
+ public:
+ explicit XMLSignature_MSCryptImpl();
+
+ //Methods from XXMLSignature
+ virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL generate(
+ const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate ,
+ const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aEnvironment
+ ) override;
+
+ virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL validate(
+ const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate ,
+ const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& aContext
+ ) override;
+
+ //Methods from XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(
+ const OUString& ServiceName
+ ) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+} ;
+
+}
+
+XMLSignature_MSCryptImpl::XMLSignature_MSCryptImpl() {
+}
+
+/* XXMLSignature */
+Reference< XXMLSignatureTemplate >
+SAL_CALL XMLSignature_MSCryptImpl::generate(
+ const Reference< XXMLSignatureTemplate >& aTemplate ,
+ const Reference< XSecurityEnvironment >& aEnvironment
+)
+{
+ xmlSecKeysMngrPtr pMngr = nullptr ;
+ xmlSecDSigCtxPtr pDsigCtx = nullptr ;
+ xmlNodePtr pNode = nullptr ;
+
+ if( !aTemplate.is() )
+ throw RuntimeException() ;
+
+ if( !aEnvironment.is() )
+ throw RuntimeException() ;
+
+ //Get Keys Manager
+ Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY_THROW ) ;
+ SecurityEnvironment_MSCryptImpl* pSecEnv = comphelper::getFromUnoTunnel<SecurityEnvironment_MSCryptImpl>(xSecTunnel);
+ if( pSecEnv == nullptr )
+ throw RuntimeException() ;
+
+ //Get the xml node
+ Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
+ if( !xElement.is() ) {
+ throw RuntimeException() ;
+ }
+
+ Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ;
+ XMLElementWrapper_XmlSecImpl* pElement = comphelper::getFromUnoTunnel<XMLElementWrapper_XmlSecImpl>(xNodTunnel);
+ if( pElement == nullptr ) {
+ throw RuntimeException() ;
+ }
+
+ pNode = pElement->getNativeElement() ;
+
+ //Get the stream/URI binding
+ Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ;
+ if( xUriBinding.is() ) {
+ //Register the stream input callbacks into libxml2
+ if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 )
+ throw RuntimeException() ;
+ }
+
+ setErrorRecorder( );
+
+ pMngr = pSecEnv->createKeysManager();
+ if( !pMngr ) {
+ throw RuntimeException() ;
+ }
+
+ //Create Signature context
+ pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ;
+ if( pDsigCtx == nullptr )
+ {
+ //throw XMLSignatureException() ;
+ SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr );
+ clearErrorRecorder();
+ return aTemplate;
+ }
+
+ //Sign the template
+ if( xmlSecDSigCtxSign( pDsigCtx , pNode ) == 0 )
+ {
+ if (pDsigCtx->status == xmlSecDSigStatusSucceeded)
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
+ else
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
+ }
+ else
+ {
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
+ }
+
+
+ xmlSecDSigCtxDestroy( pDsigCtx ) ;
+ SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr );
+
+ //Unregistered the stream/URI binding
+ if( xUriBinding.is() )
+ xmlUnregisterStreamInputCallbacks() ;
+
+ clearErrorRecorder();
+ return aTemplate ;
+}
+
+/* XXMLSignature */
+Reference< XXMLSignatureTemplate >
+SAL_CALL XMLSignature_MSCryptImpl::validate(
+ const Reference< XXMLSignatureTemplate >& aTemplate ,
+ const Reference< XXMLSecurityContext >& aSecurityCtx
+) {
+ xmlSecKeysMngrPtr pMngr = nullptr ;
+ xmlSecDSigCtxPtr pDsigCtx = nullptr ;
+ xmlNodePtr pNode = nullptr ;
+
+ if( !aTemplate.is() )
+ throw RuntimeException() ;
+
+ if( !aSecurityCtx.is() )
+ throw RuntimeException() ;
+
+ //Get Keys Manager
+ Reference< XSecurityEnvironment > xSecEnv
+ = aSecurityCtx->getSecurityEnvironmentByIndex(
+ aSecurityCtx->getDefaultSecurityEnvironmentIndex());
+ Reference< XUnoTunnel > xSecTunnel( xSecEnv , UNO_QUERY_THROW ) ;
+ SecurityEnvironment_MSCryptImpl* pSecEnv = comphelper::getFromUnoTunnel<SecurityEnvironment_MSCryptImpl>(xSecTunnel);
+ if( pSecEnv == nullptr )
+ throw RuntimeException() ;
+
+ //Get the xml node
+ Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
+ if( !xElement.is() )
+ throw RuntimeException() ;
+
+ Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ;
+ XMLElementWrapper_XmlSecImpl* pElement = comphelper::getFromUnoTunnel<XMLElementWrapper_XmlSecImpl>(xNodTunnel);
+ if( pElement == nullptr )
+ throw RuntimeException() ;
+
+ pNode = pElement->getNativeElement() ;
+
+ //Get the stream/URI binding
+ Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ;
+ if( xUriBinding.is() ) {
+ //Register the stream input callbacks into libxml2
+ if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 )
+ throw RuntimeException() ;
+ }
+
+ setErrorRecorder( );
+
+ pMngr = pSecEnv->createKeysManager();
+ if( !pMngr ) {
+ throw RuntimeException() ;
+ }
+
+ //Create Signature context
+ pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ;
+ if( pDsigCtx == nullptr )
+ {
+ SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr );
+ clearErrorRecorder();
+ return aTemplate;
+ }
+
+ // We do certificate verification ourselves.
+ pDsigCtx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
+
+ // limit possible key data to valid X509 certificates only, no KeyValues
+ if (xmlSecPtrListAdd(&(pDsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecMSCngKeyDataX509GetKlass()) < 0)
+ throw RuntimeException("failed to limit allowed key data");
+
+ //Verify signature
+ //The documentation says that the signature is only valid if the return value is 0 (that is, not < 0)
+ //AND pDsigCtx->status == xmlSecDSigStatusSucceeded. That is, we must not make any assumptions, if
+ //the return value is < 0. Then we must regard the signature as INVALID. We cannot use the
+ //error recorder feature to get the ONE error that made the verification fail, because there is no
+ //documentation/specification as to how to interpret the number of recorded errors and what is the initial
+ //error.
+ int rs = xmlSecDSigCtxVerify(pDsigCtx , pNode);
+
+ // Also verify manifest: this is empty for ODF, but contains everything (except signature metadata) for OOXML.
+ xmlSecSize nReferenceCount = xmlSecPtrListGetSize(&pDsigCtx->manifestReferences);
+ // Require that all manifest references are also good.
+ xmlSecSize nReferenceGood = 0;
+ for (xmlSecSize nReference = 0; nReference < nReferenceCount; ++nReference)
+ {
+ xmlSecDSigReferenceCtxPtr pReference = static_cast<xmlSecDSigReferenceCtxPtr>(xmlSecPtrListGetItem(&pDsigCtx->manifestReferences, nReference));
+ if (pReference)
+ {
+ if (pReference->status == xmlSecDSigStatusSucceeded)
+ ++nReferenceGood;
+ }
+ }
+ SAL_INFO("xmlsecurity.xmlsec", "xmlSecDSigCtxVerify status " << pDsigCtx->status << ", references good " << nReferenceGood << " of " << nReferenceCount);
+
+ if (rs == 0 && nReferenceCount == nReferenceGood)
+ {
+ if (pDsigCtx->status == xmlSecDSigStatusSucceeded)
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
+ else
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
+ }
+ else
+ {
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
+ }
+
+ xmlSecDSigCtxDestroy( pDsigCtx ) ;
+ SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr );
+
+ //Unregistered the stream/URI binding
+ if( xUriBinding.is() )
+ xmlUnregisterStreamInputCallbacks() ;
+
+
+ clearErrorRecorder();
+ return aTemplate;
+}
+
+/* XServiceInfo */
+OUString SAL_CALL XMLSignature_MSCryptImpl::getImplementationName() {
+ return "com.sun.star.xml.crypto.XMLSignature";
+}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL XMLSignature_MSCryptImpl::supportsService( const OUString& serviceName) {
+return cppu::supportsService(this, serviceName);
+}
+
+/* XServiceInfo */
+Sequence< OUString > SAL_CALL XMLSignature_MSCryptImpl::getSupportedServiceNames() {
+ return { "com.sun.star.xml.crypto.XMLSignature" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_xml_crypto_XMLSignature_get_implementation(uno::XComponentContext* /*pCtx*/,
+ uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new XMLSignature_MSCryptImpl);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/certerrors.h b/xmlsecurity/source/xmlsec/nss/certerrors.h
new file mode 100644
index 000000000..e8b7b3873
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/certerrors.h
@@ -0,0 +1,385 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+{SEC_ERROR_IO, "An I/O error occurred during security authorization."},
+
+{SEC_ERROR_LIBRARY_FAILURE, "security library failure."},
+
+{SEC_ERROR_BAD_DATA, "security library: received bad data."},
+
+{SEC_ERROR_OUTPUT_LEN, "security library: output length error."},
+
+{SEC_ERROR_INPUT_LEN, "security library has experienced an input length error."},
+
+{SEC_ERROR_INVALID_ARGS, "security library: invalid arguments."},
+
+{SEC_ERROR_INVALID_ALGORITHM, "security library: invalid algorithm."},
+
+{SEC_ERROR_INVALID_AVA, "security library: invalid AVA."},
+
+{SEC_ERROR_INVALID_TIME, "Improperly formatted time string."},
+
+{SEC_ERROR_BAD_DER, "security library: improperly formatted DER-encoded message."},
+
+{SEC_ERROR_BAD_SIGNATURE, "Peer's certificate has an invalid signature."},
+
+{SEC_ERROR_EXPIRED_CERTIFICATE, "Peer's Certificate has expired."},
+
+{SEC_ERROR_REVOKED_CERTIFICATE, "Peer's Certificate has been revoked."},
+
+{SEC_ERROR_UNKNOWN_ISSUER, "Peer's Certificate issuer is not recognized."},
+
+{SEC_ERROR_BAD_KEY, "Peer's public key is invalid."},
+
+{SEC_ERROR_BAD_PASSWORD, "The security password entered is incorrect."},
+
+{SEC_ERROR_RETRY_PASSWORD, "New password entered incorrectly. Please try again."},
+
+{SEC_ERROR_NO_NODELOCK, "security library: no nodelock."},
+
+{SEC_ERROR_BAD_DATABASE, "security library: bad database."},
+
+{SEC_ERROR_NO_MEMORY, "security library: memory allocation failure."},
+
+{SEC_ERROR_UNTRUSTED_ISSUER, "Peer's certificate issuer has been marked as not trusted by the user."},
+
+{SEC_ERROR_UNTRUSTED_CERT, "Peer's certificate has been marked as not trusted by the user."},
+
+{SEC_ERROR_DUPLICATE_CERT, "Certificate already exists in your database."},
+
+{SEC_ERROR_DUPLICATE_CERT_NAME, "Downloaded certificate's name duplicates one already in your database."},
+
+{SEC_ERROR_ADDING_CERT, "Error adding certificate to database."},
+
+{SEC_ERROR_FILING_KEY, "Error refiling the key for this certificate."},
+
+{SEC_ERROR_NO_KEY, "The private key for this certificate cannot be found in key database"},
+
+{SEC_ERROR_CERT_VALID, "This certificate is valid."},
+
+{SEC_ERROR_CERT_NOT_VALID, "This certificate is not valid."},
+
+{SEC_ERROR_CERT_NO_RESPONSE, "Cert Library: No Response"},
+
+{SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE, "The certificate issuer's certificate has expired. Check your system date and time."},
+
+{SEC_ERROR_CRL_EXPIRED, "The CRL for the certificate's issuer has expired. Update it or check your system date and time."},
+
+{SEC_ERROR_CRL_BAD_SIGNATURE, "The CRL for the certificate's issuer has an invalid signature."},
+
+{SEC_ERROR_CRL_INVALID, "New CRL has an invalid format."},
+
+{SEC_ERROR_EXTENSION_VALUE_INVALID, "Certificate extension value is invalid."},
+
+{SEC_ERROR_EXTENSION_NOT_FOUND, "Certificate extension not found."},
+
+{SEC_ERROR_CA_CERT_INVALID, "Issuer certificate is invalid."},
+
+{SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID, "Certificate path length constraint is invalid."},
+
+{SEC_ERROR_CERT_USAGES_INVALID, "Certificate usages field is invalid."},
+
+{SEC_INTERNAL_ONLY, "**Internal ONLY module**"},
+
+{SEC_ERROR_INVALID_KEY, "The key does not support the requested operation."},
+
+{SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION, "Certificate contains unknown critical extension."},
+
+{SEC_ERROR_OLD_CRL, "New CRL is not later than the current one."},
+
+{SEC_ERROR_NO_EMAIL_CERT, "Not encrypted or signed: you do not yet have an email certificate."},
+
+{SEC_ERROR_NO_RECIPIENT_CERTS_QUERY, "Not encrypted: you do not have certificates for each of the recipients."},
+
+{SEC_ERROR_NOT_A_RECIPIENT, "Cannot decrypt: you are not a recipient, or matching certificate and \
+private key not found."},
+
+{SEC_ERROR_PKCS7_KEYALG_MISMATCH, "Cannot decrypt: key encryption algorithm does not match your certificate."},
+
+{SEC_ERROR_PKCS7_BAD_SIGNATURE, "Signature verification failed: no signer found, too many signers found, \
+or improper or corrupted data."},
+
+{SEC_ERROR_UNSUPPORTED_KEYALG, "Unsupported or unknown key algorithm."},
+
+{SEC_ERROR_DECRYPTION_DISALLOWED, "Cannot decrypt: encrypted using a disallowed algorithm or key size."},
+
+
+/* Fortezza Alerts */
+{XP_SEC_FORTEZZA_BAD_CARD, "Fortezza card has not been properly initialized. \
+Please remove it and return it to your issuer."},
+
+{XP_SEC_FORTEZZA_NO_CARD, "No Fortezza cards Found"},
+
+{XP_SEC_FORTEZZA_NONE_SELECTED, "No Fortezza card selected"},
+
+{XP_SEC_FORTEZZA_MORE_INFO, "Please select a personality to get more info on"},
+
+{XP_SEC_FORTEZZA_PERSON_NOT_FOUND, "Personality not found"},
+
+{XP_SEC_FORTEZZA_NO_MORE_INFO, "No more information on that Personality"},
+
+{XP_SEC_FORTEZZA_BAD_PIN, "Invalid Pin"},
+
+{XP_SEC_FORTEZZA_PERSON_ERROR, "Couldn't initialize Fortezza personalities."},
+/* end fortezza alerts. */
+
+{SEC_ERROR_NO_KRL, "No KRL for this site's certificate has been found."},
+
+{SEC_ERROR_KRL_EXPIRED, "The KRL for this site's certificate has expired."},
+
+{SEC_ERROR_KRL_BAD_SIGNATURE, "The KRL for this site's certificate has an invalid signature."},
+
+{SEC_ERROR_REVOKED_KEY, "The key for this site's certificate has been revoked."},
+
+{SEC_ERROR_KRL_INVALID, "New KRL has an invalid format."},
+
+{SEC_ERROR_NEED_RANDOM, "security library: need random data."},
+
+{SEC_ERROR_NO_MODULE, "security library: no security module can perform the requested operation."},
+
+{SEC_ERROR_NO_TOKEN, "The security card or token does not exist, needs to be initialized, or has been removed."},
+
+{SEC_ERROR_READ_ONLY, "security library: read-only database."},
+
+{SEC_ERROR_NO_SLOT_SELECTED, "No slot or token was selected."},
+
+{SEC_ERROR_CERT_NICKNAME_COLLISION, "A certificate with the same nickname already exists."},
+
+{SEC_ERROR_KEY_NICKNAME_COLLISION, "A key with the same nickname already exists."},
+
+{SEC_ERROR_SAFE_NOT_CREATED, "error while creating safe object"},
+
+{SEC_ERROR_BAGGAGE_NOT_CREATED, "error while creating baggage object"},
+
+{XP_JAVA_REMOVE_PRINCIPAL_ERROR, "Couldn't remove the principal"},
+
+{XP_JAVA_DELETE_PRIVILEGE_ERROR, "Couldn't delete the privilege"},
+
+{XP_JAVA_CERT_NOT_EXISTS_ERROR, "This principal doesn't have a certificate"},
+
+{SEC_ERROR_BAD_EXPORT_ALGORITHM, "Required algorithm is not allowed."},
+
+{SEC_ERROR_EXPORTING_CERTIFICATES, "Error attempting to export certificates."},
+
+{SEC_ERROR_IMPORTING_CERTIFICATES, "Error attempting to import certificates."},
+
+{SEC_ERROR_PKCS12_DECODING_PFX, "Unable to import. Decoding error. File not valid."},
+
+{SEC_ERROR_PKCS12_INVALID_MAC, "Unable to import. Invalid MAC. Incorrect password or corrupt file."},
+
+{SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM, "Unable to import. MAC algorithm not supported."},
+
+{SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE, "Unable to import. Only password integrity and privacy modes supported."},
+
+{SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE, "Unable to import. File structure is corrupt."},
+
+{SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM, "Unable to import. Encryption algorithm not supported."},
+
+{SEC_ERROR_PKCS12_UNSUPPORTED_VERSION, "Unable to import. File version not supported."},
+
+{SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT, "Unable to import. Incorrect privacy password."},
+
+{SEC_ERROR_PKCS12_CERT_COLLISION, "Unable to import. Same nickname already exists in database."},
+
+{SEC_ERROR_USER_CANCELLED, "The user pressed cancel."},
+
+{SEC_ERROR_PKCS12_DUPLICATE_DATA, "Not imported, already in database."},
+
+{SEC_ERROR_MESSAGE_SEND_ABORTED, "Message not sent."},
+
+{SEC_ERROR_INADEQUATE_KEY_USAGE, "Certificate key usage inadequate for attempted operation."},
+
+{SEC_ERROR_INADEQUATE_CERT_TYPE, "Certificate type not approved for application."},
+
+{SEC_ERROR_CERT_ADDR_MISMATCH, "Address in signing certificate does not match address in message headers."},
+
+{SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY, "Unable to import. Error attempting to import private key."},
+
+{SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN, "Unable to import. Error attempting to import certificate chain."},
+
+{SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME, "Unable to export. Unable to locate certificate or key by nickname."},
+
+{SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY, "Unable to export. Private Key could not be located and exported."},
+
+{SEC_ERROR_PKCS12_UNABLE_TO_WRITE, "Unable to export. Unable to write the export file."},
+
+{SEC_ERROR_PKCS12_UNABLE_TO_READ, "Unable to import. Unable to read the import file."},
+
+{SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED, "Unable to export. Key database corrupt or deleted."},
+
+{SEC_ERROR_KEYGEN_FAIL, "Unable to generate public/private key pair."},
+
+{SEC_ERROR_INVALID_PASSWORD, "Password entered is invalid. Please pick a different one."},
+
+{SEC_ERROR_RETRY_OLD_PASSWORD, "Old password entered incorrectly. Please try again."},
+
+{SEC_ERROR_BAD_NICKNAME, "Certificate nickname already in use."},
+
+{SEC_ERROR_NOT_FORTEZZA_ISSUER, "Peer FORTEZZA chain has a non-FORTEZZA Certificate."},
+
+{SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY, "A sensitive key cannot be moved to the slot where it is needed."},
+
+{SEC_ERROR_JS_INVALID_MODULE_NAME, "Invalid module name."},
+
+{SEC_ERROR_JS_INVALID_DLL, "Invalid module path/filename"},
+
+{SEC_ERROR_JS_ADD_MOD_FAILURE, "Unable to add module"},
+
+{SEC_ERROR_JS_DEL_MOD_FAILURE, "Unable to delete module"},
+
+{SEC_ERROR_OLD_KRL, "New KRL is not later than the current one."},
+
+{SEC_ERROR_CKL_CONFLICT, "New CKL has different issuer than current CKL. Delete current CKL."},
+
+{SEC_ERROR_CERT_NOT_IN_NAME_SPACE, "The Certifying Authority for this certificate is not permitted to issue a \
+certificate with this name."},
+
+{SEC_ERROR_KRL_NOT_YET_VALID, "The key revocation list for this certificate is not yet valid."},
+
+{SEC_ERROR_CRL_NOT_YET_VALID, "The certificate revocation list for this certificate is not yet valid."},
+
+{SEC_ERROR_UNKNOWN_CERT, "The requested certificate could not be found."},
+
+{SEC_ERROR_UNKNOWN_SIGNER, "The signer's certificate could not be found."},
+
+{SEC_ERROR_CERT_BAD_ACCESS_LOCATION, "The location for the certificate status server has invalid format."},
+
+{SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE, "The OCSP response cannot be fully decoded; it is of an unknown type."},
+
+{SEC_ERROR_OCSP_BAD_HTTP_RESPONSE, "The OCSP server returned unexpected/invalid HTTP data."},
+
+{SEC_ERROR_OCSP_MALFORMED_REQUEST, "The OCSP server found the request to be corrupted or improperly formed."},
+
+{SEC_ERROR_OCSP_SERVER_ERROR, "The OCSP server experienced an internal error."},
+
+{SEC_ERROR_OCSP_TRY_SERVER_LATER, "The OCSP server suggests trying again later."},
+
+{SEC_ERROR_OCSP_REQUEST_NEEDS_SIG, "The OCSP server requires a signature on this request."},
+
+{SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST, "The OCSP server has refused this request as unauthorized."},
+
+{SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, "The OCSP server returned an unrecognizable status."},
+
+{SEC_ERROR_OCSP_UNKNOWN_CERT, "The OCSP server has no status for the certificate."},
+
+{SEC_ERROR_OCSP_NOT_ENABLED, "You must enable OCSP before performing this operation."},
+
+{SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER, "You must set the OCSP default responder before performing this operation."},
+
+{SEC_ERROR_OCSP_MALFORMED_RESPONSE, "The response from the OCSP server was corrupted or improperly formed."},
+
+{SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE, "The signer of the OCSP response is not authorized to give status for \
+this certificate."},
+
+{SEC_ERROR_OCSP_FUTURE_RESPONSE, "The OCSP response is not yet valid (contains a date in the future},."},
+
+{SEC_ERROR_OCSP_OLD_RESPONSE, "The OCSP response contains out-of-date information."},
+
+{SEC_ERROR_DIGEST_NOT_FOUND, "The CMS or PKCS #7 Digest was not found in signed message."},
+
+{SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE, "The CMS or PKCS #7 Message type is unsupported."},
+
+{SEC_ERROR_MODULE_STUCK, "PKCS #11 module could not be removed because it is still in use."},
+
+{SEC_ERROR_BAD_TEMPLATE, "Could not decode ASN.1 data. Specified template was invalid."},
+
+{SEC_ERROR_CRL_NOT_FOUND, "No matching CRL was found."},
+
+{SEC_ERROR_REUSED_ISSUER_AND_SERIAL, "You are attempting to import a cert with the same issuer/serial as \
+an existing cert, but that is not the same cert."},
+
+{SEC_ERROR_BUSY, "NSS could not shutdown. Objects are still in use."},
+
+{SEC_ERROR_EXTRA_INPUT, "DER-encoded message contained extra unused data."},
+
+{SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE, "Unsupported elliptic curve."},
+
+{SEC_ERROR_UNSUPPORTED_EC_POINT_FORM, "Unsupported elliptic curve point form."},
+
+{SEC_ERROR_UNRECOGNIZED_OID, "Unrecognized Object Identifier."},
+
+{SEC_ERROR_OCSP_INVALID_SIGNING_CERT, "Invalid OCSP signing certificate in OCSP response."},
+
+{SEC_ERROR_REVOKED_CERTIFICATE_CRL, "Certificate is revoked in issuer's certificate revocation list."},
+
+{SEC_ERROR_REVOKED_CERTIFICATE_OCSP, "Issuer's OCSP responder reports certificate is revoked."},
+
+{SEC_ERROR_CRL_INVALID_VERSION, "Issuer's Certificate Revocation List has an unknown version number."},
+
+{SEC_ERROR_CRL_V1_CRITICAL_EXTENSION, "Issuer's V1 Certificate Revocation List has a critical extension."},
+
+{SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION, "Issuer's V2 Certificate Revocation List has an unknown critical extension."},
+
+{SEC_ERROR_UNKNOWN_OBJECT_TYPE, "Unknown object type specified."},
+
+{SEC_ERROR_INCOMPATIBLE_PKCS11, "PKCS #11 driver violates the spec in an incompatible way."},
+
+{SEC_ERROR_NO_EVENT, "No new slot event is available at this time."},
+
+{SEC_ERROR_CRL_ALREADY_EXISTS, "CRL already exists."},
+
+{SEC_ERROR_NOT_INITIALIZED, "NSS is not initialized."},
+
+{SEC_ERROR_TOKEN_NOT_LOGGED_IN, "The operation failed because the PKCS#11 token is not logged in."},
+
+{SEC_ERROR_OCSP_RESPONDER_CERT_INVALID, "Configured OCSP responder's certificate is invalid."},
+
+{SEC_ERROR_OCSP_BAD_SIGNATURE, "OCSP response has an invalid signature."},
+
+{SEC_ERROR_OUT_OF_SEARCH_LIMITS, "Cert validation search is out of search limits"},
+
+{SEC_ERROR_INVALID_POLICY_MAPPING, "Policy mapping contains anypolicy"},
+
+{SEC_ERROR_POLICY_VALIDATION_FAILED, "Cert chain fails policy validation"},
+
+{SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE, "Unknown location type in cert AIA extension"},
+
+{SEC_ERROR_BAD_HTTP_RESPONSE, "Server returned bad HTTP response"},
+
+{SEC_ERROR_BAD_LDAP_RESPONSE, "Server returned bad LDAP response"},
+
+{SEC_ERROR_FAILED_TO_ENCODE_DATA, "Failed to encode data with ASN1 encoder"},
+
+{SEC_ERROR_BAD_INFO_ACCESS_LOCATION, "Bad information access location in cert extension"},
+
+{SEC_ERROR_LIBPKIX_INTERNAL, "Libpkix internal error occurred during cert validation."},
+
+#if ( NSS_VMAJOR > 3 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR > 12 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH > 2 )
+// following 3 errors got first used in NSS 3.12.3
+// they were in the header even in 3.12.2 but there was missing the mapping in pk11err.c
+// see also https://bugzilla.mozilla.org/show_bug.cgi?id=453364
+
+{SEC_ERROR_PKCS11_GENERAL_ERROR, "A PKCS #11 module returned CKR_GENERAL_ERROR, indicating that an unrecoverable error has occurred."},
+
+{SEC_ERROR_PKCS11_FUNCTION_FAILED, "A PKCS #11 module returned CKR_FUNCTION_FAILED, indicating that the requested function could not be performed. Trying the same operation again might succeed."},
+
+{SEC_ERROR_PKCS11_DEVICE_ERROR, "A PKCS #11 module returned CKR_DEVICE_ERROR, indicating that a problem has occurred with the token or slot."},
+
+#endif
+
+#if ( NSS_VMAJOR > 3 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR > 12 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH > 3 )
+// following 2 errors got added in NSS 3.12.4
+
+{SEC_ERROR_BAD_INFO_ACCESS_METHOD, "Unknown information access method in certificate extension."},
+
+{SEC_ERROR_CRL_IMPORT_FAILED, "Error attempting to import a CRL."},
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx b/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx
new file mode 100644
index 000000000..ff3441249
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx
@@ -0,0 +1,265 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <osl/diagnose.h>
+#include <rtl/random.h>
+#include <rtl/ref.hxx>
+
+#include "ciphercontext.hxx"
+#include <pk11pub.h>
+
+using namespace ::com::sun::star;
+
+uno::Reference< xml::crypto::XCipherContext > OCipherContext::Create( CK_MECHANISM_TYPE nNSSCipherID, const uno::Sequence< ::sal_Int8 >& aKey, const uno::Sequence< ::sal_Int8 >& aInitializationVector, bool bEncryption, bool bW3CPadding )
+{
+ ::rtl::Reference< OCipherContext > xResult = new OCipherContext;
+
+ xResult->m_pSlot = PK11_GetBestSlot( nNSSCipherID, nullptr );
+ if ( xResult->m_pSlot )
+ {
+ SECItem aKeyItem = { siBuffer, const_cast< unsigned char* >( reinterpret_cast< const unsigned char* >( aKey.getConstArray() ) ), sal::static_int_cast<unsigned>( aKey.getLength() ) };
+ xResult->m_pSymKey = PK11_ImportSymKey( xResult->m_pSlot, nNSSCipherID, PK11_OriginDerive, bEncryption ? CKA_ENCRYPT : CKA_DECRYPT, &aKeyItem, nullptr );
+ if ( xResult->m_pSymKey )
+ {
+ SECItem aIVItem = { siBuffer, const_cast< unsigned char* >( reinterpret_cast< const unsigned char* >( aInitializationVector.getConstArray() ) ), sal::static_int_cast<unsigned>( aInitializationVector.getLength() ) };
+ xResult->m_pSecParam = PK11_ParamFromIV( nNSSCipherID, &aIVItem );
+ if ( xResult->m_pSecParam )
+ {
+ xResult->m_pContext = PK11_CreateContextBySymKey( nNSSCipherID, bEncryption ? CKA_ENCRYPT : CKA_DECRYPT, xResult->m_pSymKey, xResult->m_pSecParam);
+ if ( xResult->m_pContext )
+ {
+ xResult->m_bEncryption = bEncryption;
+ xResult->m_bW3CPadding = bW3CPadding;
+ xResult->m_bPadding = bW3CPadding || ( PK11_GetPadMechanism( nNSSCipherID ) == nNSSCipherID );
+ xResult->m_nBlockSize = PK11_GetBlockSize( nNSSCipherID, xResult->m_pSecParam );
+ if ( xResult->m_nBlockSize <= SAL_MAX_INT8 )
+ return xResult;
+ }
+ }
+ }
+ }
+
+ return uno::Reference< xml::crypto::XCipherContext >();
+}
+
+void OCipherContext::Dispose()
+{
+ if ( m_pContext )
+ {
+ PK11_DestroyContext( m_pContext, PR_TRUE );
+ m_pContext = nullptr;
+ }
+
+ if ( m_pSecParam )
+ {
+ SECITEM_FreeItem( m_pSecParam, PR_TRUE );
+ m_pSecParam = nullptr;
+ }
+
+ if ( m_pSymKey )
+ {
+ PK11_FreeSymKey( m_pSymKey );
+ m_pSymKey = nullptr;
+ }
+
+ if ( m_pSlot )
+ {
+ PK11_FreeSlot( m_pSlot );
+ m_pSlot = nullptr;
+ }
+
+ m_bDisposed = true;
+}
+
+uno::Sequence< ::sal_Int8 > SAL_CALL OCipherContext::convertWithCipherContext( const uno::Sequence< ::sal_Int8 >& aData )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ if ( m_bBroken )
+ throw uno::RuntimeException();
+
+ if ( m_bDisposed )
+ throw lang::DisposedException();
+
+ uno::Sequence< sal_Int8 > aToConvert;
+ if ( aData.hasElements() )
+ {
+ sal_Int32 nOldLastBlockLen = m_aLastBlock.getLength();
+ OSL_ENSURE( nOldLastBlockLen <= m_nBlockSize, "Unexpected last block size!" );
+
+ sal_Int32 nAvailableData = nOldLastBlockLen + aData.getLength();
+ sal_Int32 nToConvertLen;
+ if ( m_bEncryption || !m_bW3CPadding )
+ {
+ if ( nAvailableData % m_nBlockSize == 0 )
+ nToConvertLen = nAvailableData;
+ else if ( nAvailableData < m_nBlockSize )
+ nToConvertLen = 0;
+ else
+ nToConvertLen = nAvailableData - nAvailableData % m_nBlockSize;
+ }
+ else
+ {
+ // decryption with W3C padding needs at least one block for finalizing
+ if ( nAvailableData < m_nBlockSize * 2 )
+ nToConvertLen = 0;
+ else
+ nToConvertLen = nAvailableData - nAvailableData % m_nBlockSize - m_nBlockSize;
+ }
+
+ aToConvert.realloc( nToConvertLen );
+ if ( nToConvertLen == 0 )
+ {
+ m_aLastBlock.realloc( nOldLastBlockLen + aData.getLength() );
+ memcpy( m_aLastBlock.getArray() + nOldLastBlockLen, aData.getConstArray(), aData.getLength() );
+ // aToConvert stays empty
+ }
+ else if ( nToConvertLen < nOldLastBlockLen )
+ {
+ memcpy( aToConvert.getArray(), m_aLastBlock.getConstArray(), nToConvertLen );
+ memcpy( m_aLastBlock.getArray(), m_aLastBlock.getConstArray() + nToConvertLen, nOldLastBlockLen - nToConvertLen );
+ m_aLastBlock.realloc( nOldLastBlockLen - nToConvertLen + aData.getLength() );
+ memcpy( m_aLastBlock.getArray() + nOldLastBlockLen - nToConvertLen, aData.getConstArray(), aData.getLength() );
+ }
+ else
+ {
+ memcpy( aToConvert.getArray(), m_aLastBlock.getConstArray(), nOldLastBlockLen );
+ if ( nToConvertLen > nOldLastBlockLen )
+ memcpy( aToConvert.getArray() + nOldLastBlockLen, aData.getConstArray(), nToConvertLen - nOldLastBlockLen );
+ m_aLastBlock.realloc( nAvailableData - nToConvertLen );
+ memcpy( m_aLastBlock.getArray(), aData.getConstArray() + nToConvertLen - nOldLastBlockLen, nAvailableData - nToConvertLen );
+ }
+ }
+
+ uno::Sequence< sal_Int8 > aResult;
+ OSL_ENSURE( aToConvert.getLength() % m_nBlockSize == 0, "Unexpected size of the data to encrypt!" );
+ if ( aToConvert.hasElements() )
+ {
+ int nResultLen = 0;
+ aResult.realloc( aToConvert.getLength() + m_nBlockSize );
+ if ( PK11_CipherOp( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() ), &nResultLen, aResult.getLength(), reinterpret_cast< const unsigned char* >( aToConvert.getConstArray() ), aToConvert.getLength() ) != SECSuccess )
+ {
+ m_bBroken = true;
+ Dispose();
+ throw uno::RuntimeException();
+ }
+
+ m_nConverted += aToConvert.getLength();
+ aResult.realloc( nResultLen );
+ }
+
+ return aResult;
+}
+
+uno::Sequence< ::sal_Int8 > SAL_CALL OCipherContext::finalizeCipherContextAndDispose()
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ if ( m_bBroken )
+ throw uno::RuntimeException();
+
+ if ( m_bDisposed )
+ throw lang::DisposedException();
+
+ OSL_ENSURE( m_nBlockSize <= SAL_MAX_INT8, "Unexpected block size!" );
+ OSL_ENSURE( m_nConverted % m_nBlockSize == 0, "Unexpected amount of bytes is already converted!" );
+ sal_Int32 nSizeForPadding = ( m_nConverted + m_aLastBlock.getLength() ) % m_nBlockSize;
+
+ // if it is decryption, the amount of data should be rounded to the block size even in case of padding
+ if ( ( !m_bPadding || !m_bEncryption ) && nSizeForPadding )
+ throw uno::RuntimeException("The data should contain complete blocks only." );
+
+ if ( m_bW3CPadding && m_bEncryption )
+ {
+ // in this case the last block should be smaller than standard block
+ // it will be increased with the padding
+ OSL_ENSURE( m_aLastBlock.getLength() < m_nBlockSize, "Unexpected size of cashed incomplete last block!" );
+
+ // W3CPadding handling for encryption
+ sal_Int32 nPaddingSize = m_nBlockSize - nSizeForPadding;
+ sal_Int32 nOldLastBlockLen = m_aLastBlock.getLength();
+ m_aLastBlock.realloc( nOldLastBlockLen + nPaddingSize );
+ auto pLastBlock = m_aLastBlock.getArray();
+
+ if ( nPaddingSize > 1 )
+ {
+ rtlRandomPool aRandomPool = rtl_random_createPool();
+ rtl_random_getBytes( aRandomPool, pLastBlock + nOldLastBlockLen, nPaddingSize - 1 );
+ rtl_random_destroyPool ( aRandomPool );
+ }
+ pLastBlock[m_aLastBlock.getLength() - 1] = static_cast< sal_Int8 >( nPaddingSize );
+ }
+
+ // finally should the last block be smaller than two standard blocks
+ OSL_ENSURE( m_aLastBlock.getLength() < m_nBlockSize * 2 , "Unexpected size of cashed incomplete last block!" );
+
+ uno::Sequence< sal_Int8 > aResult;
+ if ( m_aLastBlock.hasElements() )
+ {
+ int nPrefResLen = 0;
+ aResult.realloc( m_aLastBlock.getLength() + m_nBlockSize );
+ if ( PK11_CipherOp( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() ), &nPrefResLen, aResult.getLength(), reinterpret_cast< const unsigned char* >( m_aLastBlock.getConstArray() ), m_aLastBlock.getLength() ) != SECSuccess )
+ {
+ m_bBroken = true;
+ Dispose();
+ throw uno::RuntimeException();
+ }
+
+ aResult.realloc( nPrefResLen );
+ m_aLastBlock.realloc( 0 );
+ }
+
+ sal_Int32 nPrefixLen = aResult.getLength();
+ aResult.realloc( nPrefixLen + m_nBlockSize * 2 );
+ unsigned nFinalLen = 0;
+ if ( PK11_DigestFinal( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() + nPrefixLen ), &nFinalLen, aResult.getLength() - nPrefixLen ) != SECSuccess )
+ {
+ m_bBroken = true;
+ Dispose();
+ throw uno::RuntimeException();
+ }
+
+ aResult.realloc( nPrefixLen + nFinalLen );
+
+ if ( m_bW3CPadding && !m_bEncryption )
+ {
+ // W3CPadding handling for decryption
+ // aResult should have enough data, since we let m_aLastBlock be big enough in case of decryption
+ OSL_ENSURE( aResult.getLength() >= m_nBlockSize, "Not enough data to handle the padding!" );
+
+ sal_Int8 nBytesToRemove = aResult[aResult.getLength() - 1];
+ if ( nBytesToRemove <= 0 || nBytesToRemove > aResult.getLength() )
+ {
+ m_bBroken = true;
+ Dispose();
+ throw uno::RuntimeException();
+ }
+
+ aResult.realloc( aResult.getLength() - nBytesToRemove );
+ }
+
+ Dispose();
+
+ return aResult;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/ciphercontext.hxx b/xmlsecurity/source/xmlsec/nss/ciphercontext.hxx
new file mode 100644
index 000000000..40b610ef5
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/ciphercontext.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/crypto/XCipherContext.hpp>
+
+#include <cppuhelper/implbase.hxx>
+#include <mutex>
+#include <seccomon.h>
+#include <secmodt.h>
+
+class OCipherContext : public cppu::WeakImplHelper< css::xml::crypto::XCipherContext >
+{
+private:
+ std::mutex m_aMutex;
+
+ PK11SlotInfo* m_pSlot;
+ PK11SymKey* m_pSymKey;
+ SECItem* m_pSecParam;
+ PK11Context* m_pContext;
+
+ sal_Int32 m_nBlockSize;
+ css::uno::Sequence< sal_Int8 > m_aLastBlock;
+
+ bool m_bEncryption;
+ bool m_bPadding;
+ bool m_bW3CPadding;
+ sal_Int64 m_nConverted;
+
+ bool m_bDisposed;
+ bool m_bBroken;
+
+ void Dispose();
+
+ OCipherContext()
+ : m_pSlot( nullptr )
+ , m_pSymKey( nullptr )
+ , m_pSecParam( nullptr )
+ , m_pContext( nullptr )
+ , m_nBlockSize( 0 )
+ , m_bEncryption( false )
+ , m_bPadding( false )
+ , m_bW3CPadding( false )
+ , m_nConverted( 0 )
+ , m_bDisposed( false )
+ , m_bBroken( false )
+ {}
+
+public:
+
+ virtual ~OCipherContext() override
+ {
+ Dispose();
+ }
+
+ static css::uno::Reference< css::xml::crypto::XCipherContext > Create( CK_MECHANISM_TYPE nNSSCipherID, const css::uno::Sequence< ::sal_Int8 >& aKey, const css::uno::Sequence< ::sal_Int8 >& aInitializationVector, bool bEncryption, bool bW3CPadding );
+
+ // XCipherContext
+ virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL convertWithCipherContext( const css::uno::Sequence< ::sal_Int8 >& aData ) override;
+ virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL finalizeCipherContextAndDispose( ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/digestcontext.cxx b/xmlsecurity/source/xmlsec/nss/digestcontext.cxx
new file mode 100644
index 000000000..63c128e70
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/digestcontext.cxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+
+#include <com/sun/star/lang/DisposedException.hpp>
+
+#include <pk11pub.h>
+#include "digestcontext.hxx"
+
+using namespace ::com::sun::star;
+
+ODigestContext::~ODigestContext()
+{
+ if ( m_pContext )
+ {
+ PK11_DestroyContext( m_pContext, PR_TRUE );
+ m_pContext = nullptr;
+ }
+}
+
+void SAL_CALL ODigestContext::updateDigest( const uno::Sequence< ::sal_Int8 >& aData )
+{
+ std::scoped_lock aGuard( m_aMutex );
+
+ if ( m_bBroken )
+ throw uno::RuntimeException();
+
+ if ( m_bDisposed )
+ throw lang::DisposedException();
+
+ if (m_b1KData && m_nDigested >= 1024)
+ return;
+
+ uno::Sequence< sal_Int8 > aToDigest = aData;
+ if ( m_b1KData && m_nDigested + aData.getLength() > 1024 )
+ aToDigest.realloc( 1024 - m_nDigested );
+
+ if ( PK11_DigestOp( m_pContext, reinterpret_cast< const unsigned char* >( aToDigest.getConstArray() ), aToDigest.getLength() ) != SECSuccess )
+ {
+ PK11_DestroyContext( m_pContext, PR_TRUE );
+ m_pContext = nullptr;
+ m_bBroken = true;
+ throw uno::RuntimeException();
+ }
+
+ m_nDigested += aToDigest.getLength();
+}
+
+uno::Sequence< ::sal_Int8 > SAL_CALL ODigestContext::finalizeDigestAndDispose()
+{
+ std::scoped_lock aGuard( m_aMutex );
+
+ if ( m_bBroken )
+ throw uno::RuntimeException();
+
+ if ( m_bDisposed )
+ throw lang::DisposedException();
+
+ uno::Sequence< sal_Int8 > aResult( m_nDigestLength );
+ unsigned int nResultLen = 0;
+ if ( PK11_DigestFinal( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() ), &nResultLen, aResult.getLength() ) != SECSuccess )
+ {
+ PK11_DestroyContext( m_pContext, PR_TRUE );
+ m_pContext = nullptr;
+ m_bBroken = true;
+ throw uno::RuntimeException();
+ }
+
+ PK11_DestroyContext( m_pContext, PR_TRUE );
+ m_pContext = nullptr;
+ m_bDisposed = true;
+
+ aResult.realloc( nResultLen );
+ return aResult;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/digestcontext.hxx b/xmlsecurity/source/xmlsec/nss/digestcontext.hxx
new file mode 100644
index 000000000..72e186485
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/digestcontext.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/crypto/XDigestContext.hpp>
+
+#include <cppuhelper/implbase.hxx>
+#include <mutex>
+#include <secmodt.h>
+
+class ODigestContext : public cppu::WeakImplHelper< css::xml::crypto::XDigestContext >
+{
+private:
+ std::mutex m_aMutex;
+
+ PK11Context* m_pContext;
+ sal_Int32 const m_nDigestLength;
+ bool const m_b1KData;
+ sal_Int32 m_nDigested;
+
+ bool m_bDisposed;
+ bool m_bBroken;
+
+public:
+ ODigestContext( PK11Context* pContext, sal_Int32 nDigestLength, bool b1KData )
+ : m_pContext( pContext )
+ , m_nDigestLength( nDigestLength )
+ , m_b1KData( b1KData )
+ , m_nDigested( 0 )
+ , m_bDisposed( false )
+ , m_bBroken( false )
+ {}
+
+ virtual ~ODigestContext() override;
+
+
+ // XDigestContext
+ virtual void SAL_CALL updateDigest( const css::uno::Sequence< ::sal_Int8 >& aData ) override;
+ virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL finalizeDigestAndDispose() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx b/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx
new file mode 100644
index 000000000..29b26734e
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx
@@ -0,0 +1,638 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/mozilla/XMozillaBootstrap.hpp>
+#include <com/sun/star/xml/crypto/DigestID.hpp>
+#include <com/sun/star/xml/crypto/CipherID.hpp>
+#include <com/sun/star/xml/crypto/NSSInitializer.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <sal/types.h>
+#include <rtl/bootstrap.hxx>
+#include <rtl/string.hxx>
+#include <osl/file.hxx>
+#include <osl/thread.h>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+#include <unotools/tempfile.hxx>
+#include <salhelper/singletonref.hxx>
+#include <comphelper/sequence.hxx>
+
+#include <nss/nssinitializer.hxx>
+
+#include "digestcontext.hxx"
+#include "ciphercontext.hxx"
+
+#include <cstddef>
+#include <memory>
+#include <vector>
+
+#include <nss.h>
+#include <pk11pub.h>
+#include <secmod.h>
+#include <prerror.h>
+#include <prinit.h>
+
+namespace cssu = css::uno;
+namespace cssl = css::lang;
+
+using namespace com::sun::star;
+
+#define ROOT_CERTS "Root Certs for OpenOffice.org"
+
+extern "C" {
+
+static void nsscrypto_finalize();
+
+}
+
+namespace
+{
+
+class InitNSSPrivate
+{
+private:
+ std::unique_ptr<utl::TempFile> m_pTempFileDatabaseDirectory;
+
+public:
+ OUString getTempDatabasePath()
+ {
+ if (!m_pTempFileDatabaseDirectory)
+ {
+ m_pTempFileDatabaseDirectory.reset(new utl::TempFile(nullptr, true));
+ m_pTempFileDatabaseDirectory->EnableKillingFile();
+ }
+ return m_pTempFileDatabaseDirectory->GetFileName();
+ }
+
+ void reset()
+ {
+ if (m_pTempFileDatabaseDirectory)
+ {
+ m_pTempFileDatabaseDirectory.reset();
+ }
+ }
+};
+
+salhelper::SingletonRef<InitNSSPrivate>* getInitNSSPrivate()
+{
+ static salhelper::SingletonRef<InitNSSPrivate> aInitNSSPrivate;
+ return &aInitNSSPrivate;
+}
+
+bool nsscrypto_initialize( const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool & out_nss_init );
+
+#ifdef XMLSEC_CRYPTO_NSS
+
+void deleteRootsModule()
+{
+ SECMODModule *RootsModule = nullptr;
+ SECMODModuleList *list = SECMOD_GetDefaultModuleList();
+ SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
+ SECMOD_GetReadLock(lock);
+
+ while (!RootsModule && list)
+ {
+ SECMODModule *module = list->module;
+
+ for (int i=0; i < module->slotCount; i++)
+ {
+ PK11SlotInfo *slot = module->slots[i];
+ if (PK11_IsPresent(slot))
+ {
+ if (PK11_HasRootCerts(slot))
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "The root certificates module \"" << module->commonName << "\" is already loaded: " << module->dllName);
+
+ RootsModule = SECMOD_ReferenceModule(module);
+ break;
+ }
+ }
+ }
+ list = list->next;
+ }
+ SECMOD_ReleaseReadLock(lock);
+
+ if (!RootsModule)
+ return;
+
+ PRInt32 modType;
+ if (SECSuccess == SECMOD_DeleteModule(RootsModule->commonName, &modType))
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Deleted module \"" << RootsModule->commonName << "\".");
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Failed to delete \"" << RootsModule->commonName << "\": " << RootsModule->dllName);
+ }
+ SECMOD_DestroyModule(RootsModule);
+ RootsModule = nullptr;
+}
+
+#endif
+
+bool lcl_pathExists(const OUString& sPath)
+{
+ if (sPath.isEmpty())
+ return false;
+
+ ::osl::DirectoryItem aPathItem;
+ OUString sURL;
+ osl::FileBase::getFileURLFromSystemPath(sPath, sURL);
+ if (::osl::FileBase::E_None == ::osl::DirectoryItem::get(sURL, aPathItem))
+ {
+ ::osl::FileStatus aStatus = osl_FileStatus_Mask_Validate;
+ if (::osl::FileBase::E_None == aPathItem.getFileStatus(aStatus))
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace
+
+const OUString & ONSSInitializer::getMozillaCurrentProfile(const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool bSetActive)
+{
+ if (m_bIsNSSinitialized)
+ return m_sNSSPath;
+ if (bSetActive)
+ m_bIsNSSinitialized = true;
+
+ // first, try to get the profile from "MOZILLA_CERTIFICATE_FOLDER"
+ const char* pEnv = getenv("MOZILLA_CERTIFICATE_FOLDER");
+ if (pEnv)
+ {
+ SAL_INFO(
+ "xmlsecurity.xmlsec",
+ "Using Mozilla profile from MOZILLA_CERTIFICATE_FOLDER=" << pEnv);
+ m_sNSSPath = OStringToOUString(pEnv, osl_getThreadTextEncoding());
+ }
+
+ // second, try to get saved user-preference
+ if (m_sNSSPath.isEmpty())
+ {
+ try
+ {
+ OUString sUserSetCertPath =
+ officecfg::Office::Common::Security::Scripting::CertDir::get().value_or(OUString());
+
+ if (lcl_pathExists(sUserSetCertPath))
+ {
+ SAL_INFO(
+ "xmlsecurity.xmlsec",
+ "Using Mozilla profile from /org.openoffice.Office.Common/"
+ "Security/Scripting/CertDir: " << sUserSetCertPath);
+ m_sNSSPath = sUserSetCertPath;
+ }
+ }
+ catch (const uno::Exception &)
+ {
+ TOOLS_WARN_EXCEPTION("xmlsecurity.xmlsec", "getMozillaCurrentProfile:");
+ }
+ }
+
+ // third, dig around to see if there's one default available
+ mozilla::MozillaProductType productTypes[3] = {
+ mozilla::MozillaProductType_Thunderbird,
+ mozilla::MozillaProductType_Firefox,
+ mozilla::MozillaProductType_Mozilla };
+
+ uno::Reference<uno::XInterface> xInstance = rxContext->getServiceManager()->createInstanceWithContext("com.sun.star.mozilla.MozillaBootstrap", rxContext);
+ OSL_ENSURE( xInstance.is(), "failed to create instance" );
+
+ uno::Reference<mozilla::XMozillaBootstrap> xMozillaBootstrap(xInstance,uno::UNO_QUERY);
+ OSL_ENSURE( xMozillaBootstrap.is(), "failed to create instance" );
+
+ if (xMozillaBootstrap.is())
+ {
+ for (std::size_t i=0; i<SAL_N_ELEMENTS(productTypes); ++i)
+ {
+ OUString profile = xMozillaBootstrap->getDefaultProfile(productTypes[i]);
+
+ if (!profile.isEmpty())
+ {
+ OUString sProfilePath = xMozillaBootstrap->getProfilePath(productTypes[i], profile);
+ if (m_sNSSPath.isEmpty())
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Using Mozilla profile " << sProfilePath);
+ m_sNSSPath = sProfilePath;
+ }
+ break;
+ }
+ }
+ }
+
+ SAL_INFO_IF(m_sNSSPath.isEmpty(), "xmlsecurity.xmlsec", "No Mozilla profile found");
+ return m_sNSSPath;
+}
+
+css::uno::Sequence<css::xml::crypto::NSSProfile> SAL_CALL ONSSInitializer::getNSSProfiles()
+{
+ ONSSInitializer::getMozillaCurrentProfile(m_xContext);
+
+ std::vector<xml::crypto::NSSProfile> aProfileList;
+ aProfileList.reserve(10);
+
+ mozilla::MozillaProductType productTypes[3] = {
+ mozilla::MozillaProductType_Thunderbird,
+ mozilla::MozillaProductType_Firefox,
+ mozilla::MozillaProductType_Mozilla };
+
+ uno::Reference<uno::XInterface> xInstance = m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.mozilla.MozillaBootstrap", m_xContext);
+ OSL_ENSURE(xInstance.is(), "failed to create instance" );
+
+ uno::Reference<mozilla::XMozillaBootstrap> xMozillaBootstrap(xInstance,uno::UNO_QUERY);
+
+ if (xMozillaBootstrap.is())
+ {
+ for (std::size_t i=0; i<SAL_N_ELEMENTS(productTypes); ++i)
+ {
+ uno::Sequence<OUString> aProductProfileList;
+ xMozillaBootstrap->getProfileList(productTypes[i], aProductProfileList);
+ for (const auto& sProfile : std::as_const(aProductProfileList))
+ aProfileList.push_back({sProfile, xMozillaBootstrap->getProfilePath(productTypes[i], sProfile), productTypes[i]});
+ }
+ }
+
+ OUString sUserSelect;
+ try
+ {
+ sUserSelect = officecfg::Office::Common::Security::Scripting::CertDir::get().value_or(OUString());;
+ if (!lcl_pathExists(sUserSelect))
+ sUserSelect = OUString();
+ }
+ catch (const uno::Exception &)
+ {
+ TOOLS_WARN_EXCEPTION("xmlsecurity.xmlsec", "getMozillaCurrentProfile:");
+ }
+ aProfileList.push_back({"MANUAL", sUserSelect, mozilla::MozillaProductType_Default});
+
+ const char* pEnv = getenv("MOZILLA_CERTIFICATE_FOLDER");
+ aProfileList.push_back({"MOZILLA_CERTIFICATE_FOLDER",
+ pEnv ? OStringToOUString(pEnv, osl_getThreadTextEncoding()) : OUString(),
+ mozilla::MozillaProductType_Default});
+
+ return comphelper::containerToSequence(aProfileList);
+}
+
+bool ONSSInitializer::m_bIsNSSinitialized = false;
+OUString ONSSInitializer::m_sNSSPath;
+
+OUString SAL_CALL ONSSInitializer::getNSSPath()
+{
+ ONSSInitializer::getMozillaCurrentProfile(m_xContext);
+ return m_sNSSPath;
+};
+
+sal_Bool SAL_CALL ONSSInitializer::getIsNSSinitialized()
+{
+ return m_bIsNSSinitialized;
+}
+
+ONSSInitializer::ONSSInitializer(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
+ : m_xContext(rxContext)
+{
+}
+
+ONSSInitializer::ONSSInitializer()
+{
+}
+
+namespace
+{
+
+//Older versions of Firefox (FF), for example FF2, and Thunderbird (TB) 2 write
+//the roots certificate module (libnssckbi.so), which they use, into the
+//profile. This module will then already be loaded during NSS_Init (and the
+//other init functions). This fails in two cases. First, FF3 was used to create
+//the profile, or possibly used that profile before, and second the profile was
+//used on a different platform.
+//
+//Then one needs to add the roots module oneself. This should be done with
+//SECMOD_LoadUserModule rather than SECMOD_AddNewModule. The latter would write
+//the location of the roots module to the profile, which makes FF2 and TB2 use
+//it instead of their own module.
+//
+//When using SYSTEM_NSS then the libnss3.so lib is typically found in /usr/lib.
+//This folder may, however, NOT contain the roots certificate module. That is,
+//just providing the library name in SECMOD_LoadUserModule or
+//SECMOD_AddNewModule will FAIL to load the mozilla unless the LD_LIBRARY_PATH
+//contains an FF or TB installation.
+//ATTENTION: DO NOT call this function directly instead use initNSS
+//return true - whole initialization was successful
+//param out_nss_init = true: at least the NSS initialization (NSS_InitReadWrite
+//was successful and therefore NSS_Shutdown should be called when terminating.
+bool nsscrypto_initialize(css::uno::Reference<css::uno::XComponentContext> const & rxContext, bool & out_nss_init)
+{
+ // this method must be called only once, no need for additional lock
+ OString sCertDir;
+
+#ifdef XMLSEC_CRYPTO_NSS
+ sCertDir = OUStringToOString(ONSSInitializer::getMozillaCurrentProfile(rxContext, true), osl_getThreadTextEncoding());
+#else
+ (void) rxContext;
+#endif
+ SAL_INFO("xmlsecurity.xmlsec", "Using profile: " << sCertDir );
+
+ PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 1 ) ;
+
+ bool bSuccess = false;
+ // there might be no profile
+ if (!sCertDir.isEmpty())
+ {
+ if (sCertDir.indexOf(':') == -1) //might be env var with explicit prefix
+ {
+ OUString sCertDirURL;
+ osl::FileBase::getFileURLFromSystemPath(
+ OStringToOUString(sCertDir, osl_getThreadTextEncoding()),
+ sCertDirURL);
+ osl::DirectoryItem item;
+ if (osl::FileBase::E_NOENT != osl::DirectoryItem::get(sCertDirURL + "/cert8.db", item) &&
+ osl::FileBase::E_NOENT == osl::DirectoryItem::get(sCertDirURL + "/cert9.db", item))
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "nsscrypto_initialize: trying to avoid profile migration");
+ sCertDir = "dbm:" + sCertDir;
+ }
+ }
+ if (NSS_InitReadWrite(sCertDir.getStr()) != SECSuccess)
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS with profile failed.");
+ int errlen = PR_GetErrorTextLength();
+ if (errlen > 0)
+ {
+ std::unique_ptr<char[]> const error(new char[errlen + 1]);
+ PR_GetErrorText(error.get());
+ SAL_INFO("xmlsecurity.xmlsec", error.get());
+ }
+ }
+ else
+ {
+ bSuccess = true;
+ }
+ }
+
+ if (!bSuccess) // Try to create a database in temp dir
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS with a temporary profile.");
+ OUString rString = (*getInitNSSPrivate())->getTempDatabasePath();
+
+ if (NSS_InitReadWrite(rString.toUtf8().getStr()) != SECSuccess)
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS with a temporary profile.");
+ int errlen = PR_GetErrorTextLength();
+ if(errlen > 0)
+ {
+ std::unique_ptr<char[]> const error(new char[errlen + 1]);
+ PR_GetErrorText(error.get());
+ SAL_INFO("xmlsecurity.xmlsec", error.get());
+ }
+ return false;
+ }
+ }
+
+ // Initialize and set empty password if needed
+ // note: it's possible that the first NSS_InitReadWrite() succeeds by
+ // creating a new DB; in this case it may also be necessary to call
+ // PK11_InitPin()
+ PK11SlotInfo* pSlot = PK11_GetInternalKeySlot();
+ if (pSlot)
+ {
+ if (PK11_NeedUserInit(pSlot))
+ PK11_InitPin(pSlot, nullptr, nullptr);
+ PK11_FreeSlot(pSlot);
+ }
+
+ out_nss_init = true;
+
+#ifdef XMLSEC_CRYPTO_NSS
+ bool return_value = true;
+
+#if defined SYSTEM_NSS || defined IOS // The statically linked nss on iOS acts as a "system" nss in this regards
+ if (!SECMOD_HasRootCerts())
+#endif
+ {
+ deleteRootsModule();
+
+#ifdef IOS // Use statically linked NSS
+ OUString rootModulePath("NSSCKBI");
+
+ if (true)
+#else
+#if defined SYSTEM_NSS || defined ANDROID
+ OUString rootModule("libnssckbi" SAL_DLLEXTENSION);
+#else
+ OUString rootModule("${LO_LIB_DIR}/libnssckbi" SAL_DLLEXTENSION);
+#endif
+ ::rtl::Bootstrap::expandMacros(rootModule);
+
+ OUString rootModulePath;
+ if (::osl::File::E_None == ::osl::File::getSystemPathFromFileURL(rootModule, rootModulePath))
+#endif
+ {
+ OString ospath = OUStringToOString(rootModulePath, osl_getThreadTextEncoding());
+ OString aStr = "name=\"" ROOT_CERTS "\" library=\"" + ospath + "\"";
+
+ SECMODModule * RootsModule =
+ SECMOD_LoadUserModule(
+ const_cast<char*>(aStr.getStr()),
+ nullptr, // no parent
+ PR_FALSE); // do not recurse
+
+ if (RootsModule)
+ {
+
+ bool found = RootsModule->loaded;
+
+ SECMOD_DestroyModule(RootsModule);
+ RootsModule = nullptr;
+ if (found)
+ SAL_INFO("xmlsecurity.xmlsec", "Added new root certificate module " ROOT_CERTS " contained in " << ospath);
+ else
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "FAILED to load the new root certificate module " ROOT_CERTS "contained in " << ospath);
+ return_value = false;
+ }
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "FAILED to add new root certificate module " ROOT_CERTS " contained in " << ospath);
+ return_value = false;
+
+ }
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Adding new root certificate module failed.");
+ return_value = false;
+ }
+ }
+
+ return return_value;
+#else
+ return true;
+#endif
+}
+
+} // namespace
+
+// must be extern "C" because we pass the function pointer to atexit
+extern "C" void nsscrypto_finalize()
+{
+ SECMODModule *RootsModule = SECMOD_FindModule(ROOT_CERTS);
+
+ if (RootsModule)
+ {
+
+ if (SECSuccess == SECMOD_UnloadUserModule(RootsModule))
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Unloaded module \"" ROOT_CERTS "\".");
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Failed unloading module \"" ROOT_CERTS "\".");
+ }
+ SECMOD_DestroyModule(RootsModule);
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Unloading module \"" ROOT_CERTS "\" failed because it was not found.");
+ }
+ PK11_LogoutAll();
+ (void)NSS_Shutdown();
+
+ (*getInitNSSPrivate())->reset();
+}
+
+
+ONSSInitializer::~ONSSInitializer()
+{
+}
+
+bool ONSSInitializer::initNSS( const css::uno::Reference< css::uno::XComponentContext > &rxContext )
+{
+ static bool gbInitialized = [&rxContext]()
+ {
+ bool bNSSInit = false;
+ bool bInitialized = nsscrypto_initialize( rxContext, bNSSInit );
+ if (bNSSInit)
+ atexit(nsscrypto_finalize);
+ return bInitialized;
+ }();
+ return gbInitialized;
+}
+
+css::uno::Reference< css::xml::crypto::XDigestContext > SAL_CALL ONSSInitializer::getDigestContext( ::sal_Int32 nDigestID, const css::uno::Sequence< css::beans::NamedValue >& aParams )
+{
+ SECOidTag nNSSDigestID = SEC_OID_UNKNOWN;
+ sal_Int32 nDigestLength = 0;
+ bool b1KData = false;
+ if ( nDigestID == css::xml::crypto::DigestID::SHA256
+ || nDigestID == css::xml::crypto::DigestID::SHA256_1K )
+ {
+ nNSSDigestID = SEC_OID_SHA256;
+ nDigestLength = 32;
+ b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA256_1K );
+ }
+ else if ( nDigestID == css::xml::crypto::DigestID::SHA1
+ || nDigestID == css::xml::crypto::DigestID::SHA1_1K )
+ {
+ nNSSDigestID = SEC_OID_SHA1;
+ nDigestLength = 20;
+ b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA1_1K );
+ }
+ else if ( nDigestID == css::xml::crypto::DigestID::SHA512
+ || nDigestID == css::xml::crypto::DigestID::SHA512_1K )
+ {
+ nNSSDigestID = SEC_OID_SHA512;
+ nDigestLength = 64;
+ b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA512_1K );
+ }
+ else
+ throw css::lang::IllegalArgumentException("Unexpected digest requested.", css::uno::Reference< css::uno::XInterface >(), 1 );
+
+ if ( aParams.hasElements() )
+ throw css::lang::IllegalArgumentException("Unexpected arguments provided for digest creation.", css::uno::Reference< css::uno::XInterface >(), 2 );
+
+ css::uno::Reference< css::xml::crypto::XDigestContext > xResult;
+ if( initNSS( m_xContext ) )
+ {
+ PK11Context* pContext = PK11_CreateDigestContext( nNSSDigestID );
+ if ( pContext && PK11_DigestBegin( pContext ) == SECSuccess )
+ xResult = new ODigestContext( pContext, nDigestLength, b1KData );
+ }
+
+ return xResult;
+}
+
+css::uno::Reference< css::xml::crypto::XCipherContext > SAL_CALL ONSSInitializer::getCipherContext( ::sal_Int32 nCipherID, const css::uno::Sequence< ::sal_Int8 >& aKey, const css::uno::Sequence< ::sal_Int8 >& aInitializationVector, sal_Bool bEncryption, const css::uno::Sequence< css::beans::NamedValue >& aParams )
+{
+ CK_MECHANISM_TYPE nNSSCipherID = 0;
+ bool bW3CPadding = false;
+ if ( nCipherID != css::xml::crypto::CipherID::AES_CBC_W3C_PADDING )
+ throw css::lang::IllegalArgumentException("Unexpected cipher requested.", css::uno::Reference< css::uno::XInterface >(), 1 );
+
+ nNSSCipherID = CKM_AES_CBC;
+ bW3CPadding = true;
+
+ if ( aKey.getLength() != 16 && aKey.getLength() != 24 && aKey.getLength() != 32 )
+ throw css::lang::IllegalArgumentException("Unexpected key length.", css::uno::Reference< css::uno::XInterface >(), 2 );
+
+ if ( aParams.hasElements() )
+ throw css::lang::IllegalArgumentException("Unexpected arguments provided for cipher creation.", css::uno::Reference< css::uno::XInterface >(), 5 );
+
+ css::uno::Reference< css::xml::crypto::XCipherContext > xResult;
+ if( initNSS( m_xContext ) )
+ {
+ if ( aInitializationVector.getLength() != PK11_GetIVLength( nNSSCipherID ) )
+ throw css::lang::IllegalArgumentException("Unexpected length of initialization vector.", css::uno::Reference< css::uno::XInterface >(), 3 );
+
+ xResult = OCipherContext::Create( nNSSCipherID, aKey, aInitializationVector, bEncryption, bW3CPadding );
+ }
+
+ return xResult;
+}
+
+/* XServiceInfo */
+OUString SAL_CALL ONSSInitializer::getImplementationName()
+{
+ return "com.sun.star.xml.crypto.NSSInitializer";
+}
+
+sal_Bool SAL_CALL ONSSInitializer::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+cssu::Sequence< OUString > SAL_CALL ONSSInitializer::getSupportedServiceNames( )
+{
+ return { NSS_SERVICE_NAME };
+}
+
+#ifndef XMLSEC_CRYPTO_NSS
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_xml_crypto_NSSInitializer_get_implementation(
+ uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new ONSSInitializer(pCtx));
+}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx b/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx
new file mode 100644
index 000000000..fa861c298
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/crypto/XNSSInitializer.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+inline constexpr OUStringLiteral NSS_SERVICE_NAME = u"com.sun.star.xml.crypto.NSSInitializer";
+
+class ONSSInitializer : public cppu::WeakImplHelper
+<
+ css::xml::crypto::XNSSInitializer,
+ css::lang::XServiceInfo
+>
+{
+protected:
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+ static OUString m_sNSSPath;
+ static bool m_bIsNSSinitialized;
+
+ ONSSInitializer();
+
+public:
+ explicit ONSSInitializer(const css::uno::Reference<css::uno::XComponentContext> &rxContext);
+ virtual ~ONSSInitializer() override;
+
+ static bool initNSS( const css::uno::Reference< css::uno::XComponentContext > &rxContext );
+ static const OUString & getMozillaCurrentProfile(const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool bSetActive = false);
+
+ /* XNSSInitializer */
+ virtual OUString SAL_CALL getNSSPath() override;
+ virtual sal_Bool SAL_CALL getIsNSSinitialized() override;
+ virtual css::uno::Sequence<css::xml::crypto::NSSProfile> SAL_CALL getNSSProfiles() override;
+
+ /* XDigestContextSupplier */
+ virtual css::uno::Reference< css::xml::crypto::XDigestContext > SAL_CALL getDigestContext( ::sal_Int32 nDigestID, const css::uno::Sequence< css::beans::NamedValue >& aParams ) override;
+
+ /* XCipherContextSupplier */
+ virtual css::uno::Reference< css::xml::crypto::XCipherContext > SAL_CALL getCipherContext( ::sal_Int32 nCipherID, const css::uno::Sequence< ::sal_Int8 >& aKey, const css::uno::Sequence< ::sal_Int8 >& aInitializationVector, sal_Bool bEncryption, const css::uno::Sequence< css::beans::NamedValue >& aParams ) override;
+
+ /* XServiceInfo */
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/nssrenam.h b/xmlsecurity/source/xmlsec/nss/nssrenam.h
new file mode 100644
index 000000000..47280408b
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/nssrenam.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 2001 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#pragma once
+
+#define CERT_NewTempCertificate __CERT_NewTempCertificate
+#define PK11_GetKeyData __PK11_GetKeyData
+#define CERT_DecodeDERCertificate __CERT_DecodeDERCertificate
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.cxx
new file mode 100644
index 000000000..e37a5473c
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.cxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/security/ExtAltNameType.hpp>
+#include <com/sun/star/security/CertAltNameEntry.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <comphelper/sequence.hxx>
+#include <seccomon.h>
+#include <cert.h>
+#include <certt.h>
+
+#include "sanextension_nssimpl.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno ;
+using namespace ::com::sun::star::security ;
+
+namespace {
+ // Helper functions from nss/lib/certdb/genname.c
+ int GetNamesLength(CERTGeneralName *names)
+ {
+ int length = 0;
+ CERTGeneralName *first;
+
+ first = names;
+ if (names != nullptr) {
+ do {
+ length++;
+ names = CERT_GetNextGeneralName(names);
+ } while (names != first);
+ }
+ return length;
+ }
+
+}
+
+//Methods from XSanExtension
+css::uno::Sequence< css::security::CertAltNameEntry > SAL_CALL SanExtensionImpl::getAlternativeNames()
+{
+ if (m_Entries.empty())
+ {
+ SECItem item;
+
+ item.type = siDERCertBuffer;
+ item.data = reinterpret_cast<unsigned char*>(m_Extn.m_xExtnValue.getArray());
+ item.len = m_Extn.m_xExtnValue.getLength();
+
+ PRArenaPool *arena;
+ CERTGeneralName *nameList;
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!arena)
+ return css::uno::Sequence<css::security::CertAltNameEntry>();
+
+ nameList = CERT_DecodeAltNameExtension(arena, &item);
+
+ CERTGeneralName* current = nameList;
+
+ int size = GetNamesLength(nameList);
+ m_Entries.resize(size);
+ for(int i = 0; i < size; ++i){
+ switch (current->type) {
+ case certOtherName: {
+ m_Entries[i].Type = ExtAltNameType_OTHER_NAME;
+ css::beans::PropertyValue otherNameProp;
+ otherNameProp.Name = OUString::createFromAscii(CERT_GetOidString(&current->name.OthName.oid));
+
+ Sequence< sal_Int8 > otherName( current->name.OthName.name.len ) ;
+ auto otherNameRange = asNonConstRange(otherName);
+ for( unsigned int r = 0; r < current->name.OthName.name.len ; r ++ )
+ otherNameRange[r] = *( current->name.OthName.name.data + r ) ;
+
+ otherNameProp.Value <<= otherName;
+
+ m_Entries[i].Value <<= otherNameProp;
+ break;
+ }
+ case certRFC822Name:
+ m_Entries[i].Type = ExtAltNameType_RFC822_NAME;
+ m_Entries[i].Value <<= OUString(reinterpret_cast<char*>(current->name.other.data), current->name.other.len, RTL_TEXTENCODING_ASCII_US);
+ break;
+ case certDNSName:
+ m_Entries[i].Type = ExtAltNameType_DNS_NAME;
+ m_Entries[i].Value <<= OUString(reinterpret_cast<char*>(current->name.other.data), current->name.other.len, RTL_TEXTENCODING_ASCII_US);
+ break;
+ case certX400Address: {
+ // unsupported
+ m_Entries[i].Type = ExtAltNameType_X400_ADDRESS;
+ break;
+ }
+ case certDirectoryName: {
+ // unsupported
+ m_Entries[i].Type = ExtAltNameType_DIRECTORY_NAME;
+ break;
+ }
+ case certEDIPartyName: {
+ // unsupported
+ m_Entries[i].Type = ExtAltNameType_EDI_PARTY_NAME;
+ break;
+ }
+ case certURI:
+ m_Entries[i].Type = ExtAltNameType_URL;
+ m_Entries[i].Value <<= OUString(reinterpret_cast<char*>(current->name.other.data), current->name.other.len, RTL_TEXTENCODING_ASCII_US);
+ break;
+ case certIPAddress: {
+ m_Entries[i].Type = ExtAltNameType_IP_ADDRESS;
+
+ Sequence< sal_Int8 > ipAddress( current->name.other.len ) ;
+ auto ipAddressRange = asNonConstRange(ipAddress);
+ for( unsigned int r = 0; r < current->name.other.len ; r ++ )
+ ipAddressRange[r] = *( current->name.other.data + r ) ;
+
+ m_Entries[i].Value <<= ipAddress;
+ break;
+ }
+ case certRegisterID:
+ m_Entries[i].Type = ExtAltNameType_REGISTERED_ID;
+
+
+ OString nssOid(CERT_GetOidString(&current->name.other));
+ OString unoOid = removeOIDFromString(nssOid);
+ m_Entries[i].Value <<= OStringToOUString( unoOid, RTL_TEXTENCODING_ASCII_US );
+ break;
+ }
+ current = CERT_GetNextGeneralName(current);
+ }
+
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return comphelper::containerToSequence<css::security::CertAltNameEntry>(m_Entries);
+}
+
+OString SanExtensionImpl::removeOIDFromString( const OString &oidString)
+{
+ OString objID;
+ OString oid("OID.");
+ if (oidString.match(oid))
+ objID = oidString.copy(oid.getLength());
+ else
+ objID = oidString;
+ return objID;
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.hxx
new file mode 100644
index 000000000..3716d414e
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.hxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/security/XSanExtension.hpp>
+#include <com/sun/star/security/CertAltNameEntry.hpp>
+#include <certificateextension_certextn.hxx>
+#include <vector>
+
+class SanExtensionImpl : public ::cppu::WeakImplHelper<
+ css::security::XSanExtension >
+{
+ private:
+ CertificateExtension_CertExtn m_Extn;
+ std::vector<css::security::CertAltNameEntry> m_Entries;
+
+ static OString removeOIDFromString( const OString &oid);
+
+ public:
+ //Methods from XCertificateExtension
+ virtual sal_Bool SAL_CALL isCritical() override
+ {
+ return m_Extn.m_critical;
+ }
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionId() override
+ {
+ return m_Extn.m_xExtnId;
+ }
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionValue() override
+ {
+ return m_Extn.m_xExtnValue;
+ }
+
+ void setCertExtn(unsigned char const * value, unsigned int vlen, unsigned char const * id, unsigned int idlen, bool critical)
+ {
+ m_Extn.setCertExtn(value, vlen, id, idlen, critical);
+ }
+
+ //Methods from XSanExtension
+
+ virtual css::uno::Sequence< css::security::CertAltNameEntry > SAL_CALL getAlternativeNames() override ;
+} ;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/secerror.cxx b/xmlsecurity/source/xmlsec/nss/secerror.cxx
new file mode 100644
index 000000000..b7e623ce0
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/secerror.cxx
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include <secerr.h>
+#include "secerror.hxx"
+#include <nss.h>
+#include <certt.h>
+#include <sal/log.hxx>
+
+namespace {
+
+struct ErrDesc {
+ PRErrorCode const errNum;
+ const char * errString;
+};
+
+}
+
+const ErrDesc allDesc[] = {
+
+#include "certerrors.h"
+
+};
+
+
+/* Returns a UTF-8 encoded constant error string for "errNum".
+ * Returns NULL of errNum is unknown.
+ */
+const char *
+getCertError(PRErrorCode errNum)
+{
+ for (const ErrDesc& i : allDesc)
+ {
+ if (i.errNum == errNum)
+ return i.errString;
+ }
+
+ return "";
+}
+
+void
+printChainFailure(CERTVerifyLog *log)
+{
+ unsigned int depth = static_cast<unsigned int>(-1);
+ CERTVerifyLogNode *node = nullptr;
+
+ if (log->count > 0)
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Bad certification path:");
+ unsigned long errorFlags = 0;
+ for (node = log->head; node; node = node->next)
+ {
+ if (depth != node->depth)
+ {
+ depth = node->depth;
+ SAL_INFO("xmlsecurity.xmlsec", "Certificate: " << depth <<
+ node->cert->subjectName << ": " <<
+ (depth ? "[Certificate Authority]": ""));
+ }
+ SAL_INFO("xmlsecurity.xmlsec", " ERROR " << node->error << ": " <<
+ getCertError(node->error));
+ const char * specificError = nullptr;
+ const char * issuer = nullptr;
+ switch (node->error)
+ {
+ case SEC_ERROR_INADEQUATE_KEY_USAGE:
+ errorFlags = reinterpret_cast<unsigned long>(node->arg);
+ switch (errorFlags)
+ {
+ case KU_DIGITAL_SIGNATURE:
+ specificError = "Certificate cannot sign.";
+ break;
+ case KU_KEY_ENCIPHERMENT:
+ specificError = "Certificate cannot encrypt.";
+ break;
+ case KU_KEY_CERT_SIGN:
+ specificError = "Certificate cannot sign other certs.";
+ break;
+ default:
+ specificError = "[unknown usage].";
+ break;
+ }
+ break;
+ case SEC_ERROR_INADEQUATE_CERT_TYPE:
+ errorFlags = reinterpret_cast<unsigned long>(node->arg);
+ switch (errorFlags)
+ {
+ case NS_CERT_TYPE_SSL_CLIENT:
+ case NS_CERT_TYPE_SSL_SERVER:
+ specificError = "Certificate cannot be used for SSL.";
+ break;
+ case NS_CERT_TYPE_SSL_CA:
+ specificError = "Certificate cannot be used as an SSL CA.";
+ break;
+ case NS_CERT_TYPE_EMAIL:
+ specificError = "Certificate cannot be used for SMIME.";
+ break;
+ case NS_CERT_TYPE_EMAIL_CA:
+ specificError = "Certificate cannot be used as an SMIME CA.";
+ break;
+ case NS_CERT_TYPE_OBJECT_SIGNING:
+ specificError = "Certificate cannot be used for object signing.";
+ break;
+ case NS_CERT_TYPE_OBJECT_SIGNING_CA:
+ specificError = "Certificate cannot be used as an object signing CA.";
+ break;
+ default:
+ specificError = "[unknown usage].";
+ break;
+ }
+ break;
+ case SEC_ERROR_UNKNOWN_ISSUER:
+ specificError = "Unknown issuer:";
+ issuer = node->cert->issuerName;
+ break;
+ case SEC_ERROR_UNTRUSTED_ISSUER:
+ specificError = "Untrusted issuer:";
+ issuer = node->cert->issuerName;
+ break;
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+ specificError = "Expired issuer certificate:";
+ issuer = node->cert->issuerName;
+ break;
+ default:
+ break;
+ }
+ if (specificError)
+ SAL_INFO("xmlsecurity.xmlsec", specificError);
+ if (issuer)
+ SAL_INFO("xmlsecurity.xmlsec", issuer);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/secerror.hxx b/xmlsecurity/source/xmlsec/nss/secerror.hxx
new file mode 100644
index 000000000..bd5907826
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/secerror.hxx
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <certt.h>
+#include <prerror.h>
+
+const char* getCertError(PRErrorCode errNum);
+
+void printChainFailure(CERTVerifyLog* log);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx
new file mode 100644
index 000000000..f6c35257f
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx
@@ -0,0 +1,890 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include "nssrenam.h"
+#include <cert.h>
+#include <secerr.h>
+#include <ocsp.h>
+
+#include <sal/config.h>
+#include <sal/macros.h>
+#include <osl/diagnose.h>
+#include "securityenvironment_nssimpl.hxx"
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/servicehelper.hxx>
+
+#include <xmlsec-wrapper.h>
+
+#include <rtl/ustrbuf.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/docpasswordrequest.hxx>
+#include <sal/log.hxx>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <vector>
+#include <memory>
+#include <osl/thread.h>
+#include <comphelper/sequence.hxx>
+
+#include "x509certificate_nssimpl.hxx"
+#include "secerror.hxx"
+#include <prerror.h>
+#include <keyhi.h>
+
+// added for password exception
+#include <com/sun/star/security/NoPasswordException.hpp>
+#include <com/sun/star/security/CertificateCharacters.hpp>
+#include <com/sun/star/security/CertificateValidity.hpp>
+
+namespace csss = ::com::sun::star::security;
+using namespace ::com::sun::star::security;
+using namespace com::sun::star;
+using namespace ::com::sun::star::uno ;
+using namespace ::com::sun::star::lang ;
+
+using ::com::sun::star::xml::crypto::XSecurityEnvironment ;
+using ::com::sun::star::security::XCertificate ;
+
+namespace std
+{
+template <> struct default_delete<PRArenaPool>
+{
+ void operator()(PRArenaPool* ptr) { PORT_FreeArena(ptr, PR_FALSE); }
+};
+}
+
+static rtl::Reference<X509Certificate_NssImpl> NssCertToXCert( CERTCertificate* cert ) ;
+static rtl::Reference<X509Certificate_NssImpl> NssPrivKeyToXCert( SECKEYPrivateKey* ) ;
+
+namespace {
+
+struct UsageDescription
+{
+ SECCertificateUsage usage;
+ char const* description;
+
+ UsageDescription()
+ : usage( certificateUsageCheckAllUsages )
+ , description( nullptr )
+ {}
+
+ UsageDescription( SECCertificateUsage i_usage, char const* i_description )
+ : usage( i_usage )
+ , description( i_description )
+ {}
+};
+
+}
+
+static char* GetPasswordFunction( PK11SlotInfo* pSlot, PRBool bRetry, void* /*arg*/ )
+{
+ uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
+ uno::Reference < task::XInteractionHandler2 > xInteractionHandler(
+ task::InteractionHandler::createWithParent(xContext, nullptr) );
+
+ task::PasswordRequestMode eMode = bRetry ? task::PasswordRequestMode_PASSWORD_REENTER : task::PasswordRequestMode_PASSWORD_ENTER;
+ rtl::Reference<::comphelper::DocPasswordRequest> pPasswordRequest = new ::comphelper::DocPasswordRequest(
+ ::comphelper::DocPasswordRequestType::Standard, eMode, OUString::createFromAscii(PK11_GetTokenName(pSlot)) );
+
+ xInteractionHandler->handle( pPasswordRequest );
+
+ if ( pPasswordRequest->isPassword() )
+ {
+ OString aPassword(OUStringToOString(
+ pPasswordRequest->getPassword(),
+ osl_getThreadTextEncoding()));
+ sal_Int32 nLen = aPassword.getLength();
+ char* pPassword = static_cast<char*>(PORT_Alloc( nLen+1 ) );
+ pPassword[nLen] = 0;
+ memcpy( pPassword, aPassword.getStr(), nLen );
+ return pPassword;
+ }
+ return nullptr;
+}
+
+SecurityEnvironment_NssImpl::SecurityEnvironment_NssImpl() :
+m_pHandler( nullptr ) {
+ PK11_SetPasswordFunc( GetPasswordFunction ) ;
+}
+
+SecurityEnvironment_NssImpl::~SecurityEnvironment_NssImpl() {
+
+ PK11_SetPasswordFunc( nullptr ) ;
+
+ for (auto& slot : m_Slots)
+ {
+ PK11_FreeSlot(slot);
+ }
+
+ for( auto& symKey : m_tSymKeyList )
+ PK11_FreeSymKey( symKey ) ;
+}
+
+/* XServiceInfo */
+OUString SAL_CALL SecurityEnvironment_NssImpl::getImplementationName() {
+ return "com.sun.star.xml.crypto.SecurityEnvironment";
+}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL SecurityEnvironment_NssImpl::supportsService( const OUString& serviceName) {
+ return cppu::supportsService(this, serviceName);
+}
+
+/* XServiceInfo */
+Sequence< OUString > SAL_CALL SecurityEnvironment_NssImpl::getSupportedServiceNames() {
+ Sequence<OUString> seqServiceNames{ "com.sun.star.xml.crypto.SecurityEnvironment" };
+ return seqServiceNames;
+}
+
+/* XUnoTunnel */
+sal_Int64 SAL_CALL SecurityEnvironment_NssImpl::getSomething( const Sequence< sal_Int8 >& aIdentifier )
+{
+ return comphelper::getSomethingImpl(aIdentifier, this);
+}
+
+/* XUnoTunnel extension */
+
+const Sequence< sal_Int8>& SecurityEnvironment_NssImpl::getUnoTunnelId() {
+ static const comphelper::UnoIdInit theSecurityEnvironment_NssImplUnoTunnelId;
+ return theSecurityEnvironment_NssImplUnoTunnelId.getSeq();
+}
+
+OUString SecurityEnvironment_NssImpl::getSecurityEnvironmentInformation()
+{
+ OUStringBuffer buff;
+ for (auto& slot : m_Slots)
+ {
+ buff.append(OUString::createFromAscii(PK11_GetTokenName(slot)));
+ buff.append("\n");
+ }
+ return buff.makeStringAndClear();
+}
+
+void SecurityEnvironment_NssImpl::addCryptoSlot( PK11SlotInfo* aSlot)
+{
+ PK11_ReferenceSlot(aSlot);
+ m_Slots.push_back(aSlot);
+}
+
+//Could we have multiple cert dbs?
+void SecurityEnvironment_NssImpl::setCertDb( CERTCertDBHandle* aCertDb ) {
+ m_pHandler = aCertDb ;
+}
+
+void SecurityEnvironment_NssImpl::adoptSymKey( PK11SymKey* aSymKey ) {
+ if( aSymKey == nullptr ) return;
+
+ //First try to find the key in the list
+ if (std::find(m_tSymKeyList.begin(), m_tSymKeyList.end(), aSymKey) != m_tSymKeyList.end())
+ return;
+
+ //If we do not find the key in the list, add a new node
+ PK11SymKey* symkey = PK11_ReferenceSymKey( aSymKey ) ;
+ if( symkey == nullptr )
+ throw RuntimeException() ;
+
+ try {
+ m_tSymKeyList.push_back( symkey ) ;
+ } catch ( Exception& ) {
+ PK11_FreeSymKey( symkey ) ;
+ }
+}
+
+void SecurityEnvironment_NssImpl::updateSlots()
+{
+ //In case new tokens are present then we can obtain the corresponding slot
+ std::scoped_lock guard(m_mutex);
+
+ m_Slots.clear();
+ m_tSymKeyList.clear();
+
+ PK11SlotList * slotList = PK11_GetAllTokens( CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, nullptr ) ;
+ if( slotList == nullptr )
+ return;
+
+ for (PK11SlotListElement* slotEle = slotList->head ; slotEle != nullptr; slotEle = slotEle->next)
+ {
+ PK11SlotInfo * pSlot = slotEle->slot ;
+
+ if(pSlot != nullptr)
+ {
+ SAL_INFO(
+ "xmlsecurity.xmlsec",
+ "Found a slot: SlotName=" << PK11_GetSlotName(pSlot)
+ << ", TokenName=" << PK11_GetTokenName(pSlot));
+
+//The following code which is commented out checks if a slot, that is a smart card for example, is
+// able to generate a symmetric key of type CKM_DES3_CBC. If this fails then this token
+// will not be used. This key is possibly used for the encryption service. However, all
+// interfaces and services used for public key signature and encryption are not published
+// and the encryption is not used in OOo. Therefore it does not do any harm to remove
+// this code, hence allowing smart cards which cannot generate this type of key.
+//
+// By doing this, the encryption may fail if a smart card is being used which does not
+// support this key generation.
+//
+ PK11SymKey * pSymKey = PK11_KeyGen( pSlot , CKM_DES3_CBC, nullptr, 128, nullptr ) ;
+// if( pSymKey == NULL )
+// {
+// PK11_FreeSlot( pSlot ) ;
+// SAL_INFO( "xmlsecurity", "XMLSEC: Error - pSymKey is NULL" );
+// continue;
+// }
+ addCryptoSlot(pSlot);
+
+ if (pSymKey != nullptr)
+ {
+ adoptSymKey( pSymKey ) ;
+ PK11_FreeSymKey( pSymKey ) ;
+ pSymKey = nullptr;
+ }
+
+ }// end of if(pSlot != NULL)
+ }// end of for
+
+ PK11_FreeSlotList(slotList);
+}
+
+Sequence< Reference < XCertificate > >
+SecurityEnvironment_NssImpl::getPersonalCertificates()
+{
+ std::vector< rtl::Reference<X509Certificate_NssImpl> > certsList ;
+
+ updateSlots();
+ //firstly, we try to find private keys in slot
+ for (auto& slot : m_Slots)
+ {
+ SECKEYPrivateKeyList* priKeyList ;
+
+ if( PK11_NeedLogin(slot ) ) {
+ SECStatus nRet = PK11_Authenticate(slot, PR_TRUE, nullptr);
+ //PK11_Authenticate may fail in case the a slot has not been initialized.
+ //this is the case if the user has a new profile, so that they have never
+ //added a personal certificate.
+ if( nRet != SECSuccess && PORT_GetError() != SEC_ERROR_IO) {
+ throw NoPasswordException();
+ }
+ }
+
+ priKeyList = PK11_ListPrivateKeysInSlot(slot) ;
+ if( priKeyList != nullptr )
+ {
+ for (SECKEYPrivateKeyListNode* curPri = PRIVKEY_LIST_HEAD(priKeyList);
+ !PRIVKEY_LIST_END( curPri, priKeyList ) && curPri != nullptr;
+ curPri = PRIVKEY_LIST_NEXT(curPri))
+ {
+ rtl::Reference<X509Certificate_NssImpl> xcert = NssPrivKeyToXCert( curPri->key ) ;
+ if( xcert != nullptr )
+ certsList.push_back( xcert ) ;
+ }
+ SECKEY_DestroyPrivateKeyList( priKeyList ) ;
+ }
+
+
+ }
+
+ if( certsList.size() != 0 ) {
+ return comphelper::containerToSequence<Reference< XCertificate >>(certsList) ;
+ }
+
+ return Sequence< Reference < XCertificate > > ();
+}
+
+Reference< XCertificate > SecurityEnvironment_NssImpl::getCertificate( const OUString& issuerName, const Sequence< sal_Int8 >& serialNumber )
+{
+ if( !m_pHandler )
+ return nullptr;
+
+ rtl::Reference<X509Certificate_NssImpl> xcert;
+ CERTIssuerAndSN issuerAndSN ;
+ CERTCertificate* cert ;
+ CERTName* nmIssuer ;
+ char* chIssuer ;
+ SECItem* derIssuer ;
+ std::unique_ptr<PRArenaPool> arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
+ if( arena == nullptr )
+ throw RuntimeException() ;
+
+ // Create cert info from issue and serial
+ OString ostr = OUStringToOString( issuerName , RTL_TEXTENCODING_UTF8 ) ;
+ chIssuer = PL_strndup( ostr.getStr(), static_cast<int>(ostr.getLength()) ) ;
+ nmIssuer = CERT_AsciiToName( chIssuer ) ;
+ if( nmIssuer == nullptr ) {
+ PL_strfree( chIssuer ) ;
+ return nullptr; // no need for exception cf. i40394
+ }
+
+ derIssuer = SEC_ASN1EncodeItem( arena.get(), nullptr, static_cast<void*>(nmIssuer), SEC_ASN1_GET( CERT_NameTemplate ) ) ;
+ if( derIssuer == nullptr ) {
+ PL_strfree( chIssuer ) ;
+ CERT_DestroyName( nmIssuer ) ;
+ throw RuntimeException() ;
+ }
+
+ memset( &issuerAndSN, 0, sizeof( issuerAndSN ) ) ;
+
+ issuerAndSN.derIssuer.data = derIssuer->data ;
+ issuerAndSN.derIssuer.len = derIssuer->len ;
+
+ issuerAndSN.serialNumber.data = reinterpret_cast<unsigned char *>(const_cast<sal_Int8 *>(serialNumber.getConstArray()));
+ issuerAndSN.serialNumber.len = serialNumber.getLength() ;
+
+ cert = CERT_FindCertByIssuerAndSN( m_pHandler, &issuerAndSN ) ;
+ if( cert != nullptr ) {
+ xcert = NssCertToXCert( cert ) ;
+ }
+
+ PL_strfree( chIssuer ) ;
+ CERT_DestroyName( nmIssuer ) ;
+ //SECITEM_FreeItem( derIssuer, PR_FALSE ) ;
+ CERT_DestroyCertificate( cert ) ;
+
+ return xcert ;
+}
+
+Sequence< Reference < XCertificate > > SecurityEnvironment_NssImpl::buildCertificatePath( const Reference< XCertificate >& begin ) {
+ // Remember the signing certificate.
+ m_xSigningCertificate = begin;
+
+ Reference< XUnoTunnel > xCertTunnel( begin, UNO_QUERY_THROW ) ;
+ const X509Certificate_NssImpl* xcert = comphelper::getFromUnoTunnel<X509Certificate_NssImpl>(xCertTunnel);
+ if( xcert == nullptr ) {
+ throw RuntimeException() ;
+ }
+
+ const CERTCertificate* cert = xcert->getNssCert() ;
+ if (!cert)
+ return {};
+
+ //Get the system clock time
+ int64 timeboundary = PR_Now() ;
+ CERTCertList* certChain = CERT_GetCertChainFromCert( const_cast<CERTCertificate*>(cert), timeboundary, certUsageAnyCA ) ;
+
+ if( !certChain )
+ return {};
+
+ std::vector<uno::Reference<security::XCertificate>> aCertChain;
+
+ for (CERTCertListNode* node = CERT_LIST_HEAD(certChain); !CERT_LIST_END(node, certChain); node = CERT_LIST_NEXT(node)) {
+ rtl::Reference<X509Certificate_NssImpl> pCert = new X509Certificate_NssImpl();
+ if( pCert == nullptr ) {
+ CERT_DestroyCertList( certChain ) ;
+ throw RuntimeException() ;
+ }
+
+ pCert->setCert( node->cert ) ;
+
+ aCertChain.push_back(pCert);
+ }
+
+ CERT_DestroyCertList( certChain ) ;
+
+ return comphelper::containerToSequence(aCertChain);
+}
+
+rtl::Reference<X509Certificate_NssImpl> SecurityEnvironment_NssImpl::createAndAddCertificateFromPackage(
+ const css::uno::Sequence<sal_Int8>& raDERCertificate,
+ std::u16string_view raString)
+{
+ auto pCertificateBytes = reinterpret_cast<char *>(const_cast<sal_Int8 *>(raDERCertificate.getConstArray()));
+ CERTCertificate* pCERTCertificate = CERT_DecodeCertFromPackage(pCertificateBytes, raDERCertificate.getLength());
+
+ if (!pCERTCertificate)
+ return nullptr;
+
+ SECStatus aStatus;
+
+ OString aTrustString = OUStringToOString(raString, RTL_TEXTENCODING_ASCII_US);
+ CERTCertTrust aTrust;
+
+ aStatus = CERT_DecodeTrustString(&aTrust, aTrustString.getStr());
+
+ if (aStatus != SECSuccess)
+ {
+ PRIntn err = PR_GetError();
+ SAL_WARN("xmlsecurity.xmlsec", "Error: " << err << ": " << getCertError(err));
+ return nullptr;
+ }
+
+ PK11SlotInfo* pSlot = PK11_GetInternalKeySlot();
+
+ if (!pSlot)
+ return nullptr;
+
+ aStatus = PK11_ImportCert(pSlot, pCERTCertificate, CK_INVALID_HANDLE, nullptr, PR_FALSE);
+
+ if (aStatus != SECSuccess)
+ {
+ PRIntn err = PR_GetError();
+ SAL_WARN("xmlsecurity.xmlsec", "Error: " << err << ": " << getCertError(err));
+ return nullptr;
+ }
+
+ aStatus = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), pCERTCertificate, &aTrust);
+
+ if (aStatus != SECSuccess)
+ {
+ PRIntn err = PR_GetError();
+ SAL_WARN("xmlsecurity.xmlsec", "Error: " << err << ": " << getCertError(err));
+ return nullptr;
+ }
+
+ PK11_FreeSlot(pSlot);
+
+ rtl::Reference<X509Certificate_NssImpl> pX509Certificate = new X509Certificate_NssImpl();
+ pX509Certificate->setCert(pCERTCertificate);
+ return pX509Certificate;
+}
+
+rtl::Reference<X509Certificate_NssImpl> SecurityEnvironment_NssImpl::createX509CertificateFromDER(const css::uno::Sequence<sal_Int8>& aDerCertificate)
+{
+ rtl::Reference<X509Certificate_NssImpl> pX509Certificate;
+
+ if (aDerCertificate.hasElements())
+ {
+ pX509Certificate = new X509Certificate_NssImpl();
+ if (pX509Certificate == nullptr)
+ throw RuntimeException();
+ pX509Certificate->setRawCert(aDerCertificate);
+ }
+ return pX509Certificate;
+}
+
+Reference<XCertificate> SecurityEnvironment_NssImpl::createCertificateFromRaw(const Sequence< sal_Int8 >& rawCertificate)
+{
+ return createX509CertificateFromDER(rawCertificate);
+}
+
+Reference< XCertificate > SecurityEnvironment_NssImpl::createCertificateFromAscii( const OUString& asciiCertificate )
+{
+ OString oscert = OUStringToOString( asciiCertificate , RTL_TEXTENCODING_ASCII_US ) ;
+ xmlChar* chCert = xmlStrndup( reinterpret_cast<const xmlChar*>(oscert.getStr()), static_cast<int>(oscert.getLength()) ) ;
+ int certSize = xmlSecBase64Decode( chCert, reinterpret_cast<xmlSecByte*>(chCert), xmlStrlen( chCert ) ) ;
+ if (certSize == 0)
+ return nullptr;
+
+ Sequence< sal_Int8 > rawCert(comphelper::arrayToSequence<sal_Int8>(chCert, certSize)) ;
+
+ xmlFree( chCert ) ;
+
+ return createCertificateFromRaw( rawCert ) ;
+}
+
+sal_Int32 SecurityEnvironment_NssImpl ::
+verifyCertificate( const Reference< csss::XCertificate >& aCert,
+ const Sequence< Reference< csss::XCertificate > >& intermediateCerts )
+{
+ sal_Int32 validity = csss::CertificateValidity::INVALID;
+ const CERTCertificate* cert ;
+ Reference< XUnoTunnel > xCertTunnel( aCert, UNO_QUERY_THROW ) ;
+
+ SAL_INFO("xmlsecurity.xmlsec", "Start verification of certificate: " << aCert->getSubjectName());
+
+ const X509Certificate_NssImpl* xcert = comphelper::getFromUnoTunnel<X509Certificate_NssImpl>(xCertTunnel);
+ if( xcert == nullptr ) {
+ throw RuntimeException() ;
+ }
+
+ //CERT_PKIXVerifyCert does not take a db as argument. It will therefore
+ //internally use CERT_GetDefaultCertDB
+ //Make sure m_pHandler is the default DB
+ OSL_ASSERT(m_pHandler == CERT_GetDefaultCertDB());
+ CERTCertDBHandle * certDb = m_pHandler != nullptr ? m_pHandler : CERT_GetDefaultCertDB();
+ cert = xcert->getNssCert() ;
+ if( !cert )
+ return css::security::CertificateValidity::INVALID;
+
+
+ ::std::vector<CERTCertificate*> vecTmpNSSCertificates;
+
+ //prepare the intermediate certificates
+ for (const auto& rIntermediateCert : intermediateCerts)
+ {
+ Sequence<sal_Int8> der = rIntermediateCert->getEncoded();
+ SECItem item;
+ item.type = siBuffer;
+ item.data = reinterpret_cast<unsigned char*>(der.getArray());
+ item.len = der.getLength();
+
+ CERTCertificate* certTmp = CERT_NewTempCertificate(certDb, &item,
+ nullptr /* nickname */,
+ PR_FALSE /* isPerm */,
+ PR_TRUE /* copyDER */);
+ if (!certTmp)
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Failed to add a temporary certificate: " << rIntermediateCert->getIssuerName());
+
+ }
+ else
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Added temporary certificate: " <<
+ (certTmp->subjectName ? certTmp->subjectName : ""));
+ vecTmpNSSCertificates.push_back(certTmp);
+ }
+ }
+
+
+ SECStatus status ;
+
+ CERTVerifyLog log;
+ log.arena = PORT_NewArena(512);
+ log.head = log.tail = nullptr;
+ log.count = 0;
+
+ CERT_EnableOCSPChecking(certDb);
+ CERT_DisableOCSPDefaultResponder(certDb);
+ CERTValOutParam cvout[5];
+ CERTValInParam cvin[3];
+ int ncvinCount=0;
+
+#if ( NSS_VMAJOR > 3 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR > 12 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH > 0 )
+ cvin[ncvinCount].type = cert_pi_useAIACertFetch;
+ cvin[ncvinCount].value.scalar.b = PR_TRUE;
+ ncvinCount++;
+#endif
+
+ PRUint64 revFlagsLeaf[2];
+ PRUint64 revFlagsChain[2];
+ CERTRevocationFlags rev;
+ rev.leafTests.number_of_defined_methods = 2;
+ rev.leafTests.cert_rev_flags_per_method = revFlagsLeaf;
+ //the flags are defined in cert.h
+ //We check both leaf and chain.
+ //It is enough if one revocation method has fresh info,
+ //but at least one must have some. Otherwise validation fails.
+ //!!! using leaf test and CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE
+ // when validating a root certificate will result in "revoked". Usually
+ //there is no revocation information available for the root cert because
+ //it must be trusted anyway and it does itself issue revocation information.
+ //When we use the flag here and OOo shows the certification path then the root
+ //cert is invalid while all other can be valid. It would probably best if
+ //this interface method returned the whole chain.
+ //Otherwise we need to check if the certificate is self-signed and if it is
+ //then not use the flag when doing the leaf-test.
+ rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_crl] =
+ CERT_REV_M_TEST_USING_THIS_METHOD
+ | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE;
+ rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] =
+ CERT_REV_M_TEST_USING_THIS_METHOD
+ | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE;
+ rev.leafTests.number_of_preferred_methods = 0;
+ rev.leafTests.preferred_methods = nullptr;
+ rev.leafTests.cert_rev_method_independent_flags =
+ CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST;
+
+ rev.chainTests.number_of_defined_methods = 2;
+ rev.chainTests.cert_rev_flags_per_method = revFlagsChain;
+ rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_crl] =
+ CERT_REV_M_TEST_USING_THIS_METHOD
+ | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE;
+ rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] =
+ CERT_REV_M_TEST_USING_THIS_METHOD
+ | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE;
+ rev.chainTests.number_of_preferred_methods = 0;
+ rev.chainTests.preferred_methods = nullptr;
+ rev.chainTests.cert_rev_method_independent_flags =
+ CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST;
+
+
+ cvin[ncvinCount].type = cert_pi_revocationFlags;
+ cvin[ncvinCount].value.pointer.revocation = &rev;
+ ncvinCount++;
+ // does not work, not implemented yet in 3.12.4
+// cvin[ncvinCount].type = cert_pi_keyusage;
+// cvin[ncvinCount].value.scalar.ui = KU_DIGITAL_SIGNATURE;
+// ncvinCount++;
+ cvin[ncvinCount].type = cert_pi_end;
+
+ cvout[0].type = cert_po_trustAnchor;
+ cvout[0].value.pointer.cert = nullptr;
+ cvout[1].type = cert_po_errorLog;
+ cvout[1].value.pointer.log = &log;
+ cvout[2].type = cert_po_end;
+
+ // We check SSL server certificates, CA certificates and signing certificates.
+ //
+ // ToDo check keyusage, looking at CERT_KeyUsageAndTypeForCertUsage (
+ // mozilla/security/nss/lib/certdb/certdb.c indicates that
+ // certificateUsageSSLClient, certificateUsageSSLServer and certificateUsageSSLCA
+ // are sufficient. They cover the key usages for digital signature, key agreement
+ // and encipherment and certificate signature
+
+ //never use the following usages because they are not checked properly
+ // certificateUsageUserCertImport
+ // certificateUsageVerifyCA
+ // certificateUsageAnyCA
+ // certificateUsageProtectedObjectSigner
+
+ UsageDescription arUsages[5];
+ arUsages[0] = UsageDescription( certificateUsageSSLClient, "certificateUsageSSLClient" );
+ arUsages[1] = UsageDescription( certificateUsageSSLServer, "certificateUsageSSLServer" );
+ arUsages[2] = UsageDescription( certificateUsageSSLCA, "certificateUsageSSLCA" );
+ arUsages[3] = UsageDescription( certificateUsageEmailSigner, "certificateUsageEmailSigner" );
+ arUsages[4] = UsageDescription( certificateUsageEmailRecipient, "certificateUsageEmailRecipient" );
+
+ int numUsages = SAL_N_ELEMENTS(arUsages);
+ for (int i = 0; i < numUsages; i++)
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Testing usage " << i+1 <<
+ " of " << numUsages << ": " <<
+ arUsages[i].description <<
+ " (0x" << std::hex << static_cast<int>(arUsages[i].usage) << ")" << std::dec);
+
+ status = CERT_PKIXVerifyCert(const_cast<CERTCertificate *>(cert), arUsages[i].usage,
+ cvin, cvout, nullptr);
+ if( status == SECSuccess )
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "CERT_PKIXVerifyCert returned SECSuccess.");
+ //When an intermediate or root certificate is checked then we expect the usage
+ //certificateUsageSSLCA. This, however, will be only set when in the trust settings dialog
+ //the button "This certificate can identify websites" is checked. If for example only
+ //"This certificate can identify mail users" is set then the end certificate can
+ //be validated and the returned usage will contain certificateUsageEmailRecipient.
+ //But checking directly the root or intermediate certificate will fail. In the
+ //certificate path view the end certificate will be shown as valid but the others
+ //will be displayed as invalid.
+
+ validity = csss::CertificateValidity::VALID;
+ SAL_INFO("xmlsecurity.xmlsec", "Certificate is valid.");
+ CERTCertificate * issuerCert = cvout[0].value.pointer.cert;
+ if (issuerCert)
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Root certificate: " << issuerCert->subjectName);
+ CERT_DestroyCertificate(issuerCert);
+ };
+
+ break;
+ }
+ else
+ {
+ PRIntn err = PR_GetError();
+ SAL_INFO("xmlsecurity.xmlsec", "Error: " << err << ": " << getCertError(err));
+
+ /* Display validation results */
+ if ( log.count > 0)
+ {
+ CERTVerifyLogNode *node = nullptr;
+ printChainFailure(&log);
+
+ for (node = log.head; node; node = node->next) {
+ if (node->cert)
+ CERT_DestroyCertificate(node->cert);
+ }
+ log.head = log.tail = nullptr;
+ log.count = 0;
+ }
+ SAL_INFO("xmlsecurity.xmlsec", "Certificate is invalid.");
+ }
+ }
+
+ //Destroying the temporary certificates
+ for (auto& tmpCert : vecTmpNSSCertificates)
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "Destroying temporary certificate");
+ CERT_DestroyCertificate(tmpCert);
+ }
+ PORT_FreeArena(log.arena, true);
+ return validity ;
+}
+
+sal_Int32 SecurityEnvironment_NssImpl::getCertificateCharacters(
+ const css::uno::Reference< css::security::XCertificate >& aCert ) {
+ sal_Int32 characters ;
+ const CERTCertificate* cert ;
+
+ Reference< XUnoTunnel > xCertTunnel( aCert, UNO_QUERY_THROW ) ;
+ const X509Certificate_NssImpl* xcert = comphelper::getFromUnoTunnel<X509Certificate_NssImpl>(xCertTunnel);
+ if( xcert == nullptr ) {
+ throw RuntimeException() ;
+ }
+
+ cert = xcert->getNssCert() ;
+
+ characters = 0x00000000 ;
+
+ //Firstly, find out whether or not the cert is self-signed.
+ if( SECITEM_CompareItem( &(cert->derIssuer), &(cert->derSubject) ) == SECEqual ) {
+ characters |= css::security::CertificateCharacters::SELF_SIGNED ;
+ } else {
+ characters &= ~ css::security::CertificateCharacters::SELF_SIGNED ;
+ }
+
+ //Secondly, find out whether or not the cert has a private key.
+
+ /*
+ * i40394
+ *
+ * mmi : need to check whether the cert's slot is valid first
+ */
+ SECKEYPrivateKey* priKey = nullptr;
+
+ if (cert->slot != nullptr)
+ {
+ priKey = PK11_FindPrivateKeyFromCert( cert->slot, const_cast<CERTCertificate*>(cert), nullptr ) ;
+ }
+ if(priKey == nullptr)
+ {
+ for (auto& slot : m_Slots)
+ {
+ priKey = PK11_FindPrivateKeyFromCert(slot, const_cast<CERTCertificate*>(cert), nullptr);
+ if (priKey)
+ break;
+ }
+ }
+ if( priKey != nullptr ) {
+ characters |= css::security::CertificateCharacters::HAS_PRIVATE_KEY ;
+
+ SECKEY_DestroyPrivateKey( priKey ) ;
+ } else {
+ characters &= ~ css::security::CertificateCharacters::HAS_PRIVATE_KEY ;
+ }
+
+ return characters ;
+}
+
+rtl::Reference<X509Certificate_NssImpl> NssCertToXCert( CERTCertificate* cert )
+{
+ if( cert != nullptr ) {
+ rtl::Reference<X509Certificate_NssImpl> xcert = new X509Certificate_NssImpl() ;
+ xcert->setCert( cert ) ;
+ return xcert;
+ }
+
+ return nullptr;
+}
+
+rtl::Reference<X509Certificate_NssImpl> NssPrivKeyToXCert( SECKEYPrivateKey* priKey )
+{
+ if( priKey != nullptr ) {
+ rtl::Reference<X509Certificate_NssImpl> xcert;
+ CERTCertificate* cert = PK11_GetCertFromPrivateKey( priKey ) ;
+
+ if( cert != nullptr ) {
+ xcert = NssCertToXCert( cert ) ;
+ }
+
+ CERT_DestroyCertificate( cert ) ;
+ return xcert;
+ }
+
+ return nullptr;
+}
+
+xmlSecKeysMngrPtr SecurityEnvironment_NssImpl::createKeysManager() {
+
+ /*-
+ * The following lines is based on the private version of xmlSec-NSS
+ * crypto engine
+ */
+ int cSlots = m_Slots.size();
+ std::unique_ptr<PK11SlotInfo*[]> sarSlots(new PK11SlotInfo*[cSlots]);
+ PK11SlotInfo** slots = sarSlots.get();
+ int count = 0;
+ for (const auto& slot : m_Slots)
+ {
+ slots[count] = slot;
+ ++count;
+ }
+
+ xmlSecKeysMngrPtr pKeysMngr = xmlSecKeysMngrCreate();
+ if (!pKeysMngr)
+ throw RuntimeException();
+
+ if (xmlSecNssAppDefaultKeysMngrInit(pKeysMngr) < 0)
+ throw RuntimeException();
+
+ // Adopt the private key of the signing certificate, if it has any.
+ if (auto pCertificate = dynamic_cast<X509Certificate_NssImpl*>(m_xSigningCertificate.get()))
+ {
+ SECKEYPrivateKey* pPrivateKey = SECKEY_CopyPrivateKey(pCertificate->getPrivateKey());
+ if (pPrivateKey)
+ {
+ xmlSecKeyDataPtr pKeyData = xmlSecNssPKIAdoptKey(pPrivateKey, nullptr);
+ xmlSecKeyPtr pKey = xmlSecKeyCreate();
+ xmlSecKeySetValue(pKey, pKeyData);
+ xmlSecNssAppDefaultKeysMngrAdoptKey(pKeysMngr, pKey);
+ }
+ else
+ {
+ SAL_WARN("xmlsecurity.xmlsec", "Can't get the private key from the certificate.");
+ }
+ }
+
+ return pKeysMngr;
+}
+
+void SecurityEnvironment_NssImpl::destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr) {
+ if( pKeysMngr != nullptr ) {
+ xmlSecKeysMngrDestroy( pKeysMngr ) ;
+ }
+}
+
+SECKEYPrivateKey* SecurityEnvironment_NssImpl::insertPrivateKey(css::uno::Sequence<sal_Int8> const & raPrivateKey)
+{
+ PK11SlotInfo* pSlot = PK11_GetInternalKeySlot();
+
+ if (!pSlot)
+ return nullptr;
+
+ SECItem aDerPrivateKeyInfo;
+ aDerPrivateKeyInfo.data = reinterpret_cast<unsigned char *>(const_cast<sal_Int8 *>(raPrivateKey.getConstArray()));
+ aDerPrivateKeyInfo.len = raPrivateKey.getLength();
+
+ const unsigned int aKeyUsage = KU_ALL;
+ SECKEYPrivateKey* pPrivateKey = nullptr;
+
+ bool bPermanent = PR_FALSE;
+ bool bPrivate = PR_TRUE;
+
+ SECStatus nStatus = PK11_ImportDERPrivateKeyInfoAndReturnKey(
+ pSlot, &aDerPrivateKeyInfo, nullptr, nullptr, bPermanent, bPrivate,
+ aKeyUsage, &pPrivateKey, nullptr);
+
+ if (nStatus != SECSuccess)
+ return nullptr;
+
+ PK11_FreeSlot(pSlot);
+
+ return pPrivateKey;
+}
+
+uno::Reference<security::XCertificate> SecurityEnvironment_NssImpl::createDERCertificateWithPrivateKey(
+ Sequence<sal_Int8> const & raDERCertificate, Sequence<sal_Int8> const & raPrivateKey)
+{
+ SECKEYPrivateKey* pPrivateKey = insertPrivateKey(raPrivateKey);
+
+ if (!pPrivateKey)
+ return uno::Reference<security::XCertificate>();
+
+ return createAndAddCertificateFromPackage(raDERCertificate, u"TCu,TCu,TCu");
+}
+
+uno::Reference<security::XCertificate> SecurityEnvironment_NssImpl::addDERCertificateToTheDatabase(
+ uno::Sequence<sal_Int8> const & raDERCertificate, OUString const & raTrustString)
+{
+ return createAndAddCertificateFromPackage(raDERCertificate, raTrustString);
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_xml_crypto_SecurityEnvironment_get_implementation(
+ uno::XComponentContext* /*pCtx*/, uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new SecurityEnvironment_NssImpl);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx
new file mode 100644
index 000000000..123103720
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+#include <rtl/ustring.hxx>
+#include <rtl/ref.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
+#include <com/sun/star/xml/crypto/XCertificateCreator.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+
+#include <mutex>
+
+#include <keythi.h>
+#include <certt.h>
+
+#include <string_view>
+#include <vector>
+
+#include <xmlsec-wrapper.h>
+
+namespace com::sun::star::security { class XCertificate; }
+class X509Certificate_NssImpl;
+
+class SecurityEnvironment_NssImpl : public ::cppu::WeakImplHelper<
+ css::xml::crypto::XSecurityEnvironment,
+ css::xml::crypto::XCertificateCreator,
+ css::lang::XServiceInfo,
+ css::lang::XUnoTunnel >
+{
+private:
+
+ std::vector< PK11SlotInfo* > m_Slots;
+ /// The last used certificate which has the private key for signing.
+ css::uno::Reference<css::security::XCertificate> m_xSigningCertificate;
+
+ std::mutex m_mutex;
+
+ CERTCertDBHandle* m_pHandler ;
+ std::vector< PK11SymKey* > m_tSymKeyList ;
+
+ public:
+ SecurityEnvironment_NssImpl();
+ virtual ~SecurityEnvironment_NssImpl() override;
+
+ //Methods from XSecurityEnvironment
+
+ //Methods from XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override ;
+
+ virtual sal_Bool SAL_CALL supportsService(
+ const OUString& ServiceName
+ ) override ;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override ;
+
+ virtual ::sal_Int32 SAL_CALL verifyCertificate(
+ const css::uno::Reference<
+ css::security::XCertificate >& xCert,
+ const css::uno::Sequence<
+ css::uno::Reference< css::security::XCertificate > > &
+ intermediateCerts) override ;
+
+ virtual ::sal_Int32 SAL_CALL getCertificateCharacters( const css::uno::Reference< css::security::XCertificate >& xCert ) override ;
+
+ virtual OUString SAL_CALL getSecurityEnvironmentInformation( ) override;
+
+ //Methods from XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override;
+
+ static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId() ;
+
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ void setCertDb( CERTCertDBHandle* aCertDb ) ;
+
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ void adoptSymKey( PK11SymKey* aSymKey ) ;
+
+ virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getPersonalCertificates() override ;
+ virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getAllCertificates() override
+ { return css::uno::Sequence< css::uno::Reference< css::security::XCertificate > >(); }
+
+ virtual css::uno::Reference< css::security::XCertificate > SAL_CALL getCertificate( const OUString& issuerName, const css::uno::Sequence< sal_Int8 >& serialNumber ) override ;
+
+ virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL buildCertificatePath( const css::uno::Reference< css::security::XCertificate >& beginCert ) override ;
+
+ virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromRaw( const css::uno::Sequence< sal_Int8 >& rawCertificate ) override ;
+ virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromAscii( const OUString& asciiCertificate ) override ;
+
+ // Methods of XCertificateCreator
+ css::uno::Reference<css::security::XCertificate> SAL_CALL addDERCertificateToTheDatabase(
+ css::uno::Sequence<sal_Int8> const & raDERCertificate,
+ OUString const & raTrustString) override;
+
+ css::uno::Reference<css::security::XCertificate> SAL_CALL createDERCertificateWithPrivateKey(
+ css::uno::Sequence<sal_Int8> const & raDERCertificate,
+ css::uno::Sequence<sal_Int8> const & raPrivateKey) override;
+
+ //Native methods
+ /// @throws css::uno::RuntimeException
+ xmlSecKeysMngrPtr createKeysManager() ;
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ static void destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr) ;
+
+private:
+
+ void updateSlots();
+
+ static rtl::Reference<X509Certificate_NssImpl> createAndAddCertificateFromPackage(
+ const css::uno::Sequence<sal_Int8>& raDerCertificate,
+ std::u16string_view raString);
+ static SECKEYPrivateKey* insertPrivateKey(css::uno::Sequence<sal_Int8> const & raPrivateKey);
+
+ static rtl::Reference<X509Certificate_NssImpl> createX509CertificateFromDER(const css::uno::Sequence<sal_Int8>& raDerCertificate);
+
+ /// @throws css::uno::Exception
+ /// @throws css::uno::RuntimeException
+ void addCryptoSlot( PK11SlotInfo* aSlot ) ;
+} ;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx
new file mode 100644
index 000000000..6ada0522b
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx
@@ -0,0 +1,144 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/types.h>
+#include <com/sun/star/xml/crypto/SecurityEnvironment.hpp>
+#include <com/sun/star/xml/crypto/XMLSecurityContext.hpp>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include "seinitializer_nssimpl.hxx"
+#include "securityenvironment_nssimpl.hxx"
+
+#include <cert.h>
+
+
+using namespace com::sun::star;
+
+
+SEInitializer_NssImpl::SEInitializer_NssImpl( const css::uno::Reference< css::uno::XComponentContext > &rxContext )
+{
+ m_xContext = rxContext;
+}
+
+SEInitializer_NssImpl::~SEInitializer_NssImpl()
+{
+}
+
+/* XSEInitializer */
+uno::Reference< css::xml::crypto::XXMLSecurityContext > SAL_CALL
+ SEInitializer_NssImpl::createSecurityContext( const OUString& )
+{
+ CERTCertDBHandle *pCertHandle = nullptr ;
+
+ if( !initNSS( m_xContext ) )
+ return nullptr;
+
+ pCertHandle = CERT_GetDefaultCertDB() ;
+
+ try
+ {
+ /* Build XML Security Context */
+ uno::Reference< css::xml::crypto::XXMLSecurityContext > xSecCtx = css::xml::crypto::XMLSecurityContext::create( m_xContext );
+
+ uno::Reference< css::xml::crypto::XSecurityEnvironment > xSecEnv = css::xml::crypto::SecurityEnvironment::create( m_xContext );
+ uno::Reference< lang::XUnoTunnel > xSecEnvTunnel(xSecEnv, uno::UNO_QUERY_THROW);
+ SecurityEnvironment_NssImpl* pSecEnv = comphelper::getFromUnoTunnel<SecurityEnvironment_NssImpl>(xSecEnvTunnel);
+ pSecEnv->setCertDb(pCertHandle);
+
+ sal_Int32 n = xSecCtx->addSecurityEnvironment(xSecEnv);
+ //originally the SecurityEnvironment with the internal slot was set as default
+ xSecCtx->setDefaultSecurityEnvironmentIndex( n );
+ return xSecCtx;
+ }
+ catch( const uno::Exception& )
+ {
+ //PK11_LogoutAll();
+ //NSS_Shutdown();
+ return nullptr;
+ }
+}
+
+void SAL_CALL SEInitializer_NssImpl::freeSecurityContext( const uno::Reference< css::xml::crypto::XXMLSecurityContext >& )
+{
+ /*
+ * because the security context will free all its content when it
+ * is destructed, so here no free process for the security context
+ * is needed.
+ */
+ //PK11_LogoutAll();
+ //NSS_Shutdown();
+}
+
+/* XServiceInfo */
+OUString SAL_CALL SEInitializer_NssImpl::getImplementationName( )
+{
+ return "com.sun.star.xml.crypto.SEInitializer";
+}
+sal_Bool SAL_CALL SEInitializer_NssImpl::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService( this, rServiceName );
+}
+uno::Sequence< OUString > SAL_CALL SEInitializer_NssImpl::getSupportedServiceNames( )
+{
+ return { "com.sun.star.xml.crypto.SEInitializer" };
+}
+
+namespace {
+
+class NSSInitializer_NssImpl : public SEInitializer_NssImpl
+{
+public:
+ explicit NSSInitializer_NssImpl(const uno::Reference<uno::XComponentContext>& xContext);
+ OUString SAL_CALL getImplementationName() override;
+ uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+}
+
+NSSInitializer_NssImpl::NSSInitializer_NssImpl(const uno::Reference<uno::XComponentContext>& xContext)
+ : SEInitializer_NssImpl(xContext)
+{
+}
+
+OUString NSSInitializer_NssImpl::getImplementationName()
+{
+ return "com.sun.star.xml.crypto.NSSInitializer";
+}
+
+uno::Sequence<OUString> SAL_CALL NSSInitializer_NssImpl::getSupportedServiceNames()
+{
+ return { "com.sun.star.xml.crypto.NSSInitializer" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_xml_crypto_NSSInitializer_get_implementation(
+ uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new NSSInitializer_NssImpl(pCtx));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_xml_crypto_SEInitializer_get_implementation(
+ uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new SEInitializer_NssImpl(pCtx));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx
new file mode 100644
index 000000000..f078f387a
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/crypto/XSEInitializer.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+#include "nssinitializer.hxx"
+
+namespace com::sun::star::xml::crypto { class XXMLSecurityContext; }
+
+class SEInitializer_NssImpl : public cppu::ImplInheritanceHelper
+<
+ ONSSInitializer,
+ css::xml::crypto::XSEInitializer
+>
+{
+public:
+ explicit SEInitializer_NssImpl(const css::uno::Reference<css::uno::XComponentContext > &rxContext);
+ virtual ~SEInitializer_NssImpl() override;
+
+ /* XSEInitializer */
+ virtual css::uno::Reference< css::xml::crypto::XXMLSecurityContext >
+ SAL_CALL createSecurityContext( const OUString& ) override;
+
+ virtual void SAL_CALL freeSecurityContext( const css::uno::Reference<
+ css::xml::crypto::XXMLSecurityContext >& securityContext ) override;
+
+ /* XServiceInfo */
+ virtual OUString SAL_CALL getImplementationName( ) override;
+
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx
new file mode 100644
index 000000000..7e28cbc61
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx
@@ -0,0 +1,614 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include "nssrenam.h"
+#include <secder.h>
+
+#include <cert.h>
+#include <pk11pub.h>
+#include <hasht.h>
+
+#include <comphelper/sequence.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include "x509certificate_nssimpl.hxx"
+
+#include <biginteger.hxx>
+#include <certificateextension_xmlsecimpl.hxx>
+
+#include "sanextension_nssimpl.hxx"
+#include <tools/time.hxx>
+#include <svl/sigstruct.hxx>
+
+using ::css::util::DateTime;
+
+X509Certificate_NssImpl::X509Certificate_NssImpl() :
+ m_pCert(nullptr)
+{
+}
+
+X509Certificate_NssImpl::~X509Certificate_NssImpl() {
+ if( m_pCert != nullptr ) {
+ CERT_DestroyCertificate( m_pCert ) ;
+ }
+}
+
+//Methods from XCertificate
+sal_Int16 SAL_CALL X509Certificate_NssImpl::getVersion() {
+ if( m_pCert != nullptr ) {
+ if( m_pCert->version.len > 0 ) {
+ return static_cast<char>(*( m_pCert->version.data )) ;
+ } else
+ return 0 ;
+ } else {
+ return -1 ;
+ }
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getSerialNumber() {
+ if( m_pCert != nullptr && m_pCert->serialNumber.len > 0 ) {
+ return comphelper::arrayToSequence<sal_Int8>(m_pCert->serialNumber.data,
+ m_pCert->serialNumber.len) ;
+ } else {
+ return css::uno::Sequence< sal_Int8 >();
+ }
+}
+
+OUString SAL_CALL X509Certificate_NssImpl::getIssuerName() {
+ if( m_pCert != nullptr ) {
+ return OUString(m_pCert->issuerName , PL_strlen(m_pCert->issuerName) , RTL_TEXTENCODING_UTF8) ;
+ } else {
+ return OUString() ;
+ }
+}
+
+OUString SAL_CALL X509Certificate_NssImpl::getSubjectName() {
+ if( m_pCert != nullptr ) {
+ return OUString(m_pCert->subjectName , PL_strlen(m_pCert->subjectName) , RTL_TEXTENCODING_UTF8);
+ } else {
+ return OUString() ;
+ }
+}
+
+css::util::DateTime SAL_CALL X509Certificate_NssImpl::getNotValidBefore() {
+ if( m_pCert != nullptr ) {
+ SECStatus rv ;
+ PRTime notBefore ;
+ PRExplodedTime explTime ;
+ DateTime dateTime ;
+
+ rv = DER_DecodeTimeChoice( &notBefore, &m_pCert->validity.notBefore ) ;
+ if( rv != SECStatus::SECSuccess ) {
+ return DateTime() ;
+ }
+
+ //Convert the time to readable local time
+ PR_ExplodeTime( notBefore, PR_LocalTimeParameters, &explTime ) ;
+
+ dateTime.NanoSeconds = static_cast< sal_Int32 >( explTime.tm_usec * ::tools::Time::nanoPerMicro );
+ dateTime.Seconds = static_cast< sal_Int16 >( explTime.tm_sec );
+ dateTime.Minutes = static_cast< sal_Int16 >( explTime.tm_min );
+ dateTime.Hours = static_cast< sal_Int16 >( explTime.tm_hour );
+ dateTime.Day = static_cast< sal_Int16 >( explTime.tm_mday );
+ dateTime.Month = static_cast< sal_Int16 >( explTime.tm_month+1 );
+ dateTime.Year = static_cast< sal_Int16 >( explTime.tm_year );
+
+ return dateTime ;
+ } else {
+ return DateTime() ;
+ }
+}
+
+css::util::DateTime SAL_CALL X509Certificate_NssImpl::getNotValidAfter() {
+ if( m_pCert != nullptr ) {
+ SECStatus rv ;
+ PRTime notAfter ;
+ PRExplodedTime explTime ;
+ DateTime dateTime ;
+
+ rv = DER_DecodeTimeChoice( &notAfter, &m_pCert->validity.notAfter ) ;
+ if( rv != SECStatus::SECSuccess ) {
+ return DateTime() ;
+ }
+
+ //Convert the time to readable local time
+ PR_ExplodeTime( notAfter, PR_LocalTimeParameters, &explTime ) ;
+
+ dateTime.NanoSeconds = static_cast< sal_Int16 >( explTime.tm_usec * ::tools::Time::nanoPerMicro );
+ dateTime.Seconds = static_cast< sal_Int16 >( explTime.tm_sec );
+ dateTime.Minutes = static_cast< sal_Int16 >( explTime.tm_min );
+ dateTime.Hours = static_cast< sal_Int16 >( explTime.tm_hour );
+ dateTime.Day = static_cast< sal_Int16 >( explTime.tm_mday );
+ dateTime.Month = static_cast< sal_Int16 >( explTime.tm_month+1 );
+ dateTime.Year = static_cast< sal_Int16 >( explTime.tm_year );
+
+ return dateTime ;
+ } else {
+ return DateTime() ;
+ }
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getIssuerUniqueID() {
+ if( m_pCert != nullptr && m_pCert->issuerID.len > 0 ) {
+ return comphelper::arrayToSequence<sal_Int8>(m_pCert->issuerID.data, m_pCert->issuerID.len) ;
+ } else {
+ return css::uno::Sequence< sal_Int8 >();
+ }
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getSubjectUniqueID() {
+ if( m_pCert != nullptr && m_pCert->subjectID.len > 0 ) {
+ return comphelper::arrayToSequence<sal_Int8>(m_pCert->subjectID.data,
+ m_pCert->subjectID.len) ;
+ } else {
+ return css::uno::Sequence< sal_Int8 >();
+ }
+}
+
+css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL X509Certificate_NssImpl::getExtensions() {
+ if( m_pCert != nullptr && m_pCert->extensions != nullptr ) {
+ CERTCertExtension** extns ;
+ int len ;
+
+ for( len = 0, extns = m_pCert->extensions; *extns != nullptr; len ++, extns ++ ) ;
+ css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > xExtns( len ) ;
+ auto xExtnsRange = asNonConstRange(xExtns);
+
+ for( extns = m_pCert->extensions, len = 0; *extns != nullptr; extns ++, len ++ ) {
+ const SECItem id = (*extns)->id;
+ OString oidString(CERT_GetOidString(&id));
+
+ bool crit;
+ if( (*extns)->critical.data == nullptr )
+ crit = false ;
+ else
+ crit = (*extns)->critical.data[0] == 0xFF;
+
+ // remove "OID." prefix if existing
+ OString objID;
+ OString oid("OID.");
+ if (oidString.match(oid))
+ objID = oidString.copy(oid.getLength());
+ else
+ objID = oidString;
+
+ unsigned char* value = (*extns)->value.data;
+ unsigned int vlen = (*extns)->value.len;
+ unsigned char* objid = reinterpret_cast<unsigned char *>(const_cast<char *>(objID.getStr()));
+ unsigned int objidlen = objID.getLength();
+
+ if (objID == "2.5.29.17")
+ {
+ rtl::Reference<SanExtensionImpl> pExtn = new SanExtensionImpl;
+ pExtn->setCertExtn(value, vlen, objid, objidlen, crit);
+ xExtnsRange[len] = pExtn ;
+ }
+ else
+ {
+ rtl::Reference<CertificateExtension_XmlSecImpl> pExtn = new CertificateExtension_XmlSecImpl;
+ pExtn->setCertExtn(value, vlen, objid, objidlen, crit);
+ xExtnsRange[len] = pExtn;
+ }
+ }
+
+ return xExtns ;
+ } else {
+ return css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > ();
+ }
+}
+
+css::uno::Reference< css::security::XCertificateExtension > SAL_CALL X509Certificate_NssImpl::findCertificateExtension( const css::uno::Sequence< sal_Int8 >& oid ) {
+ if( m_pCert != nullptr && m_pCert->extensions != nullptr ) {
+ CERTCertExtension** extns ;
+ SECItem idItem ;
+
+ idItem.data = reinterpret_cast<unsigned char *>(const_cast<sal_Int8 *>(oid.getConstArray()));
+ idItem.len = oid.getLength() ;
+
+ css::uno::Reference<css::security::XCertificateExtension> xExtn;
+ for( extns = m_pCert->extensions; *extns != nullptr; extns ++ ) {
+ if( SECITEM_CompareItem( &idItem, &(*extns)->id ) == SECEqual ) {
+ const SECItem id = (*extns)->id;
+ OString objId(CERT_GetOidString(&id));
+
+ bool crit;
+ if( (*extns)->critical.data == nullptr )
+ crit = false ;
+ else
+ crit = (*extns)->critical.data[0] == 0xFF;
+
+ unsigned char* value = (*extns)->value.data;
+ unsigned int vlen = (*extns)->value.len;
+ unsigned char* objid = (*extns)->id.data;
+ unsigned int objidlen = (*extns)->id.len;
+
+ if ( objId == "OID.2.5.29.17" )
+ {
+ rtl::Reference<SanExtensionImpl> xSanImpl(
+ new SanExtensionImpl);
+ xSanImpl->setCertExtn(value, vlen, objid, objidlen, crit);
+ xExtn = xSanImpl.get();
+ }
+ else
+ {
+ rtl::Reference<CertificateExtension_XmlSecImpl> xSecImpl(
+ new CertificateExtension_XmlSecImpl);
+ xSecImpl->setCertExtn(value, vlen, objid, objidlen, crit);
+ xExtn = xSecImpl.get();
+ }
+ break;
+ }
+ }
+
+ return xExtn;
+ } else {
+ return nullptr ;
+ }
+}
+
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getEncoded() {
+ if( m_pCert != nullptr && m_pCert->derCert.len > 0 ) {
+ return comphelper::arrayToSequence<sal_Int8>(m_pCert->derCert.data, m_pCert->derCert.len) ;
+ } else {
+ return css::uno::Sequence< sal_Int8 >();
+ }
+}
+
+//Helper methods
+void X509Certificate_NssImpl::setCert( CERTCertificate* cert ) {
+ if( m_pCert != nullptr ) {
+ CERT_DestroyCertificate( m_pCert ) ;
+ m_pCert = nullptr ;
+ }
+
+ if( cert != nullptr ) {
+ m_pCert = CERT_DupCertificate( cert ) ;
+ }
+}
+
+const CERTCertificate* X509Certificate_NssImpl::getNssCert() const {
+ if( m_pCert != nullptr ) {
+ return m_pCert ;
+ } else {
+ return nullptr ;
+ }
+}
+
+void X509Certificate_NssImpl::setRawCert( const css::uno::Sequence< sal_Int8 >& rawCert ) {
+ CERTCertificate* cert ;
+ SECItem certItem ;
+
+ certItem.data = reinterpret_cast<unsigned char *>(const_cast<sal_Int8 *>(rawCert.getConstArray()));
+ certItem.len = rawCert.getLength() ;
+
+ cert = CERT_DecodeDERCertificate( &certItem, PR_TRUE, nullptr ) ;
+ if( cert == nullptr )
+ throw css::uno::RuntimeException() ;
+
+ if( m_pCert != nullptr ) {
+ CERT_DestroyCertificate( m_pCert ) ;
+ m_pCert = nullptr ;
+ }
+
+ m_pCert = cert ;
+}
+
+SECKEYPrivateKey* X509Certificate_NssImpl::getPrivateKey()
+{
+ if (m_pCert && m_pCert->slot)
+ {
+ SECKEYPrivateKey* pPrivateKey = PK11_FindPrivateKeyFromCert(m_pCert->slot, m_pCert, nullptr);
+ if (pPrivateKey)
+ return pPrivateKey;
+ pPrivateKey = PK11_FindKeyByDERCert(m_pCert->slot, m_pCert, nullptr);
+ if (pPrivateKey)
+ {
+ SAL_INFO("xmlsecurity.xmlsec", "fallback from PK11_FindPrivateKeyFromCert to PK11_FindKeyByDERCert needed");
+ return pPrivateKey;
+ }
+ SAL_WARN("xmlsecurity.xmlsec", "X509Certificate_NssImpl::getPrivateKey() cannot find private key");
+ }
+ return nullptr;
+}
+
+/* XUnoTunnel */
+sal_Int64 SAL_CALL X509Certificate_NssImpl::getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) {
+ return comphelper::getSomethingImpl(aIdentifier, this);
+}
+
+/* XUnoTunnel extension */
+
+const css::uno::Sequence< sal_Int8>& X509Certificate_NssImpl::getUnoTunnelId() {
+ static const comphelper::UnoIdInit theX509Certificate_NssImplUnoTunnelId;
+ return theX509Certificate_NssImplUnoTunnelId.getSeq();
+}
+
+static OUString getAlgorithmDescription(SECAlgorithmID const *aid)
+{
+ SECOidTag tag;
+ tag = SECOID_GetAlgorithmTag(aid);
+
+ const char *pDesc = SECOID_FindOIDTagDescription(tag);
+
+ return OUString::createFromAscii( pDesc ) ;
+}
+
+static css::uno::Sequence< sal_Int8 > getThumbprint(CERTCertificate const *pCert, SECOidTag id)
+{
+ if( pCert != nullptr )
+ {
+ SECStatus rv;
+ unsigned char fingerprint[32];
+ int length = 0;
+ switch (id)
+ {
+ case SEC_OID_MD5:
+ length = MD5_LENGTH;
+ break;
+ case SEC_OID_SHA1:
+ length = SHA1_LENGTH;
+ break;
+ case SEC_OID_SHA256:
+ length = SHA256_LENGTH;
+ break;
+ default:
+ break;
+ }
+
+ memset(fingerprint, 0, sizeof fingerprint);
+ rv = PK11_HashBuf(id, fingerprint, pCert->derCert.data, pCert->derCert.len);
+ if(rv == SECStatus::SECSuccess)
+ {
+ return comphelper::arrayToSequence<sal_Int8>(fingerprint, length);
+ }
+ }
+ return css::uno::Sequence< sal_Int8 >();
+}
+
+OUString SAL_CALL X509Certificate_NssImpl::getSubjectPublicKeyAlgorithm()
+{
+ if( m_pCert != nullptr )
+ {
+ return getAlgorithmDescription(&(m_pCert->subjectPublicKeyInfo.algorithm));
+ }
+ else
+ {
+ return OUString() ;
+ }
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getSubjectPublicKeyValue()
+{
+ if( m_pCert != nullptr )
+ {
+ SECItem spk = m_pCert->subjectPublicKeyInfo.subjectPublicKey;
+ DER_ConvertBitString(&spk);
+
+ if ( spk.len>0)
+ {
+ return comphelper::arrayToSequence<sal_Int8>(spk.data, spk.len) ;
+ }
+ }
+
+ return css::uno::Sequence< sal_Int8 >();
+}
+
+OUString SAL_CALL X509Certificate_NssImpl::getSignatureAlgorithm()
+{
+ if( m_pCert != nullptr )
+ {
+ return getAlgorithmDescription(&(m_pCert->signature));
+ }
+ else
+ {
+ return OUString() ;
+ }
+}
+
+svl::crypto::SignatureMethodAlgorithm X509Certificate_NssImpl::getSignatureMethodAlgorithm()
+{
+ svl::crypto::SignatureMethodAlgorithm nRet = svl::crypto::SignatureMethodAlgorithm::RSA;
+
+ if (!m_pCert)
+ return nRet;
+
+ SECOidTag eTag = SECOID_GetAlgorithmTag(&m_pCert->subjectPublicKeyInfo.algorithm);
+ if (eTag == SEC_OID_ANSIX962_EC_PUBLIC_KEY)
+ nRet = svl::crypto::SignatureMethodAlgorithm::ECDSA;
+
+ return nRet;
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getSHA1Thumbprint()
+{
+ return getThumbprint(m_pCert, SEC_OID_SHA1);
+}
+
+css::uno::Sequence<sal_Int8> X509Certificate_NssImpl::getSHA256Thumbprint()
+{
+ return getThumbprint(m_pCert, SEC_OID_SHA256);
+}
+
+css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getMD5Thumbprint()
+{
+ return getThumbprint(m_pCert, SEC_OID_MD5);
+}
+
+css::security::CertificateKind SAL_CALL X509Certificate_NssImpl::getCertificateKind()
+{
+ return css::security::CertificateKind_X509;
+}
+
+sal_Int32 SAL_CALL X509Certificate_NssImpl::getCertificateUsage( )
+{
+ SECStatus rv;
+ SECItem tmpitem;
+ sal_Int32 usage;
+
+ rv = CERT_FindKeyUsageExtension(m_pCert, &tmpitem);
+ if ( rv == SECStatus::SECSuccess )
+ {
+ usage = tmpitem.data[0];
+ PORT_Free(tmpitem.data);
+ tmpitem.data = nullptr;
+ }
+ else
+ {
+ usage = KU_ALL;
+ }
+
+ /*
+ * to make the nss implementation compatible with MSCrypto,
+ * the following usage is ignored
+ *
+ *
+ if ( CERT_GovtApprovedBitSet(m_pCert) )
+ {
+ usage |= KU_NS_GOVT_APPROVED;
+ }
+ */
+
+ return usage;
+}
+
+/* XServiceInfo */
+OUString SAL_CALL X509Certificate_NssImpl::getImplementationName()
+{
+ return "com.sun.star.xml.security.gpg.XCertificate_NssImpl";
+}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL X509Certificate_NssImpl::supportsService(const OUString& serviceName)
+{
+ return cppu::supportsService(this, serviceName);
+}
+
+/* XServiceInfo */
+css::uno::Sequence<OUString> SAL_CALL X509Certificate_NssImpl::getSupportedServiceNames() { return { OUString() }; }
+
+namespace xmlsecurity {
+
+// based on some guesswork and:
+// https://datatracker.ietf.org/doc/html/rfc1485
+// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certnametostra#CERT_X500_NAME_STR
+// the main problem appears to be that in values " is escaped as "" vs. \"
+static OUString CompatDNCryptoAPI(OUString const& rDN)
+{
+ OUStringBuffer buf(rDN.getLength());
+ enum { DEFAULT, INVALUE, INQUOTE } state(DEFAULT);
+ for (sal_Int32 i = 0; i < rDN.getLength(); ++i)
+ {
+ if (state == DEFAULT)
+ {
+ buf.append(rDN[i]);
+ if (rDN[i] == '=')
+ {
+ if (rDN.getLength() == i+1)
+ {
+ break; // invalid?
+ }
+ else if (rDN[i+1] == '"')
+ {
+ buf.append(rDN[i+1]);
+ ++i;
+ state = INQUOTE;
+ }
+ else
+ {
+ state = INVALUE;
+ }
+ }
+ }
+ else if (state == INVALUE)
+ {
+ if (rDN[i] == '+' || rDN[i] == ',' || rDN[i] == ';')
+ {
+ state = DEFAULT;
+ }
+ buf.append(rDN[i]);
+ }
+ else
+ {
+ assert(state == INQUOTE);
+ if (rDN[i] == '"')
+ {
+ if (rDN.getLength() != i+1 && rDN[i+1] == '"')
+ {
+ buf.append('\\');
+ buf.append(rDN[i+1]);
+ ++i;
+ }
+ else
+ {
+ buf.append(rDN[i]);
+ state = DEFAULT;
+ }
+ }
+ else
+ {
+ buf.append(rDN[i]);
+ }
+ }
+ }
+ return buf.makeStringAndClear();
+}
+
+bool EqualDistinguishedNames(
+ std::u16string_view const rName1, std::u16string_view const rName2,
+ EqualMode const eMode)
+{
+ if (eMode == COMPAT_BOTH && !rName1.empty() && rName1 == rName2)
+ { // handle case where both need to be converted
+ return true;
+ }
+ CERTName *const pName1(CERT_AsciiToName(OUStringToOString(rName1, RTL_TEXTENCODING_UTF8).getStr()));
+ if (pName1 == nullptr)
+ {
+ return false;
+ }
+ CERTName *const pName2(CERT_AsciiToName(OUStringToOString(rName2, RTL_TEXTENCODING_UTF8).getStr()));
+ bool ret(false);
+ if (pName2)
+ {
+ ret = (CERT_CompareName(pName1, pName2) == SECEqual);
+ CERT_DestroyName(pName2);
+ }
+ if (!ret && eMode == COMPAT_2ND)
+ {
+ CERTName *const pName2Compat(CERT_AsciiToName(OUStringToOString(
+ CompatDNCryptoAPI(OUString(rName2)), RTL_TEXTENCODING_UTF8).getStr()));
+ if (pName2Compat == nullptr)
+ {
+ CERT_DestroyName(pName1);
+ return false;
+ }
+ ret = CERT_CompareName(pName1, pName2Compat) == SECEqual;
+ CERT_DestroyName(pName2Compat);
+ }
+ CERT_DestroyName(pName1);
+ return ret;
+}
+
+} // namespace xmlsecurity
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx
new file mode 100644
index 000000000..dbfb6c6b0
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+#include <rtl/ustring.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/security/CertificateKind.hpp>
+#include <com/sun/star/security/XCertificate.hpp>
+
+#include <certificate.hxx>
+#include <certt.h>
+#include <keythi.h>
+
+class X509Certificate_NssImpl : public ::cppu::WeakImplHelper<
+ css::security::XCertificate ,
+ css::lang::XUnoTunnel,
+ css::lang::XServiceInfo > , public xmlsecurity::Certificate
+{
+ private:
+ CERTCertificate* m_pCert;
+
+ public:
+ X509Certificate_NssImpl() ;
+ virtual ~X509Certificate_NssImpl() override ;
+
+ //Methods from XCertificate
+ virtual sal_Int16 SAL_CALL getVersion( ) override ;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSerialNumber( ) override ;
+
+ virtual OUString SAL_CALL getIssuerName( ) override ;
+ virtual OUString SAL_CALL getSubjectName( ) override ;
+
+ virtual css::util::DateTime SAL_CALL getNotValidBefore( ) override ;
+ virtual css::util::DateTime SAL_CALL getNotValidAfter( ) override ;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getIssuerUniqueID( ) override ;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectUniqueID( ) override ;
+
+ virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL getExtensions( ) override ;
+
+ virtual css::uno::Reference< css::security::XCertificateExtension > SAL_CALL findCertificateExtension( const css::uno::Sequence< sal_Int8 >& oid ) override ;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getEncoded( ) override ;
+
+ virtual OUString SAL_CALL getSubjectPublicKeyAlgorithm() override ;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectPublicKeyValue() override ;
+
+ virtual OUString SAL_CALL getSignatureAlgorithm() override ;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSHA1Thumbprint() override ;
+
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getMD5Thumbprint() override ;
+ virtual css::security::CertificateKind SAL_CALL getCertificateKind() override;
+
+ virtual sal_Int32 SAL_CALL getCertificateUsage( ) override ;
+
+ //Methods from XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override;
+
+ /// @see xmlsecurity::Certificate::getSHA256Thumbprint().
+ virtual css::uno::Sequence<sal_Int8> getSHA256Thumbprint() override;
+
+ /// @see xmlsecurity::Certificate::getSignatureMethodAlgorithm().
+ virtual svl::crypto::SignatureMethodAlgorithm getSignatureMethodAlgorithm() override;
+
+ static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId() ;
+
+ //Helper methods
+ void setCert( CERTCertificate* cert ) ;
+ const CERTCertificate* getNssCert() const ;
+
+ /// @throws css::uno::RuntimeException
+ void setRawCert( const css::uno::Sequence< sal_Int8 >& rawCert ) ;
+ SECKEYPrivateKey* getPrivateKey();
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+} ;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx
new file mode 100644
index 000000000..9ccf0ab98
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+#include <vector>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp>
+#include <o3tl/safeint.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang ;
+
+using ::com::sun::star::xml::crypto::XSecurityEnvironment ;
+using ::com::sun::star::xml::crypto::XXMLSecurityContext ;
+
+namespace {
+
+class XMLSecurityContext_NssImpl
+ : public ::cppu::WeakImplHelper<xml::crypto::XXMLSecurityContext, lang::XServiceInfo>
+{
+private:
+ std::vector<uno::Reference<xml::crypto::XSecurityEnvironment>> m_vSecurityEnvironments;
+
+ sal_Int32 m_nDefaultEnvIndex;
+
+public:
+ XMLSecurityContext_NssImpl();
+
+ //XXMLSecurityContext
+ virtual sal_Int32 SAL_CALL addSecurityEnvironment(
+ const uno::Reference<xml::crypto::XSecurityEnvironment>& aSecurityEnvironment) override;
+
+ virtual ::sal_Int32 SAL_CALL getSecurityEnvironmentNumber() override;
+
+ virtual uno::Reference<xml::crypto::XSecurityEnvironment>
+ SAL_CALL getSecurityEnvironmentByIndex(::sal_Int32 index) override;
+
+ virtual uno::Reference<xml::crypto::XSecurityEnvironment>
+ SAL_CALL getSecurityEnvironment() override;
+
+ virtual ::sal_Int32 SAL_CALL getDefaultSecurityEnvironmentIndex() override;
+
+ virtual void SAL_CALL setDefaultSecurityEnvironmentIndex(sal_Int32 nDefaultEnvIndex) override;
+
+ //XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+
+ virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+}
+
+XMLSecurityContext_NssImpl::XMLSecurityContext_NssImpl()
+ : m_nDefaultEnvIndex(-1)
+{
+}
+
+sal_Int32 SAL_CALL XMLSecurityContext_NssImpl::addSecurityEnvironment(
+ const uno::Reference< xml::crypto::XSecurityEnvironment >& aSecurityEnvironment)
+{
+ if( !aSecurityEnvironment.is() )
+ {
+ throw uno::RuntimeException() ;
+ }
+
+ m_vSecurityEnvironments.push_back( aSecurityEnvironment );
+
+ return m_vSecurityEnvironments.size() - 1 ;
+}
+
+
+sal_Int32 SAL_CALL XMLSecurityContext_NssImpl::getSecurityEnvironmentNumber( )
+{
+ return m_vSecurityEnvironments.size();
+}
+
+uno::Reference< xml::crypto::XSecurityEnvironment > SAL_CALL
+ XMLSecurityContext_NssImpl::getSecurityEnvironmentByIndex( sal_Int32 index )
+{
+ if (index < 0 || o3tl::make_unsigned(index) >= m_vSecurityEnvironments.size())
+ throw uno::RuntimeException();
+
+ uno::Reference< xml::crypto::XSecurityEnvironment > xSecurityEnvironment = m_vSecurityEnvironments[index];
+ return xSecurityEnvironment;
+}
+
+uno::Reference< xml::crypto::XSecurityEnvironment > SAL_CALL
+ XMLSecurityContext_NssImpl::getSecurityEnvironment( )
+{
+ if (m_nDefaultEnvIndex < 0 || o3tl::make_unsigned(m_nDefaultEnvIndex) >= m_vSecurityEnvironments.size())
+ throw uno::RuntimeException();
+
+ return getSecurityEnvironmentByIndex(m_nDefaultEnvIndex);
+}
+
+sal_Int32 SAL_CALL XMLSecurityContext_NssImpl::getDefaultSecurityEnvironmentIndex( )
+{
+ return m_nDefaultEnvIndex ;
+}
+
+void SAL_CALL XMLSecurityContext_NssImpl::setDefaultSecurityEnvironmentIndex( sal_Int32 nDefaultEnvIndex )
+{
+ m_nDefaultEnvIndex = nDefaultEnvIndex;
+}
+
+/* XServiceInfo */
+OUString SAL_CALL XMLSecurityContext_NssImpl::getImplementationName() {
+ return "com.sun.star.xml.crypto.XMLSecurityContext";
+}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL XMLSecurityContext_NssImpl::supportsService( const OUString& serviceName) {
+ return cppu::supportsService(this, serviceName);
+}
+
+/* XServiceInfo */
+uno::Sequence< OUString > SAL_CALL XMLSecurityContext_NssImpl::getSupportedServiceNames() {
+ return { "com.sun.star.xml.crypto.XMLSecurityContext" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_xml_crypto_XMLSecurityContext_get_implementation(
+ uno::XComponentContext* /*pCtx*/, uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new XMLSecurityContext_NssImpl);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx
new file mode 100644
index 000000000..94e84a71b
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx
@@ -0,0 +1,325 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+#include <xmlsec-wrapper.h>
+
+#include <xmlsec/nss/x509.h>
+
+#include <xmlelementwrapper_xmlsecimpl.hxx>
+#include <xmlsec/xmlstreamio.hxx>
+#include <xmlsec/errorcallback.hxx>
+
+#include "securityenvironment_nssimpl.hxx"
+
+#include <comphelper/servicehelper.hxx>
+#include <sal/log.hxx>
+
+#include <com/sun/star/xml/crypto/XXMLSignature.hpp>
+#include <memory>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno ;
+using namespace ::com::sun::star::lang ;
+
+using ::com::sun::star::xml::wrapper::XXMLElementWrapper ;
+using ::com::sun::star::xml::crypto::XSecurityEnvironment ;
+using ::com::sun::star::xml::crypto::XXMLSignature ;
+using ::com::sun::star::xml::crypto::XXMLSignatureTemplate ;
+using ::com::sun::star::xml::crypto::XXMLSecurityContext ;
+using ::com::sun::star::xml::crypto::XUriBinding ;
+
+namespace std
+{
+template <> struct default_delete<xmlSecKeysMngr>
+{
+ void operator()(xmlSecKeysMngrPtr ptr) { SecurityEnvironment_NssImpl::destroyKeysManager(ptr); }
+};
+template <> struct default_delete<xmlSecDSigCtx>
+{
+ void operator()(xmlSecDSigCtxPtr ptr) { xmlSecDSigCtxDestroy(ptr); }
+};
+}
+
+namespace {
+
+class XMLSignature_NssImpl
+ : public ::cppu::WeakImplHelper<xml::crypto::XXMLSignature, lang::XServiceInfo>
+{
+public:
+ explicit XMLSignature_NssImpl();
+
+ //Methods from XXMLSignature
+ virtual uno::Reference<xml::crypto::XXMLSignatureTemplate> SAL_CALL
+ generate(const uno::Reference<xml::crypto::XXMLSignatureTemplate>& aTemplate,
+ const uno::Reference<xml::crypto::XSecurityEnvironment>& aEnvironment) override;
+
+ virtual uno::Reference<xml::crypto::XXMLSignatureTemplate> SAL_CALL
+ validate(const uno::Reference<xml::crypto::XXMLSignatureTemplate>& aTemplate,
+ const uno::Reference<xml::crypto::XXMLSecurityContext>& aContext) override;
+
+ //Methods from XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+
+ virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+}
+
+XMLSignature_NssImpl::XMLSignature_NssImpl() {
+}
+
+/* XXMLSignature */
+Reference< XXMLSignatureTemplate >
+SAL_CALL XMLSignature_NssImpl::generate(
+ const Reference< XXMLSignatureTemplate >& aTemplate ,
+ const Reference< XSecurityEnvironment >& aEnvironment
+)
+{
+ xmlNodePtr pNode = nullptr ;
+
+ if( !aTemplate.is() )
+ throw RuntimeException() ;
+
+ if( !aEnvironment.is() )
+ throw RuntimeException() ;
+
+ //Get the xml node
+ Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
+ if( !xElement.is() ) {
+ throw RuntimeException() ;
+ }
+
+ Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ;
+ XMLElementWrapper_XmlSecImpl* pElement
+ = comphelper::getFromUnoTunnel<XMLElementWrapper_XmlSecImpl>(xNodTunnel);
+ if( pElement == nullptr ) {
+ throw RuntimeException() ;
+ }
+
+ pNode = pElement->getNativeElement() ;
+
+ //Get the stream/URI binding
+ Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ;
+ if( xUriBinding.is() ) {
+ //Register the stream input callbacks into libxml2
+ if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 )
+ throw RuntimeException() ;
+ }
+
+ //Get Keys Manager
+ Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY_THROW ) ;
+
+ // the key manager should be retrieved from SecurityEnvironment, instead of SecurityContext
+ SecurityEnvironment_NssImpl* pSecEnv
+ = comphelper::getFromUnoTunnel<SecurityEnvironment_NssImpl>(xSecTunnel);
+ if( pSecEnv == nullptr )
+ throw RuntimeException() ;
+
+ setErrorRecorder();
+
+ std::unique_ptr<xmlSecKeysMngr> pMngr(pSecEnv->createKeysManager());
+ if( !pMngr ) {
+ throw RuntimeException() ;
+ }
+
+ //Create Signature context
+ std::unique_ptr<xmlSecDSigCtx> pDsigCtx(xmlSecDSigCtxCreate(pMngr.get()));
+ if( pDsigCtx == nullptr )
+ {
+ //throw XMLSignatureException() ;
+ clearErrorRecorder();
+ return aTemplate;
+ }
+
+ //Sign the template
+ if( xmlSecDSigCtxSign( pDsigCtx.get() , pNode ) == 0 )
+ {
+ if (pDsigCtx->status == xmlSecDSigStatusSucceeded)
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
+ else
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
+ }
+ else
+ {
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
+ }
+
+ //Unregistered the stream/URI binding
+ if( xUriBinding.is() )
+ xmlUnregisterStreamInputCallbacks() ;
+
+ clearErrorRecorder();
+ return aTemplate ;
+}
+
+/* XXMLSignature */
+Reference< XXMLSignatureTemplate >
+SAL_CALL XMLSignature_NssImpl::validate(
+ const Reference< XXMLSignatureTemplate >& aTemplate ,
+ const Reference< XXMLSecurityContext >& aSecurityCtx
+) {
+ xmlNodePtr pNode = nullptr ;
+ //sal_Bool valid ;
+
+ if( !aTemplate.is() )
+ throw RuntimeException() ;
+
+ if( !aSecurityCtx.is() )
+ throw RuntimeException() ;
+
+ //Get the xml node
+ Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ;
+ if( !xElement.is() )
+ throw RuntimeException() ;
+
+ Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ;
+ XMLElementWrapper_XmlSecImpl* pElement
+ = comphelper::getFromUnoTunnel<XMLElementWrapper_XmlSecImpl>(xNodTunnel);
+ if( pElement == nullptr )
+ throw RuntimeException() ;
+
+ pNode = pElement->getNativeElement() ;
+
+ //Get the stream/URI binding
+ Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ;
+ if( xUriBinding.is() ) {
+ //Register the stream input callbacks into libxml2
+ if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 )
+ throw RuntimeException() ;
+ }
+
+ setErrorRecorder();
+
+ sal_Int32 nSecurityEnvironment = aSecurityCtx->getSecurityEnvironmentNumber();
+ sal_Int32 i;
+
+ for (i=0; i<nSecurityEnvironment; ++i)
+ {
+ Reference< XSecurityEnvironment > aEnvironment = aSecurityCtx->getSecurityEnvironmentByIndex(i);
+
+ //Get Keys Manager
+ Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY_THROW ) ;
+ SecurityEnvironment_NssImpl* pSecEnv
+ = comphelper::getFromUnoTunnel<SecurityEnvironment_NssImpl>(xSecTunnel);
+ if( pSecEnv == nullptr )
+ throw RuntimeException() ;
+
+ std::unique_ptr<xmlSecKeysMngr> pMngr(pSecEnv->createKeysManager());
+ if( !pMngr ) {
+ throw RuntimeException() ;
+ }
+
+ //Create Signature context
+ std::unique_ptr<xmlSecDSigCtx> pDsigCtx(xmlSecDSigCtxCreate(pMngr.get()));
+ if( pDsigCtx == nullptr )
+ {
+ clearErrorRecorder();
+ return aTemplate;
+ }
+
+ // We do certificate verification ourselves.
+ pDsigCtx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
+
+ // limit possible key data to valid X509 certificates only, no KeyValues
+ if (xmlSecPtrListAdd(&(pDsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecNssKeyDataX509GetKlass()) < 0)
+ throw RuntimeException("failed to limit allowed key data");
+
+ xmlBufferPtr pBuf = xmlBufferCreate();
+ xmlNodeDump(pBuf, nullptr, pNode, 0, 0);
+ SAL_INFO("xmlsecurity.xmlsec", "xmlSecDSigCtxVerify input XML node is '"
+ << reinterpret_cast<const char*>(xmlBufferContent(pBuf))
+ << "'");
+ xmlBufferFree(pBuf);
+
+ //Verify signature
+ int rs = xmlSecDSigCtxVerify( pDsigCtx.get() , pNode );
+
+ // Also verify manifest: this is empty for ODF, but contains everything (except signature metadata) for OOXML.
+ xmlSecSize nReferenceCount = xmlSecPtrListGetSize(&pDsigCtx->manifestReferences);
+ // Require that all manifest references are also good.
+ xmlSecSize nReferenceGood = 0;
+ for (xmlSecSize nReference = 0; nReference < nReferenceCount; ++nReference)
+ {
+ xmlSecDSigReferenceCtxPtr pReference = static_cast<xmlSecDSigReferenceCtxPtr>(xmlSecPtrListGetItem(&pDsigCtx->manifestReferences, nReference));
+ if (pReference)
+ {
+ if (pReference->status == xmlSecDSigStatusSucceeded)
+ ++nReferenceGood;
+ }
+ }
+ SAL_INFO("xmlsecurity.xmlsec", "xmlSecDSigCtxVerify status " << pDsigCtx->status << ", references good " << nReferenceGood << " of " << nReferenceCount);
+
+ if (rs == 0 && pDsigCtx->status == xmlSecDSigStatusSucceeded && nReferenceCount == nReferenceGood)
+ {
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED);
+ break;
+ }
+ else
+ {
+ aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN);
+ }
+ }
+
+
+ //Unregistered the stream/URI binding
+ if( xUriBinding.is() )
+ xmlUnregisterStreamInputCallbacks() ;
+
+ //return valid ;
+ clearErrorRecorder();
+ return aTemplate;
+}
+
+/* XServiceInfo */
+OUString SAL_CALL XMLSignature_NssImpl::getImplementationName()
+{
+ return "com.sun.star.xml.crypto.XMLSignature";
+}
+
+/* XServiceInfo */
+sal_Bool SAL_CALL XMLSignature_NssImpl::supportsService(const OUString& rServiceName)
+{
+ const css::uno::Sequence<OUString> aServiceNames = getSupportedServiceNames();
+ for (OUString const & rCurrentServiceName : aServiceNames)
+ {
+ if (rCurrentServiceName == rServiceName)
+ return true;
+ }
+ return false;
+}
+
+/* XServiceInfo */
+Sequence<OUString> SAL_CALL XMLSignature_NssImpl::getSupportedServiceNames()
+{
+ return { "com.sun.star.xml.crypto.XMLSignature" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_xml_crypto_XMLSignature_get_implementation(uno::XComponentContext* /*pCtx*/,
+ uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new XMLSignature_NssImpl);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/saxhelper.cxx b/xmlsecurity/source/xmlsec/saxhelper.cxx
new file mode 100644
index 000000000..ff576db49
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/saxhelper.cxx
@@ -0,0 +1,364 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <rtl/ustring.hxx>
+
+#include <xmlsec/saxhelper.hxx>
+#include <libxml/parserInternals.h>
+
+#include <com/sun/star/xml/csax/XMLAttribute.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+
+#ifndef XMLSEC_NO_XSLT
+#include "libxslt/xslt.h"
+#endif
+
+/**
+ * The return value is NULL terminated. The application has the responsibility to
+ * deallocate the return value.
+ */
+static xmlChar* ous_to_xmlstr( std::u16string_view oustr )
+{
+ OString ostr = OUStringToOString( oustr , RTL_TEXTENCODING_UTF8 ) ;
+ return xmlStrndup( reinterpret_cast<xmlChar const *>(ostr.getStr()), static_cast<int>(ostr.getLength()) ) ;
+}
+
+/**
+ * The return value is NULL terminated. The application has the responsibility to
+ * deallocate the return value.
+ */
+static xmlChar* ous_to_nxmlstr( std::u16string_view oustr, int& length )
+{
+ OString ostr = OUStringToOString( oustr , RTL_TEXTENCODING_UTF8 ) ;
+ length = ostr.getLength();
+
+ return xmlStrndup( reinterpret_cast<xmlChar const *>(ostr.getStr()), length ) ;
+}
+
+/**
+ * The return value and the referenced value must be NULL terminated.
+ * The application has the responsibility to deallocate the return value.
+ */
+static const xmlChar** attrlist_to_nxmlstr( const css::uno::Sequence< css::xml::csax::XMLAttribute >& aAttributes )
+{
+ xmlChar* attname = nullptr ;
+ xmlChar* attvalue = nullptr ;
+ const xmlChar** attrs = nullptr ;
+
+ sal_Int32 nLength = aAttributes.getLength();
+
+ if( nLength != 0 )
+ {
+ attrs = static_cast<const xmlChar**>(xmlMalloc( ( nLength * 2 + 2 ) * sizeof( xmlChar* ) ));
+ }
+ else
+ {
+ return nullptr ;
+ }
+
+ int i = 0;
+ for( const auto& rAttr : aAttributes )
+ {
+ attname = ous_to_xmlstr( rAttr.sName ) ;
+ attvalue = ous_to_xmlstr( rAttr.sValue ) ;
+
+ if( attname != nullptr && attvalue != nullptr )
+ {
+ attrs[i++] = attname ;
+ attrs[i++] = attvalue ;
+ attrs[i] = nullptr ;
+ attrs[i+1] = nullptr ;
+ }
+ else
+ {
+ if( attname != nullptr )
+ xmlFree( attname ) ;
+ if( attvalue != nullptr )
+ xmlFree( attvalue ) ;
+ }
+ }
+
+ return attrs ;
+}
+
+/**
+ * Constructor
+ *
+ * In this constructor, a libxml sax parser context is initialized. a libxml
+ * default sax handler is initialized with the context.
+ */
+SAXHelper::SAXHelper( )
+ : m_pParserCtxt( nullptr ),
+ m_pSaxHandler( nullptr )
+{
+ xmlInitParser() ;
+ LIBXML_TEST_VERSION ;
+
+ /*
+ * compile error:
+ * xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS ;
+ */
+ xmlSubstituteEntitiesDefault(0) ;
+
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1 ;
+#endif /* XMLSEC_NO_XSLT */
+
+ m_pParserCtxt = xmlNewParserCtxt() ;
+
+ if( m_pParserCtxt == nullptr )
+ {
+// see issue i74334, we cannot call xmlCleanupParser when libxml is still used
+// in other parts of the office.
+// xmlCleanupParser() ;
+// and neither can we call xsltCleanupGlobals()
+ throw css::uno::RuntimeException() ;
+ }
+
+ xmlSAXVersion(m_pParserCtxt->sax, 1);
+
+ if (m_pParserCtxt->inputTab != nullptr)
+ {
+ m_pParserCtxt->inputTab[0] = nullptr ;
+ }
+
+ if( m_pParserCtxt->sax == nullptr )
+ {
+ xmlFreeParserCtxt( m_pParserCtxt ) ;
+
+// see issue i74334, we cannot call xmlCleanupParser when libxml is still used
+// in other parts of the office.
+// xmlCleanupParser() ;
+// and neither can we call xsltCleanupGlobals()
+ m_pParserCtxt = nullptr ;
+ throw css::uno::RuntimeException() ;
+ }
+ else
+ {
+ m_pSaxHandler = m_pParserCtxt->sax ;
+
+ //Adjust the context
+ m_pParserCtxt->recovery = 1 ;
+ }
+}
+
+/**
+ * Destructor
+ *
+ * In this destructor, a libxml sax parser context is destructed. The XML tree
+ * in the context is not deallocated because the tree is bind with a document
+ * model by the setTargetDocument method, which delegate the target document to
+ * destruct the xml tree.
+ */
+SAXHelper::~SAXHelper() {
+ if( m_pParserCtxt != nullptr )
+ {
+ /*
+ * In the situation that no object refer the Document, this destructor
+ * must deallocate the Document memory
+ */
+ if( m_pSaxHandler == m_pParserCtxt->sax )
+ {
+ m_pSaxHandler = nullptr ;
+ }
+
+ xmlFreeParserCtxt( m_pParserCtxt ) ;
+ m_pParserCtxt = nullptr ;
+ }
+
+ if( m_pSaxHandler != nullptr )
+ {
+ xmlFree( m_pSaxHandler ) ;
+ m_pSaxHandler = nullptr ;
+ }
+// see issue i74334, we cannot call xmlCleanupParser when libxml is still used
+// in other parts of the office.
+// xmlCleanupParser() ;
+}
+
+
+void SAXHelper::setCurrentNode(const xmlNodePtr pNode)
+{
+ /*
+ * This is really a black trick.
+ * When the current node is replaced, the nodeTab
+ * stack's top has to been replaced with the same
+ * node, in order to make compatibility.
+ */
+ m_pParserCtxt->nodeTab[m_pParserCtxt->nodeNr - 1]
+ = m_pParserCtxt->node
+ = pNode;
+}
+
+
+/**
+ * XDocumentHandler -- start an xml document
+ */
+void SAXHelper::startDocument()
+{
+ if( m_pParserCtxt == nullptr)
+ {
+ throw css::uno::RuntimeException() ;
+ }
+ /*
+ * Adjust inputTab
+ */
+ xmlParserInputPtr pInput = xmlNewInputStream( m_pParserCtxt ) ;
+
+ if( m_pParserCtxt->inputTab != nullptr && m_pParserCtxt->inputMax != 0 )
+ {
+ m_pParserCtxt->inputTab[0] = pInput ;
+ m_pParserCtxt->input = pInput ;
+ }
+
+ m_pSaxHandler->startDocument( m_pParserCtxt ) ;
+
+ if( m_pParserCtxt->myDoc == nullptr )
+ {
+ throw css::uno::RuntimeException() ;
+ }
+}
+
+/**
+ * XDocumentHandler -- end an xml document
+ */
+void SAXHelper::endDocument()
+{
+ m_pSaxHandler->endDocument( m_pParserCtxt ) ;
+}
+
+/**
+ * XDocumentHandler -- start an xml element
+ */
+void SAXHelper::startElement(
+ std::u16string_view aName,
+ const css::uno::Sequence< css::xml::csax::XMLAttribute >& aAttributes )
+{
+ const xmlChar* fullName = nullptr ;
+ const xmlChar** attrs = nullptr ;
+
+ fullName = ous_to_xmlstr( aName ) ;
+ attrs = attrlist_to_nxmlstr( aAttributes ) ;
+
+ if( fullName != nullptr || attrs != nullptr )
+ {
+ m_pSaxHandler->startElement( m_pParserCtxt , fullName , attrs ) ;
+ }
+
+ if( fullName != nullptr )
+ {
+ xmlFree( const_cast<xmlChar*>(fullName) ) ;
+ fullName = nullptr ;
+ }
+
+ if( attrs != nullptr )
+ {
+ for( int i = 0 ; attrs[i] != nullptr ; ++i )
+ {
+ xmlFree( const_cast<xmlChar*>(attrs[i]) ) ;
+ attrs[i] = nullptr ;
+ }
+
+ xmlFree( static_cast<void*>(attrs) ) ;
+ attrs = nullptr ;
+ }
+}
+
+/**
+ * XDocumentHandler -- end an xml element
+ */
+void SAXHelper::endElement( std::u16string_view aName )
+{
+ xmlChar* fullname = ous_to_xmlstr( aName ) ;
+ m_pSaxHandler->endElement( m_pParserCtxt , fullname ) ;
+
+ if( fullname != nullptr )
+ {
+ xmlFree( fullname ) ;
+ fullname = nullptr ;
+ }
+}
+
+/**
+ * XDocumentHandler -- an xml element or cdata characters
+ */
+void SAXHelper::characters( std::u16string_view aChars )
+{
+ const xmlChar* chars = nullptr ;
+ int length = 0 ;
+
+ chars = ous_to_nxmlstr( aChars, length ) ;
+ m_pSaxHandler->characters( m_pParserCtxt , chars , length ) ;
+
+ if( chars != nullptr )
+ {
+ xmlFree( const_cast<xmlChar*>(chars) ) ;
+ }
+}
+
+/**
+ * XDocumentHandler -- ignorable xml white space
+ */
+void SAXHelper::ignorableWhitespace( std::u16string_view aWhitespaces )
+{
+ const xmlChar* chars = nullptr ;
+ int length = 0 ;
+
+ chars = ous_to_nxmlstr( aWhitespaces, length ) ;
+ m_pSaxHandler->ignorableWhitespace( m_pParserCtxt , chars , length ) ;
+
+ if( chars != nullptr )
+ {
+ xmlFree( const_cast<xmlChar*>(chars) ) ;
+ }
+}
+
+/**
+ * XDocumentHandler -- preprocessing instruction
+ */
+void SAXHelper::processingInstruction(
+ std::u16string_view aTarget,
+ std::u16string_view aData )
+{
+ xmlChar* target = nullptr ;
+ xmlChar* data = nullptr ;
+
+ target = ous_to_xmlstr( aTarget ) ;
+ data = ous_to_xmlstr( aData ) ;
+
+ m_pSaxHandler->processingInstruction( m_pParserCtxt , target , data ) ;
+
+ if( target != nullptr )
+ {
+ xmlFree( target ) ;
+ target = nullptr ;
+ }
+
+ if( data != nullptr )
+ {
+ xmlFree( data ) ;
+ data = nullptr ;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.cxx b/xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.cxx
new file mode 100644
index 000000000..1694e30c8
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.cxx
@@ -0,0 +1,902 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+
+#include <osl/diagnose.h>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/xml/crypto/sax/XSAXEventKeeper.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <xmlsec/xmldocumentwrapper_xmlsecimpl.hxx>
+#include "xmlelementwrapper_xmlsecimpl.hxx"
+
+#include <xmloff/attrlist.hxx>
+#include <rtl/ref.hxx>
+
+#ifdef UNX
+#define stricmp strcasecmp
+#endif
+
+using namespace com::sun::star;
+
+#define STRXMLNS "xmlns"
+
+/* used by the recursiveDelete method */
+#define NODE_REMOVED 0
+#define NODE_NOTREMOVED 1
+#define NODE_STOPPED 2
+
+XMLDocumentWrapper_XmlSecImpl::XMLDocumentWrapper_XmlSecImpl()
+ : m_nCurrentPosition(0)
+ , m_pStopAtNode(nullptr)
+ , m_pCurrentReservedNode(nullptr)
+ , m_nReservedNodeIndex(0)
+{
+ saxHelper.startDocument();
+ m_pDocument = saxHelper.getDocument();
+
+ /*
+ * creates the virtual root element
+ */
+ saxHelper.startElement(u"root", uno::Sequence<css::xml::csax::XMLAttribute>());
+
+ m_pRootElement = saxHelper.getCurrentNode();
+ m_pCurrentElement = m_pRootElement;
+}
+
+XMLDocumentWrapper_XmlSecImpl::~XMLDocumentWrapper_XmlSecImpl()
+{
+ saxHelper.endDocument();
+ xmlFreeDoc(m_pDocument);
+}
+
+void XMLDocumentWrapper_XmlSecImpl::getNextSAXEvent()
+/****** XMLDocumentWrapper_XmlSecImpl/getNextSAXEvent *************************
+ *
+ * NAME
+ * getNextSAXEvent -- Prepares the next SAX event to be manipulate
+ *
+ * FUNCTION
+ * When converting the document into SAX events, this method is used to
+ * decide the next SAX event to be generated.
+ * Two member variables are checked to make the decision, the
+ * m_pCurrentElement and the m_nCurrentPosition.
+ * The m_pCurrentElement represents the node which have been covered, and
+ * the m_nCurrentPosition represents the event which have been sent.
+ * For example, suppose that the m_pCurrentElement
+ * points to element A, and the m_nCurrentPosition equals to
+ * NODEPOSITION_STARTELEMENT, then the next SAX event should be the
+ * endElement for element A if A has no child, or startElement for the
+ * first child element of element A otherwise.
+ * The m_nCurrentPosition can be one of following values:
+ * NODEPOSITION_STARTELEMENT for startElement;
+ * NODEPOSITION_ENDELEMENT for endElement;
+ * NODEPOSITION_NORMAL for other SAX events;
+ ******************************************************************************/
+{
+ OSL_ASSERT( m_pCurrentElement != nullptr );
+
+ /*
+ * Get the next event through tree order.
+ *
+ * if the current event is a startElement, then the next
+ * event depends on whether or not the current node has
+ * children.
+ */
+ if (m_nCurrentPosition == NODEPOSITION_STARTELEMENT)
+ {
+ /*
+ * If the current node has children, then its first child
+ * should be next current node, and the next event will be
+ * startElement or characters(PI) based on that child's node
+ * type. Otherwise, the endElement of current node is the
+ * next event.
+ */
+ if (m_pCurrentElement->children != nullptr)
+ {
+ m_pCurrentElement = m_pCurrentElement->children;
+ m_nCurrentPosition
+ = (m_pCurrentElement->type == XML_ELEMENT_NODE)?
+ NODEPOSITION_STARTELEMENT:NODEPOSITION_NORMAL;
+ }
+ else
+ {
+ m_nCurrentPosition = NODEPOSITION_ENDELEMENT;
+ }
+ }
+ /*
+ * if the current event is a not startElement, then the next
+ * event depends on whether or not the current node has
+ * following sibling.
+ */
+ else if (m_nCurrentPosition == NODEPOSITION_ENDELEMENT || m_nCurrentPosition == NODEPOSITION_NORMAL)
+ {
+ xmlNodePtr pNextSibling = m_pCurrentElement->next;
+
+ /*
+ * If the current node has following sibling, that sibling
+ * should be next current node, and the next event will be
+ * startElement or characters(PI) based on that sibling's node
+ * type. Otherwise, the endElement of current node's parent
+ * becomes the next event.
+ */
+ if (pNextSibling != nullptr)
+ {
+ m_pCurrentElement = pNextSibling;
+ m_nCurrentPosition
+ = (m_pCurrentElement->type == XML_ELEMENT_NODE)?
+ NODEPOSITION_STARTELEMENT:NODEPOSITION_NORMAL;
+ }
+ else
+ {
+ m_pCurrentElement = m_pCurrentElement->parent;
+ m_nCurrentPosition = NODEPOSITION_ENDELEMENT;
+ }
+ }
+}
+
+void XMLDocumentWrapper_XmlSecImpl::sendStartElement(
+ const uno::Reference< css::xml::sax::XDocumentHandler >& xHandler,
+ const uno::Reference< css::xml::sax::XDocumentHandler >& xHandler2,
+ const xmlNodePtr pNode)
+/****** XMLDocumentWrapper_XmlSecImpl/sendStartElement ************************
+ *
+ * NAME
+ * sendStartElement -- Constructs a startElement SAX event
+ *
+ * FUNCTION
+ * Used when converting the document into SAX event stream.
+ * This method constructs a startElement SAX event for a particular
+ * element, then calls the startElement methods of the XDocumentHandlers.
+ *
+ * INPUTS
+ * xHandler - the first XDocumentHandler interface to receive the
+ * startElement SAX event. It can be NULL.
+ * xHandler2 - the second XDocumentHandler interface to receive the
+ * startElement SAX event. It can't be NULL.
+ * pNode - the node on which the startElement should be generated.
+ * This node must be an element type.
+ ******************************************************************************/
+{
+ rtl::Reference<SvXMLAttributeList> pAttributeList = new SvXMLAttributeList();
+
+ xmlNsPtr pNsDef = pNode->nsDef;
+
+ while (pNsDef != nullptr)
+ {
+ const xmlChar* pNsPrefix = pNsDef->prefix;
+ const xmlChar* pNsHref = pNsDef->href;
+
+ if (pNsDef->prefix == nullptr)
+ {
+ pAttributeList->AddAttribute(
+ STRXMLNS,
+ OUString::fromUtf8(reinterpret_cast<char const *>(pNsHref)));
+ }
+ else
+ {
+ pAttributeList->AddAttribute(
+ STRXMLNS ":"
+ +OUString::fromUtf8(reinterpret_cast<char const *>(pNsPrefix)),
+ OUString::fromUtf8(reinterpret_cast<char const *>(pNsHref)));
+ }
+
+ pNsDef = pNsDef->next;
+ }
+
+ xmlAttrPtr pAttr = pNode->properties;
+
+ while (pAttr != nullptr)
+ {
+ const xmlChar* pAttrName = pAttr->name;
+ xmlNsPtr pAttrNs = pAttr->ns;
+
+ OUString ouAttrName;
+ if (pAttrNs == nullptr)
+ {
+ ouAttrName = OUString::fromUtf8(reinterpret_cast<char const *>(pAttrName));
+ }
+ else
+ {
+ ouAttrName = OUString::fromUtf8(reinterpret_cast<char const *>(pAttrNs->prefix))
+ + ":" + OUString::fromUtf8(reinterpret_cast<char const *>(pAttrName));
+ }
+
+ pAttributeList->AddAttribute(
+ ouAttrName,
+ OUString::fromUtf8(reinterpret_cast<char*>(pAttr->children->content)));
+ pAttr = pAttr->next;
+ }
+
+ OString sNodeName = getNodeQName(pNode);
+
+ if (xHandler.is())
+ {
+ xHandler->startElement(
+ OUString::fromUtf8(sNodeName),
+ pAttributeList);
+ }
+
+ xHandler2->startElement(
+ OUString::fromUtf8(sNodeName),
+ pAttributeList);
+}
+
+void XMLDocumentWrapper_XmlSecImpl::sendEndElement(
+ const uno::Reference< css::xml::sax::XDocumentHandler >& xHandler,
+ const uno::Reference< css::xml::sax::XDocumentHandler >& xHandler2,
+ const xmlNodePtr pNode)
+/****** XMLDocumentWrapper_XmlSecImpl/sendEndElement **************************
+ *
+ * NAME
+ * sendEndElement -- Constructs an endElement SAX event
+ *
+ * FUNCTION
+ * Used when converting the document into SAX event stream.
+ * This method constructs an endElement SAX event for a particular
+ * element, then calls the endElement methods of the XDocumentHandlers.
+ *
+ * INPUTS
+ * xHandler - the first XDocumentHandler interface to receive the
+ * endElement SAX event. It can be NULL.
+ * xHandler2 - the second XDocumentHandler interface to receive the
+ * endElement SAX event. It can't be NULL.
+ * pNode - the node on which the endElement should be generated.
+ * This node must be an element type.
+ ******************************************************************************/
+{
+ OString sNodeName = getNodeQName(pNode);
+
+ if (xHandler.is())
+ {
+ xHandler->endElement(OUString::fromUtf8(sNodeName));
+ }
+
+ xHandler2->endElement(OUString::fromUtf8(sNodeName));
+}
+
+void XMLDocumentWrapper_XmlSecImpl::sendNode(
+ const uno::Reference< css::xml::sax::XDocumentHandler >& xHandler,
+ const uno::Reference< css::xml::sax::XDocumentHandler >& xHandler2,
+ const xmlNodePtr pNode)
+/****** XMLDocumentWrapper_XmlSecImpl/sendNode ********************************
+ *
+ * NAME
+ * sendNode -- Constructs a characters SAX event or a
+ * processingInstruction SAX event
+ *
+ * FUNCTION
+ * Used when converting the document into SAX event stream.
+ * This method constructs a characters SAX event or a
+ * processingInstructionfor SAX event based on the type of a particular
+ * element, then calls the corresponding methods of the XDocumentHandlers.
+ *
+ * INPUTS
+ * xHandler - the first XDocumentHandler interface to receive the
+ * SAX event. It can be NULL.
+ * xHandler2 - the second XDocumentHandler interface to receive the
+ * SAX event. It can't be NULL.
+ * pNode - the node on which the endElement should be generated.
+ * If it is a text node, then a characters SAX event is
+ * generated; if it is a PI node, then a
+ * processingInstructionfor SAX event is generated.
+ ******************************************************************************/
+{
+ xmlElementType type = pNode->type;
+
+ if (type == XML_TEXT_NODE)
+ {
+ if (xHandler.is())
+ {
+ xHandler->characters(OUString::fromUtf8(reinterpret_cast<char*>(pNode->content)));
+ }
+
+ xHandler2->characters(OUString::fromUtf8(reinterpret_cast<char*>(pNode->content)));
+ }
+ else if (type == XML_PI_NODE)
+ {
+ if (xHandler.is())
+ {
+ xHandler->processingInstruction(
+ OUString::fromUtf8(reinterpret_cast<char const *>(pNode->name)),
+ OUString::fromUtf8(reinterpret_cast<char const *>(pNode->content)));
+ }
+
+ xHandler2->processingInstruction(
+ OUString::fromUtf8(reinterpret_cast<char const *>(pNode->name)),
+ OUString::fromUtf8(reinterpret_cast<char*>(pNode->content)));
+ }
+}
+
+OString XMLDocumentWrapper_XmlSecImpl::getNodeQName(const xmlNodePtr pNode)
+/****** XMLDocumentWrapper_XmlSecImpl/getNodeQName ****************************
+ *
+ * NAME
+ * getNodeQName -- Retrieves the qualified name of a node
+ *
+ * INPUTS
+ * pNode - the node whose name will be retrieved
+ *
+ * RESULT
+ * name - the node's qualified name
+ ******************************************************************************/
+{
+ OString sNodeName(reinterpret_cast<const char*>(pNode->name));
+ if (pNode->ns != nullptr)
+ {
+ xmlNsPtr pNs = pNode->ns;
+
+ if (pNs->prefix != nullptr)
+ {
+ OString sPrefix(reinterpret_cast<const char*>(pNs->prefix));
+ sNodeName = sPrefix + ":" + sNodeName;
+ }
+ }
+
+ return sNodeName;
+}
+
+xmlNodePtr XMLDocumentWrapper_XmlSecImpl::checkElement( const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& xXMLElement)
+/****** XMLDocumentWrapper_XmlSecImpl/checkElement ****************************
+ *
+ * NAME
+ * checkElement -- Retrieves the node wrapped by an XXMLElementWrapper
+ * interface
+ *
+ * INPUTS
+ * xXMLElement - the XXMLElementWrapper interface wrapping a node
+ *
+ * RESULT
+ * node - the node wrapped in the XXMLElementWrapper interface
+ ******************************************************************************/
+{
+ xmlNodePtr rc = nullptr;
+
+ if (xXMLElement.is())
+ {
+ uno::Reference< css::lang::XUnoTunnel > xNodTunnel( xXMLElement, uno::UNO_QUERY_THROW ) ;
+ XMLElementWrapper_XmlSecImpl* pElement
+ = comphelper::getFromUnoTunnel<XMLElementWrapper_XmlSecImpl>(xNodTunnel);
+
+ if( pElement == nullptr ) {
+ throw uno::RuntimeException() ;
+ }
+
+ rc = pElement->getNativeElement();
+ }
+
+ return rc;
+}
+
+sal_Int32 XMLDocumentWrapper_XmlSecImpl::recursiveDelete(
+ const xmlNodePtr pNode)
+/****** XMLDocumentWrapper_XmlSecImpl/recursiveDelete *************************
+ *
+ * NAME
+ * recursiveDelete -- Deletes a particular node with its branch.
+ *
+ * FUNCTION
+ * Deletes a particular node with its branch, while reserving the nodes
+ * (and their branches) listed in the m_aReservedNodes.
+ * The deletion process is performed in the tree order, that is, a node
+ * is deleted after its previous sibling node is deleted, a parent node
+ * is deleted after its branch is deleted.
+ * During the deletion process when the m_pStopAtNode is reached, the
+ * progress is interrupted at once.
+ *
+ * INPUTS
+ * pNode - the node to be deleted
+ *
+ * RESULT
+ * result - the result of the deletion process, can be one of following
+ * values:
+ * NODE_STOPPED - the process is interrupted by meeting the
+ * m_pStopAtNode
+ * NODE_NOTREMOVED - the pNode is not completely removed
+ * because there is its descendant in the
+ * m_aReservedNodes list
+ * NODE_REMOVED - the pNode and its branch are completely
+ * removed
+ *
+ * NOTES
+ * The node in the m_aReservedNodes list must be in the tree order, otherwise
+ * the result is unpredictable.
+ ******************************************************************************/
+{
+ if (pNode == m_pStopAtNode)
+ {
+ return NODE_STOPPED;
+ }
+
+ if (pNode != m_pCurrentReservedNode)
+ {
+ xmlNodePtr pChild = pNode->children;
+
+ xmlNodePtr pNextSibling;
+ bool bIsRemoved = true;
+ sal_Int32 nResult;
+
+ while( pChild != nullptr )
+ {
+ pNextSibling = pChild->next;
+ nResult = recursiveDelete(pChild);
+
+ switch (nResult)
+ {
+ case NODE_STOPPED:
+ return NODE_STOPPED;
+ case NODE_NOTREMOVED:
+ bIsRemoved = false;
+ break;
+ case NODE_REMOVED:
+ removeNode(pChild);
+ break;
+ default:
+ throw uno::RuntimeException();
+ }
+
+ pChild = pNextSibling;
+ }
+
+ if (pNode == m_pCurrentElement)
+ {
+ bIsRemoved = false;
+ }
+
+ return bIsRemoved?NODE_REMOVED:NODE_NOTREMOVED;
+ }
+ else
+ {
+ getNextReservedNode();
+ return NODE_NOTREMOVED;
+ }
+}
+
+void XMLDocumentWrapper_XmlSecImpl::getNextReservedNode()
+/****** XMLDocumentWrapper_XmlSecImpl/getNextReservedNode *********************
+ *
+ * NAME
+ * getNextReservedNode -- Highlights the next reserved node in the
+ * reserved node list
+ *
+ * FUNCTION
+ * The m_aReservedNodes array holds a node list, while the
+ * m_pCurrentReservedNode points to the one currently highlighted.
+ * This method is used to highlight the next node in the node list.
+ * This method is called at the time when the current highlighted node
+ * has been already processed, and the next node should be ready.
+ ******************************************************************************/
+{
+ if (m_nReservedNodeIndex < m_aReservedNodes.getLength())
+ {
+ m_pCurrentReservedNode = checkElement( m_aReservedNodes[m_nReservedNodeIndex] );
+ m_nReservedNodeIndex ++;
+ }
+ else
+ {
+ m_pCurrentReservedNode = nullptr;
+ }
+}
+
+void XMLDocumentWrapper_XmlSecImpl::removeNode(const xmlNodePtr pNode) const
+/****** XMLDocumentWrapper_XmlSecImpl/removeNode ******************************
+ *
+ * NAME
+ * removeNode -- Deletes a node with its branch unconditionally
+ *
+ * FUNCTION
+ * Delete the node along with its branch from the document.
+ *
+ * INPUTS
+ * pNode - the node to be deleted
+ ******************************************************************************/
+{
+ /* you can't remove the current node */
+ OSL_ASSERT( m_pCurrentElement != pNode );
+
+ xmlAttrPtr pAttr = pNode->properties;
+
+ while (pAttr != nullptr)
+ {
+ if (!stricmp(reinterpret_cast<char const *>(pAttr->name), "id"))
+ {
+ xmlRemoveID(m_pDocument, pAttr);
+ }
+
+ pAttr = pAttr->next;
+ }
+
+ xmlUnlinkNode(pNode);
+ xmlFreeNode(pNode);
+}
+
+void XMLDocumentWrapper_XmlSecImpl::buildIDAttr(xmlNodePtr pNode) const
+/****** XMLDocumentWrapper_XmlSecImpl/buildIDAttr *****************************
+ *
+ * NAME
+ * buildIDAttr -- build the ID attribute of a node
+ *
+ * INPUTS
+ * pNode - the node whose id attribute will be built
+ ******************************************************************************/
+{
+ xmlAttrPtr idAttr = xmlHasProp( pNode, reinterpret_cast<const unsigned char *>("id") );
+ if (idAttr == nullptr)
+ {
+ idAttr = xmlHasProp( pNode, reinterpret_cast<const unsigned char *>("Id") );
+ }
+
+ if (idAttr != nullptr)
+ {
+ xmlChar* idValue = xmlNodeListGetString( m_pDocument, idAttr->children, 1 ) ;
+ xmlAddID( nullptr, m_pDocument, idValue, idAttr );
+ }
+}
+
+void XMLDocumentWrapper_XmlSecImpl::rebuildIDLink(xmlNodePtr pNode) const
+/****** XMLDocumentWrapper_XmlSecImpl/rebuildIDLink ***************************
+ *
+ * NAME
+ * rebuildIDLink -- rebuild the ID link for the branch
+ *
+ * INPUTS
+ * pNode - the node, from which the branch will be rebuilt
+ ******************************************************************************/
+{
+ if (pNode != nullptr && pNode->type == XML_ELEMENT_NODE)
+ {
+ buildIDAttr( pNode );
+
+ xmlNodePtr child = pNode->children;
+ while (child != nullptr)
+ {
+ rebuildIDLink(child);
+ child = child->next;
+ }
+ }
+}
+
+/* XXMLDocumentWrapper */
+uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getCurrentElement( )
+{
+ return new XMLElementWrapper_XmlSecImpl(m_pCurrentElement);
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::setCurrentElement( const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& element )
+{
+ m_pCurrentElement = checkElement( element );
+ saxHelper.setCurrentNode( m_pCurrentElement );
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::removeCurrentElement( )
+{
+ OSL_ASSERT( m_pCurrentElement != nullptr );
+
+ xmlNodePtr pOldCurrentElement = m_pCurrentElement;
+
+ /*
+ * pop the top node in the parser context's
+ * nodeTab stack, then the parent of that node will
+ * automatically become the new stack top, and
+ * the current node as well.
+ */
+ saxHelper.endElement(OUString::fromUtf8(reinterpret_cast<char const *>(pOldCurrentElement->name)));
+ m_pCurrentElement = saxHelper.getCurrentNode();
+
+ /*
+ * remove the node
+ */
+ removeNode(pOldCurrentElement);
+}
+
+sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::isCurrent( const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& node )
+{
+ xmlNodePtr pNode = checkElement(node);
+ return (pNode == m_pCurrentElement);
+}
+
+sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::isCurrentElementEmpty( )
+{
+ bool rc = false;
+
+ if (m_pCurrentElement->children == nullptr)
+ {
+ rc = true;
+ }
+
+ return rc;
+}
+
+OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getNodeName( const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& node )
+{
+ xmlNodePtr pNode = checkElement(node);
+ return OUString::fromUtf8(reinterpret_cast<char const *>(pNode->name));
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::clearUselessData(
+ const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& node,
+ const uno::Sequence< uno::Reference< css::xml::wrapper::XXMLElementWrapper > >& reservedDescendants,
+ const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& stopAtNode )
+{
+ xmlNodePtr pTargetNode = checkElement(node);
+
+ m_pStopAtNode = checkElement(stopAtNode);
+ m_aReservedNodes = reservedDescendants;
+ m_nReservedNodeIndex = 0;
+
+ getNextReservedNode();
+
+ recursiveDelete(pTargetNode);
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::collapse( const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& node )
+{
+ xmlNodePtr pTargetNode = checkElement(node);
+ xmlNodePtr pParent;
+
+ while (pTargetNode != nullptr)
+ {
+ if (pTargetNode->children != nullptr || pTargetNode == m_pCurrentElement)
+ {
+ break;
+ }
+
+ pParent = pTargetNode->parent;
+ removeNode(pTargetNode);
+ pTargetNode = pParent;
+ }
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::getTree( const uno::Reference< css::xml::sax::XDocumentHandler >& handler )
+{
+ if (m_pRootElement == nullptr)
+ return;
+
+ xmlNodePtr pTempCurrentElement = m_pCurrentElement;
+ sal_Int32 nTempCurrentPosition = m_nCurrentPosition;
+
+ m_pCurrentElement = m_pRootElement;
+
+ m_nCurrentPosition = NODEPOSITION_STARTELEMENT;
+
+ while(true)
+ {
+ switch (m_nCurrentPosition)
+ {
+ case NODEPOSITION_STARTELEMENT:
+ sendStartElement(nullptr, handler, m_pCurrentElement);
+ break;
+ case NODEPOSITION_ENDELEMENT:
+ sendEndElement(nullptr, handler, m_pCurrentElement);
+ break;
+ case NODEPOSITION_NORMAL:
+ sendNode(nullptr, handler, m_pCurrentElement);
+ break;
+ }
+
+ if ( (m_pCurrentElement == m_pRootElement) && (m_nCurrentPosition == NODEPOSITION_ENDELEMENT ))
+ {
+ break;
+ }
+
+ getNextSAXEvent();
+ }
+
+ m_pCurrentElement = pTempCurrentElement;
+ m_nCurrentPosition = nTempCurrentPosition;
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::generateSAXEvents(
+ const uno::Reference< css::xml::sax::XDocumentHandler >& handler,
+ const uno::Reference< css::xml::sax::XDocumentHandler >& xEventKeeperHandler,
+ const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& startNode,
+ const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& endNode )
+{
+ /*
+ * The first SAX event is the startElement of the startNode
+ * element.
+ */
+ bool bHasCurrentElementChild = (m_pCurrentElement->children != nullptr);
+
+ xmlNodePtr pTempCurrentElement = m_pCurrentElement;
+
+ m_pCurrentElement = checkElement(startNode);
+
+ if (m_pCurrentElement->type == XML_ELEMENT_NODE)
+ {
+ m_nCurrentPosition = NODEPOSITION_STARTELEMENT;
+ }
+ else
+ {
+ m_nCurrentPosition = NODEPOSITION_NORMAL;
+ }
+
+ xmlNodePtr pEndNode = checkElement(endNode);
+
+ uno::Reference < css::xml::crypto::sax::XSAXEventKeeper > xSAXEventKeeper( xEventKeeperHandler, uno::UNO_QUERY );
+
+ uno::Reference< css::xml::sax::XDocumentHandler > xHandler = handler;
+
+ while(true)
+ {
+ switch (m_nCurrentPosition)
+ {
+ case NODEPOSITION_STARTELEMENT:
+ sendStartElement(xHandler, xEventKeeperHandler, m_pCurrentElement);
+ break;
+ case NODEPOSITION_ENDELEMENT:
+ sendEndElement(xHandler, xEventKeeperHandler, m_pCurrentElement);
+ break;
+ case NODEPOSITION_NORMAL:
+ sendNode(xHandler, xEventKeeperHandler, m_pCurrentElement);
+ break;
+ default:
+ throw uno::RuntimeException();
+ }
+
+ if (xSAXEventKeeper->isBlocking())
+ {
+ xHandler = nullptr;
+ }
+
+ if (pEndNode == nullptr &&
+ ((bHasCurrentElementChild && m_pCurrentElement == xmlGetLastChild(pTempCurrentElement) && m_nCurrentPosition != NODEPOSITION_STARTELEMENT) ||
+ (!bHasCurrentElementChild && m_pCurrentElement == pTempCurrentElement && m_nCurrentPosition == NODEPOSITION_STARTELEMENT)))
+ {
+ break;
+ }
+
+ getNextSAXEvent();
+
+ /*
+ * If there is an end point specified, then check whether
+ * the current node equals to the end point. If so, stop
+ * generating.
+ */
+ if (pEndNode != nullptr && m_pCurrentElement == pEndNode)
+ {
+ break;
+ }
+ }
+
+ m_pCurrentElement = pTempCurrentElement;
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::rebuildIDLink(
+ const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& node )
+{
+ xmlNodePtr pNode = checkElement( node );
+ rebuildIDLink(pNode);
+}
+
+
+/* css::xml::sax::XDocumentHandler */
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startDocument( )
+{
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endDocument( )
+{
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startElement( const OUString& aName, const uno::Reference< css::xml::sax::XAttributeList >& xAttribs )
+{
+ sal_Int32 nLength = xAttribs->getLength();
+ uno::Sequence< css::xml::csax::XMLAttribute > aAttributes (nLength);
+ auto aAttributesRange = asNonConstRange(aAttributes);
+
+ for (int i = 0; i < nLength; ++i)
+ {
+ aAttributesRange[i].sName = xAttribs->getNameByIndex(static_cast<short>(i));
+ aAttributesRange[i].sValue =xAttribs->getValueByIndex(static_cast<short>(i));
+ }
+
+ compressedStartElement(aName, aAttributes);
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endElement( const OUString& aName )
+{
+ saxHelper.endElement(aName);
+ m_pCurrentElement = saxHelper.getCurrentNode();
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::characters( const OUString& aChars )
+{
+ saxHelper.characters(aChars);
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::ignorableWhitespace( const OUString& aWhitespaces )
+{
+ saxHelper.ignorableWhitespace(aWhitespaces);
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::processingInstruction( const OUString& aTarget, const OUString& aData )
+{
+ saxHelper.processingInstruction(aTarget, aData);
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::setDocumentLocator( const uno::Reference< css::xml::sax::XLocator >& )
+{
+}
+
+/* XCompressedDocumentHandler */
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedStartDocument( )
+{
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedEndDocument( )
+{
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedStartElement( const OUString& aName, const uno::Sequence< css::xml::csax::XMLAttribute >& aAttributes )
+{
+ saxHelper.startElement(aName, aAttributes);
+ m_pCurrentElement = saxHelper.getCurrentNode();
+
+ buildIDAttr( m_pCurrentElement );
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedEndElement( const OUString& aName )
+{
+ endElement( aName );
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedCharacters( const OUString& aChars )
+{
+ characters( aChars );
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedIgnorableWhitespace( const OUString& aWhitespaces )
+{
+ ignorableWhitespace( aWhitespaces );
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedProcessingInstruction( const OUString& aTarget, const OUString& aData )
+{
+ processingInstruction( aTarget, aData );
+}
+
+void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedSetDocumentLocator( sal_Int32 /*columnNumber*/, sal_Int32 /*lineNumber*/, const OUString& /*publicId*/, const OUString& /*systemId*/ )
+{
+}
+
+/* XServiceInfo */
+OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getImplementationName( )
+{
+ return "com.sun.star.xml.wrapper.XMLDocumentWrapper";
+}
+
+sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService( this, rServiceName );
+}
+
+uno::Sequence< OUString > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getSupportedServiceNames( )
+{
+ return { "com.sun.star.xml.wrapper.XMLDocumentWrapper" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_xml_wrapper_XMLDocumentWrapper_get_implementation(
+ uno::XComponentContext* /*pCtx*/, uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new XMLDocumentWrapper_XmlSecImpl());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.cxx b/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.cxx
new file mode 100644
index 000000000..910496618
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.cxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <string.h>
+
+#include "xmlelementwrapper_xmlsecimpl.hxx"
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace com::sun::star;
+
+XMLElementWrapper_XmlSecImpl::XMLElementWrapper_XmlSecImpl(const xmlNodePtr pNode)
+ : m_pElement( pNode )
+{
+}
+
+/* XUnoTunnel */
+const uno::Sequence< sal_Int8 > & XMLElementWrapper_XmlSecImpl::getUnoTunnelId()
+{
+ static const comphelper::UnoIdInit implId;
+ return implId.getSeq();
+}
+
+sal_Int64 SAL_CALL XMLElementWrapper_XmlSecImpl::getSomething( const uno::Sequence< sal_Int8 >& aIdentifier )
+{
+ return comphelper::getSomethingImpl(aIdentifier, this);
+}
+
+/* XServiceInfo */
+OUString SAL_CALL XMLElementWrapper_XmlSecImpl::getImplementationName( )
+{
+ return "com.sun.star.xml.wrapper.XMLElementWrapper";
+}
+
+sal_Bool SAL_CALL XMLElementWrapper_XmlSecImpl::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService( this, rServiceName );
+}
+
+uno::Sequence< OUString > SAL_CALL XMLElementWrapper_XmlSecImpl::getSupportedServiceNames( )
+{
+ return { "com.sun.star.xml.wrapper.XMLElementWrapper" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
+com_sun_star_xml_wrapper_XMLElementWrapper_get_implementation(
+ uno::XComponentContext* /*pCtx*/, uno::Sequence<uno::Any> const& /*rSeq*/)
+{
+ return cppu::acquire(new XMLElementWrapper_XmlSecImpl(nullptr));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx b/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx
new file mode 100644
index 000000000..de833d25a
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/wrapper/XXMLElementWrapper.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase.hxx>
+
+#include <libxml/tree.h>
+#include <xsecxmlsecdllapi.h>
+
+class XMLElementWrapper_XmlSecImpl : public cppu::WeakImplHelper
+<
+ css::xml::wrapper::XXMLElementWrapper,
+ css::lang::XUnoTunnel,
+ css::lang::XServiceInfo
+>
+/****** XMLElementWrapper_XmlSecImpl.hxx/CLASS XMLElementWrapper_XmlSecImpl ***
+ *
+ * NAME
+ * XMLElementWrapper_XmlSecImpl -- Class to wrap a libxml2 node
+ *
+ * FUNCTION
+ * Used as a wrapper class to transfer a libxml2 node structure
+ * between different UNO components.
+ ******************************************************************************/
+{
+private:
+ /* the libxml2 node wrapped by this object */
+ xmlNodePtr const m_pElement;
+
+public:
+ explicit XMLElementWrapper_XmlSecImpl(const xmlNodePtr pNode);
+
+ /* XXMLElementWrapper */
+
+ /* css::lang::XUnoTunnel */
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override;
+ /// @throws css::uno::RuntimeException
+ static const css::uno::Sequence < sal_Int8 > & getUnoTunnelId();
+
+ /* css::lang::XServiceInfo */
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+public:
+ /*
+ * NAME
+ * getNativeElement -- Retrieves the libxml2 node wrapped by this object
+ *
+ * SYNOPSIS
+ * pNode = getNativeElement();
+ *
+ * RESULT
+ * pNode - the libxml2 node wrapped by this object
+ */
+ xmlNodePtr getNativeElement( ) const { return m_pElement;}
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/xmlsec_init.cxx b/xmlsecurity/source/xmlsec/xmlsec_init.cxx
new file mode 100644
index 000000000..410408ed2
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/xmlsec_init.cxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+#include <xmlsec-wrapper.h>
+
+#include <xmlsec/xmlsec_init.hxx>
+
+#include <com/sun/star/uno/RuntimeException.hpp>
+
+#include <xmlsec/xmlstreamio.hxx>
+#ifdef XMLSEC_CRYPTO_MSCRYPTO
+#include <xmlsec/mscng/crypto.h>
+#endif
+#ifdef XMLSEC_CRYPTO_NSS
+#include <xmlsec/nss/crypto.h>
+#endif
+
+using namespace css::uno;
+
+XSECXMLSEC_DLLPUBLIC void initXmlSec()
+{
+ //Init xmlsec library
+ if( xmlSecInit() < 0 ) {
+ throw RuntimeException() ;
+ }
+
+ //Init xmlsec crypto engine library
+#ifdef XMLSEC_CRYPTO_MSCRYPTO
+ if( xmlSecMSCngInit() < 0 ) {
+ xmlSecShutdown();
+ throw RuntimeException();
+ }
+#endif
+#ifdef XMLSEC_CRYPTO_NSS
+ if( xmlSecNssInit() < 0 ) {
+ xmlSecShutdown();
+ throw RuntimeException();
+ }
+#endif
+
+ //Enable external stream handlers
+ if( xmlEnableStreamInputCallbacks() < 0 ) {
+#ifdef XMLSEC_CRYPTO_MSCRYPTO
+ xmlSecMSCngShutdown();
+#endif
+#ifdef XMLSEC_CRYPTO_NSS
+ xmlSecNssShutdown();
+#endif
+ xmlSecShutdown() ;
+ throw RuntimeException() ;
+ }
+}
+
+XSECXMLSEC_DLLPUBLIC void deInitXmlSec()
+{
+ xmlDisableStreamInputCallbacks();
+#ifdef XMLSEC_CRYPTO_MSCRYPTO
+ xmlSecMSCngShutdown();
+#endif
+#ifdef XMLSEC_CRYPTO_NSS
+ xmlSecNssShutdown();
+#endif
+ xmlSecShutdown();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/source/xmlsec/xmlstreamio.cxx b/xmlsecurity/source/xmlsec/xmlstreamio.cxx
new file mode 100644
index 000000000..b3ee76712
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/xmlstreamio.cxx
@@ -0,0 +1,251 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <sal/config.h>
+#include <xmlsec-wrapper.h>
+
+/*
+ * Implementation of the I/O interfaces based on stream and URI binding
+ */
+#include <xmlsec/xmlstreamio.hxx>
+#include <xmlsec/errorcallback.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/uri.hxx>
+#include <comphelper/scopeguard.hxx>
+#include <sal/log.hxx>
+
+#include <com/sun/star/xml/crypto/XUriBinding.hpp>
+
+static bool g_bInputCallbacksEnabled = false;
+static bool g_bInputCallbacksRegistered = false;
+
+static css::uno::Reference< css::xml::crypto::XUriBinding > m_xUriBinding ;
+
+extern "C" {
+
+static int xmlStreamMatch( const char* uri )
+{
+ css::uno::Reference< css::io::XInputStream > xInputStream ;
+
+ if (g_bInputCallbacksEnabled && g_bInputCallbacksRegistered)
+ {
+ if( uri == nullptr || !m_xUriBinding.is() )
+ return 0 ;
+ //XMLSec first unescapes the uri and calls this function. For example, we pass the Uri
+ //ObjectReplacements/Object%201 then XMLSec passes ObjectReplacements/Object 1
+ //first. If this failed it would try this
+ //again with the original escaped string. However, it does not get this far, because there
+ //is another callback registered by libxml which claims to be able to handle this uri.
+ OUString sUri =
+ ::rtl::Uri::encode( OUString::createFromAscii( uri ),
+ rtl_UriCharClassUric, rtl_UriEncodeKeepEscapes, RTL_TEXTENCODING_UTF8);
+ xInputStream = m_xUriBinding->getUriBinding( sUri ) ;
+ if (!xInputStream.is())
+ {
+ //Try the passed in uri directly.
+ //For old documents prior OOo 3.0. We did not use URIs then.
+ xInputStream = m_xUriBinding->getUriBinding(
+ OUString::createFromAscii(uri));
+ }
+ }
+ SAL_INFO("xmlsecurity.xmlsec",
+ "xmlStreamMath: uri is '" << uri << "', returning " << xInputStream.is());
+ if (xInputStream.is())
+ return 1;
+ else
+ return 0 ;
+}
+
+static void* xmlStreamOpen( const char* uri )
+{
+ css::uno::Reference< css::io::XInputStream > xInputStream ;
+
+ if (g_bInputCallbacksEnabled && g_bInputCallbacksRegistered)
+ {
+ if( uri == nullptr || !m_xUriBinding.is() )
+ return nullptr ;
+
+ //see xmlStreamMatch
+ OUString sUri =
+ ::rtl::Uri::encode( OUString::createFromAscii( uri ),
+ rtl_UriCharClassUric, rtl_UriEncodeKeepEscapes, RTL_TEXTENCODING_UTF8);
+ xInputStream = m_xUriBinding->getUriBinding( sUri ) ;
+ if (!xInputStream.is())
+ {
+ //For old documents.
+ //try the passed in uri directly.
+ xInputStream = m_xUriBinding->getUriBinding(
+ OUString::createFromAscii(uri));
+ }
+
+ if( xInputStream.is() ) {
+ css::io::XInputStream* pInputStream ;
+ pInputStream = xInputStream.get() ;
+ pInputStream->acquire() ;
+ SAL_INFO("xmlsecurity.xmlsec",
+ "xmlStreamOpen: uri is '" << uri << "', returning context " << pInputStream);
+ return static_cast<void*>(pInputStream) ;
+ }
+ }
+
+ return nullptr ;
+}
+
+static int xmlStreamRead( void* context, char* buffer, int len )
+{
+ int numbers ;
+ css::uno::Reference< css::io::XInputStream > xInputStream ;
+ css::uno::Sequence< sal_Int8 > outSeqs( len ) ;
+
+ numbers = 0 ;
+ if (g_bInputCallbacksEnabled && g_bInputCallbacksRegistered)
+ {
+ if( context != nullptr ) {
+ xInputStream = static_cast<css::io::XInputStream*>(context);
+ if( !xInputStream.is() )
+ return 0 ;
+
+ numbers = xInputStream->readBytes( outSeqs, len ) ;
+ const sal_Int8* readBytes = outSeqs.getArray() ;
+ for( int i = 0 ; i < numbers ; i ++ )
+ *( buffer + i ) = *( readBytes + i ) ;
+ }
+ }
+
+ SAL_INFO("xmlsecurity.xmlsec", "xmlStreamRead: context is " << context << ", buffer is now '"
+ << OString(buffer, numbers) << "'");
+ return numbers ;
+}
+
+static int xmlStreamClose( void * context )
+{
+ if (g_bInputCallbacksEnabled && g_bInputCallbacksRegistered)
+ {
+ if( context != nullptr ) {
+ css::io::XInputStream* pInputStream ;
+ pInputStream = static_cast<css::io::XInputStream*>(context);
+ pInputStream->release() ;
+ SAL_INFO("xmlsecurity.xmlsec", "xmlStreamRead: closed context " << context);
+ }
+ }
+
+ return 0 ;
+}
+
+}
+
+int xmlEnableStreamInputCallbacks()
+{
+ if (!g_bInputCallbacksEnabled)
+ {
+ //Register the callbacks into xmlSec
+ //In order to make the xmlsec io finding the callbacks firstly,
+ //I put the callbacks at the very beginning.
+
+ //Cleanup the older callbacks.
+ //Notes: all none default callbacks will lose.
+ xmlSecIOCleanupCallbacks() ;
+
+ // Make sure that errors are reported via SAL_WARN().
+ setErrorRecorder();
+ comphelper::ScopeGuard g([] { clearErrorRecorder(); });
+
+ // Newer xmlsec wants the callback order in the opposite direction.
+ if (xmlSecCheckVersionExt(1, 2, 26, xmlSecCheckVersionABICompatible))
+ {
+ //Register the default callbacks.
+ //Notes: the error will cause xmlsec working problems.
+ int cbs = xmlSecIORegisterDefaultCallbacks() ;
+ if( cbs < 0 ) {
+ return -1 ;
+ }
+
+ //Register my classbacks.
+ cbs = xmlSecIORegisterCallbacks(
+ xmlStreamMatch,
+ xmlStreamOpen,
+ xmlStreamRead,
+ xmlStreamClose ) ;
+ if( cbs < 0 ) {
+ return -1 ;
+ }
+ }
+ else
+ {
+ //Register my classbacks.
+ int cbs = xmlSecIORegisterCallbacks(
+ xmlStreamMatch,
+ xmlStreamOpen,
+ xmlStreamRead,
+ xmlStreamClose ) ;
+ if( cbs < 0 ) {
+ return -1 ;
+ }
+
+ //Register the default callbacks.
+ //Notes: the error will cause xmlsec working problems.
+ cbs = xmlSecIORegisterDefaultCallbacks() ;
+ if( cbs < 0 ) {
+ return -1 ;
+ }
+ }
+
+ g_bInputCallbacksEnabled = true;
+ }
+
+ return 0 ;
+}
+
+int xmlRegisterStreamInputCallbacks(
+ css::uno::Reference< css::xml::crypto::XUriBinding > const & aUriBinding
+) {
+ if (!g_bInputCallbacksEnabled)
+ {
+ if( xmlEnableStreamInputCallbacks() < 0 )
+ return -1 ;
+ }
+
+ if (!g_bInputCallbacksRegistered)
+ g_bInputCallbacksRegistered = true;
+
+ m_xUriBinding = aUriBinding ;
+
+ return 0 ;
+}
+
+int xmlUnregisterStreamInputCallbacks()
+{
+ if (g_bInputCallbacksRegistered)
+ {
+ //Clear the uri-stream binding
+ m_xUriBinding.clear() ;
+
+ //disable the registered flag
+ g_bInputCallbacksRegistered = false;
+ }
+
+ return 0 ;
+}
+
+void xmlDisableStreamInputCallbacks() {
+ xmlUnregisterStreamInputCallbacks() ;
+ g_bInputCallbacksEnabled = false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmlsecurity/test_docs/CAs/README.txt b/xmlsecurity/test_docs/CAs/README.txt
new file mode 100644
index 000000000..b454f1faf
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/README.txt
@@ -0,0 +1,383 @@
+This folder contains the directory structures needed by openssl to create
+and manager certificates.
+
+
+
+################################################################################
+
+Root 1
+======
+Valid root CA certificate.
+Provides CRL = NO
+Provides CRL via HTTP = NO
+Provides OCSP = NO
+
+Sub CA 1 Root 1
+===============
+Valid intermediate CA certificate.
+Provides CRL = NO
+Provides CRL via HTTP = NO
+Provides OCSP = NO
+CRLDP = NO
+AIA = NO
+
+User 1 Sub CA 1 Root 1
+======================
+Valid end certificate.
+CRLDP = NO
+AIA = NO
+
+################################################################################
+
+Root 2
+======
+Valid root CA certificate.
+Provides CRL = NO
+Provides CRL via HTTP = NO
+Provides OCSP = NO
+
+Sub CA 1 Root 2
+===============
+Valid intermediate CA certificate.
+Provides CRL = YES
+Provides CRL via HTTP = NO
+Provides OCSP = NO
+CRLDP = NO
+AIA = NO
+
+User 1 Sub CA 1 Root 2
+======================
+Valid end certificate.
+CRLDP = NO
+AIA = NO
+
+################################################################################
+
+Root 3
+======
+Valid root CA certificate.
+Provides CRL = YES
+Provides CRL via HTTP = NO
+Provides OCSP = NO
+
+Sub CA 1 Root 3
+===============
+Valid intermediate CA certificate.
+Provides CRL = NO
+Provides CRL via HTTP = NO
+Provides OCSP = NO
+CRLDP = NO
+AIA = NO
+
+User 1 Sub CA 1 Root 3
+======================
+Valid end certificate.
+CRLDP = NO
+AIA = NO
+
+################################################################################
+
+Root 4
+======
+Valid root CA certificate.
+Provides CRL = YES
+Provides CRL via HTTP = NO
+Provides OCSP = NO
+
+Revoked certificates:
+
+- Sub CA 2 Root 4
+
+
+Sub CA 1 Root 4
+===============
+Valid intermediate CA certificate.
+Provides CRL = YES
+Provides CRL via HTTP = NO
+Provides OCSP = NO
+CRLDP = NO
+AIA = NO
+
+Revoked certificates:
+
+- User 2 Sub CA 1 Root 4
+
+
+User 1 Sub CA 1 Root 4
+======================
+Valid end certificate.
+CRLDP = NO
+AIA = NO
+
+User 2 Sub CA 1 Root 4
+======================
+Revoked end certificate.
+CRLDP = NO
+AIA = NO
+
+Sub CA 2 Root 4
+===============
+Revoked intermediate CA certificate. Reason = keyCompromise
+Provides CRL = YES
+Provides CRL via HTTP = NO
+Provides OCSP = NO
+CRLDP = NO
+AIA = NO
+
+Revoked certificates:
+
+- User 2 Sub CA 2 Root 4
+
+User 1 Sub CA 2 Root 4
+======================
+Valid end certificate. Issuer is revoked.
+CRLDP = NO
+AIA = NO
+
+User 2 Sub CA 2 Root 4
+======================
+Revoked end certificate. Reason = keyCompromise. Issuer is revoked.
+CRLDP = NO
+AIA = NO
+
+################################################################################
+
+Root 5
+======
+Valid root CA certificate.
+Provides CRL = NO
+Provides CRL via HTTP = NO
+Provides OCSP = NO
+
+Sub CA 1 Root 5
+===============
+Valid intermediate CA certificate.
+Provides CRL = NO
+Provides CRL via HTTP = YES
+Provides OCSP = NO
+CRLDP = URL=http://localhost:8901/demoCA/crl/Root_5.crl
+AIA = NO
+
+User 1 Sub CA 1 Root 5
+======================
+Valid end certificate.
+CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_1_Root_5.crl
+AIA = NO
+
+
+################################################################################
+
+Root 6
+======
+Valid root CA certificate.
+Provides CRL = NO
+Provides CRL via HTTP = YES
+Provides OCSP = NO
+
+Sub CA 1 Root 6
+===============
+Valid intermediate CA certificate.
+Provides CRL = NO
+Provides CRL via HTTP = NO
+Provides OCSP = NO
+CRLDP = URL=http://localhost:8901/demoCA/crl/Root_6.crl
+AIA = NO
+
+User 1 Sub CA 1 Root 6
+======================
+Valid end certificate.
+CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_1_Root_6.crl
+AIA = NO
+
+################################################################################
+
+Root 7
+======
+Valid root CA certificate.
+Provides CRL = NO
+Provides CRL via HTTP = YES
+Provides OCSP = NO
+
+Revoked certificates:
+
+- Sub CA 2 Root 7
+
+
+Sub CA 1 Root 7
+===============
+Valid intermediate CA certificate.
+Provides CRL = NO
+Provides CRL via HTTP = YES
+Provides OCSP = NO
+CRLDP = URL=http://localhost:8901/demoCA/crl/Root_7.crl
+AIA = NO
+
+Revoked certificates:
+
+- User 2 Sub CA 1 Root 7
+
+
+User 1 Sub CA 1 Root 7
+======================
+Valid end certificate.
+CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl
+AIA = NO
+
+User 2 Sub CA 1 Root 7
+======================
+Revoked end certificate. Reason = CACompromise.
+CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl
+AIA = NO
+
+Sub CA 2 Root 7
+===============
+Revoked intermediate CA certificate. Reason = keyCompromise
+Provides CRL = NO
+Provides CRL via HTTP = YES
+Provides OCSP = NO
+CRLDP = URL=http://localhost:8901/demoCA/crl/Root_7.crl
+AIA = NO
+
+Revoked certificates:
+
+- User 2 Sub CA 2 Root 7
+
+User 1 Sub CA 2 Root 7
+======================
+Valid end certificate. Issuer is revoked.
+CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl
+AIA = NO
+
+User 2 Sub CA 2 Root 7
+======================
+Revoked end certificate. Reason = CACompromise. Issuer is revoked.
+CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl
+AIA = NO
+
+################################################################################
+
+Root 8
+======
+Valid root CA certificate.
+Provides CRL = NO
+Provides CRL via HTTP = NO
+Provides OCSP = YES
+
+Revoked certificates:
+
+- Sub CA 2 Root 8
+
+
+Sub CA 1 Root 8
+===============
+Valid intermediate CA certificate.
+Provides CRL = NO
+Provides CRL via HTTP = NO
+Provides OCSP = YES
+CRLDP =
+AIA = OCSP;URI:http://localhost:8888
+
+Revoked certificates:
+
+- User 2 Sub CA 1 Root 8
+
+
+User 1 Sub CA 1 Root 8
+======================
+Valid end certificate.
+CRLDP = NO
+AIA = OCSP;URI:http://localhost:8889
+
+User 2 Sub CA 1 Root 8
+======================
+Revoked end certificate. Reason = superseded.
+CRLDP = NO
+AIA = OCSP;URI:http://localhost:8889
+
+Sub CA 2 Root 8
+===============
+Revoked intermediate CA certificate. Reason = superseded.
+Provides CRL = NO
+Provides CRL via HTTP = NO
+Provides OCSP = YES
+CRLDP = NO
+AIA = OCSP;URI:http://localhost:8888
+
+Revoked certificates:
+
+- User 2 Sub CA 2 Root 8
+
+User 1 Sub CA 2 Root 8
+======================
+Valid end certificate. Issuer is revoked.
+CRLDP = NO
+AIA = OCSP;URI:http://localhost:8889
+
+User 2 Sub CA 2 Root 8
+======================
+Revoked end certificate. Reason = superseded. Issuer is revoked.
+CRLDP = NO
+AIA = OCSP;URI:http://localhost:8889
+
+################################################################################
+
+Root 9
+======
+Valid root CA certificate. (Not installed.)
+Provides CRL = YES
+Provides CRL via HTTP = NO
+Provides OCSP = NO
+
+Sub CA 1 Root 9
+===============
+Valid intermediate CA certificate.
+Provides CRL = YES
+Provides CRL via HTTP = NO
+Provides OCSP = NO
+CRLDP = NO
+AIA = NO
+
+User 1 Sub CA 1 Root 9
+======================
+Valid end certificate.
+CRLDP = NO
+AIA = NO
+
+################################################################################
+
+Root 10
+======
+Valid root CA certificate.
+Provides CRL = YES
+Provides CRL via HTTP = NO
+Provides OCSP = NO
+
+Sub CA 1 Root 10
+===============
+Valid intermediate CA certificate. (Not installed.)
+Provides CRL = NO
+Provides CRL via HTTP = YES
+Provides OCSP = NO
+CRLDP = NO
+AIA = NO
+
+User 1 Sub CA 1 Root 10
+======================
+Valid end certificate.
+CRLDP = URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_10.crl
+AIA = caIssuers;URI:http://localhost:8910/demoCA/Sub_CA_1_Root_10.crt
+
+################################################################################
+
+Root 11
+======
+Valid root CA certificate.
+Provides CRL = YES
+Provides CRL via HTTP = NO
+Provides OCSP = NO
+
+User x Root 11
+======================
+All certificate issues by Root 11 are valid end certificate. Currently there are
+31 certificates.
+
diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_1/demoCA/cacert.pem
new file mode 100644
index 000000000..091052e3a
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/cacert.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDBDCCAm2gAwIBAgIJAJWwBSvtwjktMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV
+BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y
+ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMTAeFw0wOTEx
+MTgxNDU1NDFaFw0zNDExMTIxNDU1NDFaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAvrD6NFWcOQQVxIuXw5Pzpy667PZbBP80ow2Bbnj+RFCI/LbgfQTsC8Bw
+eSlQGX7IqMHkCTuWNJw7CoNeOLFhRMtm0DEKnEkZlM0t6kpFshbs12jZu9okcnII
+F5uIoKxx/thbD5AbC1Q74vZr6XOXY5Sc+k9Ic6Jwhe9ZyEt6SUsCAwEAAaOBxzCB
+xDAdBgNVHQ4EFgQUD/rG69/OuLuzqT5Cprrs0pPKR6QwgZEGA1UdIwSBiTCBhoAU
+D/rG69/OuLuzqT5Cprrs0pPKR6ShY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMYIJAJWwBSvtwjktMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAqORur4HQGdQOQCaiyZR5u0+9mM/0w79y
+r8Cmt+H8WB5BBeDgCyOcmaZjF0eEoRBF/ZhtlO54i4CH/yb/Pl6gGlxfGZL9iLu0
+tv4HRIIibnoi0N7Z0r/dhJcrTHo4Ha8EARhAqxoNUSlGVBsaKUfjW9RyCjv4Akyi
+WUSwsmtd/sY=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL
diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_1/demoCA/crlnumber
new file mode 100644
index 000000000..83b33d238
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/crlnumber
@@ -0,0 +1 @@
+1000
diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt
new file mode 100644
index 000000000..9a6e64301
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt
@@ -0,0 +1 @@
+V 341112150713Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 1
diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_1/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..be26aa5d8
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/newcerts/1000.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 1
+ Validity
+ Not Before: Nov 18 15:07:13 2009 GMT
+ Not After : Nov 12 15:07:13 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:d9:3a:8d:64:95:87:76:76:e8:61:c3:e9:65:f4:
+ a6:b7:0c:77:0e:4b:10:e8:14:a3:e1:84:69:7c:8e:
+ 97:d2:7d:01:ad:b2:dc:5c:cd:c6:91:a1:f3:93:7c:
+ 54:36:64:e3:ca:22:ca:00:cb:c6:91:ab:6b:26:88:
+ 69:60:9a:61:d7:59:17:db:93:7d:09:36:da:28:cb:
+ ec:2d:a4:26:bb:1a:42:20:b8:08:b2:0f:b9:77:a6:
+ 80:71:cf:13:f5:37:a2:90:4d:ab:e8:97:49:d2:80:
+ 94:8f:b1:9d:5a:b4:9f:de:ff:fa:b6:d6:e0:45:5f:
+ cc:d4:10:1e:32:46:7b:ba:55
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 37:71:74:81:44:DD:1E:B1:60:96:41:B7:4B:38:C4:B7:79:1B:CF:8A
+ X509v3 Authority Key Identifier:
+ keyid:0F:FA:C6:EB:DF:CE:B8:BB:B3:A9:3E:42:A6:BA:EC:D2:93:CA:47:A4
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 1
+ serial:95:B0:05:2B:ED:C2:39:2D
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 18:f6:02:5e:75:04:5f:eb:3b:07:41:85:c0:9e:08:29:58:3d:
+ b5:6f:c2:aa:24:0d:93:1d:17:fc:be:d6:43:ac:43:d7:4d:a0:
+ 2c:40:fd:3d:d5:7e:91:46:25:49:62:ba:e9:7f:67:c2:fc:8a:
+ c3:a0:37:bf:ec:f9:54:bf:61:10:35:dd:5b:bb:da:7c:70:54:
+ 32:13:b9:ae:7d:ea:a5:7d:aa:55:3e:ef:0a:ef:12:fd:c3:f6:
+ e5:25:98:97:34:02:64:fd:88:79:b3:e2:f4:fc:ff:e7:d3:98:
+ f1:d9:d5:18:d9:b4:62:ae:99:88:61:2e:ff:02:6a:13:35:fe:
+ 37:c7
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAxMB4XDTA5MTExODE1MDcx
+M1oXDTM0MTExMjE1MDcxM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAxMIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDZOo1klYd2duhhw+ll9Ka3DHcOSxDoFKPhhGl8jpfSfQGtstxczcaR
+ofOTfFQ2ZOPKIsoAy8aRq2smiGlgmmHXWRfbk30JNtooy+wtpCa7GkIguAiyD7l3
+poBxzxP1N6KQTavol0nSgJSPsZ1atJ/e//q21uBFX8zUEB4yRnu6VQIDAQABo4HH
+MIHEMB0GA1UdDgQWBBQ3cXSBRN0esWCWQbdLOMS3eRvPijCBkQYDVR0jBIGJMIGG
+gBQP+sbr3864u7OpPkKmuuzSk8pHpKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAxggkAlbAFK+3COS0wDwYDVR0TAQH/
+BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAY9gJedQRf6zsHQYXAnggpWD21b8Kq
+JA2THRf8vtZDrEPXTaAsQP091X6RRiVJYrrpf2fC/IrDoDe/7PlUv2EQNd1bu9p8
+cFQyE7mufeqlfapVPu8K7xL9w/blJZiXNAJk/Yh5s+L0/P/n05jx2dUY2bRirpmI
+YS7/AmoTNf43xw==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_1/demoCA/private/cakey.pem
new file mode 100644
index 000000000..6d38b24e6
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,2D2CC3782F59A842
+
+901JcMMdeCfHjfY05bkyLIsgMxwu4SFJPXZH75ebFtJQpkQQf5WNhSlo3sgKJ5MF
+GZeqQw4w9CmN+CNqQENZOOGrVKxT+sFtWIgSLVk4hrLzPtsT7domHc1yUKfpBH/w
+xo/bsL5wZPqcsxSdlmd4FA0PKzW/rhyYvRxF0oKQx2PVnJKT29WbhwlYurI3+2gG
+pS+N6f7awWjmgyqYvFuFo7DWhERDDL/Bi/sJ7qFinijtfp1CkVG1XWFZ8Tu9ij+t
+KPT3fpWbh4sV0V1ZGng7EPb4c+p/+GHvKsGM9N5kuyxufllNzAeIy6hfTR3mxn0i
+Ep4CoufMi0JwNEfgwBB+o47k1hVoBTn0ofXc2iP6iQWsoC5ZoPPGLLklWK3Tur7P
+kpng8UECTxV2s6J3nYkAoHfy+TzK+nssFPpE8zDmaprpeTj9oh3KrPTn0IdoPHcx
+oI3yqWqDK9uErJBBCAjLF0SPJWAsmp0HsJaGnj5ErVe0yy3jBxVWogVDSWkoWU0W
++umK1pSQrS1A/oKErsnbhPi8XAD/gd4etEaKdcY538QKgE2tdPvhLoAeXxslyOfG
+UiPohtmcm2Mva7vT0Iu1MGKplw76DxmmM1Rpf3+u7Kwf/+K6bMOSBGZQJhjE2AuZ
+aPyHX8gCNlZfqB6eeuWdbqIHhTN5dS2Bba3QquvS84Vgb3O2ck+vdjmdPEeetvA7
+7S4WZYHBRmz1ZHwdfSvwyBkdTRP5YrUhrIthbqy2NjcP9TkpQmJaDIlWXsGY738q
+zTsjCkcnS06x0/JvHe1I8IAib+MFsmGI7Dw25fzgY3ReS4wZRZdU0A==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_1/demoCA/serial
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/serial
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Root_1/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_1/openssl.cfg
new file mode 100644
index 000000000..0dd15bd9e
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_1/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_10/demoCA/cacert.pem
new file mode 100644
index 000000000..72e6c66e2
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/cacert.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDBzCCAnCgAwIBAgIJAL/ID7vZoDprMA0GCSqGSIb3DQEBBQUAMGAxCzAJBgNV
+BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y
+ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxEDAOBgNVBAMTB1Jvb3QgMTAwHhcNMDkx
+MTIzMTUwNzA0WhcNMzQxMTE3MTUwNzA0WjBgMQswCQYDVQQGEwJERTEQMA4GA1UE
+CBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0Rl
+dmVsb3BtZW50MRAwDgYDVQQDEwdSb290IDEwMIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQC5qE1pk/tI2i60IrVhlwS77j7jAyktxRuwKJqBECd2ZD2/goO8wcwD
+R/wfrh+zuLWRwFb57PF1O7ig+WNhQk3GDhXhMbuB82Bwjb/n5phKDWHsAIqDRbH4
+vpl/7sWYXvE46zf41PpQPgudOtqpeL1ENFoHKZOJthkBc4Yx6HTUSQIDAQABo4HI
+MIHFMB0GA1UdDgQWBBTIp6OAIHRsb+wReva+JhA3MYewejCBkgYDVR0jBIGKMIGH
+gBTIp6OAIHRsb+wReva+JhA3MYeweqFkpGIwYDELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMIIJAL/ID7vZoDprMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAroDDzqZQL+7NeQuePohejcGfFR/0
+vtbQ3AYViQ2JS42gQpaNaMNcVCvO0nUwLHldLNVdQsn9P0ultu6KcUKkBbY4/2Xp
+er6RMQWsrKVLnszgIi2gk1NiNwZ+N9RISJvElaQuIciZs+8sM6LOPybVTArMjxEo
+U3VqHTViFfOvWC0=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_10/demoCA/crlnumber
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/crlnumber
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt
new file mode 100644
index 000000000..2db3924ce
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt
@@ -0,0 +1 @@
+V 341117151448Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 10
diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_10/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..1f27b97b3
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/newcerts/1000.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 10
+ Validity
+ Not Before: Nov 23 15:14:48 2009 GMT
+ Not After : Nov 17 15:14:48 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 10
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:e4:d5:66:14:88:9f:79:41:50:b0:d1:a0:1b:98:
+ bf:b0:21:34:30:36:70:58:6f:8b:58:f1:b9:58:3a:
+ ce:29:6b:65:b6:11:f7:0d:c8:a6:c3:be:db:0f:2a:
+ 4e:c7:42:df:c9:0e:13:c0:00:0f:af:b5:71:c4:bc:
+ dd:82:fc:4a:27:c0:ee:af:ba:e1:7b:67:de:6b:bb:
+ ac:4c:fe:88:01:1a:73:4e:f5:32:15:3a:d0:cb:6b:
+ 97:84:1b:6c:d0:d6:91:a8:a4:5a:87:2a:69:61:36:
+ 1d:42:cc:16:d0:03:9c:c6:90:5c:61:20:8b:b1:be:
+ b6:54:24:5b:6f:1f:a9:5a:6f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 11:63:A1:BE:8B:E3:56:07:E6:A3:9F:23:39:72:7D:E3:22:B6:53:39
+ X509v3 Authority Key Identifier:
+ keyid:C8:A7:A3:80:20:74:6C:6F:EC:11:7A:F6:BE:26:10:37:31:87:B0:7A
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 10
+ serial:BF:C8:0F:BB:D9:A0:3A:6B
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 6b:0f:75:6d:56:b0:4e:45:19:65:ad:50:ef:4e:87:6c:95:5d:
+ 05:39:5a:43:5c:b4:51:25:9a:ec:f4:93:d1:f0:f6:91:dd:a3:
+ 77:95:0c:74:3c:a9:7c:c2:f6:62:ce:bf:58:5f:66:1f:d0:55:
+ ca:d8:2d:c4:1e:29:3a:ad:55:2c:9d:2c:8f:8e:9e:ce:ac:17:
+ 7e:1b:d1:16:d9:12:76:5c:2d:3f:9d:70:66:aa:39:34:f0:ec:
+ 31:4b:4b:5a:14:0c:c5:5b:3c:c8:47:02:90:cb:77:d7:4f:88:
+ 10:a7:80:3d:ca:19:5c:b5:04:c9:f0:e1:1b:5a:5f:fb:61:b2:
+ 14:b5
+-----BEGIN CERTIFICATE-----
+MIIDCTCCAnKgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMDAeFw0wOTExMjMxNTE0
+NDhaFw0zNDExMTcxNTE0NDhaMGkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxGTAXBgNVBAMTEFN1YiBDQSAxIFJvb3QgMTAwgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBAOTVZhSIn3lBULDRoBuYv7AhNDA2cFhvi1jxuVg6zilrZbYR9w3I
+psO+2w8qTsdC38kOE8AAD6+1ccS83YL8SifA7q+64Xtn3mu7rEz+iAEac071MhU6
+0Mtrl4QbbNDWkaikWocqaWE2HULMFtADnMaQXGEgi7G+tlQkW28fqVpvAgMBAAGj
+gcgwgcUwHQYDVR0OBBYEFBFjob6L41YH5qOfIzlyfeMitlM5MIGSBgNVHSMEgYow
+gYeAFMino4AgdGxv7BF69r4mEDcxh7B6oWSkYjBgMQswCQYDVQQGEwJERTEQMA4G
+A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT
+C0RldmVsb3BtZW50MRAwDgYDVQQDEwdSb290IDEwggkAv8gPu9mgOmswDwYDVR0T
+AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBrD3VtVrBORRllrVDvTodslV0F
+OVpDXLRRJZrs9JPR8PaR3aN3lQx0PKl8wvZizr9YX2Yf0FXK2C3EHik6rVUsnSyP
+jp7OrBd+G9EW2RJ2XC0/nXBmqjk08OwxS0taFAzFWzzIRwKQy3fXT4gQp4A9yhlc
+tQTJ8OEbWl/7YbIUtQ==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_10/demoCA/private/cakey.pem
new file mode 100644
index 000000000..f75ccc08e
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,78CCF9A24E7B5044
+
+ppKSX6K7DHnU4EvbmBAIzWDJ35yGppjzNdWRKpB7rkGW60dW0Cw0Jmbxf1dfbUC+
+UTWtxE+i0x159jF7jGobPvLFQnAg1ZPUUIgeXJt+fqf/OghY4i8x82BdSlaKJ293
+GgwR9m1N1I2/6ydob+9KwzJhOPhmylyUyRJVAx/OF86E9G4nxtuJA1c1nzSBgwR5
+7uHU0LiY5A42iTDiMmu7Jw4vj6Cy81P88hmyoVzo4JQG8YFuJyLz2ei+DJ3/572z
+BCefqDKmlmI2vvayZW1jgpLDlTwmqiIGUDBBipN4vDmqZAdEbv/9BjLkS4Svy3PU
+xaFs1tFQzv8ivGpyPWU5naoTKhmMhOEAKpEi6YqWbcD/qKn1pRrYSyVyD9zNXHEK
+QrXjTP+D/DMSHNJTo5WI4kxvwSZtPI97vaCTmxkrjnIXDPD5L4v9dJUdejnngsqn
+cHB/C/05dR0RLEp5CHrl0hwGiIY1IgQXmGHY2HEUyQYttyJ5jdY0pdnn9n0eQxHr
+9Mg3WneWC42XHw0pyqEsgiMmr8SjaF42MSrMB6y4WEVtBstn03LTdFnRIFTgZ5Mj
+l/O2mSk+YUBR4CYTUTRaWpzCAZmFVy98I8KQgrhi8t96wrRe0+9tB1uC5PoDNR5P
+CcgsmiEPeqolPZwOmnDdij+DcIiT43Sx2vDYGfDtqc+kur/O6noYyX8Kf7wzcpan
+V4gHTCEOrlcRiEcVIxAQFDpB8CERG9fJvnBdZE9Gjepz6OatRpE/2kDZMelwRcEx
+V5zeE1qNS51gdq2dE0qYkdyU1yfbNUouqtFy/z1sXU6Q5nR1r21jFQ==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_10/demoCA/serial
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/serial
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Root_10/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_10/openssl.cfg
new file mode 100644
index 000000000..f48e3d5a3
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_10/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/cacert.pem
new file mode 100644
index 000000000..8cfffd9a6
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/cacert.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDBzCCAnCgAwIBAgIJAI3gSU2IIGPLMA0GCSqGSIb3DQEBBQUAMGAxCzAJBgNV
+BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y
+ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxEDAOBgNVBAMTB1Jvb3QgMTEwHhcNMTAw
+MTE0MTEzNzA1WhcNMzUwMTA4MTEzNzA2WjBgMQswCQYDVQQGEwJERTEQMA4GA1UE
+CBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0Rl
+dmVsb3BtZW50MRAwDgYDVQQDEwdSb290IDExMIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDKGrq6yC3tyctcBo+iz31MF2yvDiQ7YFgez8TswNvb3USOPOUPsCaB
+ufVN6ULSqmGi5BzFIW7CVAj5L+iCrrwMtPyG86fKbvgdWmLepz5a4S1y+vydnQ0B
+rJCNdxmLdQK+l/P7jzrH5xhcR62DPQ2lLabvmixvylHv4H6cFjJ98wIDAQABo4HI
+MIHFMB0GA1UdDgQWBBToarvCkOpscCI+9vZIGwPmvremVTCBkgYDVR0jBIGKMIGH
+gBToarvCkOpscCI+9vZIGwPmvremVaFkpGIwYDELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMYIJAI3gSU2IIGPLMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAZRXdBfSqhY+xELs28/gjsZ4/mUvu
+LKL3PruRCNqUgIOznEdxsQXsmLIQhEPZ4a4jd31srFD2j5gJmZ8KdeFXII9NRvIX
+RpRcrl2uclHXWbIC7s6xiATDWumrL2nXB5bU4qYMZ0ybytXprIwkzqRFXUrEHcYm
+OXJCSKayIviQ6G0=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_11/demoCA/crlnumber
new file mode 100644
index 000000000..83b33d238
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/crlnumber
@@ -0,0 +1 @@
+1000
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt
new file mode 100644
index 000000000..f6c52e5ac
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt
@@ -0,0 +1,35 @@
+V 350108161110Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\xC5\xB9\xC5\xBA\xC5\xBB\xC5\xBC\xC5\xBD\xC5\xBE \xEF\xAC\xB3 j\xCE\xAC\xCE\xAD\xCE\xAE
+V 350108161614Z 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\xC5\xB9\xC5\xBA\xC5\xBB\xC5\xBC\xC5\xBD\xC5\xBE \xEF\xAD\x86 j\xCE\xAC\xCE\xAD\xCE\xAE
+V 350112144417Z 1002 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x04\x0F\x04\x10\x04\x11\x04\x12\x04\x13\x04\x14
+V 350112153942Z 1003 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x01y\x01z\x01{\x00 \x03\xA6\x03\xA7\x03\xA8\x03\xA9
+V 350112160038Z 1004 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00"
+V 350112160547Z 1005 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00"\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00"\x00"
+V 350112160921Z 1006 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00"\x00t\x00w\x00o\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00o\x00n\x00e\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00"
+V 350112161153Z 1007 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e
+V 350112161405Z 1008 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00"
+V 350112161631Z 1009 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00"\x00q\x00u\x00o\x00t\x00e
+V 350112161857Z 100A unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00"\x00"\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e
+V 350113090237Z 100B unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00p\x00a\x00r\x00t\x00i\x00a\x00l\x00l\x00y\x00 \x00"\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00"
+V 350113094852Z 100C unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00U\x00s\x00e\x00r\x00 \x001\x001\x00,\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e
+V 350113095110Z 100D unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x001\x002\x00,\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00"
+V 350113095308Z 100E unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00U\x00s\x00e\x00r\x00 \x001\x003\x00,\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00"
+V 350113095502Z 100F unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x001\x004\x00 \x00"\x00,\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e\x00"
+V 350113095752Z 1010 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00\
+V 350113095922Z 1011 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00\\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00\\x00\
+V 350113100207Z 1012 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00\\x00t\x00w\x00o\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00o\x00n\x00e\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\
+V 350113100436Z 1013 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e
+V 350113100550Z 1014 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\
+V 350113100707Z 1015 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00\\x00q\x00u\x00o\x00t\x00e
+V 350113100950Z 1016 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00\\x00\\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e
+V 350113101153Z 1017 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00p\x00a\x00r\x00t\x00i\x00a\x00l\x00l\x00y\x00 \x00\\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\
+V 350113101338Z 1018 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00U\x00s\x00e\x00r\x00 \x002\x003\x00,\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e
+V 350113101450Z 1019 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x002\x004\x00,\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\
+V 350113101610Z 101A unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00U\x00s\x00e\x00r\x00 \x002\x005\x00,\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\
+V 350113101745Z 101B unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x002\x006\x00\\x00,\x00 \x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e
+V 350113101913Z 101C unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=comma, comma, comma ,
+V 350113102047Z 101D unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=equal CN=User 28
+V 350113102213Z 101E unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 29+OU=ooo
+V 350113102601Z 101F unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x003\x000\x00<\x00 \x00>\x00#\x00;\x00 \x00"\x00+\x00"
+V 350113102847Z 1020 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x003\x001\x00 \x00\\x00"\x00a\x00,\x00b\x00"\x00+\x00C\x00N\x00=\x00U\x00S\x00,\x00 \x00>\x00 \x00\\x00\\x00d\x00e\x00 \x00<
+V 350113104059Z 1021 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x001\x004\x00 \x00"\x00,\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e
+V 111108105139Z 1022 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 35
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..6efde26f7
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1000.pem
@@ -0,0 +1,57 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 14 16:11:10 2010 GMT
+ Not After : Jan 8 16:11:10 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\xC5\xB9\xC5\xBA\xC5\xBB\xC5\xBC\xC5\xBD\xC5\xBE \xEF\xAC\xB3 j\xCE\xAC\xCE\xAD\xCE\xAE
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:c5:8e:23:dc:00:60:ab:13:ac:00:15:c8:2f:13:
+ 04:4a:05:15:38:1e:ea:43:cb:68:8e:e3:08:cc:a4:
+ bb:ef:78:3e:4a:d3:3c:89:50:95:c4:16:6f:a4:89:
+ 97:4a:07:ad:17:b4:96:1e:54:87:82:ed:22:a4:15:
+ f7:cf:09:83:b7:4d:ee:75:70:8c:71:5a:b8:e7:4d:
+ 27:b4:f8:eb:19:67:8f:58:3f:4c:5f:b3:ca:aa:bd:
+ 5b:95:d7:b4:ba:d4:bc:0e:69:01:52:b9:8a:2d:55:
+ 83:9e:4d:3f:01:0c:f1:d7:bd:c9:82:54:d2:71:d6:
+ 51:9c:55:4c:a3:82:43:35:2f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ CA:DF:DA:1A:F7:9C:D8:41:19:34:69:EA:67:74:68:CA:A3:24:0F:9F
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 28:3a:db:4b:fd:15:4c:bb:ea:74:b4:53:4f:75:2a:92:3c:78:
+ b6:86:aa:39:bc:b0:67:3a:5a:00:f1:1e:74:5c:c7:2b:19:4f:
+ f4:c0:4d:ff:01:4c:b2:0f:b5:49:14:c3:9a:96:ce:61:b6:c7:
+ 37:82:44:75:76:fc:bd:5d:74:f9:22:ae:f2:36:cb:20:b7:e3:
+ c8:c8:01:ae:d5:01:f6:5e:b4:cb:ca:76:fe:72:98:f3:0a:c3:
+ ac:76:fa:41:67:b4:5c:92:67:fa:ca:17:02:80:00:d8:b6:d5:
+ 01:03:89:25:97:96:60:86:0c:0b:d8:64:94:c9:77:43:28:06:
+ f9:4e
+-----BEGIN CERTIFICATE-----
+MIIClzCCAgCgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTQxNjEx
+MTBaFw0zNTAxMDgxNjExMTBaMHExCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxITAfBgNVBAMUGMW5xbrFu8W8xb3FviDvrLMgas6szq3OrjCBnzANBgkqhkiG
+9w0BAQEFAAOBjQAwgYkCgYEAxY4j3ABgqxOsABXILxMESgUVOB7qQ8tojuMIzKS7
+73g+StM8iVCVxBZvpImXSgetF7SWHlSHgu0ipBX3zwmDt03udXCMcVq4500ntPjr
+GWePWD9MX7PKqr1blde0utS8DmkBUrmKLVWDnk0/AQzx173JglTScdZRnFVMo4JD
+NS8CAwEAAaNPME0wCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTK39oa95zYQRk0aepn
+dGjKoyQPnzAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTANBgkqhkiG
+9w0BAQUFAAOBgQAoOttL/RVMu+p0tFNPdSqSPHi2hqo5vLBnOloA8R50XMcrGU/0
+wE3/AUyyD7VJFMOals5htsc3gkR1dvy9XXT5Iq7yNssgt+PIyAGu1QH2XrTLynb+
+cpjzCsOsdvpBZ7Rckmf6yhcCgADYttUBA4kll5ZghgwL2GSUyXdDKAb5Tg==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1002.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1002.pem
new file mode 100644
index 000000000..037410ad7
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1002.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4098 (0x1002)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 18 14:44:17 2010 GMT
+ Not After : Jan 12 14:44:17 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x04\x0F\x04\x10\x04\x11\x04\x12\x04\x13\x04\x14
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:b4:d3:fd:a0:56:2b:d9:72:66:e3:fc:4b:5b:70:
+ fb:9c:23:10:0b:b9:8a:c4:d1:dd:1d:37:cd:20:f4:
+ 9d:52:c3:8f:80:14:26:c4:3e:dc:3d:af:38:86:70:
+ 2f:e1:54:1c:a6:5e:b6:6a:2d:73:b4:2d:88:7c:ed:
+ eb:63:34:bf:ef:d0:a8:e0:00:ea:f0:24:50:68:3b:
+ ff:03:4a:22:e0:eb:5c:a4:e8:65:e4:c7:e7:38:e9:
+ ce:0c:44:3e:36:08:fe:82:d8:50:b9:13:43:3b:17:
+ 77:09:ef:7b:cc:9f:b4:7d:5d:f7:ab:8e:ab:c0:11:
+ bc:7a:07:ea:98:51:c0:27:1f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 49:1F:9A:43:D9:43:B9:89:0C:00:D9:90:C8:BC:9C:67:CD:8D:3E:C6
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 2 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 03:bc:24:ba:71:8b:4f:cc:3a:60:5a:04:13:15:4e:b0:79:e7:
+ 94:6c:9b:3b:4c:5d:d8:26:75:f5:94:04:71:5a:3e:b9:8c:5f:
+ b5:3d:e0:bb:8b:64:71:8f:0d:9a:99:b8:ff:ec:14:c0:c0:ca:
+ 63:5a:4e:1d:75:77:7a:2f:fb:12:90:25:44:ba:d8:2f:03:39:
+ 86:ef:88:4a:cc:69:79:0b:ff:a6:66:83:45:08:17:0b:0c:05:
+ f9:25:7c:6a:30:05:b3:61:df:1a:fe:2c:ca:49:e9:73:bd:b3:
+ 11:6b:bf:04:b0:a6:46:76:21:40:95:5c:78:b3:aa:4b:fd:03:
+ ee:51
+-----BEGIN CERTIFICATE-----
+MIICszCCAhygAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNDQ0
+MTdaFw0zNTAxMTIxNDQ0MTdaMGUxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxFTATBgNVBAMeDAQPBBAEEQQSBBMEFDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAtNP9oFYr2XJm4/xLW3D7nCMQC7mKxNHdHTfNIPSdUsOPgBQmxD7cPa84
+hnAv4VQcpl62ai1ztC2IfO3rYzS/79Co4ADq8CRQaDv/A0oi4OtcpOhl5MfnOOnO
+DEQ+Ngj+gthQuRNDOxd3Ce97zJ+0fV33q46rwBG8egfqmFHAJx8CAwEAAaN3MHUw
+CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBRJH5pD2UO5iQwA2ZDIvJxnzY0+xjAfBgNV
+HSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTAmBgNVHREEHzAdpBswGTEXMBUG
+A1UEAxMOVXNlciAyIFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEAA7wkunGLT8w6
+YFoEExVOsHnnlGybO0xd2CZ19ZQEcVo+uYxftT3gu4tkcY8Nmpm4/+wUwMDKY1pO
+HXV3ei/7EpAlRLrYLwM5hu+ISsxpeQv/pmaDRQgXCwwF+SV8ajAFs2HfGv4syknp
+c72zEWu/BLCmRnYhQJVceLOqS/0D7lE=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1003.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1003.pem
new file mode 100644
index 000000000..95589b227
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1003.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4099 (0x1003)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 18 15:39:42 2010 GMT
+ Not After : Jan 12 15:39:42 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x01y\x01z\x01{\x00 \x03\xA6\x03\xA7\x03\xA8\x03\xA9
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:d6:d8:62:3c:69:c9:dd:93:b3:e9:65:63:89:03:
+ 4e:f8:8a:e1:8b:9d:92:c6:43:ca:8e:af:fd:6e:9c:
+ c7:66:31:48:f4:ce:5e:be:38:c5:6c:1b:48:c9:61:
+ f5:78:8a:e9:74:ac:a8:98:9c:83:f9:b0:74:e3:25:
+ 7c:5a:bb:df:5f:73:ef:fc:a0:dc:6a:ac:07:a2:b8:
+ 52:ea:7a:42:ba:9f:74:3c:00:cc:26:46:ba:90:5d:
+ 45:78:02:57:e7:47:9f:8e:94:9c:5a:31:ab:f3:ff:
+ bc:9f:7f:d9:b0:a6:f6:86:70:a6:9d:52:ff:c8:19:
+ 47:88:75:78:6a:73:d5:97:e9
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ E3:01:F6:1E:51:6D:FC:DB:BF:82:A9:12:21:4B:E2:46:FF:E8:EE:FF
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 1 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 68:f0:88:18:d5:98:63:da:42:39:47:bf:51:22:f6:0b:8e:46:
+ b0:8c:83:b0:4d:07:a4:e3:a9:66:76:4d:41:23:1a:6b:dc:d8:
+ d1:85:b1:bf:4f:f9:e6:01:4a:36:a9:a3:26:2d:0b:33:cc:36:
+ 97:c6:40:b6:77:26:1c:06:f2:1b:fa:0a:ef:5c:61:8d:0d:9c:
+ 3c:d3:0f:db:dd:60:69:8c:24:c6:70:bc:f8:3b:38:19:90:7a:
+ f3:4f:7e:7c:b7:69:b6:0f:55:e1:4b:da:77:cd:b1:fe:5f:f1:
+ c1:8a:f8:3d:26:10:3d:40:6f:83:17:0a:d8:dd:da:a1:27:10:
+ a1:73
+-----BEGIN CERTIFICATE-----
+MIICtzCCAiCgAwIBAgICEAMwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNTM5
+NDJaFw0zNTAxMTIxNTM5NDJaMGkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxGTAXBgNVBAMeEAF5AXoBewAgA6YDpwOoA6kwgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBANbYYjxpyd2Ts+llY4kDTviK4YudksZDyo6v/W6cx2YxSPTOXr44
+xWwbSMlh9XiK6XSsqJicg/mwdOMlfFq7319z7/yg3GqsB6K4Uup6QrqfdDwAzCZG
+upBdRXgCV+dHn46UnFoxq/P/vJ9/2bCm9oZwpp1S/8gZR4h1eGpz1ZfpAgMBAAGj
+dzB1MAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQU4wH2HlFt/Nu/gqkSIUviRv/o7v8w
+HwYDVR0jBBgwFoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJgYDVR0RBB8wHaQbMBkx
+FzAVBgNVBAMTDlVzZXIgMSBSb290IDExMA0GCSqGSIb3DQEBBQUAA4GBAGjwiBjV
+mGPaQjlHv1Ei9guORrCMg7BNB6TjqWZ2TUEjGmvc2NGFsb9P+eYBSjapoyYtCzPM
+NpfGQLZ3JhwG8hv6Cu9cYY0NnDzTD9vdYGmMJMZwvPg7OBmQevNPfny3abYPVeFL
+2nfNsf5f8cGK+D0mED1Ab4MXCtjd2qEnEKFz
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1004.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1004.pem
new file mode 100644
index 000000000..6f57ca684
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1004.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4100 (0x1004)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 18 16:00:38 2010 GMT
+ Not After : Jan 12 16:00:38 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00"
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:c9:ff:37:16:4d:7a:ad:59:bd:f2:c4:dc:4f:79:
+ 6a:f6:21:c7:ef:cd:af:f1:39:34:24:92:f4:46:d3:
+ 8b:43:31:55:11:3e:22:2b:85:19:38:ed:0b:35:3c:
+ 73:fc:b9:17:e8:73:99:21:a2:20:30:b4:e9:11:c6:
+ 7a:61:fa:fa:fe:eb:c8:30:c4:73:5f:77:f2:fc:42:
+ b7:10:29:ac:9e:8a:c2:df:25:9b:44:17:05:a3:39:
+ d9:1b:58:62:fb:2c:86:07:f7:f0:28:7b:5a:38:1b:
+ 6a:de:88:fb:ad:32:f4:53:e2:a1:c5:0f:68:db:64:
+ ae:39:2a:5e:02:d0:b5:38:07
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 86:2F:46:D0:A9:F9:3F:22:BD:57:83:51:35:F9:67:11:A2:00:AB:33
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 3 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ bb:f6:61:ae:30:94:3a:4a:d6:d5:cb:b5:50:bb:ca:0e:ab:9f:
+ 09:e9:78:d4:2f:20:fe:18:4e:d8:61:db:97:28:a9:d9:dc:e5:
+ 06:f8:6c:41:c2:5a:95:53:47:7e:a7:73:c9:45:4f:6b:30:fc:
+ fd:17:9a:7b:a9:d8:27:57:a9:fd:8d:e7:7e:4b:3e:98:11:42:
+ 00:39:1a:55:4b:3d:a5:de:75:3c:43:5a:33:10:d3:cf:4e:04:
+ 0a:71:d4:93:2b:0b:2b:15:82:7b:04:46:9b:50:da:18:84:66:
+ 31:75:36:5b:09:eb:82:5d:7d:e1:35:a3:a4:6c:b2:ac:c8:fa:
+ bd:5f
+-----BEGIN CERTIFICATE-----
+MIICyzCCAjSgAwIBAgICEAQwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjAw
+MzhaFw0zNTAxMTIxNjAwMzhaMH0xCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxLTArBgNVBAMeJAAiAGUAbgBjAGwAbwBzAGkAbgBnACAAcQB1AG8AdABlAHMA
+IjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyf83Fk16rVm98sTcT3lq9iHH
+782v8Tk0JJL0RtOLQzFVET4iK4UZOO0LNTxz/LkX6HOZIaIgMLTpEcZ6Yfr6/uvI
+MMRzX3fy/EK3ECmsnorC3yWbRBcFoznZG1hi+yyGB/fwKHtaOBtq3oj7rTL0U+Kh
+xQ9o22SuOSpeAtC1OAcCAwEAAaN3MHUwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBSG
+L0bQqfk/Ir1Xg1E1+WcRogCrMzAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPm
+vremVTAmBgNVHREEHzAdpBswGTEXMBUGA1UEAxMOVXNlciAzIFJvb3QgMTEwDQYJ
+KoZIhvcNAQEFBQADgYEAu/ZhrjCUOkrW1cu1ULvKDqufCel41C8g/hhO2GHblyip
+2dzlBvhsQcJalVNHfqdzyUVPazD8/Reae6nYJ1ep/Y3nfks+mBFCADkaVUs9pd51
+PENaMxDTz04ECnHUkysLKxWCewRGm1DaGIRmMXU2Wwnrgl194TWjpGyyrMj6vV8=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1005.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1005.pem
new file mode 100644
index 000000000..3a2f7522d
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1005.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4101 (0x1005)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 18 16:05:47 2010 GMT
+ Not After : Jan 12 16:05:47 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00"\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00"\x00"
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:de:4d:31:93:c5:1b:7c:2b:85:86:da:89:3d:06:
+ 6f:6d:44:a5:de:6c:6a:06:28:b0:96:7b:40:34:01:
+ af:e4:b1:f4:93:f1:25:78:b0:43:ea:92:2a:87:60:
+ e8:be:7e:c9:b6:02:f8:14:93:1b:b8:5f:cb:2c:24:
+ e2:80:24:f0:5c:6d:77:f2:dc:ef:90:d6:d1:78:22:
+ 53:f0:7f:45:ad:f2:1a:9d:25:08:13:c8:62:6b:9e:
+ 88:79:3d:9e:b4:0a:05:11:79:7d:a1:b2:46:89:f3:
+ 45:ce:f3:22:2e:17:ab:e1:a9:b1:04:93:3b:f3:ca:
+ e6:60:c0:fd:91:7f:34:80:65
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ C1:6E:6A:FB:5A:B1:0C:67:07:C8:7E:F1:8D:86:F6:D0:27:56:6D:73
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 4 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 61:72:4b:33:1d:60:91:08:19:4f:ff:ec:8e:9e:83:71:d7:00:
+ 96:0a:b5:82:b7:8c:a6:3f:70:64:36:ac:25:a7:f1:a9:83:f1:
+ 63:f8:29:06:fa:58:86:8a:fd:25:9e:77:38:dd:c7:3b:cd:68:
+ 91:8e:f4:57:42:c9:6b:88:87:ec:24:57:38:84:fb:c0:d9:bc:
+ 6c:1c:6e:9d:9d:b9:da:cc:7e:fe:f9:bd:29:be:14:26:6f:63:
+ 1f:6f:6a:f1:dd:fd:d2:03:69:f2:36:e1:35:e0:57:72:d5:e3:
+ 09:ee:6a:08:45:b4:73:e9:d1:18:c2:38:1d:86:53:53:6d:bf:
+ f0:1e
+-----BEGIN CERTIFICATE-----
+MIIC3jCCAkegAwIBAgICEAUwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjA1
+NDdaFw0zNTAxMTIxNjA1NDdaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MT8wPQYDVQQDHjYAIgAiAGQAbwB1AGIAbABlACAAZQBuAGMAbABvAHMAaQBu
+AGcAIABxAHUAbwB0AGUAcwAiACIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
+AN5NMZPFG3wrhYbaiT0Gb21Epd5sagYosJZ7QDQBr+Sx9JPxJXiwQ+qSKodg6L5+
+ybYC+BSTG7hfyywk4oAk8Fxtd/Lc75DW0XgiU/B/Ra3yGp0lCBPIYmueiHk9nrQK
+BRF5faGyRonzRc7zIi4Xq+GpsQSTO/PK5mDA/ZF/NIBlAgMBAAGjdzB1MAsGA1Ud
+DwQEAwIF4DAdBgNVHQ4EFgQUwW5q+1qxDGcHyH7xjYb20CdWbXMwHwYDVR0jBBgw
+FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJgYDVR0RBB8wHaQbMBkxFzAVBgNVBAMT
+DlVzZXIgNCBSb290IDExMA0GCSqGSIb3DQEBBQUAA4GBAGFySzMdYJEIGU//7I6e
+g3HXAJYKtYK3jKY/cGQ2rCWn8amD8WP4KQb6WIaK/SWedzjdxzvNaJGO9FdCyWuI
+h+wkVziE+8DZvGwcbp2dudrMfv75vSm+FCZvYx9vavHd/dIDafI24TXgV3LV4wnu
+aghFtHPp0RjCOB2GU1Ntv/Ae
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1006.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1006.pem
new file mode 100644
index 000000000..cb72b8d16
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1006.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4102 (0x1006)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 18 16:09:21 2010 GMT
+ Not After : Jan 12 16:09:21 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00"\x00t\x00w\x00o\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00o\x00n\x00e\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00"
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:d1:a4:91:c7:28:84:f8:54:63:09:1f:bc:2e:4e:
+ a3:be:54:01:42:2e:f7:ef:4f:b8:46:a9:35:b1:b3:
+ 29:0e:8b:f7:b5:fa:b7:71:5b:33:03:ac:e6:b5:f6:
+ ba:f5:ba:21:72:ed:7d:ea:f0:f1:2c:55:2a:a9:c6:
+ d8:54:ef:12:f0:f5:37:ca:57:b2:3c:ce:7c:5a:57:
+ 86:68:a2:51:82:80:bd:58:a5:04:1c:e8:cf:f6:5b:
+ 4e:d2:6a:79:63:eb:ac:52:7c:61:8c:fe:0a:6b:b2:
+ f6:16:9c:94:ae:a6:f6:69:b9:d5:0b:26:0d:01:7f:
+ 62:d2:58:c2:02:53:25:63:0d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 45:DF:D7:35:D1:13:E4:8F:E3:0D:E3:7E:A9:9A:5D:56:00:64:4E:43
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 5 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 9d:bd:dc:dc:8e:a8:e8:e4:15:cb:14:c1:6a:ab:d8:ab:e6:e5:
+ 4f:f5:a8:8b:2c:ab:80:e2:31:f9:89:d8:12:ba:9c:4f:b3:f5:
+ bb:7e:ee:8b:df:58:d3:b2:ee:f8:c5:46:c3:5d:2e:a9:35:d0:
+ 7a:1e:80:18:14:4d:78:6e:f1:c8:9a:51:db:86:3e:2c:04:4a:
+ 0a:2f:f1:7a:01:e3:1b:31:d7:1d:f1:32:c4:04:db:b9:7e:c4:
+ fd:b0:c1:41:3f:8a:b3:88:4f:4a:9c:a6:38:11:2a:4a:0f:8b:
+ d0:9a:8a:2c:33:fe:7f:42:b5:93:8d:54:df:de:2b:b1:08:5c:
+ d9:0d
+-----BEGIN CERTIFICATE-----
+MIIC6DCCAlGgAwIBAgICEAYwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjA5
+MjFaFw0zNTAxMTIxNjA5MjFaMIGZMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MUkwRwYDVQQDHkAAIgAiAHQAdwBvACAAcwB0AGEAcgB0AGkAbgBnACAAbwBu
+AGUAIABlAG4AZABpAG4AZwAgAHEAdQBvAHQAZQAiMIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDRpJHHKIT4VGMJH7wuTqO+VAFCLvfvT7hGqTWxsykOi/e1+rdx
+WzMDrOa19rr1uiFy7X3q8PEsVSqpxthU7xLw9TfKV7I8znxaV4ZoolGCgL1YpQQc
+6M/2W07Sanlj66xSfGGM/gprsvYWnJSupvZpudULJg0Bf2LSWMICUyVjDQIDAQAB
+o3cwdTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFEXf1zXRE+SP4w3jfqmaXVYAZE5D
+MB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCYGA1UdEQQfMB2kGzAZ
+MRcwFQYDVQQDEw5Vc2VyIDUgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQCdvdzc
+jqjo5BXLFMFqq9ir5uVP9aiLLKuA4jH5idgSupxPs/W7fu6L31jTsu74xUbDXS6p
+NdB6HoAYFE14bvHImlHbhj4sBEoKL/F6AeMbMdcd8TLEBNu5fsT9sMFBP4qziE9K
+nKY4ESpKD4vQmoosM/5/QrWTjVTf3iuxCFzZDQ==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1007.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1007.pem
new file mode 100644
index 000000000..ce9b36d12
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1007.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4103 (0x1007)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 18 16:11:53 2010 GMT
+ Not After : Jan 12 16:11:53 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:d1:99:9c:20:2e:65:ee:0f:ce:cb:8a:d8:70:c8:
+ 04:3c:ac:2f:14:7c:6c:8f:5e:95:36:f8:53:74:5b:
+ 88:bf:a1:43:73:04:ab:3a:42:b4:7c:2c:3c:3b:63:
+ 7e:ef:82:c5:bb:b1:28:9b:8b:b7:29:72:3d:30:08:
+ e9:a2:d7:4b:08:e2:2e:e6:d4:9f:75:29:31:23:be:
+ b4:30:5d:94:30:41:38:a1:d5:34:bc:69:f5:d8:8d:
+ c6:08:cc:28:4a:92:22:2b:19:89:f5:ad:7c:49:89:
+ b3:63:c6:e5:6c:86:d7:62:05:1b:97:db:2d:fb:c2:
+ 47:e5:51:a6:f0:50:6f:e3:53
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 5F:DA:34:F6:6F:BA:9E:12:99:DC:02:2A:4C:3E:8C:0D:14:A1:9B:2B
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 6 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 24:af:11:b6:1a:5c:d1:bf:70:93:85:c0:2e:10:96:4d:b7:ad:
+ 4e:d7:c4:7e:87:a1:3b:20:d7:bf:04:07:cc:91:13:0c:ad:66:
+ 08:d6:2e:b6:d0:aa:d0:45:0e:c0:92:3d:7c:a6:82:19:04:3c:
+ 9a:b3:5e:e8:fe:9e:5c:d6:17:75:73:e3:3c:64:0c:ae:5d:92:
+ 2a:eb:0e:ef:04:f5:ce:a5:7f:1f:2f:1d:05:a0:70:f4:24:80:
+ c3:38:35:2d:e5:ac:a7:11:4a:3e:a2:b2:d1:14:91:ba:b0:d8:
+ 5f:be:80:8a:34:2c:72:fb:00:47:88:47:9e:34:65:12:ad:9f:
+ ff:99
+-----BEGIN CERTIFICATE-----
+MIICxTCCAi6gAwIBAgICEAcwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjEx
+NTNaFw0zNTAxMTIxNjExNTNaMHcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxJzAlBgNVBAMeHgAiAHMAdABhAHIAdABpAG4AZwAgAHEAdQBvAHQAZTCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0ZmcIC5l7g/Oy4rYcMgEPKwvFHxsj16V
+NvhTdFuIv6FDcwSrOkK0fCw8O2N+74LFu7Eom4u3KXI9MAjpotdLCOIu5tSfdSkx
+I760MF2UMEE4odU0vGn12I3GCMwoSpIiKxmJ9a18SYmzY8blbIbXYgUbl9st+8JH
+5VGm8FBv41MCAwEAAaN3MHUwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBRf2jT2b7qe
+EpncAipMPowNFKGbKzAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTAm
+BgNVHREEHzAdpBswGTEXMBUGA1UEAxMOVXNlciA2IFJvb3QgMTEwDQYJKoZIhvcN
+AQEFBQADgYEAJK8Rthpc0b9wk4XALhCWTbetTtfEfoehOyDXvwQHzJETDK1mCNYu
+ttCq0EUOwJI9fKaCGQQ8mrNe6P6eXNYXdXPjPGQMrl2SKusO7wT1zqV/Hy8dBaBw
+9CSAwzg1LeWspxFKPqKy0RSRurDYX76AijQscvsAR4hHnjRlEq2f/5k=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1008.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1008.pem
new file mode 100644
index 000000000..8d6f2bd25
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1008.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4104 (0x1008)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 18 16:14:05 2010 GMT
+ Not After : Jan 12 16:14:05 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00"
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:a6:a8:3f:60:a7:9a:3b:20:c9:2c:8c:4f:cd:11:
+ 1f:0d:a9:2a:2c:eb:12:80:0c:55:8a:4d:06:ef:b2:
+ 5f:2e:47:be:0d:10:22:8a:15:57:29:4a:90:63:f9:
+ 1c:13:85:47:c7:c9:b9:76:09:10:a9:b1:94:5c:8d:
+ c9:f4:01:26:43:e4:d4:98:d6:00:1a:d4:cd:2a:d1:
+ cd:7e:4c:4e:ab:18:78:5a:fb:b2:ec:a3:87:a1:0e:
+ 84:3f:70:cf:ca:02:24:c8:d7:1b:83:a3:ac:a5:f0:
+ 10:c5:de:b7:a2:6c:0b:0c:9d:ab:32:a3:1a:c9:ae:
+ 9b:48:a8:65:cd:50:db:0b:cf
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 91:32:56:26:62:63:A1:32:B0:BC:D0:91:F1:D8:F2:94:CB:10:F1:91
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 7 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 4c:d5:2f:ab:fb:83:f8:11:c9:d2:df:aa:dc:e9:b8:38:2e:53:
+ e1:3a:5b:bb:0a:bf:72:f7:47:b5:57:de:82:8a:e6:bb:7d:62:
+ af:1b:9c:8e:4a:f5:cf:0b:ac:e9:06:16:ca:59:f1:7f:d7:45:
+ c0:88:84:ee:f4:c7:8b:e0:39:aa:c7:b7:95:b9:fe:a2:4a:3a:
+ 41:df:d0:02:bf:6f:54:30:9a:9a:0a:a6:04:5f:f4:17:52:d6:
+ c2:39:43:5e:b9:a3:86:0f:3d:ad:eb:a3:81:f4:cc:90:29:17:
+ dc:46:5e:6b:9c:f6:70:0f:b2:0f:dc:0f:9c:9f:09:6c:fa:31:
+ 6c:01
+-----BEGIN CERTIFICATE-----
+MIICwTCCAiqgAwIBAgICEAgwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjE0
+MDVaFw0zNTAxMTIxNjE0MDVaMHMxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxIzAhBgNVBAMeGgBlAG4AZABpAG4AZwAgAHEAdQBvAHQAZQAiMIGfMA0GCSqG
+SIb3DQEBAQUAA4GNADCBiQKBgQCmqD9gp5o7IMksjE/NER8NqSos6xKADFWKTQbv
+sl8uR74NECKKFVcpSpBj+RwThUfHybl2CRCpsZRcjcn0ASZD5NSY1gAa1M0q0c1+
+TE6rGHha+7Lso4ehDoQ/cM/KAiTI1xuDo6yl8BDF3reibAsMnasyoxrJrptIqGXN
+UNsLzwIDAQABo3cwdTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJEyViZiY6EysLzQ
+kfHY8pTLEPGRMB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCYGA1Ud
+EQQfMB2kGzAZMRcwFQYDVQQDEw5Vc2VyIDcgUm9vdCAxMTANBgkqhkiG9w0BAQUF
+AAOBgQBM1S+r+4P4EcnS36rc6bg4LlPhOlu7Cr9y90e1V96Ciua7fWKvG5yOSvXP
+C6zpBhbKWfF/10XAiITu9MeL4Dmqx7eVuf6iSjpB39ACv29UMJqaCqYEX/QXUtbC
+OUNeuaOGDz2t66OB9MyQKRfcRl5rnPZwD7IP3A+cnwls+jFsAQ==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1009.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1009.pem
new file mode 100644
index 000000000..c1a94dae5
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1009.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4105 (0x1009)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 18 16:16:31 2010 GMT
+ Not After : Jan 12 16:16:31 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00"\x00q\x00u\x00o\x00t\x00e
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:b4:3b:c7:b0:6c:b5:f2:b3:a5:79:89:54:de:af:
+ 03:3c:0e:c9:57:15:8e:73:2a:48:83:18:59:ce:b4:
+ 12:fb:5c:92:28:69:75:18:f9:0f:24:15:95:38:b2:
+ 4c:81:07:90:97:3b:d7:3a:ab:a6:92:5a:9f:5a:1f:
+ fe:14:ac:4d:b5:5e:6a:a6:0f:98:55:08:07:09:07:
+ a5:fb:79:9e:a0:2d:73:99:92:ad:6e:bc:75:36:d0:
+ b5:f1:1c:91:3a:d4:49:8a:60:1e:a7:01:2f:bc:d9:
+ cd:b4:f4:70:b4:38:d1:3c:d3:ee:00:df:b3:83:45:
+ 63:5c:5d:28:47:bc:b1:b9:57
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ D6:18:38:7B:14:4B:D6:72:42:A9:53:E2:1D:BE:81:88:26:DB:0A:06
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 8 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 98:f3:ac:db:7b:a0:00:d2:58:be:74:21:ff:09:29:4c:0c:1a:
+ 7a:1f:dd:e2:f3:f4:9a:52:5d:da:ac:10:30:f9:b8:93:10:60:
+ 46:bf:48:47:bd:af:87:a1:d9:c6:46:81:b3:0d:a4:f8:ba:ca:
+ 17:7c:f2:f9:46:03:62:7f:32:6b:f0:7c:75:a4:05:44:cb:10:
+ 42:36:ce:12:c0:b9:e5:5f:e0:7b:c6:c8:39:5c:0c:50:30:a0:
+ f6:fe:e1:a2:e6:00:b3:fc:86:56:11:66:d8:41:81:e3:4e:15:
+ e5:68:9d:1c:b0:c4:4f:ab:86:75:55:fa:39:58:3f:7c:68:03:
+ e0:76
+-----BEGIN CERTIFICATE-----
+MIICwTCCAiqgAwIBAgICEAkwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjE2
+MzFaFw0zNTAxMTIxNjE2MzFaMHMxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxIzAhBgNVBAMeGgBtAGkAZABkAGwAZQAgACIAcQB1AG8AdABlMIGfMA0GCSqG
+SIb3DQEBAQUAA4GNADCBiQKBgQC0O8ewbLXys6V5iVTerwM8DslXFY5zKkiDGFnO
+tBL7XJIoaXUY+Q8kFZU4skyBB5CXO9c6q6aSWp9aH/4UrE21XmqmD5hVCAcJB6X7
+eZ6gLXOZkq1uvHU20LXxHJE61EmKYB6nAS+82c209HC0ONE80+4A37ODRWNcXShH
+vLG5VwIDAQABo3cwdTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFNYYOHsUS9ZyQqlT
+4h2+gYgm2woGMB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCYGA1Ud
+EQQfMB2kGzAZMRcwFQYDVQQDEw5Vc2VyIDggUm9vdCAxMTANBgkqhkiG9w0BAQUF
+AAOBgQCY86zbe6AA0li+dCH/CSlMDBp6H93i8/SaUl3arBAw+biTEGBGv0hHva+H
+odnGRoGzDaT4usoXfPL5RgNifzJr8Hx1pAVEyxBCNs4SwLnlX+B7xsg5XAxQMKD2
+/uGi5gCz/IZWEWbYQYHjThXlaJ0csMRPq4Z1Vfo5WD98aAPgdg==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100A.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100A.pem
new file mode 100644
index 000000000..a3a79bf83
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100A.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4106 (0x100a)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 18 16:18:57 2010 GMT
+ Not After : Jan 12 16:18:57 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00"\x00"\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:e5:3f:d4:e1:d6:26:2a:c9:40:1d:34:3c:1e:e8:
+ f4:54:67:6b:6c:a5:b7:fe:04:bb:cb:0e:c0:2d:26:
+ 61:c1:81:80:9d:da:1b:fd:d3:7a:7a:57:78:c5:f6:
+ e6:4b:ad:2d:a2:8d:49:b3:ac:18:ca:1c:25:67:44:
+ 7c:8e:b5:ab:ec:f7:a8:da:b7:37:ed:77:76:b2:8f:
+ bb:15:b2:e3:45:5f:b2:2a:aa:27:b7:f1:bc:37:8f:
+ b7:b4:c5:ff:45:fd:67:04:25:47:2c:1a:a7:63:1e:
+ 97:f6:ac:d7:39:cf:ef:24:63:a1:87:9b:36:97:92:
+ fa:d9:4d:a9:fa:dd:c9:fb:75
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 62:F1:43:E3:B1:7B:98:0D:69:A4:8F:CF:32:F7:6D:E6:88:D6:23:90
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 9 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ ab:46:88:13:e8:02:63:4e:f2:a0:5a:48:7e:35:a4:c2:f8:55:
+ 33:cb:ef:45:55:30:81:a1:9e:c2:c7:43:cd:19:23:1f:df:3f:
+ 8b:b8:7e:69:5e:98:06:b1:47:dd:e5:05:e2:3a:19:cf:af:e3:
+ dd:7b:75:e5:53:b0:bc:4e:58:40:bf:3b:d2:9c:7f:9e:b1:66:
+ f8:3f:58:c4:5f:ab:be:1f:03:fb:89:47:a4:25:8a:1e:10:e0:
+ 20:33:70:07:13:92:32:e1:bf:92:6a:d5:89:03:2c:ad:e1:85:
+ 8c:b3:1d:ee:0c:35:70:2f:aa:e5:e0:77:97:b0:9b:a3:0d:22:
+ 6f:dc
+-----BEGIN CERTIFICATE-----
+MIIC0jCCAjugAwIBAgICEAowDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjE4
+NTdaFw0zNTAxMTIxNjE4NTdaMIGDMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MTMwMQYDVQQDHioAZABvAHUAYgBsAGUAIAAiACIAbQBpAGQAZABsAGUAIABx
+AHUAbwB0AGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOU/1OHWJirJQB00
+PB7o9FRna2ylt/4Eu8sOwC0mYcGBgJ3aG/3TenpXeMX25kutLaKNSbOsGMocJWdE
+fI61q+z3qNq3N+13drKPuxWy40VfsiqqJ7fxvDePt7TF/0X9ZwQlRywap2Mel/as
+1znP7yRjoYebNpeS+tlNqfrdyft1AgMBAAGjdzB1MAsGA1UdDwQEAwIF4DAdBgNV
+HQ4EFgQUYvFD47F7mA1ppI/PMvdt5ojWI5AwHwYDVR0jBBgwFoAU6Gq7wpDqbHAi
+Pvb2SBsD5r63plUwJgYDVR0RBB8wHaQbMBkxFzAVBgNVBAMTDlVzZXIgOSBSb290
+IDExMA0GCSqGSIb3DQEBBQUAA4GBAKtGiBPoAmNO8qBaSH41pML4VTPL70VVMIGh
+nsLHQ80ZIx/fP4u4fmlemAaxR93lBeI6Gc+v4917deVTsLxOWEC/O9Kcf56xZvg/
+WMRfq74fA/uJR6Qlih4Q4CAzcAcTkjLhv5Jq1YkDLK3hhYyzHe4MNXAvquXgd5ew
+m6MNIm/c
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100B.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100B.pem
new file mode 100644
index 000000000..75684732d
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100B.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4107 (0x100b)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 09:02:37 2010 GMT
+ Not After : Jan 13 09:02:37 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00p\x00a\x00r\x00t\x00i\x00a\x00l\x00l\x00y\x00 \x00"\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00"
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:ae:9f:8e:b8:88:8e:ed:53:aa:2a:2c:ed:f1:6c:
+ 99:47:9f:ab:8b:4e:8e:d8:2e:c2:78:2c:54:f9:29:
+ 14:27:b9:6a:3c:33:3f:06:51:ba:76:15:0a:16:60:
+ db:f2:f0:db:af:5b:38:be:18:42:b4:31:02:ba:6f:
+ 19:00:57:be:d0:f3:7c:6b:34:36:e8:7c:45:77:0d:
+ f5:d0:7c:0e:23:64:7c:59:02:5c:54:15:71:82:be:
+ 98:3f:c9:2d:f0:9e:d5:f0:32:02:44:61:5b:2f:71:
+ 16:13:9a:b3:2b:28:ff:d5:d8:3d:00:9c:eb:ec:b7:
+ 04:e2:b6:15:42:45:e5:ef:3f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 8C:2C:B6:8B:82:43:DC:41:EC:AC:D4:75:E8:DA:D8:3F:A9:A0:F5:31
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 10 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 48:a6:51:46:5b:44:a5:be:18:ed:8f:d4:c6:d2:3c:86:8f:e7:
+ e5:f4:a2:5d:51:aa:00:9b:bc:d8:b1:d3:f4:24:a0:a1:0d:80:
+ 2e:7e:62:26:ee:8c:4b:bd:79:0c:39:bd:6e:af:db:92:b6:03:
+ b1:b0:49:95:a7:59:28:54:30:33:fc:7e:2f:0f:a2:ce:90:27:
+ 29:b9:d8:3f:99:36:e9:81:9f:f5:fa:cb:f9:f2:05:b5:48:60:
+ 4d:50:4d:1e:ba:45:fd:f1:99:84:a6:79:0b:6b:76:eb:73:9d:
+ 5c:47:27:be:0d:23:0b:97:cc:9d:5a:80:fa:9b:ff:66:e7:37:
+ 60:a4
+-----BEGIN CERTIFICATE-----
+MIIC3zCCAkigAwIBAgICEAswDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTAy
+MzdaFw0zNTAxMTMwOTAyMzdaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MT8wPQYDVQQDHjYAcABhAHIAdABpAGEAbABsAHkAIAAiAGUAbgBjAGwAbwBz
+AGkAbgBnACAAcQB1AG8AdABlACIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
+AK6fjriIju1Tqios7fFsmUefq4tOjtguwngsVPkpFCe5ajwzPwZRunYVChZg2/Lw
+269bOL4YQrQxArpvGQBXvtDzfGs0Nuh8RXcN9dB8DiNkfFkCXFQVcYK+mD/JLfCe
+1fAyAkRhWy9xFhOasyso/9XYPQCc6+y3BOK2FUJF5e8/AgMBAAGjeDB2MAsGA1Ud
+DwQEAwIF4DAdBgNVHQ4EFgQUjCy2i4JD3EHsrNR16NrYP6mg9TEwHwYDVR0jBBgw
+FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMT
+D1VzZXIgMTAgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQBIplFGW0Slvhjtj9TG
+0jyGj+fl9KJdUaoAm7zYsdP0JKChDYAufmIm7oxLvXkMOb1ur9uStgOxsEmVp1ko
+VDAz/H4vD6LOkCcpudg/mTbpgZ/1+sv58gW1SGBNUE0eukX98ZmEpnkLa3brc51c
+Rye+DSMLl8ydWoD6m/9m5zdgpA==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100C.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100C.pem
new file mode 100644
index 000000000..115190ca6
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100C.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4108 (0x100c)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 09:48:52 2010 GMT
+ Not After : Jan 13 09:48:52 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00U\x00s\x00e\x00r\x00 \x001\x001\x00,\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:e2:8b:a9:94:06:b0:cb:e7:1b:a3:fd:7c:70:d1:
+ 66:e6:2d:aa:c7:ec:2e:e3:08:c3:39:3f:48:47:fd:
+ 09:67:2d:16:17:87:c0:e3:4d:c1:cc:6b:3f:c4:7b:
+ 74:d5:71:70:d6:74:8a:a2:17:fd:39:78:f8:c7:b3:
+ 42:54:ac:f7:07:d7:6f:55:da:03:15:11:e0:c2:d8:
+ 95:d2:87:c3:9c:3d:94:96:9d:01:81:5d:61:43:aa:
+ 4c:92:d5:68:aa:6c:73:88:52:7b:ee:9b:76:65:0d:
+ 2a:ae:3d:83:71:41:44:8b:23:7d:a6:f9:3c:81:56:
+ 6c:9b:52:96:87:c8:97:18:8d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 48:89:BE:3C:AA:C9:5A:38:6B:CA:FA:C8:B2:BB:F7:E1:44:4B:7B:08
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 11 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 23:c9:5b:f5:9f:59:ff:97:0b:79:35:2d:32:db:b7:4b:b1:c9:
+ 2b:1e:cf:88:7b:b4:4e:f0:ed:13:a3:64:85:8f:d6:70:b5:ed:
+ 2a:57:92:a0:b4:14:96:48:7a:aa:a4:19:59:df:d9:a9:0f:86:
+ a3:e5:ec:b5:67:ef:c3:ee:23:dd:c3:3e:24:86:6c:09:03:59:
+ ab:93:d6:c7:0a:4c:ef:c5:4a:be:d6:ff:0f:2e:81:8e:18:d5:
+ 44:21:3a:0e:86:04:aa:86:8a:38:1e:d6:07:75:d0:08:be:ef:
+ 29:7d:d2:fc:85:8d:0c:d3:bd:ea:47:be:40:bb:fa:2f:29:fc:
+ c6:d8
+-----BEGIN CERTIFICATE-----
+MIIC2TCCAkKgAwIBAgICEAwwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTQ4
+NTJaFw0zNTAxMTMwOTQ4NTJaMIGJMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MTkwNwYDVQQDHjAAIgBVAHMAZQByACAAMQAxACwAIABzAHQAYQByAHQAaQBu
+AGcAIABxAHUAbwB0AGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOKLqZQG
+sMvnG6P9fHDRZuYtqsfsLuMIwzk/SEf9CWctFheHwONNwcxrP8R7dNVxcNZ0iqIX
+/Tl4+MezQlSs9wfXb1XaAxUR4MLYldKHw5w9lJadAYFdYUOqTJLVaKpsc4hSe+6b
+dmUNKq49g3FBRIsjfab5PIFWbJtSlofIlxiNAgMBAAGjeDB2MAsGA1UdDwQEAwIF
+4DAdBgNVHQ4EFgQUSIm+PKrJWjhryvrIsrv34URLewgwHwYDVR0jBBgwFoAU6Gq7
+wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMTD1VzZXIg
+MTEgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQAjyVv1n1n/lwt5NS0y27dLsckr
+Hs+Ie7RO8O0To2SFj9Zwte0qV5KgtBSWSHqqpBlZ39mpD4aj5ey1Z+/D7iPdwz4k
+hmwJA1mrk9bHCkzvxUq+1v8PLoGOGNVEIToOhgSqhoo4HtYHddAIvu8pfdL8hY0M
+073qR75Au/ovKfzG2A==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100D.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100D.pem
new file mode 100644
index 000000000..95e419a17
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100D.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4109 (0x100d)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 09:51:10 2010 GMT
+ Not After : Jan 13 09:51:10 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x001\x002\x00,\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00"
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:bf:4f:93:6b:6b:86:76:30:31:3b:0e:eb:b7:a6:
+ b9:a3:3e:84:ea:d5:31:50:5a:df:f4:3f:67:11:5a:
+ a5:28:23:58:37:67:a5:5c:72:6d:f2:fc:80:81:55:
+ 78:86:28:e9:60:c2:0a:d0:17:3c:3a:e9:a8:01:71:
+ 64:b8:27:f4:42:e0:d7:69:f5:4e:ef:14:07:69:fd:
+ de:7b:af:c8:a4:0c:9c:56:00:8b:76:67:d1:ba:a9:
+ e7:40:63:77:da:44:d3:89:5c:a7:5a:ea:d5:f3:9b:
+ 15:43:f3:08:2d:bc:8a:bf:4a:5b:57:01:f0:c7:97:
+ fe:b0:93:b2:1b:79:a0:4e:ad
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 0A:A2:A6:09:88:23:56:82:9E:60:8B:79:23:61:CA:BF:D4:F7:ED:A9
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 12 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 64:3e:b6:a6:5e:0d:6f:b3:e7:f6:c7:1f:4a:48:96:4c:fe:13:
+ 3c:4a:7b:e7:46:51:56:45:66:02:e4:79:1a:7f:15:a4:e9:5b:
+ f7:4c:68:cf:cf:b0:7b:e2:ba:57:37:23:c6:cd:ba:75:85:e8:
+ eb:d5:ca:a2:6d:9a:75:84:4b:7b:47:38:58:bc:0a:4b:cc:2c:
+ 2a:0d:eb:7e:ac:36:6f:0b:a5:26:b7:d3:0b:0f:e7:cc:26:db:
+ bb:01:48:5b:38:49:f5:3e:2d:75:c0:d6:11:ad:3e:a0:b6:8a:
+ 8e:7f:4d:10:2c:7b:d7:03:0d:de:da:6b:e0:07:06:90:73:1f:
+ dd:f1
+-----BEGIN CERTIFICATE-----
+MIIC1TCCAj6gAwIBAgICEA0wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTUx
+MTBaFw0zNTAxMTMwOTUxMTBaMIGFMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MTUwMwYDVQQDHiwAVQBzAGUAcgAgADEAMgAsACAAZQBuAGQAaQBuAGcAIABx
+AHUAbwB0AGUAIjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAv0+Ta2uGdjAx
+Ow7rt6a5oz6E6tUxUFrf9D9nEVqlKCNYN2elXHJt8vyAgVV4hijpYMIK0Bc8Oumo
+AXFkuCf0QuDXafVO7xQHaf3ee6/IpAycVgCLdmfRuqnnQGN32kTTiVynWurV85sV
+Q/MILbyKv0pbVwHwx5f+sJOyG3mgTq0CAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0G
+A1UdDgQWBBQKoqYJiCNWgp5gi3kjYcq/1PftqTAfBgNVHSMEGDAWgBToarvCkOps
+cCI+9vZIGwPmvremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAxMiBS
+b290IDExMA0GCSqGSIb3DQEBBQUAA4GBAGQ+tqZeDW+z5/bHH0pIlkz+EzxKe+dG
+UVZFZgLkeRp/FaTpW/dMaM/PsHviulc3I8bNunWF6OvVyqJtmnWES3tHOFi8CkvM
+LCoN636sNm8LpSa30wsP58wm27sBSFs4SfU+LXXA1hGtPqC2io5/TRAse9cDDd7a
+a+AHBpBzH93x
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100E.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100E.pem
new file mode 100644
index 000000000..f91766a0a
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100E.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4110 (0x100e)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 09:53:08 2010 GMT
+ Not After : Jan 13 09:53:08 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00U\x00s\x00e\x00r\x00 \x001\x003\x00,\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00"
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:e0:b2:b3:77:34:32:23:3c:45:ce:1f:5f:9a:60:
+ c5:59:af:2f:bf:73:8e:be:3d:88:8d:97:4f:fe:8a:
+ 00:b9:71:7f:07:3a:1e:6a:5b:37:8a:ff:58:8f:f1:
+ b3:e5:0b:9d:35:58:57:6d:da:d1:15:cd:52:7f:e2:
+ 15:25:16:d4:d6:1e:71:a6:f3:f7:c5:6d:01:64:fc:
+ 20:d4:4e:6a:f2:f9:b9:2a:36:f8:ae:e6:17:a8:f9:
+ 8e:7c:bb:75:e5:24:39:ad:4c:18:c8:bb:07:22:cd:
+ d1:a6:52:93:7f:24:5f:90:dd:0f:64:07:70:42:67:
+ 39:9b:1f:ea:5e:bb:cd:df:ab
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 75:49:D0:1F:A0:B3:A2:C6:F2:7F:CF:16:A3:4C:4B:DF:D6:4C:07:9D
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 13 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 5d:60:60:06:aa:8a:2d:ee:20:2a:ee:fb:b5:99:8c:ed:d8:67:
+ 28:30:d8:26:a7:e0:1c:6e:5d:e1:4c:5e:c8:f9:02:e2:2e:c4:
+ 1e:58:e9:84:bc:d7:79:4e:d5:c5:ea:ba:74:aa:4e:30:9d:2b:
+ 98:c8:0b:fe:7f:eb:fb:e9:24:5f:f8:17:27:a9:ce:7c:ff:4b:
+ 88:15:3e:25:18:71:73:bf:b6:bf:c5:51:6b:1d:db:32:1d:ae:
+ 00:bf:ed:a5:65:99:16:43:8d:d2:6d:27:53:fc:65:9a:91:94:
+ 7b:44:c8:58:a1:f1:2b:95:86:0b:2d:2d:94:10:6f:5e:be:f8:
+ 7b:8e
+-----BEGIN CERTIFICATE-----
+MIIC3zCCAkigAwIBAgICEA4wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTUz
+MDhaFw0zNTAxMTMwOTUzMDhaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MT8wPQYDVQQDHjYAIgBVAHMAZQByACAAMQAzACwAIABlAG4AYwBsAG8AcwBp
+AG4AZwAgAHEAdQBvAHQAZQBzACIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
+AOCys3c0MiM8Rc4fX5pgxVmvL79zjr49iI2XT/6KALlxfwc6HmpbN4r/WI/xs+UL
+nTVYV23a0RXNUn/iFSUW1NYecabz98VtAWT8INROavL5uSo2+K7mF6j5jny7deUk
+Oa1MGMi7ByLN0aZSk38kX5DdD2QHcEJnOZsf6l67zd+rAgMBAAGjeDB2MAsGA1Ud
+DwQEAwIF4DAdBgNVHQ4EFgQUdUnQH6Czosbyf88Wo0xL39ZMB50wHwYDVR0jBBgw
+FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMT
+D1VzZXIgMTMgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQBdYGAGqoot7iAq7vu1
+mYzt2GcoMNgmp+Acbl3hTF7I+QLiLsQeWOmEvNd5TtXF6rp0qk4wnSuYyAv+f+v7
+6SRf+Bcnqc58/0uIFT4lGHFzv7a/xVFrHdsyHa4Av+2lZZkWQ43SbSdT/GWakZR7
+RMhYofErlYYLLS2UEG9evvh7jg==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100F.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100F.pem
new file mode 100644
index 000000000..34a9b97c5
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100F.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4111 (0x100f)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 09:55:02 2010 GMT
+ Not After : Jan 13 09:55:02 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x001\x004\x00 \x00"\x00,\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e\x00"
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:d7:b7:68:39:6e:80:18:83:2e:d7:0a:e5:f1:3f:
+ 27:80:68:59:a8:05:ac:7f:d9:6e:5d:7f:1c:58:86:
+ b7:74:b5:51:3d:64:09:4a:a0:ff:e7:10:0e:bc:8a:
+ f0:d1:54:18:0a:ed:68:0a:a2:33:e5:9f:f0:3d:7f:
+ 24:9c:46:34:ba:45:8f:05:59:51:2d:fb:32:1d:79:
+ 51:37:1a:4b:f8:6e:c5:49:c0:49:9e:ef:2b:ae:aa:
+ 03:fa:ff:55:08:69:85:0d:b4:06:53:ee:20:4e:74:
+ 6c:ca:b8:98:8d:64:8f:b5:99:a9:06:37:32:ca:ca:
+ eb:31:16:ce:97:e8:17:0d:9d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ A7:D8:65:FB:E9:A1:F6:A4:16:76:1C:2E:5B:F3:1B:8E:08:B1:1D:7F
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 14 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 35:54:0f:d2:d3:ec:9e:a6:ea:e6:51:69:27:a3:f1:ae:ea:ef:
+ f9:da:ca:2a:50:f1:9e:2a:7c:74:43:d6:7f:91:ad:5a:5c:e2:
+ da:f3:cb:27:a2:78:99:75:0b:9e:e9:3a:bd:3e:31:14:6a:06:
+ b7:3f:59:d1:0a:67:03:a4:32:63:cd:b1:b6:5c:68:bb:bb:e2:
+ 23:a6:ff:8e:55:e5:92:a6:a8:b3:87:3d:25:21:9c:2a:6f:ab:
+ 09:ad:f5:e6:e6:d8:37:62:f2:30:ac:51:da:f4:9c:1d:06:f6:
+ f3:73:2f:6a:3b:7f:53:0d:c0:2e:ad:cc:6e:81:fe:ce:e3:53:
+ 0e:23
+-----BEGIN CERTIFICATE-----
+MIIC1zCCAkCgAwIBAgICEA8wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTU1
+MDJaFw0zNTAxMTMwOTU1MDJaMIGHMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MTcwNQYDVQQDHi4AVQBzAGUAcgAgADEANAAgACIALABtAGkAZABkAGwAZQAg
+AHEAdQBvAHQAZQAiMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXt2g5boAY
+gy7XCuXxPyeAaFmoBax/2W5dfxxYhrd0tVE9ZAlKoP/nEA68ivDRVBgK7WgKojPl
+n/A9fyScRjS6RY8FWVEt+zIdeVE3Gkv4bsVJwEme7yuuqgP6/1UIaYUNtAZT7iBO
+dGzKuJiNZI+1makGNzLKyusxFs6X6BcNnQIDAQABo3gwdjALBgNVHQ8EBAMCBeAw
+HQYDVR0OBBYEFKfYZfvpofakFnYcLlvzG44IsR1/MB8GA1UdIwQYMBaAFOhqu8KQ
+6mxwIj729kgbA+a+t6ZVMCcGA1UdEQQgMB6kHDAaMRgwFgYDVQQDEw9Vc2VyIDE0
+IFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEANVQP0tPsnqbq5lFpJ6Pxrurv+drK
+KlDxnip8dEPWf5GtWlzi2vPLJ6J4mXULnuk6vT4xFGoGtz9Z0QpnA6QyY82xtlxo
+u7viI6b/jlXlkqaos4c9JSGcKm+rCa315ubYN2LyMKxR2vScHQb283Mvajt/Uw3A
+Lq3MboH+zuNTDiM=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1010.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1010.pem
new file mode 100644
index 000000000..ae0a41747
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1010.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4112 (0x1010)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 09:57:52 2010 GMT
+ Not After : Jan 13 09:57:52 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00\
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:a1:cc:00:2b:07:2b:e7:ac:80:29:cb:40:37:e3:
+ 1f:a3:c5:13:86:16:63:6b:cc:b8:c1:aa:54:fd:57:
+ 0f:de:4c:69:2f:e5:5f:f0:a9:bb:25:74:48:ee:36:
+ 77:6b:08:b5:95:a9:00:aa:15:31:9e:d8:f6:25:53:
+ 78:9d:bc:2b:8f:7a:19:32:12:8c:13:60:7d:76:1e:
+ 4e:b1:e4:51:c7:43:c0:e6:ee:d9:61:df:85:90:a0:
+ 95:3c:a2:81:83:3d:22:f6:8d:42:ee:69:fa:5c:ae:
+ 1c:b5:52:02:fb:ec:a6:12:2f:bb:fb:6c:a8:61:95:
+ 08:6c:d2:e5:1e:90:61:a6:27
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 2F:C9:F6:94:E6:1E:91:13:CE:75:A1:17:FD:1D:93:7E:45:CE:4D:67
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 15 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 19:d0:dc:4c:c8:59:f0:7a:14:f2:51:54:e5:9e:5a:b3:27:0b:
+ d7:36:0f:74:38:07:26:65:1a:b5:94:1a:1f:b2:b7:3d:ee:b1:
+ 90:05:83:41:6a:98:5f:25:b4:cb:5c:49:12:24:35:d6:97:cf:
+ 50:2e:0a:17:41:0b:75:e9:6a:a4:fb:bb:c2:cc:c1:94:64:03:
+ 81:c4:25:d2:3f:3e:8f:d1:29:44:db:a9:3c:7f:0c:2c:6d:48:
+ 38:cb:8f:56:82:9c:d3:f3:f3:20:1f:45:19:8e:ea:91:9c:c1:
+ 25:cf:20:1d:bb:70:7e:b9:a0:c5:34:78:93:5f:2b:d9:fd:d5:
+ de:ad
+-----BEGIN CERTIFICATE-----
+MIICzDCCAjWgAwIBAgICEBAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTU3
+NTJaFw0zNTAxMTMwOTU3NTJaMH0xCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxLTArBgNVBAMeJABcAGUAbgBjAGwAbwBzAGkAbgBnACAAcQB1AG8AdABlAHMA
+XDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAocwAKwcr56yAKctAN+Mfo8UT
+hhZja8y4wapU/VcP3kxpL+Vf8Km7JXRI7jZ3awi1lakAqhUxntj2JVN4nbwrj3oZ
+MhKME2B9dh5OseRRx0PA5u7ZYd+FkKCVPKKBgz0i9o1C7mn6XK4ctVIC++ymEi+7
++2yoYZUIbNLlHpBhpicCAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBQv
+yfaU5h6RE851oRf9HZN+Rc5NZzAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPm
+vremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAxNSBSb290IDExMA0G
+CSqGSIb3DQEBBQUAA4GBABnQ3EzIWfB6FPJRVOWeWrMnC9c2D3Q4ByZlGrWUGh+y
+tz3usZAFg0FqmF8ltMtcSRIkNdaXz1AuChdBC3XpaqT7u8LMwZRkA4HEJdI/Po/R
+KUTbqTx/DCxtSDjLj1aCnNPz8yAfRRmO6pGcwSXPIB27cH65oMU0eJNfK9n91d6t
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1011.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1011.pem
new file mode 100644
index 000000000..21222706f
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1011.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4113 (0x1011)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 09:59:22 2010 GMT
+ Not After : Jan 13 09:59:22 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00\\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00\\x00\
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:a4:e3:64:10:9f:0a:e4:35:bb:e3:e1:f0:28:86:
+ 8a:f2:6e:d3:f8:44:ac:58:7b:f5:dd:1c:71:17:bf:
+ 3e:14:29:55:f0:5c:c9:ed:36:c0:7f:e7:cc:7c:a3:
+ c4:9a:13:4f:7d:6c:b3:1e:ab:24:ba:1a:ff:48:96:
+ 67:a5:ca:e5:75:30:24:70:3a:94:d2:92:db:29:2b:
+ 69:1f:1d:a4:da:37:91:57:03:79:d7:0a:c7:a9:09:
+ 14:a8:70:60:b5:a3:62:4f:b8:bf:0a:22:0a:9c:83:
+ 3a:4d:1a:47:06:97:f1:4a:38:78:95:45:10:9e:44:
+ 90:fb:6e:13:ba:3a:1b:b7:4b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ A5:32:FD:E7:0D:90:82:17:34:E1:AD:2A:48:5D:78:27:2B:C9:2A:B8
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 16 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 96:ee:46:fc:41:4f:55:0d:bc:46:27:5a:3c:09:7c:17:6c:e3:
+ 9e:3a:85:eb:3b:e2:f7:a5:ab:b5:ae:aa:44:81:d7:b7:29:39:
+ b8:20:40:1e:36:da:a8:03:8b:3a:96:c3:2e:ba:cd:81:b9:af:
+ a0:a5:95:b0:3b:55:c1:85:9d:3d:c2:d0:7b:a4:d0:0e:16:7c:
+ 26:ba:85:e5:96:f0:f9:cc:28:c4:ed:83:e8:6f:30:a8:22:7a:
+ 7e:3b:99:d6:b2:3d:a2:90:1e:c9:9b:70:0a:af:04:d9:7c:46:
+ 52:e2:5a:d3:57:d6:18:a9:e9:55:ee:00:e8:10:a1:84:ed:ca:
+ 2b:bf
+-----BEGIN CERTIFICATE-----
+MIIC3zCCAkigAwIBAgICEBEwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTU5
+MjJaFw0zNTAxMTMwOTU5MjJaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MT8wPQYDVQQDHjYAXABcAGQAbwB1AGIAbABlACAAZQBuAGMAbABvAHMAaQBu
+AGcAIABxAHUAbwB0AGUAcwBcAFwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
+AKTjZBCfCuQ1u+Ph8CiGivJu0/hErFh79d0ccRe/PhQpVfBcye02wH/nzHyjxJoT
+T31ssx6rJLoa/0iWZ6XK5XUwJHA6lNKS2ykraR8dpNo3kVcDedcKx6kJFKhwYLWj
+Yk+4vwoiCpyDOk0aRwaX8Uo4eJVFEJ5EkPtuE7o6G7dLAgMBAAGjeDB2MAsGA1Ud
+DwQEAwIF4DAdBgNVHQ4EFgQUpTL95w2Qghc04a0qSF14JyvJKrgwHwYDVR0jBBgw
+FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMT
+D1VzZXIgMTYgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQCW7kb8QU9VDbxGJ1o8
+CXwXbOOeOoXrO+L3pau1rqpEgde3KTm4IEAeNtqoA4s6lsMuus2Bua+gpZWwO1XB
+hZ09wtB7pNAOFnwmuoXllvD5zCjE7YPobzCoInp+O5nWsj2ikB7Jm3AKrwTZfEZS
+4lrTV9YYqelV7gDoEKGE7corvw==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1012.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1012.pem
new file mode 100644
index 000000000..b75551711
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1012.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4114 (0x1012)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 10:02:07 2010 GMT
+ Not After : Jan 13 10:02:07 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00\\x00t\x00w\x00o\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00o\x00n\x00e\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:e9:8c:31:90:52:8d:ef:c6:6a:10:17:7d:37:a3:
+ ef:00:34:19:dd:a4:1a:f6:cc:37:b0:19:c8:9d:f6:
+ 9f:f8:3d:15:c9:cf:73:ab:0a:42:f2:54:5b:cc:12:
+ fb:64:35:54:c9:50:36:18:6c:b6:b0:cf:d6:1e:30:
+ 0b:0d:fa:f3:25:99:d7:49:20:dd:cc:04:d7:bb:07:
+ 00:b9:b9:87:8c:75:e5:28:a6:74:a9:b4:96:36:b8:
+ 15:62:84:0c:7a:a2:f3:07:9c:5c:8f:7a:22:3d:ba:
+ a4:06:69:f6:ce:d2:36:a0:62:e1:ae:67:aa:23:24:
+ ac:1d:53:ac:bf:b6:30:74:f7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ C0:28:3E:BA:44:88:99:A0:80:67:AA:3E:B6:D4:12:A7:35:DA:A6:BB
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 17 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 06:5b:fb:65:55:34:ca:2c:1a:c2:2d:2a:97:1b:a1:68:f6:0c:
+ 13:18:03:44:f9:0d:37:a1:8c:b1:f7:bc:b7:74:a8:aa:c1:e7:
+ 36:e7:b9:e0:64:79:76:63:98:7b:1d:d8:80:8c:d9:26:61:a8:
+ e7:07:96:60:e9:8a:24:78:cb:9c:f3:35:15:c9:d9:0c:2e:68:
+ 68:48:9c:df:6b:56:3f:aa:47:34:36:b0:ef:0e:d2:e0:ee:a9:
+ a9:6a:27:93:60:27:5f:42:76:9c:e0:aa:74:6c:b9:aa:de:fe:
+ 86:98:5a:3d:73:c5:15:38:c8:ff:09:8e:ed:da:06:74:fb:67:
+ 92:51
+-----BEGIN CERTIFICATE-----
+MIIC6TCCAlKgAwIBAgICEBIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDAy
+MDdaFw0zNTAxMTMxMDAyMDdaMIGZMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MUkwRwYDVQQDHkAAXABcAHQAdwBvACAAcwB0AGEAcgB0AGkAbgBnACAAbwBu
+AGUAIABlAG4AZABpAG4AZwAgAHEAdQBvAHQAZQBcMIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDpjDGQUo3vxmoQF303o+8ANBndpBr2zDewGcid9p/4PRXJz3Or
+CkLyVFvMEvtkNVTJUDYYbLawz9YeMAsN+vMlmddJIN3MBNe7BwC5uYeMdeUopnSp
+tJY2uBVihAx6ovMHnFyPeiI9uqQGafbO0jagYuGuZ6ojJKwdU6y/tjB09wIDAQAB
+o3gwdjALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFMAoPrpEiJmggGeqPrbUEqc12qa7
+MB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1UdEQQgMB6kHDAa
+MRgwFgYDVQQDEw9Vc2VyIDE3IFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEABlv7
+ZVU0yiwawi0qlxuhaPYMExgDRPkNN6GMsfe8t3SoqsHnNue54GR5dmOYex3YgIzZ
+JmGo5weWYOmKJHjLnPM1FcnZDC5oaEic32tWP6pHNDaw7w7S4O6pqWonk2AnX0J2
+nOCqdGy5qt7+hphaPXPFFTjI/wmO7doGdPtnklE=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1013.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1013.pem
new file mode 100644
index 000000000..2b48a29b0
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1013.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4115 (0x1013)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 10:04:36 2010 GMT
+ Not After : Jan 13 10:04:36 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:bb:73:a4:4e:45:8e:80:b1:65:b6:d8:3b:96:c8:
+ 3b:c4:2e:40:98:2a:a9:0d:2e:75:29:df:dd:28:8f:
+ dc:65:4e:2f:8b:24:55:f4:5b:95:5e:d8:29:c8:31:
+ aa:53:41:a6:1b:2a:cc:8d:67:b6:d8:5f:56:7d:bd:
+ 0e:17:88:9b:28:b8:fc:54:ff:0e:1f:d9:59:f7:6f:
+ 99:46:76:86:69:87:f7:07:51:f6:1a:76:91:37:40:
+ 96:de:5a:0e:c1:20:7f:b5:1b:79:c2:63:13:50:dc:
+ f0:35:11:2c:4a:30:e0:68:8f:dc:51:4c:2b:61:ba:
+ a5:e6:ad:72:8b:c4:e1:2d:73
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 31:AE:51:BD:37:3E:EB:D6:98:7D:BD:DF:45:0C:92:4E:73:58:35:AA
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 18 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 51:34:24:4b:78:89:95:5d:43:15:3e:62:fc:40:a0:34:a5:6e:
+ 83:b5:ee:f0:93:ae:8a:27:97:9c:66:54:c9:aa:f5:9b:96:88:
+ 43:25:76:b6:0d:06:36:6c:0e:08:5f:15:45:c6:cc:d1:62:18:
+ 6b:fa:cd:af:53:7c:7c:97:30:13:a7:03:ac:db:04:25:bb:22:
+ 7d:49:70:30:69:9f:c8:22:94:32:40:83:d3:d1:9d:1c:2a:64:
+ cf:a9:42:0c:ce:0c:b8:3d:63:33:bb:e1:85:45:a7:79:89:ac:
+ 0c:1b:b5:a4:e0:1d:4d:99:d6:68:9b:c2:67:97:9c:9d:2c:57:
+ 12:fe
+-----BEGIN CERTIFICATE-----
+MIICxjCCAi+gAwIBAgICEBMwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDA0
+MzZaFw0zNTAxMTMxMDA0MzZaMHcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxJzAlBgNVBAMeHgBcAHMAdABhAHIAdABpAG4AZwAgAHEAdQBvAHQAZTCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAu3OkTkWOgLFlttg7lsg7xC5AmCqpDS51
+Kd/dKI/cZU4viyRV9FuVXtgpyDGqU0GmGyrMjWe22F9Wfb0OF4ibKLj8VP8OH9lZ
+92+ZRnaGaYf3B1H2GnaRN0CW3loOwSB/tRt5wmMTUNzwNREsSjDgaI/cUUwrYbql
+5q1yi8ThLXMCAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBQxrlG9Nz7r
+1ph9vd9FDJJOc1g1qjAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTAn
+BgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAxOCBSb290IDExMA0GCSqGSIb3
+DQEBBQUAA4GBAFE0JEt4iZVdQxU+YvxAoDSlboO17vCTroonl5xmVMmq9ZuWiEMl
+drYNBjZsDghfFUXGzNFiGGv6za9TfHyXMBOnA6zbBCW7In1JcDBpn8gilDJAg9PR
+nRwqZM+pQgzODLg9YzO74YVFp3mJrAwbtaTgHU2Z1mibwmeXnJ0sVxL+
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1014.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1014.pem
new file mode 100644
index 000000000..a2027e9d8
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1014.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4116 (0x1014)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 10:05:50 2010 GMT
+ Not After : Jan 13 10:05:50 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:ca:cc:98:77:0c:10:dd:0e:87:a2:da:b6:e6:97:
+ 91:36:71:54:de:2b:f8:de:18:b7:23:eb:e5:e3:57:
+ ae:cf:0b:6d:86:0f:63:f0:c4:4e:2a:66:48:33:c4:
+ e3:0b:2c:f5:e6:e5:e5:0f:f8:e0:a1:bc:11:06:a1:
+ 19:16:ec:44:77:a6:db:7d:d6:78:29:1f:57:f1:9d:
+ 3c:b4:3a:2b:3b:94:64:6d:e3:ce:b3:fa:d8:28:e2:
+ ed:76:9a:97:41:64:7c:0d:48:b8:1d:6a:56:e3:f9:
+ 4c:88:e9:1a:3c:b8:af:7a:13:67:19:59:36:46:79:
+ 52:72:ea:51:80:65:be:e2:0f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ D2:D8:8D:EE:39:D7:EA:15:23:00:7C:9D:48:1C:51:17:F8:80:86:CE
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 19 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 6e:05:c4:48:32:4a:62:6f:a3:8c:23:af:47:dd:d4:c7:c1:91:
+ 17:7e:cd:36:73:39:a3:7b:c9:ae:da:f6:e1:bd:82:d6:72:17:
+ 78:20:a2:27:ad:f5:d2:3f:10:66:e0:d8:ba:10:00:c3:76:5b:
+ de:36:cb:2a:91:25:89:08:0e:2a:6a:81:d0:a7:49:70:42:f3:
+ 94:a3:bf:6c:6b:b9:fa:fd:f9:d4:1f:6f:75:27:b9:0d:d3:d2:
+ fd:5d:0d:dc:f5:34:29:a2:3a:2f:04:ab:48:41:6d:d7:2b:fd:
+ 42:02:99:3c:cf:aa:6b:98:66:17:83:39:4a:6f:47:36:ad:db:
+ 22:6e
+-----BEGIN CERTIFICATE-----
+MIICwjCCAiugAwIBAgICEBQwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDA1
+NTBaFw0zNTAxMTMxMDA1NTBaMHMxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxIzAhBgNVBAMeGgBlAG4AZABpAG4AZwAgAHEAdQBvAHQAZQBcMIGfMA0GCSqG
+SIb3DQEBAQUAA4GNADCBiQKBgQDKzJh3DBDdDoei2rbml5E2cVTeK/jeGLcj6+Xj
+V67PC22GD2PwxE4qZkgzxOMLLPXm5eUP+OChvBEGoRkW7ER3ptt91ngpH1fxnTy0
+Ois7lGRt486z+tgo4u12mpdBZHwNSLgdalbj+UyI6Ro8uK96E2cZWTZGeVJy6lGA
+Zb7iDwIDAQABo3gwdjALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFNLYje451+oVIwB8
+nUgcURf4gIbOMB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1Ud
+EQQgMB6kHDAaMRgwFgYDVQQDEw9Vc2VyIDE5IFJvb3QgMTEwDQYJKoZIhvcNAQEF
+BQADgYEAbgXESDJKYm+jjCOvR93Ux8GRF37NNnM5o3vJrtr24b2C1nIXeCCiJ631
+0j8QZuDYuhAAw3Zb3jbLKpEliQgOKmqB0KdJcELzlKO/bGu5+v351B9vdSe5DdPS
+/V0N3PU0KaI6LwSrSEFt1yv9QgKZPM+qa5hmF4M5Sm9HNq3bIm4=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1015.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1015.pem
new file mode 100644
index 000000000..d9d3f941e
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1015.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4117 (0x1015)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 10:07:07 2010 GMT
+ Not After : Jan 13 10:07:07 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00\\x00q\x00u\x00o\x00t\x00e
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:f0:7c:07:f6:13:52:ce:13:cf:8a:5f:7f:5f:3c:
+ d4:93:c8:a0:43:1f:e2:fc:3f:62:63:be:b5:17:e0:
+ 32:b0:d0:c2:9a:35:9e:3b:29:30:b4:13:78:18:ae:
+ 80:ba:fb:f3:fc:81:ad:aa:47:18:eb:fc:d1:76:de:
+ b6:cf:55:65:5e:3e:15:93:8e:9c:39:4e:a3:ae:1d:
+ c0:49:22:dc:25:09:33:95:0d:b5:62:7c:96:0b:05:
+ b6:10:ae:ee:f8:18:24:9f:d4:ed:b3:4c:a9:4d:f2:
+ be:6c:66:37:b9:17:cb:14:df:52:b4:a8:de:63:0d:
+ 4f:78:58:16:ab:f2:3f:f6:a9
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 41:CC:3D:88:34:10:21:13:A2:34:24:B6:4E:F9:33:3C:B3:FA:56:BC
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 20 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ a7:17:c3:92:37:10:ee:9a:12:65:32:82:56:93:82:fa:0e:40:
+ 9f:ae:30:6a:b1:6f:85:18:7f:ff:9c:30:49:b7:56:bf:a3:86:
+ d7:dd:5d:79:d1:7f:9a:95:b6:bd:1d:43:cc:2c:aa:7a:40:c4:
+ de:17:02:22:74:ec:a9:cd:8d:93:f6:6c:98:7e:bb:6a:68:70:
+ 66:d4:a0:8f:1a:7a:8e:9e:38:35:aa:87:6a:e5:db:80:69:51:
+ 51:68:46:4f:3d:da:17:df:6f:22:60:77:95:55:d3:12:1b:11:
+ c1:6f:c1:96:78:00:47:61:af:53:c0:37:44:6b:92:67:7f:14:
+ 79:80
+-----BEGIN CERTIFICATE-----
+MIICwjCCAiugAwIBAgICEBUwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDA3
+MDdaFw0zNTAxMTMxMDA3MDdaMHMxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxIzAhBgNVBAMeGgBtAGkAZABkAGwAZQAgAFwAcQB1AG8AdABlMIGfMA0GCSqG
+SIb3DQEBAQUAA4GNADCBiQKBgQDwfAf2E1LOE8+KX39fPNSTyKBDH+L8P2JjvrUX
+4DKw0MKaNZ47KTC0E3gYroC6+/P8ga2qRxjr/NF23rbPVWVePhWTjpw5TqOuHcBJ
+ItwlCTOVDbVifJYLBbYQru74GCSf1O2zTKlN8r5sZje5F8sU31K0qN5jDU94WBar
+8j/2qQIDAQABo3gwdjALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFEHMPYg0ECETojQk
+tk75Mzyz+la8MB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1Ud
+EQQgMB6kHDAaMRgwFgYDVQQDEw9Vc2VyIDIwIFJvb3QgMTEwDQYJKoZIhvcNAQEF
+BQADgYEApxfDkjcQ7poSZTKCVpOC+g5An64warFvhRh//5wwSbdWv6OG191dedF/
+mpW2vR1DzCyqekDE3hcCInTsqc2Nk/ZsmH67amhwZtSgjxp6jp44NaqHauXbgGlR
+UWhGTz3aF99vImB3lVXTEhsRwW/BlngAR2GvU8A3RGuSZ38UeYA=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1016.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1016.pem
new file mode 100644
index 000000000..9f4e006f0
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1016.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4118 (0x1016)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 10:09:50 2010 GMT
+ Not After : Jan 13 10:09:50 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00\\x00\\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:cd:22:93:9a:93:18:34:2f:50:e0:cc:23:f4:60:
+ bc:96:60:d5:a5:f9:da:45:9a:5b:a3:0a:fb:71:25:
+ 4c:bd:60:84:19:f5:93:28:c1:5d:b9:8d:05:05:4d:
+ 01:85:aa:9e:5b:08:9c:01:f8:32:90:fe:ef:7f:eb:
+ cb:b3:8b:b2:c8:d1:79:d6:47:a3:d8:df:f1:d0:56:
+ 04:04:bd:41:72:fc:98:75:10:d2:9b:b5:bc:55:a1:
+ fa:19:01:67:93:09:48:0a:67:ec:4d:12:47:37:6f:
+ c2:53:0e:c9:7a:30:ec:1d:9d:a5:e2:64:d8:92:4d:
+ ed:ec:b2:bb:10:96:76:28:47
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ DC:FF:9A:2B:49:51:1E:FB:A7:3A:90:94:1B:E0:3E:34:89:13:48:EE
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 21 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 16:aa:a6:b7:0e:e3:d2:ba:7e:9b:59:f6:cc:ce:5d:4d:2a:f2:
+ 95:60:46:24:dd:ea:e8:08:e6:60:9c:33:82:8c:34:a2:d8:38:
+ fb:75:fe:31:79:10:78:7d:93:44:3b:00:90:83:a4:15:52:8d:
+ 3a:b4:9c:c0:6f:95:2c:4f:d8:b3:3b:cf:69:ab:3c:41:3a:43:
+ 1b:0a:8b:b0:b4:aa:8b:bf:6f:96:e2:65:4a:00:3a:49:bc:9a:
+ a1:cd:13:b1:24:93:f6:44:cd:d3:71:91:da:4f:dd:75:3d:68:
+ 5c:6b:49:14:8a:23:b5:b6:4f:b6:41:d0:a7:16:7c:67:4c:b3:
+ 0a:88
+-----BEGIN CERTIFICATE-----
+MIIC0zCCAjygAwIBAgICEBYwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDA5
+NTBaFw0zNTAxMTMxMDA5NTBaMIGDMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MTMwMQYDVQQDHioAZABvAHUAYgBsAGUAIABcAFwAbQBpAGQAZABsAGUAIABx
+AHUAbwB0AGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM0ik5qTGDQvUODM
+I/RgvJZg1aX52kWaW6MK+3ElTL1ghBn1kyjBXbmNBQVNAYWqnlsInAH4MpD+73/r
+y7OLssjRedZHo9jf8dBWBAS9QXL8mHUQ0pu1vFWh+hkBZ5MJSApn7E0SRzdvwlMO
+yXow7B2dpeJk2JJN7eyyuxCWdihHAgMBAAGjeDB2MAsGA1UdDwQEAwIF4DAdBgNV
+HQ4EFgQU3P+aK0lRHvunOpCUG+A+NIkTSO4wHwYDVR0jBBgwFoAU6Gq7wpDqbHAi
+Pvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMTD1VzZXIgMjEgUm9v
+dCAxMTANBgkqhkiG9w0BAQUFAAOBgQAWqqa3DuPSun6bWfbMzl1NKvKVYEYk3ero
+COZgnDOCjDSi2Dj7df4xeRB4fZNEOwCQg6QVUo06tJzAb5UsT9izO89pqzxBOkMb
+CouwtKqLv2+W4mVKADpJvJqhzROxJJP2RM3TcZHaT911PWhca0kUiiO1tk+2QdCn
+FnxnTLMKiA==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1017.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1017.pem
new file mode 100644
index 000000000..7bb12fa78
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1017.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4119 (0x1017)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 10:11:53 2010 GMT
+ Not After : Jan 13 10:11:53 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00p\x00a\x00r\x00t\x00i\x00a\x00l\x00l\x00y\x00 \x00\\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:e7:c9:bb:89:11:2f:2c:39:bc:d3:f5:d9:86:d4:
+ 8e:d7:20:11:81:75:30:25:7e:2b:29:70:61:83:38:
+ 24:d1:0f:cc:0b:88:71:29:06:05:a5:53:d2:00:2f:
+ 12:0c:7d:42:e6:47:33:de:cc:f8:7b:2a:5d:d9:cb:
+ 69:24:91:38:bf:0c:1a:12:cf:1e:f9:44:c2:1c:e8:
+ 6f:ea:ab:8b:92:4c:93:8c:69:61:b9:57:b3:1d:d0:
+ 03:3e:13:9d:30:bd:b2:b9:d9:c7:9b:4d:18:45:b0:
+ 19:19:15:58:4c:bd:5a:a1:59:4f:f0:1f:99:26:3b:
+ 4e:76:c6:bb:21:3c:94:bc:d9
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 43:E4:70:39:E3:91:80:2A:C3:BC:1A:F4:A3:51:4B:99:C5:20:93:A6
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 22 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 28:ce:8c:f0:bf:56:c6:a4:02:df:dd:1d:75:dc:cf:62:a0:92:
+ 58:64:91:8c:bb:96:3c:52:d5:66:6c:31:7e:1c:d9:a8:e5:1c:
+ a6:9f:5e:26:3f:69:71:c6:d7:5d:02:4f:a7:42:a5:85:fa:38:
+ 01:43:36:54:75:4c:51:a2:99:5d:72:05:9a:9b:fc:5e:83:9b:
+ a0:ef:11:b1:a4:dd:a5:50:2f:d0:14:dd:04:0f:8b:93:7e:4b:
+ 3e:24:04:45:d0:98:46:49:74:9f:d7:b4:68:09:dc:b6:ac:35:
+ 3f:5d:f9:ee:77:a4:35:46:75:a4:6a:d6:c1:53:4f:d2:0c:38:
+ 3c:df
+-----BEGIN CERTIFICATE-----
+MIIC3zCCAkigAwIBAgICEBcwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDEx
+NTNaFw0zNTAxMTMxMDExNTNaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MT8wPQYDVQQDHjYAcABhAHIAdABpAGEAbABsAHkAIABcAGUAbgBjAGwAbwBz
+AGkAbgBnACAAcQB1AG8AdABlAFwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
+AOfJu4kRLyw5vNP12YbUjtcgEYF1MCV+KylwYYM4JNEPzAuIcSkGBaVT0gAvEgx9
+QuZHM97M+HsqXdnLaSSROL8MGhLPHvlEwhzob+qri5JMk4xpYblXsx3QAz4TnTC9
+srnZx5tNGEWwGRkVWEy9WqFZT/AfmSY7TnbGuyE8lLzZAgMBAAGjeDB2MAsGA1Ud
+DwQEAwIF4DAdBgNVHQ4EFgQUQ+RwOeORgCrDvBr0o1FLmcUgk6YwHwYDVR0jBBgw
+FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMT
+D1VzZXIgMjIgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQAozozwv1bGpALf3R11
+3M9ioJJYZJGMu5Y8UtVmbDF+HNmo5Rymn14mP2lxxtddAk+nQqWF+jgBQzZUdUxR
+opldcgWam/xeg5ug7xGxpN2lUC/QFN0ED4uTfks+JARF0JhGSXSf17RoCdy2rDU/
+Xfnud6Q1RnWkatbBU0/SDDg83w==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1018.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1018.pem
new file mode 100644
index 000000000..d134dc5f3
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1018.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4120 (0x1018)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 10:13:38 2010 GMT
+ Not After : Jan 13 10:13:38 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00U\x00s\x00e\x00r\x00 \x002\x003\x00,\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:b9:e3:64:f8:02:be:98:47:de:c6:f4:22:14:4f:
+ 22:fe:17:8c:14:7f:b8:27:44:51:9d:5a:79:33:b4:
+ d0:21:27:b0:ed:f9:9f:3d:54:ef:ba:3a:d8:89:2a:
+ ca:a8:8f:f3:f6:a7:6b:5f:0a:58:2d:a0:e3:05:3a:
+ 26:a6:1e:b6:89:a1:e1:71:11:e7:16:93:29:69:f8:
+ 14:a2:e3:d7:4e:e5:60:40:d7:40:c5:37:d6:95:7c:
+ 4f:35:fd:a8:82:7f:90:32:1d:99:e7:8a:b9:93:a4:
+ f3:23:0a:a5:f9:56:31:73:d8:e3:cb:d6:0e:2f:2b:
+ ee:8e:b5:ca:eb:63:82:1c:0b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 80:A8:F7:13:E3:E8:F8:A6:60:94:21:C1:FE:54:54:89:AC:4B:DF:45
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 23 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ be:31:bd:4a:56:80:64:f0:1e:ea:77:4a:f3:e3:ec:f0:ad:27:
+ cc:05:01:fa:d2:12:7c:8e:85:5b:37:54:9c:4f:96:2d:1c:81:
+ e4:21:3d:4b:d9:86:1a:6c:29:5e:88:f2:ae:04:f1:70:87:25:
+ b9:9a:4a:ef:dd:21:f9:17:33:ee:a1:eb:38:fb:c4:73:72:70:
+ 0c:67:58:96:95:8c:2c:5a:4a:31:28:50:52:64:65:5c:63:60:
+ de:24:df:a0:e9:0d:c0:b6:d6:4c:51:a7:5a:e8:dd:f6:ff:49:
+ e6:6f:7f:86:38:5d:c7:f9:eb:55:f1:b2:89:3b:cd:41:f7:5d:
+ a8:b0
+-----BEGIN CERTIFICATE-----
+MIIC2TCCAkKgAwIBAgICEBgwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDEz
+MzhaFw0zNTAxMTMxMDEzMzhaMIGJMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MTkwNwYDVQQDHjAAXABVAHMAZQByACAAMgAzACwAIABzAHQAYQByAHQAaQBu
+AGcAIABxAHUAbwB0AGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALnjZPgC
+vphH3sb0IhRPIv4XjBR/uCdEUZ1aeTO00CEnsO35nz1U77o62IkqyqiP8/ana18K
+WC2g4wU6JqYetomh4XER5xaTKWn4FKLj107lYEDXQMU31pV8TzX9qIJ/kDIdmeeK
+uZOk8yMKpflWMXPY48vWDi8r7o61yutjghwLAgMBAAGjeDB2MAsGA1UdDwQEAwIF
+4DAdBgNVHQ4EFgQUgKj3E+Po+KZglCHB/lRUiaxL30UwHwYDVR0jBBgwFoAU6Gq7
+wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMTD1VzZXIg
+MjMgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQC+Mb1KVoBk8B7qd0rz4+zwrSfM
+BQH60hJ8joVbN1ScT5YtHIHkIT1L2YYabCleiPKuBPFwhyW5mkrv3SH5FzPuoes4
++8RzcnAMZ1iWlYwsWkoxKFBSZGVcY2DeJN+g6Q3AttZMUada6N32/0nmb3+GOF3H
++etV8bKJO81B912osA==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1019.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1019.pem
new file mode 100644
index 000000000..66c3f15bf
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1019.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4121 (0x1019)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 10:14:50 2010 GMT
+ Not After : Jan 13 10:14:50 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x002\x004\x00,\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:9c:cd:78:e7:11:1d:61:d4:0c:c6:87:c9:28:47:
+ 84:23:6b:86:c3:38:37:62:5a:9a:4b:50:fc:b7:f3:
+ d9:4b:1b:20:ff:06:42:bb:22:33:c5:22:12:2c:bb:
+ e6:c8:08:69:0e:af:e9:22:45:9f:ef:2c:26:46:d7:
+ 1b:36:db:70:58:32:bc:3d:d7:7d:64:27:44:54:6c:
+ 89:12:88:d7:31:3d:3f:5c:96:cb:69:9f:b1:a9:e0:
+ 9a:de:50:b7:ad:d8:29:bf:bc:3c:21:e9:a2:79:21:
+ 46:81:ea:90:df:44:0c:6c:bb:f8:47:c8:e9:79:d1:
+ 8d:40:1b:5d:d3:75:9b:e4:0b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 81:14:09:35:7F:F6:7A:83:6B:19:C2:22:24:92:E6:D4:EF:52:1C:0B
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 24 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 7c:65:0b:e2:cd:ca:00:e8:40:0f:37:70:a1:89:54:5d:03:06:
+ 2c:60:56:dc:2f:b7:01:ac:75:58:f6:82:8f:91:63:e2:91:d1:
+ 17:7b:bd:63:b9:9c:4e:46:86:3e:a6:f5:a6:56:ac:90:2a:f4:
+ d8:a0:6c:02:15:6e:d9:f6:2a:f8:9a:c4:48:bd:cd:54:82:55:
+ c6:d5:52:76:09:e3:3d:17:8d:5c:46:16:ae:9e:56:df:9f:c3:
+ 05:15:6f:ae:d0:b5:76:67:48:2d:5a:3c:59:da:1b:13:c3:84:
+ 5e:2a:57:8d:86:9a:f1:8a:5d:01:47:93:44:62:af:65:03:e1:
+ df:10
+-----BEGIN CERTIFICATE-----
+MIIC1TCCAj6gAwIBAgICEBkwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDE0
+NTBaFw0zNTAxMTMxMDE0NTBaMIGFMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MTUwMwYDVQQDHiwAVQBzAGUAcgAgADIANAAsACAAZQBuAGQAaQBuAGcAIABx
+AHUAbwB0AGUAXDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnM145xEdYdQM
+xofJKEeEI2uGwzg3YlqaS1D8t/PZSxsg/wZCuyIzxSISLLvmyAhpDq/pIkWf7ywm
+RtcbNttwWDK8Pdd9ZCdEVGyJEojXMT0/XJbLaZ+xqeCa3lC3rdgpv7w8IemieSFG
+geqQ30QMbLv4R8jpedGNQBtd03Wb5AsCAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0G
+A1UdDgQWBBSBFAk1f/Z6g2sZwiIkkubU71IcCzAfBgNVHSMEGDAWgBToarvCkOps
+cCI+9vZIGwPmvremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAyNCBS
+b290IDExMA0GCSqGSIb3DQEBBQUAA4GBAHxlC+LNygDoQA83cKGJVF0DBixgVtwv
+twGsdVj2go+RY+KR0Rd7vWO5nE5Ghj6m9aZWrJAq9NigbAIVbtn2KviaxEi9zVSC
+VcbVUnYJ4z0XjVxGFq6eVt+fwwUVb67QtXZnSC1aPFnaGxPDhF4qV42GmvGKXQFH
+k0Rir2UD4d8Q
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101A.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101A.pem
new file mode 100644
index 000000000..ba352d83d
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101A.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4122 (0x101a)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 10:16:10 2010 GMT
+ Not After : Jan 13 10:16:10 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00U\x00s\x00e\x00r\x00 \x002\x005\x00,\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:ad:20:4a:85:d2:a8:2a:f8:0e:4c:b5:2d:72:a5:
+ 1d:0e:b1:8a:76:2c:b0:bf:7a:48:b8:57:29:cb:40:
+ c5:8a:e8:0e:d3:f6:f9:b1:90:a6:4a:bb:82:45:fd:
+ c2:ff:03:fa:fc:4a:5d:93:0b:52:a2:17:10:b1:7e:
+ 13:1d:9d:28:26:e3:44:bd:fd:26:da:b2:7b:47:e1:
+ c4:35:ea:53:1b:94:76:cc:f2:f6:c1:86:f2:18:46:
+ e1:71:c0:5d:e5:8f:0a:10:7a:ea:61:af:d0:ba:28:
+ 22:13:77:0f:7d:9e:e0:0a:f0:92:ce:dd:b3:5d:a6:
+ df:c1:eb:a8:29:57:e6:71:65
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ C3:EE:4A:7E:AC:46:2D:BA:42:F7:33:1F:E7:49:FA:21:D3:BC:DD:49
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 25 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ bf:63:34:12:e3:4b:83:4e:e5:c5:08:c3:b3:ea:be:38:33:38:
+ 3c:99:c3:ca:08:84:05:d4:21:53:7a:7d:43:86:c2:63:e2:d3:
+ 7c:21:3c:72:fa:c6:f3:bf:2b:10:5e:ca:4b:2c:2c:1c:e3:10:
+ eb:7c:ff:b1:20:b2:47:1b:b3:3e:77:b6:74:fb:83:85:ac:b8:
+ c9:5b:ca:8a:14:2f:e4:81:6e:04:6f:c8:37:c0:9f:c0:41:0f:
+ b4:6e:21:82:69:51:e8:68:09:72:c4:8c:72:db:47:0b:a5:52:
+ d7:e7:b3:5d:10:9c:ed:14:af:1c:fd:0b:11:a3:fd:f9:b9:2d:
+ 48:b5
+-----BEGIN CERTIFICATE-----
+MIIC3TCCAkagAwIBAgICEBowDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDE2
+MTBaFw0zNTAxMTMxMDE2MTBaMIGNMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MT0wOwYDVQQDHjQAXABVAHMAZQByACAAMgA1ACwAIABlAG4AYwBsAG8AcwBp
+AG4AZwAgAHEAdQBvAHQAZQBcMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCt
+IEqF0qgq+A5MtS1ypR0OsYp2LLC/eki4VynLQMWK6A7T9vmxkKZKu4JF/cL/A/r8
+Sl2TC1KiFxCxfhMdnSgm40S9/SbasntH4cQ16lMblHbM8vbBhvIYRuFxwF3ljwoQ
+euphr9C6KCITdw99nuAK8JLO3bNdpt/B66gpV+ZxZQIDAQABo3gwdjALBgNVHQ8E
+BAMCBeAwHQYDVR0OBBYEFMPuSn6sRi26QvczH+dJ+iHTvN1JMB8GA1UdIwQYMBaA
+FOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1UdEQQgMB6kHDAaMRgwFgYDVQQDEw9V
+c2VyIDI1IFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEAv2M0EuNLg07lxQjDs+q+
+ODM4PJnDygiEBdQhU3p9Q4bCY+LTfCE8cvrG878rEF7KSywsHOMQ63z/sSCyRxuz
+Pne2dPuDhay4yVvKihQv5IFuBG/IN8CfwEEPtG4hgmlR6GgJcsSMcttHC6VS1+ez
+XRCc7RSvHP0LEaP9+bktSLU=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101B.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101B.pem
new file mode 100644
index 000000000..4c03562a8
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101B.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4123 (0x101b)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 10:17:45 2010 GMT
+ Not After : Jan 13 10:17:45 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x002\x006\x00\\x00,\x00 \x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:ec:4c:2b:ba:b1:e5:ba:83:e8:64:6c:67:fe:f9:
+ 84:9a:71:68:0b:10:b0:2e:2c:21:d8:6d:c8:cc:de:
+ 82:76:15:b8:74:a0:4b:3c:39:f0:ee:3a:08:6c:0e:
+ 0c:36:51:ed:44:04:ca:2b:76:30:6f:85:d4:f6:f0:
+ 7e:53:2b:17:90:6a:7b:79:e0:c2:00:f2:5f:dd:19:
+ 8f:09:7a:a2:c8:85:95:24:e0:41:39:ec:75:e1:c7:
+ 03:ba:6d:e9:81:48:8b:36:38:e0:99:3e:58:04:e3:
+ 03:8d:e4:3b:95:98:0a:23:96:f1:96:50:06:5d:71:
+ 6f:02:e1:c5:cd:e0:5c:c4:7b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 1D:A3:64:F0:93:51:C2:F2:1A:BB:D0:2D:20:95:5E:19:94:4C:72:BB
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 26 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 8c:c1:56:7d:d9:a8:f7:af:4b:57:4a:a5:2a:32:11:12:e0:d8:
+ 0e:10:39:8f:17:53:25:f5:c6:57:55:e4:f0:16:f2:11:cc:af:
+ cc:44:6b:23:6f:8e:2a:df:ee:ff:f0:d4:3f:0a:85:7e:19:de:
+ f8:cf:69:be:8b:59:ad:3c:be:3c:d7:32:ac:ba:82:91:28:23:
+ 71:ba:b5:29:05:e4:98:ee:2b:bb:56:04:7f:8b:69:c5:f9:4c:
+ 1b:0b:2e:3a:46:41:8e:da:16:68:9f:c7:57:71:8e:97:0d:b0:
+ a1:92:ae:7c:75:46:ef:b4:6d:8e:e7:53:07:23:a4:e1:e0:f0:
+ e7:3b
+-----BEGIN CERTIFICATE-----
+MIIC1TCCAj6gAwIBAgICEBswDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDE3
+NDVaFw0zNTAxMTMxMDE3NDVaMIGFMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MTUwMwYDVQQDHiwAVQBzAGUAcgAgADIANgBcACwAIABtAGkAZABkAGwAZQAg
+AHEAdQBvAHQAZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA7EwrurHluoPo
+ZGxn/vmEmnFoCxCwLiwh2G3IzN6CdhW4dKBLPDnw7joIbA4MNlHtRATKK3Ywb4XU
+9vB+UysXkGp7eeDCAPJf3RmPCXqiyIWVJOBBOex14ccDum3pgUiLNjjgmT5YBOMD
+jeQ7lZgKI5bxllAGXXFvAuHFzeBcxHsCAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0G
+A1UdDgQWBBQdo2Twk1HC8hq70C0glV4ZlExyuzAfBgNVHSMEGDAWgBToarvCkOps
+cCI+9vZIGwPmvremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAyNiBS
+b290IDExMA0GCSqGSIb3DQEBBQUAA4GBAIzBVn3ZqPevS1dKpSoyERLg2A4QOY8X
+UyX1xldV5PAW8hHMr8xEayNvjirf7v/w1D8KhX4Z3vjPab6LWa08vjzXMqy6gpEo
+I3G6tSkF5JjuK7tWBH+LacX5TBsLLjpGQY7aFmifx1dxjpcNsKGSrnx1Ru+0bY7n
+UwcjpOHg8Oc7
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101C.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101C.pem
new file mode 100644
index 000000000..c403402f3
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101C.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4124 (0x101c)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 10:19:13 2010 GMT
+ Not After : Jan 13 10:19:13 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=comma, comma, comma ,
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:af:2e:02:1a:b8:ed:7e:6e:27:2f:6e:ca:dc:57:
+ 11:17:88:37:38:37:26:d0:fb:d0:ee:ad:f3:a8:ad:
+ f5:8a:53:04:6a:82:a7:31:b5:e6:ce:88:24:fa:22:
+ 75:84:1b:a8:8c:fd:7f:63:0c:fc:13:41:82:60:a3:
+ 19:33:3d:d3:18:6e:09:c5:c7:e7:e9:9e:49:dd:f4:
+ 77:ef:f1:06:91:9a:c5:57:68:e5:0f:59:19:8d:53:
+ ff:cb:ae:11:33:48:5c:eb:72:e8:2f:67:ae:94:42:
+ d3:5b:2e:31:e3:6f:a7:5e:5e:9c:ea:2c:d2:c3:af:
+ 66:10:34:32:e5:2d:3f:55:c1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ A1:FB:82:9C:27:AD:83:67:5E:8C:CC:A2:BA:32:3C:30:26:74:F4:CE
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 27 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ c6:72:8b:f8:57:9e:b7:bf:b1:f3:99:41:1c:8c:47:a1:93:d8:
+ 62:8e:2d:68:6c:db:12:02:86:e0:66:65:c1:7c:c4:83:35:4c:
+ 16:53:fd:34:c1:3c:60:15:fc:3d:3b:90:07:68:ca:af:a1:10:
+ 39:c4:6b:15:a6:1a:71:51:20:ea:35:84:ef:8f:ac:51:bc:d7:
+ 84:d8:35:71:44:8e:8c:4f:59:76:3d:b3:5f:5c:26:9e:bc:ee:
+ 09:40:13:3b:38:85:02:56:7d:97:db:4d:3d:b5:a1:66:cf:df:
+ 19:7a:2f:71:b7:a4:12:c3:9b:df:83:f9:a8:8a:00:68:e4:3a:
+ ee:25
+-----BEGIN CERTIFICATE-----
+MIICvTCCAiagAwIBAgICEBwwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDE5
+MTNaFw0zNTAxMTMxMDE5MTNaMG4xCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxHjAcBgNVBAMTFWNvbW1hLCBjb21tYSwgY29tbWEgLDCBnzANBgkqhkiG9w0B
+AQEFAAOBjQAwgYkCgYEAry4CGrjtfm4nL27K3FcRF4g3ODcm0PvQ7q3zqK31ilME
+aoKnMbXmzogk+iJ1hBuojP1/Ywz8E0GCYKMZMz3TGG4Jxcfn6Z5J3fR37/EGkZrF
+V2jlD1kZjVP/y64RM0hc63LoL2eulELTWy4x42+nXl6c6izSw69mEDQy5S0/VcEC
+AwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBSh+4KcJ62DZ16MzKK6Mjww
+JnT0zjAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTAnBgNVHREEIDAe
+pBwwGjEYMBYGA1UEAxMPVXNlciAyNyBSb290IDExMA0GCSqGSIb3DQEBBQUAA4GB
+AMZyi/hXnre/sfOZQRyMR6GT2GKOLWhs2xIChuBmZcF8xIM1TBZT/TTBPGAV/D07
+kAdoyq+hEDnEaxWmGnFRIOo1hO+PrFG814TYNXFEjoxPWXY9s19cJp687glAEzs4
+hQJWfZfbTT21oWbP3xl6L3G3pBLDm9+D+aiKAGjkOu4l
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101D.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101D.pem
new file mode 100644
index 000000000..2790a2abd
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101D.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4125 (0x101d)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 10:20:47 2010 GMT
+ Not After : Jan 13 10:20:47 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=equal CN=User 28
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:ae:df:12:64:ab:d9:2f:ee:21:64:b5:08:c5:c8:
+ 8f:a1:ad:0e:b9:28:91:69:74:13:a5:aa:49:fe:fa:
+ 02:9d:37:db:0a:3b:26:6a:20:25:3d:f9:2d:b2:3b:
+ 39:c8:c6:e3:a7:aa:a1:0b:b2:1b:58:43:e6:3c:3f:
+ 67:fe:bb:bd:9b:b5:d9:de:e9:ed:76:ab:fd:f5:c8:
+ 15:b2:fb:a6:3f:23:ef:9f:5f:71:43:b3:be:55:1e:
+ 85:5f:13:b1:6b:9d:42:d7:30:a8:d2:9b:fe:71:7a:
+ c7:d3:60:7a:cf:e2:83:75:83:b8:1c:d3:ef:ee:94:
+ 3f:14:63:aa:7c:15:4e:42:1d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 3B:2D:2B:5F:2E:E6:32:23:AE:47:B7:30:25:CB:ED:B0:6D:0C:30:E4
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 28 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 5b:cf:de:92:f8:ac:39:fb:0a:81:70:5b:17:d0:0d:0d:85:5e:
+ 2e:7d:be:d1:1a:ad:1d:99:a4:a6:f0:48:5a:7b:04:39:e2:93:
+ ff:80:84:f6:a1:e6:8a:52:12:55:46:c0:57:84:d9:c3:13:92:
+ 61:d7:41:af:39:09:57:05:25:01:90:68:7c:7c:5c:85:c6:f2:
+ fe:0e:37:e3:58:68:f9:32:fc:41:2c:35:36:f4:cf:ea:55:2d:
+ 52:7c:fb:37:32:35:cf:82:eb:fc:f1:39:f1:51:f1:e1:5b:d6:
+ 58:e1:7f:d4:50:ce:cf:07:f2:e5:f5:e2:dd:fe:55:3f:64:07:
+ 90:4f
+-----BEGIN CERTIFICATE-----
+MIICuDCCAiGgAwIBAgICEB0wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDIw
+NDdaFw0zNTAxMTMxMDIwNDdaMGkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxGTAXBgNVBAMTEGVxdWFsIENOPVVzZXIgMjgwgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBAK7fEmSr2S/uIWS1CMXIj6GtDrkokWl0E6WqSf76Ap032wo7Jmog
+JT35LbI7OcjG46eqoQuyG1hD5jw/Z/67vZu12d7p7Xar/fXIFbL7pj8j759fcUOz
+vlUehV8TsWudQtcwqNKb/nF6x9Nges/ig3WDuBzT7+6UPxRjqnwVTkIdAgMBAAGj
+eDB2MAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQUOy0rXy7mMiOuR7cwJcvtsG0MMOQw
+HwYDVR0jBBgwFoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBox
+GDAWBgNVBAMTD1VzZXIgMjggUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQBbz96S
++Kw5+wqBcFsX0A0NhV4ufb7RGq0dmaSm8EhaewQ54pP/gIT2oeaKUhJVRsBXhNnD
+E5Jh10GvOQlXBSUBkGh8fFyFxvL+DjfjWGj5MvxBLDU29M/qVS1SfPs3MjXPguv8
+8TnxUfHhW9ZY4X/UUM7PB/Ll9eLd/lU/ZAeQTw==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101E.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101E.pem
new file mode 100644
index 000000000..f12a0c1c0
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101E.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4126 (0x101e)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 10:22:13 2010 GMT
+ Not After : Jan 13 10:22:13 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 29+OU=ooo
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:ae:12:dc:26:fe:7f:b8:3f:47:a2:dc:83:a1:70:
+ 6d:ab:db:e5:3c:28:d5:18:32:2c:8d:ee:85:c6:f9:
+ f4:8b:31:34:71:de:91:79:fb:56:b4:9c:af:3e:b1:
+ c6:de:06:3f:32:fc:45:9d:9b:dd:15:0f:b5:c3:98:
+ ab:8c:1e:3d:63:7c:2a:c5:b9:38:3d:50:6c:81:9e:
+ f0:b3:5b:41:1a:ec:15:b2:7f:2b:b4:d4:42:aa:ca:
+ e6:89:b0:c6:58:bd:2d:38:f3:4d:85:c3:08:d7:45:
+ 48:42:d7:fe:ee:7a:c0:22:41:c0:c6:cb:77:7c:22:
+ 43:07:35:dc:88:7c:49:3a:9b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ E0:19:7F:AC:F8:6A:42:7E:84:CA:8C:84:45:75:4E:9D:A1:D1:2A:72
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 29 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 85:c9:ea:82:e2:ac:f6:b3:15:51:11:bd:69:81:31:8f:ee:d3:
+ f9:f4:8e:d5:27:34:20:89:76:eb:8a:5b:02:69:9b:97:89:d7:
+ 6b:aa:03:7f:b5:40:f9:ac:54:ce:8f:30:fd:3e:78:72:91:96:
+ dc:a6:bd:64:42:f8:e4:18:1a:e3:b5:db:08:fe:1e:fc:3d:a2:
+ 55:21:ad:0f:1a:87:df:f2:65:87:4d:91:52:c1:46:c1:c0:7c:
+ cc:81:79:97:dc:2e:41:cc:ae:8c:8e:79:4e:02:49:7c:c5:b0:
+ 3e:8e:d9:f0:aa:6b:a6:2f:e7:d2:21:5b:7f:57:e8:f7:f6:00:
+ 3c:ad
+-----BEGIN CERTIFICATE-----
+MIICtjCCAh+gAwIBAgICEB4wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDIy
+MTNaFw0zNTAxMTMxMDIyMTNaMGcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxFzAVBgNVBAMTDlVzZXIgMjkrT1U9b29vMIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQCuEtwm/n+4P0ei3IOhcG2r2+U8KNUYMiyN7oXG+fSLMTRx3pF5+1a0
+nK8+scbeBj8y/EWdm90VD7XDmKuMHj1jfCrFuTg9UGyBnvCzW0Ea7BWyfyu01EKq
+yuaJsMZYvS04802FwwjXRUhC1/7uesAiQcDGy3d8IkMHNdyIfEk6mwIDAQABo3gw
+djALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFOAZf6z4akJ+hMqMhEV1Tp2h0SpyMB8G
+A1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1UdEQQgMB6kHDAaMRgw
+FgYDVQQDEw9Vc2VyIDI5IFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEAhcnqguKs
+9rMVURG9aYExj+7T+fSO1Sc0IIl264pbAmmbl4nXa6oDf7VA+axUzo8w/T54cpGW
+3Ka9ZEL45Bga47XbCP4e/D2iVSGtDxqH3/Jlh02RUsFGwcB8zIF5l9wuQcyujI55
+TgJJfMWwPo7Z8Kprpi/n0iFbf1fo9/YAPK0=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101F.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101F.pem
new file mode 100644
index 000000000..1393b9ed3
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101F.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4127 (0x101f)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 10:26:01 2010 GMT
+ Not After : Jan 13 10:26:01 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x003\x000\x00<\x00 \x00>\x00#\x00;\x00 \x00"\x00+\x00"
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:cf:40:99:4d:a5:5d:73:2a:78:72:9c:32:94:15:
+ 1e:01:40:b4:68:8f:b8:4e:38:aa:b9:82:96:5a:5c:
+ 03:d5:db:09:42:46:d8:2d:f0:da:f8:1a:f0:85:10:
+ f2:cb:1f:be:50:b7:ae:6f:22:80:f2:bf:14:73:84:
+ da:30:b9:54:26:0d:72:1c:55:99:50:c6:78:a3:37:
+ 15:b2:9c:03:22:dc:ea:8b:f5:07:32:f3:d9:76:64:
+ 92:a3:4f:73:12:e2:43:79:0e:e6:44:17:99:79:49:
+ 73:65:da:03:3d:be:db:e3:4f:ae:6c:d0:6c:e6:4a:
+ d3:83:45:5d:83:18:d5:cc:29
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ D9:EA:10:1D:D3:F5:30:AD:30:0E:80:73:14:22:1A:26:35:90:DC:67
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 30 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 42:3a:02:d5:7b:23:9f:cc:5b:b8:d4:c8:e8:0c:e3:0d:8a:17:
+ 65:b6:87:ce:c9:dc:f7:84:95:e0:17:ea:11:8b:15:30:e1:a2:
+ 42:6c:4e:f0:31:fa:fd:ff:03:37:d4:ec:4c:1d:29:8d:07:8a:
+ c8:de:0b:d6:df:d7:2e:12:8a:00:a0:ca:be:48:af:17:36:63:
+ 8e:f2:cf:80:8b:a1:e2:33:ef:42:db:91:d3:8e:4b:02:55:5e:
+ f7:79:11:5c:6d:ef:64:8b:53:a6:af:f5:0f:e2:75:7a:d6:85:
+ f6:60:d5:7e:d6:8c:0e:37:84:a9:50:2b:c7:e6:63:bf:1d:14:
+ aa:bf
+-----BEGIN CERTIFICATE-----
+MIICyDCCAjGgAwIBAgICEB8wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDI2
+MDFaFw0zNTAxMTMxMDI2MDFaMHkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxKTAnBgNVBAMeIABVAHMAZQByACAAMwAwADwAIAA+ACMAOwAgACIAKwAiMIGf
+MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPQJlNpV1zKnhynDKUFR4BQLRoj7hO
+OKq5gpZaXAPV2wlCRtgt8Nr4GvCFEPLLH75Qt65vIoDyvxRzhNowuVQmDXIcVZlQ
+xnijNxWynAMi3OqL9Qcy89l2ZJKjT3MS4kN5DuZEF5l5SXNl2gM9vtvjT65s0Gzm
+StODRV2DGNXMKQIDAQABo3gwdjALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFNnqEB3T
+9TCtMA6AcxQiGiY1kNxnMB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZV
+MCcGA1UdEQQgMB6kHDAaMRgwFgYDVQQDEw9Vc2VyIDMwIFJvb3QgMTEwDQYJKoZI
+hvcNAQEFBQADgYEAQjoC1Xsjn8xbuNTI6AzjDYoXZbaHzsnc94SV4BfqEYsVMOGi
+QmxO8DH6/f8DN9TsTB0pjQeKyN4L1t/XLhKKAKDKvkivFzZjjvLPgIuh4jPvQtuR
+045LAlVe93kRXG3vZItTpq/1D+J1etaF9mDVftaMDjeEqVArx+Zjvx0Uqr8=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1020.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1020.pem
new file mode 100644
index 000000000..40e90d4cb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1020.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4128 (0x1020)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 10:28:47 2010 GMT
+ Not After : Jan 13 10:28:47 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x003\x001\x00 \x00\\x00"\x00a\x00,\x00b\x00"\x00+\x00C\x00N\x00=\x00U\x00S\x00,\x00 \x00>\x00 \x00\\x00\\x00d\x00e\x00 \x00<
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:ac:02:18:e0:1c:54:bb:76:97:2e:d3:67:78:b7:
+ 14:78:46:83:7c:e9:5c:2b:2f:25:bb:bf:90:c0:52:
+ ea:2c:79:d6:9d:af:b5:f8:86:a2:bf:56:9b:0f:33:
+ ed:ef:d2:2c:57:c6:0a:25:b3:f7:9b:a1:7a:3b:75:
+ 0b:18:86:23:64:2a:23:b0:60:f1:d8:05:b4:a6:7b:
+ 77:21:30:b4:0d:f1:af:e1:fb:d6:88:a8:5b:5d:7e:
+ a2:bf:ce:20:f6:c0:7a:89:f2:0f:33:47:6d:49:0f:
+ 3d:59:27:f9:95:c0:3b:a3:1c:18:a1:2d:95:09:e8:
+ d2:95:ac:10:92:fc:db:84:e3
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ F8:BA:7E:78:BC:70:33:D3:45:68:37:59:3A:06:AC:65:B1:15:74:F0
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 31 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 0f:a8:53:f0:56:76:df:a8:b3:5b:d1:e8:98:62:8f:a6:13:96:
+ c3:6b:ca:3f:e1:09:37:54:6f:ac:15:4b:74:0c:6c:3f:fe:de:
+ 36:58:a2:9d:a0:1f:18:97:2c:1d:bc:c6:df:ee:aa:5b:d3:da:
+ 2f:51:02:7a:ba:a9:7e:4d:cf:47:16:0b:f1:b1:e1:28:2b:fe:
+ a4:9d:50:96:cd:c5:45:09:35:50:93:9b:97:a9:23:2a:5e:f0:
+ 2e:16:18:3f:50:7a:83:59:c5:6c:79:99:d3:ea:12:ef:15:a9:
+ b0:93:1e:4b:26:6c:63:13:7f:d3:5a:0c:4d:0b:f4:51:21:98:
+ 4f:81
+-----BEGIN CERTIFICATE-----
+MIIC5TCCAk6gAwIBAgICECAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDI4
+NDdaFw0zNTAxMTMxMDI4NDdaMIGVMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MUUwQwYDVQQDHjwAVQBzAGUAcgAgADMAMQAgAFwAIgBhACwAYgAiACsAQwBO
+AD0AVQBTACwAIAA+ACAAXABcAGQAZQAgADwwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAKwCGOAcVLt2ly7TZ3i3FHhGg3zpXCsvJbu/kMBS6ix51p2vtfiGor9W
+mw8z7e/SLFfGCiWz95uhejt1CxiGI2QqI7Bg8dgFtKZ7dyEwtA3xr+H71oioW11+
+or/OIPbAeonyDzNHbUkPPVkn+ZXAO6McGKEtlQno0pWsEJL824TjAgMBAAGjeDB2
+MAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQU+Lp+eLxwM9NFaDdZOgasZbEVdPAwHwYD
+VR0jBBgwFoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAW
+BgNVBAMTD1VzZXIgMzEgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQAPqFPwVnbf
+qLNb0eiYYo+mE5bDa8o/4Qk3VG+sFUt0DGw//t42WKKdoB8YlywdvMbf7qpb09ov
+UQJ6uql+Tc9HFgvxseEoK/6knVCWzcVFCTVQk5uXqSMqXvAuFhg/UHqDWcVseZnT
+6hLvFamwkx5LJmxjE3/TWgxNC/RRIZhPgQ==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1021.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1021.pem
new file mode 100644
index 000000000..443c07462
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1021.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4129 (0x1021)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Jan 19 10:40:59 2010 GMT
+ Not After : Jan 13 10:40:59 2035 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x001\x004\x00 \x00"\x00,\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:da:7a:30:0d:63:da:74:05:ef:3e:d2:f4:2b:1b:
+ 50:e3:64:67:98:7d:2f:83:e7:77:7b:b8:72:9b:c8:
+ 9e:65:de:cc:2a:7b:76:c2:08:05:7a:ce:88:3e:ed:
+ b5:75:89:36:d2:4a:bb:3b:66:ac:57:2b:15:99:c9:
+ d4:74:ca:f5:eb:ff:80:b7:9f:6b:48:2f:3b:a7:51:
+ c4:12:af:96:ca:ac:b9:ea:23:fd:93:f7:7d:5b:d1:
+ ab:7c:24:1e:fe:48:dc:33:de:45:d6:8c:86:5a:b9:
+ 56:3c:e4:a9:f1:8c:d7:41:01:da:04:2a:7d:06:c3:
+ 5b:a4:cc:5f:6c:ef:7c:4e:ef
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 49:E2:AE:12:D7:EF:C3:B5:02:65:DD:CF:B2:62:E6:25:ED:3D:10:9C
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DirName:/CN=User 14 Root 11
+ Signature Algorithm: sha1WithRSAEncryption
+ 8b:ca:d2:93:cb:d1:cc:a9:67:a3:be:75:cf:ca:cd:22:78:cc:
+ 7c:f9:f1:2c:94:2c:60:bd:0f:18:16:26:fe:de:0d:19:5a:87:
+ de:34:8c:1f:eb:89:37:74:63:d4:d9:cd:59:35:06:24:a5:6f:
+ f2:c6:69:f4:b5:37:6d:ae:8b:d3:5d:5e:43:8f:36:7d:f8:0c:
+ 30:3f:74:3d:e2:85:89:75:58:36:0f:df:72:17:47:22:c6:fd:
+ 47:e3:d6:73:d1:40:89:e8:9a:ba:53:14:5c:3a:de:a9:85:a8:
+ 8f:b0:27:81:4d:87:ef:bb:6b:bf:8c:8a:71:9b:94:1d:30:d5:
+ 12:ed
+-----BEGIN CERTIFICATE-----
+MIIC1TCCAj6gAwIBAgICECEwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDQw
+NTlaFw0zNTAxMTMxMDQwNTlaMIGFMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt
+YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt
+ZW50MTUwMwYDVQQDHiwAVQBzAGUAcgAgADEANAAgACIALABtAGkAZABkAGwAZQAg
+AHEAdQBvAHQAZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2nowDWPadAXv
+PtL0KxtQ42RnmH0vg+d3e7hym8ieZd7MKnt2wggFes6IPu21dYk20kq7O2asVysV
+mcnUdMr16/+At59rSC87p1HEEq+Wyqy56iP9k/d9W9GrfCQe/kjcM95F1oyGWrlW
+POSp8YzXQQHaBCp9BsNbpMxfbO98Tu8CAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0G
+A1UdDgQWBBRJ4q4S1+/DtQJl3c+yYuYl7T0QnDAfBgNVHSMEGDAWgBToarvCkOps
+cCI+9vZIGwPmvremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAxNCBS
+b290IDExMA0GCSqGSIb3DQEBBQUAA4GBAIvK0pPL0cypZ6O+dc/KzSJ4zHz58SyU
+LGC9DxgWJv7eDRlah940jB/riTd0Y9TZzVk1BiSlb/LGafS1N22ui9NdXkOPNn34
+DDA/dD3ihYl1WDYP33IXRyLG/Ufj1nPRQInomrpTFFw63qmFqI+wJ4FNh++7a7+M
+inGblB0w1RLt
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1022.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1022.pem
new file mode 100644
index 000000000..690260575
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1022.pem
@@ -0,0 +1,64 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4130 (0x1022)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Nov 8 10:51:39 2010 GMT
+ Not After : Nov 8 10:51:39 2011 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 35
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:9b:36:00:64:f3:ce:93:97:62:19:fa:78:d9:6f:
+ 92:6a:b9:d2:9a:4e:06:2c:02:52:cd:93:50:84:28:
+ 19:42:a2:4a:34:e2:cd:e6:b0:39:7a:c8:4d:84:bc:
+ 71:51:ed:5d:6c:7e:f9:cc:01:5a:4b:73:50:a9:3b:
+ 5d:ad:cc:89:f7:dc:e0:dd:0a:ff:48:01:a9:34:19:
+ c0:6a:ee:4b:20:f4:cf:3c:94:c1:ae:88:0f:c9:42:
+ 1a:a6:47:31:fe:37:04:00:bb:ec:07:5f:cb:ee:70:
+ c4:c7:7c:6f:ee:03:19:76:de:0b:df:d0:48:91:67:
+ 55:9b:90:91:f4:ce:56:04:d5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 91:47:AC:29:95:5D:EF:72:14:8F:82:45:07:E2:94:49:75:C6:7D:73
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DNS:alt.openoffice.org, IP Address:192.168.7.1, IP Address:13:0:0:0:0:0:0:17, email:my@other.address, Registered ID:1.2.3.4, othername:<unsupported>, DirName:/C=DE/O=OpenOffice.org/OU=Development/CN=User 32 Root 11, URI:http://my.url.here/
+ Signature Algorithm: sha1WithRSAEncryption
+ 6e:80:e6:1e:86:3d:d2:65:a6:17:fa:80:2d:2e:dc:85:32:05:
+ a1:69:82:e1:79:d1:dc:de:69:cd:9e:f0:cc:90:75:a9:45:ee:
+ 73:46:fe:29:69:c0:99:bb:fc:3a:db:c0:5f:69:c6:b7:ea:9a:
+ 63:b2:8e:29:2c:a5:5a:88:88:94:75:4b:ab:0a:72:f6:3a:aa:
+ 5d:6b:3a:5c:b6:9b:57:f5:c1:51:af:df:3c:a6:8a:a3:da:70:
+ 66:61:49:12:06:78:98:9f:bc:78:3c:43:6d:08:94:aa:32:b6:
+ f3:cc:af:0d:29:fe:96:47:7d:fe:4a:61:48:90:11:0b:bd:0f:
+ a0:fd
+-----BEGIN CERTIFICATE-----
+MIIDajCCAtOgAwIBAgICECIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDExMDgxMDUx
+MzlaFw0xMTExMDgxMDUxMzlaMGAxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxEDAOBgNVBAMTB1VzZXIgMzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
+AJs2AGTzzpOXYhn6eNlvkmq50ppOBiwCUs2TUIQoGUKiSjTizeawOXrITYS8cVHt
+XWx++cwBWktzUKk7Xa3Miffc4N0K/0gBqTQZwGruSyD0zzyUwa6ID8lCGqZHMf43
+BAC77Adfy+5wxMd8b+4DGXbeC9/QSJFnVZuQkfTOVgTVAgMBAAGjggExMIIBLTAL
+BgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJFHrCmVXe9yFI+CRQfilEl1xn1zMB8GA1Ud
+IwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMIHdBgNVHREEgdUwgdKCEmFsdC5v
+cGVub2ZmaWNlLm9yZ4cEwKgHAYcQABMAAAAAAAAAAAAAAAAAF4EQbXlAb3RoZXIu
+YWRkcmVzc4gDKgMEoB4GAyoDBKAXDBVzb21lIG90aGVyIGlkZW50aWZpZXKkWDBW
+MQswCQYDVQQGEwJERTEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT
+C0RldmVsb3BtZW50MRgwFgYDVQQDEw9Vc2VyIDMyIFJvb3QgMTGGE2h0dHA6Ly9t
+eS51cmwuaGVyZS8wDQYJKoZIhvcNAQEFBQADgYEAboDmHoY90mWmF/qALS7chTIF
+oWmC4XnR3N5pzZ7wzJB1qUXuc0b+KWnAmbv8OtvAX2nGt+qaY7KOKSylWoiIlHVL
+qwpy9jqqXWs6XLabV/XBUa/fPKaKo9pwZmFJEgZ4mJ+8eDxDbQiUqjK288yvDSn+
+lkd9/kphSJARC70PoP0=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/private/cakey.pem
new file mode 100644
index 000000000..fb0dd164e
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,F268674FF1377D42
+
+kJQy9qJMCqZyDVs3+ZKQnh22enecltKSYzd0S1dIN1chgQ0RzLEiWBHmHCVP/yB0
+YoKrQ07FUR/uSLqTbyhAl+KDVcNvqrj/NeWs0n8zqN0ZF6wQtxtDrWFWmHNAvQXU
+2kO1CvjYiruapgwmVDDJV1qf25byenQv9LMyQMD6EPU1XqFeamklidALdkb7DylA
+WL6EIg4vhh96ZaG6PwLcB9rho0QRrXrLS6SHiklNBN5fHUWOfDyhXJ7K4HvzH1SS
+/EtqgyKKxH5irTRdoJg2OaDBAahyW93CneEnFdufDgzvCdrsg79Z2GFz7TDJEfW4
+rnoqoXTdei1Ah+t1BC4uXXAU8DR0xusnJi0qJDJ7ETRBhROlNhTRF8TAHll+5dIf
+9772GwVT+hADZn1qJgmhPiN4f8Fx33k5NOcwb0X/0Z1mzULrwm1P6lng0DsusDo0
+dr/wFyRjWZEWhMcL/sIO1BwVTBPcE8CACnXutehs44DBWd91EQ4+PWNq7oPtHFw8
+09d30h4aJJZF/SGRi+f/czFyZF4WS2Q+UWmNNKJX8wCGQqzUb02kVwMEWHiNFiEo
+V8xI3JXVmKHDWlgdoIz9kVe//3AfY5y+52cYLdqaNW8IsgWZC8SC9Lk9j5uaNZ/I
+leNppt4ID7mfYPqjEXEKleC+1ncwFwdVl/zaa/fM78sWqDYrLZC47DToLfoQ9Gez
+3dj3554iHTe61Jd7JsK85pYsrIHAeYppOpqzLyQmCu3twBl3uGD7KXxvdZRt8foE
+Vrg/QSIB4E6gfSBP0UrXzsnga8tjVyqRW2vAvt0uLn945ducapf9oQ==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_11/demoCA/serial
new file mode 100644
index 000000000..b70608fe8
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/serial
@@ -0,0 +1 @@
+1023
diff --git a/xmlsecurity/test_docs/CAs/Root_11/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_11/openssl.cfg
new file mode 100644
index 000000000..dd84cb906
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_11/openssl.cfg
@@ -0,0 +1,298 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+utf8 = yes
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask =pkix
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+commonName_default =User 14 \",middle quote
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+#nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+subjectAltName=DNS:alt.openoffice.org,IP:192.168.7.1,IP:13::17,email:my@other.address,RID:1.2.3.4,otherName:1.2.3.4;UTF8:some other identifier,dirName:dir_sect,URI:http://my.url.here/
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+[dir_sect]
+C=DE
+O=OpenOffice.org
+OU=Development
+CN=User 32 Root 11
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_2/demoCA/cacert.pem
new file mode 100644
index 000000000..e64badeef
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/cacert.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDBDCCAm2gAwIBAgIJAKKvFYnsc1SGMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV
+BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y
+ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMjAeFw0wOTEx
+MTgxNTQ2NTJaFw0zNDExMTIxNTQ2NTJaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAsJSDLnSsoNY1U8hS0g5cmu7ihp+nvDvx8C75Wav80KumG9gcS3icmSOm
+vPVqUmJq5o9CKM8z4vJR7D3e+Wf7S7XHMdL0uXuQi+QQCB1aMAWMxo7xnoWAXZrS
+LG1BWUjD9sdKCHuQfFQv9ke3cA2dGZFSMsUD73JYoo0RD72ftFkCAwEAAaOBxzCB
+xDAdBgNVHQ4EFgQUX7xM2usKDLUjQ14kMid5QfWCowIwgZEGA1UdIwSBiTCBhoAU
+X7xM2usKDLUjQ14kMid5QfWCowKhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMoIJAKKvFYnsc1SGMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAqfEPhXASt24n8P9mDKisEn2EIYmJKLaY
+AVwXLPXUOiMlqrfPRKpseQII4WmDCRxMa6bKCwf4pKUWIpTpDhRZCUespaLz1AcU
+ntv+HTXq1ECK+akK33fsh5qMvokfzZM+Q0zCiFV/c2aTTGSM5mV3/q810RUlNQY3
+1y+AN+6fRqE=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Root_2/demoCA/crl/DO_NOT_CREATE_A_CRL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/crl/DO_NOT_CREATE_A_CRL
diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_2/demoCA/crlnumber
new file mode 100644
index 000000000..83b33d238
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/crlnumber
@@ -0,0 +1 @@
+1000
diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt
new file mode 100644
index 000000000..3e79e22d7
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt
@@ -0,0 +1 @@
+V 341112155538Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 2
diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_2/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..36a8eb3c0
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/newcerts/1000.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 2
+ Validity
+ Not Before: Nov 18 15:55:38 2009 GMT
+ Not After : Nov 12 15:55:38 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:f0:7a:16:4c:ab:06:b2:af:27:9c:7d:3f:86:da:
+ de:7a:c3:01:67:77:56:49:09:ed:ed:31:72:83:e8:
+ 75:9c:4c:ce:f9:97:b6:63:3c:e2:ca:83:80:92:03:
+ 9c:96:e2:de:72:79:c1:cf:3e:3f:b9:0d:b4:87:c7:
+ 75:e6:56:8d:aa:f8:77:47:11:4e:fe:07:b0:1d:64:
+ 06:73:4b:6f:d4:ac:da:0f:05:87:b1:f1:98:a9:f5:
+ 8a:a1:a8:ed:17:9c:26:b8:da:92:63:d2:53:87:e6:
+ fc:ed:44:de:94:56:90:3e:a2:a1:67:08:cb:38:d4:
+ cf:17:3b:7e:ff:7a:97:c0:7b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 8C:F3:2C:30:A2:E8:62:50:70:BC:FC:71:A0:41:FA:E0:58:B4:4D:B8
+ X509v3 Authority Key Identifier:
+ keyid:5F:BC:4C:DA:EB:0A:0C:B5:23:43:5E:24:32:27:79:41:F5:82:A3:02
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 2
+ serial:A2:AF:15:89:EC:73:54:86
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 52:83:16:ab:0e:43:2d:b3:e4:0f:6c:c1:63:d4:86:ac:e7:1e:
+ ee:7b:ee:9b:0c:ff:4f:e0:59:d5:e4:27:af:68:bf:a7:f5:2a:
+ a3:c9:e3:2b:8d:b7:31:26:f6:04:80:4e:f2:a5:bf:da:63:5e:
+ 8c:d6:c6:b2:46:a0:46:10:2f:84:9f:02:76:f3:c8:33:05:62:
+ 0c:5f:2d:cc:06:23:53:9f:d9:f8:46:e4:2e:5c:da:05:fc:bf:
+ db:45:b4:ac:8d:8b:b5:4b:60:7b:7b:26:34:7f:b1:4b:41:96:
+ 41:26:70:7a:9d:78:a2:9b:e0:de:62:a2:04:86:9f:ed:7c:a6:
+ 20:eb
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAyMB4XDTA5MTExODE1NTUz
+OFoXDTM0MTExMjE1NTUzOFowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAyMIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDwehZMqwayryecfT+G2t56wwFnd1ZJCe3tMXKD6HWcTM75l7ZjPOLK
+g4CSA5yW4t5yecHPPj+5DbSHx3XmVo2q+HdHEU7+B7AdZAZzS2/UrNoPBYex8Zip
+9YqhqO0XnCa42pJj0lOH5vztRN6UVpA+oqFnCMs41M8XO37/epfAewIDAQABo4HH
+MIHEMB0GA1UdDgQWBBSM8ywwouhiUHC8/HGgQfrgWLRNuDCBkQYDVR0jBIGJMIGG
+gBRfvEza6woMtSNDXiQyJ3lB9YKjAqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAyggkAoq8ViexzVIYwDwYDVR0TAQH/
+BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBSgxarDkMts+QPbMFj1Ias5x7ue+6b
+DP9P4FnV5CevaL+n9SqjyeMrjbcxJvYEgE7ypb/aY16M1sayRqBGEC+EnwJ288gz
+BWIMXy3MBiNTn9n4RuQuXNoF/L/bRbSsjYu1S2B7eyY0f7FLQZZBJnB6nXiim+De
+YqIEhp/tfKYg6w==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_2/demoCA/private/cakey.pem
new file mode 100644
index 000000000..7ef7ef0a5
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,52B792B2B0E03BD6
+
+GIFY+N2q5LMcrtTplZUToF0/nuplr7ASLAe7lEcDLTTHeBTO+w4ScB62Dl6veeEU
+3/pPevG+V3HIA5ukywX334DuWjL3bFIsPg8a3NKKn0nTpmwqHqXZ53kbSMHIiu6v
+MkvGeVLLxLhnCsqQ8HI2ccuxGSXLA0rqlnrZTOtvQpw9ohpCM3CX1GeekLc83bL/
+4HHmw8nNL+OCH4l9g3Y8XpN3ySRgl+lWmoKxl9s2Mn7jFoaqSXuuH3wIu9D2kJxS
+qfVs/fo12j8RWXSIMpiCJFCOx1v+zzX7dJ0cyim83WF2OHsOW03UYnWzgk44iz4d
+/WVWJuRU3gEwpN3CDdhzBZuYw9DmaG8HLHYT15CSdkQrfHeFM3Axcoju7b887JX7
+sOHU6h4ebMVhAswAXKGlTKOY2PO1GE9cKoa2jxnB2z8Dhe8rxzuvWyr5BfXrS3KT
+lM6pjxZSoGMcmG7FtDgU/aAIn+DPR/rdB7tfZwP3GoVV+n3jRi8LU5I3wbi4z70o
+bwXMb7zN13WHFszZgPX4tHD3jjyLwk7rFmMJ17L3K6eOAlGg8o+FBgoqYFQo05sY
+2SElOibX8RIj9m9lerNLOxB5ty2VDUSaytJ0b1gPTXAdsaryq7tKFxIrNKpiJ1qk
+snQSJyr2JwRqBLRwkXZV5CliWwZJGGJsC9I5fAMuuW6qkDhsSQ1fIJsGn/SbbiZj
+lnZVY/33vHMltbwEgY4GuQWm29VYJwLWk925BY/nQ5fWPARYsap04JIwtperrZKj
+XETzTrnTje6sVl32aCLdYlwsVbh04zRwUFharCz5vtDdVeHrfsBDKA==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_2/demoCA/serial
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/serial
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Root_2/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_2/openssl.cfg
new file mode 100644
index 000000000..0dd15bd9e
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_2/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_3/demoCA/cacert.pem
new file mode 100644
index 000000000..55be15521
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/cacert.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDBDCCAm2gAwIBAgIJAJVv8OMrvnb5MA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV
+BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y
+ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMzAeFw0wOTEx
+MjAwNzM2MTVaFw0zNDExMTQwNzM2MTVaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEA3L6zaGhxFC+Mf55dzotmPKxdZndlxSVVOVI93JrxKVfn8mYOCZEjdb9Q
+65vgLxGXMC9LCiF6SfT8dIfav1hUugmLaLzBesPu6h4kHN33/7Asj8BzY5I57uvF
+sMLNL5hHFRRqtBqHvmO2G8zjHPluObnBzaQNCbdZxYODeh1GFpECAwEAAaOBxzCB
+xDAdBgNVHQ4EFgQUaf8w7B80mmc6ayDS33/1BQTt+RwwgZEGA1UdIwSBiTCBhoAU
+af8w7B80mmc6ayDS33/1BQTt+RyhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgM4IJAJVv8OMrvnb5MA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEABPdAJer/8FoOAMWszhfz/BEjF97TTFs1
+KqSEiuymswG706weo9tcnP8u81AITQPSWZE1ALQN5L35Zvg6ubJsNM3+VSoQ6hZj
+G9oWAJzFN7DhIqs3Xb13eBH/0yqAdTuFB5uLcJdR3GIXGFvcU/5FZBpYnORVqvg4
+irKv2VvyCR0=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_3/demoCA/crlnumber
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/crlnumber
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt
new file mode 100644
index 000000000..dd9a47ee6
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt
@@ -0,0 +1 @@
+V 341114074039Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 3
diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_3/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..c14880b58
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/newcerts/1000.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 3
+ Validity
+ Not Before: Nov 20 07:40:39 2009 GMT
+ Not After : Nov 14 07:40:39 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 3
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:9e:87:1f:af:f0:a0:1c:f4:9e:f8:c3:e7:ee:d3:
+ cb:a8:e2:54:98:ba:dd:7e:dc:6e:14:e1:7e:7f:5b:
+ 1e:ef:53:3d:89:76:ea:e2:b3:6c:08:0d:e8:c8:4d:
+ 24:40:ff:92:f3:5b:51:f7:90:ac:69:37:29:90:f5:
+ e8:95:6f:67:d1:10:cd:7b:dd:65:38:d6:25:ec:63:
+ 39:ba:2e:ea:13:58:8e:7a:82:8e:10:d1:7b:77:7a:
+ 08:d5:82:66:62:a4:83:39:ad:f5:83:d5:2f:5c:bc:
+ 23:6e:c8:78:8b:38:9f:eb:a3:67:ba:43:fa:e4:07:
+ 3f:90:72:db:0c:f9:49:0e:0d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 1B:2D:E0:A2:26:7F:0D:BA:38:7E:EC:06:81:81:0F:12:74:4C:5A:4D
+ X509v3 Authority Key Identifier:
+ keyid:69:FF:30:EC:1F:34:9A:67:3A:6B:20:D2:DF:7F:F5:05:04:ED:F9:1C
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 3
+ serial:95:6F:F0:E3:2B:BE:76:F9
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 6f:ac:53:9d:16:6e:95:ed:97:60:ed:c8:a8:96:ab:24:c5:1e:
+ d5:d7:26:98:fb:b5:aa:ef:da:a4:91:6a:82:55:ec:21:a2:08:
+ 24:c7:0c:a7:58:0c:06:69:3d:04:7d:08:f1:0b:77:41:ad:1c:
+ 13:c2:bd:17:c9:9e:ff:df:64:69:8b:58:f1:bc:40:bd:cf:e4:
+ 57:29:bc:5e:93:84:61:56:4c:e6:c1:3a:2c:6e:71:ea:5d:67:
+ c0:54:be:4f:2f:27:a8:59:8d:29:94:ba:c6:6c:ff:ed:25:3d:
+ 0b:fa:93:c9:45:f4:d5:a3:3d:be:8a:f1:9d:c4:92:d5:5c:d2:
+ 77:7c
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAzMB4XDTA5MTEyMDA3NDAz
+OVoXDTM0MTExNDA3NDAzOVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAzMIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQCehx+v8KAc9J74w+fu08uo4lSYut1+3G4U4X5/Wx7vUz2Jduris2wI
+DejITSRA/5LzW1H3kKxpNymQ9eiVb2fREM173WU41iXsYzm6LuoTWI56go4Q0Xt3
+egjVgmZipIM5rfWD1S9cvCNuyHiLOJ/ro2e6Q/rkBz+QctsM+UkODQIDAQABo4HH
+MIHEMB0GA1UdDgQWBBQbLeCiJn8Nujh+7AaBgQ8SdExaTTCBkQYDVR0jBIGJMIGG
+gBRp/zDsHzSaZzprINLff/UFBO35HKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAzggkAlW/w4yu+dvkwDwYDVR0TAQH/
+BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBvrFOdFm6V7Zdg7ciolqskxR7V1yaY
++7Wq79qkkWqCVewhoggkxwynWAwGaT0EfQjxC3dBrRwTwr0XyZ7/32Rpi1jxvEC9
+z+RXKbxek4RhVkzmwTosbnHqXWfAVL5PLyeoWY0plLrGbP/tJT0L+pPJRfTVoz2+
+ivGdxJLVXNJ3fA==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_3/demoCA/private/cakey.pem
new file mode 100644
index 000000000..445d86f99
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,24B61B9BC2D90894
+
+pJUmVTVcjD3b4WKoSDJHrxHYOJ5/6P0FyQRYaJhnDXpcC5cQywl7yuD3HpRh3cXT
+Y5k6d1E64St3I/IDImdbiEEDbjlSG9gfFf9vYeP/Xlpaja0Y9Q2ePnQvJY47HB7+
+qkrt6b+3yIW024wHi83dzaeYeNUJaY1jGsra2TzGk/+hYrf6yvnyehEAsy5WChof
+bfaQ29RrGTlzf6IpSRpiHUL7nVl+eHfbGLX4Ih8aEFXpcnoWtpY8FgQ5+bJxMeR4
+R2ge0c3G0VIBXBRRUoGsU0ZcRLdxYUFcDGZse50ZboUwvROfPCimowcyWKluV9yj
+l4+e3glYcwGHRqHYArsLDUV2hzHHEJ1IKn4E+oExqQSGgDQgUDN0kjlRPPxWQb29
+6dZSHW4VXW609Q10FKbPuCocgQ2Ut2bNGWqXsiNNTr39iB0r/hA/V4bKy3G8ogsH
+AQFp6D9LaFlt9ZFA49Y4WoPzSY9J2C4eFJzQ+jhCpeapzQ54BWNTYMQe+SJHkp1O
+PWVovUrRbTDesIUeY1UJuSnbDotOc6vzEAsP+FIL2qUySUGG/CPyAf3R4FyahwjL
+bgU5kmpzBKsgqRYrO2yfLz5/3/e9xUGfHVi8lbI5f21NQKesqHY2xS2NmGvakzbe
+ZvD3bhythAR5L0Pp+tiiHE1LUAbcKp90aFPeaONDpUtrRU21gqqvEKnnubCvnjmE
+l6GrH2WKSgxJbQ3GGqNaDg1ivB8XXyjx7guvBzpA0Pe2YCYMa0RI27GywNkv+RsR
+eo3ox2QhUpvPxUl3ijwOPN3EFXrq0gdlYQJBWW3GLlX4Q71KJF+jUQ==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_3/demoCA/serial
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/serial
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Root_3/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_3/openssl.cfg
new file mode 100644
index 000000000..51e520525
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_3/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Root_4/README.txt b/xmlsecurity/test_docs/CAs/Root_4/README.txt
new file mode 100644
index 000000000..b9fb278a2
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_4/README.txt
@@ -0,0 +1,4 @@
+Revoked certificates:
+
+- Sub CA 2 Root 4
+
diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_4/demoCA/cacert.pem
new file mode 100644
index 000000000..45b4ce8a5
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/cacert.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDBDCCAm2gAwIBAgIJAKKTRnQ7puOtMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV
+BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y
+ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNDAeFw0wOTEx
+MjAwODM1MDRaFw0zNDExMTQwODM1MDRaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEA2k+jPArotoY09an0BpF3RYIPP/5RN04E4S+Ulp/ipttaVxtAC0ojJSlp
+0PGp/vIodFT9pkBb0nq56LHjFLj+lyW5tKAR+4B+VVvzwJhUBD8qHjYJE30vWZ88
+3+3I+GmXDzy962kQxrb4J6dBwGImoqhBTXWOxGnPjXxtovzYmMECAwEAAaOBxzCB
+xDAdBgNVHQ4EFgQUuo2hl9zEOR+QtVFrEBnyRg2pZY4wgZEGA1UdIwSBiTCBhoAU
+uo2hl9zEOR+QtVFrEBnyRg2pZY6hY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNIIJAKKTRnQ7puOtMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEARdHX1KRJ/DE1zOkbjINPX4pFjTMIIfKd
+ncEBM7Po20it75Hbl8bHoxwCrjOu+9L1xaTCWcunyqv26yrjVpORPHPODLMc2W8x
+FQm39hL6a0RjqurDlhcrjor3HD7hQ+GjEUDAX6Pk9RDxN+uMHvF5/5WCEhSn2aLT
+IozGu5SmZys=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_4/demoCA/crlnumber
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/crlnumber
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt
new file mode 100644
index 000000000..f07b3377d
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt
@@ -0,0 +1,2 @@
+V 341114083727Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 4
+R 341114092227Z 091120092718Z,keyCompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 2 Root 4
diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..391037118
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1000.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 4
+ Validity
+ Not Before: Nov 20 08:37:27 2009 GMT
+ Not After : Nov 14 08:37:27 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 4
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:da:b0:21:94:89:b0:00:89:cb:69:59:9b:0d:fe:
+ 1f:b9:a0:a8:44:92:55:5f:0b:d5:e5:08:63:bd:47:
+ 6b:11:4d:b1:a8:12:6f:c1:cf:cb:9e:ae:e2:c1:03:
+ 68:46:59:0b:96:7c:21:45:9b:14:81:d8:f1:83:70:
+ 6b:3d:b4:56:65:49:87:1d:ab:e2:08:6a:49:66:0e:
+ 59:b4:da:7a:3f:72:23:b8:1f:fb:78:f5:f0:2d:c4:
+ fe:d9:94:6e:2e:c3:6e:95:ba:38:60:d1:0b:fa:16:
+ c7:02:71:ef:3e:71:72:63:26:56:35:1e:8b:ec:47:
+ 87:25:6e:bc:90:d0:8b:37:2d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 96:9A:2D:06:F6:76:4F:83:68:7B:9C:69:C4:18:BB:4A:EB:46:38:E4
+ X509v3 Authority Key Identifier:
+ keyid:BA:8D:A1:97:DC:C4:39:1F:90:B5:51:6B:10:19:F2:46:0D:A9:65:8E
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 4
+ serial:A2:93:46:74:3B:A6:E3:AD
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 45:77:ba:6b:b6:a7:2a:0f:6b:38:90:9f:0a:18:11:c7:54:7b:
+ c9:3b:9a:93:90:96:f0:04:0a:56:87:30:e0:f5:d8:84:40:39:
+ 90:85:ca:e7:38:1b:d8:df:2f:bd:73:91:13:cb:a6:c9:b0:7a:
+ f7:59:77:6b:9a:d5:86:78:06:dc:40:14:ce:ea:43:a8:ae:ed:
+ a2:03:64:51:3a:47:7a:9f:df:2d:65:49:56:a5:39:cf:28:2a:
+ ac:ab:fd:e1:93:fd:3e:56:e8:eb:7a:11:a8:f7:f9:1a:a1:83:
+ 1f:92:f7:da:4e:c6:d9:67:dd:67:ff:be:6f:e5:24:e1:6e:cc:
+ 94:3c
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0MB4XDTA5MTEyMDA4Mzcy
+N1oXDTM0MTExNDA4MzcyN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA0MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDasCGUibAAictpWZsN/h+5oKhEklVfC9XlCGO9R2sRTbGoEm/Bz8ue
+ruLBA2hGWQuWfCFFmxSB2PGDcGs9tFZlSYcdq+IIaklmDlm02no/ciO4H/t49fAt
+xP7ZlG4uw26Vujhg0Qv6FscCce8+cXJjJlY1HovsR4clbryQ0Is3LQIDAQABo4HH
+MIHEMB0GA1UdDgQWBBSWmi0G9nZPg2h7nGnEGLtK60Y45DCBkQYDVR0jBIGJMIGG
+gBS6jaGX3MQ5H5C1UWsQGfJGDalljqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0ggkAopNGdDum460wDwYDVR0TAQH/
+BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBFd7prtqcqD2s4kJ8KGBHHVHvJO5qT
+kJbwBApWhzDg9diEQDmQhcrnOBvY3y+9c5ETy6bJsHr3WXdrmtWGeAbcQBTO6kOo
+ru2iA2RROkd6n98tZUlWpTnPKCqsq/3hk/0+VujrehGo9/kaoYMfkvfaTsbZZ91n
+/75v5SThbsyUPA==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1001.pem
new file mode 100644
index 000000000..9d951ee26
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1001.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 4
+ Validity
+ Not Before: Nov 20 09:22:27 2009 GMT
+ Not After : Nov 14 09:22:27 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 4
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:e5:8d:27:4e:09:53:08:61:c6:23:25:9e:dd:9c:
+ 07:bf:81:38:5c:5c:10:8f:e4:12:2f:4e:2e:b1:a1:
+ cf:21:46:53:bf:e8:5e:de:17:3a:9d:f7:e8:ef:3e:
+ 9c:b4:29:37:4c:31:35:15:dc:98:e0:93:9c:ce:6a:
+ d6:e1:35:19:6b:d4:1d:3b:81:86:b1:e7:ff:1f:b8:
+ 34:a9:f9:de:4d:b8:62:ac:3b:d4:58:8e:5c:76:b5:
+ 07:7f:32:8a:3a:90:73:71:d5:da:f1:79:39:14:ed:
+ 1b:f1:8a:3e:be:48:bc:07:ec:f9:7c:03:14:fc:e7:
+ 55:a3:65:81:c7:6c:70:0b:ff
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 69:DE:B6:99:C4:95:F7:5A:FA:41:6B:4C:F6:C3:6D:89:AA:37:31:9D
+ X509v3 Authority Key Identifier:
+ keyid:BA:8D:A1:97:DC:C4:39:1F:90:B5:51:6B:10:19:F2:46:0D:A9:65:8E
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 4
+ serial:A2:93:46:74:3B:A6:E3:AD
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ bc:cf:43:eb:72:b1:71:a7:94:8e:cd:5b:fc:d8:21:31:83:db:
+ a9:de:c7:5b:14:e5:7b:90:43:e6:05:df:db:6e:95:5f:24:ac:
+ 0c:a1:8a:ac:c6:cf:f2:03:cd:a0:30:ae:d3:a9:41:07:c9:b1:
+ be:4b:e0:fc:a2:76:09:07:75:6a:fa:e4:2f:a3:3a:cd:81:68:
+ ab:f6:06:c4:32:08:25:6e:e8:e7:36:9c:1a:f7:42:73:f8:b0:
+ d8:42:3e:85:c2:11:23:10:d6:6a:e4:8f:53:cb:8b:8b:1b:5a:
+ 4d:6d:9d:34:45:26:52:d2:ee:6d:8f:23:ff:00:92:f5:99:62:
+ 4c:41
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAm+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0MB4XDTA5MTEyMDA5MjIy
+N1oXDTM0MTExNDA5MjIyN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA0MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDljSdOCVMIYcYjJZ7dnAe/gThcXBCP5BIvTi6xoc8hRlO/6F7eFzqd
+9+jvPpy0KTdMMTUV3Jjgk5zOatbhNRlr1B07gYax5/8fuDSp+d5NuGKsO9RYjlx2
+tQd/Moo6kHNx1drxeTkU7Rvxij6+SLwH7Pl8AxT851WjZYHHbHAL/wIDAQABo4HH
+MIHEMB0GA1UdDgQWBBRp3raZxJX3WvpBa0z2w22JqjcxnTCBkQYDVR0jBIGJMIGG
+gBS6jaGX3MQ5H5C1UWsQGfJGDalljqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0ggkAopNGdDum460wDwYDVR0TAQH/
+BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQC8z0PrcrFxp5SOzVv82CExg9up3sdb
+FOV7kEPmBd/bbpVfJKwMoYqsxs/yA82gMK7TqUEHybG+S+D8onYJB3Vq+uQvozrN
+gWir9gbEMgglbujnNpwa90Jz+LDYQj6FwhEjENZq5I9Ty4uLG1pNbZ00RSZS0u5t
+jyP/AJL1mWJMQQ==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_4/demoCA/private/cakey.pem
new file mode 100644
index 000000000..003d2f3b5
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,26D3AA1ECCD64EF2
+
+Smy62JNi1/1qKZI1q2lF13336vwJWfw+ii4g/ZwMJWuwTWUGXWZ1o9B9pZFo78KM
+pMlasoCwAoI3lepMIwxtSRMgstxacJ4QRVPdevo7Qq6+++qNXdkqq9pYM19dsOiu
+UNpbPXVvKQZnvm0ZFCjqiylvjCaQVQRScdwu9cJyq2qIQ1laXQoW2fPYBb8KSsCO
+B5E76zAGdRlzEglT9Qkjbi2dQWxWpMHFfWZydFJnNbuh7O+RxCSOJN3jXlDRGPag
+IwL4mFX8dElCwWhNpdd1pXF2ZXQ2S6Ke1MoOXRvJ7XVvEfnGyHpHQRdNB0M9gJCf
+3ynJ0UUiCvXJs/6NEcOZzZ+R38XfMvsOcG1jNuh2KE5hW3cGbQMV2TPZMHjGE/qn
+EhX+vzIOhRUPTUQjrjmV/lgioL4pMKFBXyfr2tkNLVOfzQtIXVfgxF1ooVmZFGKR
+fAmHRbXKSrGWPJkX75bdlVnQ15qz5dU7PkIohGwGojOHuTWLXzKtOuLs7KMmH/i1
+5MhxcoXbI4R+hX/oj2Es4MKYFcSI0MID9Z5Se6z/yaz++5P9OrEGrXydg4W5YSuc
+Q+MovUuqNoDH+Mo0z2P2DL4OxcIkBYoUVFOnIL2v5thRgbdWk05m0OBWYnvue9MG
+CiuA49Lqg0H2ViZrDCyGDQNBkDkW7AKHYhVe3afHSDENX+wsgB1oj1bMvWNLQfCB
+2IOYjv+of7tNOvIH6AuaJDqF2TYOm4ipcjSD/SEuKfrOgXlq6702tRhL4aAfHa6K
+o1yrUfAxLwqN/TjSDNfOIUr5ro24tYnUaUnYPpn/zwZ5WfitZ4RGBg==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_4/demoCA/serial
new file mode 100644
index 000000000..7d802a3e7
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/serial
@@ -0,0 +1 @@
+1002
diff --git a/xmlsecurity/test_docs/CAs/Root_4/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_4/openssl.cfg
new file mode 100644
index 000000000..51e520525
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_4/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_5/demoCA/cacert.pem
new file mode 100644
index 000000000..631deb24d
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/cacert.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDBDCCAm2gAwIBAgIJAPA9tqmpnKNOMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV
+BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y
+ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNTAeFw0wOTEx
+MjAxMDEwMzdaFw0zNDExMTQxMDEwMzdaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAwbqFK0+BWGylCl9gJj/eVuuNBcSgVetgx0cXwMRPHiwFZ8ilxPJm4kd0
+k2WDKHox5Ol8T0pU4n3fA5VmxjcfGnx03R8rFTn5deetrKQzyWUjz7EIl4mZYSvK
+hwlbg5ZB4FJDYUoC/3eVHdQq2jUvRaQad1TvdBmvIMbDaYmTT3cCAwEAAaOBxzCB
+xDAdBgNVHQ4EFgQUwdGg1FsLnX4xYfk5EJ8xEODSBrUwgZEGA1UdIwSBiTCBhoAU
+wdGg1FsLnX4xYfk5EJ8xEODSBrWhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNYIJAPA9tqmpnKNOMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAeX2QYyrs9an5ObWjzauPCzr8hx6k8dF3
+YXU8f/JCf/fKG5u5WQZmmu0YZXMSaDyzqS3rKupDSm4kbfB9l9oTkgZszueI29pd
+C/QIh8vUTiAlV5zxR4ypqmBg489W/uXdQPicuFhGFYX9EWjuGhwk8dL0dcUCufwX
+UBYBlUiceFU=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Root_5/demoCA/crl/DO_NOT_CREATE_A_CRL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/crl/DO_NOT_CREATE_A_CRL
diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_5/demoCA/crlnumber
new file mode 100644
index 000000000..83b33d238
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/crlnumber
@@ -0,0 +1 @@
+1000
diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt
new file mode 100644
index 000000000..d910b9acc
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt
@@ -0,0 +1 @@
+V 341114113023Z 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 5
diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_5/demoCA/newcerts/1001.pem
new file mode 100644
index 000000000..b350f6eb3
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/newcerts/1001.pem
@@ -0,0 +1,66 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 5
+ Validity
+ Not Before: Nov 20 11:30:23 2009 GMT
+ Not After : Nov 14 11:30:23 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 5
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:97:fa:a2:49:d3:bf:c1:2e:7a:ed:83:83:3c:78:
+ 96:c8:b2:b9:67:af:c0:5e:0a:89:89:fb:94:59:32:
+ a8:2a:e4:20:2f:3b:3d:ce:53:4f:72:fc:6c:0b:93:
+ 38:c3:df:66:6e:d5:79:d0:a4:4e:41:84:43:3c:99:
+ 79:0c:e0:5f:19:1a:3d:f5:4b:11:28:0f:80:b0:a0:
+ 71:34:5b:90:71:c2:ef:1e:85:2e:5b:9f:3b:22:c3:
+ 18:f8:7c:1f:ef:1b:78:17:a0:44:60:46:7e:88:eb:
+ a7:60:a0:5c:2a:7c:37:99:fa:27:97:08:e8:89:ba:
+ bc:69:4b:79:93:8f:ad:b5:9b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 01:E9:B5:99:E4:6D:F9:8C:42:3D:09:10:0F:A7:75:C6:27:78:4A:AF
+ X509v3 Authority Key Identifier:
+ keyid:C1:D1:A0:D4:5B:0B:9D:7E:31:61:F9:39:10:9F:31:10:E0:D2:06:B5
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 5
+ serial:F0:3D:B6:A9:A9:9C:A3:4E
+
+ X509v3 CRL Distribution Points:
+ URI:http://localhost:8901/demoCA/crl/Root_5.crl
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 6d:ca:34:05:99:ff:99:49:d3:6d:9d:ad:c6:99:da:9d:6c:94:
+ 62:77:ed:1c:39:23:d2:e8:b6:3e:df:63:dc:7c:10:3f:c2:ed:
+ f4:04:26:58:05:01:4c:ed:a9:83:43:3a:5d:fe:60:6d:5b:58:
+ dc:93:8c:94:69:b6:7f:02:48:30:9c:31:f4:7d:de:e0:de:04:
+ d2:dc:79:b7:60:c2:87:f7:c7:92:a2:f5:86:a7:0c:70:3b:a3:
+ a7:35:11:cf:a4:28:21:aa:8b:24:50:2e:96:41:be:66:01:bd:
+ b9:ec:04:0c:92:d9:8a:e7:a0:96:24:9b:f1:a2:9f:59:59:4a:
+ 32:a4
+-----BEGIN CERTIFICATE-----
+MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA1MB4XDTA5MTEyMDExMzAy
+M1oXDTM0MTExNDExMzAyM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA1MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQCX+qJJ07/BLnrtg4M8eJbIsrlnr8BeComJ+5RZMqgq5CAvOz3OU09y
+/GwLkzjD32Zu1XnQpE5BhEM8mXkM4F8ZGj31SxEoD4CwoHE0W5Bxwu8ehS5bnzsi
+wxj4fB/vG3gXoERgRn6I66dgoFwqfDeZ+ieXCOiJurxpS3mTj621mwIDAQABo4IB
+BjCCAQIwHQYDVR0OBBYEFAHptZnkbfmMQj0JEA+ndcYneEqvMIGRBgNVHSMEgYkw
+gYaAFMHRoNRbC51+MWH5ORCfMRDg0ga1oWOkYTBfMQswCQYDVQQGEwJERTEQMA4G
+A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT
+C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDWCCQDwPbapqZyjTjA8BgNVHR8E
+NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290
+XzUuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAbco0BZn/
+mUnTbZ2txpnanWyUYnftHDkj0ui2Pt9j3HwQP8Lt9AQmWAUBTO2pg0M6Xf5gbVtY
+3JOMlGm2fwJIMJwx9H3e4N4E0tx5t2DCh/fHkqL1hqcMcDujpzURz6QoIaqLJFAu
+lkG+ZgG9uewEDJLZiuegliSb8aKfWVlKMqQ=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_5/demoCA/private/cakey.pem
new file mode 100644
index 000000000..222320a9a
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,5F2D7F26BBEBD8FB
+
+qFyJ/G/DFwA+Kx3cVldc6bOMRbbduL7x5DBjCqS20YfoQoyvDcyel8FYz4/8CQ9d
+kmb4nrM0Dj8/FgDiite2E8+qJV4U8OIBsXelFd8FWC8hB4z0DtwVxIAiM6mTMMcu
+bWta3Lu5xrNvU/vosB967COztoYB5XLLQ/DrRPoV+tvJx0Le3zXLzceIj4PicuIk
+/Mh5NVqN5a5blaV1/1JvcfOQLCI0rNebP3iAYhwCkKyu6WkpSNuHIw5gaMC6KXpq
+ORPf3m+3/YKHLS9/tg+9CPQrRpyzLV/TOUduq6HFfzh9ZRXd04Dpn0P61JVCypYo
+9u62lnNCAtreyvCUttzANLgujbgT9HNsjzKTAD2g+zjwQPgIS4epNm5LBPsQv15A
+Vuw7CnNlLa8PxUxuDUjoW2YaGUR3PHNUz+TA1U0UFxlNK/lgeekIvmSvPjVyROOB
+SxOH88yAZWe6pWioS3uzeg1kf1F5sj9u+KHPyikUe3nUBrS1cZSRtQczhlWWocgm
+GtfwQSSVSwRtd7CWe/nQHuSJyrIJCbWFaDhnVXRhr+tyDpLtoeApCvefvel0p/AY
+LTaRcno3zUxZS3G8Cv71hBPR8y5di5dAxBSfLgMYxwBD3UFO6CPkmiJteIhHska9
+FJqR98hfvF+0hwFnaFUTszDMGK1xV20MeTMhLAwSlttbuwtWMTourFKtS6t1SomB
+JOTkpiVfojTSAJX40ExQgNtvY+7ayNUBLX9NIuIcOjFbQa1LNmGy9cOPQD49x067
+fALGA+V1KO7sFeUrunkpHncYoux5OThq3iDJ2tPfBmyhTQhOSzN38w==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_5/demoCA/serial
new file mode 100644
index 000000000..7d802a3e7
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/serial
@@ -0,0 +1 @@
+1002
diff --git a/xmlsecurity/test_docs/CAs/Root_5/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_5/openssl.cfg
new file mode 100644
index 000000000..0ea6df297
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_5/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_5.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Root_6/README.txt b/xmlsecurity/test_docs/CAs/Root_6/README.txt
new file mode 100644
index 000000000..e49615a51
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_6/README.txt
@@ -0,0 +1,5 @@
+To provide the CRL via HTTP run
+
+java -jar ../../tools/httpserv/dist/httpserv.jar -a 8901
+
+
diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_6/demoCA/cacert.pem
new file mode 100644
index 000000000..5a7fc185b
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/cacert.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDBDCCAm2gAwIBAgIJANhqTyT5yZQnMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV
+BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y
+ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNjAeFw0wOTEx
+MjAxMjI2MDFaFw0zNDExMTQxMjI2MDFaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAslt6KM0bikDy8n0lNMeaNQiZk9Pcfsf6Vaasn9A8FABFn1chxV5zOMag
+jo6CyZG1CNLhA841RtgiWVMc8BA+pDKzOQAzfgSk4VjXaY8nYgKEmGDKuNvls+kE
+OKMkJibh/scNMDUOx8Bnc6S9LyYJAhZFrxm/lgmoIo7QMcdseIsCAwEAAaOBxzCB
+xDAdBgNVHQ4EFgQUrCVem7W6TY69d7Kd2eKErnoxj/IwgZEGA1UdIwSBiTCBhoAU
+rCVem7W6TY69d7Kd2eKErnoxj/KhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNoIJANhqTyT5yZQnMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAU6Sjyeo650mhSGK8JJBhDroVJgAryVF4
+wXEKWxK0yuO0TVZJxUWeHOESpegBW1eP5m9Pz0IHnxj6MsGBYq7SZU84awt4HJto
+6O1ARZYfT9r+qTts33I/VVQVTJbvETF1vGsuAZfTTDhAJDqS2oueiPDSinzQxNMy
+16L4Rajm8LE=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/Root_6.crl b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/Root_6.crl
new file mode 100644
index 000000000..df6dcb21e
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/Root_6.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crlnumber
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crlnumber
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt
new file mode 100644
index 000000000..7f0df0d95
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt
@@ -0,0 +1 @@
+V 341114122807Z 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 6
diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_6/demoCA/newcerts/1001.pem
new file mode 100644
index 000000000..0490b88cd
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/newcerts/1001.pem
@@ -0,0 +1,66 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 6
+ Validity
+ Not Before: Nov 20 12:28:07 2009 GMT
+ Not After : Nov 14 12:28:07 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 6
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:c4:d9:ab:27:06:66:41:0e:36:ff:d4:b1:d0:8c:
+ f7:b4:25:55:cd:fd:fa:a4:5a:e6:4f:d0:05:dc:a3:
+ e5:bd:8d:53:77:d1:ea:95:5a:52:81:c8:b6:36:a0:
+ 5f:3a:e1:85:1e:8a:48:91:7d:29:78:ff:ea:c5:e3:
+ ad:c4:27:d5:b7:8f:59:20:26:d4:45:87:6a:56:db:
+ ac:f5:f8:0a:88:82:9e:c2:00:06:fc:98:8a:fe:35:
+ c3:02:a1:67:08:06:42:e3:88:48:e0:8f:33:ff:f8:
+ a4:87:1a:3a:d9:54:0e:1c:09:3e:a0:f0:70:cd:b5:
+ b0:b2:7e:07:73:ad:20:64:69
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 89:8C:D7:71:EB:67:78:4E:D6:01:35:B2:AC:A1:B4:88:43:CE:70:A7
+ X509v3 Authority Key Identifier:
+ keyid:AC:25:5E:9B:B5:BA:4D:8E:BD:77:B2:9D:D9:E2:84:AE:7A:31:8F:F2
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 6
+ serial:D8:6A:4F:24:F9:C9:94:27
+
+ X509v3 CRL Distribution Points:
+ URI:http://localhost:8901/demoCA/crl/Root_6.crl
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 55:5b:3b:6b:8a:d0:1b:d8:19:d9:96:85:4d:b4:a0:98:b1:bd:
+ 9f:0b:62:21:92:8b:4e:d3:d0:1b:91:3d:e3:f5:bd:ce:16:57:
+ fc:b7:84:15:51:fd:98:ab:32:59:28:0b:44:57:49:ec:ac:11:
+ 67:26:7a:a3:c5:b8:9d:2a:de:b6:7c:76:0a:e9:18:9f:98:87:
+ e8:80:c8:72:99:56:74:ab:73:1b:f4:e7:b9:b1:3a:f3:7b:0d:
+ 2f:5d:82:6c:d1:99:9f:23:be:23:fb:4c:0e:15:5e:f5:9f:90:
+ 88:d7:51:3a:6a:7a:f0:54:a5:c4:89:a5:0d:0a:4e:94:59:64:
+ 59:54
+-----BEGIN CERTIFICATE-----
+MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA2MB4XDTA5MTEyMDEyMjgw
+N1oXDTM0MTExNDEyMjgwN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA2MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDE2asnBmZBDjb/1LHQjPe0JVXN/fqkWuZP0AXco+W9jVN30eqVWlKB
+yLY2oF864YUeikiRfSl4/+rF463EJ9W3j1kgJtRFh2pW26z1+AqIgp7CAAb8mIr+
+NcMCoWcIBkLjiEjgjzP/+KSHGjrZVA4cCT6g8HDNtbCyfgdzrSBkaQIDAQABo4IB
+BjCCAQIwHQYDVR0OBBYEFImM13HrZ3hO1gE1sqyhtIhDznCnMIGRBgNVHSMEgYkw
+gYaAFKwlXpu1uk2OvXeyndnihK56MY/yoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G
+A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT
+C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDaCCQDYak8k+cmUJzA8BgNVHR8E
+NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290
+XzYuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAVVs7a4rQ
+G9gZ2ZaFTbSgmLG9nwtiIZKLTtPQG5E94/W9zhZX/LeEFVH9mKsyWSgLRFdJ7KwR
+ZyZ6o8W4nSretnx2CukYn5iH6IDIcplWdKtzG/TnubE683sNL12CbNGZnyO+I/tM
+DhVe9Z+QiNdROmp68FSlxImlDQpOlFlkWVQ=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_6/demoCA/private/cakey.pem
new file mode 100644
index 000000000..166be0166
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,BADC417CBCEF5888
+
+5vIfuyyd2rgqSPUElPa2YM8on+FeoYuAIB+mfVHy0nSGisUKjmQQACaeTVD+aO6S
+UFBz3W/RJXCj/8x5+ZYa8Rj44DeSwlDrxSy5VBrWegOzujfGPqrzwCL/ASKGPPFN
+RwK0i0niJsj6+oQOGgP6AIb08reX1tkT0GItwQMjIQAFETcDP8m1sA1kFpLhvBCF
+dHyw0lfnh+NZ9nnpAdpVXwt8teccLUyEHARNscebg8vqjc2gRxi3KpT3pURg0dUc
+eaGH8DIB5CuAYW2Mo1LLRQ0uvkFgSl56WcolYiRTy2KUMW7Gz7oBA5Qyb9lz25yV
+9djt4Hrs9cI1p1TGmvSklGPKJUaTf0Yrf0XRkS6xknFVX4zzkbD4vYFelITSxeMT
+pPVbjLSWiIo+mqBuW6i+LUNMt45b1RWM96pomrPRrGne4saJOkhVXTvv/pR4KB+S
+J2iwlEDNOwzkxeqSB7lJuzIce/iUqERAzlXe8e0VVgy0P0UfOIViLWS98cuqR86H
+P1rMYtWilAkLKBUYo+lS7f/3YD8E3V10XdBmYJFvmpHPXM2SP5HQZXtoNCXJNcvB
+aAlb3c7InxfqLLn+kH6WgPzXXcXO7cxlZ3cXBbJf3IhRT3aBEnAH+s+DDCi0RCII
+UiLOnrgfOEZuNyRhGin9R7WFRtnGYJjHTP54FMOY0f0Rj7ElT+xymeAZE8wyXKfi
+MWDgswTYYkcC7uPJAJ8HnLtFixr9aEriug7yemGyr686oX8gLPdwrYwPYJBt7Q+b
+0nf22SoMqMNWSCWcr89sc1AIb0ebX+FxtsN6j45ztEjZGjXYkk2iXQ==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_6/demoCA/serial
new file mode 100644
index 000000000..7d802a3e7
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/serial
@@ -0,0 +1 @@
+1002
diff --git a/xmlsecurity/test_docs/CAs/Root_6/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_6/openssl.cfg
new file mode 100644
index 000000000..f49c11090
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_6/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_6.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Root_7/README.txt b/xmlsecurity/test_docs/CAs/Root_7/README.txt
new file mode 100644
index 000000000..056f1b133
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_7/README.txt
@@ -0,0 +1,10 @@
+Revoked certificates:
+
+- Sub CA 2 Root 7
+
+
+To provide the CRL via HTTP run
+
+java -jar ../../tools/httpserv/dist/httpserv.jar -a 8901
+
+
diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_7/demoCA/cacert.pem
new file mode 100644
index 000000000..01761f55b
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/cacert.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDBDCCAm2gAwIBAgIJANXmY18YCYKJMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV
+BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y
+ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNzAeFw0wOTEx
+MjAxMzA0NDhaFw0zNDExMTQxMzA0NDhaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAvG//bRySIKOz1hmmH6qx02wtf2ZO2skK/wxPnTAd+LLuH2upOfGkaFCi
+hd1zsIshs9/TjtLNa4nplkYSvZlYBsbpIuNQZrEedbvLYV/zNdsnLfht+aX3yMuk
+q1dh2BI0LdwXiyMyPwATJwQ96AXq/a+cZi1ZRBToCztZArJK/xMCAwEAAaOBxzCB
+xDAdBgNVHQ4EFgQUgMb4C198SeSG/ciSxoBw2cBve94wgZEGA1UdIwSBiTCBhoAU
+gMb4C198SeSG/ciSxoBw2cBve96hY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgN4IJANXmY18YCYKJMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAg15QATKSYmz+XGtnBLDnWu2Gk59nglH4
+gG3p1xiVVgOyQVGsvNr+3ETPTTcf6x+ap1+AHE9SJJ0/WQSuUHtOv6y/prp4MWbw
+/QBL2WHS7adTFWxOJ/VWpb8GhTtJdG9PKYeSmVAtC1qzdI1zsjPYvHO3UJnokDkB
+fY7kpaTJprg=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/Root_7.crl b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/Root_7.crl
new file mode 100644
index 000000000..0eefbda68
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/Root_7.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crlnumber
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crlnumber
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt
new file mode 100644
index 000000000..24c353872
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt
@@ -0,0 +1,2 @@
+V 341114130753Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 7
+R 341114133506Z 091120133621Z,keyCompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 2 Root 7
diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..2dda8f2b2
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1000.pem
@@ -0,0 +1,66 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 7
+ Validity
+ Not Before: Nov 20 13:07:53 2009 GMT
+ Not After : Nov 14 13:07:53 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 7
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:b0:ae:6d:0a:21:ae:8a:92:b1:16:25:d3:08:cb:
+ ac:b7:4c:53:6d:4b:b3:12:82:40:54:c9:44:28:fc:
+ 4e:10:e6:65:40:de:70:5d:8b:ab:1f:5c:77:03:43:
+ 3d:3a:3d:9e:f7:37:66:9a:33:68:a0:cf:ad:8f:f4:
+ fb:9c:a3:87:57:5d:ec:d6:55:5a:18:b5:e1:2b:d2:
+ c4:10:fe:f0:01:a5:da:29:ee:c4:af:15:c9:8c:dc:
+ 7c:45:84:bd:e5:5b:09:1f:16:1d:11:e7:61:e6:22:
+ e7:1f:c8:86:bf:a1:da:cb:fe:6b:7e:c0:6e:aa:7f:
+ 97:84:e8:8f:81:69:f1:26:87
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 54:64:15:7E:93:8A:19:C8:F9:B7:EF:60:A0:DF:5C:C8:15:56:C0:EE
+ X509v3 Authority Key Identifier:
+ keyid:80:C6:F8:0B:5F:7C:49:E4:86:FD:C8:92:C6:80:70:D9:C0:6F:7B:DE
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 7
+ serial:D5:E6:63:5F:18:09:82:89
+
+ X509v3 CRL Distribution Points:
+ URI:http://localhost:8901/demoCA/crl/Root_7.crl
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 1a:bc:5a:4b:9a:d5:e8:c0:35:c2:61:0a:58:7d:33:e2:87:01:
+ 61:83:80:42:8d:1a:7e:b1:9a:58:d5:01:fd:e7:ae:5c:c8:65:
+ fb:9e:1d:bf:49:ba:ed:40:f4:05:7c:3b:2d:db:0e:53:d0:05:
+ a0:bd:15:87:c4:37:22:0b:a0:04:a3:ad:cb:57:b2:00:97:ee:
+ 8f:89:91:8e:7d:0b:e2:27:96:6e:0f:ab:73:33:59:fa:9f:37:
+ f2:77:79:99:af:72:ad:f9:49:05:ed:55:08:31:eb:97:0f:99:
+ 6e:9c:a3:df:f0:52:1a:14:4e:78:25:0c:8b:02:cb:56:e9:4d:
+ f5:9f
+-----BEGIN CERTIFICATE-----
+MIIDRjCCAq+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA3MB4XDTA5MTEyMDEzMDc1
+M1oXDTM0MTExNDEzMDc1M1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA3MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQCwrm0KIa6KkrEWJdMIy6y3TFNtS7MSgkBUyUQo/E4Q5mVA3nBdi6sf
+XHcDQz06PZ73N2aaM2igz62P9Puco4dXXezWVVoYteEr0sQQ/vABpdop7sSvFcmM
+3HxFhL3lWwkfFh0R52HmIucfyIa/odrL/mt+wG6qf5eE6I+BafEmhwIDAQABo4IB
+BjCCAQIwHQYDVR0OBBYEFFRkFX6TihnI+bfvYKDfXMgVVsDuMIGRBgNVHSMEgYkw
+gYaAFIDG+AtffEnkhv3IksaAcNnAb3veoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G
+A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT
+C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDeCCQDV5mNfGAmCiTA8BgNVHR8E
+NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290
+XzcuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAGrxaS5rV
+6MA1wmEKWH0z4ocBYYOAQo0afrGaWNUB/eeuXMhl+54dv0m67UD0BXw7LdsOU9AF
+oL0Vh8Q3IgugBKOty1eyAJfuj4mRjn0L4ieWbg+rczNZ+p838nd5ma9yrflJBe1V
+CDHrlw+Zbpyj3/BSGhROeCUMiwLLVulN9Z8=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1001.pem
new file mode 100644
index 000000000..0d2a0f02a
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1001.pem
@@ -0,0 +1,66 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 7
+ Validity
+ Not Before: Nov 20 13:35:06 2009 GMT
+ Not After : Nov 14 13:35:06 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 7
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:f9:3f:5e:76:52:9a:ce:5d:98:b0:00:d8:e0:65:
+ e7:78:11:4c:7b:c7:e2:d3:44:bf:8e:60:42:69:3e:
+ 75:67:65:24:ab:f7:07:d8:9d:be:0f:23:b5:c1:26:
+ 00:6b:c3:22:84:72:a9:96:dc:5f:63:fc:f5:e0:e3:
+ cc:da:0c:74:e9:31:51:91:89:27:8f:e5:17:41:6e:
+ 3d:5e:2a:13:cd:08:f7:f3:61:34:a1:f7:79:c6:bd:
+ 5d:2c:34:01:ea:5a:8c:48:97:36:d6:57:e0:80:03:
+ 2e:7a:03:83:4c:bd:b4:af:a2:fd:d7:4b:1a:f7:ab:
+ 9f:5a:22:2b:d1:25:73:dd:6f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 3B:50:26:45:6C:E2:FE:28:B1:71:0A:A8:95:2D:78:63:8E:2C:48:92
+ X509v3 Authority Key Identifier:
+ keyid:80:C6:F8:0B:5F:7C:49:E4:86:FD:C8:92:C6:80:70:D9:C0:6F:7B:DE
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 7
+ serial:D5:E6:63:5F:18:09:82:89
+
+ X509v3 CRL Distribution Points:
+ URI:http://localhost:8901/demoCA/crl/Root_7.crl
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 5f:b4:70:11:4f:d9:df:6a:6a:5a:4a:97:fe:8b:5d:9e:46:84:
+ e2:27:67:41:7c:a9:2e:9d:77:cc:e4:8c:d6:16:3c:39:7d:51:
+ 29:60:80:32:4f:a1:d0:b4:7f:2a:e5:60:f4:b8:d3:3b:94:f8:
+ a5:fb:15:99:cf:a9:c5:a7:59:c1:11:89:67:11:9c:ff:a9:ac:
+ dd:ca:a9:92:a8:60:26:c3:ab:74:41:86:b9:4d:1e:4a:c5:de:
+ 63:e6:da:2a:36:39:7b:6c:66:f3:20:57:d1:f1:36:4b:69:c5:
+ 04:a3:1f:cf:de:0c:10:d0:3f:07:e2:8e:0f:cd:41:26:c9:2e:
+ e9:1b
+-----BEGIN CERTIFICATE-----
+MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA3MB4XDTA5MTEyMDEzMzUw
+NloXDTM0MTExNDEzMzUwNlowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA3MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQD5P152UprOXZiwANjgZed4EUx7x+LTRL+OYEJpPnVnZSSr9wfYnb4P
+I7XBJgBrwyKEcqmW3F9j/PXg48zaDHTpMVGRiSeP5RdBbj1eKhPNCPfzYTSh93nG
+vV0sNAHqWoxIlzbWV+CAAy56A4NMvbSvov3XSxr3q59aIivRJXPdbwIDAQABo4IB
+BjCCAQIwHQYDVR0OBBYEFDtQJkVs4v4osXEKqJUteGOOLEiSMIGRBgNVHSMEgYkw
+gYaAFIDG+AtffEnkhv3IksaAcNnAb3veoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G
+A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT
+C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDeCCQDV5mNfGAmCiTA8BgNVHR8E
+NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290
+XzcuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAX7RwEU/Z
+32pqWkqX/otdnkaE4idnQXypLp13zOSM1hY8OX1RKWCAMk+h0LR/KuVg9LjTO5T4
+pfsVmc+pxadZwRGJZxGc/6ms3cqpkqhgJsOrdEGGuU0eSsXeY+baKjY5e2xm8yBX
+0fE2S2nFBKMfz94MENA/B+KOD81BJsku6Rs=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_7/demoCA/private/cakey.pem
new file mode 100644
index 000000000..147ca4e9b
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B17A06040862AC63
+
+9VJMswLGoelYtmpO17/f34Lb7j1I2vaK+RUg7fH09M6rQKurA2SmpsO7kJo7lMUb
+lwXEC8+JC5b3OoUcPeHLkZ5e9bB+flMJQq+bkzWs4NWYI17gRs2Tc74xm04XRTsO
+OYU+H7uOyRMAuS86hkQF13H3hCHcZkg8RZcvqfDXhsY8S7iyp0gErQv8IDmbIije
+R7go3NdZXCmkuINKhhABFYnPxnEpaHxhIMNKykbSn+jby02LX57X/u4JDGfkzjCH
+wyJMi9PiO7VbXvi8IPYnFz0IaCMVr5cltTh47/KiqACeAADQ6ETekrX9r7lngkRz
+sqFuyqEtdi02ujElsGIaDCImQ5KbD2u2IQ3FX2b6Jwmd/uDmqQQwtEfarEoUxich
+chCEUBGAiqRxLcrnRzjT+Reqgx7qGNurjP78kmKeD91hDm3tEHeWtecy4iA3C8z0
+aMZFOZLx1r7kf5/YaRMREcLPmreEWgFmkIMN004GdIvOwlsUjmAM7UMle+cef17v
+h1hxbFsznzYLBk0zOYjmsTpI3dQHtxSUVsyUWXXVJ0Y4YhJSjMHlMOOCanGYOpGS
+vipUNzLx4aIWfMmQdJePQM4uxO2FNwTc1IGyRpoOhj6vxroICuGK3WkxqZsN3VwR
+hwNol0cNMNHbVacKvhh5PQJcmWiqmLEXaQD8VWgCNQVa0otS59vj+SeyW4ZvULBM
+Od/9FhFfEBHQDxNSL+c6B/dXFIO1oY159ErdElAn+NPRtQcHAsnu8HknKLhry1NP
+b4d+KZcTZAq9q97ltRQf9/hXBpA3ophMtbBFnnnh5WJuMMdDMNgGsg==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_7/demoCA/serial
new file mode 100644
index 000000000..7d802a3e7
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/serial
@@ -0,0 +1 @@
+1002
diff --git a/xmlsecurity/test_docs/CAs/Root_7/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_7/openssl.cfg
new file mode 100644
index 000000000..f2615bef4
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_7/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Root_8/README.txt b/xmlsecurity/test_docs/CAs/Root_8/README.txt
new file mode 100644
index 000000000..d749d8ebc
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_8/README.txt
@@ -0,0 +1,9 @@
+Revoked certificates:
+
+- Sub CA 2 Root 8
+
+
+Start the OCSP responder:
+openssl ocsp -index demoCA/index.txt -port 8888 -rsigner demoCA/cacert.pem -rkey demoCA/private/cakey.pem -CA demoCA/cacert.pem -text
+
+
diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_8/demoCA/cacert.pem
new file mode 100644
index 000000000..ef431ec95
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/cacert.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDBDCCAm2gAwIBAgIJALJH3moqTIMZMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV
+BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y
+ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgODAeFw0wOTEx
+MjAxNTI4NTZaFw0zNDExMTQxNTI4NTZaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgODCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAmR4R07C/I8zEPsAEQdc/nzH74hLjEwImtiWKL8nVc70fwquIRzWLaavm
+DaQE3g/ha00d2hepB2dUiR1nV2GhMYdV64eq1utEPU+tTIYpx163axOGLYLWwKc3
+cBaR2mCqZmAkS+WABHkCX9hsBn+Ju/XNxLDVcpBohVrx882+3kMCAwEAAaOBxzCB
+xDAdBgNVHQ4EFgQU1mZ2yQX/qVCIlmDd+8cwGHJnQRkwgZEGA1UdIwSBiTCBhoAU
+1mZ2yQX/qVCIlmDd+8cwGHJnQRmhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgOIIJALJH3moqTIMZMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAfZylT15q6Dnpvf9jWoCovzvUoBqAwL1Z
+UDEikhCpajYsrfXI3MRvKYkTvt18lgg2Y09gJ2vhfLBCaDp+ELUq0Vc5hIbblGGO
+EA4vBuH5Yfho3AK3gKAtk7Rc9l/qP2rBPb1JVw79pRaz95IkYGeOp35pVDQfBN+i
+jji5JSyOeYQ=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/Root_8.crl b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/Root_8.crl
new file mode 100644
index 000000000..8f91a1949
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/Root_8.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crlnumber
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crlnumber
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt
new file mode 100644
index 000000000..831cbf1a3
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt
@@ -0,0 +1,2 @@
+V 341114153321Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 8
+R 341114155533Z 091120155655Z,superseded 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 2 Root 8
diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..b2d1deb75
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1000.pem
@@ -0,0 +1,66 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 8
+ Validity
+ Not Before: Nov 20 15:33:21 2009 GMT
+ Not After : Nov 14 15:33:21 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 8
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:96:79:01:9f:4f:68:c1:09:0d:44:3a:82:e4:eb:
+ ad:70:7a:cf:b9:71:e5:fb:e0:c8:0c:21:79:3e:cb:
+ 78:91:7f:4a:a0:de:3e:37:0f:a1:6b:73:10:12:9b:
+ 08:c4:96:dc:cb:a8:5b:87:9b:75:24:e4:00:5e:4a:
+ 6f:4c:13:79:1f:57:13:8c:3e:1b:38:31:e1:77:74:
+ 52:f9:94:47:36:57:33:bd:de:08:11:a3:01:e1:53:
+ 1c:bd:7b:39:9c:5e:96:5c:a9:61:6c:cc:2b:90:8d:
+ 5a:3c:9e:f4:4b:6e:e5:97:64:86:f3:8e:e8:72:20:
+ 5d:0d:50:bf:e9:cf:be:d4:13
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ EF:BD:C8:8E:78:79:F9:76:4B:11:59:B6:C3:32:10:07:C0:BC:E3:8A
+ X509v3 Authority Key Identifier:
+ keyid:D6:66:76:C9:05:FF:A9:50:88:96:60:DD:FB:C7:30:18:72:67:41:19
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 8
+ serial:B2:47:DE:6A:2A:4C:83:19
+
+ Authority Information Access:
+ OCSP - URI:http://localhost:8888
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 4c:95:44:3b:57:08:ec:01:ec:f9:3e:7c:89:1c:30:b1:4e:26:
+ 32:b6:57:fa:25:bc:ed:eb:d4:a2:1c:67:ee:b9:8b:d0:4c:57:
+ 8a:0e:db:a0:9d:92:e7:de:c6:73:01:e7:de:61:1b:b5:0e:d0:
+ c5:c1:a7:a6:ab:e0:c6:0b:51:dd:e5:a2:32:1f:c6:52:ea:d3:
+ 03:68:3a:f5:92:bd:8b:b8:03:bb:50:70:63:cc:ec:ed:3c:11:
+ 76:ca:ac:72:47:ad:99:6b:8e:07:9e:38:f2:63:e1:ba:d4:df:
+ a9:73:54:1d:74:89:94:01:2e:68:dd:97:e7:53:f9:cf:b6:7d:
+ fc:87
+-----BEGIN CERTIFICATE-----
+MIIDOTCCAqKgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4MB4XDTA5MTEyMDE1MzMy
+MVoXDTM0MTExNDE1MzMyMVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA4MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQCWeQGfT2jBCQ1EOoLk661wes+5ceX74MgMIXk+y3iRf0qg3j43D6Fr
+cxASmwjEltzLqFuHm3Uk5ABeSm9ME3kfVxOMPhs4MeF3dFL5lEc2VzO93ggRowHh
+Uxy9ezmcXpZcqWFszCuQjVo8nvRLbuWXZIbzjuhyIF0NUL/pz77UEwIDAQABo4H6
+MIH3MB0GA1UdDgQWBBTvvciOeHn5dksRWbbDMhAHwLzjijCBkQYDVR0jBIGJMIGG
+gBTWZnbJBf+pUIiWYN37xzAYcmdBGaFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4ggkAskfeaipMgxkwMQYIKwYBBQUH
+AQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojg4ODgwDwYDVR0T
+AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBMlUQ7VwjsAez5PnyJHDCxTiYy
+tlf6Jbzt69SiHGfuuYvQTFeKDtugnZLn3sZzAefeYRu1DtDFwaemq+DGC1Hd5aIy
+H8ZS6tMDaDr1kr2LuAO7UHBjzOztPBF2yqxyR62Za44HnjjyY+G61N+pc1QddImU
+AS5o3ZfnU/nPtn38hw==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1001.pem
new file mode 100644
index 000000000..26368962e
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1001.pem
@@ -0,0 +1,66 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 8
+ Validity
+ Not Before: Nov 20 15:55:33 2009 GMT
+ Not After : Nov 14 15:55:33 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 8
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:e9:91:38:d8:c1:36:e5:c1:d0:32:e8:ae:02:11:
+ 97:e5:c5:07:8f:5b:46:3a:3c:d9:49:5e:9a:4b:51:
+ 4c:b7:7d:e9:d1:4f:a7:15:8c:c6:10:f6:fa:5f:a9:
+ 0b:1b:bc:de:56:f5:ad:a3:a0:40:f1:75:10:58:74:
+ 37:f9:b7:9f:76:ca:46:96:4c:1a:81:f4:a2:ce:88:
+ 8b:9e:00:6d:42:b3:d6:68:d1:67:d6:9f:b8:9c:3f:
+ 43:c7:36:bf:41:88:1b:e8:74:26:a0:51:5c:e2:ee:
+ 6d:9d:73:bb:0d:36:e1:5c:68:9f:21:3b:b2:aa:ed:
+ 39:1d:ae:fc:b4:ca:38:c2:fb
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 1B:AB:6B:0F:42:91:DC:1E:D4:7A:95:87:30:2D:CC:11:4F:35:B7:73
+ X509v3 Authority Key Identifier:
+ keyid:D6:66:76:C9:05:FF:A9:50:88:96:60:DD:FB:C7:30:18:72:67:41:19
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 8
+ serial:B2:47:DE:6A:2A:4C:83:19
+
+ Authority Information Access:
+ OCSP - URI:http://localhost:8888
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 89:f8:8d:a8:e5:0b:2a:fb:f3:6a:80:2c:26:a1:a7:36:7e:a0:
+ c5:61:65:9d:7e:d6:47:60:b4:f6:72:e9:6e:2c:d9:f8:7f:c8:
+ 7a:5d:75:98:ad:88:de:e7:1b:44:a3:96:37:84:c0:b3:20:98:
+ 3b:b5:f6:ee:70:9c:04:7a:6c:88:05:75:7f:12:cf:b9:76:e8:
+ c0:17:0c:5e:eb:10:38:1e:54:41:58:56:f6:3c:ec:07:a5:c0:
+ 74:24:34:af:b3:c7:b2:58:85:47:0f:6c:e4:a0:9f:c8:7b:5c:
+ 95:77:17:e5:ad:eb:c3:86:44:f7:81:ef:cb:58:12:1a:6a:c7:
+ 19:95
+-----BEGIN CERTIFICATE-----
+MIIDOTCCAqKgAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4MB4XDTA5MTEyMDE1NTUz
+M1oXDTM0MTExNDE1NTUzM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA4MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDpkTjYwTblwdAy6K4CEZflxQePW0Y6PNlJXppLUUy3fenRT6cVjMYQ
+9vpfqQsbvN5W9a2joEDxdRBYdDf5t592ykaWTBqB9KLOiIueAG1Cs9Zo0WfWn7ic
+P0PHNr9BiBvodCagUVzi7m2dc7sNNuFcaJ8hO7Kq7Tkdrvy0yjjC+wIDAQABo4H6
+MIH3MB0GA1UdDgQWBBQbq2sPQpHcHtR6lYcwLcwRTzW3czCBkQYDVR0jBIGJMIGG
+gBTWZnbJBf+pUIiWYN37xzAYcmdBGaFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4ggkAskfeaipMgxkwMQYIKwYBBQUH
+AQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojg4ODgwDwYDVR0T
+AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCJ+I2o5Qsq+/NqgCwmoac2fqDF
+YWWdftZHYLT2culuLNn4f8h6XXWYrYje5xtEo5Y3hMCzIJg7tfbucJwEemyIBXV/
+Es+5dujAFwxe6xA4HlRBWFb2POwHpcB0JDSvs8eyWIVHD2zkoJ/Ie1yVdxflrevD
+hkT3ge/LWBIaascZlQ==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_8/demoCA/private/cakey.pem
new file mode 100644
index 000000000..dd11db443
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1DE6DE80057C280E
+
+1pXaFFR4KgVEWQzq73tQrfEkLZn7J0G0fxp1ZZYKOVdL3g/S4su2cXn5zfkSypjG
+sTPnj9YuHzZiW1sB5M+U84b0aCSuh4+HK1Y+K6Us99psx/VaDq36uEBJZQviJ4zb
+uF7ZT6NRGWMs3pIkFEHqi9TQ6mmeRgHMgkiI/mpM/26Y00dLpXdxBIGOCpKIPXwp
+02mx/o9CHqI7ASuXV6ZAhawEmvFKKRNCKsKOaSs0CylGOT5nAaqWRp/IVMrm46wr
+o7cErGgCZCPzQ5Ndx4553oSeWTjnm4iTS5UKg0nwPgS6sVhsr3zrTxIhS9zzcW2G
+ycREX312K7q0zxtCxdNZxGeSfowRRy54JRoLf+O5yoNTRXYFjLxXGHgCTQRWgpIh
+ggOmgUyIeNQXts4Qf6ddUtEcfGzMowCAJWTakXpOBoWj42mF85lDlcAAn8V1L90Q
+MDF31HzrDAe3po4g+dNA6qdZrpSpnDDVp0oPsr3ooz1dLlwa8LWpPpq5PRgDWeQF
+hcYrywI5tfUJyXv0xkEv+BIGKjGofWHGNtZWazBunhAVgWG/GQbzWxdSBS5w2waE
+2Zo65PBqfLgRdnO6HYl15Pc5wm3gEQJo5VYgl7HmRpEt7lQrcnReqLWnsuHmqZ/H
+vaEmGnSfXauVTvBVRXnrpznM/ROC9n2FR50lNIO1nAtMM7a0S0PIKgB+uNwAtsAR
+Y4dY4YCS/io8wCL+DNBPtdvuY85/y5lnURpj9ojWO916WZsK/EFPJIQFuVwhal2C
+Q9NVu8PXPDiBAHTVGZz8HoG32eYYUtqzeIY4Xo5ybUlnsNGlncWSqw==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_8/demoCA/serial
new file mode 100644
index 000000000..7d802a3e7
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/serial
@@ -0,0 +1 @@
+1002
diff --git a/xmlsecurity/test_docs/CAs/Root_8/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_8/openssl.cfg
new file mode 100644
index 000000000..077e13b2b
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_8/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Root_9/DO_NOT_INSTALL_THIS_ROOT_CERT.txt b/xmlsecurity/test_docs/CAs/Root_9/DO_NOT_INSTALL_THIS_ROOT_CERT.txt
new file mode 100644
index 000000000..ee3d2b339
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_9/DO_NOT_INSTALL_THIS_ROOT_CERT.txt
@@ -0,0 +1 @@
+!!!DO NOT INSTALL THIS ROOT CERTIFICATE!!!
diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/DO_NO_INSTALL_THIS_ROOT_CERTIFICATE b/xmlsecurity/test_docs/CAs/Root_9/demoCA/DO_NO_INSTALL_THIS_ROOT_CERTIFICATE
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/DO_NO_INSTALL_THIS_ROOT_CERTIFICATE
diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/Root_9.crt b/xmlsecurity/test_docs/CAs/Root_9/demoCA/Root_9.crt
new file mode 100644
index 000000000..66e316546
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/Root_9.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_9/demoCA/cacert.pem
new file mode 100644
index 000000000..ca53f28f7
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/cacert.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDBDCCAm2gAwIBAgIJAKTbFg1LjNSmMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV
+BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y
+ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgOTAeFw0wOTEx
+MjMxMzUyNDNaFw0zNDExMTcxMzUyNDNaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgOTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAsOgehurKuYszsH2LFeGyHA9WYmCOMZmQfBFOgS/kO1Hkv6tNrDbshzyc
+I/qOlpkosXUbQaaJPYoQmv3eTpfYxM9Dju5GkzOL03Q9J8AGe8RW1urMCfD5fC9g
+XmhxAnIbrmDhS4K0lV8ngWwTQjmec9CV8SVBLQerrNtmcY/VvcMCAwEAAaOBxzCB
+xDAdBgNVHQ4EFgQUzTNeq3MjUYC4A60SAQvFXo5VymQwgZEGA1UdIwSBiTCBhoAU
+zTNeq3MjUYC4A60SAQvFXo5VymShY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI
+EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2
+ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgOYIJAKTbFg1LjNSmMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAqQkfiXNJm8l5v6qQzv6HwcDIgSQBuwkp
+bN5FgHdLXaae/UOelXpmLSfrAbizw0Om1xLH/tnSeNY9MCGMGA4ScGU1hdNLUTIU
+LK9upl/q+cHQayZL/Hz4Z8sqRNrP+E2m0GY0RMF1getJunfYZZV9VcsfbO3SqgAQ
+exqICFDFi8M=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_9/demoCA/crlnumber
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/crlnumber
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt
new file mode 100644
index 000000000..c741bbfda
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt
@@ -0,0 +1 @@
+V 341117135919Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 9
diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_9/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..0b38d4db4
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/newcerts/1000.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 9
+ Validity
+ Not Before: Nov 23 13:59:19 2009 GMT
+ Not After : Nov 17 13:59:19 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 9
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:a9:6d:7f:6a:08:fb:e2:3a:5e:83:3f:ff:58:ba:
+ 92:a1:79:9d:ce:d2:0c:16:15:f2:7e:b3:e4:45:9c:
+ 02:32:65:9b:02:90:78:05:95:e4:04:1d:4a:05:bb:
+ ea:f6:ac:ab:15:74:c2:bc:ee:2a:c1:80:55:3e:93:
+ 1f:5c:94:eb:cf:cf:8f:15:eb:b8:22:fe:69:61:51:
+ a9:08:b8:80:bd:48:99:da:85:10:1c:75:97:fd:d3:
+ c3:c4:0b:dd:eb:01:12:5d:ee:62:62:c3:0c:18:ea:
+ ed:76:ff:9b:1c:1f:c7:81:f9:9a:cd:e5:25:89:b2:
+ 13:57:56:f3:27:53:72:76:69
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 7B:D3:57:BF:6A:CB:6C:10:81:91:DA:95:DC:88:4F:A5:D0:DB:D1:46
+ X509v3 Authority Key Identifier:
+ keyid:CD:33:5E:AB:73:23:51:80:B8:03:AD:12:01:0B:C5:5E:8E:55:CA:64
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 9
+ serial:A4:DB:16:0D:4B:8C:D4:A6
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 17:67:b0:21:da:0d:a1:fe:09:62:d0:cf:1d:c0:c8:bd:d4:22:
+ dd:75:ec:04:e2:23:ae:ea:8c:15:fa:73:2e:83:f4:16:eb:c1:
+ e1:87:36:bd:58:d0:64:e0:6e:2c:bc:27:cb:dc:4b:58:01:80:
+ 48:27:53:bb:75:85:a7:19:b8:e2:c0:1f:9f:a2:18:27:82:3f:
+ 25:bf:17:d1:34:32:de:c4:81:9d:8a:39:6f:6b:1f:b6:12:61:
+ 74:78:96:6d:6e:52:23:4a:67:30:78:03:91:b7:89:bf:3c:4a:
+ 36:e3:95:21:38:35:af:05:55:81:05:25:91:78:ca:2f:5d:79:
+ d2:05
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA5MB4XDTA5MTEyMzEzNTkx
+OVoXDTM0MTExNzEzNTkxOVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQCpbX9qCPviOl6DP/9YupKheZ3O0gwWFfJ+s+RFnAIyZZsCkHgFleQE
+HUoFu+r2rKsVdMK87irBgFU+kx9clOvPz48V67gi/mlhUakIuIC9SJnahRAcdZf9
+08PEC93rARJd7mJiwwwY6u12/5scH8eB+ZrN5SWJshNXVvMnU3J2aQIDAQABo4HH
+MIHEMB0GA1UdDgQWBBR701e/astsEIGR2pXciE+l0NvRRjCBkQYDVR0jBIGJMIGG
+gBTNM16rcyNRgLgDrRIBC8VejlXKZKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA5ggkApNsWDUuM1KYwDwYDVR0TAQH/
+BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAXZ7Ah2g2h/gli0M8dwMi91CLddewE
+4iOu6owV+nMug/QW68Hhhza9WNBk4G4svCfL3EtYAYBIJ1O7dYWnGbjiwB+fohgn
+gj8lvxfRNDLexIGdijlvax+2EmF0eJZtblIjSmcweAORt4m/PEo245UhODWvBVWB
+BSWReMovXXnSBQ==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_9/demoCA/private/cakey.pem
new file mode 100644
index 000000000..65149ff65
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,EEC173CF380C4BEC
+
+3ZAmsMS1aFKb3EfOncYO+hg0ucK80Y7pHg7GaH2/XZ+b6HmVQrHKuDrIcQNGEY5Z
+QTCBeCGhmh7hnemBSrco4HURl/2LlA5CoYyd6CCc79VeUQZRJdLjL2thD4x/QwQs
+Vh9uG+nunEAXK2kI2sFAxCScoCXSZmAgQqAANQ3SHyJ14e8BlOVgucfD0afYEDNE
+udc86lO8+Lz7HfTvysnKO06pgp30ZFJlnBzSBXkXsTShPWEPg8f+2JRc+A5PbxVM
+gz/S/ZrPMg8QyIfwwCGjRKzyRBeXVfquXqrwNqtGI+HXo4QaYYT8zuYUn9XuJsac
+ZFn2BoXhI6TCBzyM+yuoXp+Xx5plY2A8QXaiLdKO2usV5xcXaBY3XTczrnOfJh7f
+F3B2mbfhr/s4UJaFmnG4eULklFGADRY5tN2bIutsWmuuw17/ZwUSZxsjl+TybqVi
+uvfmEqrSgoZ9Qz1vvRngVAAwJPAvQqsBQwkq3WapNeoLqmQeSHq/6z4G5RKPbkMs
+t21L4SBUGQMhkZWAnJEtECDGsQpDjjwbDuJzrbVTSBiNvDWWeXJuGdyhzI6b17v7
+CZosIrzE82Oo0C+afWJVek2cB8rIMbgqEL+3Sj7x9c/kGeLx957d+geTSStqjD3z
+P574kcEDP9ppEHalg1ygJ6t3SjkTNMWrbuYH+GlY8all7rniMDYUDMECIj3Xrv+Q
+x3Yzv07FAooDYBE4pdWtTjpBlmwxa68XaMSDG28jQwTHck30GU/gwrM74CKWsg8y
+4eZAaeQKHeUYFGsxWeYfmwr7aD4pG+VYGOmRmdia5PA=
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_9/demoCA/serial
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/serial
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Root_9/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_9/openssl.cfg
new file mode 100644
index 000000000..f48e3d5a3
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Root_9/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/cacert.pem
new file mode 100644
index 000000000..be26aa5d8
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/cacert.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 1
+ Validity
+ Not Before: Nov 18 15:07:13 2009 GMT
+ Not After : Nov 12 15:07:13 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:d9:3a:8d:64:95:87:76:76:e8:61:c3:e9:65:f4:
+ a6:b7:0c:77:0e:4b:10:e8:14:a3:e1:84:69:7c:8e:
+ 97:d2:7d:01:ad:b2:dc:5c:cd:c6:91:a1:f3:93:7c:
+ 54:36:64:e3:ca:22:ca:00:cb:c6:91:ab:6b:26:88:
+ 69:60:9a:61:d7:59:17:db:93:7d:09:36:da:28:cb:
+ ec:2d:a4:26:bb:1a:42:20:b8:08:b2:0f:b9:77:a6:
+ 80:71:cf:13:f5:37:a2:90:4d:ab:e8:97:49:d2:80:
+ 94:8f:b1:9d:5a:b4:9f:de:ff:fa:b6:d6:e0:45:5f:
+ cc:d4:10:1e:32:46:7b:ba:55
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 37:71:74:81:44:DD:1E:B1:60:96:41:B7:4B:38:C4:B7:79:1B:CF:8A
+ X509v3 Authority Key Identifier:
+ keyid:0F:FA:C6:EB:DF:CE:B8:BB:B3:A9:3E:42:A6:BA:EC:D2:93:CA:47:A4
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 1
+ serial:95:B0:05:2B:ED:C2:39:2D
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 18:f6:02:5e:75:04:5f:eb:3b:07:41:85:c0:9e:08:29:58:3d:
+ b5:6f:c2:aa:24:0d:93:1d:17:fc:be:d6:43:ac:43:d7:4d:a0:
+ 2c:40:fd:3d:d5:7e:91:46:25:49:62:ba:e9:7f:67:c2:fc:8a:
+ c3:a0:37:bf:ec:f9:54:bf:61:10:35:dd:5b:bb:da:7c:70:54:
+ 32:13:b9:ae:7d:ea:a5:7d:aa:55:3e:ef:0a:ef:12:fd:c3:f6:
+ e5:25:98:97:34:02:64:fd:88:79:b3:e2:f4:fc:ff:e7:d3:98:
+ f1:d9:d5:18:d9:b4:62:ae:99:88:61:2e:ff:02:6a:13:35:fe:
+ 37:c7
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAxMB4XDTA5MTExODE1MDcx
+M1oXDTM0MTExMjE1MDcxM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAxMIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDZOo1klYd2duhhw+ll9Ka3DHcOSxDoFKPhhGl8jpfSfQGtstxczcaR
+ofOTfFQ2ZOPKIsoAy8aRq2smiGlgmmHXWRfbk30JNtooy+wtpCa7GkIguAiyD7l3
+poBxzxP1N6KQTavol0nSgJSPsZ1atJ/e//q21uBFX8zUEB4yRnu6VQIDAQABo4HH
+MIHEMB0GA1UdDgQWBBQ3cXSBRN0esWCWQbdLOMS3eRvPijCBkQYDVR0jBIGJMIGG
+gBQP+sbr3864u7OpPkKmuuzSk8pHpKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAxggkAlbAFK+3COS0wDwYDVR0TAQH/
+BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAY9gJedQRf6zsHQYXAnggpWD21b8Kq
+JA2THRf8vtZDrEPXTaAsQP091X6RRiVJYrrpf2fC/IrDoDe/7PlUv2EQNd1bu9p8
+cFQyE7mufeqlfapVPu8K7xL9w/blJZiXNAJk/Yh5s+L0/P/n05jx2dUY2bRirpmI
+YS7/AmoTNf43xw==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crlnumber
new file mode 100644
index 000000000..83b33d238
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crlnumber
@@ -0,0 +1 @@
+1000
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt
new file mode 100644
index 000000000..e2027ce9f
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt
@@ -0,0 +1 @@
+V 341112152323Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 1
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..e7d22dfd0
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/newcerts/1000.pem
@@ -0,0 +1,58 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 1
+ Validity
+ Not Before: Nov 18 15:23:23 2009 GMT
+ Not After : Nov 12 15:23:23 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:c8:41:66:84:c7:d5:c5:72:8f:a6:98:1b:59:e2:
+ 33:ca:0d:d2:24:b3:c1:47:db:11:e2:bf:23:da:32:
+ 68:41:cc:ff:28:fe:9a:39:49:e7:08:f0:22:75:15:
+ 61:99:9e:99:e5:14:65:71:60:00:0f:58:42:70:78:
+ 5a:1e:d8:fa:97:92:82:0e:e3:0c:ac:20:dc:b8:e3:
+ 5e:87:8b:89:e3:a1:c3:87:49:1d:92:a5:fd:7c:77:
+ 79:ce:1f:fa:9c:5a:17:d9:11:0c:f2:7f:1a:fa:d8:
+ 32:41:f8:69:80:ae:8a:66:bd:36:c2:21:65:57:08:
+ be:cf:f0:ec:83:15:98:6d:65
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ FF:BB:B0:7F:E3:0E:E3:8C:CF:EC:88:49:A9:0E:62:B5:D3:60:12:46
+ X509v3 Authority Key Identifier:
+ keyid:37:71:74:81:44:DD:1E:B1:60:96:41:B7:4B:38:C4:B7:79:1B:CF:8A
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 33:dd:e8:57:3e:69:1b:a0:4c:83:51:99:dd:73:b0:0c:cb:c7:
+ c0:ff:12:8b:b6:3b:59:12:b9:f1:20:87:75:f0:71:6e:bc:94:
+ 47:72:62:ae:93:90:05:e2:ff:63:31:5a:d2:80:a5:4a:7f:57:
+ e9:f7:4e:3e:be:bd:4c:9e:74:07:19:b0:4d:88:97:af:23:a7:
+ 5a:23:af:d1:a9:98:9b:55:7e:fa:6b:18:77:03:c4:aa:49:bc:
+ b6:3d:66:3e:8d:0a:80:5f:ac:b9:58:fb:11:ef:60:db:ad:a8:
+ 79:41:83:1a:6a:61:87:99:64:2d:e4:6a:bb:c0:30:00:dd:69:
+ e5:92
+-----BEGIN CERTIFICATE-----
+MIICvjCCAiegAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAxMB4XDTA5
+MTExODE1MjMyM1oXDTM0MTExMjE1MjMyM1owbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgMTCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyEFmhMfVxXKPppgbWeIzyg3SJLPBR9sR
+4r8j2jJoQcz/KP6aOUnnCPAidRVhmZ6Z5RRlcWAAD1hCcHhaHtj6l5KCDuMMrCDc
+uONeh4uJ46HDh0kdkqX9fHd5zh/6nFoX2REM8n8a+tgyQfhpgK6KZr02wiFlVwi+
+z/DsgxWYbWUCAwEAAaNwMG4wLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJh
+dGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBT/u7B/4w7jjM/siEmpDmK102ASRjAf
+BgNVHSMEGDAWgBQ3cXSBRN0esWCWQbdLOMS3eRvPijANBgkqhkiG9w0BAQUFAAOB
+gQAz3ehXPmkboEyDUZndc7AMy8fA/xKLtjtZErnxIId18HFuvJRHcmKuk5AF4v9j
+MVrSgKVKf1fp904+vr1MnnQHGbBNiJevI6daI6/RqZibVX76axh3A8SqSby2PWY+
+jQqAX6y5WPsR72Dbrah5QYMaamGHmWQt5Gq7wDAA3Wnlkg==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/private/cakey.pem
new file mode 100644
index 000000000..602026a47
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,4E900CB191575111
+
+vHLTGKUgxa3C35alVr0gWT30x8WW5Pmz4oFv23fMMWIXjrp/QLlRRmd2AO9H8rLb
+3MWnA7cby5UTcrcsqwBA30TqhduNDi4iQFcOM60/S7yUFKjF5nj9bGi8XuUzMgTx
+OrJuxMGkayLiELskZxEpi6SJvTEsSdreT6OvyhzXQfAFDodoJSW65oF08cuYxXzi
+FFYFqvyWXa29WUyinBav5k3Mjax3Av3dYfMf/1u2n4vjGyjkfMg7mHrno19daWqa
+FJsxHHFezq//G5+JvePWFQUo1b0fVh13fx9x1dCbCRGQ9duSXaI7BNfl2Jd2rlVk
+xUMqnvd8VBNkW1AHxZL4csurQyO8ZQzg46w/kWaIMroeXbUnZYNJV7/TCs6nLGJF
+iNwtsFAjunWgWttFbMx3X7L7T6f6cWXocOOTNeIDpH+W6Pw9vltrjzNPAyBBok17
+sboWXDtlihMrSq5lWzUSPE8gOueh7Bcf7fSnLTeXuOXgKooJVXelookSQzsilWmS
+Fo5PTM+jOOaXVlbf8zfKFreLawohNkzagIxrCEP+HU+tF52ybJDP4mwPi1sQNcA0
+0luHyCL5EmaH5hVIqYeGUQoNPois5TqgYH1SEujyIuoNdEBi5r5qIRR/zz+BEpKU
+Z1B+HmmSWb0hjfenFSSaSSmGyS6VW1wZsU2B+wcPr7r0uFqoWllkxYNmSdky6qmw
+4Or0D6ayFUaJOQG6aTEfEVS31B4TUfFGfOLbeuUdwNa4/pNwMeFFSx+Xj7J3oYrn
+udjIL0Hz8hhjLVXaPVcu/qkZ7pXhOVlRQJ7byx730G3+elUFalJ/eQ==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/serial
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/serial
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/openssl.cfg
new file mode 100644
index 000000000..0dd15bd9e
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/DO_NOT_INSTALL_THIS_CERTIFICATE b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/DO_NOT_INSTALL_THIS_CERTIFICATE
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/DO_NOT_INSTALL_THIS_CERTIFICATE
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/README.txt
new file mode 100644
index 000000000..a18ed9ce0
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/README.txt
@@ -0,0 +1,19 @@
+Do NOT install !!!
+
+
+
+To provide the CRL via HTTP run
+
+
+
+java -jar ../../tools/httpserv/dist/httpserv.jar -a 8902
+
+
+To provide the intermediate certificate run
+
+java -jar ../../tools/httpserv/dist/httpserv.jar -a 8910
+
+
+
+
+
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/DO_NOT_INSTALL_THIS_CERTIFICATE b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/DO_NOT_INSTALL_THIS_CERTIFICATE
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/DO_NOT_INSTALL_THIS_CERTIFICATE
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/Sub_CA_1_Root_10.crt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/Sub_CA_1_Root_10.crt
new file mode 100644
index 000000000..2bb9a4289
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/Sub_CA_1_Root_10.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/cacert.pem
new file mode 100644
index 000000000..1f27b97b3
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/cacert.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 10
+ Validity
+ Not Before: Nov 23 15:14:48 2009 GMT
+ Not After : Nov 17 15:14:48 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 10
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:e4:d5:66:14:88:9f:79:41:50:b0:d1:a0:1b:98:
+ bf:b0:21:34:30:36:70:58:6f:8b:58:f1:b9:58:3a:
+ ce:29:6b:65:b6:11:f7:0d:c8:a6:c3:be:db:0f:2a:
+ 4e:c7:42:df:c9:0e:13:c0:00:0f:af:b5:71:c4:bc:
+ dd:82:fc:4a:27:c0:ee:af:ba:e1:7b:67:de:6b:bb:
+ ac:4c:fe:88:01:1a:73:4e:f5:32:15:3a:d0:cb:6b:
+ 97:84:1b:6c:d0:d6:91:a8:a4:5a:87:2a:69:61:36:
+ 1d:42:cc:16:d0:03:9c:c6:90:5c:61:20:8b:b1:be:
+ b6:54:24:5b:6f:1f:a9:5a:6f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 11:63:A1:BE:8B:E3:56:07:E6:A3:9F:23:39:72:7D:E3:22:B6:53:39
+ X509v3 Authority Key Identifier:
+ keyid:C8:A7:A3:80:20:74:6C:6F:EC:11:7A:F6:BE:26:10:37:31:87:B0:7A
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 10
+ serial:BF:C8:0F:BB:D9:A0:3A:6B
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 6b:0f:75:6d:56:b0:4e:45:19:65:ad:50:ef:4e:87:6c:95:5d:
+ 05:39:5a:43:5c:b4:51:25:9a:ec:f4:93:d1:f0:f6:91:dd:a3:
+ 77:95:0c:74:3c:a9:7c:c2:f6:62:ce:bf:58:5f:66:1f:d0:55:
+ ca:d8:2d:c4:1e:29:3a:ad:55:2c:9d:2c:8f:8e:9e:ce:ac:17:
+ 7e:1b:d1:16:d9:12:76:5c:2d:3f:9d:70:66:aa:39:34:f0:ec:
+ 31:4b:4b:5a:14:0c:c5:5b:3c:c8:47:02:90:cb:77:d7:4f:88:
+ 10:a7:80:3d:ca:19:5c:b5:04:c9:f0:e1:1b:5a:5f:fb:61:b2:
+ 14:b5
+-----BEGIN CERTIFICATE-----
+MIIDCTCCAnKgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMDAeFw0wOTExMjMxNTE0
+NDhaFw0zNDExMTcxNTE0NDhaMGkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxGTAXBgNVBAMTEFN1YiBDQSAxIFJvb3QgMTAwgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBAOTVZhSIn3lBULDRoBuYv7AhNDA2cFhvi1jxuVg6zilrZbYR9w3I
+psO+2w8qTsdC38kOE8AAD6+1ccS83YL8SifA7q+64Xtn3mu7rEz+iAEac071MhU6
+0Mtrl4QbbNDWkaikWocqaWE2HULMFtADnMaQXGEgi7G+tlQkW28fqVpvAgMBAAGj
+gcgwgcUwHQYDVR0OBBYEFBFjob6L41YH5qOfIzlyfeMitlM5MIGSBgNVHSMEgYow
+gYeAFMino4AgdGxv7BF69r4mEDcxh7B6oWSkYjBgMQswCQYDVQQGEwJERTEQMA4G
+A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT
+C0RldmVsb3BtZW50MRAwDgYDVQQDEwdSb290IDEwggkAv8gPu9mgOmswDwYDVR0T
+AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBrD3VtVrBORRllrVDvTodslV0F
+OVpDXLRRJZrs9JPR8PaR3aN3lQx0PKl8wvZizr9YX2Yf0FXK2C3EHik6rVUsnSyP
+jp7OrBd+G9EW2RJ2XC0/nXBmqjk08OwxS0taFAzFWzzIRwKQy3fXT4gQp4A9yhlc
+tQTJ8OEbWl/7YbIUtQ==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/Sub_CA_1_Root_10.crl b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/Sub_CA_1_Root_10.crl
new file mode 100644
index 000000000..67ed32da5
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/Sub_CA_1_Root_10.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crlnumber
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crlnumber
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt
new file mode 100644
index 000000000..810ec7ef2
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt
@@ -0,0 +1 @@
+V 341117153149Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 10
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..7449048bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/newcerts/1000.pem
@@ -0,0 +1,67 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 10
+ Validity
+ Not Before: Nov 23 15:31:49 2009 GMT
+ Not After : Nov 17 15:31:49 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 10
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:ce:41:53:5f:ba:d9:26:e4:45:14:74:a9:f2:9e:
+ fa:91:50:ea:fe:e7:76:76:6e:62:26:4c:a2:bd:c9:
+ 98:ce:1d:b3:74:ea:95:04:ec:d8:24:ac:29:de:2d:
+ 7f:2f:7f:10:94:24:d2:0c:0b:ff:d0:38:f1:a9:8f:
+ ee:25:97:bf:bd:b0:1f:24:d7:9d:7a:20:79:c0:73:
+ 97:12:cb:5a:cf:6d:4f:df:4a:a8:9c:1b:be:49:63:
+ 1f:b1:03:6d:c6:5f:69:5c:0d:7e:81:23:48:2a:76:
+ 80:53:53:d2:03:f6:56:6d:dc:e3:cc:be:cb:0f:c3:
+ 1b:b7:6e:79:33:e0:da:f6:5d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ Authority Information Access:
+ CA Issuers - URI:http://localhost:8910/demoCA/Sub_CA_1_Root_10.crt
+
+ X509v3 CRL Distribution Points:
+ URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_10.crl
+
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 90:DC:ED:B0:CB:62:A1:BE:8F:23:65:01:79:14:85:22:48:70:7B:A1
+ X509v3 Authority Key Identifier:
+ keyid:11:63:A1:BE:8B:E3:56:07:E6:A3:9F:23:39:72:7D:E3:22:B6:53:39
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 54:e3:d2:eb:dc:aa:db:8b:88:34:c6:b9:5b:f6:d8:ca:81:24:
+ d0:ba:4c:c2:a7:8e:82:22:d3:68:64:c9:61:9b:0a:00:3e:d1:
+ 4e:cb:83:1d:b9:c7:07:6a:5e:7b:b4:ca:92:0c:93:d7:9e:99:
+ e1:58:47:17:b0:a7:6d:68:5f:e5:59:f9:2a:d1:96:df:b6:9f:
+ bc:47:40:f2:71:ed:71:2b:8a:6e:6f:aa:29:9f:4d:98:ee:f1:
+ aa:63:b4:44:39:58:8a:f8:c2:af:8d:c1:49:92:b4:99:02:2f:
+ 27:c7:5b:f5:30:7c:ed:67:ff:cd:12:dc:a7:c4:8e:98:4f:2c:
+ e0:05
+-----BEGIN CERTIFICATE-----
+MIIDODCCAqGgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaTELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEZMBcGA1UEAxMQU3ViIENBIDEgUm9vdCAxMDAeFw0w
+OTExMjMxNTMxNDlaFw0zNDExMTcxNTMxNDlaMHAxCzAJBgNVBAYTAkRFMRAwDgYD
+VQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxML
+RGV2ZWxvcG1lbnQxIDAeBgNVBAMTF1VzZXIgMSBTdWIgQ0EgMSBSb290IDEwMIGf
+MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOQVNfutkm5EUUdKnynvqRUOr+53Z2
+bmImTKK9yZjOHbN06pUE7NgkrCneLX8vfxCUJNIMC//QOPGpj+4ll7+9sB8k1516
+IHnAc5cSy1rPbU/fSqicG75JYx+xA23GX2lcDX6BI0gqdoBTU9ID9lZt3OPMvssP
+wxu3bnkz4Nr2XQIDAQABo4HnMIHkME0GCCsGAQUFBwEBBEEwPzA9BggrBgEFBQcw
+AoYxaHR0cDovL2xvY2FsaG9zdDo4OTEwL2RlbW9DQS9TdWJfQ0FfMV9Sb290XzEw
+LmNydDBGBgNVHR8EPzA9MDugOaA3hjVodHRwOi8vbG9jYWxob3N0Ojg5MDIvZGVt
+b0NBL2NybC9TdWJfQ0FfMV9Sb290XzEwLmNybDALBgNVHQ8EBAMCBeAwHQYDVR0O
+BBYEFJDc7bDLYqG+jyNlAXkUhSJIcHuhMB8GA1UdIwQYMBaAFBFjob6L41YH5qOf
+IzlyfeMitlM5MA0GCSqGSIb3DQEBBQUAA4GBAFTj0uvcqtuLiDTGuVv22MqBJNC6
+TMKnjoIi02hkyWGbCgA+0U7Lgx25xwdqXnu0ypIMk9eemeFYRxewp21oX+VZ+SrR
+lt+2n7xHQPJx7XErim5vqimfTZju8apjtEQ5WIr4wq+NwUmStJkCLyfHW/UwfO1n
+/80S3KfEjphPLOAF
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/private/cakey.pem
new file mode 100644
index 000000000..260e3aa94
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,170F9697C268C4B5
+
+eIaE0ShuxMcOUBJBlI7PXIuKg69hDunjUz55iy0I+4sGc9tFK+vtjvDZWxx+dpZI
+WKGto0fDeobBf3f2xgKQFcwAtUPtiTMXk8C0BYfAbXsTYBgOgvKwJGOIo5FsjukZ
+VJCNlUM1mwX5P3OrLdyT0j8OoL6lINztYDhSC8XL12YJk1j05yN4Gl8N108JQMLA
+sywA2Q6WIhPloZQXtHkiN2mlQ7WWwbSBbaUbdXNQKk6sXelFLPMOk+JOTCLp9kHU
+svTBAg7RyWKBuUmtEmkipNLtYhdkRVJ/dgL3/TAsZET6cjDd/eZg+1Kl0pn93KGv
+avSQKppkKNjUcWkZiuM1imS8+0qeMiw56JQGzMdEeSjadcTdsyYb0lssXmndK/z0
+90bA6GegvCnsq6Wj0Nz97GbK+ZMzA76e+HPQLli0j3poAlVwdzBCFRyLO4ET5Qzl
+OhTewxKZxe2yx75chECWJS+CLOajHkVyUe3x6QzyVuU+YZqjXWkJP7rTcQJZFcml
++3PHYWy5RnZ2sKOegksr3+QtL+UmDVa1xEeIhk3m0IMiYZ9HNWlrg1gedY02y9yY
+MGsCOkCF10KnCNIp4j5s1kGMicdMquDt0jTXwu+8jt6Skh8FWcr9aLf0bNc63oHg
+NaI7Y3+Ssl3GLUGFOGwC0lpooZ10SoJJDK9xxEjt48vUfX+Npn3bRv+UlwfLBYLo
+GENyNV3OVAsKYQ8fGIh/gTeIqwMUdo7Efcs6bdeqiOrYQhBl04Gty0I4cO6/lFGd
+by/4SesYDXoVtaKto1B5VOQn+QxovF7eY1pK6wDBU8+EaJbGSNK9Rw==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/serial
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/serial
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/openssl.cfg
new file mode 100644
index 000000000..431650974
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/openssl.cfg
@@ -0,0 +1,293 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8889
+authorityInfoAccess = caIssuers;URI:http://localhost:8910/demoCA/Sub_CA_1_Root_10.crt
+crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_10.crl
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+#nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/cacert.pem
new file mode 100644
index 000000000..36a8eb3c0
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/cacert.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 2
+ Validity
+ Not Before: Nov 18 15:55:38 2009 GMT
+ Not After : Nov 12 15:55:38 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:f0:7a:16:4c:ab:06:b2:af:27:9c:7d:3f:86:da:
+ de:7a:c3:01:67:77:56:49:09:ed:ed:31:72:83:e8:
+ 75:9c:4c:ce:f9:97:b6:63:3c:e2:ca:83:80:92:03:
+ 9c:96:e2:de:72:79:c1:cf:3e:3f:b9:0d:b4:87:c7:
+ 75:e6:56:8d:aa:f8:77:47:11:4e:fe:07:b0:1d:64:
+ 06:73:4b:6f:d4:ac:da:0f:05:87:b1:f1:98:a9:f5:
+ 8a:a1:a8:ed:17:9c:26:b8:da:92:63:d2:53:87:e6:
+ fc:ed:44:de:94:56:90:3e:a2:a1:67:08:cb:38:d4:
+ cf:17:3b:7e:ff:7a:97:c0:7b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 8C:F3:2C:30:A2:E8:62:50:70:BC:FC:71:A0:41:FA:E0:58:B4:4D:B8
+ X509v3 Authority Key Identifier:
+ keyid:5F:BC:4C:DA:EB:0A:0C:B5:23:43:5E:24:32:27:79:41:F5:82:A3:02
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 2
+ serial:A2:AF:15:89:EC:73:54:86
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 52:83:16:ab:0e:43:2d:b3:e4:0f:6c:c1:63:d4:86:ac:e7:1e:
+ ee:7b:ee:9b:0c:ff:4f:e0:59:d5:e4:27:af:68:bf:a7:f5:2a:
+ a3:c9:e3:2b:8d:b7:31:26:f6:04:80:4e:f2:a5:bf:da:63:5e:
+ 8c:d6:c6:b2:46:a0:46:10:2f:84:9f:02:76:f3:c8:33:05:62:
+ 0c:5f:2d:cc:06:23:53:9f:d9:f8:46:e4:2e:5c:da:05:fc:bf:
+ db:45:b4:ac:8d:8b:b5:4b:60:7b:7b:26:34:7f:b1:4b:41:96:
+ 41:26:70:7a:9d:78:a2:9b:e0:de:62:a2:04:86:9f:ed:7c:a6:
+ 20:eb
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAyMB4XDTA5MTExODE1NTUz
+OFoXDTM0MTExMjE1NTUzOFowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAyMIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDwehZMqwayryecfT+G2t56wwFnd1ZJCe3tMXKD6HWcTM75l7ZjPOLK
+g4CSA5yW4t5yecHPPj+5DbSHx3XmVo2q+HdHEU7+B7AdZAZzS2/UrNoPBYex8Zip
+9YqhqO0XnCa42pJj0lOH5vztRN6UVpA+oqFnCMs41M8XO37/epfAewIDAQABo4HH
+MIHEMB0GA1UdDgQWBBSM8ywwouhiUHC8/HGgQfrgWLRNuDCBkQYDVR0jBIGJMIGG
+gBRfvEza6woMtSNDXiQyJ3lB9YKjAqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAyggkAoq8ViexzVIYwDwYDVR0TAQH/
+BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBSgxarDkMts+QPbMFj1Ias5x7ue+6b
+DP9P4FnV5CevaL+n9SqjyeMrjbcxJvYEgE7ypb/aY16M1sayRqBGEC+EnwJ288gz
+BWIMXy3MBiNTn9n4RuQuXNoF/L/bRbSsjYu1S2B7eyY0f7FLQZZBJnB6nXiim+De
+YqIEhp/tfKYg6w==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/crlnumber
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/crlnumber
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt
new file mode 100644
index 000000000..ae1f2d1e4
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt
@@ -0,0 +1 @@
+V 341112160955Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 2
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..a8c0b74ca
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/newcerts/1000.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 2
+ Validity
+ Not Before: Nov 18 16:09:55 2009 GMT
+ Not After : Nov 12 16:09:55 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:c7:00:aa:e0:5a:42:af:9c:b5:43:8c:f4:7d:7a:
+ 0f:ee:a9:19:22:d8:47:14:af:b4:e4:dd:5d:41:92:
+ a1:2b:32:39:5c:71:88:10:e3:77:87:b6:d5:38:85:
+ de:4b:91:c6:17:97:8e:3d:96:b3:af:8c:9d:74:8c:
+ 88:7f:2a:72:9a:ca:1a:1b:56:6c:63:2e:a4:a0:fc:
+ 3a:7b:0d:c2:16:15:d0:80:15:29:de:cd:0b:74:bc:
+ 5e:31:84:71:a4:fd:be:9b:06:6a:0c:47:1d:f9:e4:
+ c1:98:ae:46:e6:e2:51:55:d5:bb:ab:05:28:69:b5:
+ f8:35:32:d6:f0:64:d8:44:81
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 71:60:2B:22:B5:DF:FC:38:7E:79:F3:EF:7C:96:5F:C1:D2:42:9C:61
+ X509v3 Authority Key Identifier:
+ keyid:8C:F3:2C:30:A2:E8:62:50:70:BC:FC:71:A0:41:FA:E0:58:B4:4D:B8
+
+ Signature Algorithm: sha1WithRSAEncryption
+ e5:b8:1a:43:82:75:20:48:e0:52:d0:46:25:6f:f7:5b:a9:3f:
+ 9e:cd:db:45:da:15:53:95:e7:c8:74:7b:e0:e4:2c:8c:f6:4d:
+ 1c:73:6e:2c:11:eb:c1:dc:4c:1d:50:e3:e8:10:2f:03:20:06:
+ ff:d7:4f:c9:a2:2e:ef:85:27:92:31:47:64:c8:75:f2:fc:a4:
+ 9d:c9:53:55:c5:da:69:b0:96:99:fd:ac:c4:16:40:ea:0c:1b:
+ 32:c3:fd:65:1d:03:ad:be:60:88:7c:70:53:35:91:ce:13:e2:
+ 3d:23:6b:e8:23:c0:3c:9a:57:5f:ad:4b:03:94:92:16:62:f9:
+ d4:01
+-----BEGIN CERTIFICATE-----
+MIICyzCCAjSgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAyMB4XDTA5
+MTExODE2MDk1NVoXDTM0MTExMjE2MDk1NVowbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgMjCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxwCq4FpCr5y1Q4z0fXoP7qkZIthHFK+0
+5N1dQZKhKzI5XHGIEON3h7bVOIXeS5HGF5eOPZazr4yddIyIfypymsoaG1ZsYy6k
+oPw6ew3CFhXQgBUp3s0LdLxeMYRxpP2+mwZqDEcd+eTBmK5G5uJRVdW7qwUoabX4
+NTLW8GTYRIECAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P
+cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUcWArIrXf/Dh+
+efPvfJZfwdJCnGEwHwYDVR0jBBgwFoAUjPMsMKLoYlBwvPxxoEH64Fi0TbgwDQYJ
+KoZIhvcNAQEFBQADgYEA5bgaQ4J1IEjgUtBGJW/3W6k/ns3bRdoVU5XnyHR74OQs
+jPZNHHNuLBHrwdxMHVDj6BAvAyAG/9dPyaIu74UnkjFHZMh18vyknclTVcXaabCW
+mf2sxBZA6gwbMsP9ZR0Drb5giHxwUzWRzhPiPSNr6CPAPJpXX61LA5SSFmL51AE=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/private/cakey.pem
new file mode 100644
index 000000000..ba6119464
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,A5EF3D451C410026
+
+RByk5Bn7uG1eixW1qTghnNri2bQHvnrNUYcpSL/mJIx6NjuYEY6vE/vQ9A9qcjuZ
+8NInLR1w+EmSlDS499za8dfllaJ4/djswWN+4gtkoP/kKF390AcNgIpf/gIiJX6d
+tkrw3Esst2gUwdtdhWItQNh0qZoeWpY9KlraDdEYVZt46JmsgwEIufzHyHTHf53C
+E9ZP7/vYBQeHPOvMGsvhwZWAZZOO5GnD4fktbVAnybQdnlPgJDrRTGabbTdawQNc
+8GJoG6hgJPcwlYm7NbRrtB18L3bG4bxx95fjqeOtvGDSUxSY+FNV7B2xQpivnBu6
+ppLdwTRYHQGOCJSCZoCtW+GYM7wXR2L4kGXMPwB4hHUAQXt+Tva9TP0t96313lMW
+bFTRgTcT71eBidEkUIn1OrOL/Al2lXvSaDhm0P2F0yElzj3JN/gqrIUChaXWcLrS
+CZuOGA2zGpoBASQ5jF+CyC+5mEkmDgvbmAXiJNjNmK/ColklpTNRSGk65Vr8AufA
+d/yoSQCGprhMgqhviue40MGSsOD58TLwR4Tsm5ptze0QYRNC2SkKCrgtS0IEXh/Z
+/9cMAgwOypW1T7LMOV+rG9DOyKx9Ye+oxPLCHdS7wN4h6blusiESbbUW0f5wqAzF
+FCe6VEd+AjahnQLjw7O8vP4zl8q99cjOYD5SB+wqYrr0beEely7xdpKrDMgXqiBe
+tOE9XvgU9KR59GZd0l6FPRkpZCUA+3Wuu4Zvrbam5kEbxVy+VTamWd5cRrxbJBM4
+Ipn414lfeq/5Foz13roErJE6gbWxXeCFDzg0z5fjWc2T41PX58x4Tw==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/req.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/req.pem
new file mode 100644
index 000000000..cc93d02e5
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/req.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBqDCCARECAQAwaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxFzAV
+BgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEYMBYG
+A1UEAxMPU3ViIENBIDEgUm9vdCAyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
+gQDwehZMqwayryecfT+G2t56wwFnd1ZJCe3tMXKD6HWcTM75l7ZjPOLKg4CSA5yW
+4t5yecHPPj+5DbSHx3XmVo2q+HdHEU7+B7AdZAZzS2/UrNoPBYex8Zip9YqhqO0X
+nCa42pJj0lOH5vztRN6UVpA+oqFnCMs41M8XO37/epfAewIDAQABoAAwDQYJKoZI
+hvcNAQEFBQADgYEADbuni6Yq0l5FJGFDUaabv4T75XxyMWy+k6wSojSt1thtwcJI
+Bx5x1ngG5VyxeNmqyjLvd2KeYsVaV8M9J9ty40QGL8F83OArJPGADtBSM+gwmjdu
+C+ksYL+5Yl8vSY3M7tKqJB2AFk2QlfP5okMQWRJ5QFTTwA8EFpHFsy4gsks=
+-----END CERTIFICATE REQUEST-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/serial
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/serial
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/openssl.cfg
new file mode 100644
index 000000000..51e520525
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/cacert.pem
new file mode 100644
index 000000000..c14880b58
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/cacert.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 3
+ Validity
+ Not Before: Nov 20 07:40:39 2009 GMT
+ Not After : Nov 14 07:40:39 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 3
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:9e:87:1f:af:f0:a0:1c:f4:9e:f8:c3:e7:ee:d3:
+ cb:a8:e2:54:98:ba:dd:7e:dc:6e:14:e1:7e:7f:5b:
+ 1e:ef:53:3d:89:76:ea:e2:b3:6c:08:0d:e8:c8:4d:
+ 24:40:ff:92:f3:5b:51:f7:90:ac:69:37:29:90:f5:
+ e8:95:6f:67:d1:10:cd:7b:dd:65:38:d6:25:ec:63:
+ 39:ba:2e:ea:13:58:8e:7a:82:8e:10:d1:7b:77:7a:
+ 08:d5:82:66:62:a4:83:39:ad:f5:83:d5:2f:5c:bc:
+ 23:6e:c8:78:8b:38:9f:eb:a3:67:ba:43:fa:e4:07:
+ 3f:90:72:db:0c:f9:49:0e:0d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 1B:2D:E0:A2:26:7F:0D:BA:38:7E:EC:06:81:81:0F:12:74:4C:5A:4D
+ X509v3 Authority Key Identifier:
+ keyid:69:FF:30:EC:1F:34:9A:67:3A:6B:20:D2:DF:7F:F5:05:04:ED:F9:1C
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 3
+ serial:95:6F:F0:E3:2B:BE:76:F9
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 6f:ac:53:9d:16:6e:95:ed:97:60:ed:c8:a8:96:ab:24:c5:1e:
+ d5:d7:26:98:fb:b5:aa:ef:da:a4:91:6a:82:55:ec:21:a2:08:
+ 24:c7:0c:a7:58:0c:06:69:3d:04:7d:08:f1:0b:77:41:ad:1c:
+ 13:c2:bd:17:c9:9e:ff:df:64:69:8b:58:f1:bc:40:bd:cf:e4:
+ 57:29:bc:5e:93:84:61:56:4c:e6:c1:3a:2c:6e:71:ea:5d:67:
+ c0:54:be:4f:2f:27:a8:59:8d:29:94:ba:c6:6c:ff:ed:25:3d:
+ 0b:fa:93:c9:45:f4:d5:a3:3d:be:8a:f1:9d:c4:92:d5:5c:d2:
+ 77:7c
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAzMB4XDTA5MTEyMDA3NDAz
+OVoXDTM0MTExNDA3NDAzOVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAzMIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQCehx+v8KAc9J74w+fu08uo4lSYut1+3G4U4X5/Wx7vUz2Jduris2wI
+DejITSRA/5LzW1H3kKxpNymQ9eiVb2fREM173WU41iXsYzm6LuoTWI56go4Q0Xt3
+egjVgmZipIM5rfWD1S9cvCNuyHiLOJ/ro2e6Q/rkBz+QctsM+UkODQIDAQABo4HH
+MIHEMB0GA1UdDgQWBBQbLeCiJn8Nujh+7AaBgQ8SdExaTTCBkQYDVR0jBIGJMIGG
+gBRp/zDsHzSaZzprINLff/UFBO35HKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAzggkAlW/w4yu+dvkwDwYDVR0TAQH/
+BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBvrFOdFm6V7Zdg7ciolqskxR7V1yaY
++7Wq79qkkWqCVewhoggkxwynWAwGaT0EfQjxC3dBrRwTwr0XyZ7/32Rpi1jxvEC9
+z+RXKbxek4RhVkzmwTosbnHqXWfAVL5PLyeoWY0plLrGbP/tJT0L+pPJRfTVoz2+
+ivGdxJLVXNJ3fA==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crl/DO_NOT_CREATE_A_CRL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crl/DO_NOT_CREATE_A_CRL
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crlnumber
new file mode 100644
index 000000000..83b33d238
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crlnumber
@@ -0,0 +1 @@
+1000
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt
new file mode 100644
index 000000000..bd3b5eaea
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt
@@ -0,0 +1 @@
+V 341114075225Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 3
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..46d60bda0
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/newcerts/1000.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 3
+ Validity
+ Not Before: Nov 20 07:52:25 2009 GMT
+ Not After : Nov 14 07:52:25 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 3
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:bc:82:f1:75:77:02:f8:fb:3a:c2:8d:3c:1b:cb:
+ b2:63:2e:89:07:92:6b:b4:e1:ab:ce:30:a1:a4:82:
+ 38:30:64:2a:ba:01:c6:ac:ee:03:cc:65:bf:83:3e:
+ 39:b8:ce:ac:45:99:97:f9:94:e2:7d:5d:f3:c5:f7:
+ d4:a5:d6:57:cf:24:c1:d7:56:eb:00:9c:5d:80:bc:
+ 23:0c:91:d6:8e:2a:62:f6:af:4d:c9:19:5b:dd:16:
+ be:21:54:51:71:be:f2:c6:64:c5:bb:8e:37:49:c9:
+ 4d:68:82:3a:42:8a:e3:de:ab:fa:c7:ff:a5:b4:c7:
+ 53:8f:17:a4:66:9d:c3:8e:b1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 0B:DD:2E:E9:5C:8A:5F:67:C9:75:4C:B3:04:DB:95:2F:D8:74:76:EF
+ X509v3 Authority Key Identifier:
+ keyid:1B:2D:E0:A2:26:7F:0D:BA:38:7E:EC:06:81:81:0F:12:74:4C:5A:4D
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 18:2f:af:1a:27:c7:f8:81:cd:d5:31:a0:f2:06:05:94:d6:12:
+ 11:88:24:ae:4f:f6:86:18:bf:d0:1b:c9:19:7a:47:30:0e:fb:
+ 30:b2:50:31:8d:30:6b:8b:54:17:67:bc:b8:c1:d5:1c:6c:95:
+ c5:e4:c4:ad:12:39:2f:38:ee:53:6a:cf:be:1c:4f:ac:98:0c:
+ ea:eb:0b:48:3d:5e:7a:2b:ed:02:8b:34:89:0a:d8:32:b4:6f:
+ f4:b2:06:96:aa:6b:ae:19:38:ec:9f:47:43:3b:7b:bd:71:38:
+ 99:4f:b4:1e:87:95:73:63:76:d4:ff:21:57:2c:c3:f4:3c:fd:
+ cb:c3
+-----BEGIN CERTIFICATE-----
+MIICyzCCAjSgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAzMB4XDTA5
+MTEyMDA3NTIyNVoXDTM0MTExNDA3NTIyNVowbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgMzCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvILxdXcC+Ps6wo08G8uyYy6JB5JrtOGr
+zjChpII4MGQqugHGrO4DzGW/gz45uM6sRZmX+ZTifV3zxffUpdZXzyTB11brAJxd
+gLwjDJHWjipi9q9NyRlb3Ra+IVRRcb7yxmTFu443SclNaII6Qorj3qv6x/+ltMdT
+jxekZp3DjrECAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P
+cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUC90u6VyKX2fJ
+dUyzBNuVL9h0du8wHwYDVR0jBBgwFoAUGy3goiZ/Dbo4fuwGgYEPEnRMWk0wDQYJ
+KoZIhvcNAQEFBQADgYEAGC+vGifH+IHN1TGg8gYFlNYSEYgkrk/2hhi/0BvJGXpH
+MA77MLJQMY0wa4tUF2e8uMHVHGyVxeTErRI5LzjuU2rPvhxPrJgM6usLSD1eeivt
+Aos0iQrYMrRv9LIGlqprrhk47J9HQzt7vXE4mU+0HoeVc2N21P8hVyzD9Dz9y8M=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/private/cakey.pem
new file mode 100644
index 000000000..8d893cdf9
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,EF032FCF0827A7AA
+
+vTlvOy1d4MK41zEZfeUWDO7kjLqZ53jK6JdXhKT2P9MnstGf1S0QxwbEKP+KWj+4
+lwS7fSXs6/s2Q5OrG9QSV4bm5Sob0OpDfoc1GS24uSGvYXzhuyM9sjiITXvyGKCH
++0VQPV/GSXWShsk5CCzUXIBSBHDVxlEzmBvzWiHfcLEAwF1JJlh6ex9Xju9JL9sN
+Gp4VMw9PML11V4iqNXKeyBZ87Bv/yew+bDACLCe7e1liBxdOj2ntc7mtpCrkf/pn
+hLnJ1qKodcwgmmMLufa7//E1RCBMn1gml0YXMe+Grrn7tFdVWT/puKiSrKGgIbbB
+RNf7JnG5E8Oy2V8NRk4SV5Au784fw5NMykQDCMJFp9aldwP7LlIUBPtPm/jpaY0V
+e6tKT20e4Ru2mDzyfef8nhFRogMxvPrxVSxN8aI1u/soPMp55ypWrqg99QlsiZgG
+MhpHaFODSWvHaFcwFY+gEDUmEH76S3wuOSgeFolvIPEETjw6Vc46Zi32N1ycQ1wz
+NCbIGy2ftEzKIEOeXHAsuQiP+Cic1QYJEOxhvOq9VteYfilT7D9FQ2+QOqrl4+2X
+hj2RaTJawpSFoWfEh7QM1ir0TPj3wRSTg6g3e0f+vAvI9AfVEP3ctPm6tpXirUgh
+QOA1LZKZzHUYqr0q2TBvItyGsg3w7dxyeB6brCtzOzg+GpvNhaRZ1/+SVPxzYVgf
+buLQIfvvLE6TmABxOloop1m61u6c6+Bg5kKHXSnUKehGv+iIxVLZgxrNkCFyyzX0
+Dpu9hkGYzVzE8QCujC09MZCKH/85iYGuEZtP81Mjyjs=
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/req.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/req.pem
new file mode 100644
index 000000000..dd08bf671
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/req.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBqDCCARECAQAwaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxFzAV
+BgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEYMBYG
+A1UEAxMPU3ViIENBIDEgUm9vdCAzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
+gQCehx+v8KAc9J74w+fu08uo4lSYut1+3G4U4X5/Wx7vUz2Jduris2wIDejITSRA
+/5LzW1H3kKxpNymQ9eiVb2fREM173WU41iXsYzm6LuoTWI56go4Q0Xt3egjVgmZi
+pIM5rfWD1S9cvCNuyHiLOJ/ro2e6Q/rkBz+QctsM+UkODQIDAQABoAAwDQYJKoZI
+hvcNAQEFBQADgYEAiwW4WbC3V3wEBfPlIFiUagJHOettp5NyCzLULyQZE1FXs/zV
+RxIi3Oxdaj643QZ8h6upKf9F60T8+oG15RBdp1ZjmBXnv7ZRx33LynExbxX0XKjo
+Pg/8dGLFBomZqE8MpWbQtY5lRkQOkgt5XZLj5SMJQsgpVaAOPQcOg5Sqfag=
+-----END CERTIFICATE REQUEST-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/serial
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/serial
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/openssl.cfg
new file mode 100644
index 000000000..51e520525
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/README.txt
new file mode 100644
index 000000000..3ac354b8f
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/README.txt
@@ -0,0 +1,4 @@
+Revoked certificates:
+---------------------
+- User 2 Sub CA 1 Root 4
+
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/cacert.pem
new file mode 100644
index 000000000..391037118
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/cacert.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 4
+ Validity
+ Not Before: Nov 20 08:37:27 2009 GMT
+ Not After : Nov 14 08:37:27 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 4
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:da:b0:21:94:89:b0:00:89:cb:69:59:9b:0d:fe:
+ 1f:b9:a0:a8:44:92:55:5f:0b:d5:e5:08:63:bd:47:
+ 6b:11:4d:b1:a8:12:6f:c1:cf:cb:9e:ae:e2:c1:03:
+ 68:46:59:0b:96:7c:21:45:9b:14:81:d8:f1:83:70:
+ 6b:3d:b4:56:65:49:87:1d:ab:e2:08:6a:49:66:0e:
+ 59:b4:da:7a:3f:72:23:b8:1f:fb:78:f5:f0:2d:c4:
+ fe:d9:94:6e:2e:c3:6e:95:ba:38:60:d1:0b:fa:16:
+ c7:02:71:ef:3e:71:72:63:26:56:35:1e:8b:ec:47:
+ 87:25:6e:bc:90:d0:8b:37:2d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 96:9A:2D:06:F6:76:4F:83:68:7B:9C:69:C4:18:BB:4A:EB:46:38:E4
+ X509v3 Authority Key Identifier:
+ keyid:BA:8D:A1:97:DC:C4:39:1F:90:B5:51:6B:10:19:F2:46:0D:A9:65:8E
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 4
+ serial:A2:93:46:74:3B:A6:E3:AD
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 45:77:ba:6b:b6:a7:2a:0f:6b:38:90:9f:0a:18:11:c7:54:7b:
+ c9:3b:9a:93:90:96:f0:04:0a:56:87:30:e0:f5:d8:84:40:39:
+ 90:85:ca:e7:38:1b:d8:df:2f:bd:73:91:13:cb:a6:c9:b0:7a:
+ f7:59:77:6b:9a:d5:86:78:06:dc:40:14:ce:ea:43:a8:ae:ed:
+ a2:03:64:51:3a:47:7a:9f:df:2d:65:49:56:a5:39:cf:28:2a:
+ ac:ab:fd:e1:93:fd:3e:56:e8:eb:7a:11:a8:f7:f9:1a:a1:83:
+ 1f:92:f7:da:4e:c6:d9:67:dd:67:ff:be:6f:e5:24:e1:6e:cc:
+ 94:3c
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0MB4XDTA5MTEyMDA4Mzcy
+N1oXDTM0MTExNDA4MzcyN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA0MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDasCGUibAAictpWZsN/h+5oKhEklVfC9XlCGO9R2sRTbGoEm/Bz8ue
+ruLBA2hGWQuWfCFFmxSB2PGDcGs9tFZlSYcdq+IIaklmDlm02no/ciO4H/t49fAt
+xP7ZlG4uw26Vujhg0Qv6FscCce8+cXJjJlY1HovsR4clbryQ0Is3LQIDAQABo4HH
+MIHEMB0GA1UdDgQWBBSWmi0G9nZPg2h7nGnEGLtK60Y45DCBkQYDVR0jBIGJMIGG
+gBS6jaGX3MQ5H5C1UWsQGfJGDalljqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0ggkAopNGdDum460wDwYDVR0TAQH/
+BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBFd7prtqcqD2s4kJ8KGBHHVHvJO5qT
+kJbwBApWhzDg9diEQDmQhcrnOBvY3y+9c5ETy6bJsHr3WXdrmtWGeAbcQBTO6kOo
+ru2iA2RROkd6n98tZUlWpTnPKCqsq/3hk/0+VujrehGo9/kaoYMfkvfaTsbZZ91n
+/75v5SThbsyUPA==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/crlnumber
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/crlnumber
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt
new file mode 100644
index 000000000..88e41b76a
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt
@@ -0,0 +1,2 @@
+V 341114084401Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 4
+R 341114085720Z 091120085929Z,keyCompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 1 Root 4
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..73563ed96
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1000.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 4
+ Validity
+ Not Before: Nov 20 08:44:01 2009 GMT
+ Not After : Nov 14 08:44:01 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 4
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:c3:55:aa:1b:4f:f6:b4:78:be:ac:61:2a:92:94:
+ 73:1b:39:4c:0e:57:7e:da:78:03:7e:65:11:57:97:
+ e6:f4:0d:72:1f:f6:2b:a4:33:f9:5c:bd:2b:25:6c:
+ 58:29:73:b9:46:d5:db:e9:03:1d:a2:f8:8e:6e:c2:
+ b5:95:ec:ba:95:c3:ac:2e:c0:b6:40:ba:23:1d:74:
+ 75:91:cc:d6:3a:4c:15:4d:15:03:a4:e6:80:4a:93:
+ fe:6c:91:ab:77:60:3b:43:65:21:cd:04:3d:01:71:
+ 99:47:28:12:c8:9d:f9:d7:25:7a:30:82:76:c0:27:
+ 5e:c3:70:42:54:2a:0a:02:97
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ D5:2F:1A:60:8E:F9:2E:8F:51:EB:F7:AB:24:47:80:CE:B6:8D:F1:63
+ X509v3 Authority Key Identifier:
+ keyid:96:9A:2D:06:F6:76:4F:83:68:7B:9C:69:C4:18:BB:4A:EB:46:38:E4
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 7a:83:0c:a0:2d:14:52:97:a1:0e:dd:b3:2e:a1:1f:0d:51:e7:
+ 98:2e:89:9a:36:a3:1b:af:28:95:13:ab:3e:31:2e:f6:fa:5f:
+ f7:85:8c:01:7a:1b:25:63:7e:d6:f9:8e:ad:84:9e:42:3e:1d:
+ f4:ad:dc:b1:20:91:83:8b:48:ad:34:2a:b9:cc:ae:06:e6:bc:
+ e1:05:e6:35:71:ca:43:98:3a:e5:93:52:e1:3c:3a:1b:83:53:
+ d3:a6:ba:6a:43:38:00:92:ba:fb:8f:a8:17:46:f9:32:ac:42:
+ 47:87:7f:2e:ae:76:49:88:55:1e:65:70:6c:d6:35:ab:64:48:
+ a9:66
+-----BEGIN CERTIFICATE-----
+MIICyzCCAjSgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA0MB4XDTA5
+MTEyMDA4NDQwMVoXDTM0MTExNDA4NDQwMVowbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgNDCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAw1WqG0/2tHi+rGEqkpRzGzlMDld+2ngD
+fmURV5fm9A1yH/YrpDP5XL0rJWxYKXO5RtXb6QMdoviObsK1ley6lcOsLsC2QLoj
+HXR1kczWOkwVTRUDpOaASpP+bJGrd2A7Q2UhzQQ9AXGZRygSyJ351yV6MIJ2wCde
+w3BCVCoKApcCAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P
+cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU1S8aYI75Lo9R
+6/erJEeAzraN8WMwHwYDVR0jBBgwFoAUlpotBvZ2T4Noe5xpxBi7SutGOOQwDQYJ
+KoZIhvcNAQEFBQADgYEAeoMMoC0UUpehDt2zLqEfDVHnmC6JmjajG68olROrPjEu
+9vpf94WMAXobJWN+1vmOrYSeQj4d9K3csSCRg4tIrTQqucyuBua84QXmNXHKQ5g6
+5ZNS4Tw6G4NT06a6akM4AJK6+4+oF0b5MqxCR4d/Lq52SYhVHmVwbNY1q2RIqWY=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1001.pem
new file mode 100644
index 000000000..7068aa0af
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1001.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 4
+ Validity
+ Not Before: Nov 20 08:57:20 2009 GMT
+ Not After : Nov 14 08:57:20 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 1 Root 4
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:ab:2a:df:93:6c:f0:b1:34:54:15:5b:06:4e:15:
+ bb:94:53:89:96:96:47:db:43:49:e7:66:d5:6b:53:
+ eb:04:54:d0:96:48:08:8f:8e:cc:70:e1:62:88:6a:
+ f3:ff:bc:65:55:b9:55:a6:29:22:c1:f6:16:9a:01:
+ 25:86:a9:72:c8:7c:0f:29:87:b9:14:51:34:d2:fc:
+ 01:3e:20:46:dc:54:3f:f3:03:d8:07:e0:6b:0c:78:
+ 70:d0:d0:93:83:e2:cf:53:fc:3b:d5:b0:c9:7d:40:
+ 8b:ee:5d:d3:30:e9:24:01:1e:b0:ac:de:1a:18:97:
+ a1:0d:58:79:5e:67:cd:99:bf
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 47:DB:A7:93:38:C2:0F:34:7F:B7:DE:35:C9:23:75:CC:30:93:A4:42
+ X509v3 Authority Key Identifier:
+ keyid:96:9A:2D:06:F6:76:4F:83:68:7B:9C:69:C4:18:BB:4A:EB:46:38:E4
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 97:70:47:74:ce:e1:f6:51:bf:cc:cf:0f:cf:cc:23:75:df:4b:
+ 3d:36:f0:70:0f:47:5d:c7:96:ad:b0:78:95:89:3a:2a:7a:ba:
+ 79:45:fe:2f:37:4c:69:76:ab:0a:10:ea:0d:5e:fe:28:04:44:
+ 9c:f3:8d:43:f5:15:fa:79:be:d3:86:f3:c1:b5:8b:5a:74:a9:
+ c5:b7:fe:e8:63:6e:1f:13:3a:c9:49:3b:45:0c:a6:64:b9:07:
+ 9b:1a:30:09:1d:5e:f0:2b:a9:55:aa:41:fa:85:0d:ef:dd:c3:
+ f5:58:52:bf:7f:6d:f4:18:06:f4:5a:71:af:e4:57:b0:0a:6e:
+ f6:76
+-----BEGIN CERTIFICATE-----
+MIICyzCCAjSgAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA0MB4XDTA5
+MTEyMDA4NTcyMFoXDTM0MTExNDA4NTcyMFowbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAxIFJvb3QgNDCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqyrfk2zwsTRUFVsGThW7lFOJlpZH20NJ
+52bVa1PrBFTQlkgIj47McOFiiGrz/7xlVblVpikiwfYWmgElhqlyyHwPKYe5FFE0
+0vwBPiBG3FQ/8wPYB+BrDHhw0NCTg+LPU/w71bDJfUCL7l3TMOkkAR6wrN4aGJeh
+DVh5XmfNmb8CAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P
+cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUR9unkzjCDzR/
+t941ySN1zDCTpEIwHwYDVR0jBBgwFoAUlpotBvZ2T4Noe5xpxBi7SutGOOQwDQYJ
+KoZIhvcNAQEFBQADgYEAl3BHdM7h9lG/zM8Pz8wjdd9LPTbwcA9HXceWrbB4lYk6
+Knq6eUX+LzdMaXarChDqDV7+KAREnPONQ/UV+nm+04bzwbWLWnSpxbf+6GNuHxM6
+yUk7RQymZLkHmxowCR1e8CupVapB+oUN793D9VhSv39t9BgG9Fpxr+RXsApu9nY=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/private/cakey.pem
new file mode 100644
index 000000000..4c3de720f
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,48187111D008BD14
+
+9y5tseMMq8fPCuUelw75mRr1ALSrxNWatiMrmFM44I27wxIlaVgePNk3ovpuUpjB
+RTArkp0zqA8tHCE/ZzE0cKtkxabTfrghxeKb2lAIrIUFwAFnMPEoB69M23qKblQD
+/CbYquy6mpjzLBYwM0Ub8fj4d6fMCJ29Mqlbzj9XJ2oif8zW90lxE4CZNGEWKWaO
+pF0ytqUM0aVIBVXZOGmeUpJlAgwdshYHD0JwoULWzFOa+9aks+wjYwQcDxbPq3YC
+TBSzHiKd68YSDvK5VevIAIrSKEEqrXgsnL0k23/xkK5ZN8w9gmROrwpqg78Aa/cp
+13luMYMRAm+hBfCFzKXvc8hV49UCPWOJcB4/p8to8Bx95UcJ17npG71yrNJgwTA6
+Wgj4pxtddt4QItVqv6usIvkMwD4pQqZ4y+5UMEvw2paG428+SN6YElH6/6yB/9Cc
+B7BxhhaazM+AEulpvvfQgjpIqn5+QyaZ7GVcNh/Bi66tenNv9NBVqP1PmuZUMF77
+QddQGzCpxaSb/x/3InhMP2PgGN37B9ezm8ee+AQpmk1VzJ5zpiuoGbQ3oLnDVMKS
+aNe7VIyhovq7tnJIuIft8jOEMFfPot9vgIwnHVQ4PF+KK0bzWjSK+6HyO+1Jkw/5
+TpHfQSxEVf8brC8g9l7+FjGSbHF80EzOUx1lMDe/BUzuVvRhiewqrlkCrPf90uuy
+hEf1UKqrDK2i2iLBzZ0+OXba3wj20jFRaYLN5YykE6fKo/H6UjEn203nMI2Qi+2m
+5j5dgDAOXnNWQN45MxIMu6xxPSaEcb8YUgfMqwytfVmo/xSioyoV+w==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/serial
new file mode 100644
index 000000000..7d802a3e7
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/serial
@@ -0,0 +1 @@
+1002
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/openssl.cfg
new file mode 100644
index 000000000..51e520525
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/README.txt
new file mode 100644
index 000000000..b266749a9
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/README.txt
@@ -0,0 +1,5 @@
+To provide the CRL via HTTP run
+
+java -jar ../../tools/httpserv/dist/httpserv.jar -a 8902
+
+
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/cacert.pem
new file mode 100644
index 000000000..b350f6eb3
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/cacert.pem
@@ -0,0 +1,66 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 5
+ Validity
+ Not Before: Nov 20 11:30:23 2009 GMT
+ Not After : Nov 14 11:30:23 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 5
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:97:fa:a2:49:d3:bf:c1:2e:7a:ed:83:83:3c:78:
+ 96:c8:b2:b9:67:af:c0:5e:0a:89:89:fb:94:59:32:
+ a8:2a:e4:20:2f:3b:3d:ce:53:4f:72:fc:6c:0b:93:
+ 38:c3:df:66:6e:d5:79:d0:a4:4e:41:84:43:3c:99:
+ 79:0c:e0:5f:19:1a:3d:f5:4b:11:28:0f:80:b0:a0:
+ 71:34:5b:90:71:c2:ef:1e:85:2e:5b:9f:3b:22:c3:
+ 18:f8:7c:1f:ef:1b:78:17:a0:44:60:46:7e:88:eb:
+ a7:60:a0:5c:2a:7c:37:99:fa:27:97:08:e8:89:ba:
+ bc:69:4b:79:93:8f:ad:b5:9b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 01:E9:B5:99:E4:6D:F9:8C:42:3D:09:10:0F:A7:75:C6:27:78:4A:AF
+ X509v3 Authority Key Identifier:
+ keyid:C1:D1:A0:D4:5B:0B:9D:7E:31:61:F9:39:10:9F:31:10:E0:D2:06:B5
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 5
+ serial:F0:3D:B6:A9:A9:9C:A3:4E
+
+ X509v3 CRL Distribution Points:
+ URI:http://localhost:8901/demoCA/crl/Root_5.crl
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 6d:ca:34:05:99:ff:99:49:d3:6d:9d:ad:c6:99:da:9d:6c:94:
+ 62:77:ed:1c:39:23:d2:e8:b6:3e:df:63:dc:7c:10:3f:c2:ed:
+ f4:04:26:58:05:01:4c:ed:a9:83:43:3a:5d:fe:60:6d:5b:58:
+ dc:93:8c:94:69:b6:7f:02:48:30:9c:31:f4:7d:de:e0:de:04:
+ d2:dc:79:b7:60:c2:87:f7:c7:92:a2:f5:86:a7:0c:70:3b:a3:
+ a7:35:11:cf:a4:28:21:aa:8b:24:50:2e:96:41:be:66:01:bd:
+ b9:ec:04:0c:92:d9:8a:e7:a0:96:24:9b:f1:a2:9f:59:59:4a:
+ 32:a4
+-----BEGIN CERTIFICATE-----
+MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA1MB4XDTA5MTEyMDExMzAy
+M1oXDTM0MTExNDExMzAyM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA1MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQCX+qJJ07/BLnrtg4M8eJbIsrlnr8BeComJ+5RZMqgq5CAvOz3OU09y
+/GwLkzjD32Zu1XnQpE5BhEM8mXkM4F8ZGj31SxEoD4CwoHE0W5Bxwu8ehS5bnzsi
+wxj4fB/vG3gXoERgRn6I66dgoFwqfDeZ+ieXCOiJurxpS3mTj621mwIDAQABo4IB
+BjCCAQIwHQYDVR0OBBYEFAHptZnkbfmMQj0JEA+ndcYneEqvMIGRBgNVHSMEgYkw
+gYaAFMHRoNRbC51+MWH5ORCfMRDg0ga1oWOkYTBfMQswCQYDVQQGEwJERTEQMA4G
+A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT
+C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDWCCQDwPbapqZyjTjA8BgNVHR8E
+NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290
+XzUuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAbco0BZn/
+mUnTbZ2txpnanWyUYnftHDkj0ui2Pt9j3HwQP8Lt9AQmWAUBTO2pg0M6Xf5gbVtY
+3JOMlGm2fwJIMJwx9H3e4N4E0tx5t2DCh/fHkqL1hqcMcDujpzURz6QoIaqLJFAu
+lkG+ZgG9uewEDJLZiuegliSb8aKfWVlKMqQ=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/Sub_CA_1_Root_5.crl b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/Sub_CA_1_Root_5.crl
new file mode 100644
index 000000000..3aec2bba1
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/Sub_CA_1_Root_5.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crlnumber
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crlnumber
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt
new file mode 100644
index 000000000..2f83d6f9b
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt
@@ -0,0 +1 @@
+V 341114113322Z 1002 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 5
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/newcerts/1002.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/newcerts/1002.pem
new file mode 100644
index 000000000..59d5f7a2b
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/newcerts/1002.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4098 (0x1002)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 5
+ Validity
+ Not Before: Nov 20 11:33:22 2009 GMT
+ Not After : Nov 14 11:33:22 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 5
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:d3:fd:a7:4f:ea:02:e2:b4:32:80:3f:64:bb:37:
+ 9d:9e:fa:86:b2:25:b3:1d:f6:5d:05:8e:2b:0c:bd:
+ 60:1e:e6:52:39:4c:84:9e:93:6c:d2:b4:2d:34:1a:
+ e7:42:b6:bf:34:bd:ca:44:31:fb:06:5e:20:0a:a1:
+ 22:ca:9b:4f:01:57:bd:b1:30:57:a9:0f:fc:06:ae:
+ 18:6c:2d:9e:70:7a:21:2a:fd:0c:f8:03:00:32:60:
+ 5d:37:c5:11:56:74:30:e4:03:3c:88:71:d5:79:d3:
+ 76:02:e1:85:87:63:4b:5b:cd:c9:1f:ca:85:7a:8c:
+ 3a:fd:a9:83:94:b9:6d:f6:95
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 CRL Distribution Points:
+ URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_5.crl
+
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ E0:53:2E:E4:6B:0B:99:C0:AD:C1:02:40:46:6C:35:EE:49:73:5D:0B
+ X509v3 Authority Key Identifier:
+ keyid:01:E9:B5:99:E4:6D:F9:8C:42:3D:09:10:0F:A7:75:C6:27:78:4A:AF
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 5f:6a:81:3b:56:e8:6d:33:0e:1e:6a:73:b1:e8:69:b7:3f:83:
+ 81:6c:73:7c:9d:f7:12:c9:bf:99:16:cf:56:38:e4:58:db:28:
+ a5:9c:e3:8e:ed:27:d2:da:53:41:80:2a:d4:c3:92:5d:b5:b4:
+ 5a:d6:17:f7:74:9d:83:13:06:7f:20:8e:50:5f:60:5b:3a:9a:
+ 9f:c2:58:5f:fa:07:90:df:a0:02:cf:c4:d7:7d:2e:b7:72:df:
+ 8f:93:ce:5a:b3:17:ba:73:93:20:64:b9:b2:ad:6e:89:63:c5:
+ 08:e1:a0:6a:b2:9d:1e:33:31:83:98:d1:05:7d:ec:48:72:1f:
+ dd:60
+-----BEGIN CERTIFICATE-----
+MIIC5jCCAk+gAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA1MB4XDTA5
+MTEyMDExMzMyMloXDTM0MTExNDExMzMyMlowbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgNTCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0/2nT+oC4rQygD9kuzednvqGsiWzHfZd
+BY4rDL1gHuZSOUyEnpNs0rQtNBrnQra/NL3KRDH7Bl4gCqEiyptPAVe9sTBXqQ/8
+Bq4YbC2ecHohKv0M+AMAMmBdN8URVnQw5AM8iHHVedN2AuGFh2NLW83JH8qFeow6
+/amDlLlt9pUCAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j
+YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMV9Sb290XzUuY3JsMAsGA1Ud
+DwQEAwIF4DAdBgNVHQ4EFgQU4FMu5GsLmcCtwQJARmw17klzXQswHwYDVR0jBBgw
+FoAUAem1meRt+YxCPQkQD6d1xid4Sq8wDQYJKoZIhvcNAQEFBQADgYEAX2qBO1bo
+bTMOHmpzsehptz+DgWxzfJ33Esm/mRbPVjjkWNsopZzjju0n0tpTQYAq1MOSXbW0
+WtYX93SdgxMGfyCOUF9gWzqan8JYX/oHkN+gAs/E130ut3Lfj5POWrMXunOTIGS5
+sq1uiWPFCOGgarKdHjMxg5jRBX3sSHIf3WA=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/private/cakey.pem
new file mode 100644
index 000000000..fb9af1caa
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,30B50FFE9747C5F2
+
+pXO59gJmBcDztjZDwRRcJV+m/BBdF/NlI0WD7WBr4vR663B6hZw0hqAkCn3o0VbO
+DzLsoQUMUv/70aXc2SgvS8LleG+mWCkPE+huzFjPAn6Z6+p0MhHrYRJ7iulPAVV0
++wCs8+1UbvKyozLy+BfvEwGHEho8sr3w81y2noE2pjaQOE1JGKY91VnFz1yPhYHC
+r26sO1DqoqtWS8XSe2FdREG/guKpoHtoUazQhCkgeBk18OImKlrxp1pT/haObv5i
+5qILjSvMBjmrTCJDi1vgShEiAZTE318ipK5wCLKiA6UvZ3GMxb2xjy+na3CUTrzf
+AAefrW4NaoyIWI8dRtPxFic678ZgqcRMdMW7BgdffLXX5IueCqHeTNS7xcr2T2gd
+hzKxinZnY8MQosFeyzP3fYWxv5PY54HNmCnsN2SXJSOq+CPSsIvbDR5p1bhrcEf9
+1O815NhJTx2nPAkIC+7bemAkz2f3g09SuhtQTaCnZMwcAmnMAT0ewWJSxDCVOg5s
+B/OPe8RJ1tiO7DnaZH6RQDPUCKaUgS9xSzCu1q0IWWbzUWioPIX13fFlvl9gAxbY
++FI6dD2DwHBTyiPLLyT7FBfwjnHul2zSn/jXnby7n1sILQIP0AQK0cJDS1ZdC2CB
+oe4gwzSVCxp7v3Zfp1ZoyYOtei0gT6+bDvjBYsl90jyvyucWfKjlZiEauQV8gSOQ
+G2iY5QZ0clAFg7MQKmHuTaAALk0IrauSW20eR/HF0/2R6xCt91zcyhwbOiZFNyQ3
+gtvwLu9ZzAHfWcnIEWxpYF68O+vj+g6Jpl/q6j8KaTta3smEBzgpow==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/serial
new file mode 100644
index 000000000..baccd0398
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/serial
@@ -0,0 +1 @@
+1003
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/openssl.cfg
new file mode 100644
index 000000000..963ab884f
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_5.crl
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+#nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/cacert.pem
new file mode 100644
index 000000000..0490b88cd
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/cacert.pem
@@ -0,0 +1,66 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 6
+ Validity
+ Not Before: Nov 20 12:28:07 2009 GMT
+ Not After : Nov 14 12:28:07 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 6
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:c4:d9:ab:27:06:66:41:0e:36:ff:d4:b1:d0:8c:
+ f7:b4:25:55:cd:fd:fa:a4:5a:e6:4f:d0:05:dc:a3:
+ e5:bd:8d:53:77:d1:ea:95:5a:52:81:c8:b6:36:a0:
+ 5f:3a:e1:85:1e:8a:48:91:7d:29:78:ff:ea:c5:e3:
+ ad:c4:27:d5:b7:8f:59:20:26:d4:45:87:6a:56:db:
+ ac:f5:f8:0a:88:82:9e:c2:00:06:fc:98:8a:fe:35:
+ c3:02:a1:67:08:06:42:e3:88:48:e0:8f:33:ff:f8:
+ a4:87:1a:3a:d9:54:0e:1c:09:3e:a0:f0:70:cd:b5:
+ b0:b2:7e:07:73:ad:20:64:69
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 89:8C:D7:71:EB:67:78:4E:D6:01:35:B2:AC:A1:B4:88:43:CE:70:A7
+ X509v3 Authority Key Identifier:
+ keyid:AC:25:5E:9B:B5:BA:4D:8E:BD:77:B2:9D:D9:E2:84:AE:7A:31:8F:F2
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 6
+ serial:D8:6A:4F:24:F9:C9:94:27
+
+ X509v3 CRL Distribution Points:
+ URI:http://localhost:8901/demoCA/crl/Root_6.crl
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 55:5b:3b:6b:8a:d0:1b:d8:19:d9:96:85:4d:b4:a0:98:b1:bd:
+ 9f:0b:62:21:92:8b:4e:d3:d0:1b:91:3d:e3:f5:bd:ce:16:57:
+ fc:b7:84:15:51:fd:98:ab:32:59:28:0b:44:57:49:ec:ac:11:
+ 67:26:7a:a3:c5:b8:9d:2a:de:b6:7c:76:0a:e9:18:9f:98:87:
+ e8:80:c8:72:99:56:74:ab:73:1b:f4:e7:b9:b1:3a:f3:7b:0d:
+ 2f:5d:82:6c:d1:99:9f:23:be:23:fb:4c:0e:15:5e:f5:9f:90:
+ 88:d7:51:3a:6a:7a:f0:54:a5:c4:89:a5:0d:0a:4e:94:59:64:
+ 59:54
+-----BEGIN CERTIFICATE-----
+MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA2MB4XDTA5MTEyMDEyMjgw
+N1oXDTM0MTExNDEyMjgwN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA2MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDE2asnBmZBDjb/1LHQjPe0JVXN/fqkWuZP0AXco+W9jVN30eqVWlKB
+yLY2oF864YUeikiRfSl4/+rF463EJ9W3j1kgJtRFh2pW26z1+AqIgp7CAAb8mIr+
+NcMCoWcIBkLjiEjgjzP/+KSHGjrZVA4cCT6g8HDNtbCyfgdzrSBkaQIDAQABo4IB
+BjCCAQIwHQYDVR0OBBYEFImM13HrZ3hO1gE1sqyhtIhDznCnMIGRBgNVHSMEgYkw
+gYaAFKwlXpu1uk2OvXeyndnihK56MY/yoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G
+A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT
+C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDaCCQDYak8k+cmUJzA8BgNVHR8E
+NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290
+XzYuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAVVs7a4rQ
+G9gZ2ZaFTbSgmLG9nwtiIZKLTtPQG5E94/W9zhZX/LeEFVH9mKsyWSgLRFdJ7KwR
+ZyZ6o8W4nSretnx2CukYn5iH6IDIcplWdKtzG/TnubE683sNL12CbNGZnyO+I/tM
+DhVe9Z+QiNdROmp68FSlxImlDQpOlFlkWVQ=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crl/DO_NOT_CREATE_A_CRL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crl/DO_NOT_CREATE_A_CRL
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crlnumber
new file mode 100644
index 000000000..83b33d238
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crlnumber
@@ -0,0 +1 @@
+1000
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt
new file mode 100644
index 000000000..6e4d7577d
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt
@@ -0,0 +1 @@
+V 341114123743Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 6
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..538cb4e0b
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/newcerts/1000.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 6
+ Validity
+ Not Before: Nov 20 12:37:43 2009 GMT
+ Not After : Nov 14 12:37:43 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 6
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:bb:ac:68:10:41:28:94:fd:fe:39:5e:63:cf:eb:
+ 9f:2b:20:82:f3:86:d2:e1:38:05:7e:95:cc:46:e5:
+ 42:8b:5c:0d:2c:ad:ad:44:c0:4c:2f:7c:75:e8:bd:
+ aa:cd:f2:05:16:18:a5:a3:fa:e7:a0:ba:57:31:e2:
+ b0:4d:85:9d:60:e4:41:92:49:3f:e1:79:47:52:e8:
+ 9e:71:be:88:10:6c:30:89:9f:55:84:9d:83:d0:c9:
+ 11:66:95:33:8b:44:38:86:45:05:b3:3a:54:c4:cf:
+ 4e:72:4c:00:07:d7:59:3a:8d:2f:cd:5e:0c:a0:95:
+ be:00:85:7a:a4:42:c2:f3:b7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 CRL Distribution Points:
+ URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_6.crl
+
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 57:51:A4:44:AE:92:01:3C:9F:7E:82:67:C0:E5:B9:D7:A6:8F:A5:79
+ X509v3 Authority Key Identifier:
+ keyid:89:8C:D7:71:EB:67:78:4E:D6:01:35:B2:AC:A1:B4:88:43:CE:70:A7
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 7b:de:f2:2b:d7:94:ce:12:e2:f9:a7:b2:91:08:c6:51:3f:bc:
+ e2:87:ed:79:6d:3b:f5:38:6e:02:d4:63:e6:b8:a7:e5:df:f4:
+ 6e:b0:8a:bd:bb:b1:0b:e0:c2:cf:fa:af:0a:6a:a5:1f:28:ff:
+ de:21:bd:8a:f7:ec:48:35:bb:ab:97:c2:7a:31:6d:d1:73:8e:
+ ae:74:9b:94:86:73:06:06:da:6a:2c:82:04:b1:49:19:62:a9:
+ 05:e5:e7:2c:68:a1:3b:f4:bf:80:85:5b:1b:dc:21:7b:3d:c1:
+ ee:97:6c:72:35:2d:80:19:90:b4:ab:19:34:bb:88:5e:ea:70:
+ 27:df
+-----BEGIN CERTIFICATE-----
+MIIC5jCCAk+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA2MB4XDTA5
+MTEyMDEyMzc0M1oXDTM0MTExNDEyMzc0M1owbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgNjCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAu6xoEEEolP3+OV5jz+ufKyCC84bS4TgF
+fpXMRuVCi1wNLK2tRMBML3x16L2qzfIFFhilo/rnoLpXMeKwTYWdYORBkkk/4XlH
+Uuiecb6IEGwwiZ9VhJ2D0MkRZpUzi0Q4hkUFszpUxM9OckwAB9dZOo0vzV4MoJW+
+AIV6pELC87cCAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j
+YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMV9Sb290XzYuY3JsMAsGA1Ud
+DwQEAwIF4DAdBgNVHQ4EFgQUV1GkRK6SATyffoJnwOW516aPpXkwHwYDVR0jBBgw
+FoAUiYzXcetneE7WATWyrKG0iEPOcKcwDQYJKoZIhvcNAQEFBQADgYEAe97yK9eU
+zhLi+aeykQjGUT+84ofteW079ThuAtRj5rin5d/0brCKvbuxC+DCz/qvCmqlHyj/
+3iG9ivfsSDW7q5fCejFt0XOOrnSblIZzBgbaaiyCBLFJGWKpBeXnLGihO/S/gIVb
+G9whez3B7pdscjUtgBmQtKsZNLuIXupwJ98=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/private/cakey.pem
new file mode 100644
index 000000000..9912ee088
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,8F1C89446B1EC221
+
+joSSrVc7E1RavSuMdWDDAozXOV4Z0XIusMv5NjIWHLyKdW/SmFv6yfPy7PeuK1Qj
+p/DuEO/ULU6SLmAhESXrdC8UzyL/B3hfPK3UzUzJzIRrDitF21SXLjMKU+KVxMrb
+GkmstfsIQM157TZHOHJbk4F9zs9Xkl8ipKYDBpJrtVJo8gf4SeLfcEVXW9J0tlLU
+Qi13SWWn4kGK+Latypx684S247Y0JfKSJ5BVHUGunmd+b/3mRpH1WARU03JmNqG9
+tyCJxyvCkkQh5Jnm4UEI72ywxSscemtFAzd5fa5LOrsVWOImSixfP1VdJvU0jCTv
+gyXK03e/L+B+DhbUm2a6xkt+u83hQ2QjoGdmnfKwhX4vdYZBYINlBnHtHn2B8x2o
+IXgLQmBFO/heY/K9wJ1BwwqPW31wHG3MhjRY7ooac1JAZsxS0/pU8cR/GNMpKjvE
+fer3tGGUvPL3H1v3pT2XAA4Gm9pOtvnOHuLjbzg2mgNZScYMpcqa/vaQ5gXqCnhw
+dtFrGVxEEQ5jTL23EAh4WfhPvsnewujr7Rkc6+a8xKpDJOHejgAPJYpXrYHg4poA
+L0aQlIFSX1jriGu4KYAQiZO7bouhVWqcf9B3BNewr0kTaD7qq0gDvygCKLyrUyb7
+hqk0TwVfvmk7nYNFLBsTEcsB/el6jqH40oOfFo+ErlQzmdzRrKy9gBEaecDj8DxV
+Fa8XPapE81O8WjS09a/WJNPW+3NdrI5wYMg72srOW8ll+AMtiUTWrAY2hIRxzZGt
+VntCKwG/3j0v60jg+0wCP+l/IV4pPbV4He3ysxwM6lH1Y86XfaUBiA==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/serial
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/serial
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/openssl.cfg
new file mode 100644
index 000000000..188ed62e2
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_6.crl
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+#nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/README.txt
new file mode 100644
index 000000000..d70e0550a
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/README.txt
@@ -0,0 +1,3 @@
+To provide the CRL run:
+
+java -jar ../../tools/httpserv/dist/httpserv.jar -a 8902
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/cacert.pem
new file mode 100644
index 000000000..2dda8f2b2
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/cacert.pem
@@ -0,0 +1,66 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 7
+ Validity
+ Not Before: Nov 20 13:07:53 2009 GMT
+ Not After : Nov 14 13:07:53 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 7
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:b0:ae:6d:0a:21:ae:8a:92:b1:16:25:d3:08:cb:
+ ac:b7:4c:53:6d:4b:b3:12:82:40:54:c9:44:28:fc:
+ 4e:10:e6:65:40:de:70:5d:8b:ab:1f:5c:77:03:43:
+ 3d:3a:3d:9e:f7:37:66:9a:33:68:a0:cf:ad:8f:f4:
+ fb:9c:a3:87:57:5d:ec:d6:55:5a:18:b5:e1:2b:d2:
+ c4:10:fe:f0:01:a5:da:29:ee:c4:af:15:c9:8c:dc:
+ 7c:45:84:bd:e5:5b:09:1f:16:1d:11:e7:61:e6:22:
+ e7:1f:c8:86:bf:a1:da:cb:fe:6b:7e:c0:6e:aa:7f:
+ 97:84:e8:8f:81:69:f1:26:87
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 54:64:15:7E:93:8A:19:C8:F9:B7:EF:60:A0:DF:5C:C8:15:56:C0:EE
+ X509v3 Authority Key Identifier:
+ keyid:80:C6:F8:0B:5F:7C:49:E4:86:FD:C8:92:C6:80:70:D9:C0:6F:7B:DE
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 7
+ serial:D5:E6:63:5F:18:09:82:89
+
+ X509v3 CRL Distribution Points:
+ URI:http://localhost:8901/demoCA/crl/Root_7.crl
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 1a:bc:5a:4b:9a:d5:e8:c0:35:c2:61:0a:58:7d:33:e2:87:01:
+ 61:83:80:42:8d:1a:7e:b1:9a:58:d5:01:fd:e7:ae:5c:c8:65:
+ fb:9e:1d:bf:49:ba:ed:40:f4:05:7c:3b:2d:db:0e:53:d0:05:
+ a0:bd:15:87:c4:37:22:0b:a0:04:a3:ad:cb:57:b2:00:97:ee:
+ 8f:89:91:8e:7d:0b:e2:27:96:6e:0f:ab:73:33:59:fa:9f:37:
+ f2:77:79:99:af:72:ad:f9:49:05:ed:55:08:31:eb:97:0f:99:
+ 6e:9c:a3:df:f0:52:1a:14:4e:78:25:0c:8b:02:cb:56:e9:4d:
+ f5:9f
+-----BEGIN CERTIFICATE-----
+MIIDRjCCAq+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA3MB4XDTA5MTEyMDEzMDc1
+M1oXDTM0MTExNDEzMDc1M1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA3MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQCwrm0KIa6KkrEWJdMIy6y3TFNtS7MSgkBUyUQo/E4Q5mVA3nBdi6sf
+XHcDQz06PZ73N2aaM2igz62P9Puco4dXXezWVVoYteEr0sQQ/vABpdop7sSvFcmM
+3HxFhL3lWwkfFh0R52HmIucfyIa/odrL/mt+wG6qf5eE6I+BafEmhwIDAQABo4IB
+BjCCAQIwHQYDVR0OBBYEFFRkFX6TihnI+bfvYKDfXMgVVsDuMIGRBgNVHSMEgYkw
+gYaAFIDG+AtffEnkhv3IksaAcNnAb3veoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G
+A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT
+C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDeCCQDV5mNfGAmCiTA8BgNVHR8E
+NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290
+XzcuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAGrxaS5rV
+6MA1wmEKWH0z4ocBYYOAQo0afrGaWNUB/eeuXMhl+54dv0m67UD0BXw7LdsOU9AF
+oL0Vh8Q3IgugBKOty1eyAJfuj4mRjn0L4ieWbg+rczNZ+p838nd5ma9yrflJBe1V
+CDHrlw+Zbpyj3/BSGhROeCUMiwLLVulN9Z8=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/Sub_CA_1_Root_7.crl b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/Sub_CA_1_Root_7.crl
new file mode 100644
index 000000000..f3f7e5cba
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/Sub_CA_1_Root_7.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crlnumber
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crlnumber
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt
new file mode 100644
index 000000000..8bcb130f6
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt
@@ -0,0 +1,2 @@
+V 341114131904Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 7
+R 341114132648Z 091120132827Z,CACompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 1 Root 7
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..234638d8c
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1000.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 7
+ Validity
+ Not Before: Nov 20 13:19:04 2009 GMT
+ Not After : Nov 14 13:19:04 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 7
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:ce:23:98:19:ac:0d:7c:f0:60:a2:94:72:c3:ab:
+ a5:a1:6b:d3:af:8c:cb:b9:c9:ee:0b:3e:a4:2e:0e:
+ 08:a5:a9:4c:09:2f:1a:a0:fe:87:89:41:4a:aa:b6:
+ ac:b4:bc:d3:0e:f9:c3:12:1f:b1:90:b3:6d:72:a6:
+ 38:5b:9d:05:7e:97:ff:f4:e1:31:2b:b4:08:de:b1:
+ 43:fe:1d:7e:32:54:ce:db:d5:14:21:f3:ad:9f:26:
+ f3:c6:0b:77:51:e4:11:88:ad:86:e1:30:d1:af:87:
+ 29:c0:7b:92:db:68:06:74:ca:27:ac:0b:61:3a:ac:
+ ba:03:35:e7:8e:08:28:58:7d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 CRL Distribution Points:
+ URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl
+
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ DE:66:84:E4:9B:BF:70:00:BD:60:3D:34:45:96:FE:FD:D5:88:9B:CD
+ X509v3 Authority Key Identifier:
+ keyid:54:64:15:7E:93:8A:19:C8:F9:B7:EF:60:A0:DF:5C:C8:15:56:C0:EE
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 6e:da:66:d2:3b:00:d6:0b:5a:9f:21:28:de:e1:10:fe:fd:26:
+ db:a6:75:86:74:47:e4:b0:b7:c4:c1:dc:43:82:51:71:00:8f:
+ bf:71:9a:23:db:2d:79:27:a2:80:2e:12:a4:5f:13:0c:73:53:
+ 1e:5c:33:6a:e9:31:be:e2:ae:4f:55:b0:e8:0a:0f:54:f0:3a:
+ 7e:14:41:d7:34:18:58:90:26:63:7d:2c:1a:ab:93:7f:4a:3d:
+ 5e:cf:f1:9d:c3:76:ee:a4:76:1c:d8:f9:d0:ac:53:3c:1a:4d:
+ c7:fa:b6:23:54:4b:04:a1:e2:76:a5:e3:0d:b8:db:8e:d3:39:
+ c2:65
+-----BEGIN CERTIFICATE-----
+MIIC5jCCAk+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA3MB4XDTA5
+MTEyMDEzMTkwNFoXDTM0MTExNDEzMTkwNFowbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgNzCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAziOYGawNfPBgopRyw6uloWvTr4zLucnu
+Cz6kLg4IpalMCS8aoP6HiUFKqrastLzTDvnDEh+xkLNtcqY4W50Ffpf/9OExK7QI
+3rFD/h1+MlTO29UUIfOtnybzxgt3UeQRiK2G4TDRr4cpwHuS22gGdMonrAthOqy6
+AzXnjggoWH0CAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j
+YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMV9Sb290XzcuY3JsMAsGA1Ud
+DwQEAwIF4DAdBgNVHQ4EFgQU3maE5Ju/cAC9YD00RZb+/dWIm80wHwYDVR0jBBgw
+FoAUVGQVfpOKGcj5t+9goN9cyBVWwO4wDQYJKoZIhvcNAQEFBQADgYEAbtpm0jsA
+1gtanyEo3uEQ/v0m26Z1hnRH5LC3xMHcQ4JRcQCPv3GaI9steSeigC4SpF8TDHNT
+HlwzaukxvuKuT1Ww6AoPVPA6fhRB1zQYWJAmY30sGquTf0o9Xs/xncN27qR2HNj5
+0KxTPBpNx/q2I1RLBKHidqXjDbjbjtM5wmU=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1001.pem
new file mode 100644
index 000000000..ddc504d77
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1001.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 7
+ Validity
+ Not Before: Nov 20 13:26:48 2009 GMT
+ Not After : Nov 14 13:26:48 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 1 Root 7
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:b3:58:b2:22:45:b9:37:83:e5:a4:6f:5d:4e:59:
+ 60:60:4e:46:26:27:9a:70:4d:34:89:cf:cb:4f:4f:
+ 0b:22:6e:e4:21:e6:ab:c9:0a:4a:c4:cd:6f:3c:db:
+ e8:a3:52:55:2d:26:1d:13:9a:8b:cf:38:25:4e:4f:
+ 4a:e3:39:01:fa:5b:10:a5:3e:e1:93:65:19:ca:8b:
+ 5c:9f:e8:19:ed:0a:ef:47:e9:11:73:28:ce:b0:95:
+ 10:3a:ce:b5:46:89:79:a3:90:ea:d5:ca:ac:c9:af:
+ ee:55:0d:6c:32:5f:d2:f1:76:1c:b9:e7:d2:ac:07:
+ 61:83:82:c5:95:5a:62:ff:67
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 CRL Distribution Points:
+ URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl
+
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 12:7A:7A:69:C5:FE:E0:23:FD:8E:51:25:55:94:9F:C8:44:D8:F2:29
+ X509v3 Authority Key Identifier:
+ keyid:54:64:15:7E:93:8A:19:C8:F9:B7:EF:60:A0:DF:5C:C8:15:56:C0:EE
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 4a:57:08:6a:66:af:b4:05:4f:b3:4c:39:23:2b:5d:c9:88:7b:
+ 6f:b5:28:a3:5a:72:e6:0b:e2:9e:64:65:ce:8f:b5:31:0f:5f:
+ c7:b7:56:96:4f:d3:34:65:1a:ea:84:60:2b:fe:27:1f:75:fd:
+ 0f:53:e5:eb:25:d3:f6:2c:21:72:59:40:32:ba:ec:72:cc:64:
+ d6:1d:db:cf:ca:ec:91:0a:81:ef:f5:e4:56:31:a3:c2:9a:1d:
+ e9:5c:48:b0:7c:7b:e2:51:35:33:ad:a8:5c:79:ac:ee:bf:42:
+ fa:0b:a0:02:72:cc:5e:07:c0:d4:d3:96:26:16:3e:8c:32:8d:
+ b4:09
+-----BEGIN CERTIFICATE-----
+MIIC5jCCAk+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA3MB4XDTA5
+MTEyMDEzMjY0OFoXDTM0MTExNDEzMjY0OFowbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAxIFJvb3QgNzCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAs1iyIkW5N4PlpG9dTllgYE5GJieacE00
+ic/LT08LIm7kIearyQpKxM1vPNvoo1JVLSYdE5qLzzglTk9K4zkB+lsQpT7hk2UZ
+yotcn+gZ7QrvR+kRcyjOsJUQOs61Rol5o5Dq1cqsya/uVQ1sMl/S8XYcuefSrAdh
+g4LFlVpi/2cCAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j
+YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMV9Sb290XzcuY3JsMAsGA1Ud
+DwQEAwIF4DAdBgNVHQ4EFgQUEnp6acX+4CP9jlElVZSfyETY8ikwHwYDVR0jBBgw
+FoAUVGQVfpOKGcj5t+9goN9cyBVWwO4wDQYJKoZIhvcNAQEFBQADgYEASlcIamav
+tAVPs0w5IytdyYh7b7Uoo1py5gvinmRlzo+1MQ9fx7dWlk/TNGUa6oRgK/4nH3X9
+D1Pl6yXT9iwhcllAMrrscsxk1h3bz8rskQqB7/XkVjGjwpod6VxIsHx74lE1M62o
+XHms7r9C+gugAnLMXgfA1NOWJhY+jDKNtAk=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/private/cakey.pem
new file mode 100644
index 000000000..c107913a2
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,D710D797627524D4
+
+SC46mzOOSpNMZ9t2F3syLy0MmYOk3zBJnY/qcm/ggD4ETOse6zGpqhXVSeZdn3OG
+Uwj+b9tCjVC/7GMWanH4DmshCv89IRljMyy5DShsOVmgAr0hqLZNlkKqQRRRHC4d
+y9ozYq1J9Zcj16jTmCbpPJW8Ul7kblelNbD0nVgJABc6m6Di/syCFEC0KVGmoJZv
+5QjxyNiulh0UNmmP+X6iEGPWw4s5JJdcAg5DFXjPiCvvGazvjCGTT38Hcnya4GkB
+9aHo7KbjFU4P98zQKUAV0fSVU7+tzJrLxH0aefenbkIKI45xegOTJmcv8NEZ3YgQ
+64r+OlmqOONmvcWrtUdhADvsl8oJ8Lz+1UYcyPpbYLUvMhj8Potf6C6rCz1GuQPS
+EmGPltUAOcaylpnP/neyuErAMHGQI9Mn2dhLc/NGK6gxqZi1SawGbrit7Uv5il/n
+O3zc7D+d1Jmdkcqm/BZKsMW5hwM3KF4gzb6zMe/8ZCmtqT4iH4eDqjFQfaWeBXNK
+kTM8vMUNCU8yQjMYoWL8iL4NNJxRheD0l2FABcGTbWI159eXy8laenk5eBfYKIwl
+YGnoylDD2F4W0mdMl2MJIYNYTRP7pAQhLnMbVNSgGDgk5Z0kUF2Kl2rNz+3w1c36
+L3VC/CGFp5/spnQHhYMH2oUAkliS0iev7bNJyhvycVQkMlwYu8KZKMtqyn9bnpU4
+Kd6XlXPwF3BHGrVVdcb6RQo65GrwT6j+hWRwUKgEvcxC7BjtsY1ZV3xRfsRQpA/b
+1sTQ/W0ev09+OJAHWEedIg2sTTp5WSiF2whCz6yviFxEAeYIUEGVHw==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/serial
new file mode 100644
index 000000000..7d802a3e7
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/serial
@@ -0,0 +1 @@
+1002
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/openssl.cfg
new file mode 100644
index 000000000..7cbc4664f
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+#nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/README.txt
new file mode 100644
index 000000000..4d510fe39
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/README.txt
@@ -0,0 +1,13 @@
+Revoked certificates:
+
+- User 2 Sub CA 1 Root 8
+
+
+Start the OCSP responder:
+openssl ocsp -index demoCA/index.txt -port 8889 -rsigner demoCA/cacert.pem -rkey demoCA/private/cakey.pem -CA demoCA/cacert.pem -text
+
+
+
+
+
+
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/cacert.pem
new file mode 100644
index 000000000..b2d1deb75
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/cacert.pem
@@ -0,0 +1,66 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 8
+ Validity
+ Not Before: Nov 20 15:33:21 2009 GMT
+ Not After : Nov 14 15:33:21 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 8
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:96:79:01:9f:4f:68:c1:09:0d:44:3a:82:e4:eb:
+ ad:70:7a:cf:b9:71:e5:fb:e0:c8:0c:21:79:3e:cb:
+ 78:91:7f:4a:a0:de:3e:37:0f:a1:6b:73:10:12:9b:
+ 08:c4:96:dc:cb:a8:5b:87:9b:75:24:e4:00:5e:4a:
+ 6f:4c:13:79:1f:57:13:8c:3e:1b:38:31:e1:77:74:
+ 52:f9:94:47:36:57:33:bd:de:08:11:a3:01:e1:53:
+ 1c:bd:7b:39:9c:5e:96:5c:a9:61:6c:cc:2b:90:8d:
+ 5a:3c:9e:f4:4b:6e:e5:97:64:86:f3:8e:e8:72:20:
+ 5d:0d:50:bf:e9:cf:be:d4:13
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ EF:BD:C8:8E:78:79:F9:76:4B:11:59:B6:C3:32:10:07:C0:BC:E3:8A
+ X509v3 Authority Key Identifier:
+ keyid:D6:66:76:C9:05:FF:A9:50:88:96:60:DD:FB:C7:30:18:72:67:41:19
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 8
+ serial:B2:47:DE:6A:2A:4C:83:19
+
+ Authority Information Access:
+ OCSP - URI:http://localhost:8888
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 4c:95:44:3b:57:08:ec:01:ec:f9:3e:7c:89:1c:30:b1:4e:26:
+ 32:b6:57:fa:25:bc:ed:eb:d4:a2:1c:67:ee:b9:8b:d0:4c:57:
+ 8a:0e:db:a0:9d:92:e7:de:c6:73:01:e7:de:61:1b:b5:0e:d0:
+ c5:c1:a7:a6:ab:e0:c6:0b:51:dd:e5:a2:32:1f:c6:52:ea:d3:
+ 03:68:3a:f5:92:bd:8b:b8:03:bb:50:70:63:cc:ec:ed:3c:11:
+ 76:ca:ac:72:47:ad:99:6b:8e:07:9e:38:f2:63:e1:ba:d4:df:
+ a9:73:54:1d:74:89:94:01:2e:68:dd:97:e7:53:f9:cf:b6:7d:
+ fc:87
+-----BEGIN CERTIFICATE-----
+MIIDOTCCAqKgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4MB4XDTA5MTEyMDE1MzMy
+MVoXDTM0MTExNDE1MzMyMVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA4MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQCWeQGfT2jBCQ1EOoLk661wes+5ceX74MgMIXk+y3iRf0qg3j43D6Fr
+cxASmwjEltzLqFuHm3Uk5ABeSm9ME3kfVxOMPhs4MeF3dFL5lEc2VzO93ggRowHh
+Uxy9ezmcXpZcqWFszCuQjVo8nvRLbuWXZIbzjuhyIF0NUL/pz77UEwIDAQABo4H6
+MIH3MB0GA1UdDgQWBBTvvciOeHn5dksRWbbDMhAHwLzjijCBkQYDVR0jBIGJMIGG
+gBTWZnbJBf+pUIiWYN37xzAYcmdBGaFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4ggkAskfeaipMgxkwMQYIKwYBBQUH
+AQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojg4ODgwDwYDVR0T
+AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBMlUQ7VwjsAez5PnyJHDCxTiYy
+tlf6Jbzt69SiHGfuuYvQTFeKDtugnZLn3sZzAefeYRu1DtDFwaemq+DGC1Hd5aIy
+H8ZS6tMDaDr1kr2LuAO7UHBjzOztPBF2yqxyR62Za44HnjjyY+G61N+pc1QddImU
+AS5o3ZfnU/nPtn38hw==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/Sub_CA_1_Root_8.crl b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/Sub_CA_1_Root_8.crl
new file mode 100644
index 000000000..7a9ee345e
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/Sub_CA_1_Root_8.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crlnumber
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crlnumber
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt
new file mode 100644
index 000000000..ff1b3fe19
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt
@@ -0,0 +1,2 @@
+V 341114154212Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 8
+R 341114154716Z 091120155036Z,superseded 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 1 Root 8
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..71456d01b
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1000.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 8
+ Validity
+ Not Before: Nov 20 15:42:12 2009 GMT
+ Not After : Nov 14 15:42:12 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 8
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:b6:aa:34:ec:31:e5:9a:aa:fe:90:31:1f:e5:83:
+ 90:cb:9a:9e:15:cd:bb:35:1b:fc:3c:8b:d9:3d:29:
+ de:f4:07:3f:4c:06:9b:4f:db:21:a2:4b:87:8b:fd:
+ b4:61:31:de:34:6c:14:10:f9:a7:7a:e0:0a:e9:bf:
+ b3:83:a3:35:44:f4:ad:c3:d0:60:e8:71:8e:6d:c0:
+ 70:9a:16:85:65:7a:82:68:7c:67:ee:57:31:6b:e8:
+ fd:f2:3f:5f:c7:ec:4e:db:e7:8a:98:d6:15:45:13:
+ 14:03:bc:4e:8a:03:48:c2:e4:aa:c5:32:cf:80:82:
+ 45:16:8b:63:37:4b:d5:7a:97
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ Authority Information Access:
+ OCSP - URI:http://localhost:8889
+
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 4E:0B:28:05:B5:07:8F:77:1E:A6:37:CB:CC:F0:CB:09:A4:8C:4A:1E
+ X509v3 Authority Key Identifier:
+ keyid:EF:BD:C8:8E:78:79:F9:76:4B:11:59:B6:C3:32:10:07:C0:BC:E3:8A
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 3e:f7:c5:94:58:2f:18:c9:11:29:29:28:33:bb:e7:6c:70:7c:
+ f8:c7:60:4a:e5:37:f2:bb:78:d9:52:1e:c2:a3:dd:b1:7f:da:
+ e1:8a:8b:9c:7e:d6:ee:ec:ef:94:37:b5:b8:97:26:92:01:56:
+ 78:15:44:4b:95:4d:d9:59:12:b0:89:86:e4:b5:7d:b4:73:0f:
+ f1:0d:a8:04:69:e4:3f:2a:6a:65:b9:0e:9a:06:f7:16:29:94:
+ 4d:ac:64:ab:e9:0f:06:3c:74:fe:4c:e1:71:98:bd:9f:bb:c1:
+ 2d:47:70:6a:3c:b3:76:0b:fc:c8:05:d6:4e:bf:33:9f:dd:58:
+ 74:9c
+-----BEGIN CERTIFICATE-----
+MIIC0jCCAjugAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA4MB4XDTA5
+MTEyMDE1NDIxMloXDTM0MTExNDE1NDIxMlowbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgODCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtqo07DHlmqr+kDEf5YOQy5qeFc27NRv8
+PIvZPSne9Ac/TAabT9shokuHi/20YTHeNGwUEPmneuAK6b+zg6M1RPStw9Bg6HGO
+bcBwmhaFZXqCaHxn7lcxa+j98j9fx+xO2+eKmNYVRRMUA7xOigNIwuSqxTLPgIJF
+FotjN0vVepcCAwEAAaOBgzCBgDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG
+FWh0dHA6Ly9sb2NhbGhvc3Q6ODg4OTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFE4L
+KAW1B493HqY3y8zwywmkjEoeMB8GA1UdIwQYMBaAFO+9yI54efl2SxFZtsMyEAfA
+vOOKMA0GCSqGSIb3DQEBBQUAA4GBAD73xZRYLxjJESkpKDO752xwfPjHYErlN/K7
+eNlSHsKj3bF/2uGKi5x+1u7s75Q3tbiXJpIBVngVREuVTdlZErCJhuS1fbRzD/EN
+qARp5D8qamW5DpoG9xYplE2sZKvpDwY8dP5M4XGYvZ+7wS1HcGo8s3YL/MgF1k6/
+M5/dWHSc
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1001.pem
new file mode 100644
index 000000000..51102e24a
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1001.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 8
+ Validity
+ Not Before: Nov 20 15:47:16 2009 GMT
+ Not After : Nov 14 15:47:16 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 1 Root 8
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:a1:55:67:7e:e5:7a:62:eb:2b:36:45:fa:1d:4d:
+ c7:0e:6d:db:f6:54:65:4d:55:39:14:ea:c1:ad:75:
+ 1b:2f:2f:3c:6e:67:e0:6d:c6:76:66:0c:11:a2:89:
+ fe:70:3b:24:3e:0d:2a:13:9f:86:b4:8a:a3:27:50:
+ 52:77:1f:b8:7b:85:4e:36:94:68:4f:23:2c:f6:a1:
+ 0f:01:bc:6d:d4:e9:a4:54:12:15:37:bd:6c:ba:ad:
+ ed:78:ed:00:cc:be:a9:20:99:f5:a5:db:96:ba:cb:
+ 89:6b:ff:30:36:5c:84:77:a8:0d:28:d3:f8:20:99:
+ 01:4d:0f:8e:b3:8e:de:8d:09
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ Authority Information Access:
+ OCSP - URI:http://localhost:8889
+
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ FC:DC:A7:1C:CE:D2:A9:DA:9A:76:9D:AE:8F:C8:1E:56:BA:D2:D5:D5
+ X509v3 Authority Key Identifier:
+ keyid:EF:BD:C8:8E:78:79:F9:76:4B:11:59:B6:C3:32:10:07:C0:BC:E3:8A
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 87:30:ed:08:e6:03:fa:cf:65:5a:ed:9e:83:db:64:5f:bb:6b:
+ 5c:f3:db:8d:b7:d0:95:35:8c:f6:c1:1c:2c:d9:0c:0a:41:27:
+ f9:1f:e4:aa:25:95:59:3c:45:85:ac:0f:02:42:92:67:e2:09:
+ 45:d3:c1:7b:6e:db:42:84:7b:0d:57:47:f5:07:38:dd:cf:38:
+ ac:29:b9:14:79:2e:04:a5:a0:d6:71:be:fa:6d:9e:b5:cd:89:
+ 99:d1:47:58:56:81:8c:d4:b0:96:c6:dc:a7:1b:b0:ef:6b:0c:
+ 25:5f:92:b8:01:b7:74:f0:e3:49:eb:30:29:9f:f3:b5:bd:ae:
+ 45:99
+-----BEGIN CERTIFICATE-----
+MIIC0jCCAjugAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA4MB4XDTA5
+MTEyMDE1NDcxNloXDTM0MTExNDE1NDcxNlowbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAxIFJvb3QgODCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAoVVnfuV6YusrNkX6HU3HDm3b9lRlTVU5
+FOrBrXUbLy88bmfgbcZ2ZgwRoon+cDskPg0qE5+GtIqjJ1BSdx+4e4VONpRoTyMs
+9qEPAbxt1OmkVBIVN71suq3teO0AzL6pIJn1pduWusuJa/8wNlyEd6gNKNP4IJkB
+TQ+Os47ejQkCAwEAAaOBgzCBgDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG
+FWh0dHA6Ly9sb2NhbGhvc3Q6ODg4OTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFPzc
+pxzO0qnamnadro/IHla60tXVMB8GA1UdIwQYMBaAFO+9yI54efl2SxFZtsMyEAfA
+vOOKMA0GCSqGSIb3DQEBBQUAA4GBAIcw7QjmA/rPZVrtnoPbZF+7a1zz24230JU1
+jPbBHCzZDApBJ/kf5KollVk8RYWsDwJCkmfiCUXTwXtu20KEew1XR/UHON3POKwp
+uRR5LgSloNZxvvptnrXNiZnRR1hWgYzUsJbG3KcbsO9rDCVfkrgBt3Tw40nrMCmf
+87W9rkWZ
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/private/cakey.pem
new file mode 100644
index 000000000..6c934e3ec
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,D40C0B2149B20A3E
+
+u5VzDci4c2i/pIElAbIAVT81F72A2V3fpvZv8yUpQRai5ZPzciSc4oYgavdu3tLV
+p8bS+60akNpr3/ti7sB4tQBcql/3FMdKLFCgflJgCH9ivr2UrUSIJOyu9UNoG2ym
+UcJrvCSAqtksL11VLMb3SJO7TRYxJ/xOl69Auf0R+aRwdof9nSBO4jDPTqvR/X8L
+j/plBnw7ENO0ravRnEEEAEiSgx/z0LkhzAsPTkrrkNN5eZ+kR2Sk/Uo5aTx3FTpB
+RU+iZQxmbNTrxCErfYvSnMJ4w6soT+Bzezwfn2tVGLwbur/3gtuNMEHJpL0Y2st9
+aRBHHF6+DlJ30rqNWCVV5ZY+2wMUEPBtcRftLdmh3caw/9aN/NqVUGuvqmhWyTt7
+TJmnKLJhE9NSztQM2PuV7ka9jWp5D6KLv0g+cbedpEOw6VjYL5e1EKt0AOu4Pp2r
+HerL1ouRmpzIQLpskFTwkccjVDQm/H2fnB/nVrjdWxi/U4QJ0EPHL8iCyyox5np+
+3HilWBkpyBSvMOhyGfPkUucsMZA6O7/XhDcciBSsCJ4SSMa5gQmfYfixQHKRwixS
+O5sJADUnJkbo4hyvrptAolM/JJU+HN8IYnq541mJ72dXbyodheedRPIOpTCiLQam
+1Y04wfuIFMN4w98O0oMpCbqcDsOHysxN1XYg2kMzlxYbwooFC5cud5+cEW6d9FWQ
+kpZ8Wkigno3ytjpUXWb9TmsRcMNiQdgxlpkvN/eYhk4xsUpwzhA/M/HTkLkn8WtC
+52EwCv9KcxF31AA0lOeI+oNfcyMruwNXwEkFn3eD36axZQ8QjPHfhw==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/serial
new file mode 100644
index 000000000..7d802a3e7
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/serial
@@ -0,0 +1 @@
+1002
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/openssl.cfg
new file mode 100644
index 000000000..571237e7d
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+authorityInfoAccess = OCSP;URI:http://localhost:8889
+#crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+#nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/cacert.pem
new file mode 100644
index 000000000..0b38d4db4
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/cacert.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 9
+ Validity
+ Not Before: Nov 23 13:59:19 2009 GMT
+ Not After : Nov 17 13:59:19 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 9
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:a9:6d:7f:6a:08:fb:e2:3a:5e:83:3f:ff:58:ba:
+ 92:a1:79:9d:ce:d2:0c:16:15:f2:7e:b3:e4:45:9c:
+ 02:32:65:9b:02:90:78:05:95:e4:04:1d:4a:05:bb:
+ ea:f6:ac:ab:15:74:c2:bc:ee:2a:c1:80:55:3e:93:
+ 1f:5c:94:eb:cf:cf:8f:15:eb:b8:22:fe:69:61:51:
+ a9:08:b8:80:bd:48:99:da:85:10:1c:75:97:fd:d3:
+ c3:c4:0b:dd:eb:01:12:5d:ee:62:62:c3:0c:18:ea:
+ ed:76:ff:9b:1c:1f:c7:81:f9:9a:cd:e5:25:89:b2:
+ 13:57:56:f3:27:53:72:76:69
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 7B:D3:57:BF:6A:CB:6C:10:81:91:DA:95:DC:88:4F:A5:D0:DB:D1:46
+ X509v3 Authority Key Identifier:
+ keyid:CD:33:5E:AB:73:23:51:80:B8:03:AD:12:01:0B:C5:5E:8E:55:CA:64
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 9
+ serial:A4:DB:16:0D:4B:8C:D4:A6
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 17:67:b0:21:da:0d:a1:fe:09:62:d0:cf:1d:c0:c8:bd:d4:22:
+ dd:75:ec:04:e2:23:ae:ea:8c:15:fa:73:2e:83:f4:16:eb:c1:
+ e1:87:36:bd:58:d0:64:e0:6e:2c:bc:27:cb:dc:4b:58:01:80:
+ 48:27:53:bb:75:85:a7:19:b8:e2:c0:1f:9f:a2:18:27:82:3f:
+ 25:bf:17:d1:34:32:de:c4:81:9d:8a:39:6f:6b:1f:b6:12:61:
+ 74:78:96:6d:6e:52:23:4a:67:30:78:03:91:b7:89:bf:3c:4a:
+ 36:e3:95:21:38:35:af:05:55:81:05:25:91:78:ca:2f:5d:79:
+ d2:05
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA5MB4XDTA5MTEyMzEzNTkx
+OVoXDTM0MTExNzEzNTkxOVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQCpbX9qCPviOl6DP/9YupKheZ3O0gwWFfJ+s+RFnAIyZZsCkHgFleQE
+HUoFu+r2rKsVdMK87irBgFU+kx9clOvPz48V67gi/mlhUakIuIC9SJnahRAcdZf9
+08PEC93rARJd7mJiwwwY6u12/5scH8eB+ZrN5SWJshNXVvMnU3J2aQIDAQABo4HH
+MIHEMB0GA1UdDgQWBBR701e/astsEIGR2pXciE+l0NvRRjCBkQYDVR0jBIGJMIGG
+gBTNM16rcyNRgLgDrRIBC8VejlXKZKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA5ggkApNsWDUuM1KYwDwYDVR0TAQH/
+BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAXZ7Ah2g2h/gli0M8dwMi91CLddewE
+4iOu6owV+nMug/QW68Hhhza9WNBk4G4svCfL3EtYAYBIJ1O7dYWnGbjiwB+fohgn
+gj8lvxfRNDLexIGdijlvax+2EmF0eJZtblIjSmcweAORt4m/PEo245UhODWvBVWB
+BSWReMovXXnSBQ==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/crlnumber
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/crlnumber
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt
new file mode 100644
index 000000000..8c466eaff
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt
@@ -0,0 +1 @@
+V 341117140202Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 9
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..e3ca26a8a
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/newcerts/1000.pem
@@ -0,0 +1,58 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 9
+ Validity
+ Not Before: Nov 23 14:02:02 2009 GMT
+ Not After : Nov 17 14:02:02 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 9
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:f2:d3:15:3c:73:42:ce:22:e4:40:3a:6b:02:f6:
+ 59:bd:66:0d:87:91:f4:c0:be:a9:ce:33:21:09:d9:
+ 4e:4b:03:51:87:c3:e9:75:91:e9:80:5e:fc:a1:f7:
+ 43:9b:c6:32:af:6d:77:4b:b6:dc:b1:08:a3:1f:a0:
+ 6d:ec:81:12:23:48:36:2d:7a:5a:d0:88:88:49:7c:
+ ce:ae:98:45:d8:ff:9f:15:72:ab:b4:85:f6:a5:23:
+ af:43:e4:64:45:da:20:e1:e0:3e:f2:87:ea:67:ea:
+ 0e:08:8a:c8:1c:ef:85:a5:e6:f3:54:68:02:fd:de:
+ bc:4d:a2:eb:7d:0d:7d:80:59
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 1B:56:DD:11:CE:38:A0:97:FF:BE:39:9C:AF:F4:60:82:3A:CA:5D:51
+ X509v3 Authority Key Identifier:
+ keyid:7B:D3:57:BF:6A:CB:6C:10:81:91:DA:95:DC:88:4F:A5:D0:DB:D1:46
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 54:5e:40:1d:83:35:67:23:01:28:35:e3:02:7f:9e:9f:ce:83:
+ fb:45:dd:5c:96:62:f5:28:45:c8:90:2a:7e:84:88:e9:e9:b7:
+ 21:17:e0:3b:ea:de:6d:a1:d5:37:90:ae:15:86:30:7f:82:81:
+ d1:bb:ca:d2:6c:7c:39:2e:e9:65:57:2b:74:47:04:49:99:74:
+ 63:c7:03:cc:7d:f4:b0:6e:92:75:bb:aa:28:dc:71:d3:95:73:
+ 15:f4:4f:38:43:9e:4f:9f:e3:97:5c:8d:dc:1e:ad:ad:1e:b7:
+ c2:b2:ca:87:ee:8e:a2:93:12:60:95:1a:fb:bf:42:c8:31:48:
+ 8a:43
+-----BEGIN CERTIFICATE-----
+MIICnTCCAgagAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA5MB4XDTA5
+MTEyMzE0MDIwMloXDTM0MTExNzE0MDIwMlowbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgOTCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA8tMVPHNCziLkQDprAvZZvWYNh5H0wL6p
+zjMhCdlOSwNRh8PpdZHpgF78ofdDm8Yyr213S7bcsQijH6Bt7IESI0g2LXpa0IiI
+SXzOrphF2P+fFXKrtIX2pSOvQ+RkRdog4eA+8ofqZ+oOCIrIHO+FpebzVGgC/d68
+TaLrfQ19gFkCAwEAAaNPME0wCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBQbVt0Rzjig
+l/++OZyv9GCCOspdUTAfBgNVHSMEGDAWgBR701e/astsEIGR2pXciE+l0NvRRjAN
+BgkqhkiG9w0BAQUFAAOBgQBUXkAdgzVnIwEoNeMCf56fzoP7Rd1clmL1KEXIkCp+
+hIjp6bchF+A76t5todU3kK4VhjB/goHRu8rSbHw5LullVyt0RwRJmXRjxwPMffSw
+bpJ1u6oo3HHTlXMV9E84Q55Pn+OXXI3cHq2tHrfCssqH7o6ikxJglRr7v0LIMUiK
+Qw==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/private/cakey.pem
new file mode 100644
index 000000000..be54b542a
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6D4A43A204C02659
+
+ZPB/XY3gNrLz1f2DqTRkoZiL64CjVUEPw6ujRi/cAaMfAB+p32O/obtFbMyZWfpv
+aLaoPmQH5hagNgsQqOW6OrSguxQ9i64Wv795TzRBrSYRHJ1as73AfDcS9aeI61AM
+kiweFkVFAOPfgKOczYO152uXxtdRm4kpVr/CMsYuViE7966dzFvjDlY4vTDAD32+
+KJemzfjwsyErT/nYJaaabEkxxn+O3nwhgVqueoYWI8VeLYotFU41wO1NrOQvshs0
+tyrs5meiuSNPVuKagTltWfHv9PlMyVne7XYiRv1k7CIPmEansBge9/lY5KoPLHGQ
+CHjuuwPykf6jnW7QG9IAGKRNPSdlMBpOT97EvKgNZ9I0FB4lSumhrxkjPHrRKz/J
+usV+mEcGGYrfAb2OT0B/YSddOk1rCtKXpRVUMF8dzD7AyVxnU0Sdub6lwjNojAGh
+Nb8exIFnVBM0/ka19xvlcdY0q9du7e0MuVvy8NhE0vkoqqDrUUnCP8iqg+uRBVts
+0P7yk1lucsrNw8JQveLuiHm6zxN91iUAsBguwoOHG6szp3X9GLvvGhpQWPxTIOyo
+obPMw6lY0y9MHY6eW9ekXVWGMZL2GDpIKLq9kqzLTqhY9kDw9OXYio4UYLl9vQG4
+Akr4ogzm8SKNQkPnGHprCdQV5J4V7fOa4HTNJb6NlTvMFuC99Sst+PYdE4RAn3sT
+Jn+Lj2g0fDDSjvLNohmrT08DAYAAinbNt/+6gI975syPxuqxggrgfis4cliI7pf8
+ecmKIoSlbsJVCSfgd5a/d7e+9KwNuqBqopLu2vfgUN1YiFlEwAEQaQ==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/serial
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/serial
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/openssl.cfg
new file mode 100644
index 000000000..4a5b97f53
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8889
+#crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+#nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/README.txt
new file mode 100644
index 000000000..e020f03a5
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/README.txt
@@ -0,0 +1,4 @@
+Revoked certificates:
+
+- User 2 Sub CA 2 Root 4
+
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/cacert.pem
new file mode 100644
index 000000000..9d951ee26
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/cacert.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 4
+ Validity
+ Not Before: Nov 20 09:22:27 2009 GMT
+ Not After : Nov 14 09:22:27 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 4
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:e5:8d:27:4e:09:53:08:61:c6:23:25:9e:dd:9c:
+ 07:bf:81:38:5c:5c:10:8f:e4:12:2f:4e:2e:b1:a1:
+ cf:21:46:53:bf:e8:5e:de:17:3a:9d:f7:e8:ef:3e:
+ 9c:b4:29:37:4c:31:35:15:dc:98:e0:93:9c:ce:6a:
+ d6:e1:35:19:6b:d4:1d:3b:81:86:b1:e7:ff:1f:b8:
+ 34:a9:f9:de:4d:b8:62:ac:3b:d4:58:8e:5c:76:b5:
+ 07:7f:32:8a:3a:90:73:71:d5:da:f1:79:39:14:ed:
+ 1b:f1:8a:3e:be:48:bc:07:ec:f9:7c:03:14:fc:e7:
+ 55:a3:65:81:c7:6c:70:0b:ff
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 69:DE:B6:99:C4:95:F7:5A:FA:41:6B:4C:F6:C3:6D:89:AA:37:31:9D
+ X509v3 Authority Key Identifier:
+ keyid:BA:8D:A1:97:DC:C4:39:1F:90:B5:51:6B:10:19:F2:46:0D:A9:65:8E
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 4
+ serial:A2:93:46:74:3B:A6:E3:AD
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ bc:cf:43:eb:72:b1:71:a7:94:8e:cd:5b:fc:d8:21:31:83:db:
+ a9:de:c7:5b:14:e5:7b:90:43:e6:05:df:db:6e:95:5f:24:ac:
+ 0c:a1:8a:ac:c6:cf:f2:03:cd:a0:30:ae:d3:a9:41:07:c9:b1:
+ be:4b:e0:fc:a2:76:09:07:75:6a:fa:e4:2f:a3:3a:cd:81:68:
+ ab:f6:06:c4:32:08:25:6e:e8:e7:36:9c:1a:f7:42:73:f8:b0:
+ d8:42:3e:85:c2:11:23:10:d6:6a:e4:8f:53:cb:8b:8b:1b:5a:
+ 4d:6d:9d:34:45:26:52:d2:ee:6d:8f:23:ff:00:92:f5:99:62:
+ 4c:41
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAm+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0MB4XDTA5MTEyMDA5MjIy
+N1oXDTM0MTExNDA5MjIyN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA0MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDljSdOCVMIYcYjJZ7dnAe/gThcXBCP5BIvTi6xoc8hRlO/6F7eFzqd
+9+jvPpy0KTdMMTUV3Jjgk5zOatbhNRlr1B07gYax5/8fuDSp+d5NuGKsO9RYjlx2
+tQd/Moo6kHNx1drxeTkU7Rvxij6+SLwH7Pl8AxT851WjZYHHbHAL/wIDAQABo4HH
+MIHEMB0GA1UdDgQWBBRp3raZxJX3WvpBa0z2w22JqjcxnTCBkQYDVR0jBIGJMIGG
+gBS6jaGX3MQ5H5C1UWsQGfJGDalljqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0ggkAopNGdDum460wDwYDVR0TAQH/
+BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQC8z0PrcrFxp5SOzVv82CExg9up3sdb
+FOV7kEPmBd/bbpVfJKwMoYqsxs/yA82gMK7TqUEHybG+S+D8onYJB3Vq+uQvozrN
+gWir9gbEMgglbujnNpwa90Jz+LDYQj6FwhEjENZq5I9Ty4uLG1pNbZ00RSZS0u5t
+jyP/AJL1mWJMQQ==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/crlnumber
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/crlnumber
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt
new file mode 100644
index 000000000..554a773b4
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt
@@ -0,0 +1,2 @@
+V 341114093339Z 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 2 Root 4
+R 341114095105Z 091120095246Z,keyCompromise 1002 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 2 Root 4
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1001.pem
new file mode 100644
index 000000000..3fbf2133f
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1001.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 4
+ Validity
+ Not Before: Nov 20 09:33:39 2009 GMT
+ Not After : Nov 14 09:33:39 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 2 Root 4
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:c6:b2:8e:e4:f1:67:0b:07:3c:8c:b8:78:d9:79:
+ b1:2e:d5:10:c5:e8:76:9a:25:3f:dd:a3:0b:e0:3f:
+ 9f:50:87:e9:f1:15:74:86:ce:a0:01:07:b2:37:d0:
+ 74:dc:96:69:b4:f1:0e:cd:15:37:ca:ba:ed:ea:a3:
+ 99:ec:43:d4:ac:1c:8b:9b:18:d0:cd:80:78:49:80:
+ ca:e3:85:c6:2d:9a:15:02:73:d3:97:08:1d:4b:68:
+ 95:52:e6:92:57:c7:f6:76:0c:f1:a7:3d:90:10:0c:
+ 35:a8:9c:d3:e4:10:30:20:04:7f:ea:ad:ef:39:0c:
+ 65:05:43:f4:b6:51:3a:e7:95
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 79:C2:63:88:76:DF:C6:6F:BD:1D:AF:57:6E:87:08:AC:55:5D:AD:D1
+ X509v3 Authority Key Identifier:
+ keyid:69:DE:B6:99:C4:95:F7:5A:FA:41:6B:4C:F6:C3:6D:89:AA:37:31:9D
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 07:68:5f:e9:01:bc:e4:d7:78:16:2b:19:7f:c2:9d:15:74:91:
+ ea:6d:fb:c9:ee:29:07:ff:62:e2:6a:85:5e:85:7d:5f:b4:bc:
+ 48:e1:89:24:3e:03:21:42:c1:10:3f:c6:41:7e:04:30:86:db:
+ c5:7e:7e:9f:04:49:a0:1e:fc:93:8e:b3:d1:cf:39:e3:41:89:
+ c3:06:51:3f:15:d5:02:49:2a:0b:15:d1:25:30:12:b6:2a:f9:
+ 03:06:f1:03:84:ae:4e:86:e1:dc:e6:a3:36:a4:27:24:2b:db:
+ 3a:3c:15:48:6f:c7:9f:ce:38:34:06:94:e3:d3:64:f7:4d:9e:
+ b6:c0
+-----BEGIN CERTIFICATE-----
+MIICyzCCAjSgAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA0MB4XDTA5
+MTEyMDA5MzMzOVoXDTM0MTExNDA5MzMzOVowbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAyIFJvb3QgNDCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxrKO5PFnCwc8jLh42XmxLtUQxeh2miU/
+3aML4D+fUIfp8RV0hs6gAQeyN9B03JZptPEOzRU3yrrt6qOZ7EPUrByLmxjQzYB4
+SYDK44XGLZoVAnPTlwgdS2iVUuaSV8f2dgzxpz2QEAw1qJzT5BAwIAR/6q3vOQxl
+BUP0tlE655UCAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P
+cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUecJjiHbfxm+9
+Ha9XbocIrFVdrdEwHwYDVR0jBBgwFoAUad62mcSV91r6QWtM9sNtiao3MZ0wDQYJ
+KoZIhvcNAQEFBQADgYEAB2hf6QG85Nd4FisZf8KdFXSR6m37ye4pB/9i4mqFXoV9
+X7S8SOGJJD4DIULBED/GQX4EMIbbxX5+nwRJoB78k46z0c8540GJwwZRPxXVAkkq
+CxXRJTAStir5AwbxA4SuTobh3OajNqQnJCvbOjwVSG/Hn844NAaU49Nk902etsA=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1002.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1002.pem
new file mode 100644
index 000000000..595fbbfaf
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1002.pem
@@ -0,0 +1,60 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4098 (0x1002)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 4
+ Validity
+ Not Before: Nov 20 09:51:05 2009 GMT
+ Not After : Nov 14 09:51:05 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 2 Root 4
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:f5:2d:4a:b8:5d:39:da:58:5c:3c:a5:7d:4c:98:
+ b8:32:db:43:a0:13:cb:25:f8:5b:0b:6a:f2:e0:8d:
+ de:8f:c6:ea:c5:1c:03:bf:e0:b1:c9:14:a4:85:4b:
+ ed:95:87:f7:88:88:86:9e:65:3d:6e:e8:c5:be:17:
+ e6:9b:09:8e:44:c1:0a:20:00:ae:b4:3d:ba:68:9f:
+ 3e:ea:76:3c:96:64:ee:a7:91:65:31:03:f5:fd:01:
+ e5:60:a0:5e:62:a0:37:7b:db:cf:71:78:58:cc:dd:
+ 74:fc:b3:b1:2e:6b:f3:ec:ad:ac:75:ae:d8:d6:42:
+ 28:0a:20:68:8d:20:4a:30:61
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 32:E4:11:DF:CD:54:D6:80:67:68:85:36:A0:C5:14:88:D6:85:DB:C9
+ X509v3 Authority Key Identifier:
+ keyid:69:DE:B6:99:C4:95:F7:5A:FA:41:6B:4C:F6:C3:6D:89:AA:37:31:9D
+
+ Signature Algorithm: sha1WithRSAEncryption
+ e1:c2:5d:63:42:27:f4:df:a2:f0:f5:61:c3:e3:ac:f7:b6:29:
+ a9:dd:34:63:0c:cc:c9:7b:5c:1b:ac:77:8f:1a:e1:f4:3b:c8:
+ 96:8a:89:f6:c0:f0:c4:3b:bd:6e:b7:e7:84:5c:38:4f:d3:66:
+ 55:d6:d3:f8:70:1f:14:ce:9f:d3:04:68:be:6b:81:fc:6c:b6:
+ 2f:31:3d:de:2a:4e:6c:66:c0:c2:09:c8:ef:be:c4:88:39:28:
+ e8:62:da:44:63:f4:5c:f4:bb:cf:4b:54:c9:c0:ce:b4:27:7b:
+ 1e:9c:2f:90:9e:18:da:8a:27:af:e5:37:ea:3f:99:86:f8:5d:
+ d1:cb
+-----BEGIN CERTIFICATE-----
+MIICyzCCAjSgAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA0MB4XDTA5
+MTEyMDA5NTEwNVoXDTM0MTExNDA5NTEwNVowbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAyIFJvb3QgNDCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA9S1KuF052lhcPKV9TJi4MttDoBPLJfhb
+C2ry4I3ej8bqxRwDv+CxyRSkhUvtlYf3iIiGnmU9bujFvhfmmwmORMEKIACutD26
+aJ8+6nY8lmTup5FlMQP1/QHlYKBeYqA3e9vPcXhYzN10/LOxLmvz7K2sda7Y1kIo
+CiBojSBKMGECAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P
+cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUMuQR381U1oBn
+aIU2oMUUiNaF28kwHwYDVR0jBBgwFoAUad62mcSV91r6QWtM9sNtiao3MZ0wDQYJ
+KoZIhvcNAQEFBQADgYEA4cJdY0In9N+i8PVhw+Os97Ypqd00YwzMyXtcG6x3jxrh
+9DvIloqJ9sDwxDu9brfnhFw4T9NmVdbT+HAfFM6f0wRovmuB/Gy2LzE93ipObGbA
+wgnI777EiDko6GLaRGP0XPS7z0tUycDOtCd7HpwvkJ4Y2oonr+U36j+Zhvhd0cs=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/private/cakey.pem
new file mode 100644
index 000000000..a8f9640c8
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1BD121CFCC6764E4
+
+k3SMhf7UEWvpfhEyvd7Zc6kJFmiZ1JTg7KAawQhFhoRbGIVA1rSmRbuBdJm4XdQ5
+OxEAC5bVx5o3yxyhGmEkZr1dkGXkzQ1tc2a4Exf2p0O5zjlHUaxd2A4/mRYVAT0e
+LAIQ+D+yqSd2wmLkLaz3EGGlfIPS8amTpnhSOvai40NjbLlRpw5DqDP/2KVWp7jH
+T4JNzU33Xd6QuBsTSWyXuhIEeuzyrDbou0LceHIZSaa8Jqvp3yKX6OBTUdCNakwR
+QtLLag63ie87qEhqeHg2VvZuVVEyhNCjPf2zRfxsCx742wI4TyY28JpxjYlFzJxX
+Zd9toqIGFwritEOcr6wAqVX7NlE8/dDFFdEK9fPuv/jLoOYCCwDRvIMgDTE76c1k
+foRMDMmqe0KcMdp+fbcfNDnV/U8gle2902AbEOXJLhdDEVUG/LCwrnIeUrfMOKiY
+LwPysGwVndUb3uTFJ2e+PqV9i96G+ewpN9/hI9fThE12t8rhkpIsozEMl7WsBMgD
+tdKrA5l7eibshCpk+zkIwGhkdMYXhj7hmioWWBJeMdJ93Ba8f91kt1IvI+J2Mn2K
+1/5D0ZKEGPoTSAlEgMZ888sYWkT6WMk0UXH2Nq8BqdrrSTUypY2Uz0nDbWvhLrCf
+zac6RZu9TtFsKAY6CQnXHFUJ+dvRmcSNQMhrIKS2VZ2UkL2oXASzXW2c9Hx6LO7T
+WHuR7bXZiJhI63gUGI9pMRCs5NoRuXdg3KutzSTy8EWKJDXDKcvTemiomUZFB6i5
+zduXL73Wf/VjMcs7iOAijd7czGre0LBwyvgeNUAK2gj7SaGkR3bPZg==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/serial
new file mode 100644
index 000000000..baccd0398
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/serial
@@ -0,0 +1 @@
+1003
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/openssl.cfg
new file mode 100644
index 000000000..51e520525
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/README.txt
new file mode 100644
index 000000000..e04f69532
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/README.txt
@@ -0,0 +1,12 @@
+Revoked certificates:
+
+- User 2 Sub 2 Root 7
+
+
+To provide the CRL via HTTP run
+
+java -jar ../../tools/httpserv/dist/httpserv.jar -a 8902
+
+
+
+
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/cacert.pem
new file mode 100644
index 000000000..0d2a0f02a
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/cacert.pem
@@ -0,0 +1,66 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 7
+ Validity
+ Not Before: Nov 20 13:35:06 2009 GMT
+ Not After : Nov 14 13:35:06 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 7
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:f9:3f:5e:76:52:9a:ce:5d:98:b0:00:d8:e0:65:
+ e7:78:11:4c:7b:c7:e2:d3:44:bf:8e:60:42:69:3e:
+ 75:67:65:24:ab:f7:07:d8:9d:be:0f:23:b5:c1:26:
+ 00:6b:c3:22:84:72:a9:96:dc:5f:63:fc:f5:e0:e3:
+ cc:da:0c:74:e9:31:51:91:89:27:8f:e5:17:41:6e:
+ 3d:5e:2a:13:cd:08:f7:f3:61:34:a1:f7:79:c6:bd:
+ 5d:2c:34:01:ea:5a:8c:48:97:36:d6:57:e0:80:03:
+ 2e:7a:03:83:4c:bd:b4:af:a2:fd:d7:4b:1a:f7:ab:
+ 9f:5a:22:2b:d1:25:73:dd:6f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 3B:50:26:45:6C:E2:FE:28:B1:71:0A:A8:95:2D:78:63:8E:2C:48:92
+ X509v3 Authority Key Identifier:
+ keyid:80:C6:F8:0B:5F:7C:49:E4:86:FD:C8:92:C6:80:70:D9:C0:6F:7B:DE
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 7
+ serial:D5:E6:63:5F:18:09:82:89
+
+ X509v3 CRL Distribution Points:
+ URI:http://localhost:8901/demoCA/crl/Root_7.crl
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 5f:b4:70:11:4f:d9:df:6a:6a:5a:4a:97:fe:8b:5d:9e:46:84:
+ e2:27:67:41:7c:a9:2e:9d:77:cc:e4:8c:d6:16:3c:39:7d:51:
+ 29:60:80:32:4f:a1:d0:b4:7f:2a:e5:60:f4:b8:d3:3b:94:f8:
+ a5:fb:15:99:cf:a9:c5:a7:59:c1:11:89:67:11:9c:ff:a9:ac:
+ dd:ca:a9:92:a8:60:26:c3:ab:74:41:86:b9:4d:1e:4a:c5:de:
+ 63:e6:da:2a:36:39:7b:6c:66:f3:20:57:d1:f1:36:4b:69:c5:
+ 04:a3:1f:cf:de:0c:10:d0:3f:07:e2:8e:0f:cd:41:26:c9:2e:
+ e9:1b
+-----BEGIN CERTIFICATE-----
+MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA3MB4XDTA5MTEyMDEzMzUw
+NloXDTM0MTExNDEzMzUwNlowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA3MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQD5P152UprOXZiwANjgZed4EUx7x+LTRL+OYEJpPnVnZSSr9wfYnb4P
+I7XBJgBrwyKEcqmW3F9j/PXg48zaDHTpMVGRiSeP5RdBbj1eKhPNCPfzYTSh93nG
+vV0sNAHqWoxIlzbWV+CAAy56A4NMvbSvov3XSxr3q59aIivRJXPdbwIDAQABo4IB
+BjCCAQIwHQYDVR0OBBYEFDtQJkVs4v4osXEKqJUteGOOLEiSMIGRBgNVHSMEgYkw
+gYaAFIDG+AtffEnkhv3IksaAcNnAb3veoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G
+A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT
+C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDeCCQDV5mNfGAmCiTA8BgNVHR8E
+NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290
+XzcuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAX7RwEU/Z
+32pqWkqX/otdnkaE4idnQXypLp13zOSM1hY8OX1RKWCAMk+h0LR/KuVg9LjTO5T4
+pfsVmc+pxadZwRGJZxGc/6ms3cqpkqhgJsOrdEGGuU0eSsXeY+baKjY5e2xm8yBX
+0fE2S2nFBKMfz94MENA/B+KOD81BJsku6Rs=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/Sub_CA_2_Root_7.crl b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/Sub_CA_2_Root_7.crl
new file mode 100644
index 000000000..c4dd13d83
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/Sub_CA_2_Root_7.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crlnumber
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crlnumber
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt
new file mode 100644
index 000000000..a5e282ddd
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt
@@ -0,0 +1,2 @@
+V 341114134608Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 2 Root 7
+R 341114135230Z 091120135413Z,CACompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 2 Root 7
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1000.pem
new file mode 100644
index 000000000..ff1f1fa66
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1000.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4096 (0x1000)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 7
+ Validity
+ Not Before: Nov 20 13:46:08 2009 GMT
+ Not After : Nov 14 13:46:08 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 2 Root 7
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:a7:6b:af:a2:6e:61:33:2e:71:7b:e2:38:44:d9:
+ 4c:da:6e:86:bb:c6:f5:64:8e:2e:8b:e8:71:c8:46:
+ ad:c5:46:05:d2:06:a6:89:e2:ce:1f:1c:a7:4c:94:
+ a4:24:56:93:07:b1:c4:52:44:69:27:0b:34:eb:31:
+ 20:71:63:5c:0a:33:aa:0c:39:71:ac:08:49:c3:66:
+ ac:cb:e3:a8:66:ab:5c:a2:00:7a:bb:24:e6:93:91:
+ 1e:0e:7c:83:9e:f2:10:87:3f:0e:c0:f6:e5:bf:2c:
+ d3:cc:17:4c:d5:9a:96:35:4b:4e:ca:72:3a:9b:90:
+ c8:4c:24:04:2f:51:99:20:95
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 CRL Distribution Points:
+ URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl
+
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 27:98:7E:F6:AD:82:6D:F4:7A:32:AE:F1:54:D1:07:AE:08:0E:0E:2B
+ X509v3 Authority Key Identifier:
+ keyid:3B:50:26:45:6C:E2:FE:28:B1:71:0A:A8:95:2D:78:63:8E:2C:48:92
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 06:7d:0a:e8:fa:8b:87:1d:75:61:2b:c7:d1:6d:56:5f:26:e3:
+ 29:b4:c3:27:05:35:0f:b7:c1:20:42:95:0b:9d:34:16:5d:9b:
+ c2:48:c8:67:e1:e7:43:eb:10:9e:45:3e:44:da:7c:4b:19:05:
+ 00:66:91:83:ea:82:86:48:e8:87:ea:a0:9f:c9:1d:f8:af:13:
+ fd:2e:4e:50:7e:a0:d2:b0:5e:a4:6f:dd:e6:c8:11:60:bc:41:
+ e5:b6:01:4c:7a:af:32:f6:cc:5b:57:e6:e4:87:21:ec:17:98:
+ 67:eb:4d:2f:07:db:8f:70:e2:f3:77:8f:c7:ff:60:d6:d9:f7:
+ 82:e3
+-----BEGIN CERTIFICATE-----
+MIIC5jCCAk+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA3MB4XDTA5
+MTEyMDEzNDYwOFoXDTM0MTExNDEzNDYwOFowbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAyIFJvb3QgNzCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAp2uvom5hMy5xe+I4RNlM2m6Gu8b1ZI4u
+i+hxyEatxUYF0gamieLOHxynTJSkJFaTB7HEUkRpJws06zEgcWNcCjOqDDlxrAhJ
+w2asy+OoZqtcogB6uyTmk5EeDnyDnvIQhz8OwPblvyzTzBdM1ZqWNUtOynI6m5DI
+TCQEL1GZIJUCAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j
+YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMl9Sb290XzcuY3JsMAsGA1Ud
+DwQEAwIF4DAdBgNVHQ4EFgQUJ5h+9q2CbfR6Mq7xVNEHrggODiswHwYDVR0jBBgw
+FoAUO1AmRWzi/iixcQqolS14Y44sSJIwDQYJKoZIhvcNAQEFBQADgYEABn0K6PqL
+hx11YSvH0W1WXybjKbTDJwU1D7fBIEKVC500Fl2bwkjIZ+HnQ+sQnkU+RNp8SxkF
+AGaRg+qChkjoh+qgn8kd+K8T/S5OUH6g0rBepG/d5sgRYLxB5bYBTHqvMvbMW1fm
+5Ich7BeYZ+tNLwfbj3Di83ePx/9g1tn3guM=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1001.pem
new file mode 100644
index 000000000..f16cdf4aa
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1001.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 7
+ Validity
+ Not Before: Nov 20 13:52:30 2009 GMT
+ Not After : Nov 14 13:52:30 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 2 Root 7
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:d3:1f:7e:28:b6:fd:f0:bb:01:21:88:04:c4:da:
+ 3d:6a:ce:09:8e:04:29:a5:0f:38:db:74:d0:ee:ad:
+ 5c:95:79:16:11:c0:b1:51:69:95:bb:a8:8f:8b:1c:
+ 7b:8c:82:27:16:21:82:82:d7:36:6f:b3:bb:36:a8:
+ ad:69:e2:e3:cd:6f:ef:81:ac:fa:e3:a9:ac:86:b7:
+ 31:1d:75:11:a3:2e:1d:89:0b:9c:5e:03:45:7a:b0:
+ a9:9d:ee:31:f1:15:c1:c5:f6:26:8e:d4:89:72:8f:
+ f4:86:94:d1:49:37:24:56:84:10:db:cc:f2:1d:3e:
+ 58:66:97:b2:17:6f:15:cb:81
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 CRL Distribution Points:
+ URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl
+
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ CD:A2:AE:51:D0:CF:A2:89:3A:53:23:74:1D:69:10:EE:2A:40:3A:22
+ X509v3 Authority Key Identifier:
+ keyid:3B:50:26:45:6C:E2:FE:28:B1:71:0A:A8:95:2D:78:63:8E:2C:48:92
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 40:8a:be:55:1f:d9:0f:96:fd:54:dd:9f:6b:1d:b1:34:ed:b7:
+ 11:6d:72:a9:65:9a:39:bd:79:3b:d3:4e:0c:22:60:39:e8:c0:
+ 2c:34:64:09:2c:0c:aa:f7:f9:9d:f1:d9:b9:04:d6:e2:c4:cb:
+ d5:05:33:75:5e:87:c0:2c:80:06:8b:6e:9c:ad:0c:7f:03:c0:
+ f5:91:e4:3a:64:b9:52:3b:5a:e0:e5:79:32:89:fb:4a:54:68:
+ 9a:e6:72:3e:61:93:a3:2a:67:aa:95:d0:3d:37:33:5c:da:6e:
+ a6:ac:3d:b6:b1:ac:68:f0:8c:8b:6b:96:a5:f7:ed:2d:6e:64:
+ c7:11
+-----BEGIN CERTIFICATE-----
+MIIC5jCCAk+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA3MB4XDTA5
+MTEyMDEzNTIzMFoXDTM0MTExNDEzNTIzMFowbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAyIFJvb3QgNzCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0x9+KLb98LsBIYgExNo9as4JjgQppQ84
+23TQ7q1clXkWEcCxUWmVu6iPixx7jIInFiGCgtc2b7O7NqitaeLjzW/vgaz646ms
+hrcxHXURoy4diQucXgNFerCpne4x8RXBxfYmjtSJco/0hpTRSTckVoQQ28zyHT5Y
+ZpeyF28Vy4ECAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j
+YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMl9Sb290XzcuY3JsMAsGA1Ud
+DwQEAwIF4DAdBgNVHQ4EFgQUzaKuUdDPook6UyN0HWkQ7ipAOiIwHwYDVR0jBBgw
+FoAUO1AmRWzi/iixcQqolS14Y44sSJIwDQYJKoZIhvcNAQEFBQADgYEAQIq+VR/Z
+D5b9VN2fax2xNO23EW1yqWWaOb15O9NODCJgOejALDRkCSwMqvf5nfHZuQTW4sTL
+1QUzdV6HwCyABotunK0MfwPA9ZHkOmS5Ujta4OV5Mon7SlRomuZyPmGToypnqpXQ
+PTczXNpupqw9trGsaPCMi2uWpfftLW5kxxE=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/private/cakey.pem
new file mode 100644
index 000000000..1f95ffa3c
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,70BBA561902B1296
+
++Pbay3A7tcxOMNFXIlyQ6Hpl4QxJJmzZzXT5UOfGZYYRYrFKv1489pqvzLNgp06z
+nWvyILc3AUd4dWnzfkWvPN3fjJazGWXoZaYLfGgdccA0LdXh+TmqVHHxFjOZVFeO
+lYlKqK6dUsybaciOhkYBKPs1ZFAaNtQLZc1/GVAA9jVYnfwNVmW14d5Q8gurZTp8
+qYwQmT9Sjm2j9USIFcD9MDH94gW77PI+XD1hu6PJTF8m7n8eSY9KcWfVmd/Qj9Ly
+nzLRaS6SOKETWL4+fUaN6aDtddKGwFgagyDwlRRuizX18ZSue2qoK73AhLtZ8Gx/
+vgFLTsvcniZus9kzVrRm2dsWvzaVAmOwqN04IqD6bEr+kXq1obP/T+deGsRwR54K
+wEy7NrkkMSGw4AOuxVNSO7NYgU2kXueAfvGU8SQiXuU1S7fdZpWci8T5Dm7FuP9B
+iKsHqUH9GYgAVl+Y3dwa9n+mDaFkn4wxeVHDdL40XJT0LYCMz9PGKRy3JSTiHF//
+j9BHDpIC+E8L9N01cJ74+p0bzLLOhZ7vyjx8umVJbNIAAlDbCrEi4ZFqwGvmdjHF
+2dti2S0ALixAFQybub4s9Cp3QxfaWnYQOvV7A0SGhtHkjycaJwO0cSonQ8yEjJJJ
+PQkIW9SK+xz/yDYMHqa/Yo5t53GkpCTKBo2STSdnXjnABNk3FAusf72POkIPcH99
+5uyje8bo+lS2VB/O/pm8tbf9mW9YEh/xd3VAglWiAMzYSfO1x0rSTpdqJMSDfOhK
+ogim9NdrVwASi0JrE8nCovwO3auOPu+5sRvYstnt18IVNisZZoW/Qg==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/serial
new file mode 100644
index 000000000..7d802a3e7
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/serial
@@ -0,0 +1 @@
+1002
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/openssl.cfg
new file mode 100644
index 000000000..c6acf751f
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+#nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/README.txt
new file mode 100644
index 000000000..645ae6037
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/README.txt
@@ -0,0 +1,13 @@
+Revoked certificates:
+
+- User 2 Sub CA 2 Root 8
+
+
+Start the OCSP responder:
+openssl ocsp -index demoCA/index.txt -port 8889 -rsigner demoCA/cacert.pem -rkey demoCA/private/cakey.pem -CA demoCA/cacert.pem -text
+
+
+
+
+
+
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/cacert.pem
new file mode 100644
index 000000000..26368962e
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/cacert.pem
@@ -0,0 +1,66 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 8
+ Validity
+ Not Before: Nov 20 15:55:33 2009 GMT
+ Not After : Nov 14 15:55:33 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 8
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:e9:91:38:d8:c1:36:e5:c1:d0:32:e8:ae:02:11:
+ 97:e5:c5:07:8f:5b:46:3a:3c:d9:49:5e:9a:4b:51:
+ 4c:b7:7d:e9:d1:4f:a7:15:8c:c6:10:f6:fa:5f:a9:
+ 0b:1b:bc:de:56:f5:ad:a3:a0:40:f1:75:10:58:74:
+ 37:f9:b7:9f:76:ca:46:96:4c:1a:81:f4:a2:ce:88:
+ 8b:9e:00:6d:42:b3:d6:68:d1:67:d6:9f:b8:9c:3f:
+ 43:c7:36:bf:41:88:1b:e8:74:26:a0:51:5c:e2:ee:
+ 6d:9d:73:bb:0d:36:e1:5c:68:9f:21:3b:b2:aa:ed:
+ 39:1d:ae:fc:b4:ca:38:c2:fb
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 1B:AB:6B:0F:42:91:DC:1E:D4:7A:95:87:30:2D:CC:11:4F:35:B7:73
+ X509v3 Authority Key Identifier:
+ keyid:D6:66:76:C9:05:FF:A9:50:88:96:60:DD:FB:C7:30:18:72:67:41:19
+ DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 8
+ serial:B2:47:DE:6A:2A:4C:83:19
+
+ Authority Information Access:
+ OCSP - URI:http://localhost:8888
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 89:f8:8d:a8:e5:0b:2a:fb:f3:6a:80:2c:26:a1:a7:36:7e:a0:
+ c5:61:65:9d:7e:d6:47:60:b4:f6:72:e9:6e:2c:d9:f8:7f:c8:
+ 7a:5d:75:98:ad:88:de:e7:1b:44:a3:96:37:84:c0:b3:20:98:
+ 3b:b5:f6:ee:70:9c:04:7a:6c:88:05:75:7f:12:cf:b9:76:e8:
+ c0:17:0c:5e:eb:10:38:1e:54:41:58:56:f6:3c:ec:07:a5:c0:
+ 74:24:34:af:b3:c7:b2:58:85:47:0f:6c:e4:a0:9f:c8:7b:5c:
+ 95:77:17:e5:ad:eb:c3:86:44:f7:81:ef:cb:58:12:1a:6a:c7:
+ 19:95
+-----BEGIN CERTIFICATE-----
+MIIDOTCCAqKgAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4MB4XDTA5MTEyMDE1NTUz
+M1oXDTM0MTExNDE1NTUzM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1
+cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu
+dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA4MIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQDpkTjYwTblwdAy6K4CEZflxQePW0Y6PNlJXppLUUy3fenRT6cVjMYQ
+9vpfqQsbvN5W9a2joEDxdRBYdDf5t592ykaWTBqB9KLOiIueAG1Cs9Zo0WfWn7ic
+P0PHNr9BiBvodCagUVzi7m2dc7sNNuFcaJ8hO7Kq7Tkdrvy0yjjC+wIDAQABo4H6
+MIH3MB0GA1UdDgQWBBQbq2sPQpHcHtR6lYcwLcwRTzW3czCBkQYDVR0jBIGJMIGG
+gBTWZnbJBf+pUIiWYN37xzAYcmdBGaFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4ggkAskfeaipMgxkwMQYIKwYBBQUH
+AQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojg4ODgwDwYDVR0T
+AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCJ+I2o5Qsq+/NqgCwmoac2fqDF
+YWWdftZHYLT2culuLNn4f8h6XXWYrYje5xtEo5Y3hMCzIJg7tfbucJwEemyIBXV/
+Es+5dujAFwxe6xA4HlRBWFb2POwHpcB0JDSvs8eyWIVHD2zkoJ/Ie1yVdxflrevD
+hkT3ge/LWBIaascZlQ==
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/Sub_CA_2_Root_8.crl b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/Sub_CA_2_Root_8.crl
new file mode 100644
index 000000000..f4e88754b
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/Sub_CA_2_Root_8.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crlnumber
new file mode 100644
index 000000000..dd1172404
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crlnumber
@@ -0,0 +1 @@
+1001
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt
new file mode 100644
index 000000000..cdace00f7
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt
@@ -0,0 +1,2 @@
+V 341114161332Z 1002 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 2 Root 8
+R 341114161602Z 091120161700Z,superseded 1003 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 2 Root 8
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt.attr
new file mode 100644
index 000000000..8f7e63a34
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1002.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1002.pem
new file mode 100644
index 000000000..1107a4327
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1002.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4098 (0x1002)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 8
+ Validity
+ Not Before: Nov 20 16:13:32 2009 GMT
+ Not After : Nov 14 16:13:32 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 2 Root 8
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:d2:f6:25:c0:95:4b:07:1e:a0:57:67:52:36:b3:
+ 3e:5d:32:7f:61:25:e9:dd:31:a1:67:6e:02:9f:4f:
+ ca:ff:82:50:64:2e:ed:4e:8d:09:73:48:91:e1:90:
+ ca:df:06:ab:f4:c3:3d:8b:7d:d1:6b:5f:f8:f8:d6:
+ c0:f4:81:59:7c:0e:53:32:a9:cd:e4:34:3c:20:a9:
+ 08:b6:c2:b3:b7:91:d2:db:46:06:09:55:ff:f9:f4:
+ 4e:2a:28:36:46:0e:04:f1:78:7d:a3:ff:ac:08:1b:
+ 21:99:f5:b4:5b:f6:be:fd:1a:89:26:4b:eb:b9:58:
+ fc:c2:5f:44:42:a9:00:76:ff
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ Authority Information Access:
+ OCSP - URI:http://localhost:8889
+
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 9D:91:CD:7F:70:3B:00:C1:2A:FD:2F:5D:64:C4:8F:EB:0E:37:25:1B
+ X509v3 Authority Key Identifier:
+ keyid:1B:AB:6B:0F:42:91:DC:1E:D4:7A:95:87:30:2D:CC:11:4F:35:B7:73
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 2c:68:5e:5b:2e:d7:48:ca:2a:01:b4:a0:99:0e:06:2d:e8:23:
+ b3:66:31:97:cd:9e:73:61:35:af:9d:d9:2f:7c:e6:87:7f:2a:
+ ae:3e:b0:99:c9:20:10:30:e3:a0:5b:28:8b:57:f2:12:3a:87:
+ c1:7a:5e:c8:21:b9:ae:49:c1:aa:4f:1c:9e:a8:ae:0f:ad:a2:
+ 3e:aa:61:94:64:41:f8:d7:19:8d:a1:be:c0:15:04:25:2c:35:
+ 29:af:00:1e:40:7c:e7:d7:41:89:a7:ab:2d:dd:78:dd:c7:ba:
+ d0:1b:7b:68:fa:7e:a4:0f:4c:ab:02:6e:d2:ff:b8:5b:05:f6:
+ 47:29
+-----BEGIN CERTIFICATE-----
+MIIC0jCCAjugAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA4MB4XDTA5
+MTEyMDE2MTMzMloXDTM0MTExNDE2MTMzMlowbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAyIFJvb3QgODCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0vYlwJVLBx6gV2dSNrM+XTJ/YSXp3TGh
+Z24Cn0/K/4JQZC7tTo0Jc0iR4ZDK3war9MM9i33Ra1/4+NbA9IFZfA5TMqnN5DQ8
+IKkItsKzt5HS20YGCVX/+fROKig2Rg4E8Xh9o/+sCBshmfW0W/a+/RqJJkvruVj8
+wl9EQqkAdv8CAwEAAaOBgzCBgDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG
+FWh0dHA6Ly9sb2NhbGhvc3Q6ODg4OTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJ2R
+zX9wOwDBKv0vXWTEj+sONyUbMB8GA1UdIwQYMBaAFBuraw9Ckdwe1HqVhzAtzBFP
+NbdzMA0GCSqGSIb3DQEBBQUAA4GBACxoXlsu10jKKgG0oJkOBi3oI7NmMZfNnnNh
+Na+d2S985od/Kq4+sJnJIBAw46BbKItX8hI6h8F6Xsghua5JwapPHJ6org+toj6q
+YZRkQfjXGY2hvsAVBCUsNSmvAB5AfOfXQYmnqy3deN3HutAbe2j6fqQPTKsCbtL/
+uFsF9kcp
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1003.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1003.pem
new file mode 100644
index 000000000..53268ff52
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1003.pem
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4099 (0x1003)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 8
+ Validity
+ Not Before: Nov 20 16:16:02 2009 GMT
+ Not After : Nov 14 16:16:02 2034 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 2 Root 8
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:b4:58:05:7c:f5:f2:48:af:35:03:82:62:af:d3:
+ ef:50:f0:0b:b1:a9:a1:9b:14:1c:54:a9:71:b4:f6:
+ e0:7d:8a:25:b3:21:e2:53:ab:a5:08:9e:ed:5a:ef:
+ 8b:4f:be:75:40:b0:10:05:eb:08:3b:94:c2:57:37:
+ 51:41:08:57:b9:1c:a5:2f:e9:cc:3c:a8:70:2b:eb:
+ 00:92:43:64:44:18:23:9f:85:5f:7f:a5:c9:30:b3:
+ 14:c0:2b:fc:94:a5:a6:ad:46:a8:37:12:20:ab:cf:
+ e0:02:74:5d:1f:2e:ec:1c:9f:27:1f:83:fc:c4:62:
+ d2:0b:6b:f4:65:21:1d:94:ff
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ Authority Information Access:
+ OCSP - URI:http://localhost:8889
+
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 1E:C7:A3:43:33:6B:EC:90:B5:66:81:64:D6:43:72:45:DB:D9:E4:57
+ X509v3 Authority Key Identifier:
+ keyid:1B:AB:6B:0F:42:91:DC:1E:D4:7A:95:87:30:2D:CC:11:4F:35:B7:73
+
+ Signature Algorithm: sha1WithRSAEncryption
+ a8:66:0d:4b:6a:00:fc:31:e3:f5:8f:49:44:3d:60:26:76:2e:
+ 51:f8:41:35:3b:5b:7f:87:e3:00:d7:ae:85:bb:d9:81:a5:30:
+ db:6a:0a:a0:d2:e8:69:f5:47:d8:19:e5:2a:bd:c5:8e:99:f9:
+ 57:fc:b0:64:f5:43:bc:37:4a:8e:28:70:a4:6d:7d:da:2c:9e:
+ c1:55:8d:00:89:fe:f7:ef:c9:d9:8d:fe:01:3e:83:23:58:c3:
+ 3e:41:09:ab:5c:60:0e:9e:18:69:9e:99:7f:a2:cd:b7:95:5c:
+ ea:31:02:79:32:eb:1a:07:dc:75:98:80:8e:56:f2:0a:8f:0e:
+ cf:4f
+-----BEGIN CERTIFICATE-----
+MIIC0jCCAjugAwIBAgICEAMwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA4MB4XDTA5
+MTEyMDE2MTYwMloXDTM0MTExNDE2MTYwMlowbzELMAkGA1UEBhMCREUxEDAOBgNV
+BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAyIFJvb3QgODCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtFgFfPXySK81A4Jir9PvUPALsamhmxQc
+VKlxtPbgfYolsyHiU6ulCJ7tWu+LT751QLAQBesIO5TCVzdRQQhXuRylL+nMPKhw
+K+sAkkNkRBgjn4Vff6XJMLMUwCv8lKWmrUaoNxIgq8/gAnRdHy7sHJ8nH4P8xGLS
+C2v0ZSEdlP8CAwEAAaOBgzCBgDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG
+FWh0dHA6Ly9sb2NhbGhvc3Q6ODg4OTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFB7H
+o0Mza+yQtWaBZNZDckXb2eRXMB8GA1UdIwQYMBaAFBuraw9Ckdwe1HqVhzAtzBFP
+NbdzMA0GCSqGSIb3DQEBBQUAA4GBAKhmDUtqAPwx4/WPSUQ9YCZ2LlH4QTU7W3+H
+4wDXroW72YGlMNtqCqDS6Gn1R9gZ5Sq9xY6Z+Vf8sGT1Q7w3So4ocKRtfdosnsFV
+jQCJ/vfvydmN/gE+gyNYwz5BCatcYA6eGGmemX+izbeVXOoxAnky6xoH3HWYgI5W
+8gqPDs9P
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/private/cakey.pem
new file mode 100644
index 000000000..e063b9726
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/private/cakey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B84323C471CC815A
+
+UrT9eGAJB4+hzdjcS7YBCJi6jCL9n9/vZC0fC6mjZRK/dw4CxLka0KapKUVd+pj/
+I+XG6JOqa5tmsHcp9OWaWpzyu9W5DJqjodTum6pNlig68GVVSs21u7q0mF5mA6OR
+PmRu+iOe2oZO6kVaRnpdGBnbsUsvlsbayiY3nHjXeDPxyc+XGnIMjT7mBOO360iR
+h6IEOyapRho8klyuOXLy8hHZuUyspm66Nq+czorGdv3nlEdSI4t4LPTcqJGUMiHb
+hLYsCK9Zwu7RQWne3OmGjAspU37TB3F1YrWjnHFIKE6YSvtdYMwXosMbybdUZFwQ
+w4dGUhIxCxWLDF99Qfnygi8HJOC1FiFcJslVem0Xi3M654sshGLCiA4jMjdUAEmL
+R+rzjUNZEHqvO/bGm7zsEoLWQFWEYqQZguwxDScam9Sii/fcnEBcSERbEi3yjvlX
+7L3q4j/7/PlpYuRVB+f21ZuoI8R6M+omwF1ZzuSQNMSvUMyhAgQ+yB/pFJbArU68
+4l7ks0wNcSlLyGzjsexrzU9UB8Y8avFOMGuRiWGt4Kh54hNxgaCRGp9ugoyEq5H5
++QNB1x8tBJSe1YC4T06olH2xZTYCd5e9qTyjQrbnqTK4SEBDrOL+XSASkleH3vVH
+SO1paXDjh9fSSTxPo1T8DnAadIcouVlUNdvO4WrtqO4Kbf0rDHbqzZDtrNYG3Hwd
+w86nEo6J1AKrTKyXysOLdhuAhNr+hGx4ITT5HfV/H5BE3ba0/fmLxvenqTxBXrJc
+wkEeORwtu1XWW1hxYKRi3lRgfi4OH/ciMwxU530mKZzIJTOdvsKPgw==
+-----END RSA PRIVATE KEY-----
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/serial
new file mode 100644
index 000000000..59c112266
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/serial
@@ -0,0 +1 @@
+1004
diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/openssl.cfg
new file mode 100644
index 000000000..571237e7d
--- /dev/null
+++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/openssl.cfg
@@ -0,0 +1,292 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca' and 'req'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = ./demoCA # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certificates with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem # The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+# crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = sha1 # which md to use.
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = match
+stateOrProvinceName = match
+organizationName = match
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 1024
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = DE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Hamburg
+
+localityName = Locality Name (eg, city)
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = OpenOffice.org
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+organizationalUnitName_default = Development
+
+commonName = Common Name (eg, YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+authorityInfoAccess = OCSP;URI:http://localhost:8889
+#crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+#nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+#authorityInfoAccess = OCSP;URI:http://localhost:8888/
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer:always
+
+#authorityInfoAccess = OCSP;URI:http://localhost:8888
+#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = critical, CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as a test self-signed certificate it is best
+# left out by default.
+# keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_1.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_1.crt
new file mode 100644
index 000000000..ff4f23a90
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Root_1.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_10.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_10.crt
new file mode 100644
index 000000000..64f80334b
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Root_10.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_11.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_11.crt
new file mode 100644
index 000000000..bbf0819dd
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_2.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_2.crt
new file mode 100644
index 000000000..5f4bd15cd
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Root_2.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_3.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_3.crt
new file mode 100644
index 000000000..306aa5649
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Root_3.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_4.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_4.crt
new file mode 100644
index 000000000..a4c1dd84d
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Root_4.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_5.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_5.crt
new file mode 100644
index 000000000..e9af2c330
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Root_5.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_6.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_6.crt
new file mode 100644
index 000000000..03f2ff0b3
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Root_6.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_7.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_7.crt
new file mode 100644
index 000000000..96eb50459
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Root_7.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_8.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_8.crt
new file mode 100644
index 000000000..c714844ad
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Root_8.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_1.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_1.crt
new file mode 100644
index 000000000..d83ce86de
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_1.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_2.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_2.crt
new file mode 100644
index 000000000..c4857c541
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_2.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_3.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_3.crt
new file mode 100644
index 000000000..d39b18b57
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_3.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_4.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_4.crt
new file mode 100644
index 000000000..b881f8a12
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_4.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_5.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_5.crt
new file mode 100644
index 000000000..61391a8c2
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_5.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_6.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_6.crt
new file mode 100644
index 000000000..223d047ca
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_6.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_7.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_7.crt
new file mode 100644
index 000000000..af6a36003
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_7.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_8.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_8.crt
new file mode 100644
index 000000000..05297a327
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_8.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_9.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_9.crt
new file mode 100644
index 000000000..209059fac
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_9.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_4.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_4.crt
new file mode 100644
index 000000000..a981a091c
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_4.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_7.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_7.crt
new file mode 100644
index 000000000..d73827e10
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_7.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_8.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_8.crt
new file mode 100644
index 000000000..69da1318b
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_8.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/crl/Root_10.crl b/xmlsecurity/test_docs/certs/crl/Root_10.crl
new file mode 100644
index 000000000..e7fee3ade
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/crl/Root_10.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/crl/Root_11.crl b/xmlsecurity/test_docs/certs/crl/Root_11.crl
new file mode 100644
index 000000000..95e18ae6a
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/crl/Root_11.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/crl/Root_3.crl b/xmlsecurity/test_docs/certs/crl/Root_3.crl
new file mode 100644
index 000000000..5978b2613
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/crl/Root_3.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/crl/Root_4.crl b/xmlsecurity/test_docs/certs/crl/Root_4.crl
new file mode 100644
index 000000000..10b370c14
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/crl/Root_4.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/crl/Root_9.crl b/xmlsecurity/test_docs/certs/crl/Root_9.crl
new file mode 100644
index 000000000..90bf8eba4
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/crl/Root_9.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_2.crl b/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_2.crl
new file mode 100644
index 000000000..c9f542029
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_2.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_4.crl b/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_4.crl
new file mode 100644
index 000000000..7fc03f255
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_4.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_9.crl b/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_9.crl
new file mode 100644
index 000000000..567b8b5d1
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_9.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/crl/Sub_CA_2_Root_4.crl b/xmlsecurity/test_docs/certs/crl/Sub_CA_2_Root_4.crl
new file mode 100644
index 000000000..a2ce79b3a
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/crl/Sub_CA_2_Root_4.crl
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_10_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_10_Root_11.crt
new file mode 100644
index 000000000..16abebe51
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_10_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_11_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_11_Root_11.crt
new file mode 100644
index 000000000..08f5040ce
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_11_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_12_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_12_Root_11.crt
new file mode 100644
index 000000000..18bd2475c
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_12_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_13_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_13_Root_11.crt
new file mode 100644
index 000000000..c7c83cf19
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_13_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_14_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_14_Root_11.crt
new file mode 100644
index 000000000..3ff2118d2
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_14_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_15_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_15_Root_11.crt
new file mode 100644
index 000000000..0fcd6393a
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_15_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_16_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_16_Root_11.crt
new file mode 100644
index 000000000..9f2874060
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_16_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_17_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_17_Root_11.crt
new file mode 100644
index 000000000..49442c6df
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_17_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_18_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_18_Root_11.crt
new file mode 100644
index 000000000..27109c5bb
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_18_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_19_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_19_Root_11.crt
new file mode 100644
index 000000000..5cce769b4
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_19_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Root_11.crt
new file mode 100644
index 000000000..09f2a54f4
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_1.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_1.crt
new file mode 100644
index 000000000..c3810ab50
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_1.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_10.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_10.crt
new file mode 100644
index 000000000..1531d1e8d
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_10.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_2.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_2.crt
new file mode 100644
index 000000000..3dab25877
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_2.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_3.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_3.crt
new file mode 100644
index 000000000..278b11b77
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_3.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_4.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_4.crt
new file mode 100644
index 000000000..fa6e84547
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_4.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_5.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_5.crt
new file mode 100644
index 000000000..863f6f613
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_5.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_6.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_6.crt
new file mode 100644
index 000000000..cae3959d1
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_6.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_7.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_7.crt
new file mode 100644
index 000000000..e5786dc6c
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_7.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_8.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_8.crt
new file mode 100644
index 000000000..a63a9f8c9
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_8.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_9.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_9.crt
new file mode 100644
index 000000000..59a77df71
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_9.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_4.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_4.crt
new file mode 100644
index 000000000..3b12b29c1
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_4.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_7.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_7.crt
new file mode 100644
index 000000000..c11e716d7
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_7.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_8.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_8.crt
new file mode 100644
index 000000000..026274f63
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_8.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_20_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_20_Root_11.crt
new file mode 100644
index 000000000..4a026790e
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_20_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_21_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_21_Root_11.crt
new file mode 100644
index 000000000..46b008eeb
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_21_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_22_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_22_Root_11.crt
new file mode 100644
index 000000000..7c1c2cb29
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_22_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_23_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_23_Root_11.crt
new file mode 100644
index 000000000..cc6185cc9
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_23_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_24_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_24_Root_11.crt
new file mode 100644
index 000000000..fa646e402
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_24_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_25_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_25_Root_11.crt
new file mode 100644
index 000000000..673db6cc9
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_25_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_26_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_26_Root_11.crt
new file mode 100644
index 000000000..e284dca9b
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_26_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_27_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_27_Root_11.crt
new file mode 100644
index 000000000..5b2cda461
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_27_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_28_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_28_Root_11.crt
new file mode 100644
index 000000000..532010b18
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_28_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_29_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_29_Root_11.crt
new file mode 100644
index 000000000..282aa47af
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_29_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_2_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_2_Root_11.crt
new file mode 100644
index 000000000..26a51418f
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_2_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_4.crt b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_4.crt
new file mode 100644
index 000000000..8a00d3008
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_4.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_7.crt b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_7.crt
new file mode 100644
index 000000000..935da38c2
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_7.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_8.crt b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_8.crt
new file mode 100644
index 000000000..79ea4fbcf
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_8.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_4.crt b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_4.crt
new file mode 100644
index 000000000..011c4ae2a
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_4.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_7.crt b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_7.crt
new file mode 100644
index 000000000..b14254428
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_7.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_8.crt b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_8.crt
new file mode 100644
index 000000000..8c8689e10
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_8.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_30_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_30_Root_11.crt
new file mode 100644
index 000000000..ed39bea1e
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_30_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_31_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_31_Root_11.crt
new file mode 100644
index 000000000..7f9e13698
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_31_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_32_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_32_Root_11.crt
new file mode 100644
index 000000000..dc28470c8
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_32_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_33_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_33_Root_11.crt
new file mode 100644
index 000000000..df9d81d8d
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_33_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_34_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_34_Root_11.crt
new file mode 100644
index 000000000..018da383d
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_34_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_35_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_35_Root_11.crt
new file mode 100644
index 000000000..0092d16c7
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_35_Root_11.crt
@@ -0,0 +1,64 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4130 (0x1022)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11
+ Validity
+ Not Before: Nov 8 10:51:39 2010 GMT
+ Not After : Nov 8 10:51:39 2011 GMT
+ Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 35
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:9b:36:00:64:f3:ce:93:97:62:19:fa:78:d9:6f:
+ 92:6a:b9:d2:9a:4e:06:2c:02:52:cd:93:50:84:28:
+ 19:42:a2:4a:34:e2:cd:e6:b0:39:7a:c8:4d:84:bc:
+ 71:51:ed:5d:6c:7e:f9:cc:01:5a:4b:73:50:a9:3b:
+ 5d:ad:cc:89:f7:dc:e0:dd:0a:ff:48:01:a9:34:19:
+ c0:6a:ee:4b:20:f4:cf:3c:94:c1:ae:88:0f:c9:42:
+ 1a:a6:47:31:fe:37:04:00:bb:ec:07:5f:cb:ee:70:
+ c4:c7:7c:6f:ee:03:19:76:de:0b:df:d0:48:91:67:
+ 55:9b:90:91:f4:ce:56:04:d5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 91:47:AC:29:95:5D:EF:72:14:8F:82:45:07:E2:94:49:75:C6:7D:73
+ X509v3 Authority Key Identifier:
+ keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55
+
+ X509v3 Subject Alternative Name:
+ DNS:alt.openoffice.org, IP Address:192.168.7.1, IP Address:13:0:0:0:0:0:0:17, email:my@other.address, Registered ID:1.2.3.4, othername:<unsupported>, DirName:/C=DE/O=OpenOffice.org/OU=Development/CN=User 32 Root 11, URI:http://my.url.here/
+ Signature Algorithm: sha1WithRSAEncryption
+ 6e:80:e6:1e:86:3d:d2:65:a6:17:fa:80:2d:2e:dc:85:32:05:
+ a1:69:82:e1:79:d1:dc:de:69:cd:9e:f0:cc:90:75:a9:45:ee:
+ 73:46:fe:29:69:c0:99:bb:fc:3a:db:c0:5f:69:c6:b7:ea:9a:
+ 63:b2:8e:29:2c:a5:5a:88:88:94:75:4b:ab:0a:72:f6:3a:aa:
+ 5d:6b:3a:5c:b6:9b:57:f5:c1:51:af:df:3c:a6:8a:a3:da:70:
+ 66:61:49:12:06:78:98:9f:bc:78:3c:43:6d:08:94:aa:32:b6:
+ f3:cc:af:0d:29:fe:96:47:7d:fe:4a:61:48:90:11:0b:bd:0f:
+ a0:fd
+-----BEGIN CERTIFICATE-----
+MIIDajCCAtOgAwIBAgICECIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD
+VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDExMDgxMDUx
+MzlaFw0xMTExMDgxMDUxMzlaMGAxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i
+dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l
+bnQxEDAOBgNVBAMTB1VzZXIgMzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
+AJs2AGTzzpOXYhn6eNlvkmq50ppOBiwCUs2TUIQoGUKiSjTizeawOXrITYS8cVHt
+XWx++cwBWktzUKk7Xa3Miffc4N0K/0gBqTQZwGruSyD0zzyUwa6ID8lCGqZHMf43
+BAC77Adfy+5wxMd8b+4DGXbeC9/QSJFnVZuQkfTOVgTVAgMBAAGjggExMIIBLTAL
+BgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJFHrCmVXe9yFI+CRQfilEl1xn1zMB8GA1Ud
+IwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMIHdBgNVHREEgdUwgdKCEmFsdC5v
+cGVub2ZmaWNlLm9yZ4cEwKgHAYcQABMAAAAAAAAAAAAAAAAAF4EQbXlAb3RoZXIu
+YWRkcmVzc4gDKgMEoB4GAyoDBKAXDBVzb21lIG90aGVyIGlkZW50aWZpZXKkWDBW
+MQswCQYDVQQGEwJERTEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT
+C0RldmVsb3BtZW50MRgwFgYDVQQDEw9Vc2VyIDMyIFJvb3QgMTGGE2h0dHA6Ly9t
+eS51cmwuaGVyZS8wDQYJKoZIhvcNAQEFBQADgYEAboDmHoY90mWmF/qALS7chTIF
+oWmC4XnR3N5pzZ7wzJB1qUXuc0b+KWnAmbv8OtvAX2nGt+qaY7KOKSylWoiIlHVL
+qwpy9jqqXWs6XLabV/XBUa/fPKaKo9pwZmFJEgZ4mJ+8eDxDbQiUqjK288yvDSn+
+lkd9/kphSJARC70PoP0=
+-----END CERTIFICATE-----
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_3_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_3_Root_11.crt
new file mode 100644
index 000000000..879f4578c
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_3_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_4_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_4_Root_11.crt
new file mode 100644
index 000000000..75a9c7c84
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_4_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_5_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_5_Root_11.crt
new file mode 100644
index 000000000..cf07f4aa2
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_5_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_6_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_6_Root_11.crt
new file mode 100644
index 000000000..993a09f95
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_6_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_7_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_7_Root_11.crt
new file mode 100644
index 000000000..a1cebacb3
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_7_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_8_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_8_Root_11.crt
new file mode 100644
index 000000000..12410ebc8
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_8_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/end_certs/User_9_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_9_Root_11.crt
new file mode 100644
index 000000000..f7372d09f
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/end_certs/User_9_Root_11.crt
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/Root_11.p12 b/xmlsecurity/test_docs/certs/p12/Root_11.p12
new file mode 100644
index 000000000..7df592643
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_10_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_10_Root_11.p12
new file mode 100644
index 000000000..048ca8e8f
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_10_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_11_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_11_Root_11.p12
new file mode 100644
index 000000000..4498cdb76
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_11_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_12_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_12_Root_11.p12
new file mode 100644
index 000000000..d85e0b7d4
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_12_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_13_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_13_Root_11.p12
new file mode 100644
index 000000000..ff666ff1e
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_13_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_14_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_14_Root_11.p12
new file mode 100644
index 000000000..55e0d6233
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_14_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_15_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_15_Root_11.p12
new file mode 100644
index 000000000..baa32f26b
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_15_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_16_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_16_Root_11.p12
new file mode 100644
index 000000000..7b20ff98c
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_16_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_17_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_17_Root_11.p12
new file mode 100644
index 000000000..6e980df49
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_17_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_18_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_18_Root_11.p12
new file mode 100644
index 000000000..4d343d6e7
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_18_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_19_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_19_Root_11.p12
new file mode 100644
index 000000000..aa5f27d2d
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_19_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Root_11.p12
new file mode 100644
index 000000000..80e5bf47c
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_1_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_1.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_1.p12
new file mode 100644
index 000000000..1e9a14cb8
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_1.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_10.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_10.p12
new file mode 100644
index 000000000..d7096919b
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_10.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_2.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_2.p12
new file mode 100644
index 000000000..adc61fff4
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_2.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_3.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_3.p12
new file mode 100644
index 000000000..9213427a1
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_3.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_4.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_4.p12
new file mode 100644
index 000000000..005191d16
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_4.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_5.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_5.p12
new file mode 100644
index 000000000..e4599b113
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_5.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_6.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_6.p12
new file mode 100644
index 000000000..32b4926ad
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_6.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_7.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_7.p12
new file mode 100644
index 000000000..2c0ea4acb
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_7.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_8.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_8.p12
new file mode 100644
index 000000000..b69a19e4e
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_8.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_9.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_9.p12
new file mode 100644
index 000000000..7897733c4
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_9.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_4.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_4.p12
new file mode 100644
index 000000000..99eb94452
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_4.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_7.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_7.p12
new file mode 100644
index 000000000..1aefff504
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_7.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_8.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_8.p12
new file mode 100644
index 000000000..6b6d5fd4e
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_8.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_20_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_20_Root_11.p12
new file mode 100644
index 000000000..bebfdc88a
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_20_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_21_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_21_Root_11.p12
new file mode 100644
index 000000000..cbd6730a8
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_21_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_22_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_22_Root_11.p12
new file mode 100644
index 000000000..ab2b651c1
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_22_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_23_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_23_Root_11.p12
new file mode 100644
index 000000000..518388c5b
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_23_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_24_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_24_Root_11.p12
new file mode 100644
index 000000000..775b1359d
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_24_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_25_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_25_Root_11.p12
new file mode 100644
index 000000000..f76a61869
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_25_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_26_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_26_Root_11.p12
new file mode 100644
index 000000000..ef1273c72
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_26_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_27_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_27_Root_11.p12
new file mode 100644
index 000000000..4208dc431
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_27_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_28_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_28_Root_11.p12
new file mode 100644
index 000000000..4826f2d04
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_28_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_29_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_29_Root_11.p12
new file mode 100644
index 000000000..bc211718a
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_29_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_2_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_2_Root_11.p12
new file mode 100644
index 000000000..876151de3
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_2_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_4.p12 b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_4.p12
new file mode 100644
index 000000000..268eeb938
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_4.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_7.p12 b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_7.p12
new file mode 100644
index 000000000..2fc86b9af
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_7.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_8.p12 b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_8.p12
new file mode 100644
index 000000000..80dd6a8b0
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_8.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_4.p12 b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_4.p12
new file mode 100644
index 000000000..821bb8ea5
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_4.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_7.p12 b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_7.p12
new file mode 100644
index 000000000..3671d176d
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_7.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_8.p12 b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_8.p12
new file mode 100644
index 000000000..a4c63b7f2
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_8.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_30_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_30_Root_11.p12
new file mode 100644
index 000000000..99b0be699
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_30_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_31_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_31_Root_11.p12
new file mode 100644
index 000000000..5dbaf524c
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_31_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_32_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_32_Root_11.p12
new file mode 100644
index 000000000..17e22f7a5
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_32_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_33_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_33_Root_11.p12
new file mode 100644
index 000000000..5982532a9
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_33_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_34_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_34_Root_11.p12
new file mode 100644
index 000000000..4c00b21d4
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_34_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_3_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_3_Root_11.p12
new file mode 100644
index 000000000..bc476b257
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_3_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_4_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_4_Root_11.p12
new file mode 100644
index 000000000..0b9bd319b
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_4_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_5_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_5_Root_11.p12
new file mode 100644
index 000000000..99de803de
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_5_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_6_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_6_Root_11.p12
new file mode 100644
index 000000000..a663a92d9
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_6_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_7_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_7_Root_11.p12
new file mode 100644
index 000000000..c3d4e7532
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_7_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_8_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_8_Root_11.p12
new file mode 100644
index 000000000..9db9c0ad4
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_8_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/certs/p12/User_9_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_9_Root_11.p12
new file mode 100644
index 000000000..ccb03b327
--- /dev/null
+++ b/xmlsecurity/test_docs/certs/p12/User_9_Root_11.p12
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/aia_ca_issuers.odt b/xmlsecurity/test_docs/documents/aia_ca_issuers.odt
new file mode 100644
index 000000000..8c34889df
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/aia_ca_issuers.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/aia_ocsp.odt b/xmlsecurity/test_docs/documents/aia_ocsp.odt
new file mode 100644
index 000000000..6a1b48c6a
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/aia_ocsp.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/aia_ocsp_revoked_chain.odt b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_chain.odt
new file mode 100644
index 000000000..248fccedd
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_chain.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf.odt b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf.odt
new file mode 100644
index 000000000..2e0dbd6f7
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf_chain.odt b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf_chain.odt
new file mode 100644
index 000000000..3519e4a81
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf_chain.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/crl.odt b/xmlsecurity/test_docs/documents/crl.odt
new file mode 100644
index 000000000..06e412fa3
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/crl.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/crl_revoked_chain.odt b/xmlsecurity/test_docs/documents/crl_revoked_chain.odt
new file mode 100644
index 000000000..851fc87e7
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/crl_revoked_chain.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/crl_revoked_leaf.odt b/xmlsecurity/test_docs/documents/crl_revoked_leaf.odt
new file mode 100644
index 000000000..a97598d55
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/crl_revoked_leaf.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/crl_revoked_leaf_chain.odt b/xmlsecurity/test_docs/documents/crl_revoked_leaf_chain.odt
new file mode 100644
index 000000000..f82a02a45
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/crl_revoked_leaf_chain.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/crldp.odt b/xmlsecurity/test_docs/documents/crldp.odt
new file mode 100644
index 000000000..5cbf289de
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/crldp.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/crldp_no_intermediate_ca_revocation_info.odt b/xmlsecurity/test_docs/documents/crldp_no_intermediate_ca_revocation_info.odt
new file mode 100644
index 000000000..20c28d925
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/crldp_no_intermediate_ca_revocation_info.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/crldp_no_root_revocation_info.odt b/xmlsecurity/test_docs/documents/crldp_no_root_revocation_info.odt
new file mode 100644
index 000000000..d3f59e601
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/crldp_no_root_revocation_info.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/crldp_revoked_chain.odt b/xmlsecurity/test_docs/documents/crldp_revoked_chain.odt
new file mode 100644
index 000000000..8c6416b80
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/crldp_revoked_chain.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/crldp_revoked_leaf.odt b/xmlsecurity/test_docs/documents/crldp_revoked_leaf.odt
new file mode 100644
index 000000000..fce479cc6
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/crldp_revoked_leaf.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/crldp_revoked_leaf_chain.odt b/xmlsecurity/test_docs/documents/crldp_revoked_leaf_chain.odt
new file mode 100644
index 000000000..53d1e01e7
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/crldp_revoked_leaf_chain.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/dn_cyrillic_bmpstring.odt b/xmlsecurity/test_docs/documents/dn_cyrillic_bmpstring.odt
new file mode 100644
index 000000000..1f69a3248
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/dn_cyrillic_bmpstring.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/dn_latin_ext_greak_bmpstring.odt b/xmlsecurity/test_docs/documents/dn_latin_ext_greak_bmpstring.odt
new file mode 100644
index 000000000..53a29310e
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/dn_latin_ext_greak_bmpstring.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/dn_multivalue_rdn.odt b/xmlsecurity/test_docs/documents/dn_multivalue_rdn.odt
new file mode 100644
index 000000000..4d34bc0f5
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/dn_multivalue_rdn.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/dn_quoting.odt b/xmlsecurity/test_docs/documents/dn_quoting.odt
new file mode 100644
index 000000000..ca17f6aab
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/dn_quoting.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/dn_single_multivalue_rdn.odt b/xmlsecurity/test_docs/documents/dn_single_multivalue_rdn.odt
new file mode 100644
index 000000000..798f25a35
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/dn_single_multivalue_rdn.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/dn_single_multivalue_rdn_with_quoting.odt b/xmlsecurity/test_docs/documents/dn_single_multivalue_rdn_with_quoting.odt
new file mode 100644
index 000000000..591f9aa4d
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/dn_single_multivalue_rdn_with_quoting.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/incomplete_path.odt b/xmlsecurity/test_docs/documents/incomplete_path.odt
new file mode 100644
index 000000000..cb0763b0a
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/incomplete_path.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc1.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc1.odt
new file mode 100644
index 000000000..f0555b1a2
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc1.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc2.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc2.odt
new file mode 100644
index 000000000..b2e24fc61
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc2.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro1.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro1.odt
new file mode 100644
index 000000000..640a80dce
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro1.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro2.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro2.odt
new file mode 100644
index 000000000..35847216b
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro2.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro3.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro3.odt
new file mode 100644
index 000000000..575f3a12d
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro3.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro4.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro4.odt
new file mode 100644
index 000000000..75a417cab
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro4.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro5.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro5.odt
new file mode 100644
index 000000000..f7d71762f
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro5.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc1.odt b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc1.odt
new file mode 100644
index 000000000..9984aa1bb
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc1.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc3.odt b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc3.odt
new file mode 100644
index 000000000..5ad7b68ab
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc3.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc4.odt b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc4.odt
new file mode 100644
index 000000000..d126a8dff
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc4.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/invalid_ooo_3_2_doc2.odt b/xmlsecurity/test_docs/documents/invalid_ooo_3_2_doc2.odt
new file mode 100644
index 000000000..dd475c354
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/invalid_ooo_3_2_doc2.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/ocsp_crl.odt b/xmlsecurity/test_docs/documents/ocsp_crl.odt
new file mode 100644
index 000000000..f8ab95c04
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/ocsp_crl.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/ocsp_crl_revoked_leaf.odt b/xmlsecurity/test_docs/documents/ocsp_crl_revoked_leaf.odt
new file mode 100644
index 000000000..4d7c5cd80
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/ocsp_crl_revoked_leaf.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/stateOrProvinceName.odt b/xmlsecurity/test_docs/documents/stateOrProvinceName.odt
new file mode 100644
index 000000000..0979ae5a9
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/stateOrProvinceName.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/valid_no_revocation.odt b/xmlsecurity/test_docs/documents/valid_no_revocation.odt
new file mode 100644
index 000000000..f7c9bbf5e
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/valid_no_revocation.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/valid_no_root_revocation_info.odt b/xmlsecurity/test_docs/documents/valid_no_root_revocation_info.odt
new file mode 100644
index 000000000..d26eb58f0
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/valid_no_root_revocation_info.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/valid_no_sub_ca_revocation_info.odt b/xmlsecurity/test_docs/documents/valid_no_sub_ca_revocation_info.odt
new file mode 100644
index 000000000..5d6c053c2
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/valid_no_sub_ca_revocation_info.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/valid_ooo2_x_doc1.odt b/xmlsecurity/test_docs/documents/valid_ooo2_x_doc1.odt
new file mode 100644
index 000000000..cb6401c16
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/valid_ooo2_x_doc1.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/valid_ooo2_x_doc_macro.odt b/xmlsecurity/test_docs/documents/valid_ooo2_x_doc_macro.odt
new file mode 100644
index 000000000..09b63b40a
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/valid_ooo2_x_doc_macro.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/valid_ooo2_x_doc_unsigned_macro.odt b/xmlsecurity/test_docs/documents/valid_ooo2_x_doc_unsigned_macro.odt
new file mode 100644
index 000000000..e810d785d
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/valid_ooo2_x_doc_unsigned_macro.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/valid_ooo3_0_doc1.odt b/xmlsecurity/test_docs/documents/valid_ooo3_0_doc1.odt
new file mode 100644
index 000000000..6c2bbd045
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/valid_ooo3_0_doc1.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/valid_ooo3_0_doc_macro.odt b/xmlsecurity/test_docs/documents/valid_ooo3_0_doc_macro.odt
new file mode 100644
index 000000000..b8b036cc8
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/valid_ooo3_0_doc_macro.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/valid_ooo3_0_doc_unsigned_macro.odt b/xmlsecurity/test_docs/documents/valid_ooo3_0_doc_unsigned_macro.odt
new file mode 100644
index 000000000..6ba0ec52a
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/valid_ooo3_0_doc_unsigned_macro.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/valid_ooo3_2_doc1.odt b/xmlsecurity/test_docs/documents/valid_ooo3_2_doc1.odt
new file mode 100644
index 000000000..de1c635c1
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/valid_ooo3_2_doc1.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/valid_ooo3_2_doc_macro.odt b/xmlsecurity/test_docs/documents/valid_ooo3_2_doc_macro.odt
new file mode 100644
index 000000000..f6575ec88
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/valid_ooo3_2_doc_macro.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/documents/valid_ooo3_2_doc_unsigned_macro.odt b/xmlsecurity/test_docs/documents/valid_ooo3_2_doc_unsigned_macro.odt
new file mode 100644
index 000000000..41f676f63
--- /dev/null
+++ b/xmlsecurity/test_docs/documents/valid_ooo3_2_doc_unsigned_macro.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/test_description.odt b/xmlsecurity/test_docs/test_description.odt
new file mode 100644
index 000000000..45bbb5b0d
--- /dev/null
+++ b/xmlsecurity/test_docs/test_description.odt
Binary files differ
diff --git a/xmlsecurity/test_docs/tools/README.txt b/xmlsecurity/test_docs/tools/README.txt
new file mode 100644
index 000000000..b253a78b6
--- /dev/null
+++ b/xmlsecurity/test_docs/tools/README.txt
@@ -0,0 +1,24 @@
+httpserv
+============
+Simple http server for testing of Certificate Revocation Lists (CRL).
+
+Netbeans 6.7.1 project. httpserv.jar requires java 6.
+
+Run with
+
+java -jar httpserv/dist/httpserv.jar --accept portnumber
+
+portnumber: an arbitrary port number to which the server should listen.
+
+httpserv looks for the requested file relative to the current directory. For
+example, you are in
+$(SRC_ROOT)/xmlsecurity/$(INPATH)/httpserv/dist/javadoc,
+a directory which contains the index.html. From there you run httpserv.jar:
+
+java -jar <path_to_wherever_it_is>/httpserv.jar --accept 8000
+
+now enter in the Browser:
+
+localhost:8000/index.html
+
+
diff --git a/xmlsecurity/test_docs/tools/httpserv/build.xml b/xmlsecurity/test_docs/tools/httpserv/build.xml
new file mode 100644
index 000000000..3492d3aa6
--- /dev/null
+++ b/xmlsecurity/test_docs/tools/httpserv/build.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See commented blocks below for -->
+<!-- some examples of how to customize the build. -->
+<!-- (If you delete it and reopen the project it will be recreated.) -->
+<!-- By default, only the Clean and Build commands use this build script. -->
+<!-- Commands such as Run, Debug, and Test only use this build script if -->
+<!-- the Compile on Save feature is turned off for the project. -->
+<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
+<!-- in the project's Project Properties dialog box.-->
+<project name="httpserv" default="default" basedir=".">
+ <description>Builds, tests, and runs the project httpserv.</description>
+ <import file="nbproject/build-impl.xml"/>
+ <!--
+
+ There exist several targets which are by default empty and which can be
+ used for execution of your tasks. These targets are usually executed
+ before and after some main targets. They are:
+
+ -pre-init: called before initialization of project properties
+ -post-init: called after initialization of project properties
+ -pre-compile: called before javac compilation
+ -post-compile: called after javac compilation
+ -pre-compile-single: called before javac compilation of single file
+ -post-compile-single: called after javac compilation of single file
+ -pre-compile-test: called before javac compilation of JUnit tests
+ -post-compile-test: called after javac compilation of JUnit tests
+ -pre-compile-test-single: called before javac compilation of single JUnit test
+ -post-compile-test-single: called after javac compilation of single JUnit test
+ -pre-jar: called before JAR building
+ -post-jar: called after JAR building
+ -post-clean: called after cleaning build products
+
+ (Targets beginning with '-' are not intended to be called on their own.)
+
+ Example of inserting an obfuscator after compilation could look like this:
+
+ <target name="-post-compile">
+ <obfuscate>
+ <fileset dir="${build.classes.dir}"/>
+ </obfuscate>
+ </target>
+
+ For list of available properties check the imported
+ nbproject/build-impl.xml file.
+
+
+ Another way to customize the build is by overriding existing main targets.
+ The targets of interest are:
+
+ -init-macrodef-javac: defines macro for javac compilation
+ -init-macrodef-junit: defines macro for junit execution
+ -init-macrodef-debug: defines macro for class debugging
+ -init-macrodef-java: defines macro for class execution
+ -do-jar-with-manifest: JAR building (if you are using a manifest)
+ -do-jar-without-manifest: JAR building (if you are not using a manifest)
+ run: execution of project
+ -javadoc-build: Javadoc generation
+ test-report: JUnit report generation
+
+ An example of overriding the target for project execution could look like this:
+
+ <target name="run" depends="httpserv-impl.jar">
+ <exec dir="bin" executable="launcher.exe">
+ <arg file="${dist.jar}"/>
+ </exec>
+ </target>
+
+ Notice that the overridden target depends on the jar target and not only on
+ the compile target as the regular run target does. Again, for a list of available
+ properties which you can use, check the target you are overriding in the
+ nbproject/build-impl.xml file.
+
+ -->
+ <!-- Import the environment as properties to make them available in project.properties
+ -->
+ <target name="-pre-init">
+ <property environment="env" />
+ </target>
+</project>
diff --git a/xmlsecurity/test_docs/tools/httpserv/manifest.mf b/xmlsecurity/test_docs/tools/httpserv/manifest.mf
new file mode 100644
index 000000000..328e8e5bc
--- /dev/null
+++ b/xmlsecurity/test_docs/tools/httpserv/manifest.mf
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+X-COMMENT: Main-Class will be added automatically by build
+
diff --git a/xmlsecurity/test_docs/tools/httpserv/nbproject/build-impl.xml b/xmlsecurity/test_docs/tools/httpserv/nbproject/build-impl.xml
new file mode 100644
index 000000000..9064a3305
--- /dev/null
+++ b/xmlsecurity/test_docs/tools/httpserv/nbproject/build-impl.xml
@@ -0,0 +1,700 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT ***
+*** EDIT ../build.xml INSTEAD ***
+
+For the purpose of easier reading the script
+is divided into following sections:
+
+ - initialization
+ - compilation
+ - jar
+ - execution
+ - debugging
+ - javadoc
+ - junit compilation
+ - junit execution
+ - junit debugging
+ - applet
+ - cleanup
+
+ -->
+<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="httpserv-impl">
+ <fail message="Please build using Ant 1.7.1 or higher.">
+ <condition>
+ <not>
+ <antversion atleast="1.7.1"/>
+ </not>
+ </condition>
+ </fail>
+ <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
+ <!--
+ ======================
+ INITIALIZATION SECTION
+ ======================
+ -->
+ <target name="-pre-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="-pre-init" name="-init-private">
+ <property file="nbproject/private/config.properties"/>
+ <property file="nbproject/private/configs/${config}.properties"/>
+ <property file="nbproject/private/private.properties"/>
+ </target>
+ <target depends="-pre-init,-init-private" name="-init-user">
+ <property file="${user.properties.file}"/>
+ <!-- The two properties below are usually overridden -->
+ <!-- by the active platform. Just a fallback. -->
+ <property name="default.javac.source" value="1.4"/>
+ <property name="default.javac.target" value="1.4"/>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user" name="-init-project">
+ <property file="nbproject/configs/${config}.properties"/>
+ <property file="nbproject/project.properties"/>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
+ <available file="${manifest.file}" property="manifest.available"/>
+ <condition property="manifest.available+main.class">
+ <and>
+ <isset property="manifest.available"/>
+ <isset property="main.class"/>
+ <not>
+ <equals arg1="${main.class}" arg2="" trim="true"/>
+ </not>
+ </and>
+ </condition>
+ <condition property="manifest.available+main.class+mkdist.available">
+ <and>
+ <istrue value="${manifest.available+main.class}"/>
+ <isset property="libs.CopyLibs.classpath"/>
+ </and>
+ </condition>
+ <condition property="have.tests">
+ <or>
+ <available file="${test.src.dir}"/>
+ </or>
+ </condition>
+ <condition property="have.sources">
+ <or>
+ <available file="${src.dir}"/>
+ </or>
+ </condition>
+ <condition property="netbeans.home+have.tests">
+ <and>
+ <isset property="netbeans.home"/>
+ <isset property="have.tests"/>
+ </and>
+ </condition>
+ <condition property="no.javadoc.preview">
+ <and>
+ <isset property="javadoc.preview"/>
+ <isfalse value="${javadoc.preview}"/>
+ </and>
+ </condition>
+ <property name="run.jvmargs" value=""/>
+ <property name="javac.compilerargs" value=""/>
+ <property name="work.dir" value="${basedir}"/>
+ <condition property="no.deps">
+ <and>
+ <istrue value="${no.dependencies}"/>
+ </and>
+ </condition>
+ <property name="javac.debug" value="true"/>
+ <property name="javadoc.preview" value="true"/>
+ <property name="application.args" value=""/>
+ <property name="source.encoding" value="${file.encoding}"/>
+ <condition property="javadoc.encoding.used" value="${javadoc.encoding}">
+ <and>
+ <isset property="javadoc.encoding"/>
+ <not>
+ <equals arg1="${javadoc.encoding}" arg2=""/>
+ </not>
+ </and>
+ </condition>
+ <property name="javadoc.encoding.used" value="${source.encoding}"/>
+ <property name="includes" value="**"/>
+ <property name="excludes" value=""/>
+ <property name="do.depend" value="false"/>
+ <condition property="do.depend.true">
+ <istrue value="${do.depend}"/>
+ </condition>
+ <condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
+ <and>
+ <isset property="jaxws.endorsed.dir"/>
+ <available file="nbproject/jaxws-build.xml"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-post-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
+ <fail unless="src.dir">Must set src.dir</fail>
+ <fail unless="test.src.dir">Must set test.src.dir</fail>
+ <fail unless="build.dir">Must set build.dir</fail>
+ <fail unless="dist.dir">Must set dist.dir</fail>
+ <fail unless="build.classes.dir">Must set build.classes.dir</fail>
+ <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
+ <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
+ <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
+ <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
+ <fail unless="dist.jar">Must set dist.jar</fail>
+ </target>
+ <target name="-init-macrodef-property">
+ <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute name="name"/>
+ <attribute name="value"/>
+ <sequential>
+ <property name="@{name}" value="${@{value}}"/>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-javac">
+ <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${src.dir}" name="srcdir"/>
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <attribute default="${javac.classpath}" name="classpath"/>
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="${javac.debug}" name="debug"/>
+ <attribute default="${empty.dir}" name="sourcepath"/>
+ <attribute default="${empty.dir}" name="gensrcdir"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property location="${build.dir}/empty" name="empty.dir"/>
+ <mkdir dir="${empty.dir}"/>
+ <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}">
+ <src>
+ <dirset dir="@{gensrcdir}" erroronmissingdir="false">
+ <include name="*"/>
+ </dirset>
+ </src>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
+ <customize/>
+ </javac>
+ </sequential>
+ </macrodef>
+ <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${src.dir}" name="srcdir"/>
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <attribute default="${javac.classpath}" name="classpath"/>
+ <sequential>
+ <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ </depend>
+ </sequential>
+ </macrodef>
+ <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <sequential>
+ <fail unless="javac.includes">Must set javac.includes</fail>
+ <pathconvert pathsep="," property="javac.includes.binary">
+ <path>
+ <filelist dir="@{destdir}" files="${javac.includes}"/>
+ </path>
+ <globmapper from="*.java" to="*.class"/>
+ </pathconvert>
+ <delete>
+ <files includes="${javac.includes.binary}"/>
+ </delete>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-junit">
+ <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <sequential>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
+ <batchtest todir="${build.test.results.dir}">
+ <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+ <filename name="@{testincludes}"/>
+ </fileset>
+ </batchtest>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg line="${run.jvmargs}"/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-debug-args" name="-init-macrodef-nbjpda">
+ <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${main.class}" name="name"/>
+ <attribute default="${debug.classpath}" name="classpath"/>
+ <attribute default="" name="stopclassname"/>
+ <sequential>
+ <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ </nbjpdastart>
+ </sequential>
+ </macrodef>
+ <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${build.classes.dir}" name="dir"/>
+ <sequential>
+ <nbjpdareload>
+ <fileset dir="@{dir}" includes="${fix.classes}">
+ <include name="${fix.includes}*.class"/>
+ </fileset>
+ </nbjpdareload>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-debug-args">
+ <property name="version-output" value="java version &quot;${ant.java.version}"/>
+ <condition property="have-jdk-older-than-1.4">
+ <or>
+ <contains string="${version-output}" substring="java version &quot;1.0"/>
+ <contains string="${version-output}" substring="java version &quot;1.1"/>
+ <contains string="${version-output}" substring="java version &quot;1.2"/>
+ <contains string="${version-output}" substring="java version &quot;1.3"/>
+ </or>
+ </condition>
+ <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
+ <istrue value="${have-jdk-older-than-1.4}"/>
+ </condition>
+ <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
+ <os family="windows"/>
+ </condition>
+ <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
+ <isset property="debug.transport"/>
+ </condition>
+ </target>
+ <target depends="-init-debug-args" name="-init-macrodef-debug">
+ <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${main.class}" name="classname"/>
+ <attribute default="${debug.classpath}" name="classpath"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <java classname="@{classname}" dir="${work.dir}" fork="true">
+ <jvmarg line="${debug-args-line}"/>
+ <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+ <jvmarg value="-Dfile.encoding=${source.encoding}"/>
+ <redirector errorencoding="${source.encoding}" inputencoding="${source.encoding}" outputencoding="${source.encoding}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="run-sys-prop."/>
+ <mapper from="run-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <customize/>
+ </java>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-java">
+ <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${main.class}" name="classname"/>
+ <attribute default="${run.classpath}" name="classpath"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <java classname="@{classname}" dir="${work.dir}" fork="true">
+ <jvmarg value="-Dfile.encoding=${source.encoding}"/>
+ <redirector errorencoding="${source.encoding}" inputencoding="${source.encoding}" outputencoding="${source.encoding}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="run-sys-prop."/>
+ <mapper from="run-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <customize/>
+ </java>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-presetdef-jar">
+ <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <jar compress="${jar.compress}" jarfile="${dist.jar}">
+ <j2seproject1:fileset dir="${build.classes.dir}"/>
+ </jar>
+ </presetdef>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar" name="init"/>
+ <!--
+ ===================
+ COMPILATION SECTION
+ ===================
+ -->
+ <target depends="init" name="deps-jar" unless="no.deps"/>
+ <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
+ <target depends="init" name="-check-automatic-build">
+ <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
+ </target>
+ <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
+ <antcall target="clean"/>
+ </target>
+ <target depends="init,deps-jar" name="-pre-pre-compile">
+ <mkdir dir="${build.classes.dir}"/>
+ </target>
+ <target name="-pre-compile">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="do.depend.true" name="-compile-depend">
+ <pathconvert property="build.generated.subdirs">
+ <dirset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+ <include name="*"/>
+ </dirset>
+ </pathconvert>
+ <j2seproject3:depend srcdir="${src.dir}:${build.generated.subdirs}"/>
+ </target>
+ <target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
+ <j2seproject3:javac gensrcdir="${build.generated.sources.dir}"/>
+ <copy todir="${build.classes.dir}">
+ <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target name="-post-compile">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
+ <target name="-pre-compile-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
+ <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+ <j2seproject3:force-recompile/>
+ <j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}" sourcepath="${src.dir}"/>
+ </target>
+ <target name="-post-compile-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
+ <!--
+ ====================
+ JAR BUILDING SECTION
+ ====================
+ -->
+ <target depends="init" name="-pre-pre-jar">
+ <dirname file="${dist.jar}" property="dist.jar.dir"/>
+ <mkdir dir="${dist.jar.dir}"/>
+ </target>
+ <target name="-pre-jar">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
+ <j2seproject1:jar/>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
+ <j2seproject1:jar manifest="${manifest.file}"/>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">
+ <j2seproject1:jar manifest="${manifest.file}">
+ <j2seproject1:manifest>
+ <j2seproject1:attribute name="Main-Class" value="${main.class}"/>
+ </j2seproject1:manifest>
+ </j2seproject1:jar>
+ <echo>To run this application from the command line without Ant, try:</echo>
+ <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
+ <property location="${dist.jar}" name="dist.jar.resolved"/>
+ <pathconvert property="run.classpath.with.dist.jar">
+ <path path="${run.classpath}"/>
+ <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
+ </pathconvert>
+ <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
+ <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
+ <pathconvert property="run.classpath.without.build.classes.dir">
+ <path path="${run.classpath}"/>
+ <map from="${build.classes.dir.resolved}" to=""/>
+ </pathconvert>
+ <pathconvert pathsep=" " property="jar.classpath">
+ <path path="${run.classpath.without.build.classes.dir}"/>
+ <chainedmapper>
+ <flattenmapper/>
+ <globmapper from="*" to="lib/*"/>
+ </chainedmapper>
+ </pathconvert>
+ <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
+ <copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
+ <fileset dir="${build.classes.dir}"/>
+ <manifest>
+ <attribute name="Main-Class" value="${main.class}"/>
+ <attribute name="Class-Path" value="${jar.classpath}"/>
+ </manifest>
+ </copylibs>
+ <echo>To run this application from the command line without Ant, try:</echo>
+ <property location="${dist.jar}" name="dist.jar.resolved"/>
+ <echo>java -jar "${dist.jar.resolved}"</echo>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" if="libs.CopyLibs.classpath" name="-do-jar-with-libraries-without-manifest" unless="manifest.available+main.class">
+ <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
+ <pathconvert property="run.classpath.without.build.classes.dir">
+ <path path="${run.classpath}"/>
+ <map from="${build.classes.dir.resolved}" to=""/>
+ </pathconvert>
+ <pathconvert pathsep=" " property="jar.classpath">
+ <path path="${run.classpath.without.build.classes.dir}"/>
+ <chainedmapper>
+ <flattenmapper/>
+ <globmapper from="*" to="lib/*"/>
+ </chainedmapper>
+ </pathconvert>
+ <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
+ <copylibs compress="${jar.compress}" jarfile="${dist.jar}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
+ <fileset dir="${build.classes.dir}"/>
+ </copylibs>
+ </target>
+ <target name="-post-jar">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-do-jar-with-libraries-without-manifest,-post-jar" description="Build JAR." name="jar"/>
+ <!--
+ =================
+ EXECUTION SECTION
+ =================
+ -->
+ <target depends="init,compile" description="Run a main class." name="run">
+ <j2seproject1:java>
+ <customize>
+ <arg line="${application.args}"/>
+ </customize>
+ </j2seproject1:java>
+ </target>
+ <target name="-do-not-recompile">
+ <property name="javac.includes.binary" value=""/>
+ </target>
+ <target depends="init,-do-not-recompile,compile-single" name="run-single">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <j2seproject1:java classname="${run.class}"/>
+ </target>
+ <target depends="init,-do-not-recompile,compile-test-single" name="run-test-with-main">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <j2seproject1:java classname="${run.class}" classpath="${run.test.classpath}"/>
+ </target>
+ <!--
+ =================
+ DEBUGGING SECTION
+ =================
+ -->
+ <target depends="init" if="netbeans.home" name="-debug-start-debugger">
+ <j2seproject1:nbjpdastart name="${debug.class}"/>
+ </target>
+ <target depends="init" if="netbeans.home" name="-debug-start-debugger-main-test">
+ <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${debug.class}"/>
+ </target>
+ <target depends="init,compile" name="-debug-start-debuggee">
+ <j2seproject3:debug>
+ <customize>
+ <arg line="${application.args}"/>
+ </customize>
+ </j2seproject3:debug>
+ </target>
+ <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
+ <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
+ <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
+ </target>
+ <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
+ <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
+ <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
+ <j2seproject3:debug classname="${debug.class}"/>
+ </target>
+ <target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
+ <target depends="init,compile-test-single" if="netbeans.home" name="-debug-start-debuggee-main-test">
+ <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
+ <j2seproject3:debug classname="${debug.class}" classpath="${debug.test.classpath}"/>
+ </target>
+ <target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-main-test,-debug-start-debuggee-main-test" if="netbeans.home" name="debug-test-with-main"/>
+ <target depends="init" name="-pre-debug-fix">
+ <fail unless="fix.includes">Must set fix.includes</fail>
+ <property name="javac.includes" value="${fix.includes}.java"/>
+ </target>
+ <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
+ <j2seproject1:nbjpdareload/>
+ </target>
+ <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
+ <!--
+ ===============
+ JAVADOC SECTION
+ ===============
+ -->
+ <target depends="init" name="-javadoc-build">
+ <mkdir dir="${dist.javadoc.dir}"/>
+ <javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
+ <classpath>
+ <path path="${javac.classpath}"/>
+ </classpath>
+ <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
+ <filename name="**/*.java"/>
+ </fileset>
+ <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+ <include name="**/*.java"/>
+ </fileset>
+ </javadoc>
+ </target>
+ <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
+ <nbbrowse file="${dist.javadoc.dir}/index.html"/>
+ </target>
+ <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
+ <!--
+ =========================
+ JUNIT COMPILATION SECTION
+ =========================
+ -->
+ <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
+ <mkdir dir="${build.test.classes.dir}"/>
+ </target>
+ <target name="-pre-compile-test">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="do.depend.true" name="-compile-test-depend">
+ <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
+ </target>
+ <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
+ <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
+ <copy todir="${build.test.classes.dir}">
+ <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target name="-post-compile-test">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
+ <target name="-pre-compile-test-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
+ <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+ <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
+ <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
+ <copy todir="${build.test.classes.dir}">
+ <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target name="-post-compile-test-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
+ <!--
+ =======================
+ JUNIT EXECUTION SECTION
+ =======================
+ -->
+ <target depends="init" if="have.tests" name="-pre-test-run">
+ <mkdir dir="${build.test.results.dir}"/>
+ </target>
+ <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
+ <j2seproject3:junit testincludes="**/*Test.java"/>
+ </target>
+ <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
+ <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
+ </target>
+ <target depends="init" if="have.tests" name="test-report"/>
+ <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
+ <target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
+ <target depends="init" if="have.tests" name="-pre-test-run-single">
+ <mkdir dir="${build.test.results.dir}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
+ <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
+ <j2seproject3:junit excludes="" includes="${test.includes}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
+ <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
+ </target>
+ <target depends="init,-do-not-recompile,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
+ <!--
+ =======================
+ JUNIT DEBUGGING SECTION
+ =======================
+ -->
+ <target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
+ <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
+ <property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
+ <delete file="${test.report.file}"/>
+ <mkdir dir="${build.test.results.dir}"/>
+ <j2seproject3:debug classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" classpath="${ant.home}/lib/ant.jar:${ant.home}/lib/ant-junit.jar:${debug.test.classpath}">
+ <customize>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <arg value="${test.class}"/>
+ <arg value="showoutput=true"/>
+ <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
+ <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
+ </customize>
+ </j2seproject3:debug>
+ </target>
+ <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
+ <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
+ </target>
+ <target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
+ <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
+ <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
+ </target>
+ <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
+ <!--
+ =========================
+ APPLET EXECUTION SECTION
+ =========================
+ -->
+ <target depends="init,compile-single" name="run-applet">
+ <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+ <j2seproject1:java classname="sun.applet.AppletViewer">
+ <customize>
+ <arg value="${applet.url}"/>
+ </customize>
+ </j2seproject1:java>
+ </target>
+ <!--
+ =========================
+ APPLET DEBUGGING SECTION
+ =========================
+ -->
+ <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
+ <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+ <j2seproject3:debug classname="sun.applet.AppletViewer">
+ <customize>
+ <arg value="${applet.url}"/>
+ </customize>
+ </j2seproject3:debug>
+ </target>
+ <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
+ <!--
+ ===============
+ CLEANUP SECTION
+ ===============
+ -->
+ <target depends="init" name="deps-clean" unless="no.deps"/>
+ <target depends="init" name="-do-clean">
+ <delete dir="${build.dir}"/>
+ <delete dir="${dist.dir}"/>
+ </target>
+ <target name="-post-clean">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
+</project>
diff --git a/xmlsecurity/test_docs/tools/httpserv/nbproject/genfiles.properties b/xmlsecurity/test_docs/tools/httpserv/nbproject/genfiles.properties
new file mode 100644
index 000000000..d8139c888
--- /dev/null
+++ b/xmlsecurity/test_docs/tools/httpserv/nbproject/genfiles.properties
@@ -0,0 +1,9 @@
+# x-no-translate
+build.xml.data.CRC32=8071b819
+build.xml.script.CRC32=deb21e95
+build.xml.stylesheet.CRC32=958a1d3e@1.26.2.45
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=8071b819
+nbproject/build-impl.xml.script.CRC32=21d1be7e
+nbproject/build-impl.xml.stylesheet.CRC32=5c621a33@1.26.2.45
diff --git a/xmlsecurity/test_docs/tools/httpserv/nbproject/project.properties b/xmlsecurity/test_docs/tools/httpserv/nbproject/project.properties
new file mode 100644
index 000000000..a0ec60ac7
--- /dev/null
+++ b/xmlsecurity/test_docs/tools/httpserv/nbproject/project.properties
@@ -0,0 +1,65 @@
+# x-no-translate
+application.title=httpserv
+application.vendor=jochen
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+build.generated.sources.dir=${build.dir}/generated-sources
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+# Uncomment to specify the preferred debugger connection transport:
+#debug.transport=dt_socket
+debug.classpath=\
+ ${run.classpath}
+debug.test.classpath=\
+ ${run.test.classpath}
+# This directory is removed when the project is cleaned:
+dist.dir=../../../${env.INPATH}/misc/httpserv
+dist.jar=${dist.dir}/httpserv.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+excludes=
+includes=**
+jar.compress=false
+javac.classpath=
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.source=1.5
+javac.target=1.5
+javac.test.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}:\
+ ${libs.junit.classpath}:\
+ ${libs.junit_4.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.encoding=${source.encoding}
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+javadoc.splitindex=true
+javadoc.use=true
+javadoc.version=false
+javadoc.windowtitle=
+main.class=httpserv.Main
+manifest.file=manifest.mf
+meta.inf.dir=${src.dir}/META-INF
+platform.active=default_platform
+run.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+# Space-separated list of JVM arguments used when running the project
+# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
+# or test-sys-prop.name=value to set system properties for unit tests):
+run.jvmargs=
+run.test.classpath=\
+ ${javac.test.classpath}:\
+ ${build.test.classes.dir}
+source.encoding=UTF-8
+src.dir=src
+test.src.dir=test
diff --git a/xmlsecurity/test_docs/tools/httpserv/nbproject/project.xml b/xmlsecurity/test_docs/tools/httpserv/nbproject/project.xml
new file mode 100644
index 000000000..6fc771ca7
--- /dev/null
+++ b/xmlsecurity/test_docs/tools/httpserv/nbproject/project.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+ <type>org.netbeans.modules.java.j2seproject</type>
+ <configuration>
+ <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
+ <name>httpserv</name>
+ <source-roots>
+ <root id="src.dir"/>
+ </source-roots>
+ <test-roots>
+ <root id="test.src.dir"/>
+ </test-roots>
+ </data>
+ </configuration>
+</project>
diff --git a/xmlsecurity/test_docs/tools/httpserv/src/httpserv/Main.java b/xmlsecurity/test_docs/tools/httpserv/src/httpserv/Main.java
new file mode 100644
index 000000000..1f9fd91d2
--- /dev/null
+++ b/xmlsecurity/test_docs/tools/httpserv/src/httpserv/Main.java
@@ -0,0 +1,190 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+package httpserv;
+
+import com.sun.net.httpserver.Headers;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+
+public class Main {
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String[] args) {
+ try {
+
+ Option[] opts = new Option[2];
+ opts[0] = new Option("--help", "-h", false);
+ opts[1] = new Option("--accept", "-a", true);
+ if (!parseOptions(args, opts)) {
+ return;
+ }
+ HttpServer server = HttpServer.create(
+ new InetSocketAddress((Integer) opts[1].value), 0);
+ server.createContext("/", new MyHandler());
+ server.setExecutor(null);
+ server.start();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ static boolean parseOptions(String[] args, Option[] inout_options) {
+ if (args.length == 0) {
+ printUsage();
+ return false;
+ }
+
+ boolean bWrongArgs = true;
+ Option currentOpt = null;
+
+ for (String s : args) {
+ // get the value for an option
+ if (currentOpt != null && currentOpt.bHasValue) {
+ //now we expect the value for the option
+ //check the type
+ try {
+ if (currentOpt.sLong.equals("--accept")) {
+ currentOpt.value = Integer.decode(s);
+ }
+ } catch (Exception e ) {
+ printUsage();
+ return false;
+ }
+ currentOpt = null;
+ continue;
+ } else {
+ currentOpt = null;
+ }
+
+
+ // get the option
+ for (Option o : inout_options) {
+ if (s.equals(o.sLong) || s.equals(o.sShort)) {
+ bWrongArgs = false;
+ //special handling for --help
+ if (o.sLong.equals("--help")) {
+ printUsage();
+ return false;
+ }
+ else
+ {
+ currentOpt = o;
+ break;
+ }
+ }
+ }
+ }
+
+ if (bWrongArgs) {
+ printUsage();
+ return false;
+ }
+ return true;
+ }
+
+ static void printUsage() {
+ String usage =
+ "Usage: \n" +
+ "java -jar httpserv [options] \n" +
+ "\n" +
+ "Options are: \n" +
+ "-h --help \t this help \n" +
+ "-a --accept port \t the port number to which this server listens \n";
+ System.out.println(usage);
+ }
+}
+
+class MyHandler implements HttpHandler {
+
+ public void handle(HttpExchange xchange) throws IOException {
+ try {
+ //First get the path to the file
+ String sRequestPath = xchange.getRequestURI().getPath();
+ System.out.println("requested: " + sRequestPath);
+ File fileRequest = new File(new File(".").getCanonicalPath(), sRequestPath);
+ if (!fileRequest.exists()) {
+ throw new IOException("The file " + fileRequest + " does not exist!");
+ }
+ else if (fileRequest.isDirectory()) {
+ throw new IOException(fileRequest + " is a directory!");
+ }
+
+
+ //Read the file into a byte array
+ byte[] data = new byte[(int) fileRequest.length()];
+ FileInputStream fr = new FileInputStream(fileRequest);
+ fr.read(data);
+ fr.close();
+
+ //set the Content-type header
+ Headers h = xchange.getResponseHeaders();
+ String canonicalPath = fileRequest.getCanonicalPath();
+ int lastIndex = canonicalPath.lastIndexOf(".");
+ String fileExtension = canonicalPath.substring(lastIndex + 1);
+
+ if (fileExtension.equalsIgnoreCase("crl"))
+ {
+ h.set("Content-Type","application/pkix-crl");
+ }
+ else if (fileExtension.equalsIgnoreCase("crt")
+ || fileExtension.equalsIgnoreCase("cer")
+ || fileExtension.equalsIgnoreCase("der"))
+ {
+ h.set("Content-Type", "application/x-x509-ca-cert");
+ }
+
+ //write out the requested file
+ xchange.sendResponseHeaders(200, data.length);
+ OutputStream os = xchange.getResponseBody();
+ os.write(data);
+ os.close();
+ System.out.println("delivered: " + fileRequest.toString());
+
+ } catch (Exception e) {
+ xchange.sendResponseHeaders(404, e.getMessage().length());
+ OutputStream os = xchange.getResponseBody();
+ os.write(e.getMessage().getBytes());
+ os.close();
+ System.out.println("Error: " + e.getMessage());
+ }
+ }
+}
+
+class Option {
+
+ Option(String _sLong, String _sShort, boolean _bHasValue) {
+ sLong = _sLong;
+ sShort = _sShort;
+ bHasValue = _bHasValue;
+ }
+ String sLong;
+ String sShort;
+ boolean bHasValue;
+ Object value;
+}
+
+
diff --git a/xmlsecurity/uiconfig/ui/certdetails.ui b/xmlsecurity/uiconfig/ui/certdetails.ui
new file mode 100644
index 000000000..cc4ba2199
--- /dev/null
+++ b/xmlsecurity/uiconfig/ui/certdetails.ui
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="xsc">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="liststore3">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name text2 -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkBox" id="CertDetails">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="hscrollbar_policy">external</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="tablecontainer">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore3</property>
+ <property name="search_column">0</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn3">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="certdetails|field">Field</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn4">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="certdetails|value">Value</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer2"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="tablecontainer-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|tablecontainer">The Details page of the View Certificate dialog displays detailed information about the certificate.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTextView" id="valuedetails">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="valuedetails-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|valuedetails">Use the value list box to view values and copy them to the clipboard.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CertDetails-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|CertDetails">The Details page of the View Certificate dialog displays detailed information about the certificate.</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/xmlsecurity/uiconfig/ui/certgeneral.ui b/xmlsecurity/uiconfig/ui/certgeneral.ui
new file mode 100644
index 000000000..e0c0b48ac
--- /dev/null
+++ b/xmlsecurity/uiconfig/ui/certgeneral.ui
@@ -0,0 +1,254 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="xsc">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="CertGeneral">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage" id="certimage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">xmlsecurity/res/certificate_40x56.png</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">6</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="certgeneral|label1">Certificate Information</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="box1-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|box1">The General page of the View Certificate dialog displays basic information about the certificate.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">6</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparator" id="separator1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="hintnotrust">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin-start">36</property>
+ <property name="margin-end">36</property>
+ <property name="margin_bottom">108</property>
+ <property name="label" translatable="yes" context="certgeneral|hintnotrust">This certificate is validated.</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparator" id="separator2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="issued_to">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="certgeneral|issued_to">Issued to: </property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="issued_to_value">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="issued_by">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="certgeneral|issued_by">Issued by: </property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="issued_by_value">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="valid_from">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="certgeneral|valid_from">Valid from:</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage" id="keyimage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">xmlsecurity/res/key_12.png</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="privatekey">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="certgeneral|privatekey">You have a private key that corresponds to this certificate.</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="valid_to">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="certgeneral|valid_to">Valid to:</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="valid_from_value">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="valid_to_value">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/xmlsecurity/uiconfig/ui/certpage.ui b/xmlsecurity/uiconfig/ui/certpage.ui
new file mode 100644
index 000000000..4e0579ac5
--- /dev/null
+++ b/xmlsecurity/uiconfig/ui/certpage.ui
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="xsc">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="liststore3">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkBox" id="CertPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="certpage|label1">Certification path</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">signatures</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="viewcert">
+ <property name="label" translatable="yes" context="certpage|viewcert">View Certificate...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="signatures">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore3</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">0</property>
+ <property name="enable_tree_lines">True</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn3">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="signatures-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|signatures">The Certificate Path page of the View Certificate dialog displays the location and the status of the certificate.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="certpage|label2">Certification status</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">status</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTextView" id="status">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="status-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|status">The Certificate Path page of the View Certificate dialog displays the location and the status of the certificate.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="certok">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="certpage|certok">The certificate is OK.</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="certnotok">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="certpage|certnotok">The certificate could not be validated.</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="CertPage-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|CertPage">The Certificate Path page of the View Certificate dialog displays the location and the status of the certificate.</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/xmlsecurity/uiconfig/ui/digitalsignaturesdialog.ui b/xmlsecurity/uiconfig/ui/digitalsignaturesdialog.ui
new file mode 100644
index 000000000..cf2404c61
--- /dev/null
+++ b/xmlsecurity/uiconfig/ui/digitalsignaturesdialog.ui
@@ -0,0 +1,528 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="xsc">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="liststore3">
+ <columns>
+ <!-- column-name image -->
+ <column type="GdkPixbuf"/>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name text2 -->
+ <column type="gchararray"/>
+ <!-- column-name text3 -->
+ <column type="gchararray"/>
+ <!-- column-name text4 -->
+ <column type="gchararray"/>
+ <!-- column-name text5 -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkDialog" id="DigitalSignaturesDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="digitalsignaturesdialog|DigitalSignaturesDialog">Digital Signatures</property>
+ <property name="modal">True</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="close">
+ <property name="label" translatable="yes" context="stock">_Close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="dochint">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="digitalsignaturesdialog|dochint">The following have signed the document content: </property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="signatures">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore3</property>
+ <property name="search_column">0</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCellRendererPixbuf" id="cellrenderertext0"/>
+ <attributes>
+ <attribute name="pixbuf">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn3">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="digitalsignaturesdialog|signed">Signed by </property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer1"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn4">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="digitalsignaturesdialog|issued">Digital ID issued by </property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer2"/>
+ <attributes>
+ <attribute name="text">2</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn5">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="digitalsignaturesdialog|date">Date</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer3"/>
+ <attributes>
+ <attribute name="text">3</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn6">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="digitalsignaturesdialog|description">Description</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer4"/>
+ <attributes>
+ <attribute name="text">4</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn7">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="digitalsignaturesdialog|type">Signature type</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer5"/>
+ <attributes>
+ <attribute name="text">5</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="signatures-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="digitalsignaturesdialog|extended_tip|signatures">Lists the digital signatures for the current document.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButtonBox" id="buttonbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <property name="homogeneous">True</property>
+ <property name="layout_style">spread</property>
+ <child>
+ <object class="GtkButton" id="view">
+ <property name="label" translatable="yes" context="digitalsignaturesdialog|view">View Certificate...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="view-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="digitalsignaturesdialog|extended_tip|view">Opens the View Certificate dialog.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="sign">
+ <property name="label" translatable="yes" context="digitalsignaturesdialog|sign">Sign Document...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="sign-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="digitalsignaturesdialog|extended_tip|sign">Opens the Select Certificate dialog.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="remove">
+ <property name="label" translatable="yes" context="digitalsignaturesdialog|remove">Remove</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="remove-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="digitalsignaturesdialog|extended_tip|remove">Removes the selected signature from the list. Removes all subsequent signatures as well, in case of PDF.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="start_certmanager">
+ <property name="label" translatable="yes" context="digitalsignaturesdialog|start_certmanager">Start Certificate Manager...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="signed">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="issued">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="date">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="description">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="type">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">4</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="macrohint">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="digitalsignaturesdialog|macrohint">The following have signed the document macro:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="packagehint">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="digitalsignaturesdialog|packagehint">The following have signed this package:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="validft">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes" context="digitalsignaturesdialog|validft">The signatures in this document are valid</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="validimg">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="icon_name">xmlsecurity/res/signet_11x16.png</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="invalidft">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes" context="digitalsignaturesdialog|invalidft">The signatures in this document are invalid</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="oldsignatureft">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes" context="digitalsignaturesdialog|oldsignatureft">At least one signature has problems: the document is only partially signed.</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="notvalidatedft">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes" context="digitalsignaturesdialog|notvalidatedft">At least one signature has problems: the certificate could not be validated.</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="invalidimg">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="icon_name">svx/res/caution_11x16.png</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="oldsignatureimg">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="icon_name">svx/res/caution_11x16.png</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="notvalidatedimg">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="icon_name">xmlsecurity/res/notcertificate_16.png</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="adescompliant">
+ <property name="label" translatable="yes" context="digitalsignaturesdialog|adescompliant">Use AdES-compliant signature when there is a choice</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">start</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="adescompliant-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="digitalsignaturesdialog|extended_tip|adescompliant">Prefers creating XAdES signatures for ODF and OOXML, PAdES signatures for PDF.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">6</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-11">help</action-widget>
+ <action-widget response="-7">close</action-widget>
+ </action-widgets>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="DigitalSignaturesDialog-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="digitalsignaturesdialog|extended_tip|DigitalSignaturesDialog">Adds and removes digital signatures to and from your document. You can also use the dialog to view certificates.</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/xmlsecurity/uiconfig/ui/macrosecuritydialog.ui b/xmlsecurity/uiconfig/ui/macrosecuritydialog.ui
new file mode 100644
index 000000000..06699d588
--- /dev/null
+++ b/xmlsecurity/uiconfig/ui/macrosecuritydialog.ui
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="xsc">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="MacroSecurityDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="macrosecuritydialog|MacroSecurityDialog">Macro Security</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="reset">
+ <property name="label" translatable="yes" context="stock">_Reset</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="tabcontrol">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="scrollable">True</property>
+ <property name="enable_popup">True</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="SecurityLevelPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="macrosecuritydialog|SecurityLevelPage">Security Level</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="SecurityTrustPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="macrosecuritydialog|SecurityTrustPage">Trusted Sources</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="101">reset</action-widget>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/xmlsecurity/uiconfig/ui/securitylevelpage.ui b/xmlsecurity/uiconfig/ui/securitylevelpage.ui
new file mode 100644
index 000000000..9c601b494
--- /dev/null
+++ b/xmlsecurity/uiconfig/ui/securitylevelpage.ui
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="xsc">
+ <requires lib="gtk+" version="3.20"/>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="SecurityLevelPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="row_homogeneous">True</property>
+ <child>
+ <object class="GtkRadioButton" id="low">
+ <property name="label" translatable="yes" context="securitylevelpage|low">_Low (not recommended).
+All macros will be executed without confirmation.
+Use this setting only if you are certain that all documents that will be opened are safe.</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">high</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="low-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|low">A macro can be set to auto-start, and it can perform potentially damaging actions, as for example delete or rename files. This setting is not recommended when you open documents from other authors.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="med">
+ <property name="label" translatable="yes" context="securitylevelpage|med">_Medium.
+Confirmation required before executing macros from untrusted sources.</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">high</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="med-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|med">Trusted sources can be set on the Trusted Sources tab page. Signed macros from a trusted source are allowed to run. In addition, any macro from a trusted file location is allowed to run. All other macros require your confirmation.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="high">
+ <property name="label" translatable="yes" context="securitylevelpage|high">H_igh.
+Only signed macros from trusted sources are allowed to run.
+Unsigned macros are disabled.</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="high-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|high">Trusted sources can be set on the Trusted Sources tab page. Only signed macros from a trusted source are allowed to run. In addition, any macro from a trusted file location is allowed to run.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="vhigh">
+ <property name="label" translatable="yes" context="securitylevelpage|vhigh">_Very high.
+Only macros from trusted file locations are allowed to run.
+All other macros, regardless whether signed or not, are disabled.</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="hexpand">True</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">high</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="vhigh-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|vhigh">Trusted file locations can be set on the Trusted Sources tab page. Any macro from a trusted file location is allowed to run.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="vhighimg">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="icon_name">res/lock.png</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="highimg">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="icon_name">res/lock.png</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="medimg">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="icon_name">res/lock.png</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="lowimg">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="icon_name">res/lock.png</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/xmlsecurity/uiconfig/ui/securitytrustpage.ui b/xmlsecurity/uiconfig/ui/securitytrustpage.ui
new file mode 100644
index 000000000..267efa8f0
--- /dev/null
+++ b/xmlsecurity/uiconfig/ui/securitytrustpage.ui
@@ -0,0 +1,392 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="xsc">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="liststore2">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkTreeStore" id="liststore3">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name text2 -->
+ <column type="gchararray"/>
+ <!-- column-name text3 -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkBox" id="SecurityTrustPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkButtonBox" id="buttonbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">12</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="viewcert">
+ <property name="label" translatable="yes" context="securitytrustpage|viewcert">_View...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="viewcert-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|viewcert">Opens the View Certificate dialog for the selected certificate.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="removecert">
+ <property name="label" translatable="yes" context="stock">_Remove</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="removecert-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|removecert">Removes the selected certificate from the list of trusted certificates.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="certificates">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore3</property>
+ <property name="search_column">0</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn3">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="securitytrustpage|to">Issued to</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn4">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="securitytrustpage|by">Issued by</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer2"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn5">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="securitytrustpage|date">Expiration date</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer3"/>
+ <attributes>
+ <attribute name="text">2</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="certificates-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|certificates">Lists the trusted certificates.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="lockcertimg">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="icon_name">res/lock.png</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="securitytrustpage|label3">Trusted Certificates</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">12</property>
+ <property name="column_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="securitytrustpage|label8">Document macros are always executed if they have been opened from one of the following locations.</property>
+ <property name="wrap">True</property>
+ <property name="width_chars">56</property>
+ <property name="max_width_chars">56</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButtonBox" id="buttonbox2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="addfile">
+ <property name="label" translatable="yes" context="securitytrustpage|addfile">A_dd...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="addfile-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|addfile">Opens a folder selection dialog. Select a folder from which all macros are allowed to execute.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="removefile">
+ <property name="label" translatable="yes" context="stock">_Remove</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="removefile-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|removefile">Removes the selected folder from the list of trusted file locations.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="locations">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore2</property>
+ <property name="headers_visible">False</property>
+ <property name="search_column">0</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection1"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn9">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer0"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="locations-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|locations">Document macros are only executed if they have been opened from one of the following locations.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="lockfileimg">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="icon_name">res/lock.png</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="securitytrustpage|label4">Trusted File Locations</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup1">
+ <widgets>
+ <widget name="viewcert"/>
+ <widget name="addfile"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup2">
+ <property name="mode">vertical</property>
+ <widgets>
+ <widget name="certificates"/>
+ <widget name="locations"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/xmlsecurity/uiconfig/ui/selectcertificatedialog.ui b/xmlsecurity/uiconfig/ui/selectcertificatedialog.ui
new file mode 100644
index 000000000..668379055
--- /dev/null
+++ b/xmlsecurity/uiconfig/ui/selectcertificatedialog.ui
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="xsc">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="liststore3">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name text2 -->
+ <column type="gchararray"/>
+ <!-- column-name text3 -->
+ <column type="gchararray"/>
+ <!-- column-name text4 -->
+ <column type="gchararray"/>
+ <!-- column-name text5 -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkDialog" id="SelectCertificateDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="selectcertificatedialog|SelectCertificateDialog">Select X.509 Certificate</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">12</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="sign">
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="selectcertificatedialog|sign">Select the certificate you want to use for signing:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="encrypt">
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="selectcertificatedialog|encrypt">Select the certificate you want to use for encryption:</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="signatures">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore3</property>
+ <property name="search_column">0</property>
+ <property name="show_expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn3">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="selectcertificatedialog|issuedto">Issued to</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn4">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="selectcertificatedialog|issuedby">Issued by</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer2"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn5">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="selectcertificatedialog|type">Type</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer3"/>
+ <attributes>
+ <attribute name="text">2</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn6">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="selectcertificatedialog|expiration">Expiration date</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer4"/>
+ <attributes>
+ <attribute name="text">3</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn7">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="selectcertificatedialog|usage">Certificate usage</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer5"/>
+ <attributes>
+ <attribute name="text">4</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="signatures-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="selectcertificatedialog|extended_tip|signatures">Select the certificate that you want to digitally sign the current document with.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="viewcert">
+ <property name="label" translatable="yes" context="selectcertificatedialog|viewcert">View Certificate...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">end</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="viewcert-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="selectcertificatedialog|extended_tip|viewcert">Opens the View Certificate dialog where you can examine the selected certificate.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="dialog-hbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="description-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="selectcertificatedialog|label2">Description:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="description">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="description-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="selectcertificatedialog|extended_tip|description">Type a purpose for the signature.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="SelectCertificateDialog-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="selectcertificatedialog|extended_tip|SelectCertificateDialog">Select the certificate that you want to digitally sign the current document with.</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/xmlsecurity/uiconfig/ui/viewcertdialog.ui b/xmlsecurity/uiconfig/ui/viewcertdialog.ui
new file mode 100644
index 000000000..12cf4b40e
--- /dev/null
+++ b/xmlsecurity/uiconfig/ui/viewcertdialog.ui
@@ -0,0 +1,227 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="xsc">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="ViewCertDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="viewcertdialog|ViewCertDialog">View Certificate</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="tabcontrol">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="scrollable">True</property>
+ <property name="enable_popup">True</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="general">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="viewcertdialog|general">General</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="details">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="viewcertdialog|details">Details</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="path">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="viewcertdialog|path">Certification Path</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/xmlsecurity/util/xmlsecurity.component b/xmlsecurity/util/xmlsecurity.component
new file mode 100644
index 000000000..7dfe91a0d
--- /dev/null
+++ b/xmlsecurity/util/xmlsecurity.component
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.security.CertificateContainer"
+ constructor="com_sun_star_security_CertificateContainer_get_implementation">
+ <service name="com.sun.star.security.CertificateContainer"/>
+ </implementation>
+ <implementation name="com.sun.star.security.DocumentDigitalSignatures"
+ constructor="com_sun_star_security_DocumentDigitalSignatures_get_implementation">
+ <service name="com.sun.star.security.DocumentDigitalSignatures"/>
+ <optional/>
+ </implementation>
+</component>
diff --git a/xmlsecurity/util/xmlsecurity.component.dds b/xmlsecurity/util/xmlsecurity.component.dds
new file mode 100644
index 000000000..5dc5f6765
--- /dev/null
+++ b/xmlsecurity/util/xmlsecurity.component.dds
@@ -0,0 +1,7 @@
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+com.sun.star.security.DocumentDigitalSignatures
diff --git a/xmlsecurity/util/xsec_xmlsec.component b/xmlsecurity/util/xsec_xmlsec.component
new file mode 100644
index 000000000..f2b072949
--- /dev/null
+++ b/xmlsecurity/util/xsec_xmlsec.component
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.xml.crypto.NSSInitializer"
+ constructor="com_sun_star_xml_crypto_NSSInitializer_get_implementation">
+ <service name="com.sun.star.xml.crypto.NSSInitializer"/>
+ <optional/>
+ </implementation>
+ <implementation name="com.sun.star.xml.crypto.SEInitializer"
+ constructor="com_sun_star_xml_crypto_SEInitializer_get_implementation">
+ <service name="com.sun.star.xml.crypto.SEInitializer"/>
+ <optional/>
+ </implementation>
+ <implementation name="com.sun.star.xml.security.SEInitializer_Gpg"
+ constructor="com_sun_star_xml_security_SEInitializer_Gpg_get_implementation">
+ <service name="com.sun.star.xml.crypto.GPGSEInitializer"/>
+ <optional/>
+ </implementation>
+ <implementation name="com.sun.star.xml.crypto.SecurityEnvironment"
+ constructor="com_sun_star_xml_crypto_SecurityEnvironment_get_implementation">
+ <service name="com.sun.star.xml.crypto.SecurityEnvironment"/>
+ <optional/>
+ </implementation>
+ <implementation name="com.sun.star.xml.wrapper.XMLDocumentWrapper"
+ constructor="com_sun_star_xml_wrapper_XMLDocumentWrapper_get_implementation">
+ <service name="com.sun.star.xml.wrapper.XMLDocumentWrapper"/>
+ </implementation>
+ <implementation name="com.sun.star.xml.wrapper.XMLElementWrapper"
+ constructor="com_sun_star_xml_wrapper_XMLElementWrapper_get_implementation">
+ <service name="com.sun.star.xml.wrapper.XMLElementWrapper"/>
+ </implementation>
+ <implementation name="com.sun.star.xml.crypto.XMLSecurityContext"
+ constructor="com_sun_star_xml_crypto_XMLSecurityContext_get_implementation">
+ <service name="com.sun.star.xml.crypto.XMLSecurityContext"/>
+ <optional/>
+ </implementation>
+ <implementation name="com.sun.star.xml.crypto.XMLSignature"
+ constructor="com_sun_star_xml_crypto_XMLSignature_get_implementation">
+ <service name="com.sun.star.xml.crypto.XMLSignature"/>
+ <optional/>
+ </implementation>
+</component>
diff --git a/xmlsecurity/util/xsec_xmlsec.component.gpg b/xmlsecurity/util/xsec_xmlsec.component.gpg
new file mode 100644
index 000000000..c770a555b
--- /dev/null
+++ b/xmlsecurity/util/xsec_xmlsec.component.gpg
@@ -0,0 +1,7 @@
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+com.sun.star.xml.security.SEInitializer_Gpg
diff --git a/xmlsecurity/util/xsec_xmlsec.component.nss b/xmlsecurity/util/xsec_xmlsec.component.nss
new file mode 100644
index 000000000..3ff9557b9
--- /dev/null
+++ b/xmlsecurity/util/xsec_xmlsec.component.nss
@@ -0,0 +1,7 @@
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+com.sun.star.xml.crypto.NSSInitializer
diff --git a/xmlsecurity/util/xsec_xmlsec.component.nss_mscrypt b/xmlsecurity/util/xsec_xmlsec.component.nss_mscrypt
new file mode 100644
index 000000000..c713c1e83
--- /dev/null
+++ b/xmlsecurity/util/xsec_xmlsec.component.nss_mscrypt
@@ -0,0 +1,10 @@
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+com.sun.star.xml.crypto.SecurityEnvironment
+com.sun.star.xml.crypto.SEInitializer
+com.sun.star.xml.crypto.XMLSecurityContext
+com.sun.star.xml.crypto.XMLSignature
diff --git a/xmlsecurity/workben/pdfverify.cxx b/xmlsecurity/workben/pdfverify.cxx
new file mode 100644
index 000000000..f04db1fa6
--- /dev/null
+++ b/xmlsecurity/workben/pdfverify.cxx
@@ -0,0 +1,216 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <iostream>
+#include <string_view>
+
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/xml/crypto/SEInitializer.hpp>
+
+#include <comphelper/processfactory.hxx>
+#include <cppuhelper/bootstrap.hxx>
+#include <osl/file.hxx>
+#include <sal/log.hxx>
+#include <sal/main.h>
+#include <tools/diagnose_ex.h>
+#include <vcl/pngwrite.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <vcl/filter/pdfdocument.hxx>
+#include <comphelper/scopeguard.hxx>
+#include <svl/sigstruct.hxx>
+
+#include <pdfsignaturehelper.hxx>
+
+using namespace com::sun::star;
+
+namespace
+{
+/// Does PDF to PNG conversion using pdfium.
+void generatePreview(std::string_view rPdfPath, std::string_view rPngPath)
+{
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic;
+ OUString aInURL;
+ osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(rPdfPath), aInURL);
+ SvFileStream aInStream(aInURL, StreamMode::READ);
+ if (rFilter.ImportGraphic(aGraphic, u"", aInStream, GRFILTER_FORMAT_DONTKNOW, nullptr,
+ GraphicFilterImportFlags::NONE)
+ != ERRCODE_NONE)
+ return;
+
+ BitmapEx aBitmapEx = aGraphic.GetBitmapEx();
+ vcl::PNGWriter aWriter(aBitmapEx);
+ OUString aOutURL;
+ osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(rPngPath), aOutURL);
+ SvFileStream aOutStream(aOutURL, StreamMode::WRITE);
+ aWriter.Write(aOutStream);
+}
+
+int pdfVerify(int nArgc, char** pArgv)
+{
+ if (nArgc < 2)
+ {
+ SAL_WARN("xmlsecurity.workben", "not enough parameters");
+ return 1;
+ }
+
+ // Initialize nss / mscrypto.
+ uno::Reference<uno::XComponentContext> xComponentContext;
+ try
+ {
+ xComponentContext = cppu::defaultBootstrap_InitialComponentContext();
+ }
+ catch (const uno::RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION("xmlsecurity.workben",
+ "cppu::defaultBootstrap_InitialComponentContext() failed:");
+ return 1;
+ }
+ uno::Reference<lang::XMultiComponentFactory> xMultiComponentFactory
+ = xComponentContext->getServiceManager();
+ uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xMultiComponentFactory,
+ uno::UNO_QUERY);
+ comphelper::setProcessServiceFactory(xMultiServiceFactory);
+
+ InitVCL();
+ comphelper::ScopeGuard g([] { DeInitVCL(); });
+ if (nArgc > 3 && pArgv[3] == std::string_view("-p"))
+ {
+ generatePreview(pArgv[1], pArgv[2]);
+ return 0;
+ }
+
+ uno::Reference<xml::crypto::XSEInitializer> xSEInitializer;
+ try
+ {
+ xSEInitializer = xml::crypto::SEInitializer::create(xComponentContext);
+ }
+ catch (const uno::DeploymentException&)
+ {
+ TOOLS_WARN_EXCEPTION("xmlsecurity.workben",
+ "DeploymentException while creating SEInitializer:");
+ return 1;
+ }
+ uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext
+ = xSEInitializer->createSecurityContext(OUString());
+
+ OUString aInURL;
+ osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(pArgv[1]), aInURL);
+ OUString aOutURL;
+ if (nArgc > 2)
+ osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(pArgv[2]), aOutURL);
+
+ bool bRemoveSignature = false;
+ if (nArgc > 3 && pArgv[3] == std::string_view("-r"))
+ bRemoveSignature = true;
+
+ SvFileStream aStream(aInURL, StreamMode::READ);
+ if (aOutURL.isEmpty() && !bRemoveSignature)
+ {
+ std::cerr << "verifying signatures" << std::endl;
+ PDFSignatureHelper aHelper;
+ aStream.Seek(0);
+ aHelper.ReadAndVerifySignatureSvStream(aStream);
+ if (aHelper.GetSignatureInformations().empty())
+ std::cerr << "found no signatures" << std::endl;
+ else
+ {
+ std::cerr << "found " << aHelper.GetSignatureInformations().size() << " signatures"
+ << std::endl;
+ for (size_t i = 0; i < aHelper.GetSignatureInformations().size(); ++i)
+ {
+ const SignatureInformation& rInfo = aHelper.GetSignatureInformations()[i];
+ bool bSuccess
+ = rInfo.nStatus == xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED;
+ std::cerr << "signature #" << i << ": digest match? " << bSuccess << std::endl;
+ std::cerr << "signature #" << i << ": partial? " << rInfo.bPartialDocumentSignature
+ << std::endl;
+ }
+ }
+
+ return 0;
+ }
+
+ vcl::filter::PDFDocument aDocument;
+ if (!aDocument.Read(aStream))
+ {
+ SAL_WARN("xmlsecurity.workben", "failed to read the document");
+ return 1;
+ }
+
+ if (bRemoveSignature)
+ {
+ std::cerr << "removing the last signature" << std::endl;
+ std::vector<vcl::filter::PDFObjectElement*> aSignatures = aDocument.GetSignatureWidgets();
+ if (aSignatures.empty())
+ {
+ std::cerr << "found no signatures" << std::endl;
+ return 1;
+ }
+
+ size_t nPosition = aSignatures.size() - 1;
+ if (!aDocument.RemoveSignature(nPosition))
+ {
+ SAL_WARN("xmlsecurity.workben", "failed to remove signature #" << nPosition);
+ return 1;
+ }
+
+ SvFileStream aOutStream(aOutURL, StreamMode::WRITE | StreamMode::TRUNC);
+ if (!aDocument.Write(aOutStream))
+ {
+ SAL_WARN("xmlsecurity.workben", "failed to write the document");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ std::cerr << "adding a new signature" << std::endl;
+ uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment
+ = xSecurityContext->getSecurityEnvironment();
+ uno::Sequence<uno::Reference<security::XCertificate>> aCertificates
+ = xSecurityEnvironment->getPersonalCertificates();
+ if (!aCertificates.hasElements())
+ {
+ SAL_WARN("xmlsecurity.workben", "no signing certificates found");
+ return 1;
+ }
+ if (!aDocument.Sign(aCertificates[0], "pdfverify", /*bAdES=*/true))
+ {
+ SAL_WARN("xmlsecurity.workben", "failed to sign");
+ return 1;
+ }
+
+ SvFileStream aOutStream(aOutURL, StreamMode::WRITE | StreamMode::TRUNC);
+ if (!aDocument.Write(aOutStream))
+ {
+ SAL_WARN("xmlsecurity.workben", "failed to write the document");
+ return 1;
+ }
+
+ return 0;
+}
+}
+
+SAL_IMPLEMENT_MAIN_WITH_ARGS(nArgc, pArgv)
+{
+ try
+ {
+ return pdfVerify(nArgc, pArgv);
+ }
+ catch (...)
+ {
+ std::cerr << "pdfverify: uncaught exception while invoking pdfVerify()" << std::endl;
+ return 1;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */