summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2016-11-04 09:13:02 +0100
committerMiklos Vajna <vmiklos@collabora.co.uk>2016-11-04 09:13:32 +0100
commit3e610f8496a0b6ef126426b807e0af366a98b8f3 (patch)
tree52728e32275a50b2d9f61f9febb99fda49f4b9a9
parentf0167eced77657190226d24a19005a66ff7e739e (diff)
vcl: extract PDFWriter::GetDateTime() from PDFWriterImpl
And use it in xmlsecurity when signing an existing PDF. This is especially important on Windows, where the PKCS#7 blob doesn't have an (unsigned) timestamp. Change-Id: I4051dc19a43f8f8114d9f4d02309f28d6754e9ae
-rw-r--r--include/vcl/pdfwriter.hxx3
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx85
-rw-r--r--vcl/source/gdi/pdfwriter_impl.hxx2
-rw-r--r--xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx12
-rw-r--r--xmlsecurity/source/pdfio/pdfdocument.cxx6
5 files changed, 77 insertions, 31 deletions
diff --git a/include/vcl/pdfwriter.hxx b/include/vcl/pdfwriter.hxx
index 79ac5db594a5..0e059a601658 100644
--- a/include/vcl/pdfwriter.hxx
+++ b/include/vcl/pdfwriter.hxx
@@ -1270,6 +1270,9 @@ The following structure describes the permissions used in PDF security
/// Write rString as a PDF hex string into rBuffer.
static void AppendUnicodeTextString(const OUString& rString, OStringBuffer& rBuffer);
+
+ /// Get current date/time in PDF D:YYYYMMDDHHMMSS form.
+ static OString GetDateTime();
};
}
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 94c730ecb5a7..80cb0a00b798 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -1855,14 +1855,67 @@ PDFWriterImpl::~PDFWriterImpl()
void PDFWriterImpl::setupDocInfo()
{
std::vector< sal_uInt8 > aId;
+ m_aCreationDateString = PDFWriter::GetDateTime();
computeDocumentIdentifier( aId, m_aContext.DocumentInfo, m_aCreationDateString, m_aCreationMetaDateString );
if( m_aContext.Encryption.DocumentIdentifier.empty() )
m_aContext.Encryption.DocumentIdentifier = aId;
}
+OString PDFWriter::GetDateTime()
+{
+ OStringBuffer aRet;
+
+ TimeValue aTVal, aGMT;
+ oslDateTime aDT;
+ osl_getSystemTime(&aGMT);
+ osl_getLocalTimeFromSystemTime(&aGMT, &aTVal);
+ osl_getDateTimeFromTimeValue(&aTVal, &aDT);
+ aRet.append("D:");
+ aRet.append((sal_Char)('0' + ((aDT.Year / 1000) % 10)));
+ aRet.append((sal_Char)('0' + ((aDT.Year / 100) % 10)));
+ aRet.append((sal_Char)('0' + ((aDT.Year / 10) % 10)));
+ aRet.append((sal_Char)('0' + (aDT.Year % 10)));
+ aRet.append((sal_Char)('0' + ((aDT.Month / 10) % 10)));
+ aRet.append((sal_Char)('0' + (aDT.Month % 10)));
+ aRet.append((sal_Char)('0' + ((aDT.Day / 10) % 10)));
+ aRet.append((sal_Char)('0' + (aDT.Day % 10)));
+ aRet.append((sal_Char)('0' + ((aDT.Hours / 10) % 10)));
+ aRet.append((sal_Char)('0' + (aDT.Hours % 10)));
+ aRet.append((sal_Char)('0' + ((aDT.Minutes / 10) % 10)));
+ aRet.append((sal_Char)('0' + (aDT.Minutes % 10)));
+ aRet.append((sal_Char)('0' + ((aDT.Seconds / 10) % 10)));
+ aRet.append((sal_Char)('0' + (aDT.Seconds % 10)));
+
+ sal_uInt32 nDelta = 0;
+ if (aGMT.Seconds > aTVal.Seconds)
+ {
+ aRet.append("-");
+ nDelta = aGMT.Seconds-aTVal.Seconds;
+ }
+ else if (aGMT.Seconds < aTVal.Seconds)
+ {
+ aRet.append("+");
+ nDelta = aTVal.Seconds-aGMT.Seconds;
+ }
+ else
+ aRet.append("Z");
+
+ if (nDelta)
+ {
+ aRet.append((sal_Char)('0' + ((nDelta / 36000) % 10)));
+ aRet.append((sal_Char)('0' + ((nDelta / 3600) % 10)));
+ aRet.append("'");
+ aRet.append((sal_Char)('0' + ((nDelta / 600) % 6)));
+ aRet.append((sal_Char)('0' + ((nDelta / 60) % 10)));
+ }
+ aRet.append( "'" );
+
+ return aRet.makeStringAndClear();
+}
+
void PDFWriterImpl::computeDocumentIdentifier( std::vector< sal_uInt8 >& o_rIdentifier,
const vcl::PDFWriter::PDFDocInfo& i_rDocInfo,
- OString& o_rCString1,
+ const OString& i_rCString1,
OString& o_rCString2
)
{
@@ -1889,22 +1942,7 @@ void PDFWriterImpl::computeDocumentIdentifier( std::vector< sal_uInt8 >& o_rIden
osl_getSystemTime( &aGMT );
osl_getLocalTimeFromSystemTime( &aGMT, &aTVal );
osl_getDateTimeFromTimeValue( &aTVal, &aDT );
- OStringBuffer aCreationDateString(64), aCreationMetaDateString(64);
- aCreationDateString.append( "D:" );
- aCreationDateString.append( (sal_Char)('0' + ((aDT.Year/1000)%10)) );
- aCreationDateString.append( (sal_Char)('0' + ((aDT.Year/100)%10)) );
- aCreationDateString.append( (sal_Char)('0' + ((aDT.Year/10)%10)) );
- aCreationDateString.append( (sal_Char)('0' + ((aDT.Year)%10)) );
- aCreationDateString.append( (sal_Char)('0' + ((aDT.Month/10)%10)) );
- aCreationDateString.append( (sal_Char)('0' + ((aDT.Month)%10)) );
- aCreationDateString.append( (sal_Char)('0' + ((aDT.Day/10)%10)) );
- aCreationDateString.append( (sal_Char)('0' + ((aDT.Day)%10)) );
- aCreationDateString.append( (sal_Char)('0' + ((aDT.Hours/10)%10)) );
- aCreationDateString.append( (sal_Char)('0' + ((aDT.Hours)%10)) );
- aCreationDateString.append( (sal_Char)('0' + ((aDT.Minutes/10)%10)) );
- aCreationDateString.append( (sal_Char)('0' + ((aDT.Minutes)%10)) );
- aCreationDateString.append( (sal_Char)('0' + ((aDT.Seconds/10)%10)) );
- aCreationDateString.append( (sal_Char)('0' + ((aDT.Seconds)%10)) );
+ OStringBuffer aCreationMetaDateString(64);
//--> i59651, we fill the Metadata date string as well, if PDF/A is requested
// according to ISO 19005-1:2005 6.7.3 the date is corrected for
@@ -1935,41 +1973,30 @@ void PDFWriterImpl::computeDocumentIdentifier( std::vector< sal_uInt8 >& o_rIden
sal_uInt32 nDelta = 0;
if( aGMT.Seconds > aTVal.Seconds )
{
- aCreationDateString.append( "-" );
nDelta = aGMT.Seconds-aTVal.Seconds;
aCreationMetaDateString.append( "-" );
}
else if( aGMT.Seconds < aTVal.Seconds )
{
- aCreationDateString.append( "+" );
nDelta = aTVal.Seconds-aGMT.Seconds;
aCreationMetaDateString.append( "+" );
}
else
{
- aCreationDateString.append( "Z" );
aCreationMetaDateString.append( "Z" );
}
if( nDelta )
{
- aCreationDateString.append( (sal_Char)('0' + ((nDelta/36000)%10)) );
- aCreationDateString.append( (sal_Char)('0' + ((nDelta/3600)%10)) );
- aCreationDateString.append( "'" );
- aCreationDateString.append( (sal_Char)('0' + ((nDelta/600)%6)) );
- aCreationDateString.append( (sal_Char)('0' + ((nDelta/60)%10)) );
-
aCreationMetaDateString.append( (sal_Char)('0' + ((nDelta/36000)%10)) );
aCreationMetaDateString.append( (sal_Char)('0' + ((nDelta/3600)%10)) );
aCreationMetaDateString.append( ":" );
aCreationMetaDateString.append( (sal_Char)('0' + ((nDelta/600)%6)) );
aCreationMetaDateString.append( (sal_Char)('0' + ((nDelta/60)%10)) );
}
- aCreationDateString.append( "'" );
- aID.append( aCreationDateString.getStr(), aCreationDateString.getLength() );
+ aID.append( i_rCString1.getStr(), i_rCString1.getLength() );
aInfoValuesOut = aID.makeStringAndClear();
- o_rCString1 = aCreationDateString.makeStringAndClear();
o_rCString2 = aCreationMetaDateString.makeStringAndClear();
rtlDigest aDigest = rtl_digest_createMD5();
diff --git a/vcl/source/gdi/pdfwriter_impl.hxx b/vcl/source/gdi/pdfwriter_impl.hxx
index a49b6200eaa8..16f1fbd7f24c 100644
--- a/vcl/source/gdi/pdfwriter_impl.hxx
+++ b/vcl/source/gdi/pdfwriter_impl.hxx
@@ -972,7 +972,7 @@ i12626
static void computeDocumentIdentifier( std::vector< sal_uInt8 >& o_rIdentifier,
const vcl::PDFWriter::PDFDocInfo& i_rDocInfo,
- OString& o_rCString1,
+ const OString& i_rCString1,
OString& o_rCString2
);
static sal_Int32 computeAccessPermissions( const vcl::PDFWriter::PDFEncryptionProperties& i_rProperties,
diff --git a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
index 49da58a2fbcd..5a95586e072b 100644
--- a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
+++ b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx
@@ -12,6 +12,7 @@
#include <comphelper/processfactory.hxx>
#include <osl/file.hxx>
#include <test/bootstrapfixture.hxx>
+#include <tools/datetime.hxx>
#include <unotools/streamwrap.hxx>
#include <unotools/ucbstreamhelper.hxx>
@@ -152,7 +153,16 @@ void PDFSigningTest::testPDFAdd()
OUString aInURL = aSourceDir + "no.pdf";
OUString aTargetDir = m_directories.getURLFromWorkdir("/CppunitTest/xmlsecurity_pdfsigning.test.user/");
OUString aOutURL = aTargetDir + "add.pdf";
- sign(aInURL, aOutURL, 0);
+ bool bHadCertificates = sign(aInURL, aOutURL, 0);
+
+ if (bHadCertificates)
+ {
+ // Make sure the timestamp is correct.
+ std::vector<SignatureInformation> aInfos = verify(aOutURL, 1);
+ 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(static_cast<sal_Int16>(aDateTime.GetYear()), aInfos[0].stDateTime.Year);
+ }
}
void PDFSigningTest::testPDFAdd2()
diff --git a/xmlsecurity/source/pdfio/pdfdocument.cxx b/xmlsecurity/source/pdfio/pdfdocument.cxx
index 31ac58576469..6822e149c47b 100644
--- a/xmlsecurity/source/pdfio/pdfdocument.cxx
+++ b/xmlsecurity/source/pdfio/pdfdocument.cxx
@@ -356,6 +356,12 @@ bool PDFDocument::Sign(const uno::Reference<security::XCertificate>& xCertificat
comphelper::string::padToLength(aContentFiller, MAX_SIGNATURE_CONTENT_LENGTH, '0');
aSigBuffer.append(aContentFiller.makeStringAndClear());
aSigBuffer.append(">\n/Type/Sig/SubFilter/adbe.pkcs7.detached");
+
+ // Time of signing.
+ aSigBuffer.append(" /M (");
+ aSigBuffer.append(vcl::PDFWriter::GetDateTime());
+ aSigBuffer.append(")");
+
// Byte range: we can write offset1-length1 and offset2 right now, will
// write length2 later.
aSigBuffer.append(" /ByteRange [ 0 ");