Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / package / source / manifest / ManifestExport.cxx
blob7e55a28147d90a2aadc66eeb52fd9ce9ee517d75
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
21 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
22 #include <com/sun/star/xml/sax/XAttributeList.hpp>
23 #include <com/sun/star/xml/crypto/DigestID.hpp>
24 #include <com/sun/star/xml/crypto/CipherID.hpp>
25 #include <com/sun/star/beans/PropertyValue.hpp>
26 #include <com/sun/star/uno/RuntimeException.hpp>
28 #include <ManifestDefines.hxx>
29 #include <ManifestExport.hxx>
30 #include <sax/tools/converter.hxx>
32 #include <rtl/ustrbuf.hxx>
33 #include <comphelper/documentconstants.hxx>
34 #include <comphelper/attributelist.hxx>
36 using namespace ::com::sun::star;
38 ManifestExport::ManifestExport( uno::Reference< xml::sax::XDocumentHandler > xHandler, const uno::Sequence< uno::Sequence < beans::PropertyValue > >& rManList )
40 const OUString sFileEntryElement ( ELEMENT_FILE_ENTRY );
41 const OUString sManifestElement ( ELEMENT_MANIFEST );
42 const OUString sEncryptionDataElement( ELEMENT_ENCRYPTION_DATA );
43 const OUString sAlgorithmElement ( ELEMENT_ALGORITHM );
44 const OUString sStartKeyGenerationElement ( ELEMENT_START_KEY_GENERATION );
45 const OUString sKeyDerivationElement ( ELEMENT_KEY_DERIVATION );
47 const OUString sCdataAttribute ( ATTRIBUTE_CDATA );
48 const OUString sMediaTypeAttribute ( ATTRIBUTE_MEDIA_TYPE );
49 const OUString sVersionAttribute ( ATTRIBUTE_VERSION );
50 const OUString sFullPathAttribute ( ATTRIBUTE_FULL_PATH );
51 const OUString sSizeAttribute ( ATTRIBUTE_SIZE );
52 const OUString sKeySizeAttribute ( ATTRIBUTE_KEY_SIZE );
53 const OUString sSaltAttribute ( ATTRIBUTE_SALT );
54 const OUString sInitialisationVectorAttribute ( ATTRIBUTE_INITIALISATION_VECTOR );
55 const OUString sIterationCountAttribute ( ATTRIBUTE_ITERATION_COUNT );
56 const OUString sAlgorithmNameAttribute ( ATTRIBUTE_ALGORITHM_NAME );
57 const OUString sStartKeyGenerationNameAttribute ( ATTRIBUTE_START_KEY_GENERATION_NAME );
58 const OUString sKeyDerivationNameAttribute ( ATTRIBUTE_KEY_DERIVATION_NAME );
59 const OUString sChecksumTypeAttribute ( ATTRIBUTE_CHECKSUM_TYPE );
60 const OUString sChecksumAttribute ( ATTRIBUTE_CHECKSUM);
62 const OUString sFullPathProperty ( "FullPath" );
63 const OUString sVersionProperty ( "Version" );
64 const OUString sMediaTypeProperty ( "MediaType" );
65 const OUString sIterationCountProperty ( "IterationCount" );
66 const OUString sDerivedKeySizeProperty ( "DerivedKeySize" );
67 const OUString sSaltProperty ( "Salt" );
68 const OUString sInitialisationVectorProperty( "InitialisationVector" );
69 const OUString sSizeProperty ( "Size" );
70 const OUString sDigestProperty ( "Digest" );
71 const OUString sEncryptionAlgProperty ( "EncryptionAlgorithm" );
72 const OUString sStartKeyAlgProperty ( "StartKeyAlgorithm" );
73 const OUString sDigestAlgProperty ( "DigestAlgorithm" );
75 const OUString sWhiteSpace ( " " );
77 const OUString sSHA256_URL ( SHA256_URL );
78 const OUString sSHA1_Name ( SHA1_NAME );
80 const OUString sSHA1_1k_Name ( SHA1_1K_NAME );
81 const OUString sSHA256_1k_URL ( SHA256_1K_URL );
83 const OUString sBlowfish_Name ( BLOWFISH_NAME );
84 const OUString sAES256_URL ( AES256_URL );
86 const OUString sPBKDF2_Name ( PBKDF2_NAME );
88 ::comphelper::AttributeList * pRootAttrList = new ::comphelper::AttributeList;
89 const uno::Sequence < beans::PropertyValue > *pSequence = rManList.getConstArray();
90 const sal_uInt32 nManLength = rManList.getLength();
92 // find the mediatype of the document if any
93 OUString aDocMediaType;
94 OUString aDocVersion;
95 for (sal_uInt32 nInd = 0; nInd < nManLength ; nInd++ )
97 OUString aMediaType;
98 OUString aPath;
99 OUString aVersion;
101 const beans::PropertyValue *pValue = pSequence[nInd].getConstArray();
102 for (sal_uInt32 j = 0, nNum = pSequence[nInd].getLength(); j < nNum; j++, pValue++)
104 if (pValue->Name.equals (sMediaTypeProperty) )
106 pValue->Value >>= aMediaType;
108 else if (pValue->Name.equals (sFullPathProperty) )
110 pValue->Value >>= aPath;
112 else if (pValue->Name.equals (sVersionProperty) )
114 pValue->Value >>= aVersion;
117 if ( !aPath.isEmpty() && !aMediaType.isEmpty() && !aVersion.isEmpty() )
118 break;
121 if ( aPath == "/" )
123 aDocMediaType = aMediaType;
124 aDocVersion = aVersion;
125 break;
129 sal_Bool bProvideDTD = sal_False;
130 sal_Bool bAcceptNonemptyVersion = sal_False;
131 sal_Bool bStoreStartKeyGeneration = sal_False;
132 if ( !aDocMediaType.isEmpty() )
134 if ( aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII
135 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_TEXT_WEB_ASCII
136 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_ASCII
137 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_ASCII
138 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII
139 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII
140 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_CHART_ASCII
141 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_DATABASE_ASCII
142 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_ASCII
143 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_TEXT_TEMPLATE_ASCII
144 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_TEMPLATE_ASCII
145 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE_ASCII
146 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_TEMPLATE_ASCII
147 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_CHART_TEMPLATE_ASCII
148 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_TEMPLATE_ASCII )
151 // oasis format
152 pRootAttrList->AddAttribute ( ATTRIBUTE_XMLNS,
153 sCdataAttribute,
154 MANIFEST_OASIS_NAMESPACE );
155 bAcceptNonemptyVersion = sal_True;
156 if ( aDocVersion.compareTo( ODFVER_012_TEXT ) >= 0 )
158 // this is ODF12 generation, let encrypted streams contain start-key-generation entry
159 bStoreStartKeyGeneration = sal_True;
160 pRootAttrList->AddAttribute ( sVersionAttribute, sCdataAttribute, aDocVersion );
163 else
165 // even if it is no SO6 format the namespace must be specified
166 // thus SO6 format is used as default one
167 pRootAttrList->AddAttribute ( ATTRIBUTE_XMLNS,
168 sCdataAttribute,
169 MANIFEST_NAMESPACE );
171 bProvideDTD = sal_True;
175 uno::Reference < xml::sax::XAttributeList > xRootAttrList (pRootAttrList);
177 xHandler->startDocument();
178 uno::Reference < xml::sax::XExtendedDocumentHandler > xExtHandler ( xHandler, uno::UNO_QUERY );
179 if ( xExtHandler.is() && bProvideDTD )
181 OUString aDocType ( MANIFEST_DOCTYPE );
182 xExtHandler->unknown ( aDocType );
183 xHandler->ignorableWhitespace ( sWhiteSpace );
185 xHandler->startElement( sManifestElement, xRootAttrList );
187 for (sal_uInt32 i = 0 ; i < nManLength ; i++)
189 ::comphelper::AttributeList *pAttrList = new ::comphelper::AttributeList;
190 const beans::PropertyValue *pValue = pSequence[i].getConstArray();
191 OUString aString;
192 const uno::Any *pVector = NULL, *pSalt = NULL, *pIterationCount = NULL, *pDigest = NULL, *pDigestAlg = NULL, *pEncryptAlg = NULL, *pStartKeyAlg = NULL, *pDerivedKeySize = NULL;
193 for (sal_uInt32 j = 0, nNum = pSequence[i].getLength(); j < nNum; j++, pValue++)
195 if (pValue->Name.equals (sMediaTypeProperty) )
197 pValue->Value >>= aString;
198 pAttrList->AddAttribute ( sMediaTypeAttribute, sCdataAttribute, aString );
200 else if (pValue->Name.equals (sVersionProperty) )
202 pValue->Value >>= aString;
203 // the version is stored only if it is not empty
204 if ( bAcceptNonemptyVersion && !aString.isEmpty() )
205 pAttrList->AddAttribute ( sVersionAttribute, sCdataAttribute, aString );
207 else if (pValue->Name.equals (sFullPathProperty) )
209 pValue->Value >>= aString;
210 pAttrList->AddAttribute ( sFullPathAttribute, sCdataAttribute, aString );
212 else if (pValue->Name.equals (sSizeProperty) )
214 sal_Int64 nSize = 0;
215 pValue->Value >>= nSize;
216 OUStringBuffer aBuffer;
217 aBuffer.append ( nSize );
218 pAttrList->AddAttribute ( sSizeAttribute, sCdataAttribute, aBuffer.makeStringAndClear() );
220 else if (pValue->Name.equals (sInitialisationVectorProperty) )
221 pVector = &pValue->Value;
222 else if (pValue->Name.equals (sSaltProperty) )
223 pSalt = &pValue->Value;
224 else if (pValue->Name.equals (sIterationCountProperty) )
225 pIterationCount = &pValue->Value;
226 else if (pValue->Name.equals ( sDigestProperty ) )
227 pDigest = &pValue->Value;
228 else if (pValue->Name.equals ( sDigestAlgProperty ) )
229 pDigestAlg = &pValue->Value;
230 else if (pValue->Name.equals ( sEncryptionAlgProperty ) )
231 pEncryptAlg = &pValue->Value;
232 else if (pValue->Name.equals ( sStartKeyAlgProperty ) )
233 pStartKeyAlg = &pValue->Value;
234 else if (pValue->Name.equals ( sDerivedKeySizeProperty ) )
235 pDerivedKeySize = &pValue->Value;
238 xHandler->ignorableWhitespace ( sWhiteSpace );
239 uno::Reference < xml::sax::XAttributeList > xAttrList ( pAttrList );
240 xHandler->startElement( sFileEntryElement , xAttrList);
241 if ( pVector && pSalt && pIterationCount && pDigest && pDigestAlg && pEncryptAlg && pStartKeyAlg && pDerivedKeySize )
243 // ==== Encryption Data
244 ::comphelper::AttributeList * pNewAttrList = new ::comphelper::AttributeList;
245 uno::Reference < xml::sax::XAttributeList > xNewAttrList (pNewAttrList);
246 OUStringBuffer aBuffer;
247 uno::Sequence < sal_Int8 > aSequence;
249 xHandler->ignorableWhitespace ( sWhiteSpace );
251 // ==== Digest
252 OUString sChecksumType;
253 sal_Int32 nDigestAlgID = 0;
254 *pDigestAlg >>= nDigestAlgID;
255 if ( nDigestAlgID == xml::crypto::DigestID::SHA256_1K )
256 sChecksumType = sSHA256_1k_URL;
257 else if ( nDigestAlgID == xml::crypto::DigestID::SHA1_1K )
258 sChecksumType = sSHA1_1k_Name;
259 else
260 throw uno::RuntimeException( OSL_LOG_PREFIX "Unexpected digest algorithm is provided!", uno::Reference< uno::XInterface >() );
262 pNewAttrList->AddAttribute ( sChecksumTypeAttribute, sCdataAttribute, sChecksumType );
263 *pDigest >>= aSequence;
264 ::sax::Converter::encodeBase64(aBuffer, aSequence);
265 pNewAttrList->AddAttribute ( sChecksumAttribute, sCdataAttribute, aBuffer.makeStringAndClear() );
267 xHandler->startElement( sEncryptionDataElement , xNewAttrList);
269 // ==== Algorithm
270 pNewAttrList = new ::comphelper::AttributeList;
271 xNewAttrList = pNewAttrList;
273 sal_Int32 nEncAlgID = 0;
274 sal_Int32 nDerivedKeySize = 0;
275 *pEncryptAlg >>= nEncAlgID;
276 *pDerivedKeySize >>= nDerivedKeySize;
278 OUString sEncAlgName;
279 if ( nEncAlgID == xml::crypto::CipherID::AES_CBC_W3C_PADDING )
281 OSL_ENSURE( nDerivedKeySize, "Unexpected key size is provided!" );
282 if ( nDerivedKeySize != 32 )
283 throw uno::RuntimeException( OSL_LOG_PREFIX "Unexpected key size is provided!", uno::Reference< uno::XInterface >() );
285 sEncAlgName = sAES256_URL;
287 else if ( nEncAlgID == xml::crypto::CipherID::BLOWFISH_CFB_8 )
289 sEncAlgName = sBlowfish_Name;
291 else
292 throw uno::RuntimeException( OSL_LOG_PREFIX "Unexpected encryption algorithm is provided!", uno::Reference< uno::XInterface >() );
294 pNewAttrList->AddAttribute ( sAlgorithmNameAttribute, sCdataAttribute, sEncAlgName );
296 *pVector >>= aSequence;
297 ::sax::Converter::encodeBase64(aBuffer, aSequence);
298 pNewAttrList->AddAttribute ( sInitialisationVectorAttribute, sCdataAttribute, aBuffer.makeStringAndClear() );
300 xHandler->ignorableWhitespace ( sWhiteSpace );
301 xHandler->startElement( sAlgorithmElement , xNewAttrList);
302 xHandler->ignorableWhitespace ( sWhiteSpace );
303 xHandler->endElement( sAlgorithmElement );
305 // ==== Key Derivation
306 pNewAttrList = new ::comphelper::AttributeList;
307 xNewAttrList = pNewAttrList;
309 pNewAttrList->AddAttribute ( sKeyDerivationNameAttribute, sCdataAttribute, sPBKDF2_Name );
311 if ( bStoreStartKeyGeneration )
313 aBuffer.append( nDerivedKeySize );
314 pNewAttrList->AddAttribute ( sKeySizeAttribute, sCdataAttribute, aBuffer.makeStringAndClear() );
317 sal_Int32 nCount = 0;
318 *pIterationCount >>= nCount;
319 aBuffer.append (nCount);
320 pNewAttrList->AddAttribute ( sIterationCountAttribute, sCdataAttribute, aBuffer.makeStringAndClear() );
322 *pSalt >>= aSequence;
323 ::sax::Converter::encodeBase64(aBuffer, aSequence);
324 pNewAttrList->AddAttribute ( sSaltAttribute, sCdataAttribute, aBuffer.makeStringAndClear() );
326 xHandler->ignorableWhitespace ( sWhiteSpace );
327 xHandler->startElement( sKeyDerivationElement , xNewAttrList);
328 xHandler->ignorableWhitespace ( sWhiteSpace );
329 xHandler->endElement( sKeyDerivationElement );
331 // we have to store start-key-generation element as the last one to workaround the parsing problem
332 // in OOo3.1 and older versions
333 if ( bStoreStartKeyGeneration )
335 // ==== Start Key Generation
336 pNewAttrList = new ::comphelper::AttributeList;
337 xNewAttrList = pNewAttrList;
339 OUString sStartKeyAlg;
340 OUString sStartKeySize;
341 sal_Int32 nStartKeyAlgID = 0;
342 *pStartKeyAlg >>= nStartKeyAlgID;
343 if ( nStartKeyAlgID == xml::crypto::DigestID::SHA256 )
345 sStartKeyAlg = sSHA256_URL;
346 aBuffer.append( (sal_Int32)32 );
347 sStartKeySize = aBuffer.makeStringAndClear();
349 else if ( nStartKeyAlgID == xml::crypto::DigestID::SHA1 )
351 sStartKeyAlg = sSHA1_Name;
352 aBuffer.append( (sal_Int32)20 );
353 sStartKeySize = aBuffer.makeStringAndClear();
355 else
356 throw uno::RuntimeException( OSL_LOG_PREFIX "Unexpected start key algorithm is provided!", uno::Reference< uno::XInterface >() );
358 pNewAttrList->AddAttribute ( sStartKeyGenerationNameAttribute, sCdataAttribute, sStartKeyAlg );
359 pNewAttrList->AddAttribute ( sKeySizeAttribute, sCdataAttribute, sStartKeySize );
361 xHandler->ignorableWhitespace ( sWhiteSpace );
362 xHandler->startElement( sStartKeyGenerationElement , xNewAttrList);
363 xHandler->ignorableWhitespace ( sWhiteSpace );
364 xHandler->endElement( sStartKeyGenerationElement );
367 xHandler->ignorableWhitespace ( sWhiteSpace );
368 xHandler->endElement( sEncryptionDataElement );
370 xHandler->ignorableWhitespace ( sWhiteSpace );
371 xHandler->endElement( sFileEntryElement );
373 xHandler->ignorableWhitespace ( sWhiteSpace );
374 xHandler->endElement( sManifestElement );
375 xHandler->endDocument();
378 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */