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 "ManifestImport.hxx"
21 #include "ManifestDefines.hxx"
22 #include <PackageConstants.hxx>
23 #include <osl/diagnose.h>
24 #include <sal/log.hxx>
25 #include <com/sun/star/xml/sax/XAttributeList.hpp>
26 #include <com/sun/star/xml/crypto/DigestID.hpp>
27 #include <com/sun/star/xml/crypto/CipherID.hpp>
28 #include <com/sun/star/xml/crypto/KDFID.hpp>
29 #include <com/sun/star/beans/PropertyValue.hpp>
30 #include <comphelper/base64.hxx>
31 #include <comphelper/sequence.hxx>
33 using namespace com::sun::star::uno
;
34 using namespace com::sun::star::beans
;
35 using namespace com::sun::star
;
37 constexpr OUStringLiteral
gsFullPathProperty ( u
"FullPath" );
38 constexpr OUStringLiteral
gsMediaTypeProperty ( u
"MediaType" );
39 constexpr OUStringLiteral
gsVersionProperty ( u
"Version" );
40 constexpr OUStringLiteral
gsIterationCountProperty ( u
"IterationCount" );
41 constexpr OUStringLiteral
gsDerivedKeySizeProperty ( u
"DerivedKeySize" );
42 constexpr OUStringLiteral
gsSaltProperty ( u
"Salt" );
43 constexpr OUStringLiteral
gsInitialisationVectorProperty ( u
"InitialisationVector" );
44 constexpr OUStringLiteral
gsSizeProperty ( u
"Size" );
45 constexpr OUStringLiteral
gsDigestProperty ( u
"Digest" );
46 constexpr OUString
gsEncryptionAlgProperty ( u
"EncryptionAlgorithm"_ustr
);
47 constexpr OUString
gsStartKeyAlgProperty ( u
"StartKeyAlgorithm"_ustr
);
48 constexpr OUString
gsDigestAlgProperty ( u
"DigestAlgorithm"_ustr
);
50 ManifestImport::ManifestImport( std::vector
< Sequence
< PropertyValue
> > & rNewManVector
)
51 : bIgnoreEncryptData ( false )
52 , bPgpEncryption ( false )
53 , nDerivedKeySize( 0 )
54 , rManVector ( rNewManVector
)
59 ManifestImport::~ManifestImport()
63 void SAL_CALL
ManifestImport::startDocument( )
67 void SAL_CALL
ManifestImport::endDocument( )
71 void ManifestImport::doFileEntry(StringHashMap
&rConvertedAttribs
)
73 aSequence
.resize(PKG_SIZE_ENCR_MNFST
);
75 aSequence
[PKG_MNFST_FULLPATH
].Name
= gsFullPathProperty
;
76 aSequence
[PKG_MNFST_FULLPATH
].Value
<<= rConvertedAttribs
[ATTRIBUTE_FULL_PATH
];
77 aSequence
[PKG_MNFST_MEDIATYPE
].Name
= gsMediaTypeProperty
;
78 aSequence
[PKG_MNFST_MEDIATYPE
].Value
<<= rConvertedAttribs
[ATTRIBUTE_MEDIA_TYPE
];
80 OUString sVersion
= rConvertedAttribs
[ATTRIBUTE_VERSION
];
81 if ( sVersion
.getLength() ) {
82 aSequence
[PKG_MNFST_VERSION
].Name
= gsVersionProperty
;
83 aSequence
[PKG_MNFST_VERSION
].Value
<<= sVersion
;
86 OUString sSize
= rConvertedAttribs
[ATTRIBUTE_SIZE
];
87 if ( sSize
.getLength() ) {
88 sal_Int64 nSize
= sSize
.toInt64();
89 aSequence
[PKG_MNFST_UCOMPSIZE
].Name
= gsSizeProperty
;
90 aSequence
[PKG_MNFST_UCOMPSIZE
].Value
<<= nSize
;
94 void ManifestImport::doEncryptedKey(StringHashMap
&)
96 aKeyInfoSequence
.clear();
97 aKeyInfoSequence
.resize(3);
100 void ManifestImport::doEncryptionMethod(StringHashMap
&rConvertedAttribs
,
101 const OUString
& rAlgoAttrName
)
103 OUString aString
= rConvertedAttribs
[rAlgoAttrName
];
104 if ( aKeyInfoSequence
.size() != 3
105 || aString
!= "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" )
107 bIgnoreEncryptData
= true;
111 void ManifestImport::doEncryptedCipherValue()
113 if ( aKeyInfoSequence
.size() == 3 )
115 aKeyInfoSequence
[2].Name
= "CipherValue";
116 uno::Sequence
< sal_Int8
> aDecodeBuffer
;
117 ::comphelper::Base64::decode(aDecodeBuffer
, aCurrentCharacters
);
118 aKeyInfoSequence
[2].Value
<<= aDecodeBuffer
;
119 aCurrentCharacters
.setLength(0); // consumed
122 bIgnoreEncryptData
= true;
125 void ManifestImport::doEncryptedKeyId()
127 if ( aKeyInfoSequence
.size() == 3 )
129 aKeyInfoSequence
[0].Name
= "KeyId";
130 uno::Sequence
< sal_Int8
> aDecodeBuffer
;
131 ::comphelper::Base64::decode(aDecodeBuffer
, aCurrentCharacters
);
132 aKeyInfoSequence
[0].Value
<<= aDecodeBuffer
;
133 aCurrentCharacters
.setLength(0); // consumed
136 bIgnoreEncryptData
= true;
139 void ManifestImport::doEncryptedKeyPacket()
141 if ( aKeyInfoSequence
.size() == 3 )
143 aKeyInfoSequence
[1].Name
= "KeyPacket";
144 uno::Sequence
< sal_Int8
> aDecodeBuffer
;
145 ::comphelper::Base64::decode(aDecodeBuffer
, aCurrentCharacters
);
146 aKeyInfoSequence
[1].Value
<<= aDecodeBuffer
;
147 aCurrentCharacters
.setLength(0); // consumed
150 bIgnoreEncryptData
= true;
153 void ManifestImport::doEncryptionData(StringHashMap
&rConvertedAttribs
)
155 // If this element exists, then this stream is encrypted and we need
156 // to import the initialisation vector, salt and iteration count used
158 OUString aString
= rConvertedAttribs
[ATTRIBUTE_CHECKSUM_TYPE
];
159 if ( bIgnoreEncryptData
)
162 if ( aString
== SHA1_1K_NAME
|| aString
== SHA1_1K_URL
) {
163 aSequence
[PKG_MNFST_DIGESTALG
].Name
= gsDigestAlgProperty
;
164 aSequence
[PKG_MNFST_DIGESTALG
].Value
<<= xml::crypto::DigestID::SHA1_1K
;
165 } else if ( aString
== SHA256_1K_URL
) {
166 aSequence
[PKG_MNFST_DIGESTALG
].Name
= gsDigestAlgProperty
;
167 aSequence
[PKG_MNFST_DIGESTALG
].Value
<<= xml::crypto::DigestID::SHA256_1K
;
169 // note: digest is now *optional* - expected not to be used with AEAD
171 if (aSequence
[PKG_MNFST_DIGESTALG
].Value
.hasValue()) {
172 aString
= rConvertedAttribs
[ATTRIBUTE_CHECKSUM
];
173 uno::Sequence
< sal_Int8
> aDecodeBuffer
;
174 ::comphelper::Base64::decode(aDecodeBuffer
, aString
);
175 aSequence
[PKG_MNFST_DIGEST
].Name
= gsDigestProperty
;
176 aSequence
[PKG_MNFST_DIGEST
].Value
<<= aDecodeBuffer
;
180 void ManifestImport::doAlgorithm(StringHashMap
&rConvertedAttribs
)
182 if ( bIgnoreEncryptData
)
185 OUString aString
= rConvertedAttribs
[ATTRIBUTE_ALGORITHM_NAME
];
186 if ( aString
== BLOWFISH_NAME
|| aString
== BLOWFISH_URL
) {
187 aSequence
[PKG_MNFST_ENCALG
].Name
= gsEncryptionAlgProperty
;
188 aSequence
[PKG_MNFST_ENCALG
].Value
<<= xml::crypto::CipherID::BLOWFISH_CFB_8
;
189 } else if (aString
== AESGCM256_URL
) {
190 aSequence
[PKG_MNFST_ENCALG
].Name
= gsEncryptionAlgProperty
;
191 aSequence
[PKG_MNFST_ENCALG
].Value
<<= xml::crypto::CipherID::AES_GCM_W3C
;
192 SAL_INFO_IF(nDerivedKeySize
!= 0 && nDerivedKeySize
!= 32, "package.manifest", "Unexpected derived key length!");
193 nDerivedKeySize
= 32;
194 } else if (aString
== AESGCM192_URL
) {
195 aSequence
[PKG_MNFST_ENCALG
].Name
= gsEncryptionAlgProperty
;
196 aSequence
[PKG_MNFST_ENCALG
].Value
<<= xml::crypto::CipherID::AES_GCM_W3C
;
197 SAL_INFO_IF(nDerivedKeySize
!= 0 && nDerivedKeySize
!= 24, "package.manifest", "Unexpected derived key length!");
198 nDerivedKeySize
= 24;
199 } else if (aString
== AESGCM128_URL
) {
200 aSequence
[PKG_MNFST_ENCALG
].Name
= gsEncryptionAlgProperty
;
201 aSequence
[PKG_MNFST_ENCALG
].Value
<<= xml::crypto::CipherID::AES_GCM_W3C
;
202 SAL_INFO_IF(nDerivedKeySize
!= 0 && nDerivedKeySize
!= 16, "package.manifest", "Unexpected derived key length!");
203 nDerivedKeySize
= 16;
204 } else if ( aString
== AES256_URL
) {
205 aSequence
[PKG_MNFST_ENCALG
].Name
= gsEncryptionAlgProperty
;
206 aSequence
[PKG_MNFST_ENCALG
].Value
<<= xml::crypto::CipherID::AES_CBC_W3C_PADDING
;
207 OSL_ENSURE( !nDerivedKeySize
|| nDerivedKeySize
== 32, "Unexpected derived key length!" );
208 nDerivedKeySize
= 32;
209 } else if ( aString
== AES192_URL
) {
210 aSequence
[PKG_MNFST_ENCALG
].Name
= gsEncryptionAlgProperty
;
211 aSequence
[PKG_MNFST_ENCALG
].Value
<<= xml::crypto::CipherID::AES_CBC_W3C_PADDING
;
212 OSL_ENSURE( !nDerivedKeySize
|| nDerivedKeySize
== 24, "Unexpected derived key length!" );
213 nDerivedKeySize
= 24;
214 } else if ( aString
== AES128_URL
) {
215 aSequence
[PKG_MNFST_ENCALG
].Name
= gsEncryptionAlgProperty
;
216 aSequence
[PKG_MNFST_ENCALG
].Value
<<= xml::crypto::CipherID::AES_CBC_W3C_PADDING
;
217 OSL_ENSURE( !nDerivedKeySize
|| nDerivedKeySize
== 16, "Unexpected derived key length!" );
218 nDerivedKeySize
= 16;
220 bIgnoreEncryptData
= true;
222 if ( !bIgnoreEncryptData
) {
223 aString
= rConvertedAttribs
[ATTRIBUTE_INITIALISATION_VECTOR
];
224 uno::Sequence
< sal_Int8
> aDecodeBuffer
;
225 ::comphelper::Base64::decode(aDecodeBuffer
, aString
);
226 aSequence
[PKG_MNFST_INIVECTOR
].Name
= gsInitialisationVectorProperty
;
227 aSequence
[PKG_MNFST_INIVECTOR
].Value
<<= aDecodeBuffer
;
231 void ManifestImport::doKeyDerivation(StringHashMap
&rConvertedAttribs
)
233 if ( bIgnoreEncryptData
)
236 OUString aString
= rConvertedAttribs
[ATTRIBUTE_KEY_DERIVATION_NAME
];
237 if (aString
== PBKDF2_NAME
|| aString
== PBKDF2_URL
238 || aString
== ARGON2ID_URL
|| aString
== ARGON2ID_URL_LO
)
240 aSequence
[PKG_MNFST_KDF
].Name
= "KeyDerivationFunction";
241 if (aString
== ARGON2ID_URL
|| aString
== ARGON2ID_URL_LO
)
243 aSequence
[PKG_MNFST_KDF
].Value
<<= xml::crypto::KDFID::Argon2id
;
245 aString
= rConvertedAttribs
.find(ATTRIBUTE_ARGON2_T
) != rConvertedAttribs
.end()
246 ? rConvertedAttribs
[ATTRIBUTE_ARGON2_T
]
247 : rConvertedAttribs
[ATTRIBUTE_ARGON2_T_LO
];
248 sal_Int32
const t(aString
.toInt32());
249 aString
= rConvertedAttribs
.find(ATTRIBUTE_ARGON2_M
) != rConvertedAttribs
.end()
250 ? rConvertedAttribs
[ATTRIBUTE_ARGON2_M
]
251 : rConvertedAttribs
[ATTRIBUTE_ARGON2_M_LO
];
252 sal_Int32
const m(aString
.toInt32());
253 aString
= rConvertedAttribs
.find(ATTRIBUTE_ARGON2_P
) != rConvertedAttribs
.end()
254 ? rConvertedAttribs
[ATTRIBUTE_ARGON2_P
]
255 : rConvertedAttribs
[ATTRIBUTE_ARGON2_P_LO
];
256 sal_Int32
const p(aString
.toInt32());
257 if (0 < t
&& 0 < m
&& 0 < p
)
259 aSequence
[PKG_MNFST_ARGON2ARGS
].Name
= "Argon2Args";
260 aSequence
[PKG_MNFST_ARGON2ARGS
].Value
<<= uno::Sequence
{t
,m
,p
};
264 SAL_INFO("package.manifest", "invalid argon2 arguments");
265 bIgnoreEncryptData
= true;
270 aSequence
[PKG_MNFST_KDF
].Value
<<= xml::crypto::KDFID::PBKDF2
;
272 aString
= rConvertedAttribs
[ATTRIBUTE_ITERATION_COUNT
];
273 aSequence
[PKG_MNFST_ITERATION
].Name
= gsIterationCountProperty
;
274 aSequence
[PKG_MNFST_ITERATION
].Value
<<= aString
.toInt32();
277 aString
= rConvertedAttribs
[ATTRIBUTE_SALT
];
278 uno::Sequence
< sal_Int8
> aDecodeBuffer
;
279 ::comphelper::Base64::decode(aDecodeBuffer
, aString
);
280 aSequence
[PKG_MNFST_SALT
].Name
= gsSaltProperty
;
281 aSequence
[PKG_MNFST_SALT
].Value
<<= aDecodeBuffer
;
283 aString
= rConvertedAttribs
[ATTRIBUTE_KEY_SIZE
];
284 if ( aString
.getLength() ) {
285 sal_Int32 nKey
= aString
.toInt32();
286 OSL_ENSURE( !nDerivedKeySize
|| nKey
== nDerivedKeySize
, "Provided derived key length differs from the expected one!" );
287 nDerivedKeySize
= nKey
;
288 } else if ( !nDerivedKeySize
)
289 nDerivedKeySize
= 16;
290 else if ( nDerivedKeySize
!= 16 )
291 OSL_ENSURE( false, "Default derived key length differs from the expected one!" );
293 aSequence
[PKG_MNFST_DERKEYSIZE
].Name
= gsDerivedKeySizeProperty
;
294 aSequence
[PKG_MNFST_DERKEYSIZE
].Value
<<= nDerivedKeySize
;
295 } else if ( bPgpEncryption
) {
296 if (aString
== "PGP") {
297 aSequence
[PKG_MNFST_KDF
].Name
= "KeyDerivationFunction";
298 aSequence
[PKG_MNFST_KDF
].Value
<<= xml::crypto::KDFID::PGP_RSA_OAEP_MGF1P
;
300 bIgnoreEncryptData
= true;
303 bIgnoreEncryptData
= true;
306 void ManifestImport::doStartKeyAlg(StringHashMap
&rConvertedAttribs
)
308 OUString aString
= rConvertedAttribs
[ATTRIBUTE_START_KEY_GENERATION_NAME
];
309 if (aString
== SHA256_URL
|| aString
== SHA256_URL_ODF12
) {
310 aSequence
[PKG_MNFST_STARTALG
].Name
= gsStartKeyAlgProperty
;
311 aSequence
[PKG_MNFST_STARTALG
].Value
<<= xml::crypto::DigestID::SHA256
;
312 } else if ( aString
== SHA1_NAME
|| aString
== SHA1_URL
) {
313 aSequence
[PKG_MNFST_STARTALG
].Name
= gsStartKeyAlgProperty
;
314 aSequence
[PKG_MNFST_STARTALG
].Value
<<= xml::crypto::DigestID::SHA1
;
316 bIgnoreEncryptData
= true;
319 void SAL_CALL
ManifestImport::startElement( const OUString
& aName
, const uno::Reference
< xml::sax::XAttributeList
>& xAttribs
)
321 StringHashMap aConvertedAttribs
;
322 OUString aConvertedName
= PushNameAndNamespaces( aName
, xAttribs
, aConvertedAttribs
);
324 size_t nLevel
= aStack
.size();
330 m_PackageVersion
= aConvertedAttribs
[ATTRIBUTE_VERSION
];
331 if (aConvertedName
!= ELEMENT_MANIFEST
) //manifest:manifest
332 aStack
.back().m_bValid
= false;
336 if (aConvertedName
== ELEMENT_FILE_ENTRY
) //manifest:file-entry
337 doFileEntry(aConvertedAttribs
);
338 else if (aConvertedName
== ELEMENT_MANIFEST_KEYINFO
) //loext:keyinfo
340 else if (aConvertedName
== ELEMENT_ENCRYPTEDKEY13
) //manifest:encrypted-key
341 doEncryptedKey(aConvertedAttribs
);
343 aStack
.back().m_bValid
= false;
347 ManifestStack::reverse_iterator aIter
= aStack
.rbegin();
350 if (!aIter
->m_bValid
)
351 aStack
.back().m_bValid
= false;
352 else if (aConvertedName
== ELEMENT_ENCRYPTION_DATA
) //manifest:encryption-data
353 doEncryptionData(aConvertedAttribs
);
354 else if (aConvertedName
== ELEMENT_ENCRYPTEDKEY
) //loext:encrypted-key
355 doEncryptedKey(aConvertedAttribs
);
356 else if (aConvertedName
== ELEMENT_ENCRYPTIONMETHOD13
) //manifest:encryption-method
357 doEncryptionMethod(aConvertedAttribs
, ATTRIBUTE_ALGORITHM13
);
358 else if (aConvertedName
== ELEMENT_MANIFEST13_KEYINFO
) //manifest:keyinfo
360 else if (aConvertedName
== ELEMENT_CIPHERDATA13
) //manifest:CipherData
363 aStack
.back().m_bValid
= false;
367 ManifestStack::reverse_iterator aIter
= aStack
.rbegin();
370 if (!aIter
->m_bValid
)
371 aStack
.back().m_bValid
= false;
372 else if (aConvertedName
== ELEMENT_ALGORITHM
) //manifest:algorithm,
373 doAlgorithm(aConvertedAttribs
);
374 else if (aConvertedName
== ELEMENT_KEY_DERIVATION
) //manifest:key-derivation,
375 doKeyDerivation(aConvertedAttribs
);
376 else if (aConvertedName
== ELEMENT_START_KEY_GENERATION
) //manifest:start-key-generation
377 doStartKeyAlg(aConvertedAttribs
);
378 else if (aConvertedName
== ELEMENT_ENCRYPTIONMETHOD
) //loext:encryption-method
379 doEncryptionMethod(aConvertedAttribs
, ATTRIBUTE_ALGORITHM
);
380 else if (aConvertedName
== ELEMENT_ENCRYPTED_KEYINFO
) //loext:KeyInfo
382 else if (aConvertedName
== ELEMENT_CIPHERDATA
) //loext:CipherData
384 else if (aConvertedName
== ELEMENT_PGPDATA13
) //manifest:PGPData
386 else if (aConvertedName
== ELEMENT_CIPHERVALUE13
) //manifest:CipherValue
387 // ciphervalue action happens on endElement
388 aCurrentCharacters
= "";
390 aStack
.back().m_bValid
= false;
394 ManifestStack::reverse_iterator aIter
= aStack
.rbegin();
397 if (!aIter
->m_bValid
)
398 aStack
.back().m_bValid
= false;
399 else if (aConvertedName
== ELEMENT_PGPDATA
) //loext:PGPData
401 else if (aConvertedName
== ELEMENT_CIPHERVALUE
) //loext:CipherValue
402 // ciphervalue action happens on endElement
403 aCurrentCharacters
= "";
404 else if (aConvertedName
== ELEMENT_PGPKEYID13
) //manifest:PGPKeyID
405 // ciphervalue action happens on endElement
406 aCurrentCharacters
= "";
407 else if (aConvertedName
== ELEMENT_PGPKEYPACKET13
) //manifest:PGPKeyPacket
408 // ciphervalue action happens on endElement
409 aCurrentCharacters
= "";
411 aStack
.back().m_bValid
= false;
415 ManifestStack::reverse_iterator aIter
= aStack
.rbegin();
418 if (!aIter
->m_bValid
)
419 aStack
.back().m_bValid
= false;
420 else if (aConvertedName
== ELEMENT_PGPKEYID
) //loext:PGPKeyID
421 // ciphervalue action happens on endElement
422 aCurrentCharacters
= "";
423 else if (aConvertedName
== ELEMENT_PGPKEYPACKET
) //loext:PGPKeyPacket
424 // ciphervalue action happens on endElement
425 aCurrentCharacters
= "";
427 aStack
.back().m_bValid
= false;
431 aStack
.back().m_bValid
= false;
438 bool isEmpty(const css::beans::PropertyValue
&rProp
)
440 return rProp
.Name
.isEmpty();
444 void SAL_CALL
ManifestImport::endElement( const OUString
& aName
)
446 size_t nLevel
= aStack
.size();
450 OUString aConvertedName
= ConvertName( aName
);
451 if ( aStack
.empty() || aStack
.rbegin()->m_aConvertedName
!= aConvertedName
)
454 if ( aConvertedName
== ELEMENT_FILE_ENTRY
&& aStack
.back().m_bValid
) {
455 // required for wholesome encryption: if there is no document and hence
456 // no file-entry with a version attribute, send the package's version
457 // with the first file-entry.
458 // (note: the only case when a valid ODF document has no "/" entry with
459 // a version is when it is ODF 1.0/1.1 and then it doesn't have the
460 // package version either)
461 if (rManVector
.empty() && !m_PackageVersion
.isEmpty()
462 && !aSequence
[PKG_MNFST_VERSION
].Value
.hasValue())
464 aSequence
[PKG_MNFST_VERSION
].Name
= u
"Version"_ustr
;
465 aSequence
[PKG_MNFST_VERSION
].Value
<<= m_PackageVersion
;
467 // the first entry gets KeyInfo element if any, for PGP encryption
468 if (!bIgnoreEncryptData
&& !aKeys
.empty() && rManVector
.empty())
470 aSequence
[PKG_MNFST_KEYINFO
].Name
= "KeyInfo";
471 aSequence
[PKG_MNFST_KEYINFO
].Value
<<= comphelper::containerToSequence(aKeys
);
473 std::erase_if(aSequence
, isEmpty
);
475 bIgnoreEncryptData
= false;
476 rManVector
.push_back ( comphelper::containerToSequence(aSequence
) );
480 else if ( (aConvertedName
== ELEMENT_ENCRYPTEDKEY
481 || aConvertedName
== ELEMENT_ENCRYPTEDKEY13
)
482 && aStack
.back().m_bValid
) {
483 if ( !bIgnoreEncryptData
)
485 aKeys
.push_back( comphelper::containerToSequence(aKeyInfoSequence
) );
486 bPgpEncryption
= true;
488 aKeyInfoSequence
.clear();
491 // end element handling for elements with cdata
494 if (aConvertedName
== ELEMENT_CIPHERVALUE13
) //manifest:CipherValue
495 doEncryptedCipherValue();
497 aStack
.back().m_bValid
= false;
501 if (aConvertedName
== ELEMENT_CIPHERVALUE
) //loext:CipherValue
502 doEncryptedCipherValue();
503 else if (aConvertedName
== ELEMENT_PGPKEYID13
) //manifest:PGPKeyID
505 else if (aConvertedName
== ELEMENT_PGPKEYPACKET13
) //manifest:PGPKeyPacket
506 doEncryptedKeyPacket();
508 aStack
.back().m_bValid
= false;
512 if (aConvertedName
== ELEMENT_PGPKEYID
) //loext:PGPKeyID
514 else if (aConvertedName
== ELEMENT_PGPKEYPACKET
) //loext:PGPKeyPacket
515 doEncryptedKeyPacket();
517 aStack
.back().m_bValid
= false;
525 void SAL_CALL
ManifestImport::characters( const OUString
& aChars
)
527 aCurrentCharacters
.append(aChars
);
530 void SAL_CALL
ManifestImport::ignorableWhitespace( const OUString
& /*aWhitespaces*/ )
534 void SAL_CALL
ManifestImport::processingInstruction( const OUString
& /*aTarget*/, const OUString
& /*aData*/ )
538 void SAL_CALL
ManifestImport::setDocumentLocator( const uno::Reference
< xml::sax::XLocator
>& /*xLocator*/ )
542 OUString
ManifestImport::PushNameAndNamespaces( const OUString
& aName
, const uno::Reference
< xml::sax::XAttributeList
>& xAttribs
, StringHashMap
& o_aConvertedAttribs
)
544 StringHashMap aNamespaces
;
545 ::std::vector
< ::std::pair
< OUString
, OUString
> > aAttribsStrs
;
547 if ( xAttribs
.is() ) {
548 sal_Int16 nAttrCount
= xAttribs
.is() ? xAttribs
->getLength() : 0;
549 aAttribsStrs
.reserve( nAttrCount
);
551 for( sal_Int16 nInd
= 0; nInd
< nAttrCount
; nInd
++ ) {
552 OUString aAttrName
= xAttribs
->getNameByIndex( nInd
);
553 OUString aAttrValue
= xAttribs
->getValueByIndex( nInd
);
554 if ( aAttrName
.getLength() >= 5
555 && aAttrName
.startsWith("xmlns")
556 && ( aAttrName
.getLength() == 5 || aAttrName
[5] == ':' ) ) {
557 // this is a namespace declaration
558 OUString
aNsName( ( aAttrName
.getLength() == 5 ) ? OUString() : aAttrName
.copy( 6 ) );
559 aNamespaces
[aNsName
] = aAttrValue
;
561 // this is no namespace declaration
562 aAttribsStrs
.emplace_back( aAttrName
, aAttrValue
);
567 OUString aConvertedName
= ConvertNameWithNamespace( aName
, aNamespaces
);
568 if ( !aConvertedName
.getLength() )
569 aConvertedName
= ConvertName( aName
);
571 aStack
.emplace_back( aConvertedName
, std::move(aNamespaces
) );
573 for (const std::pair
<OUString
,OUString
> & rAttribsStr
: aAttribsStrs
) {
574 // convert the attribute names on filling
575 o_aConvertedAttribs
[ConvertName( rAttribsStr
.first
)] = rAttribsStr
.second
;
578 return aConvertedName
;
581 OUString
ManifestImport::ConvertNameWithNamespace( const OUString
& aName
, const StringHashMap
& aNamespaces
)
584 OUString aPureName
= aName
;
586 sal_Int32 nInd
= aName
.indexOf( ':' );
587 if ( nInd
!= -1 && nInd
< aName
.getLength() ) {
588 aNsAlias
= aName
.copy( 0, nInd
);
589 aPureName
= aName
.copy( nInd
+ 1 );
594 StringHashMap::const_iterator aIter
= aNamespaces
.find( aNsAlias
);
595 if ( aIter
!= aNamespaces
.end()
596 && ( aIter
->second
== MANIFEST_NAMESPACE
|| aIter
->second
== MANIFEST_OASIS_NAMESPACE
) ) {
597 // no check for manifest.xml consistency currently since the old versions have supported inconsistent documents as well
598 aResult
= MANIFEST_NSPREFIX
+ aPureName
;
604 OUString
ManifestImport::ConvertName( const OUString
& aName
)
606 OUString aConvertedName
;
607 for ( ManifestStack::reverse_iterator aIter
= aStack
.rbegin(); !aConvertedName
.getLength() && aIter
!= aStack
.rend(); ++aIter
) {
608 if ( !aIter
->m_aNamespaces
.empty() )
609 aConvertedName
= ConvertNameWithNamespace( aName
, aIter
->m_aNamespaces
);
612 if ( !aConvertedName
.getLength() )
613 aConvertedName
= aName
;
615 return aConvertedName
;
618 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */