Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/package/source/manifest/ManifestImport.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
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 .
18
 */
19
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>
32
33
using namespace com::sun::star::uno;
34
using namespace com::sun::star::beans;
35
using namespace com::sun::star;
36
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 );
49
50
ManifestImport::ManifestImport( std::vector < Sequence < PropertyValue > > & rNewManVector )
51
0
    : bIgnoreEncryptData    ( false )
52
0
    , bPgpEncryption ( false )
53
0
    , nDerivedKeySize( 0 )
54
0
    , rManVector ( rNewManVector )
55
0
{
56
0
    aStack.reserve( 10 );
57
0
}
58
59
ManifestImport::~ManifestImport()
60
0
{
61
0
}
62
63
void SAL_CALL ManifestImport::startDocument(  )
64
0
{
65
0
}
66
67
void SAL_CALL ManifestImport::endDocument(  )
68
0
{
69
0
}
70
71
void ManifestImport::doFileEntry(StringHashMap &rConvertedAttribs)
72
0
{
73
0
    aSequence.resize(PKG_SIZE_ENCR_MNFST);
74
75
0
    aSequence[PKG_MNFST_FULLPATH].Name = gsFullPathProperty;
76
0
    aSequence[PKG_MNFST_FULLPATH].Value <<= rConvertedAttribs[ATTRIBUTE_FULL_PATH];
77
0
    aSequence[PKG_MNFST_MEDIATYPE].Name = gsMediaTypeProperty;
78
0
    aSequence[PKG_MNFST_MEDIATYPE].Value <<= rConvertedAttribs[ATTRIBUTE_MEDIA_TYPE];
79
80
0
    OUString sVersion = rConvertedAttribs[ATTRIBUTE_VERSION];
81
0
    if ( sVersion.getLength() ) {
82
0
        aSequence[PKG_MNFST_VERSION].Name = gsVersionProperty;
83
0
        aSequence[PKG_MNFST_VERSION].Value <<= sVersion;
84
0
    }
85
86
0
    OUString sSize = rConvertedAttribs[ATTRIBUTE_SIZE];
87
0
    if ( sSize.getLength() ) {
88
0
        sal_Int64 nSize = sSize.toInt64();
89
0
        aSequence[PKG_MNFST_UCOMPSIZE].Name = gsSizeProperty;
90
0
        aSequence[PKG_MNFST_UCOMPSIZE].Value <<= nSize;
91
0
    }
92
0
}
93
94
void ManifestImport::doEncryptedKey(StringHashMap &)
95
0
{
96
0
    aKeyInfoSequence.clear();
97
0
    aKeyInfoSequence.resize(3);
98
0
}
99
100
void ManifestImport::doEncryptionMethod(StringHashMap &rConvertedAttribs,
101
                                        const OUString& rAlgoAttrName)
102
0
{
103
0
    OUString aString = rConvertedAttribs[rAlgoAttrName];
104
0
    if ( aKeyInfoSequence.size() != 3
105
0
         || aString != "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" )
106
0
    {
107
0
        bIgnoreEncryptData = true;
108
0
    }
109
0
}
110
111
void ManifestImport::doEncryptedCipherValue()
112
0
{
113
0
    if ( aKeyInfoSequence.size() == 3 )
114
0
    {
115
0
        aKeyInfoSequence[2].Name = "CipherValue";
116
0
        uno::Sequence < sal_Int8 > aDecodeBuffer;
117
0
        ::comphelper::Base64::decode(aDecodeBuffer, aCurrentCharacters);
118
0
        aKeyInfoSequence[2].Value <<= aDecodeBuffer;
119
0
        aCurrentCharacters.setLength(0); // consumed
120
0
    }
121
0
    else
122
0
        bIgnoreEncryptData = true;
123
0
}
124
125
void ManifestImport::doEncryptedKeyId()
126
0
{
127
0
    if ( aKeyInfoSequence.size() == 3 )
128
0
    {
129
0
        aKeyInfoSequence[0].Name = "KeyId";
130
0
        uno::Sequence < sal_Int8 > aDecodeBuffer;
131
0
        ::comphelper::Base64::decode(aDecodeBuffer, aCurrentCharacters);
132
0
        aKeyInfoSequence[0].Value <<= aDecodeBuffer;
133
0
        aCurrentCharacters.setLength(0); // consumed
134
0
    }
135
0
    else
136
0
        bIgnoreEncryptData = true;
137
0
}
138
139
void ManifestImport::doEncryptedKeyPacket()
140
0
{
141
0
    if ( aKeyInfoSequence.size() == 3 )
142
0
    {
143
0
        aKeyInfoSequence[1].Name = "KeyPacket";
144
0
        uno::Sequence < sal_Int8 > aDecodeBuffer;
145
0
        ::comphelper::Base64::decode(aDecodeBuffer, aCurrentCharacters);
146
0
        aKeyInfoSequence[1].Value <<= aDecodeBuffer;
147
0
        aCurrentCharacters.setLength(0); // consumed
148
0
    }
149
0
    else
150
0
        bIgnoreEncryptData = true;
151
0
}
152
153
void ManifestImport::doEncryptionData(StringHashMap &rConvertedAttribs)
154
0
{
155
    // If this element exists, then this stream is encrypted and we need
156
    // to import the initialisation vector, salt and iteration count used
157
0
    nDerivedKeySize = 0;
158
0
    OUString aString = rConvertedAttribs[ATTRIBUTE_CHECKSUM_TYPE];
159
0
    if ( bIgnoreEncryptData )
160
0
        return;
161
162
0
    if ( aString == SHA1_1K_NAME || aString == SHA1_1K_URL ) {
163
0
        aSequence[PKG_MNFST_DIGESTALG].Name = gsDigestAlgProperty;
164
0
        aSequence[PKG_MNFST_DIGESTALG].Value <<= xml::crypto::DigestID::SHA1_1K;
165
0
    } else if ( aString == SHA256_1K_URL ) {
166
0
        aSequence[PKG_MNFST_DIGESTALG].Name = gsDigestAlgProperty;
167
0
        aSequence[PKG_MNFST_DIGESTALG].Value <<= xml::crypto::DigestID::SHA256_1K;
168
0
    }
169
    // note: digest is now *optional* - expected not to be used with AEAD
170
171
0
    if (aSequence[PKG_MNFST_DIGESTALG].Value.hasValue()) {
172
0
        aString = rConvertedAttribs[ATTRIBUTE_CHECKSUM];
173
0
        uno::Sequence < sal_Int8 > aDecodeBuffer;
174
0
        ::comphelper::Base64::decode(aDecodeBuffer, aString);
175
0
        aSequence[PKG_MNFST_DIGEST].Name = gsDigestProperty;
176
0
        aSequence[PKG_MNFST_DIGEST].Value <<= aDecodeBuffer;
177
0
    }
178
0
}
179
180
void ManifestImport::doAlgorithm(StringHashMap &rConvertedAttribs)
181
0
{
182
0
    if ( bIgnoreEncryptData )
183
0
        return;
184
185
0
    OUString aString = rConvertedAttribs[ATTRIBUTE_ALGORITHM_NAME];
186
0
    if ( aString == BLOWFISH_NAME || aString == BLOWFISH_URL ) {
187
0
        aSequence[PKG_MNFST_ENCALG].Name = gsEncryptionAlgProperty;
188
0
        aSequence[PKG_MNFST_ENCALG].Value <<= xml::crypto::CipherID::BLOWFISH_CFB_8;
189
0
    } else if (aString == AESGCM256_URL) {
190
0
        aSequence[PKG_MNFST_ENCALG].Name = gsEncryptionAlgProperty;
191
0
        aSequence[PKG_MNFST_ENCALG].Value <<= xml::crypto::CipherID::AES_GCM_W3C;
192
0
        SAL_INFO_IF(nDerivedKeySize != 0 && nDerivedKeySize != 32, "package.manifest", "Unexpected derived key length!");
193
0
        nDerivedKeySize = 32;
194
0
    } else if (aString == AESGCM192_URL) {
195
0
        aSequence[PKG_MNFST_ENCALG].Name = gsEncryptionAlgProperty;
196
0
        aSequence[PKG_MNFST_ENCALG].Value <<= xml::crypto::CipherID::AES_GCM_W3C;
197
0
        SAL_INFO_IF(nDerivedKeySize != 0 && nDerivedKeySize != 24, "package.manifest", "Unexpected derived key length!");
198
0
        nDerivedKeySize = 24;
199
0
    } else if (aString == AESGCM128_URL) {
200
0
        aSequence[PKG_MNFST_ENCALG].Name = gsEncryptionAlgProperty;
201
0
        aSequence[PKG_MNFST_ENCALG].Value <<= xml::crypto::CipherID::AES_GCM_W3C;
202
0
        SAL_INFO_IF(nDerivedKeySize != 0 && nDerivedKeySize != 16, "package.manifest", "Unexpected derived key length!");
203
0
        nDerivedKeySize = 16;
204
0
    } else if ( aString == AES256_URL ) {
205
0
        aSequence[PKG_MNFST_ENCALG].Name = gsEncryptionAlgProperty;
206
0
        aSequence[PKG_MNFST_ENCALG].Value <<= xml::crypto::CipherID::AES_CBC_W3C_PADDING;
207
0
        OSL_ENSURE( !nDerivedKeySize || nDerivedKeySize == 32, "Unexpected derived key length!" );
208
0
        nDerivedKeySize = 32;
209
0
    } else if ( aString == AES192_URL ) {
210
0
        aSequence[PKG_MNFST_ENCALG].Name = gsEncryptionAlgProperty;
211
0
        aSequence[PKG_MNFST_ENCALG].Value <<= xml::crypto::CipherID::AES_CBC_W3C_PADDING;
212
0
        OSL_ENSURE( !nDerivedKeySize || nDerivedKeySize == 24, "Unexpected derived key length!" );
213
0
        nDerivedKeySize = 24;
214
0
    } else if ( aString == AES128_URL ) {
215
0
        aSequence[PKG_MNFST_ENCALG].Name = gsEncryptionAlgProperty;
216
0
        aSequence[PKG_MNFST_ENCALG].Value <<= xml::crypto::CipherID::AES_CBC_W3C_PADDING;
217
0
        OSL_ENSURE( !nDerivedKeySize || nDerivedKeySize == 16, "Unexpected derived key length!" );
218
0
        nDerivedKeySize = 16;
219
0
    } else
220
0
        bIgnoreEncryptData = true;
221
222
0
    if ( !bIgnoreEncryptData ) {
223
0
        aString = rConvertedAttribs[ATTRIBUTE_INITIALISATION_VECTOR];
224
0
        uno::Sequence < sal_Int8 > aDecodeBuffer;
225
0
        ::comphelper::Base64::decode(aDecodeBuffer, aString);
226
0
        aSequence[PKG_MNFST_INIVECTOR].Name = gsInitialisationVectorProperty;
227
0
        aSequence[PKG_MNFST_INIVECTOR].Value <<= aDecodeBuffer;
228
0
    }
229
0
}
230
231
void ManifestImport::doKeyDerivation(StringHashMap &rConvertedAttribs)
232
0
{
233
0
    if ( bIgnoreEncryptData )
234
0
        return;
235
236
0
    OUString aString = rConvertedAttribs[ATTRIBUTE_KEY_DERIVATION_NAME];
237
0
    if (aString == PBKDF2_NAME || aString == PBKDF2_URL
238
0
        || aString == ARGON2ID_URL || aString == ARGON2ID_URL_LO)
239
0
    {
240
0
        aSequence[PKG_MNFST_KDF].Name = "KeyDerivationFunction";
241
0
        if (aString == ARGON2ID_URL || aString == ARGON2ID_URL_LO)
242
0
        {
243
0
            aSequence[PKG_MNFST_KDF].Value <<= xml::crypto::KDFID::Argon2id;
244
245
0
            aString = rConvertedAttribs.find(ATTRIBUTE_ARGON2_T) != rConvertedAttribs.end()
246
0
                ? rConvertedAttribs[ATTRIBUTE_ARGON2_T]
247
0
                : rConvertedAttribs[ATTRIBUTE_ARGON2_T_LO];
248
0
            sal_Int32 const t(aString.toInt32());
249
0
            aString = rConvertedAttribs.find(ATTRIBUTE_ARGON2_M) != rConvertedAttribs.end()
250
0
                ? rConvertedAttribs[ATTRIBUTE_ARGON2_M]
251
0
                : rConvertedAttribs[ATTRIBUTE_ARGON2_M_LO];
252
0
            sal_Int32 const m(aString.toInt32());
253
0
            aString = rConvertedAttribs.find(ATTRIBUTE_ARGON2_P) != rConvertedAttribs.end()
254
0
                ? rConvertedAttribs[ATTRIBUTE_ARGON2_P]
255
0
                : rConvertedAttribs[ATTRIBUTE_ARGON2_P_LO];
256
0
            sal_Int32 const p(aString.toInt32());
257
0
            if (0 < t && 0 < m && 0 < p)
258
0
            {
259
0
                aSequence[PKG_MNFST_ARGON2ARGS].Name = "Argon2Args";
260
0
                aSequence[PKG_MNFST_ARGON2ARGS].Value <<= uno::Sequence{t,m,p};
261
0
            }
262
0
            else
263
0
            {
264
0
                SAL_INFO("package.manifest", "invalid argon2 arguments");
265
0
                bIgnoreEncryptData = true;
266
0
            }
267
0
        }
268
0
        else
269
0
        {
270
0
            aSequence[PKG_MNFST_KDF].Value <<= xml::crypto::KDFID::PBKDF2;
271
272
0
            aString = rConvertedAttribs[ATTRIBUTE_ITERATION_COUNT];
273
0
            aSequence[PKG_MNFST_ITERATION].Name = gsIterationCountProperty;
274
0
            aSequence[PKG_MNFST_ITERATION].Value <<= aString.toInt32();
275
0
        }
276
277
0
        aString = rConvertedAttribs[ATTRIBUTE_SALT];
278
0
        uno::Sequence < sal_Int8 > aDecodeBuffer;
279
0
        ::comphelper::Base64::decode(aDecodeBuffer, aString);
280
0
        aSequence[PKG_MNFST_SALT].Name = gsSaltProperty;
281
0
        aSequence[PKG_MNFST_SALT].Value <<= aDecodeBuffer;
282
283
0
        aString = rConvertedAttribs[ATTRIBUTE_KEY_SIZE];
284
0
        if ( aString.getLength() ) {
285
0
            sal_Int32 nKey = aString.toInt32();
286
0
            OSL_ENSURE( !nDerivedKeySize || nKey == nDerivedKeySize , "Provided derived key length differs from the expected one!" );
287
0
            nDerivedKeySize = nKey;
288
0
        } else if ( !nDerivedKeySize )
289
0
            nDerivedKeySize = 16;
290
0
        else if ( nDerivedKeySize != 16 )
291
0
            OSL_ENSURE( false, "Default derived key length differs from the expected one!" );
292
293
0
        aSequence[PKG_MNFST_DERKEYSIZE].Name = gsDerivedKeySizeProperty;
294
0
        aSequence[PKG_MNFST_DERKEYSIZE].Value <<= nDerivedKeySize;
295
0
    } else if ( bPgpEncryption ) {
296
0
        if (aString == "PGP") {
297
0
            aSequence[PKG_MNFST_KDF].Name = "KeyDerivationFunction";
298
0
            aSequence[PKG_MNFST_KDF].Value <<= xml::crypto::KDFID::PGP_RSA_OAEP_MGF1P;
299
0
        } else {
300
0
            bIgnoreEncryptData = true;
301
0
        }
302
0
    } else
303
0
        bIgnoreEncryptData = true;
304
0
}
305
306
void ManifestImport::doStartKeyAlg(StringHashMap &rConvertedAttribs)
307
0
{
308
0
    OUString aString = rConvertedAttribs[ATTRIBUTE_START_KEY_GENERATION_NAME];
309
0
    if (aString == SHA256_URL || aString == SHA256_URL_ODF12) {
310
0
        aSequence[PKG_MNFST_STARTALG].Name = gsStartKeyAlgProperty;
311
0
        aSequence[PKG_MNFST_STARTALG].Value <<= xml::crypto::DigestID::SHA256;
312
0
    } else if ( aString == SHA1_NAME || aString == SHA1_URL ) {
313
0
        aSequence[PKG_MNFST_STARTALG].Name = gsStartKeyAlgProperty;
314
0
        aSequence[PKG_MNFST_STARTALG].Value <<= xml::crypto::DigestID::SHA1;
315
0
    } else
316
0
        bIgnoreEncryptData = true;
317
0
}
318
319
void SAL_CALL ManifestImport::startElement( const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs )
320
0
{
321
0
    StringHashMap aConvertedAttribs;
322
0
    OUString aConvertedName = PushNameAndNamespaces( aName, xAttribs, aConvertedAttribs );
323
324
0
    size_t nLevel = aStack.size();
325
326
0
    assert(nLevel >= 1);
327
328
0
    switch (nLevel) {
329
0
    case 1: {
330
0
        m_PackageVersion = aConvertedAttribs[ATTRIBUTE_VERSION];
331
0
        if (aConvertedName != ELEMENT_MANIFEST) //manifest:manifest
332
0
            aStack.back().m_bValid = false;
333
0
        break;
334
0
    }
335
0
    case 2: {
336
0
        if (aConvertedName == ELEMENT_FILE_ENTRY) //manifest:file-entry
337
0
            doFileEntry(aConvertedAttribs);
338
0
        else if (aConvertedName == ELEMENT_MANIFEST_KEYINFO) //loext:keyinfo
339
0
            ;
340
0
        else if (aConvertedName == ELEMENT_ENCRYPTEDKEY13)   //manifest:encrypted-key
341
0
            doEncryptedKey(aConvertedAttribs);
342
0
        else
343
0
            aStack.back().m_bValid = false;
344
0
        break;
345
0
    }
346
0
    case 3: {
347
0
        ManifestStack::reverse_iterator aIter = aStack.rbegin();
348
0
        ++aIter;
349
350
0
        if (!aIter->m_bValid)
351
0
            aStack.back().m_bValid = false;
352
0
        else if (aConvertedName == ELEMENT_ENCRYPTION_DATA)   //manifest:encryption-data
353
0
            doEncryptionData(aConvertedAttribs);
354
0
        else if (aConvertedName == ELEMENT_ENCRYPTEDKEY)   //loext:encrypted-key
355
0
            doEncryptedKey(aConvertedAttribs);
356
0
        else if (aConvertedName == ELEMENT_ENCRYPTIONMETHOD13)   //manifest:encryption-method
357
0
            doEncryptionMethod(aConvertedAttribs, ATTRIBUTE_ALGORITHM13);
358
0
        else if (aConvertedName == ELEMENT_MANIFEST13_KEYINFO) //manifest:keyinfo
359
0
            ;
360
0
        else if (aConvertedName == ELEMENT_CIPHERDATA13)            //manifest:CipherData
361
0
            ;
362
0
        else
363
0
            aStack.back().m_bValid = false;
364
0
        break;
365
0
    }
366
0
    case 4: {
367
0
        ManifestStack::reverse_iterator aIter = aStack.rbegin();
368
0
        ++aIter;
369
370
0
        if (!aIter->m_bValid)
371
0
            aStack.back().m_bValid = false;
372
0
        else if (aConvertedName == ELEMENT_ALGORITHM)   //manifest:algorithm,
373
0
            doAlgorithm(aConvertedAttribs);
374
0
        else if (aConvertedName == ELEMENT_KEY_DERIVATION) //manifest:key-derivation,
375
0
            doKeyDerivation(aConvertedAttribs);
376
0
        else if (aConvertedName == ELEMENT_START_KEY_GENERATION)   //manifest:start-key-generation
377
0
            doStartKeyAlg(aConvertedAttribs);
378
0
        else if (aConvertedName == ELEMENT_ENCRYPTIONMETHOD)   //loext:encryption-method
379
0
            doEncryptionMethod(aConvertedAttribs, ATTRIBUTE_ALGORITHM);
380
0
        else if (aConvertedName == ELEMENT_ENCRYPTED_KEYINFO)            //loext:KeyInfo
381
0
            ;
382
0
        else if (aConvertedName == ELEMENT_CIPHERDATA)            //loext:CipherData
383
0
            ;
384
0
        else if (aConvertedName == ELEMENT_PGPDATA13)   //manifest:PGPData
385
0
            ;
386
0
        else if (aConvertedName == ELEMENT_CIPHERVALUE13) //manifest:CipherValue
387
            // ciphervalue action happens on endElement
388
0
            aCurrentCharacters = "";
389
0
        else
390
0
            aStack.back().m_bValid = false;
391
0
        break;
392
0
    }
393
0
    case 5: {
394
0
        ManifestStack::reverse_iterator aIter = aStack.rbegin();
395
0
        ++aIter;
396
397
0
        if (!aIter->m_bValid)
398
0
            aStack.back().m_bValid = false;
399
0
        else if (aConvertedName == ELEMENT_PGPDATA)   //loext:PGPData
400
0
            ;
401
0
        else if (aConvertedName == ELEMENT_CIPHERVALUE) //loext:CipherValue
402
            // ciphervalue action happens on endElement
403
0
            aCurrentCharacters = "";
404
0
        else if (aConvertedName == ELEMENT_PGPKEYID13)   //manifest:PGPKeyID
405
            // ciphervalue action happens on endElement
406
0
            aCurrentCharacters = "";
407
0
        else if (aConvertedName == ELEMENT_PGPKEYPACKET13) //manifest:PGPKeyPacket
408
            // ciphervalue action happens on endElement
409
0
            aCurrentCharacters = "";
410
0
        else
411
0
            aStack.back().m_bValid = false;
412
0
        break;
413
0
    }
414
0
    case 6: {
415
0
        ManifestStack::reverse_iterator aIter = aStack.rbegin();
416
0
        ++aIter;
417
418
0
        if (!aIter->m_bValid)
419
0
            aStack.back().m_bValid = false;
420
0
        else if (aConvertedName == ELEMENT_PGPKEYID)   //loext:PGPKeyID
421
            // ciphervalue action happens on endElement
422
0
            aCurrentCharacters = "";
423
0
        else if (aConvertedName == ELEMENT_PGPKEYPACKET) //loext:PGPKeyPacket
424
            // ciphervalue action happens on endElement
425
0
            aCurrentCharacters = "";
426
0
        else
427
0
            aStack.back().m_bValid = false;
428
0
        break;
429
0
    }
430
0
    default:
431
0
        aStack.back().m_bValid = false;
432
0
        break;
433
0
    }
434
0
}
435
436
namespace
437
{
438
bool isEmpty(const css::beans::PropertyValue &rProp)
439
0
{
440
0
    return rProp.Name.isEmpty();
441
0
}
442
}
443
444
void SAL_CALL ManifestImport::endElement( const OUString& aName )
445
0
{
446
0
    size_t nLevel = aStack.size();
447
448
0
    assert(nLevel >= 1);
449
450
0
    OUString aConvertedName = ConvertName( aName );
451
0
    if ( aStack.empty() || aStack.rbegin()->m_aConvertedName != aConvertedName )
452
0
        return;
453
454
0
    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
0
        if (rManVector.empty() && !m_PackageVersion.isEmpty()
462
0
            && !aSequence[PKG_MNFST_VERSION].Value.hasValue())
463
0
        {
464
0
            aSequence[PKG_MNFST_VERSION].Name = u"Version"_ustr;
465
0
            aSequence[PKG_MNFST_VERSION].Value <<= m_PackageVersion;
466
0
        }
467
        // the first entry gets KeyInfo element if any, for PGP encryption
468
0
        if (!bIgnoreEncryptData && !aKeys.empty() && rManVector.empty())
469
0
        {
470
0
            aSequence[PKG_MNFST_KEYINFO].Name = "KeyInfo";
471
0
            aSequence[PKG_MNFST_KEYINFO].Value <<= comphelper::containerToSequence(aKeys);
472
0
        }
473
0
        std::erase_if(aSequence, isEmpty);
474
475
0
        bIgnoreEncryptData = false;
476
0
        rManVector.push_back ( comphelper::containerToSequence(aSequence) );
477
478
0
        aSequence.clear();
479
0
    }
480
0
    else if ( (aConvertedName == ELEMENT_ENCRYPTEDKEY
481
0
               || aConvertedName == ELEMENT_ENCRYPTEDKEY13)
482
0
              && aStack.back().m_bValid ) {
483
0
        if ( !bIgnoreEncryptData )
484
0
        {
485
0
            aKeys.push_back( comphelper::containerToSequence(aKeyInfoSequence) );
486
0
            bPgpEncryption = true;
487
0
        }
488
0
        aKeyInfoSequence.clear();
489
0
    }
490
491
    // end element handling for elements with cdata
492
0
    switch (nLevel) {
493
0
        case 4: {
494
0
            if (aConvertedName == ELEMENT_CIPHERVALUE13) //manifest:CipherValue
495
0
                doEncryptedCipherValue();
496
0
            else
497
0
                aStack.back().m_bValid = false;
498
0
            break;
499
0
        }
500
0
        case 5: {
501
0
            if (aConvertedName == ELEMENT_CIPHERVALUE) //loext:CipherValue
502
0
                doEncryptedCipherValue();
503
0
            else if (aConvertedName == ELEMENT_PGPKEYID13)   //manifest:PGPKeyID
504
0
                doEncryptedKeyId();
505
0
            else if (aConvertedName == ELEMENT_PGPKEYPACKET13) //manifest:PGPKeyPacket
506
0
                doEncryptedKeyPacket();
507
0
            else
508
0
                aStack.back().m_bValid = false;
509
0
            break;
510
0
        }
511
0
        case 6: {
512
0
            if (aConvertedName == ELEMENT_PGPKEYID)   //loext:PGPKeyID
513
0
                doEncryptedKeyId();
514
0
            else if (aConvertedName == ELEMENT_PGPKEYPACKET) //loext:PGPKeyPacket
515
0
                doEncryptedKeyPacket();
516
0
            else
517
0
                aStack.back().m_bValid = false;
518
0
            break;
519
0
        }
520
0
    }
521
522
0
    aStack.pop_back();
523
0
}
524
525
void SAL_CALL ManifestImport::characters( const OUString& aChars )
526
0
{
527
0
    aCurrentCharacters.append(aChars);
528
0
}
529
530
void SAL_CALL ManifestImport::ignorableWhitespace( const OUString& /*aWhitespaces*/ )
531
0
{
532
0
}
533
534
void SAL_CALL ManifestImport::processingInstruction( const OUString& /*aTarget*/, const OUString& /*aData*/ )
535
0
{
536
0
}
537
538
void SAL_CALL ManifestImport::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& /*xLocator*/ )
539
0
{
540
0
}
541
542
OUString ManifestImport::PushNameAndNamespaces( const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs, StringHashMap& o_aConvertedAttribs )
543
0
{
544
0
    StringHashMap aNamespaces;
545
0
    ::std::vector< ::std::pair< OUString, OUString > > aAttribsStrs;
546
547
0
    if ( xAttribs.is() ) {
548
0
        sal_Int16 nAttrCount = xAttribs.is() ? xAttribs->getLength() : 0;
549
0
        aAttribsStrs.reserve( nAttrCount );
550
551
0
        for( sal_Int16 nInd = 0; nInd < nAttrCount; nInd++ ) {
552
0
            OUString aAttrName = xAttribs->getNameByIndex( nInd );
553
0
            OUString aAttrValue = xAttribs->getValueByIndex( nInd );
554
0
            if ( aAttrName.getLength() >= 5
555
0
                 && aAttrName.startsWith("xmlns")
556
0
                 && ( aAttrName.getLength() == 5 || aAttrName[5] == ':' ) ) {
557
                // this is a namespace declaration
558
0
                OUString aNsName( ( aAttrName.getLength() == 5 ) ? OUString() : aAttrName.copy( 6 ) );
559
0
                aNamespaces[aNsName] = aAttrValue;
560
0
            } else {
561
                // this is no namespace declaration
562
0
                aAttribsStrs.emplace_back( aAttrName, aAttrValue );
563
0
            }
564
0
        }
565
0
    }
566
567
0
    OUString aConvertedName = ConvertNameWithNamespace( aName, aNamespaces );
568
0
    if ( !aConvertedName.getLength() )
569
0
        aConvertedName = ConvertName( aName );
570
571
0
    aStack.emplace_back( aConvertedName, std::move(aNamespaces) );
572
573
0
    for (const std::pair<OUString,OUString> & rAttribsStr : aAttribsStrs) {
574
        // convert the attribute names on filling
575
0
        o_aConvertedAttribs[ConvertName( rAttribsStr.first )] = rAttribsStr.second;
576
0
    }
577
578
0
    return aConvertedName;
579
0
}
580
581
OUString ManifestImport::ConvertNameWithNamespace( const OUString& aName, const StringHashMap& aNamespaces )
582
0
{
583
0
    OUString aNsAlias;
584
0
    OUString aPureName = aName;
585
586
0
    sal_Int32 nInd = aName.indexOf( ':' );
587
0
    if ( nInd != -1 && nInd < aName.getLength() ) {
588
0
        aNsAlias = aName.copy( 0, nInd );
589
0
        aPureName = aName.copy( nInd + 1 );
590
0
    }
591
592
0
    OUString aResult;
593
594
0
    StringHashMap::const_iterator aIter = aNamespaces.find( aNsAlias );
595
0
    if ( aIter != aNamespaces.end()
596
0
         && ( 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
0
        aResult = MANIFEST_NSPREFIX + aPureName;
599
0
    }
600
601
0
    return aResult;
602
0
}
603
604
OUString ManifestImport::ConvertName( const OUString& aName )
605
0
{
606
0
    OUString aConvertedName;
607
0
    for ( ManifestStack::reverse_iterator aIter = aStack.rbegin(); !aConvertedName.getLength() && aIter != aStack.rend(); ++aIter ) {
608
0
        if ( !aIter->m_aNamespaces.empty() )
609
0
            aConvertedName = ConvertNameWithNamespace( aName, aIter->m_aNamespaces );
610
0
    }
611
612
0
    if ( !aConvertedName.getLength() )
613
0
        aConvertedName = aName;
614
615
0
    return aConvertedName;
616
0
}
617
618
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */