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 <sax/tools/converter.hxx> 23 #include <osl/diagnose.h> 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> 28 #include <comphelper/base64.hxx> 29 #include <comphelper/sequence.hxx> 30 31 using namespace com::sun::star::uno; 32 using namespace com::sun::star::beans; 33 using namespace com::sun::star; 34 using namespace std; 35 36 ManifestImport::ManifestImport( vector < Sequence < PropertyValue > > & rNewManVector ) 37 : bIgnoreEncryptData ( false ) 38 , bPgpEncryption ( false ) 39 , nDerivedKeySize( 0 ) 40 , rManVector ( rNewManVector ) 41 42 , sFileEntryElement ( ELEMENT_FILE_ENTRY ) 43 , sEncryptionDataElement( ELEMENT_ENCRYPTION_DATA ) 44 , sAlgorithmElement ( ELEMENT_ALGORITHM ) 45 , sStartKeyAlgElement ( ELEMENT_START_KEY_GENERATION ) 46 , sKeyDerivationElement( ELEMENT_KEY_DERIVATION ) 47 48 , sMediaTypeAttribute ( ATTRIBUTE_MEDIA_TYPE ) 49 , sVersionAttribute ( ATTRIBUTE_VERSION ) 50 , sFullPathAttribute ( ATTRIBUTE_FULL_PATH ) 51 , sSizeAttribute ( ATTRIBUTE_SIZE ) 52 , sSaltAttribute ( ATTRIBUTE_SALT ) 53 , sInitialisationVectorAttribute ( ATTRIBUTE_INITIALISATION_VECTOR ) 54 , sIterationCountAttribute ( ATTRIBUTE_ITERATION_COUNT ) 55 , sKeySizeAttribute ( ATTRIBUTE_KEY_SIZE ) 56 , sAlgorithmNameAttribute ( ATTRIBUTE_ALGORITHM_NAME ) 57 , sStartKeyAlgNameAttribute ( ATTRIBUTE_START_KEY_GENERATION_NAME ) 58 , sKeyDerivationNameAttribute ( ATTRIBUTE_KEY_DERIVATION_NAME ) 59 , sChecksumAttribute ( ATTRIBUTE_CHECKSUM ) 60 , sChecksumTypeAttribute ( ATTRIBUTE_CHECKSUM_TYPE ) 61 62 , sKeyInfoElement ( ELEMENT_ENCRYPTED_KEYINFO ) 63 , sManifestKeyInfoElement ( ELEMENT_MANIFEST_KEYINFO ) 64 , sEncryptedKeyElement ( ELEMENT_ENCRYPTEDKEY ) 65 , sEncryptionMethodElement ( ELEMENT_ENCRYPTIONMETHOD ) 66 , sPgpDataElement ( ELEMENT_PGPDATA ) 67 , sPgpKeyIDElement ( ELEMENT_PGPKEYID ) 68 , sPGPKeyPacketElement ( ELEMENT_PGPKEYPACKET ) 69 , sAlgorithmAttribute ( ATTRIBUTE_ALGORITHM ) 70 , sCipherDataElement ( ELEMENT_CIPHERDATA ) 71 , sCipherValueElement ( ELEMENT_CIPHERVALUE ) 72 73 , sFullPathProperty ( "FullPath" ) 74 , sMediaTypeProperty ( "MediaType" ) 75 , sVersionProperty ( "Version" ) 76 , sIterationCountProperty ( "IterationCount" ) 77 , sDerivedKeySizeProperty ( "DerivedKeySize" ) 78 , sSaltProperty ( "Salt" ) 79 , sInitialisationVectorProperty ( "InitialisationVector" ) 80 , sSizeProperty ( "Size" ) 81 , sDigestProperty ( "Digest" ) 82 , sEncryptionAlgProperty ( "EncryptionAlgorithm" ) 83 , sStartKeyAlgProperty ( "StartKeyAlgorithm" ) 84 , sDigestAlgProperty ( "DigestAlgorithm" ) 85 86 , sSHA256_URL_ODF12 ( SHA256_URL_ODF12 ) 87 , sSHA256_URL ( SHA256_URL ) 88 , sSHA1_Name ( SHA1_NAME ) 89 , sSHA1_URL ( SHA1_URL ) 90 91 , sSHA256_1k_URL ( SHA256_1K_URL ) 92 , sSHA1_1k_Name ( SHA1_1K_NAME ) 93 , sSHA1_1k_URL ( SHA1_1K_URL ) 94 95 , sBlowfish_Name ( BLOWFISH_NAME ) 96 , sBlowfish_URL ( BLOWFISH_URL ) 97 , sAES128_URL ( AES128_URL ) 98 , sAES192_URL ( AES192_URL ) 99 , sAES256_URL ( AES256_URL ) 100 101 , sPBKDF2_Name ( PBKDF2_NAME ) 102 , sPBKDF2_URL ( PBKDF2_URL ) 103 { 104 aStack.reserve( 10 ); 105 } 106 107 ManifestImport::~ManifestImport() 108 { 109 } 110 111 void SAL_CALL ManifestImport::startDocument( ) 112 { 113 } 114 115 void SAL_CALL ManifestImport::endDocument( ) 116 { 117 } 118 119 void ManifestImport::doFileEntry(StringHashMap &rConvertedAttribs) 120 { 121 aSequence.resize(PKG_SIZE_ENCR_MNFST); 122 123 aSequence[PKG_MNFST_FULLPATH].Name = sFullPathProperty; 124 aSequence[PKG_MNFST_FULLPATH].Value <<= rConvertedAttribs[sFullPathAttribute]; 125 aSequence[PKG_MNFST_MEDIATYPE].Name = sMediaTypeProperty; 126 aSequence[PKG_MNFST_MEDIATYPE].Value <<= rConvertedAttribs[sMediaTypeAttribute]; 127 128 OUString sVersion = rConvertedAttribs[sVersionAttribute]; 129 if ( sVersion.getLength() ) { 130 aSequence[PKG_MNFST_VERSION].Name = sVersionProperty; 131 aSequence[PKG_MNFST_VERSION].Value <<= sVersion; 132 } 133 134 OUString sSize = rConvertedAttribs[sSizeAttribute]; 135 if ( sSize.getLength() ) { 136 sal_Int64 nSize = sSize.toInt64(); 137 aSequence[PKG_MNFST_UCOMPSIZE].Name = sSizeProperty; 138 aSequence[PKG_MNFST_UCOMPSIZE].Value <<= nSize; 139 } 140 } 141 142 void ManifestImport::doKeyInfoEntry(StringHashMap &) 143 { 144 } 145 146 void ManifestImport::doEncryptedKey(StringHashMap &) 147 { 148 aKeyInfoSequence.clear(); 149 aKeyInfoSequence.resize(3); 150 } 151 152 void ManifestImport::doEncryptionMethod(StringHashMap &rConvertedAttribs) 153 { 154 OUString aString = rConvertedAttribs[sAlgorithmAttribute]; 155 if ( aKeyInfoSequence.size() != 3 156 || aString != "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" ) 157 { 158 bIgnoreEncryptData = true; 159 } 160 } 161 162 void ManifestImport::doEncryptedKeyInfo(StringHashMap &) 163 { 164 } 165 166 void ManifestImport::doEncryptedCipherData(StringHashMap &) 167 { 168 } 169 170 void ManifestImport::doEncryptedPgpData(StringHashMap &) 171 { 172 } 173 174 void ManifestImport::doEncryptedCipherValue() 175 { 176 if ( aKeyInfoSequence.size() == 3 ) 177 { 178 aKeyInfoSequence[2].Name = "CipherValue"; 179 uno::Sequence < sal_Int8 > aDecodeBuffer; 180 ::comphelper::Base64::decode(aDecodeBuffer, aCurrentCharacters); 181 aKeyInfoSequence[2].Value <<= aDecodeBuffer; 182 aCurrentCharacters = ""; // consumed 183 } 184 else 185 bIgnoreEncryptData = true; 186 } 187 188 void ManifestImport::doEncryptedKeyId() 189 { 190 if ( aKeyInfoSequence.size() == 3 ) 191 { 192 aKeyInfoSequence[0].Name = "KeyId"; 193 uno::Sequence < sal_Int8 > aDecodeBuffer; 194 ::comphelper::Base64::decode(aDecodeBuffer, aCurrentCharacters); 195 aKeyInfoSequence[0].Value <<= aDecodeBuffer; 196 aCurrentCharacters = ""; // consumed 197 } 198 else 199 bIgnoreEncryptData = true; 200 } 201 202 void ManifestImport::doEncryptedKeyPacket() 203 { 204 if ( aKeyInfoSequence.size() == 3 ) 205 { 206 aKeyInfoSequence[1].Name = "KeyPacket"; 207 uno::Sequence < sal_Int8 > aDecodeBuffer; 208 ::comphelper::Base64::decode(aDecodeBuffer, aCurrentCharacters); 209 aKeyInfoSequence[1].Value <<= aDecodeBuffer; 210 aCurrentCharacters = ""; // consumed 211 } 212 else 213 bIgnoreEncryptData = true; 214 } 215 216 void ManifestImport::doEncryptionData(StringHashMap &rConvertedAttribs) 217 { 218 // If this element exists, then this stream is encrypted and we need 219 // to import the initialisation vector, salt and iteration count used 220 nDerivedKeySize = 0; 221 OUString aString = rConvertedAttribs[sChecksumTypeAttribute]; 222 if ( !bIgnoreEncryptData ) { 223 if ( aString == sSHA1_1k_Name || aString == sSHA1_1k_URL ) { 224 aSequence[PKG_MNFST_DIGESTALG].Name = sDigestAlgProperty; 225 aSequence[PKG_MNFST_DIGESTALG].Value <<= xml::crypto::DigestID::SHA1_1K; 226 } else if ( aString == sSHA256_1k_URL ) { 227 aSequence[PKG_MNFST_DIGESTALG].Name = sDigestAlgProperty; 228 aSequence[PKG_MNFST_DIGESTALG].Value <<= xml::crypto::DigestID::SHA256_1K; 229 } else 230 bIgnoreEncryptData = true; 231 232 if ( !bIgnoreEncryptData ) { 233 aString = rConvertedAttribs[sChecksumAttribute]; 234 uno::Sequence < sal_Int8 > aDecodeBuffer; 235 ::comphelper::Base64::decode(aDecodeBuffer, aString); 236 aSequence[PKG_MNFST_DIGEST].Name = sDigestProperty; 237 aSequence[PKG_MNFST_DIGEST].Value <<= aDecodeBuffer; 238 } 239 } 240 } 241 242 void ManifestImport::doAlgorithm(StringHashMap &rConvertedAttribs) 243 { 244 if ( !bIgnoreEncryptData ) { 245 OUString aString = rConvertedAttribs[sAlgorithmNameAttribute]; 246 if ( aString == sBlowfish_Name || aString == sBlowfish_URL ) { 247 aSequence[PKG_MNFST_ENCALG].Name = sEncryptionAlgProperty; 248 aSequence[PKG_MNFST_ENCALG].Value <<= xml::crypto::CipherID::BLOWFISH_CFB_8; 249 } else if ( aString == sAES256_URL ) { 250 aSequence[PKG_MNFST_ENCALG].Name = sEncryptionAlgProperty; 251 aSequence[PKG_MNFST_ENCALG].Value <<= xml::crypto::CipherID::AES_CBC_W3C_PADDING; 252 OSL_ENSURE( !nDerivedKeySize || nDerivedKeySize == 32, "Unexpected derived key length!" ); 253 nDerivedKeySize = 32; 254 } else if ( aString == sAES192_URL ) { 255 aSequence[PKG_MNFST_ENCALG].Name = sEncryptionAlgProperty; 256 aSequence[PKG_MNFST_ENCALG].Value <<= xml::crypto::CipherID::AES_CBC_W3C_PADDING; 257 OSL_ENSURE( !nDerivedKeySize || nDerivedKeySize == 24, "Unexpected derived key length!" ); 258 nDerivedKeySize = 24; 259 } else if ( aString == sAES128_URL ) { 260 aSequence[PKG_MNFST_ENCALG].Name = sEncryptionAlgProperty; 261 aSequence[PKG_MNFST_ENCALG].Value <<= xml::crypto::CipherID::AES_CBC_W3C_PADDING; 262 OSL_ENSURE( !nDerivedKeySize || nDerivedKeySize == 16, "Unexpected derived key length!" ); 263 nDerivedKeySize = 16; 264 } else 265 bIgnoreEncryptData = true; 266 267 if ( !bIgnoreEncryptData ) { 268 aString = rConvertedAttribs[sInitialisationVectorAttribute]; 269 uno::Sequence < sal_Int8 > aDecodeBuffer; 270 ::comphelper::Base64::decode(aDecodeBuffer, aString); 271 aSequence[PKG_MNFST_INIVECTOR].Name = sInitialisationVectorProperty; 272 aSequence[PKG_MNFST_INIVECTOR].Value <<= aDecodeBuffer; 273 } 274 } 275 } 276 277 void ManifestImport::doKeyDerivation(StringHashMap &rConvertedAttribs) 278 { 279 if ( !bIgnoreEncryptData ) { 280 OUString aString = rConvertedAttribs[sKeyDerivationNameAttribute]; 281 if ( aString == sPBKDF2_Name || aString == sPBKDF2_URL ) { 282 aString = rConvertedAttribs[sSaltAttribute]; 283 uno::Sequence < sal_Int8 > aDecodeBuffer; 284 ::comphelper::Base64::decode(aDecodeBuffer, aString); 285 aSequence[PKG_MNFST_SALT].Name = sSaltProperty; 286 aSequence[PKG_MNFST_SALT].Value <<= aDecodeBuffer; 287 288 aString = rConvertedAttribs[sIterationCountAttribute]; 289 aSequence[PKG_MNFST_ITERATION].Name = sIterationCountProperty; 290 aSequence[PKG_MNFST_ITERATION].Value <<= aString.toInt32(); 291 292 aString = rConvertedAttribs[sKeySizeAttribute]; 293 if ( aString.getLength() ) { 294 sal_Int32 nKey = aString.toInt32(); 295 OSL_ENSURE( !nDerivedKeySize || nKey == nDerivedKeySize , "Provided derived key length differs from the expected one!" ); 296 nDerivedKeySize = nKey; 297 } else if ( !nDerivedKeySize ) 298 nDerivedKeySize = 16; 299 else if ( nDerivedKeySize != 16 ) 300 OSL_ENSURE( false, "Default derived key length differs from the expected one!" ); 301 302 aSequence[PKG_MNFST_DERKEYSIZE].Name = sDerivedKeySizeProperty; 303 aSequence[PKG_MNFST_DERKEYSIZE].Value <<= nDerivedKeySize; 304 } else if ( bPgpEncryption ) { 305 if ( aString != "PGP" ) 306 bIgnoreEncryptData = true; 307 } else 308 bIgnoreEncryptData = true; 309 } 310 } 311 312 void ManifestImport::doStartKeyAlg(StringHashMap &rConvertedAttribs) 313 { 314 OUString aString = rConvertedAttribs[sStartKeyAlgNameAttribute]; 315 if (aString == sSHA256_URL || aString == sSHA256_URL_ODF12) { 316 aSequence[PKG_MNFST_STARTALG].Name = sStartKeyAlgProperty; 317 aSequence[PKG_MNFST_STARTALG].Value <<= xml::crypto::DigestID::SHA256; 318 } else if ( aString == sSHA1_Name || aString == sSHA1_URL ) { 319 aSequence[PKG_MNFST_STARTALG].Name = sStartKeyAlgProperty; 320 aSequence[PKG_MNFST_STARTALG].Value <<= xml::crypto::DigestID::SHA1; 321 } else 322 bIgnoreEncryptData = true; 323 } 324 325 void SAL_CALL ManifestImport::startElement( const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs ) 326 { 327 StringHashMap aConvertedAttribs; 328 OUString aConvertedName = PushNameAndNamespaces( aName, xAttribs, aConvertedAttribs ); 329 330 size_t nLevel = aStack.size(); 331 332 assert(nLevel >= 1); 333 334 switch (nLevel) { 335 case 1: { 336 if (aConvertedName != ELEMENT_MANIFEST) //manifest:manifest 337 aStack.back().m_bValid = false; 338 break; 339 } 340 case 2: { 341 if (aConvertedName == sFileEntryElement) //manifest:file-entry 342 doFileEntry(aConvertedAttribs); 343 else if (aConvertedName == sManifestKeyInfoElement) //loext:KeyInfo 344 doKeyInfoEntry(aConvertedAttribs); 345 else 346 aStack.back().m_bValid = false; 347 break; 348 } 349 case 3: { 350 ManifestStack::reverse_iterator aIter = aStack.rbegin(); 351 ++aIter; 352 353 if (!aIter->m_bValid) 354 aStack.back().m_bValid = false; 355 else if (aConvertedName == sEncryptionDataElement) //manifest:encryption-data 356 doEncryptionData(aConvertedAttribs); 357 else if (aConvertedName == sEncryptedKeyElement) //loext:encrypted-key 358 doEncryptedKey(aConvertedAttribs); 359 else 360 aStack.back().m_bValid = false; 361 break; 362 } 363 case 4: { 364 ManifestStack::reverse_iterator aIter = aStack.rbegin(); 365 ++aIter; 366 367 if (!aIter->m_bValid) 368 aStack.back().m_bValid = false; 369 else if (aConvertedName == sAlgorithmElement) //manifest:algorithm, 370 doAlgorithm(aConvertedAttribs); 371 else if (aConvertedName == sKeyDerivationElement) //manifest:key-derivation, 372 doKeyDerivation(aConvertedAttribs); 373 else if (aConvertedName == sStartKeyAlgElement) //manifest:start-key-generation 374 doStartKeyAlg(aConvertedAttribs); 375 else if (aConvertedName == sEncryptionMethodElement) //loext:encryption-method 376 doEncryptionMethod(aConvertedAttribs); 377 else if (aConvertedName == sKeyInfoElement) //loext:KeyInfo 378 doEncryptedKeyInfo(aConvertedAttribs); 379 else if (aConvertedName == sCipherDataElement) //loext:CipherData 380 doEncryptedCipherData(aConvertedAttribs); 381 else 382 aStack.back().m_bValid = false; 383 break; 384 } 385 case 5: { 386 ManifestStack::reverse_iterator aIter = aStack.rbegin(); 387 ++aIter; 388 389 if (!aIter->m_bValid) 390 aStack.back().m_bValid = false; 391 else if (aConvertedName == sPgpDataElement) //loext:PGPData 392 doEncryptedPgpData(aConvertedAttribs); 393 else if (aConvertedName == sCipherValueElement) //loext:CipherValue 394 // ciphervalue action happens on endElement 395 aCurrentCharacters = ""; 396 else 397 aStack.back().m_bValid = false; 398 break; 399 } 400 case 6: { 401 ManifestStack::reverse_iterator aIter = aStack.rbegin(); 402 ++aIter; 403 404 if (!aIter->m_bValid) 405 aStack.back().m_bValid = false; 406 else if (aConvertedName == sPgpKeyIDElement) //loext:PGPKeyID 407 // ciphervalue action happens on endElement 408 aCurrentCharacters = ""; 409 else if (aConvertedName == sPGPKeyPacketElement) //loext:PGPKeyPacket 410 // ciphervalue action happens on endElement 411 aCurrentCharacters = ""; 412 else 413 aStack.back().m_bValid = false; 414 break; 415 } 416 default: 417 aStack.back().m_bValid = false; 418 break; 419 } 420 } 421 422 namespace 423 { 424 bool isEmpty(const css::beans::PropertyValue &rProp) 425 { 426 return rProp.Name.isEmpty(); 427 } 428 } 429 430 void SAL_CALL ManifestImport::endElement( const OUString& aName ) 431 { 432 size_t nLevel = aStack.size(); 433 434 assert(nLevel >= 1); 435 436 OUString aConvertedName = ConvertName( aName ); 437 if ( !aStack.empty() && aStack.rbegin()->m_aConvertedName == aConvertedName ) { 438 if ( aConvertedName == sFileEntryElement && aStack.back().m_bValid ) { 439 // root folder gets KeyInfo entry if any, for PGP encryption 440 if (!bIgnoreEncryptData && !aKeys.empty() && aSequence[PKG_MNFST_FULLPATH].Value.get<OUString>() == "/" ) 441 { 442 aSequence[PKG_SIZE_NOENCR_MNFST].Name = "KeyInfo"; 443 aSequence[PKG_SIZE_NOENCR_MNFST].Value <<= comphelper::containerToSequence(aKeys); 444 } 445 css::beans::PropertyValue aEmpty; 446 aSequence.erase(std::remove_if(aSequence.begin(), aSequence.end(), 447 isEmpty), aSequence.end()); 448 449 bIgnoreEncryptData = false; 450 rManVector.push_back ( comphelper::containerToSequence(aSequence) ); 451 452 aSequence.clear(); 453 } 454 else if ( aConvertedName == sEncryptedKeyElement && aStack.back().m_bValid ) { 455 if ( !bIgnoreEncryptData ) 456 { 457 aKeys.push_back( comphelper::containerToSequence(aKeyInfoSequence) ); 458 bPgpEncryption = true; 459 } 460 aKeyInfoSequence.clear(); 461 } 462 463 // end element handling for elements with cdata 464 switch (nLevel) { 465 case 5: { 466 if (aConvertedName == sCipherValueElement) //loext:CipherValue 467 doEncryptedCipherValue(); 468 else 469 aStack.back().m_bValid = false; 470 break; 471 } 472 case 6: { 473 if (aConvertedName == sPgpKeyIDElement) //loext:PGPKeyID 474 doEncryptedKeyId(); 475 else if (aConvertedName == sPGPKeyPacketElement) //loext:PGPKeyPacket 476 doEncryptedKeyPacket(); 477 else 478 aStack.back().m_bValid = false; 479 break; 480 } 481 } 482 483 aStack.pop_back(); 484 return; 485 } 486 } 487 488 void SAL_CALL ManifestImport::characters( const OUString& aChars ) 489 { 490 aCurrentCharacters += aChars; 491 } 492 493 void SAL_CALL ManifestImport::ignorableWhitespace( const OUString& /*aWhitespaces*/ ) 494 { 495 } 496 497 void SAL_CALL ManifestImport::processingInstruction( const OUString& /*aTarget*/, const OUString& /*aData*/ ) 498 { 499 } 500 501 void SAL_CALL ManifestImport::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& /*xLocator*/ ) 502 { 503 } 504 505 OUString ManifestImport::PushNameAndNamespaces( const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs, StringHashMap& o_aConvertedAttribs ) 506 { 507 StringHashMap aNamespaces; 508 ::std::vector< ::std::pair< OUString, OUString > > aAttribsStrs; 509 510 if ( xAttribs.is() ) { 511 sal_Int16 nAttrCount = xAttribs.is() ? xAttribs->getLength() : 0; 512 aAttribsStrs.reserve( nAttrCount ); 513 514 for( sal_Int16 nInd = 0; nInd < nAttrCount; nInd++ ) { 515 OUString aAttrName = xAttribs->getNameByIndex( nInd ); 516 OUString aAttrValue = xAttribs->getValueByIndex( nInd ); 517 if ( aAttrName.getLength() >= 5 518 && aAttrName.startsWith("xmlns") 519 && ( aAttrName.getLength() == 5 || aAttrName[5] == ':' ) ) { 520 // this is a namespace declaration 521 OUString aNsName( ( aAttrName.getLength() == 5 ) ? OUString() : aAttrName.copy( 6 ) ); 522 aNamespaces[aNsName] = aAttrValue; 523 } else { 524 // this is no namespace declaration 525 aAttribsStrs.emplace_back( aAttrName, aAttrValue ); 526 } 527 } 528 } 529 530 OUString aConvertedName = ConvertNameWithNamespace( aName, aNamespaces ); 531 if ( !aConvertedName.getLength() ) 532 aConvertedName = ConvertName( aName ); 533 534 aStack.emplace_back( aConvertedName, aNamespaces ); 535 536 for (const std::pair<OUString,OUString> & rAttribsStr : aAttribsStrs) { 537 // convert the attribute names on filling 538 o_aConvertedAttribs[ConvertName( rAttribsStr.first )] = rAttribsStr.second; 539 } 540 541 return aConvertedName; 542 } 543 544 OUString ManifestImport::ConvertNameWithNamespace( const OUString& aName, const StringHashMap& aNamespaces ) 545 { 546 OUString aNsAlias; 547 OUString aPureName = aName; 548 549 sal_Int32 nInd = aName.indexOf( ':' ); 550 if ( nInd != -1 && nInd < aName.getLength() ) { 551 aNsAlias = aName.copy( 0, nInd ); 552 aPureName = aName.copy( nInd + 1 ); 553 } 554 555 OUString aResult; 556 557 StringHashMap::const_iterator aIter = aNamespaces.find( aNsAlias ); 558 if ( aIter != aNamespaces.end() 559 && ( aIter->second == MANIFEST_NAMESPACE || aIter->second == MANIFEST_OASIS_NAMESPACE ) ) { 560 // no check for manifest.xml consistency currently since the old versions have supported inconsistent documents as well 561 aResult = MANIFEST_NSPREFIX; 562 aResult += aPureName; 563 } 564 565 return aResult; 566 } 567 568 OUString ManifestImport::ConvertName( const OUString& aName ) 569 { 570 OUString aConvertedName; 571 for ( ManifestStack::reverse_iterator aIter = aStack.rbegin(); !aConvertedName.getLength() && aIter != aStack.rend(); ++aIter ) { 572 if ( !aIter->m_aNamespaces.empty() ) 573 aConvertedName = ConvertNameWithNamespace( aName, aIter->m_aNamespaces ); 574 } 575 576 if ( !aConvertedName.getLength() ) 577 aConvertedName = aName; 578 579 return aConvertedName; 580 } 581 582 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 583
