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 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
21 #include <com/sun/star/xml/crypto/DigestID.hpp>
22 #include <com/sun/star/xml/crypto/CipherID.hpp>
23 #include <com/sun/star/beans/PropertyValue.hpp>
24 #include <com/sun/star/beans/NamedValue.hpp>
25 #include <com/sun/star/uno/RuntimeException.hpp>
27 #include "ManifestDefines.hxx"
28 #include "ManifestExport.hxx"
30 #include <osl/diagnose.h>
31 #include <rtl/ustrbuf.hxx>
32 #include <rtl/ref.hxx>
33 #include <sal/log.hxx>
34 #include <comphelper/base64.hxx>
35 #include <comphelper/documentconstants.hxx>
36 #include <comphelper/attributelist.hxx>
38 using namespace ::com::sun::star
;
40 #if OSL_DEBUG_LEVEL > 0
41 #define THROW_WHERE SAL_WHERE
43 #define THROW_WHERE ""
46 ManifestExport::ManifestExport( uno::Reference
< xml::sax::XDocumentHandler
> const & xHandler
, const uno::Sequence
< uno::Sequence
< beans::PropertyValue
> >& rManList
)
48 static const OUStringLiteral
sKeyInfo ( u
"KeyInfo" );
49 static const OUStringLiteral
sPgpKeyIDProperty ( u
"KeyId" );
50 static const OUStringLiteral
sPgpKeyPacketProperty ( u
"KeyPacket" );
51 static const OUStringLiteral
sCipherValueProperty ( u
"CipherValue" );
52 static const OUStringLiteral
sFullPathProperty ( u
"FullPath" );
53 static const OUStringLiteral
sVersionProperty ( u
"Version" );
54 static const OUStringLiteral
sMediaTypeProperty ( u
"MediaType" );
55 static const OUStringLiteral
sIterationCountProperty ( u
"IterationCount" );
56 static const OUStringLiteral
sDerivedKeySizeProperty ( u
"DerivedKeySize" );
57 static const OUStringLiteral
sSaltProperty ( u
"Salt" );
58 static const OUStringLiteral
sInitialisationVectorProperty( u
"InitialisationVector" );
59 static const OUStringLiteral
sSizeProperty ( u
"Size" );
60 static const OUStringLiteral
sDigestProperty ( u
"Digest" );
61 static const OUStringLiteral
sEncryptionAlgProperty ( u
"EncryptionAlgorithm" );
62 static const OUStringLiteral
sStartKeyAlgProperty ( u
"StartKeyAlgorithm" );
63 static const OUStringLiteral
sDigestAlgProperty ( u
"DigestAlgorithm" );
65 static const OUStringLiteral
sWhiteSpace ( u
" " );
67 const OUString
sSHA256_URL_ODF12 ( SHA256_URL_ODF12
);
68 const OUString
sSHA1_Name ( SHA1_NAME
);
70 const OUString
sSHA1_1k_Name ( SHA1_1K_NAME
);
71 const OUString
sSHA256_1k_URL ( SHA256_1K_URL
);
73 const OUString
sBlowfish_Name ( BLOWFISH_NAME
);
74 const OUString
sAES256_URL ( AES256_URL
);
76 const OUString
sPBKDF2_Name ( PBKDF2_NAME
);
77 const OUString
sPGP_Name ( PGP_NAME
);
79 rtl::Reference
<::comphelper::AttributeList
> pRootAttrList
= new ::comphelper::AttributeList
;
81 // find the mediatype of the document if any
82 OUString aDocMediaType
;
84 const uno::Sequence
<beans::PropertyValue
>* pRootFolderPropSeq
= nullptr;
85 for (const uno::Sequence
< beans::PropertyValue
>& rSequence
: rManList
)
91 for (const beans::PropertyValue
& rValue
: rSequence
)
93 if (rValue
.Name
== sMediaTypeProperty
)
95 rValue
.Value
>>= aMediaType
;
97 else if (rValue
.Name
== sFullPathProperty
)
99 rValue
.Value
>>= aPath
;
101 else if (rValue
.Name
== sVersionProperty
)
103 rValue
.Value
>>= aVersion
;
106 if ( !aPath
.isEmpty() && !aMediaType
.isEmpty() && !aVersion
.isEmpty() )
112 aDocMediaType
= aMediaType
;
113 aDocVersion
= aVersion
;
114 pRootFolderPropSeq
= &rSequence
;
119 bool bProvideDTD
= false;
120 bool bAcceptNonemptyVersion
= false;
121 bool bStoreStartKeyGeneration
= false;
122 if ( !aDocMediaType
.isEmpty() )
124 if ( aDocMediaType
== MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII
125 || aDocMediaType
== MIMETYPE_OASIS_OPENDOCUMENT_TEXT_WEB_ASCII
126 || aDocMediaType
== MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_ASCII
127 || aDocMediaType
== MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_ASCII
128 || aDocMediaType
== MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII
129 || aDocMediaType
== MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII
130 || aDocMediaType
== MIMETYPE_OASIS_OPENDOCUMENT_CHART_ASCII
131 || aDocMediaType
== MIMETYPE_OASIS_OPENDOCUMENT_DATABASE_ASCII
132 || aDocMediaType
== MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_ASCII
133 || aDocMediaType
== MIMETYPE_OASIS_OPENDOCUMENT_TEXT_TEMPLATE_ASCII
134 || aDocMediaType
== MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_TEMPLATE_ASCII
135 || aDocMediaType
== MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_TEMPLATE_ASCII
136 || aDocMediaType
== MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE_ASCII
137 || aDocMediaType
== MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_TEMPLATE_ASCII
138 || aDocMediaType
== MIMETYPE_OASIS_OPENDOCUMENT_CHART_TEMPLATE_ASCII
139 || aDocMediaType
== MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_TEMPLATE_ASCII
)
143 pRootAttrList
->AddAttribute ( ATTRIBUTE_XMLNS
,
145 MANIFEST_OASIS_NAMESPACE
);
146 bAcceptNonemptyVersion
= true;
147 if ( aDocVersion
.compareTo( ODFVER_012_TEXT
) >= 0 )
149 // this is ODF12 or later generation, let encrypted
150 // streams contain start-key-generation entry
151 bStoreStartKeyGeneration
= true;
152 pRootAttrList
->AddAttribute ( ATTRIBUTE_VERSION
, ATTRIBUTE_CDATA
, aDocVersion
);
153 // plus gpg4libre extensions - loext NS for that
154 pRootAttrList
->AddAttribute ( ATTRIBUTE_XMLNS_LOEXT
,
156 MANIFEST_LOEXT_NAMESPACE
);
161 // even if it is no SO6 format the namespace must be specified
162 // thus SO6 format is used as default one
163 pRootAttrList
->AddAttribute ( ATTRIBUTE_XMLNS
,
165 MANIFEST_NAMESPACE
);
171 xHandler
->startDocument();
172 uno::Reference
< xml::sax::XExtendedDocumentHandler
> xExtHandler ( xHandler
, uno::UNO_QUERY
);
173 if ( xExtHandler
.is() && bProvideDTD
)
175 xExtHandler
->unknown ( MANIFEST_DOCTYPE
);
176 xHandler
->ignorableWhitespace ( sWhiteSpace
);
178 xHandler
->startElement( ELEMENT_MANIFEST
, pRootAttrList
);
180 const uno::Any
*pKeyInfoProperty
= nullptr;
181 if ( pRootFolderPropSeq
)
183 // do we have package-wide encryption info?
184 for (const beans::PropertyValue
& rValue
: *pRootFolderPropSeq
)
186 if (rValue
.Name
== sKeyInfo
)
187 pKeyInfoProperty
= &rValue
.Value
;
190 if ( pKeyInfoProperty
)
192 // yeah, so that goes directly below the manifest:manifest
194 OUStringBuffer aBuffer
;
196 xHandler
->ignorableWhitespace ( sWhiteSpace
);
198 // ==== manifest:keyinfo & children
199 bool const isODF13(aDocVersion
.compareTo(ODFVER_013_TEXT
) >= 0);
202 xHandler
->startElement(ELEMENT_MANIFEST_KEYINFO
, nullptr);
204 xHandler
->ignorableWhitespace ( sWhiteSpace
);
206 uno::Sequence
< uno::Sequence
< beans::NamedValue
> > aKeyInfoSequence
;
207 *pKeyInfoProperty
>>= aKeyInfoSequence
;
208 for (const uno::Sequence
<beans::NamedValue
>& rKeyInfoSequence
: std::as_const(aKeyInfoSequence
))
210 uno::Sequence
< sal_Int8
> aPgpKeyID
;
211 uno::Sequence
< sal_Int8
> aPgpKeyPacket
;
212 uno::Sequence
< sal_Int8
> aCipherValue
;
213 for (const beans::NamedValue
& rNValue
: rKeyInfoSequence
)
215 if (rNValue
.Name
== sPgpKeyIDProperty
)
216 rNValue
.Value
>>= aPgpKeyID
;
217 else if (rNValue
.Name
== sPgpKeyPacketProperty
)
218 rNValue
.Value
>>= aPgpKeyPacket
;
219 else if (rNValue
.Name
== sCipherValueProperty
)
220 rNValue
.Value
>>= aCipherValue
;
223 if (aPgpKeyID
.hasElements() && aCipherValue
.hasElements() )
225 // ==== manifest:encrypted-key & children - one for each recipient
226 xHandler
->startElement(isODF13
? OUString(ELEMENT_ENCRYPTEDKEY13
) : OUString(ELEMENT_ENCRYPTEDKEY
), nullptr);
227 xHandler
->ignorableWhitespace ( sWhiteSpace
);
229 rtl::Reference
<::comphelper::AttributeList
> pNewAttrList
= new ::comphelper::AttributeList
;
230 // TODO: the algorithm should rather be configurable
231 pNewAttrList
->AddAttribute(
232 isODF13
? OUString(ATTRIBUTE_ALGORITHM13
) : OUString(ATTRIBUTE_ALGORITHM
),
234 "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" );
235 xHandler
->startElement(isODF13
? OUString(ELEMENT_ENCRYPTIONMETHOD13
) : OUString(ELEMENT_ENCRYPTIONMETHOD
), pNewAttrList
);
236 xHandler
->endElement(isODF13
? OUString(ELEMENT_ENCRYPTIONMETHOD13
) : OUString(ELEMENT_ENCRYPTIONMETHOD
));
237 xHandler
->ignorableWhitespace ( sWhiteSpace
);
239 // note: the mismatch here corresponds to ODF 1.3 cs01 schema
240 xHandler
->startElement(isODF13
? OUString(ELEMENT_MANIFEST13_KEYINFO
) : OUString(ELEMENT_MANIFEST_KEYINFO
), nullptr);
241 xHandler
->ignorableWhitespace ( sWhiteSpace
);
243 xHandler
->startElement(isODF13
? OUString(ELEMENT_PGPDATA13
) : OUString(ELEMENT_PGPDATA
), nullptr);
244 xHandler
->ignorableWhitespace ( sWhiteSpace
);
246 xHandler
->startElement(isODF13
? OUString(ELEMENT_PGPKEYID13
) : OUString(ELEMENT_PGPKEYID
), nullptr);
247 ::comphelper::Base64::encode(aBuffer
, aPgpKeyID
);
248 xHandler
->characters( aBuffer
.makeStringAndClear() );
249 xHandler
->endElement(isODF13
? OUString(ELEMENT_PGPKEYID13
) : OUString(ELEMENT_PGPKEYID
));
250 xHandler
->ignorableWhitespace ( sWhiteSpace
);
252 // key packet is optional
253 if (aPgpKeyPacket
.hasElements())
255 xHandler
->startElement(isODF13
? OUString(ELEMENT_PGPKEYPACKET13
) : OUString(ELEMENT_PGPKEYPACKET
), nullptr);
256 ::comphelper::Base64::encode(aBuffer
, aPgpKeyPacket
);
257 xHandler
->characters( aBuffer
.makeStringAndClear() );
258 xHandler
->endElement(isODF13
? OUString(ELEMENT_PGPKEYPACKET13
) : OUString(ELEMENT_PGPKEYPACKET
));
259 xHandler
->ignorableWhitespace ( sWhiteSpace
);
262 xHandler
->endElement(isODF13
? OUString(ELEMENT_PGPDATA13
) : OUString(ELEMENT_PGPDATA
));
263 xHandler
->ignorableWhitespace ( sWhiteSpace
);
265 xHandler
->endElement(isODF13
? OUString(ELEMENT_MANIFEST13_KEYINFO
) : OUString(ELEMENT_MANIFEST_KEYINFO
));
266 xHandler
->ignorableWhitespace ( sWhiteSpace
);
268 xHandler
->startElement(isODF13
? OUString(ELEMENT_CIPHERDATA13
) : OUString(ELEMENT_CIPHERDATA
), nullptr);
269 xHandler
->ignorableWhitespace ( sWhiteSpace
);
271 xHandler
->startElement(isODF13
? OUString(ELEMENT_CIPHERVALUE13
) : OUString(ELEMENT_CIPHERVALUE
), nullptr);
272 ::comphelper::Base64::encode(aBuffer
, aCipherValue
);
273 xHandler
->characters( aBuffer
.makeStringAndClear() );
274 xHandler
->endElement(isODF13
? OUString(ELEMENT_CIPHERVALUE13
) : OUString(ELEMENT_CIPHERVALUE
));
275 xHandler
->ignorableWhitespace ( sWhiteSpace
);
277 xHandler
->endElement(isODF13
? OUString(ELEMENT_CIPHERDATA13
) : OUString(ELEMENT_CIPHERDATA
));
278 xHandler
->ignorableWhitespace ( sWhiteSpace
);
280 xHandler
->endElement(isODF13
? OUString(ELEMENT_ENCRYPTEDKEY13
) : OUString(ELEMENT_ENCRYPTEDKEY
));
281 xHandler
->ignorableWhitespace ( sWhiteSpace
);
287 xHandler
->endElement(ELEMENT_MANIFEST_KEYINFO
);
289 xHandler
->ignorableWhitespace ( sWhiteSpace
);
293 // now write individual file entries
294 for (const uno::Sequence
<beans::PropertyValue
>& rSequence
: rManList
)
296 rtl::Reference
<::comphelper::AttributeList
> pAttrList
= new ::comphelper::AttributeList
;
298 const uno::Any
*pVector
= nullptr, *pSalt
= nullptr, *pIterationCount
= nullptr, *pDigest
= nullptr, *pDigestAlg
= nullptr, *pEncryptAlg
= nullptr, *pStartKeyAlg
= nullptr, *pDerivedKeySize
= nullptr;
299 for (const beans::PropertyValue
& rValue
: rSequence
)
301 if (rValue
.Name
== sMediaTypeProperty
)
303 rValue
.Value
>>= aString
;
304 pAttrList
->AddAttribute ( ATTRIBUTE_MEDIA_TYPE
, ATTRIBUTE_CDATA
, aString
);
306 else if (rValue
.Name
== sVersionProperty
)
308 rValue
.Value
>>= aString
;
309 // the version is stored only if it is not empty
310 if ( bAcceptNonemptyVersion
&& !aString
.isEmpty() )
311 pAttrList
->AddAttribute ( ATTRIBUTE_VERSION
, ATTRIBUTE_CDATA
, aString
);
313 else if (rValue
.Name
== sFullPathProperty
)
315 rValue
.Value
>>= aString
;
316 pAttrList
->AddAttribute ( ATTRIBUTE_FULL_PATH
, ATTRIBUTE_CDATA
, aString
);
318 else if (rValue
.Name
== sSizeProperty
)
321 rValue
.Value
>>= nSize
;
322 pAttrList
->AddAttribute ( ATTRIBUTE_SIZE
, ATTRIBUTE_CDATA
, OUString::number( nSize
) );
324 else if (rValue
.Name
== sInitialisationVectorProperty
)
325 pVector
= &rValue
.Value
;
326 else if (rValue
.Name
== sSaltProperty
)
327 pSalt
= &rValue
.Value
;
328 else if (rValue
.Name
== sIterationCountProperty
)
329 pIterationCount
= &rValue
.Value
;
330 else if (rValue
.Name
== sDigestProperty
)
331 pDigest
= &rValue
.Value
;
332 else if (rValue
.Name
== sDigestAlgProperty
)
333 pDigestAlg
= &rValue
.Value
;
334 else if (rValue
.Name
== sEncryptionAlgProperty
)
335 pEncryptAlg
= &rValue
.Value
;
336 else if (rValue
.Name
== sStartKeyAlgProperty
)
337 pStartKeyAlg
= &rValue
.Value
;
338 else if (rValue
.Name
== sDerivedKeySizeProperty
)
339 pDerivedKeySize
= &rValue
.Value
;
342 xHandler
->ignorableWhitespace ( sWhiteSpace
);
343 xHandler
->startElement( ELEMENT_FILE_ENTRY
, pAttrList
);
344 if ( pVector
&& pSalt
&& pIterationCount
&& pDigest
&& pDigestAlg
&& pEncryptAlg
&& pStartKeyAlg
&& pDerivedKeySize
)
346 // ==== Encryption Data
347 rtl::Reference
<::comphelper::AttributeList
> pNewAttrList
= new ::comphelper::AttributeList
;
348 OUStringBuffer aBuffer
;
349 uno::Sequence
< sal_Int8
> aSequence
;
351 xHandler
->ignorableWhitespace ( sWhiteSpace
);
354 OUString sChecksumType
;
355 sal_Int32 nDigestAlgID
= 0;
356 *pDigestAlg
>>= nDigestAlgID
;
357 if ( nDigestAlgID
== xml::crypto::DigestID::SHA256_1K
)
358 sChecksumType
= sSHA256_1k_URL
;
359 else if ( nDigestAlgID
== xml::crypto::DigestID::SHA1_1K
)
360 sChecksumType
= sSHA1_1k_Name
;
362 throw uno::RuntimeException( THROW_WHERE
"Unexpected digest algorithm is provided!" );
364 pNewAttrList
->AddAttribute ( ATTRIBUTE_CHECKSUM_TYPE
, ATTRIBUTE_CDATA
, sChecksumType
);
365 *pDigest
>>= aSequence
;
366 ::comphelper::Base64::encode(aBuffer
, aSequence
);
367 pNewAttrList
->AddAttribute ( ATTRIBUTE_CHECKSUM
, ATTRIBUTE_CDATA
, aBuffer
.makeStringAndClear() );
369 xHandler
->startElement( ELEMENT_ENCRYPTION_DATA
, pNewAttrList
);
372 pNewAttrList
= new ::comphelper::AttributeList
;
374 sal_Int32 nEncAlgID
= 0;
375 sal_Int32 nDerivedKeySize
= 0;
376 *pEncryptAlg
>>= nEncAlgID
;
377 *pDerivedKeySize
>>= nDerivedKeySize
;
379 OUString sEncAlgName
;
380 if ( nEncAlgID
== xml::crypto::CipherID::AES_CBC_W3C_PADDING
)
382 OSL_ENSURE( nDerivedKeySize
, "Unexpected key size is provided!" );
383 if ( nDerivedKeySize
!= 32 )
384 throw uno::RuntimeException( THROW_WHERE
"Unexpected key size is provided!" );
386 sEncAlgName
= sAES256_URL
;
388 else if ( nEncAlgID
== xml::crypto::CipherID::BLOWFISH_CFB_8
)
390 sEncAlgName
= sBlowfish_Name
;
393 throw uno::RuntimeException( THROW_WHERE
"Unexpected encryption algorithm is provided!" );
395 pNewAttrList
->AddAttribute ( ATTRIBUTE_ALGORITHM_NAME
, ATTRIBUTE_CDATA
, sEncAlgName
);
397 *pVector
>>= aSequence
;
398 ::comphelper::Base64::encode(aBuffer
, aSequence
);
399 pNewAttrList
->AddAttribute ( ATTRIBUTE_INITIALISATION_VECTOR
, ATTRIBUTE_CDATA
, aBuffer
.makeStringAndClear() );
401 xHandler
->ignorableWhitespace ( sWhiteSpace
);
402 xHandler
->startElement( ELEMENT_ALGORITHM
, pNewAttrList
);
403 xHandler
->ignorableWhitespace ( sWhiteSpace
);
404 xHandler
->endElement( ELEMENT_ALGORITHM
);
406 if ( bStoreStartKeyGeneration
)
408 // ==== Start Key Generation
409 pNewAttrList
= new ::comphelper::AttributeList
;
411 OUString sStartKeyAlg
;
412 OUString sStartKeySize
;
413 sal_Int32 nStartKeyAlgID
= 0;
414 *pStartKeyAlg
>>= nStartKeyAlgID
;
415 if ( nStartKeyAlgID
== xml::crypto::DigestID::SHA256
)
417 sStartKeyAlg
= sSHA256_URL_ODF12
; // TODO use SHA256_URL
418 aBuffer
.append( sal_Int32(32) );
419 sStartKeySize
= aBuffer
.makeStringAndClear();
421 else if ( nStartKeyAlgID
== xml::crypto::DigestID::SHA1
)
423 sStartKeyAlg
= sSHA1_Name
;
424 aBuffer
.append( sal_Int32(20) );
425 sStartKeySize
= aBuffer
.makeStringAndClear();
428 throw uno::RuntimeException( THROW_WHERE
"Unexpected start key algorithm is provided!" );
430 pNewAttrList
->AddAttribute ( ATTRIBUTE_START_KEY_GENERATION_NAME
, ATTRIBUTE_CDATA
, sStartKeyAlg
);
431 pNewAttrList
->AddAttribute ( ATTRIBUTE_KEY_SIZE
, ATTRIBUTE_CDATA
, sStartKeySize
);
433 xHandler
->ignorableWhitespace ( sWhiteSpace
);
434 xHandler
->startElement( ELEMENT_START_KEY_GENERATION
, pNewAttrList
);
435 xHandler
->ignorableWhitespace ( sWhiteSpace
);
436 xHandler
->endElement( ELEMENT_START_KEY_GENERATION
);
439 // ==== Key Derivation
440 pNewAttrList
= new ::comphelper::AttributeList
;
442 if (pKeyInfoProperty
)
444 pNewAttrList
->AddAttribute(ATTRIBUTE_KEY_DERIVATION_NAME
,
447 // no start-key-generation needed, our session key has
449 bStoreStartKeyGeneration
= false;
453 pNewAttrList
->AddAttribute(ATTRIBUTE_KEY_DERIVATION_NAME
,
457 if (bStoreStartKeyGeneration
)
459 aBuffer
.append(nDerivedKeySize
);
460 pNewAttrList
->AddAttribute(ATTRIBUTE_KEY_SIZE
, ATTRIBUTE_CDATA
, aBuffer
.makeStringAndClear());
463 sal_Int32 nCount
= 0;
464 *pIterationCount
>>= nCount
;
465 aBuffer
.append(nCount
);
466 pNewAttrList
->AddAttribute(ATTRIBUTE_ITERATION_COUNT
, ATTRIBUTE_CDATA
, aBuffer
.makeStringAndClear());
468 *pSalt
>>= aSequence
;
469 ::comphelper::Base64::encode(aBuffer
, aSequence
);
470 pNewAttrList
->AddAttribute(ATTRIBUTE_SALT
, ATTRIBUTE_CDATA
, aBuffer
.makeStringAndClear());
473 xHandler
->ignorableWhitespace(sWhiteSpace
);
474 xHandler
->startElement(ELEMENT_KEY_DERIVATION
, pNewAttrList
);
475 xHandler
->ignorableWhitespace(sWhiteSpace
);
476 xHandler
->endElement(ELEMENT_KEY_DERIVATION
);
478 xHandler
->ignorableWhitespace ( sWhiteSpace
);
479 xHandler
->endElement( ELEMENT_ENCRYPTION_DATA
);
481 xHandler
->ignorableWhitespace ( sWhiteSpace
);
482 xHandler
->endElement( ELEMENT_FILE_ENTRY
);
484 xHandler
->ignorableWhitespace ( sWhiteSpace
);
485 xHandler
->endElement( ELEMENT_MANIFEST
);
486 xHandler
->endDocument();
489 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */