1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 // MARKER( update_precomp.py ): autogen include statement, do not remove
21 #include <ManifestImport.hxx>
22 #include <ManifestDefines.hxx>
23 #include <sax/tools/converter.hxx>
24 #include <com/sun/star/xml/sax/XAttributeList.hpp>
25 #include <com/sun/star/xml/crypto/DigestID.hpp>
26 #include <com/sun/star/xml/crypto/CipherID.hpp>
27 #include <com/sun/star/beans/PropertyValue.hpp>
29 using namespace com::sun::star::uno
;
30 using namespace com::sun::star::beans
;
31 using namespace com::sun::star
;
35 // ---------------------------------------------------
36 ManifestImport::ManifestImport( vector
< Sequence
< PropertyValue
> > & rNewManVector
)
37 : bIgnoreEncryptData ( sal_False
)
38 , nDerivedKeySize( 0 )
39 , rManVector ( rNewManVector
)
41 , sFileEntryElement ( ELEMENT_FILE_ENTRY
)
42 , sManifestElement ( ELEMENT_MANIFEST
)
43 , sEncryptionDataElement( ELEMENT_ENCRYPTION_DATA
)
44 , sAlgorithmElement ( ELEMENT_ALGORITHM
)
45 , sStartKeyAlgElement ( ELEMENT_START_KEY_GENERATION
)
46 , sKeyDerivationElement( ELEMENT_KEY_DERIVATION
)
48 , sCdataAttribute ( ATTRIBUTE_CDATA
)
49 , sMediaTypeAttribute ( ATTRIBUTE_MEDIA_TYPE
)
50 , sVersionAttribute ( ATTRIBUTE_VERSION
)
51 , sFullPathAttribute ( ATTRIBUTE_FULL_PATH
)
52 , sSizeAttribute ( ATTRIBUTE_SIZE
)
53 , sSaltAttribute ( ATTRIBUTE_SALT
)
54 , sInitialisationVectorAttribute ( ATTRIBUTE_INITIALISATION_VECTOR
)
55 , sIterationCountAttribute ( ATTRIBUTE_ITERATION_COUNT
)
56 , sKeySizeAttribute ( ATTRIBUTE_KEY_SIZE
)
57 , sAlgorithmNameAttribute ( ATTRIBUTE_ALGORITHM_NAME
)
58 , sStartKeyAlgNameAttribute ( ATTRIBUTE_START_KEY_GENERATION_NAME
)
59 , sKeyDerivationNameAttribute ( ATTRIBUTE_KEY_DERIVATION_NAME
)
60 , sChecksumAttribute ( ATTRIBUTE_CHECKSUM
)
61 , sChecksumTypeAttribute ( ATTRIBUTE_CHECKSUM_TYPE
)
63 , sFullPathProperty ( "FullPath" )
64 , sMediaTypeProperty ( "MediaType" )
65 , sVersionProperty ( "Version" )
66 , sIterationCountProperty ( "IterationCount" )
67 , sDerivedKeySizeProperty ( "DerivedKeySize" )
68 , sSaltProperty ( "Salt" )
69 , sInitialisationVectorProperty ( "InitialisationVector" )
70 , sSizeProperty ( "Size" )
71 , sDigestProperty ( "Digest" )
72 , sEncryptionAlgProperty ( "EncryptionAlgorithm" )
73 , sStartKeyAlgProperty ( "StartKeyAlgorithm" )
74 , sDigestAlgProperty ( "DigestAlgorithm" )
78 , sSHA256_URL ( SHA256_URL
)
79 , sSHA1_Name ( SHA1_NAME
)
80 , sSHA1_URL ( SHA1_URL
)
82 , sSHA256_1k_URL ( SHA256_1K_URL
)
83 , sSHA1_1k_Name ( SHA1_1K_NAME
)
84 , sSHA1_1k_URL ( SHA1_1K_URL
)
86 , sBlowfish_Name ( BLOWFISH_NAME
)
87 , sBlowfish_URL ( BLOWFISH_URL
)
88 , sAES128_URL ( AES128_URL
)
89 , sAES192_URL ( AES192_URL
)
90 , sAES256_URL ( AES256_URL
)
92 , sPBKDF2_Name ( PBKDF2_NAME
)
93 , sPBKDF2_URL ( PBKDF2_URL
)
98 // ---------------------------------------------------
99 ManifestImport::~ManifestImport ( void )
103 // ---------------------------------------------------
104 void SAL_CALL
ManifestImport::startDocument( )
105 throw( xml::sax::SAXException
, uno::RuntimeException
)
109 // ---------------------------------------------------
110 void SAL_CALL
ManifestImport::endDocument( )
111 throw( xml::sax::SAXException
, uno::RuntimeException
)
115 void ManifestImport::doFileEntry(StringHashMap
&rConvertedAttribs
)
116 throw( uno::RuntimeException
)
118 aSequence
.resize(PKG_SIZE_ENCR_MNFST
);
120 aSequence
[PKG_MNFST_FULLPATH
].Name
= sFullPathProperty
;
121 aSequence
[PKG_MNFST_FULLPATH
].Value
<<= rConvertedAttribs
[sFullPathAttribute
];
122 aSequence
[PKG_MNFST_MEDIATYPE
].Name
= sMediaTypeProperty
;
123 aSequence
[PKG_MNFST_MEDIATYPE
].Value
<<= rConvertedAttribs
[sMediaTypeAttribute
];
125 OUString sVersion
= rConvertedAttribs
[sVersionAttribute
];
126 if ( sVersion
.getLength() )
128 aSequence
[PKG_MNFST_VERSION
].Name
= sVersionProperty
;
129 aSequence
[PKG_MNFST_VERSION
].Value
<<= sVersion
;
132 OUString sSize
= rConvertedAttribs
[sSizeAttribute
];
133 if ( sSize
.getLength() )
135 sal_Int64 nSize
= sSize
.toInt64();
136 aSequence
[PKG_MNFST_UCOMPSIZE
].Name
= sSizeProperty
;
137 aSequence
[PKG_MNFST_UCOMPSIZE
].Value
<<= nSize
;
141 void ManifestImport::doEncryptionData(StringHashMap
&rConvertedAttribs
)
142 throw( uno::RuntimeException
)
144 // If this element exists, then this stream is encrypted and we need
145 // to import the initialisation vector, salt and iteration count used
147 OUString aString
= rConvertedAttribs
[sChecksumTypeAttribute
];
148 if ( !bIgnoreEncryptData
)
150 if ( aString
.equals( sSHA1_1k_Name
) || aString
.equals( sSHA1_1k_URL
) )
152 aSequence
[PKG_MNFST_DIGESTALG
].Name
= sDigestAlgProperty
;
153 aSequence
[PKG_MNFST_DIGESTALG
].Value
<<= xml::crypto::DigestID::SHA1_1K
;
155 else if ( aString
.equals( sSHA256_1k_URL
) )
157 aSequence
[PKG_MNFST_DIGESTALG
].Name
= sDigestAlgProperty
;
158 aSequence
[PKG_MNFST_DIGESTALG
].Value
<<= xml::crypto::DigestID::SHA256_1K
;
161 bIgnoreEncryptData
= sal_True
;
163 if ( !bIgnoreEncryptData
)
165 aString
= rConvertedAttribs
[sChecksumAttribute
];
166 uno::Sequence
< sal_Int8
> aDecodeBuffer
;
167 ::sax::Converter::decodeBase64(aDecodeBuffer
, aString
);
168 aSequence
[PKG_MNFST_DIGEST
].Name
= sDigestProperty
;
169 aSequence
[PKG_MNFST_DIGEST
].Value
<<= aDecodeBuffer
;
174 void ManifestImport::doAlgorithm(StringHashMap
&rConvertedAttribs
)
175 throw( uno::RuntimeException
)
177 if ( !bIgnoreEncryptData
)
179 OUString aString
= rConvertedAttribs
[sAlgorithmNameAttribute
];
180 if ( aString
.equals( sBlowfish_Name
) || aString
.equals( sBlowfish_URL
) )
182 aSequence
[PKG_MNFST_ENCALG
].Name
= sEncryptionAlgProperty
;
183 aSequence
[PKG_MNFST_ENCALG
].Value
<<= xml::crypto::CipherID::BLOWFISH_CFB_8
;
185 else if ( aString
.equals( sAES256_URL
) )
187 aSequence
[PKG_MNFST_ENCALG
].Name
= sEncryptionAlgProperty
;
188 aSequence
[PKG_MNFST_ENCALG
].Value
<<= xml::crypto::CipherID::AES_CBC_W3C_PADDING
;
189 OSL_ENSURE( !nDerivedKeySize
|| nDerivedKeySize
== 32, "Unexpected derived key length!" );
190 nDerivedKeySize
= 32;
192 else if ( aString
.equals( sAES192_URL
) )
194 aSequence
[PKG_MNFST_ENCALG
].Name
= sEncryptionAlgProperty
;
195 aSequence
[PKG_MNFST_ENCALG
].Value
<<= xml::crypto::CipherID::AES_CBC_W3C_PADDING
;
196 OSL_ENSURE( !nDerivedKeySize
|| nDerivedKeySize
== 24, "Unexpected derived key length!" );
197 nDerivedKeySize
= 24;
199 else if ( aString
.equals( sAES128_URL
) )
201 aSequence
[PKG_MNFST_ENCALG
].Name
= sEncryptionAlgProperty
;
202 aSequence
[PKG_MNFST_ENCALG
].Value
<<= xml::crypto::CipherID::AES_CBC_W3C_PADDING
;
203 OSL_ENSURE( !nDerivedKeySize
|| nDerivedKeySize
== 16, "Unexpected derived key length!" );
204 nDerivedKeySize
= 16;
207 bIgnoreEncryptData
= sal_True
;
209 if ( !bIgnoreEncryptData
)
211 aString
= rConvertedAttribs
[sInitialisationVectorAttribute
];
212 uno::Sequence
< sal_Int8
> aDecodeBuffer
;
213 ::sax::Converter::decodeBase64(aDecodeBuffer
, aString
);
214 aSequence
[PKG_MNFST_INIVECTOR
].Name
= sInitialisationVectorProperty
;
215 aSequence
[PKG_MNFST_INIVECTOR
].Value
<<= aDecodeBuffer
;
220 void ManifestImport::doKeyDerivation(StringHashMap
&rConvertedAttribs
)
221 throw( uno::RuntimeException
)
223 if ( !bIgnoreEncryptData
)
225 OUString aString
= rConvertedAttribs
[sKeyDerivationNameAttribute
];
226 if ( aString
.equals( sPBKDF2_Name
) || aString
.equals( sPBKDF2_URL
) )
228 aString
= rConvertedAttribs
[sSaltAttribute
];
229 uno::Sequence
< sal_Int8
> aDecodeBuffer
;
230 ::sax::Converter::decodeBase64(aDecodeBuffer
, aString
);
231 aSequence
[PKG_MNFST_SALT
].Name
= sSaltProperty
;
232 aSequence
[PKG_MNFST_SALT
].Value
<<= aDecodeBuffer
;
234 aString
= rConvertedAttribs
[sIterationCountAttribute
];
235 aSequence
[PKG_MNFST_ITERATION
].Name
= sIterationCountProperty
;
236 aSequence
[PKG_MNFST_ITERATION
].Value
<<= aString
.toInt32();
238 aString
= rConvertedAttribs
[sKeySizeAttribute
];
239 if ( aString
.getLength() )
241 sal_Int32 nKey
= aString
.toInt32();
242 OSL_ENSURE( !nDerivedKeySize
|| nKey
== nDerivedKeySize
, "Provided derived key length differs from the expected one!" );
243 nDerivedKeySize
= nKey
;
245 else if ( !nDerivedKeySize
)
246 nDerivedKeySize
= 16;
247 else if ( nDerivedKeySize
!= 16 )
248 OSL_ENSURE( sal_False
, "Default derived key length differs from the expected one!" );
250 aSequence
[PKG_MNFST_DERKEYSIZE
].Name
= sDerivedKeySizeProperty
;
251 aSequence
[PKG_MNFST_DERKEYSIZE
].Value
<<= nDerivedKeySize
;
254 bIgnoreEncryptData
= sal_True
;
258 void ManifestImport::doStartKeyAlg(StringHashMap
&rConvertedAttribs
)
259 throw( uno::RuntimeException
)
261 OUString aString
= rConvertedAttribs
[sStartKeyAlgNameAttribute
];
262 if ( aString
.equals( sSHA256_URL
) )
264 aSequence
[PKG_MNFST_STARTALG
].Name
= sStartKeyAlgProperty
;
265 aSequence
[PKG_MNFST_STARTALG
].Value
<<= xml::crypto::DigestID::SHA256
;
267 else if ( aString
.equals( sSHA1_Name
) || aString
.equals( sSHA1_URL
) )
269 aSequence
[PKG_MNFST_STARTALG
].Name
= sStartKeyAlgProperty
;
270 aSequence
[PKG_MNFST_STARTALG
].Value
<<= xml::crypto::DigestID::SHA1
;
273 bIgnoreEncryptData
= sal_True
;
276 // ---------------------------------------------------
277 void SAL_CALL
ManifestImport::startElement( const OUString
& aName
, const uno::Reference
< xml::sax::XAttributeList
>& xAttribs
)
278 throw( xml::sax::SAXException
, uno::RuntimeException
)
280 StringHashMap aConvertedAttribs
;
281 OUString aConvertedName
= PushNameAndNamespaces( aName
, xAttribs
, aConvertedAttribs
);
283 size_t nLevel
= aStack
.size();
291 if (!aConvertedName
.equalsAscii(ELEMENT_MANIFEST
)) //manifest:manifest
292 aStack
.back().m_bValid
= false;
297 if (aConvertedName
== sFileEntryElement
) //manifest:file-entry
298 doFileEntry(aConvertedAttribs
);
300 aStack
.back().m_bValid
= false;
305 ManifestStack::reverse_iterator aIter
= aStack
.rbegin();
308 if (!aIter
->m_bValid
)
309 aStack
.back().m_bValid
= false;
310 else if (aConvertedName
.equals(sEncryptionDataElement
)) //manifest:encryption-data
311 doEncryptionData(aConvertedAttribs
);
313 aStack
.back().m_bValid
= false;
318 ManifestStack::reverse_iterator aIter
= aStack
.rbegin();
321 if (!aIter
->m_bValid
)
322 aStack
.back().m_bValid
= false;
323 else if (aConvertedName
.equals(sAlgorithmElement
)) //manifest:algorithm,
324 doAlgorithm(aConvertedAttribs
);
325 else if (aConvertedName
.equals(sKeyDerivationElement
)) //manifest:key-derivation,
326 doKeyDerivation(aConvertedAttribs
);
327 else if (aConvertedName
.equals(sStartKeyAlgElement
)) //manifest:start-key-generation
328 doStartKeyAlg(aConvertedAttribs
);
330 aStack
.back().m_bValid
= false;
334 aStack
.back().m_bValid
= false;
341 bool isEmpty(const com::sun::star::beans::PropertyValue
&rProp
)
343 return rProp
.Name
.isEmpty();
347 // ---------------------------------------------------
348 void SAL_CALL
ManifestImport::endElement( const OUString
& aName
)
349 throw( xml::sax::SAXException
, uno::RuntimeException
)
351 OUString aConvertedName
= ConvertName( aName
);
352 if ( !aStack
.empty() && aStack
.rbegin()->m_aConvertedName
.equals( aConvertedName
) )
354 if ( aConvertedName
.equals( sFileEntryElement
) && aStack
.back().m_bValid
)
356 com::sun::star::beans::PropertyValue aEmpty
;
357 aSequence
.erase(std::remove_if(aSequence
.begin(), aSequence
.end(),
358 isEmpty
), aSequence
.end());
360 bIgnoreEncryptData
= sal_False
;
361 rManVector
.push_back ( aSequence
.getAsConstList() );
370 // ---------------------------------------------------
371 void SAL_CALL
ManifestImport::characters( const OUString
& /*aChars*/ )
372 throw( xml::sax::SAXException
, uno::RuntimeException
)
376 // ---------------------------------------------------
377 void SAL_CALL
ManifestImport::ignorableWhitespace( const OUString
& /*aWhitespaces*/ )
378 throw( xml::sax::SAXException
, uno::RuntimeException
)
382 // ---------------------------------------------------
383 void SAL_CALL
ManifestImport::processingInstruction( const OUString
& /*aTarget*/, const OUString
& /*aData*/ )
384 throw( xml::sax::SAXException
, uno::RuntimeException
)
388 // ---------------------------------------------------
389 void SAL_CALL
ManifestImport::setDocumentLocator( const uno::Reference
< xml::sax::XLocator
>& /*xLocator*/ )
390 throw( xml::sax::SAXException
, uno::RuntimeException
)
394 // ---------------------------------------------------
395 OUString
ManifestImport::PushNameAndNamespaces( const OUString
& aName
, const uno::Reference
< xml::sax::XAttributeList
>& xAttribs
, StringHashMap
& o_aConvertedAttribs
)
397 StringHashMap aNamespaces
;
398 ::std::vector
< ::std::pair
< OUString
, OUString
> > aAttribsStrs
;
402 sal_Int16 nAttrCount
= xAttribs
.is() ? xAttribs
->getLength() : 0;
403 aAttribsStrs
.reserve( nAttrCount
);
405 for( sal_Int16 nInd
= 0; nInd
< nAttrCount
; nInd
++ )
407 OUString aAttrName
= xAttribs
->getNameByIndex( nInd
);
408 OUString aAttrValue
= xAttribs
->getValueByIndex( nInd
);
409 if ( aAttrName
.getLength() >= 5
410 && aAttrName
.startsWith("xmlns")
411 && ( aAttrName
.getLength() == 5 || aAttrName
.getStr()[5] == ( sal_Unicode
)':' ) )
413 // this is a namespace declaration
414 OUString
aNsName( ( aAttrName
.getLength() == 5 ) ? OUString() : aAttrName
.copy( 6 ) );
415 aNamespaces
[aNsName
] = aAttrValue
;
419 // this is no namespace declaration
420 aAttribsStrs
.push_back( pair
< OUString
, OUString
>( aAttrName
, aAttrValue
) );
425 OUString aConvertedName
= ConvertNameWithNamespace( aName
, aNamespaces
);
426 if ( !aConvertedName
.getLength() )
427 aConvertedName
= ConvertName( aName
);
429 aStack
.push_back( ManifestScopeEntry( aConvertedName
, aNamespaces
) );
431 for ( sal_uInt16 nInd
= 0; nInd
< aAttribsStrs
.size(); nInd
++ )
433 // convert the attribute names on filling
434 o_aConvertedAttribs
[ConvertName( aAttribsStrs
[nInd
].first
)] = aAttribsStrs
[nInd
].second
;
437 return aConvertedName
;
440 // ---------------------------------------------------
441 OUString
ManifestImport::ConvertNameWithNamespace( const OUString
& aName
, const StringHashMap
& aNamespaces
)
444 OUString aPureName
= aName
;
446 sal_Int32 nInd
= aName
.indexOf( ( sal_Unicode
)':' );
447 if ( nInd
!= -1 && nInd
< aName
.getLength() )
449 aNsAlias
= aName
.copy( 0, nInd
);
450 aPureName
= aName
.copy( nInd
+ 1 );
455 StringHashMap::const_iterator aIter
= aNamespaces
.find( aNsAlias
);
456 if ( aIter
!= aNamespaces
.end()
457 && ( aIter
->second
== MANIFEST_NAMESPACE
|| aIter
->second
== MANIFEST_OASIS_NAMESPACE
) )
459 // no check for manifest.xml consistency currently since the old versions have supported inconsistent documents as well
460 aResult
= MANIFEST_NSPREFIX
;
461 aResult
+= aPureName
;
467 // ---------------------------------------------------
468 OUString
ManifestImport::ConvertName( const OUString
& aName
)
470 OUString aConvertedName
;
471 for ( ManifestStack::reverse_iterator aIter
= aStack
.rbegin(); !aConvertedName
.getLength() && aIter
!= aStack
.rend(); ++aIter
)
473 if ( !aIter
->m_aNamespaces
.empty() )
474 aConvertedName
= ConvertNameWithNamespace( aName
, aIter
->m_aNamespaces
);
477 if ( !aConvertedName
.getLength() )
478 aConvertedName
= aName
;
480 return aConvertedName
;
483 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */