xmlsecurity PDF sign: fix removing non-last signatures
PDF signatures are always chained, so when removing a signature not only
the item at a given position should be removed on the UI, but the whole
position-last range.
Change-Id: I76b14308885267cdac994fa957218a8b7df6b3cf
diff --git a/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf b/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf
new file mode 100644
index 0000000..af668fc
--- /dev/null
+++ b/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf
Binary files differ
diff --git a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
index a2980db..4442ac5 100644
--- a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
+++ b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
@@ -12,7 +12,10 @@
#include <comphelper/processfactory.hxx>
#include <osl/file.hxx>
#include <test/bootstrapfixture.hxx>
#include <unotools/streamwrap.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <documentsignaturemanager.hxx>
#include <pdfio/pdfdocument.hxx>
using namespace com::sun::star;
@@ -42,13 +45,16 @@ public:
void testPDFAdd();
/// Test signing a previously unsigned file twice.
void testPDFAdd2();
/// Test remove a signature from a previously signed file.
/// Test removing a signature from a previously signed file.
void testPDFRemove();
/// Test removing all signatures from a previously multi-signed file.
void testPDFRemoveAll();
CPPUNIT_TEST_SUITE(PDFSigningTest);
CPPUNIT_TEST(testPDFAdd);
CPPUNIT_TEST(testPDFAdd2);
CPPUNIT_TEST(testPDFRemove);
CPPUNIT_TEST(testPDFRemoveAll);
CPPUNIT_TEST_SUITE_END();
};
@@ -187,6 +193,38 @@ void PDFSigningTest::testPDFRemove()
}
#endif
}
void PDFSigningTest::testPDFRemoveAll()
{
#ifndef _WIN32
// 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("/CppunitTest/xmlsecurity_signing.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, SignatureModeDocumentContent);
SvStream* pStream = utl::UcbStreamHelper::CreateStream(aOutURL, StreamMode::READ | StreamMode::WRITE);
uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(*pStream));
aManager.mxSignatureStream = xStream;
aManager.read(/*bUseTempStream=*/false);
std::vector<SignatureInformation>& rInformations = aManager.maCurrentSignatureInformations;
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());
#endif
}
CPPUNIT_TEST_SUITE_REGISTRATION(PDFSigningTest);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/xmlsecurity/source/helper/documentsignaturemanager.cxx b/xmlsecurity/source/helper/documentsignaturemanager.cxx
index 0a5568f..dee86c8 100644
--- a/xmlsecurity/source/helper/documentsignaturemanager.cxx
+++ b/xmlsecurity/source/helper/documentsignaturemanager.cxx
@@ -317,14 +317,15 @@ void DocumentSignatureManager::remove(sal_uInt16 nPosition)
{
// Something not ZIP based, try PDF.
uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY);
if (PDFSignatureHelper::RemoveSignature(xInputStream, nPosition))
if (!PDFSignatureHelper::RemoveSignature(xInputStream, nPosition))
{
SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::RemoveSignature() failed");
return;
}
// Only erase when the removal was successfull, it may fail for PDF.
maCurrentSignatureInformations.erase(maCurrentSignatureInformations.begin() + nPosition);
// 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;
}