LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/svl/source/passwordcontainer - passwordcontainer.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 394 679 58.0 %
Date: 2013-07-09 Functions: 42 63 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      21             : #include "passwordcontainer.hxx"
      22             : 
      23             : #include <unotools/pathoptions.hxx>
      24             : #include <cppuhelper/factory.hxx>
      25             : #include <comphelper/processfactory.hxx>
      26             : #include <comphelper/string.hxx>
      27             : #include <com/sun/star/registry/XSimpleRegistry.hpp>
      28             : #include <com/sun/star/beans/PropertyValue.hpp>
      29             : #include <com/sun/star/task/InteractionHandler.hpp>
      30             : #include <com/sun/star/task/MasterPasswordRequest.hpp>
      31             : #include <com/sun/star/task/NoMasterException.hpp>
      32             : 
      33             : #include <rtl/cipher.h>
      34             : #include <rtl/digest.h>
      35             : #include <rtl/byteseq.hxx>
      36             : 
      37             : using namespace std;
      38             : using namespace osl;
      39             : using namespace utl;
      40             : using namespace com::sun::star;
      41             : using namespace com::sun::star::uno;
      42             : using namespace com::sun::star::registry;
      43             : using namespace com::sun::star::lang;
      44             : using namespace com::sun::star::task;
      45             : using namespace com::sun::star::ucb;
      46             : 
      47             : //-------------------------------------------------------------------------
      48             : //-------------------------------------------------------------------------
      49             : 
      50          77 : static OUString createIndex( vector< OUString > lines )
      51             : {
      52          77 :     OString aResult;
      53             :     const sal_Char* pLine;
      54             : 
      55         204 :     for( unsigned int i = 0; i < lines.size(); i++ )
      56             :     {
      57         127 :         if( i )
      58          50 :             aResult += OString( "__" );
      59         127 :         OString line = OUStringToOString( lines[i], RTL_TEXTENCODING_UTF8 );
      60         127 :         pLine = line.getStr();
      61             : 
      62        2418 :         while( *pLine )
      63             :         {
      64        2164 :             if (comphelper::string::isalnumAscii(*pLine))
      65             :             {
      66        1764 :                 aResult += OString::valueOf( *pLine );
      67             :             }
      68             :             else
      69             :             {
      70         400 :                 aResult += OString("_");
      71         400 :                 aResult += OString::valueOf( (sal_Int32) *pLine, 16 );
      72             :             }
      73             : 
      74        2164 :             pLine++;
      75             :         }
      76         127 :     }
      77             : 
      78          77 :     return OUString::createFromAscii( aResult.getStr() );
      79             : }
      80             : 
      81             : //-------------------------------------------------------------------------
      82             : 
      83          20 : static vector< OUString > getInfoFromInd( OUString aInd )
      84             : {
      85          20 :     vector< OUString > aResult;
      86          20 :     sal_Bool aStart = sal_True;
      87             : 
      88          40 :     OString line = OUStringToOString( aInd, RTL_TEXTENCODING_ASCII_US );
      89          20 :     const sal_Char* pLine = line.getStr();
      90          20 :     do
      91             :     {
      92          20 :         OUString newItem;
      93          20 :         if( !aStart )
      94           0 :             pLine += 2;
      95             :         else
      96          20 :             aStart = sal_False;
      97             : 
      98         280 :         while( *pLine && !( pLine[0] == '_' && pLine[1] == '_' ))
      99         240 :             if( *pLine != '_' )
     100             :             {
     101         200 :                 newItem += OUString::valueOf( (sal_Unicode) *pLine );
     102         200 :                 pLine++;
     103             :             }
     104             :             else
     105             :             {
     106          40 :                 OUString aNum;
     107         120 :                 for( int i = 1; i < 3; i++ )
     108             :                 {
     109          80 :                     if( !pLine[i]
     110          80 :                       ||  ( ( pLine[i] < '0' || pLine[i] > '9' )
     111          40 :                          && ( pLine[i] < 'a' || pLine[i] > 'f' )
     112           0 :                          && ( pLine[i] < 'A' || pLine[i] > 'F' ) ) )
     113             :                     {
     114             :                         OSL_FAIL( "Wrong index syntax!\n" );
     115           0 :                         return aResult;
     116             :                     }
     117             : 
     118          80 :                     aNum += OUString::valueOf( (sal_Unicode) pLine[i] );
     119             :                 }
     120             : 
     121          40 :                 newItem += OUString::valueOf( (sal_Unicode) aNum.toUInt32( 16 ) );
     122          40 :                 pLine += 3;
     123             :             }
     124             : 
     125          20 :         aResult.push_back( newItem );
     126          20 :     } while( pLine[0] == '_' && pLine[1] == '_' );
     127             : 
     128          20 :     if( *pLine )
     129             :         OSL_FAIL( "Wrong index syntax!\n" );
     130             : 
     131          20 :     return aResult;
     132             : }
     133             : 
     134             : //-------------------------------------------------------------------------
     135             : 
     136           0 : static sal_Bool shorterUrl( OUString& aURL )
     137             : {
     138           0 :     sal_Int32 aInd = aURL.lastIndexOf( sal_Unicode( '/' ) );
     139           0 :     if( aInd > 0 && aURL.indexOf( "://" ) != aInd-2 )
     140             :     {
     141           0 :         aURL = aURL.copy( 0, aInd );
     142           0 :         return sal_True;
     143             :     }
     144             : 
     145           0 :     return sal_False;
     146             : }
     147             : 
     148             : //-------------------------------------------------------------------------
     149             : 
     150          27 : static OUString getAsciiLine( const ::rtl::ByteSequence& buf )
     151             : {
     152          27 :     OUString aResult;
     153             : 
     154          54 :     ::rtl::ByteSequence outbuf( buf.getLength()*2+1 );
     155             : 
     156         518 :     for( int ind = 0; ind < buf.getLength(); ind++ )
     157             :     {
     158         491 :         outbuf[ind*2]   = ( ((sal_uInt8)buf[ind]) >> 4 ) + 'a';
     159         491 :         outbuf[ind*2+1] = ( ((sal_uInt8)buf[ind]) & 0x0f ) + 'a';
     160             :     }
     161          27 :     outbuf[buf.getLength()*2] = '\0';
     162             : 
     163          27 :     aResult = OUString::createFromAscii( (sal_Char*)outbuf.getArray() );
     164             : 
     165          54 :     return aResult;
     166             : }
     167             : 
     168             : //-------------------------------------------------------------------------
     169             : 
     170          20 : static ::rtl::ByteSequence getBufFromAsciiLine( OUString line )
     171             : {
     172             :     OSL_ENSURE( line.getLength() % 2 == 0, "Wrong syntax!\n" );
     173          20 :     OString tmpLine = OUStringToOString( line, RTL_TEXTENCODING_ASCII_US );
     174          20 :     ::rtl::ByteSequence aResult(line.getLength()/2);
     175             : 
     176         360 :     for( int ind = 0; ind < tmpLine.getLength()/2; ind++ )
     177             :     {
     178         340 :         aResult[ind] = ( (sal_uInt8)( tmpLine.getStr()[ind*2] - 'a' ) << 4 ) | (sal_uInt8)( tmpLine.getStr()[ind*2+1] - 'a' );
     179             :     }
     180             : 
     181          20 :     return aResult;
     182             : }
     183             : 
     184             : //-------------------------------------------------------------------------
     185             : 
     186          40 : static Sequence< OUString > copyVectorToSequence( const vector< OUString >& original )
     187             : {
     188          40 :     Sequence< OUString > newOne ( original.size() );
     189          80 :     for( unsigned int i = 0; i < original.size() ; i++ )
     190          40 :         newOne[i] = original[i];
     191             : 
     192          40 :     return newOne;
     193             : }
     194             : 
     195          45 : static vector< OUString > copySequenceToVector( const Sequence< OUString >& original )
     196             : {
     197          45 :     vector< OUString > newOne ( original.getLength() );
     198          90 :     for( int i = 0; i < original.getLength() ; i++ )
     199          45 :         newOne[i] = original[i];
     200             : 
     201          45 :     return newOne;
     202             : }
     203             : 
     204             : //-------------------------------------------------------------------------
     205             : //-------------------------------------------------------------------------
     206             : 
     207           0 : PassMap StorageItem::getInfo()
     208             : {
     209           0 :     PassMap aResult;
     210             : 
     211           0 :     Sequence< OUString > aNodeNames     = ConfigItem::GetNodeNames( OUString("Store") );
     212           0 :     sal_Int32 aNodeCount = aNodeNames.getLength();
     213           0 :     Sequence< OUString > aPropNames( aNodeCount );
     214             :     sal_Int32 aNodeInd;
     215             : 
     216           0 :     for( aNodeInd = 0; aNodeInd < aNodeCount; ++aNodeInd )
     217             :     {
     218           0 :         aPropNames[aNodeInd]  = OUString("Store/Passwordstorage['");
     219           0 :         aPropNames[aNodeInd] += aNodeNames[aNodeInd];
     220           0 :         aPropNames[aNodeInd] += OUString("']/Password");
     221             :     }
     222             : 
     223           0 :     Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aPropNames );
     224             : 
     225           0 :     if( aPropertyValues.getLength() != aNodeNames.getLength() )
     226             :     {
     227             :         OSL_ENSURE( aPropertyValues.getLength() == aNodeNames.getLength(), "Problems during reading\n" );
     228           0 :         return aResult;
     229             :     }
     230             : 
     231           0 :     for( aNodeInd = 0; aNodeInd < aNodeCount; ++aNodeInd )
     232             :     {
     233           0 :         vector< OUString > aUrlUsr = getInfoFromInd( aNodeNames[aNodeInd] );
     234             : 
     235           0 :         if( aUrlUsr.size() == 2 )
     236             :         {
     237           0 :             OUString aUrl  = aUrlUsr[0];
     238           0 :             OUString aName = aUrlUsr[1];
     239             : 
     240           0 :             OUString aEPasswd;
     241           0 :             aPropertyValues[aNodeInd] >>= aEPasswd;
     242             : 
     243           0 :             PassMap::iterator aIter = aResult.find( aUrl );
     244           0 :             if( aIter != aResult.end() )
     245           0 :                 aIter->second.push_back( NamePassRecord( aName, aEPasswd ) );
     246             :             else
     247             :             {
     248           0 :                 NamePassRecord aNewRecord( aName, aEPasswd );
     249           0 :                 list< NamePassRecord > listToAdd( 1, aNewRecord );
     250             : 
     251           0 :                 aResult.insert( PairUrlRecord( aUrl, listToAdd ) );
     252           0 :             }
     253             :         }
     254             :         else
     255             :             OSL_FAIL( "Wrong index sintax!\n" );
     256           0 :     }
     257             : 
     258           0 :     return aResult;
     259             : }
     260             : 
     261             : //-------------------------------------------------------------------------
     262             : 
     263           4 : void StorageItem::setUseStorage( bool bUse )
     264             : {
     265           4 :     Sequence< OUString > sendNames(1);
     266           8 :     Sequence< uno::Any > sendVals(1);
     267             : 
     268           4 :     sendNames[0] = OUString("UseStorage");
     269             : 
     270           4 :     sendVals[0] <<= bUse;
     271             : 
     272           4 :     ConfigItem::SetModified();
     273           8 :     ConfigItem::PutProperties( sendNames, sendVals );
     274           4 : }
     275             : 
     276             : //-------------------------------------------------------------------------
     277             : 
     278          52 : bool StorageItem::useStorage()
     279             : {
     280          52 :     Sequence< OUString > aNodeNames( 1 );
     281          52 :     aNodeNames[0] = OUString("UseStorage");
     282             : 
     283         104 :     Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aNodeNames );
     284             : 
     285          52 :     if( aPropertyValues.getLength() != aNodeNames.getLength() )
     286             :     {
     287             :         OSL_ENSURE( aPropertyValues.getLength() == aNodeNames.getLength(), "Problems during reading\n" );
     288           0 :         return sal_False;
     289             :     }
     290             : 
     291          52 :     bool aResult = false;
     292          52 :     aPropertyValues[0] >>= aResult;
     293             : 
     294         104 :     return aResult;
     295             : }
     296             : 
     297             : //-------------------------------------------------------------------------
     298             : 
     299           2 : bool StorageItem::getEncodedMP( OUString& aResult )
     300             : {
     301           2 :     if( hasEncoded )
     302             :     {
     303           0 :         aResult = mEncoded;
     304           0 :         return true;
     305             :     }
     306             : 
     307           2 :     Sequence< OUString > aNodeNames( 2 );
     308           2 :     aNodeNames[0] = OUString("HasMaster");
     309           2 :     aNodeNames[1] = OUString("Master");
     310             : 
     311           4 :     Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aNodeNames );
     312             : 
     313           2 :     if( aPropertyValues.getLength() != aNodeNames.getLength() )
     314             :     {
     315             :         OSL_ENSURE( aPropertyValues.getLength() == aNodeNames.getLength(), "Problems during reading\n" );
     316           0 :         return false;
     317             :     }
     318             : 
     319           2 :     aPropertyValues[0] >>= hasEncoded;
     320           2 :     aPropertyValues[1] >>= mEncoded;
     321             : 
     322           2 :     aResult = mEncoded;
     323             : 
     324           4 :     return hasEncoded;
     325             : }
     326             : 
     327             : //-------------------------------------------------------------------------
     328             : 
     329           4 : void StorageItem::setEncodedMP( const OUString& aEncoded, bool bAcceptEmpty )
     330             : {
     331           4 :     Sequence< OUString > sendNames(2);
     332           8 :     Sequence< uno::Any > sendVals(2);
     333             : 
     334           4 :     sendNames[0] = OUString("HasMaster");
     335           4 :     sendNames[1] = OUString("Master");
     336             : 
     337           4 :     sal_Bool bHasMaster = ( !aEncoded.isEmpty() || bAcceptEmpty );
     338           4 :     sendVals[0] <<= bHasMaster;
     339           4 :     sendVals[1] <<= aEncoded;
     340             : 
     341           4 :     ConfigItem::SetModified();
     342           4 :     ConfigItem::PutProperties( sendNames, sendVals );
     343             : 
     344           4 :     hasEncoded = bHasMaster;
     345           8 :     mEncoded = aEncoded;
     346           4 : }
     347             : 
     348             : //-------------------------------------------------------------------------
     349             : 
     350          25 : void StorageItem::remove( const OUString& aURL, const OUString& aName )
     351             : {
     352          25 :     vector < OUString > forIndex;
     353          25 :     forIndex.push_back( aURL );
     354          25 :     forIndex.push_back( aName );
     355             : 
     356          50 :     Sequence< OUString > sendSeq(1);
     357             : 
     358          25 :     sendSeq[0] = createIndex( forIndex );
     359             : 
     360          50 :     ConfigItem::ClearNodeElements( OUString("Store"), sendSeq );
     361          25 : }
     362             : 
     363             : //-------------------------------------------------------------------------
     364             : 
     365           4 : void StorageItem::clear()
     366             : {
     367           4 :     Sequence< OUString > sendSeq(1);
     368             : 
     369           4 :     ConfigItem::ClearNodeSet( OUString("Store") );
     370           4 : }
     371             : 
     372             : //-------------------------------------------------------------------------
     373             : 
     374          25 : void StorageItem::update( const OUString& aURL, const NamePassRecord& aRecord )
     375             : {
     376          25 :     if ( !aRecord.HasPasswords( PERSISTENT_RECORD ) )
     377             :     {
     378             :         OSL_FAIL( "Unexpected storing of a record!" );
     379          25 :         return;
     380             :     }
     381             : 
     382          25 :     vector < OUString > forIndex;
     383          25 :     forIndex.push_back( aURL );
     384          25 :     forIndex.push_back( aRecord.GetUserName() );
     385             : 
     386          50 :     Sequence< beans::PropertyValue > sendSeq(1);
     387             : 
     388          25 :     sendSeq[0].Name  = OUString("Store/Passwordstorage['");
     389          25 :     sendSeq[0].Name += createIndex( forIndex );
     390          25 :     sendSeq[0].Name += OUString("']/Password");
     391             : 
     392          25 :     sendSeq[0].Value <<= aRecord.GetPersPasswords();
     393             : 
     394          25 :     ConfigItem::SetModified();
     395          50 :     ConfigItem::SetSetProperties( OUString("Store"), sendSeq );
     396             : }
     397             : 
     398             : //-------------------------------------------------------------------------
     399             : 
     400           0 : void StorageItem::Notify( const Sequence< OUString >& )
     401             : {
     402             :     // this feature still should not be used
     403           0 :     if( mainCont )
     404           0 :         mainCont->Notify();
     405           0 : }
     406             : 
     407             : //-------------------------------------------------------------------------
     408             : 
     409           1 : void StorageItem::Commit()
     410             : {
     411             :     // Do nothing, we stored everything we want already
     412           1 : }
     413             : 
     414             : //-------------------------------------------------------------------------
     415             : //-------------------------------------------------------------------------
     416             : 
     417           1 : PasswordContainer::PasswordContainer( const Reference<XMultiServiceFactory>& xServiceFactory ):
     418           1 :     m_pStorageFile( NULL )
     419             : {
     420             :     // m_pStorageFile->Notify() can be called
     421           1 :     ::osl::MutexGuard aGuard( mMutex );
     422             : 
     423           1 :     mComponent = Reference< XComponent >( xServiceFactory, UNO_QUERY );
     424           1 :     mComponent->addEventListener( this );
     425             : 
     426           1 :     m_pStorageFile = new StorageItem( this, OUString("Office.Common/Passwords") );
     427           1 :     if( m_pStorageFile )
     428           1 :         if( m_pStorageFile->useStorage() )
     429           0 :             m_aContainer = m_pStorageFile->getInfo();
     430           1 : }
     431             : 
     432             : //-------------------------------------------------------------------------
     433             : 
     434           3 : PasswordContainer::~PasswordContainer()
     435             : {
     436           1 :     ::osl::MutexGuard aGuard( mMutex );
     437             : 
     438           1 :     if( m_pStorageFile )
     439             :     {
     440           0 :         delete m_pStorageFile;
     441           0 :         m_pStorageFile = NULL;
     442             :     }
     443             : 
     444           1 :     if( mComponent.is() )
     445             :     {
     446           0 :         mComponent->removeEventListener(this);
     447           0 :         mComponent.clear();
     448           1 :     }
     449           2 : }
     450             : 
     451             : //-------------------------------------------------------------------------
     452             : 
     453           1 : void SAL_CALL PasswordContainer::disposing( const EventObject& ) throw(RuntimeException)
     454             : {
     455           1 :     ::osl::MutexGuard aGuard( mMutex );
     456             : 
     457           1 :     if( m_pStorageFile )
     458             :     {
     459           1 :         delete m_pStorageFile;
     460           1 :         m_pStorageFile = NULL;
     461             :     }
     462             : 
     463           1 :     if( mComponent.is() )
     464             :     {
     465             :         //mComponent->removeEventListener(this);
     466           1 :         mComponent.clear();
     467           1 :     }
     468           1 : }
     469             : 
     470             : //-------------------------------------------------------------------------
     471             : 
     472          20 : vector< OUString > PasswordContainer::DecodePasswords( const OUString& aLine, const OUString& aMasterPasswd ) throw(RuntimeException)
     473             : {
     474          20 :     if( !aMasterPasswd.isEmpty() )
     475             :     {
     476          20 :         rtlCipher aDecoder = rtl_cipher_create (rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream );
     477             :         OSL_ENSURE( aDecoder, "Can't create decoder\n" );
     478             : 
     479          20 :         if( aDecoder )
     480             :         {
     481             :             OSL_ENSURE( aMasterPasswd.getLength() == RTL_DIGEST_LENGTH_MD5 * 2, "Wrong master password format!\n" );
     482             : 
     483             :             unsigned char code[RTL_DIGEST_LENGTH_MD5];
     484         340 :             for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ )
     485         320 :                 code[ ind ] = (char)(aMasterPasswd.copy( ind*2, 2 ).toUInt32(16));
     486             : 
     487             :             rtlCipherError result = rtl_cipher_init (
     488             :                     aDecoder, rtl_Cipher_DirectionDecode,
     489          20 :                     code, RTL_DIGEST_LENGTH_MD5, NULL, 0 );
     490             : 
     491          20 :             if( result == rtl_Cipher_E_None )
     492             :             {
     493          20 :                 ::rtl::ByteSequence aSeq = getBufFromAsciiLine( aLine );
     494             : 
     495          40 :                 ::rtl::ByteSequence resSeq( aSeq.getLength() );
     496             : 
     497          40 :                 result = rtl_cipher_decode ( aDecoder, (sal_uInt8*)aSeq.getArray(), aSeq.getLength(),
     498          60 :                                                         (sal_uInt8*)resSeq.getArray(), resSeq.getLength() );
     499             : 
     500          40 :                 OUString aPasswd( ( sal_Char* )resSeq.getArray(), resSeq.getLength(), RTL_TEXTENCODING_UTF8 );
     501             : 
     502          20 :                 rtl_cipher_destroy (aDecoder);
     503             : 
     504          60 :                 return getInfoFromInd( aPasswd );
     505             :             }
     506             : 
     507           0 :             rtl_cipher_destroy (aDecoder);
     508             :         }
     509             :     }
     510             :     else
     511             :     {
     512             :         OSL_FAIL( "No master password provided!\n" );
     513             :         // throw special exception
     514             :     }
     515             : 
     516             :     // problems with decoding
     517             :     OSL_FAIL( "Problem with decoding\n" );
     518           0 :     throw RuntimeException("Can't decode!", Reference< XInterface >() );
     519             : }
     520             : 
     521             : 
     522             : //-------------------------------------------------------------------------
     523             : 
     524          27 : OUString PasswordContainer::EncodePasswords( vector< OUString > lines, const OUString& aMasterPasswd ) throw(RuntimeException)
     525             : {
     526          27 :     if( !aMasterPasswd.isEmpty() )
     527             :     {
     528          27 :         OString aSeq = OUStringToOString( createIndex( lines ), RTL_TEXTENCODING_UTF8 );
     529             : 
     530          27 :         rtlCipher aEncoder = rtl_cipher_create (rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream );
     531             :         OSL_ENSURE( aEncoder, "Can't create encoder\n" );
     532             : 
     533          27 :         if( aEncoder )
     534             :         {
     535             :             OSL_ENSURE( aMasterPasswd.getLength() == RTL_DIGEST_LENGTH_MD5 * 2, "Wrong master password format!\n" );
     536             : 
     537             :             unsigned char code[RTL_DIGEST_LENGTH_MD5];
     538         459 :             for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ )
     539         432 :                 code[ ind ] = (char)(aMasterPasswd.copy( ind*2, 2 ).toUInt32(16));
     540             : 
     541             :             rtlCipherError result = rtl_cipher_init (
     542             :                     aEncoder, rtl_Cipher_DirectionEncode,
     543          27 :                     code, RTL_DIGEST_LENGTH_MD5, NULL, 0 );
     544             : 
     545          27 :             if( result == rtl_Cipher_E_None )
     546             :             {
     547          27 :                 ::rtl::ByteSequence resSeq(aSeq.getLength()+1);
     548             : 
     549          54 :                 result = rtl_cipher_encode ( aEncoder, (sal_uInt8*)aSeq.getStr(), aSeq.getLength()+1,
     550          81 :                                                         (sal_uInt8*)resSeq.getArray(), resSeq.getLength() );
     551             : 
     552             : /*
     553             :                 //test
     554             :                 rtlCipherError result = rtl_cipher_init (
     555             :                     aEncoder, rtl_Cipher_DirectionDecode,
     556             :                     code, RTL_DIGEST_LENGTH_MD5, NULL, 0 );
     557             : 
     558             : 
     559             :                 if( result == rtl_Cipher_E_None )
     560             :                 {
     561             :                     OUString testOU = getAsciiLine( resSeq );
     562             :                     ::rtl::ByteSequence aSeq1 = getBufFromAsciiLine( testOU );
     563             : 
     564             :                     ::rtl::ByteSequence resSeq1( aSeq1.getLength() );
     565             : 
     566             :                     if( resSeq.getLength() == aSeq1.getLength() )
     567             :                     {
     568             :                         for( int ind = 0; ind < aSeq1.getLength(); ind++ )
     569             :                             if( resSeq[ind] != aSeq1[ind] )
     570             :                                 testOU = OUString();
     571             :                     }
     572             : 
     573             :                     result = rtl_cipher_decode ( aEncoder, (sal_uInt8*)aSeq1.getArray(), aSeq1.getLength(),
     574             :                                                         (sal_uInt8*)resSeq1.getArray(), resSeq1.getLength() );
     575             : 
     576             :                     OUString aPasswd( ( sal_Char* )resSeq1.getArray(), resSeq1.getLength(), RTL_TEXTENCODING_UTF8 );
     577             :                 }
     578             : */
     579             : 
     580          27 :                 rtl_cipher_destroy (aEncoder);
     581             : 
     582          27 :                 if( result == rtl_Cipher_E_None )
     583          54 :                     return getAsciiLine( resSeq );
     584             : 
     585             :             }
     586             : 
     587           0 :             rtl_cipher_destroy (aEncoder);
     588           0 :         }
     589             :     }
     590             :     else
     591             :     {
     592             :         OSL_FAIL( "No master password provided!\n" );
     593             :         // throw special exception
     594             :     }
     595             : 
     596             :     // problems with encoding
     597             :     OSL_FAIL( "Problem with encoding\n" );
     598           0 :     throw RuntimeException("Can't encode!", Reference< XInterface >() );
     599             : }
     600             : 
     601             : //-------------------------------------------------------------------------
     602             : 
     603          42 : void PasswordContainer::UpdateVector( const OUString& aURL, list< NamePassRecord >& toUpdate, NamePassRecord& aRecord, bool writeFile ) throw(RuntimeException)
     604             : {
     605         357 :     for( list< NamePassRecord >::iterator aNPIter = toUpdate.begin(); aNPIter != toUpdate.end(); ++aNPIter )
     606         315 :         if( aNPIter->GetUserName().equals( aRecord.GetUserName() ) )
     607             :         {
     608           0 :             if( aRecord.HasPasswords( MEMORY_RECORD ) )
     609           0 :                 aNPIter->SetMemPasswords( aRecord.GetMemPasswords() );
     610             : 
     611           0 :             if( aRecord.HasPasswords( PERSISTENT_RECORD ) )
     612             :             {
     613           0 :                 aNPIter->SetPersPasswords( aRecord.GetPersPasswords() );
     614             : 
     615           0 :                 if( writeFile )
     616             :                 {
     617             :                     // the password must be already encoded
     618           0 :                     m_pStorageFile->update( aURL, aRecord ); // change existing ( aURL, aName ) record in the configfile
     619             :                 }
     620             :             }
     621             : 
     622          42 :             return;
     623             :         }
     624             : 
     625             : 
     626          42 :     if( aRecord.HasPasswords( PERSISTENT_RECORD ) && writeFile )
     627             :     {
     628             :         // the password must be already encoded
     629          23 :         m_pStorageFile->update( aURL, aRecord ); // add new aName to the existing url
     630             :     }
     631             : 
     632          42 :     toUpdate.insert( toUpdate.begin(), aRecord );
     633             : }
     634             : 
     635             : //-------------------------------------------------------------------------
     636             : 
     637          35 : UserRecord PasswordContainer::CopyToUserRecord( const NamePassRecord& aRecord, bool& io_bTryToDecode, const Reference< XInteractionHandler >& aHandler )
     638             : {
     639          35 :     ::std::vector< OUString > aPasswords;
     640          35 :     if( aRecord.HasPasswords( MEMORY_RECORD ) )
     641          20 :         aPasswords = aRecord.GetMemPasswords();
     642             : 
     643          35 :     if( io_bTryToDecode && aRecord.HasPasswords( PERSISTENT_RECORD ) )
     644             :     {
     645             :         try
     646             :         {
     647          15 :             ::std::vector< OUString > aDecodedPasswords = DecodePasswords( aRecord.GetPersPasswords(), GetMasterPassword( aHandler ) );
     648          15 :             aPasswords.insert( aPasswords.end(), aDecodedPasswords.begin(), aDecodedPasswords.end() );
     649             :         }
     650           0 :         catch( NoMasterException& )
     651             :         {
     652             :             // if master password could not be detected the entry will be just ignored
     653           0 :             io_bTryToDecode = false;
     654             :         }
     655             :     }
     656             : 
     657          35 :     return UserRecord( aRecord.GetUserName(), copyVectorToSequence( aPasswords ) );
     658             : }
     659             : 
     660             : //-------------------------------------------------------------------------
     661             : 
     662           5 : Sequence< UserRecord > PasswordContainer::CopyToUserRecordSequence( const list< NamePassRecord >& original, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
     663             : {
     664           5 :     Sequence< UserRecord >     aResult( original.size() );
     665           5 :     sal_uInt32 nInd = 0;
     666           5 :     bool bTryToDecode = true;
     667             : 
     668         120 :     for( list< NamePassRecord >::const_iterator aNPIter = original.begin();
     669          80 :          aNPIter != original.end();
     670             :          ++aNPIter, ++nInd )
     671             :     {
     672          35 :         aResult[nInd] = CopyToUserRecord( *aNPIter, bTryToDecode, aHandler );
     673             :     }
     674             : 
     675           5 :     return aResult;
     676             : }
     677             : 
     678             : //-------------------------------------------------------------------------
     679             : 
     680          20 : void SAL_CALL PasswordContainer::add( const OUString& Url, const OUString& UserName, const Sequence< OUString >& Passwords, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
     681             : {
     682          20 :     ::osl::MutexGuard aGuard( mMutex );
     683             : 
     684          20 :     PrivateAdd( Url, UserName, Passwords, MEMORY_RECORD, aHandler );
     685          20 : }
     686             : 
     687             : //-------------------------------------------------------------------------
     688             : 
     689          25 : void SAL_CALL PasswordContainer::addPersistent( const OUString& Url, const OUString& UserName, const Sequence< OUString >& Passwords, const Reference< XInteractionHandler >& aHandler  ) throw(RuntimeException)
     690             : {
     691          25 :     ::osl::MutexGuard aGuard( mMutex );
     692             : 
     693          25 :     PrivateAdd( Url, UserName, Passwords, PERSISTENT_RECORD, aHandler );
     694          25 : }
     695             : 
     696             : //-------------------------------------------------------------------------
     697             : 
     698          45 : void PasswordContainer::PrivateAdd( const OUString& Url, const OUString& UserName, const Sequence< OUString >& Passwords, char Mode, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
     699             : {
     700          45 :     NamePassRecord aRecord( UserName );
     701          48 :     ::std::vector< OUString > aStorePass = copySequenceToVector( Passwords );
     702             : 
     703          45 :     if( Mode == PERSISTENT_RECORD )
     704          25 :         aRecord.SetPersPasswords( EncodePasswords( aStorePass, GetMasterPassword( aHandler ) ) );
     705          20 :     else if( Mode == MEMORY_RECORD )
     706          20 :         aRecord.SetMemPasswords( aStorePass );
     707             :     else
     708             :     {
     709             :         OSL_FAIL( "Unexpected persistence status!" );
     710           0 :         return;
     711             :     }
     712             : 
     713          45 :     if( !m_aContainer.empty() )
     714             :     {
     715          42 :         PassMap::iterator aIter = m_aContainer.find( Url );
     716             : 
     717          42 :         if( aIter != m_aContainer.end() )
     718             :         {
     719          42 :             UpdateVector( aIter->first, aIter->second, aRecord, sal_True );
     720          42 :             return;
     721             :         }
     722             :     }
     723             : 
     724           6 :     list< NamePassRecord > listToAdd( 1, aRecord );
     725           3 :     m_aContainer.insert( PairUrlRecord( Url, listToAdd ) );
     726             : 
     727           3 :     if( Mode == PERSISTENT_RECORD && m_pStorageFile && m_pStorageFile->useStorage() )
     728           5 :         m_pStorageFile->update( Url, aRecord );
     729             : 
     730             : }
     731             : 
     732             : //-------------------------------------------------------------------------
     733             : 
     734             : 
     735           5 : UrlRecord SAL_CALL PasswordContainer::find( const OUString& aURL, const Reference< XInteractionHandler >& aHandler  ) throw(RuntimeException)
     736             : {
     737           5 :     return find( aURL, OUString(), false, aHandler );
     738             : }
     739             : 
     740             : //-------------------------------------------------------------------------
     741             : 
     742           0 : UrlRecord SAL_CALL PasswordContainer::findForName( const OUString& aURL, const OUString& aName, const Reference< XInteractionHandler >& aHandler  ) throw(RuntimeException)
     743             : {
     744           0 :     return find( aURL, aName, true, aHandler );
     745             : }
     746             : 
     747             : //-------------------------------------------------------------------------
     748             : 
     749           0 : Sequence< UserRecord > PasswordContainer::FindUsr( const list< NamePassRecord >& userlist, const OUString& aName, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
     750             : {
     751           0 :     sal_uInt32 nInd = 0;
     752           0 :     for( list< NamePassRecord >::const_iterator aNPIter = userlist.begin();
     753           0 :          aNPIter != userlist.end();
     754             :          ++aNPIter, ++nInd )
     755             :     {
     756           0 :         if( aNPIter->GetUserName().equals( aName ) )
     757             :         {
     758           0 :             Sequence< UserRecord > aResult(1);
     759           0 :             bool bTryToDecode = true;
     760           0 :             aResult[0] = CopyToUserRecord( *aNPIter, bTryToDecode, aHandler );
     761             : 
     762           0 :             return aResult;
     763             :         }
     764             :     }
     765             : 
     766           0 :     return Sequence< UserRecord >();
     767             : }
     768             : 
     769             : //-------------------------------------------------------------------------
     770             : 
     771           5 : bool PasswordContainer::createUrlRecord(
     772             :     const PassMap::iterator & rIter,
     773             :     bool bName,
     774             :     const OUString & aName,
     775             :     const Reference< XInteractionHandler >& aHandler,
     776             :     UrlRecord & rRec )
     777             :         throw( RuntimeException )
     778             : {
     779           5 :     if ( bName )
     780             :     {
     781             :         Sequence< UserRecord > aUsrRec
     782           0 :             = FindUsr( rIter->second, aName, aHandler );
     783           0 :         if( aUsrRec.getLength() )
     784             :         {
     785           0 :             rRec = UrlRecord( rIter->first, aUsrRec );
     786           0 :             return true;
     787           0 :         }
     788             :     }
     789             :     else
     790             :     {
     791          15 :         rRec = UrlRecord(
     792           5 :             rIter->first,
     793          10 :             CopyToUserRecordSequence( rIter->second, aHandler ) );
     794           5 :         return true;
     795             :     }
     796           0 :     return false;
     797             : }
     798             : 
     799             : //-------------------------------------------------------------------------
     800             : 
     801           5 : UrlRecord PasswordContainer::find(
     802             :     const OUString& aURL,
     803             :     const OUString& aName,
     804             :     bool bName, // only needed to support empty user names
     805             :     const Reference< XInteractionHandler >& aHandler  ) throw(RuntimeException)
     806             : {
     807           5 :     ::osl::MutexGuard aGuard( mMutex );
     808             : 
     809           5 :     if( !m_aContainer.empty() && !aURL.isEmpty() )
     810             :     {
     811           5 :         OUString aUrl( aURL );
     812             : 
     813             :         // each iteration remove last '/...' section from the aUrl
     814             :         // while it's possible, up to the most left '://'
     815           0 :         do
     816             :         {
     817             :             // first look for <url>/somename and then look for <url>/somename/...
     818           5 :             PassMap::iterator aIter = m_aContainer.find( aUrl );
     819           5 :             if( aIter != m_aContainer.end() )
     820             :             {
     821           5 :                 UrlRecord aRec;
     822           5 :                 if ( createUrlRecord( aIter, bName, aName, aHandler, aRec ) )
     823           5 :                   return aRec;
     824             :             }
     825             :             else
     826             :             {
     827           0 :                 OUString tmpUrl( aUrl );
     828           0 :                 if ( tmpUrl.getStr()[tmpUrl.getLength() - 1] != (sal_Unicode)'/' )
     829           0 :                     tmpUrl += OUString("/");
     830             : 
     831           0 :                 aIter = m_aContainer.lower_bound( tmpUrl );
     832           0 :                 if( aIter != m_aContainer.end() && aIter->first.match( tmpUrl ) )
     833             :                 {
     834           0 :                     UrlRecord aRec;
     835           0 :                     if ( createUrlRecord( aIter, bName, aName, aHandler, aRec ) )
     836           0 :                       return aRec;
     837           0 :                 }
     838             :             }
     839             :         }
     840           0 :         while( shorterUrl( aUrl ) && !aUrl.isEmpty() );
     841             :     }
     842             : 
     843           0 :     return UrlRecord();
     844             : }
     845             : 
     846             : //-------------------------------------------------------------------------
     847           0 : OUString PasswordContainer::GetDefaultMasterPassword()
     848             : {
     849           0 :     OUString aResult;
     850           0 :     for ( sal_Int32 nInd = 0; nInd < RTL_DIGEST_LENGTH_MD5; nInd++ )
     851           0 :         aResult += OUString( "aa"  );
     852             : 
     853           0 :     return aResult;
     854             : }
     855             : 
     856             : //-------------------------------------------------------------------------
     857           2 : OUString PasswordContainer::RequestPasswordFromUser( PasswordRequestMode aRMode, const uno::Reference< task::XInteractionHandler >& xHandler )
     858             : {
     859             :     // empty string means that the call was cancelled or just failed
     860           2 :     OUString aResult;
     861             : 
     862           2 :     if ( xHandler.is() )
     863             :     {
     864           2 :         ::rtl::Reference< MasterPasswordRequest_Impl > xRequest = new MasterPasswordRequest_Impl( aRMode );
     865             : 
     866           2 :         xHandler->handle( xRequest.get() );
     867             : 
     868           4 :         ::rtl::Reference< ucbhelper::InteractionContinuation > xSelection = xRequest->getSelection();
     869             : 
     870           2 :         if ( xSelection.is() )
     871             :         {
     872           2 :             Reference< XInteractionAbort > xAbort( xSelection.get(), UNO_QUERY );
     873           2 :             if ( !xAbort.is() )
     874             :             {
     875             :                 const ::rtl::Reference< ucbhelper::InteractionSupplyAuthentication > & xSupp
     876           2 :                             = xRequest->getAuthenticationSupplier();
     877             : 
     878           2 :                 aResult = xSupp->getPassword();
     879           2 :             }
     880           2 :         }
     881             :     }
     882             : 
     883           2 :     return aResult;
     884             : }
     885             : 
     886             : //-------------------------------------------------------------------------
     887             : 
     888          45 : OUString PasswordContainer::GetMasterPassword( const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
     889             : {
     890          45 :     PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_ENTER;
     891          45 :     if( !m_pStorageFile || !m_pStorageFile->useStorage() )
     892           0 :         throw NoMasterException("Password storing is not active!", Reference< XInterface >(), aRMode );
     893             : 
     894          45 :     if( m_aMasterPasswd.isEmpty() && aHandler.is() )
     895             :     {
     896           2 :         OUString aEncodedMP;
     897           2 :         sal_Bool bAskAgain = sal_False;
     898           2 :         sal_Bool bDefaultPassword = sal_False;
     899             : 
     900           2 :         if( !m_pStorageFile->getEncodedMP( aEncodedMP ) )
     901           2 :             aRMode = PasswordRequestMode_PASSWORD_CREATE;
     902           0 :         else if ( aEncodedMP.isEmpty() )
     903             :         {
     904           0 :             m_aMasterPasswd = GetDefaultMasterPassword();
     905           0 :             bDefaultPassword = sal_True;
     906             :         }
     907             : 
     908           2 :         if ( !bDefaultPassword )
     909             :         {
     910           2 :             do {
     911           2 :                 bAskAgain = sal_False;
     912             : 
     913           2 :                 OUString aPass = RequestPasswordFromUser( aRMode, aHandler );
     914           2 :                 if ( !aPass.isEmpty() )
     915             :                 {
     916           2 :                     if( aRMode == PasswordRequestMode_PASSWORD_CREATE )
     917             :                     {
     918           2 :                         m_aMasterPasswd = aPass;
     919           2 :                         vector< OUString > aMaster( 1, m_aMasterPasswd );
     920             : 
     921           2 :                         m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, m_aMasterPasswd ) );
     922             :                     }
     923             :                     else
     924             :                     {
     925           0 :                         vector< OUString > aRM( DecodePasswords( aEncodedMP, aPass ) );
     926           0 :                         if( aRM.empty() || !aPass.equals( aRM[0] ) )
     927             :                         {
     928           0 :                             bAskAgain = sal_True;
     929           0 :                             aRMode = PasswordRequestMode_PASSWORD_REENTER;
     930             :                         }
     931             :                         else
     932           0 :                             m_aMasterPasswd = aPass;
     933             :                     }
     934           2 :                 }
     935             : 
     936             :             } while( bAskAgain );
     937           2 :         }
     938             :     }
     939             : 
     940          45 :     if ( m_aMasterPasswd.isEmpty() )
     941           0 :         throw NoMasterException("No master password!", Reference< XInterface >(), aRMode );
     942             : 
     943          45 :     return m_aMasterPasswd;
     944             : }
     945             : 
     946             : //-------------------------------------------------------------------------
     947             : 
     948          35 : void SAL_CALL PasswordContainer::remove( const OUString& aURL, const OUString& aName ) throw(RuntimeException)
     949             : {
     950          35 :     ::osl::MutexGuard aGuard( mMutex );
     951             : 
     952          40 :     OUString aUrl( aURL );
     953          35 :     if( !m_aContainer.empty() )
     954             :     {
     955          30 :         PassMap::iterator aIter = m_aContainer.find( aUrl );
     956             : 
     957          30 :         if( aIter == m_aContainer.end() )
     958             :         {
     959           0 :             sal_Int32 aInd = aUrl.lastIndexOf( sal_Unicode( '/' ) );
     960           0 :             if( aInd > 0 && aUrl.getLength()-1 == aInd )
     961           0 :                 aUrl = aUrl.copy( 0, aUrl.getLength() - 1 );
     962             :             else
     963           0 :                 aUrl += OUString("/");
     964             : 
     965           0 :             aIter = m_aContainer.find( aUrl );
     966             :         }
     967             : 
     968          30 :         if( aIter != m_aContainer.end() )
     969             :         {
     970         220 :             for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); ++aNPIter )
     971         220 :                 if( aNPIter->GetUserName().equals( aName ) )
     972             :                 {
     973          30 :                     if( aNPIter->HasPasswords( PERSISTENT_RECORD ) && m_pStorageFile )
     974          10 :                         m_pStorageFile->remove( aURL, aName ); // remove record ( aURL, aName )
     975             : 
     976             :                     // the iterator will not be used any more so it can be removed directly
     977          30 :                     aIter->second.erase( aNPIter );
     978             : 
     979          30 :                     if( aIter->second.begin() == aIter->second.end() )
     980           2 :                         m_aContainer.erase( aIter );
     981             : 
     982          65 :                     return;
     983             :                 }
     984             :         }
     985           5 :     }
     986             : }
     987             : 
     988             : //-------------------------------------------------------------------------
     989             : 
     990           0 : void SAL_CALL PasswordContainer::removePersistent( const OUString& aURL, const OUString& aName ) throw(RuntimeException)
     991             : {
     992           0 :     ::osl::MutexGuard aGuard( mMutex );
     993             : 
     994           0 :     OUString aUrl( aURL );
     995           0 :     if( !m_aContainer.empty() )
     996             :     {
     997           0 :         PassMap::iterator aIter = m_aContainer.find( aUrl );
     998             : 
     999           0 :         if( aIter == m_aContainer.end() )
    1000             :         {
    1001           0 :             sal_Int32 aInd = aUrl.lastIndexOf( sal_Unicode( '/' ) );
    1002           0 :             if( aInd > 0 && aUrl.getLength()-1 == aInd )
    1003           0 :                 aUrl = aUrl.copy( 0, aUrl.getLength() - 1 );
    1004             :             else
    1005           0 :                 aUrl += OUString("/");
    1006             : 
    1007           0 :             aIter = m_aContainer.find( aUrl );
    1008             :         }
    1009             : 
    1010           0 :         if( aIter != m_aContainer.end() )
    1011             :         {
    1012           0 :             for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); ++aNPIter )
    1013           0 :                 if( aNPIter->GetUserName().equals( aName ) )
    1014             :                 {
    1015           0 :                     if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
    1016             :                     {
    1017             :                         // TODO/LATER: should the password be converted to MemoryPassword?
    1018           0 :                         aNPIter->RemovePasswords( PERSISTENT_RECORD );
    1019             : 
    1020           0 :                         if ( m_pStorageFile )
    1021           0 :                             m_pStorageFile->remove( aURL, aName ); // remove record ( aURL, aName )
    1022             :                     }
    1023             : 
    1024           0 :                     if( !aNPIter->HasPasswords( MEMORY_RECORD ) )
    1025           0 :                         aIter->second.erase( aNPIter );
    1026             : 
    1027           0 :                     if( aIter->second.begin() == aIter->second.end() )
    1028           0 :                         m_aContainer.erase( aIter );
    1029             : 
    1030           0 :                     return;
    1031             :                 }
    1032             :         }
    1033           0 :     }
    1034             : }
    1035             : //-------------------------------------------------------------------------
    1036             : 
    1037           4 : void SAL_CALL PasswordContainer::removeAllPersistent() throw(RuntimeException)
    1038             : {
    1039           4 :     ::osl::MutexGuard aGuard( mMutex );
    1040             : 
    1041           4 :     if( m_pStorageFile )
    1042           4 :         m_pStorageFile->clear();
    1043             : 
    1044          10 :     for( PassMap::iterator aIter = m_aContainer.begin(); aIter != m_aContainer.end(); )
    1045             :     {
    1046          24 :         for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); )
    1047             :         {
    1048          20 :             if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
    1049             :             {
    1050             :                 // TODO/LATER: should the password be converted to MemoryPassword?
    1051          15 :                 aNPIter->RemovePasswords( PERSISTENT_RECORD );
    1052             : 
    1053          15 :                 if ( m_pStorageFile )
    1054          15 :                     m_pStorageFile->remove( aIter->first, aNPIter->GetUserName() ); // remove record ( aURL, aName )
    1055             :             }
    1056             : 
    1057          20 :             if( !aNPIter->HasPasswords( MEMORY_RECORD ) )
    1058             :             {
    1059          15 :                 list< NamePassRecord >::iterator aIterToDelete( aNPIter );
    1060          15 :                 ++aNPIter;
    1061          15 :                 aIter->second.erase( aIterToDelete );
    1062             :             }
    1063             :             else
    1064           5 :                 ++aNPIter;
    1065             :         }
    1066             : 
    1067           2 :         if( aIter->second.begin() == aIter->second.end() )
    1068             :         {
    1069           1 :             PassMap::iterator aIterToDelete( aIter );
    1070           1 :             ++aIter;
    1071           1 :             m_aContainer.erase( aIterToDelete );
    1072             :         }
    1073             :         else
    1074           1 :             ++aIter;
    1075           4 :     }
    1076           4 : }
    1077             : //-------------------------------------------------------------------------
    1078             : 
    1079           1 : Sequence< UrlRecord > SAL_CALL PasswordContainer::getAllPersistent( const Reference< XInteractionHandler >& xHandler ) throw(RuntimeException)
    1080             : {
    1081           1 :     Sequence< UrlRecord > aResult;
    1082             : 
    1083           2 :     ::osl::MutexGuard aGuard( mMutex );
    1084           2 :     for( PassMap::iterator aIter = m_aContainer.begin(); aIter != m_aContainer.end(); ++aIter )
    1085             :     {
    1086           1 :         Sequence< UserRecord > aUsers;
    1087           6 :         for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); ++aNPIter )
    1088           5 :             if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
    1089             :             {
    1090           5 :                 sal_Int32 oldLen = aUsers.getLength();
    1091           5 :                 aUsers.realloc( oldLen + 1 );
    1092           5 :                 aUsers[ oldLen ] = UserRecord( aNPIter->GetUserName(), copyVectorToSequence( DecodePasswords( aNPIter->GetPersPasswords(), GetMasterPassword( xHandler ) ) ) );
    1093             :             }
    1094             : 
    1095           1 :         if( aUsers.getLength() )
    1096             :         {
    1097           1 :             sal_Int32 oldLen = aResult.getLength();
    1098           1 :             aResult.realloc( oldLen + 1 );
    1099           1 :             aResult[ oldLen ] = UrlRecord( aIter->first, aUsers );
    1100             :         }
    1101           1 :     }
    1102             : 
    1103           2 :     return aResult;
    1104             : }
    1105             : 
    1106             : //-------------------------------------------------------------------------
    1107           0 : sal_Bool SAL_CALL PasswordContainer::authorizateWithMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler )
    1108             :     throw (uno::RuntimeException)
    1109             : {
    1110           0 :     sal_Bool bResult = sal_False;
    1111           0 :     OUString aEncodedMP;
    1112           0 :     uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler;
    1113           0 :     ::osl::MutexGuard aGuard( mMutex );
    1114             : 
    1115             :     // the method should fail if there is no master password
    1116           0 :     if( m_pStorageFile && m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) )
    1117             :     {
    1118           0 :         if ( aEncodedMP.isEmpty() )
    1119             :         {
    1120             :             // this is a default master password
    1121             :             // no UI is necessary
    1122           0 :             bResult = sal_True;
    1123             :         }
    1124             :         else
    1125             :         {
    1126           0 :             if ( !xTmpHandler.is() )
    1127             :             {
    1128           0 :                 uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW );
    1129           0 :                 uno::Reference< uno::XComponentContext > xContext( comphelper::getComponentContext(xFactory) );
    1130           0 :                 xTmpHandler.set( InteractionHandler::createWithParent(xContext, 0), uno::UNO_QUERY_THROW );
    1131             :             }
    1132             : 
    1133           0 :             if ( !m_aMasterPasswd.isEmpty() )
    1134             :             {
    1135             :                 // there is a password, it should be just rechecked
    1136           0 :                 PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_ENTER;
    1137           0 :                 OUString aPass;
    1138             : 
    1139           0 :                 do {
    1140           0 :                     aPass = RequestPasswordFromUser( aRMode, xTmpHandler );
    1141           0 :                     bResult = ( !aPass.isEmpty() && aPass.equals( m_aMasterPasswd ) );
    1142           0 :                     aRMode = PasswordRequestMode_PASSWORD_REENTER; // further questions with error notification
    1143           0 :                 } while( !bResult && !aPass.isEmpty() );
    1144             :             }
    1145             :             else
    1146             :             {
    1147             :                 try
    1148             :                 {
    1149             :                     // ask for the password, if user provide no correct password an exception will be thrown
    1150           0 :                     bResult = !GetMasterPassword( xTmpHandler ).isEmpty();
    1151             :                 }
    1152           0 :                 catch( uno::Exception& )
    1153             :                 {}
    1154             :             }
    1155             :         }
    1156             :     }
    1157             : 
    1158           0 :     return bResult;
    1159             : }
    1160             : 
    1161             : //-------------------------------------------------------------------------
    1162           0 : sal_Bool SAL_CALL PasswordContainer::changeMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler )
    1163             :     throw (uno::RuntimeException)
    1164             : {
    1165           0 :     sal_Bool bResult = sal_False;
    1166           0 :     uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler;
    1167           0 :     ::osl::MutexGuard aGuard( mMutex );
    1168             : 
    1169           0 :     if ( m_pStorageFile && m_pStorageFile->useStorage() )
    1170             :     {
    1171           0 :         if ( !xTmpHandler.is() )
    1172             :         {
    1173           0 :             uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW );
    1174           0 :             uno::Reference< uno::XComponentContext > xContext( comphelper::getComponentContext(xFactory) );
    1175           0 :             xTmpHandler.set( InteractionHandler::createWithParent(xContext, 0), uno::UNO_QUERY_THROW );
    1176             :         }
    1177             : 
    1178           0 :         sal_Bool bCanChangePassword = sal_True;
    1179             :         // if there is already a stored master password it should be entered by the user before the change happen
    1180           0 :         OUString aEncodedMP;
    1181           0 :         if( !m_aMasterPasswd.isEmpty() || m_pStorageFile->getEncodedMP( aEncodedMP ) )
    1182           0 :             bCanChangePassword = authorizateWithMasterPassword( xTmpHandler );
    1183             : 
    1184           0 :         if ( bCanChangePassword )
    1185             :         {
    1186             :             // ask for the new password, but do not set it
    1187           0 :             PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_CREATE;
    1188           0 :             OUString aPass = RequestPasswordFromUser( aRMode, xTmpHandler );
    1189             : 
    1190           0 :             if ( !aPass.isEmpty() )
    1191             :             {
    1192             :                 // get all the persistent entries if it is possible
    1193           0 :                 Sequence< UrlRecord > aPersistent = getAllPersistent( uno::Reference< task::XInteractionHandler >() );
    1194             : 
    1195             :                 // remove the master password and the entries persistence
    1196           0 :                 removeMasterPassword();
    1197             : 
    1198             :                 // store the new master password
    1199           0 :                 m_aMasterPasswd = aPass;
    1200           0 :                 vector< OUString > aMaster( 1, m_aMasterPasswd );
    1201           0 :                 m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, m_aMasterPasswd ) );
    1202             : 
    1203             :                 // store all the entries with the new password
    1204           0 :                 for ( int nURLInd = 0; nURLInd < aPersistent.getLength(); nURLInd++ )
    1205           0 :                     for ( int nNameInd = 0; nNameInd< aPersistent[nURLInd].UserList.getLength(); nNameInd++ )
    1206           0 :                         addPersistent( aPersistent[nURLInd].Url,
    1207           0 :                                        aPersistent[nURLInd].UserList[nNameInd].UserName,
    1208           0 :                                        aPersistent[nURLInd].UserList[nNameInd].Passwords,
    1209           0 :                                        uno::Reference< task::XInteractionHandler >() );
    1210             : 
    1211           0 :                 bResult = sal_True;
    1212           0 :             }
    1213           0 :         }
    1214             :     }
    1215             : 
    1216           0 :     return bResult;
    1217             : }
    1218             : 
    1219             : //-------------------------------------------------------------------------
    1220           2 : void SAL_CALL PasswordContainer::removeMasterPassword()
    1221             :     throw (uno::RuntimeException)
    1222             : {
    1223             :     // remove all the stored passwords and the master password
    1224           2 :     removeAllPersistent();
    1225             : 
    1226           2 :     ::osl::MutexGuard aGuard( mMutex );
    1227           2 :     if ( m_pStorageFile )
    1228             :     {
    1229           2 :         m_aMasterPasswd = OUString();
    1230           2 :         m_pStorageFile->setEncodedMP( OUString() ); // let the master password be removed from configuration
    1231           2 :     }
    1232           2 : }
    1233             : 
    1234             : //-------------------------------------------------------------------------
    1235           0 : ::sal_Bool SAL_CALL PasswordContainer::hasMasterPassword(  )
    1236             :     throw (::com::sun::star::uno::RuntimeException)
    1237             : {
    1238           0 :     ::osl::MutexGuard aGuard( mMutex );
    1239             : 
    1240           0 :     if ( !m_pStorageFile )
    1241           0 :         throw uno::RuntimeException();
    1242             : 
    1243           0 :     OUString aEncodedMP;
    1244           0 :     return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) );
    1245             : }
    1246             : 
    1247             : //-------------------------------------------------------------------------
    1248           4 : ::sal_Bool SAL_CALL PasswordContainer::allowPersistentStoring( ::sal_Bool bAllow )
    1249             :     throw (::com::sun::star::uno::RuntimeException)
    1250             : {
    1251           4 :     ::osl::MutexGuard aGuard( mMutex );
    1252             : 
    1253           4 :     if ( !m_pStorageFile )
    1254           0 :         throw uno::RuntimeException();
    1255             : 
    1256           4 :     if ( !bAllow )
    1257           2 :         removeMasterPassword();
    1258             : 
    1259           4 :     if (m_pStorageFile->useStorage() == static_cast<bool>(bAllow))
    1260           0 :         return bAllow;
    1261             : 
    1262           4 :     m_pStorageFile->setUseStorage( bAllow );
    1263           4 :     return !bAllow;
    1264             : }
    1265             : 
    1266             : //-------------------------------------------------------------------------
    1267           0 : ::sal_Bool SAL_CALL PasswordContainer::isPersistentStoringAllowed()
    1268             :     throw (::com::sun::star::uno::RuntimeException)
    1269             : {
    1270           0 :     ::osl::MutexGuard aGuard( mMutex );
    1271             : 
    1272           0 :     if ( !m_pStorageFile )
    1273           0 :         throw uno::RuntimeException();
    1274             : 
    1275           0 :     return m_pStorageFile->useStorage();
    1276             : }
    1277             : 
    1278             : //-------------------------------------------------------------------------
    1279           0 : ::sal_Bool SAL_CALL PasswordContainer::useDefaultMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler )
    1280             :     throw ( uno::RuntimeException )
    1281             : {
    1282           0 :     sal_Bool bResult = sal_False;
    1283           0 :     uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler;
    1284           0 :     ::osl::MutexGuard aGuard( mMutex );
    1285             : 
    1286           0 :     if ( m_pStorageFile && m_pStorageFile->useStorage() )
    1287             :     {
    1288           0 :         if ( !xTmpHandler.is() )
    1289             :         {
    1290           0 :             uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW );
    1291           0 :             uno::Reference< uno::XComponentContext > xContext( comphelper::getComponentContext(xFactory) );
    1292           0 :             xTmpHandler.set( InteractionHandler::createWithParent(xContext, 0), uno::UNO_QUERY_THROW );
    1293             :         }
    1294             : 
    1295           0 :         sal_Bool bCanChangePassword = sal_True;
    1296             :         // if there is already a stored nondefault master password it should be entered by the user before the change happen
    1297           0 :         OUString aEncodedMP;
    1298           0 :         if( m_pStorageFile->getEncodedMP( aEncodedMP ) && !aEncodedMP.isEmpty() )
    1299           0 :             bCanChangePassword = authorizateWithMasterPassword( xTmpHandler );
    1300             : 
    1301           0 :         if ( bCanChangePassword )
    1302             :         {
    1303             :             // generate the default password
    1304           0 :             OUString aPass = GetDefaultMasterPassword();
    1305           0 :             if ( !aPass.isEmpty() )
    1306             :             {
    1307             :                 // get all the persistent entries if it is possible
    1308           0 :                 Sequence< UrlRecord > aPersistent = getAllPersistent( uno::Reference< task::XInteractionHandler >() );
    1309             : 
    1310             :                 // remove the master password and the entries persistence
    1311           0 :                 removeMasterPassword();
    1312             : 
    1313             :                 // store the empty string to flag the default master password
    1314           0 :                 m_aMasterPasswd = aPass;
    1315           0 :                 m_pStorageFile->setEncodedMP( OUString(), sal_True );
    1316             : 
    1317             :                 // store all the entries with the new password
    1318           0 :                 for ( int nURLInd = 0; nURLInd < aPersistent.getLength(); nURLInd++ )
    1319           0 :                     for ( int nNameInd = 0; nNameInd< aPersistent[nURLInd].UserList.getLength(); nNameInd++ )
    1320           0 :                         addPersistent( aPersistent[nURLInd].Url,
    1321           0 :                                        aPersistent[nURLInd].UserList[nNameInd].UserName,
    1322           0 :                                        aPersistent[nURLInd].UserList[nNameInd].Passwords,
    1323           0 :                                        uno::Reference< task::XInteractionHandler >() );
    1324             : 
    1325           0 :                 bResult = sal_True;
    1326           0 :             }
    1327           0 :         }
    1328             :     }
    1329             : 
    1330           0 :     return bResult;
    1331             : 
    1332             : }
    1333             : 
    1334             : //-------------------------------------------------------------------------
    1335           0 : ::sal_Bool SAL_CALL PasswordContainer::isDefaultMasterPasswordUsed()
    1336             :     throw ( uno::RuntimeException )
    1337             : {
    1338           0 :     ::osl::MutexGuard aGuard( mMutex );
    1339             : 
    1340           0 :     if ( !m_pStorageFile )
    1341           0 :         throw uno::RuntimeException();
    1342             : 
    1343           0 :     OUString aEncodedMP;
    1344           0 :     return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) && aEncodedMP.isEmpty() );
    1345             : }
    1346             : 
    1347             : 
    1348             : //-------------------------------------------------------------------------
    1349           0 : void SAL_CALL PasswordContainer::addUrl( const OUString& Url, ::sal_Bool MakePersistent )
    1350             :     throw (uno::RuntimeException)
    1351             : {
    1352           0 :     mUrlContainer.add( Url, MakePersistent );
    1353           0 : }
    1354             : 
    1355             : //-------------------------------------------------------------------------
    1356           0 : OUString SAL_CALL PasswordContainer::findUrl( const OUString& Url )
    1357             :     throw (uno::RuntimeException)
    1358             : {
    1359           0 :     return mUrlContainer.find( Url );
    1360             : }
    1361             : 
    1362             : //-------------------------------------------------------------------------
    1363           0 : void SAL_CALL PasswordContainer::removeUrl( const OUString& Url )
    1364             :     throw (uno::RuntimeException)
    1365             : {
    1366           0 :     mUrlContainer.remove( Url );
    1367           0 : }
    1368             : 
    1369             : //-------------------------------------------------------------------------
    1370           0 : uno::Sequence< OUString > SAL_CALL PasswordContainer::getUrls( ::sal_Bool OnlyPersistent )
    1371             :     throw (uno::RuntimeException)
    1372             : {
    1373           0 :     return mUrlContainer.list( OnlyPersistent );
    1374             : }
    1375             : 
    1376             : //-------------------------------------------------------------------------
    1377             : 
    1378           0 : void PasswordContainer::Notify()
    1379             : {
    1380           0 :     ::osl::MutexGuard aGuard( mMutex );
    1381             : 
    1382           0 :     PassMap::iterator aIter;
    1383             : 
    1384             :     // remove the cached persistent values in the memory
    1385           0 :     for( aIter = m_aContainer.begin(); aIter != m_aContainer.end(); ++aIter )
    1386             :     {
    1387           0 :         for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); )
    1388             :         {
    1389           0 :             if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
    1390             :             {
    1391           0 :                 aNPIter->RemovePasswords( PERSISTENT_RECORD );
    1392             : 
    1393           0 :                 if ( m_pStorageFile )
    1394           0 :                     m_pStorageFile->remove( aIter->first, aNPIter->GetUserName() ); // remove record ( aURL, aName )
    1395             :             }
    1396             : 
    1397           0 :             if( !aNPIter->HasPasswords( MEMORY_RECORD ) )
    1398             :             {
    1399           0 :                 list< NamePassRecord >::iterator aIterToDelete( aNPIter );
    1400           0 :                 ++aNPIter;
    1401           0 :                 aIter->second.erase( aIterToDelete );
    1402             :             }
    1403             :             else
    1404           0 :                 ++aNPIter;
    1405             :         }
    1406             :     }
    1407             : 
    1408           0 :     PassMap addon;
    1409           0 :     if( m_pStorageFile )
    1410           0 :         addon = m_pStorageFile->getInfo();
    1411             : 
    1412           0 :     for( aIter = addon.begin(); aIter != addon.end(); ++aIter )
    1413             :     {
    1414           0 :         PassMap::iterator aSearchIter = m_aContainer.find( aIter->first );
    1415           0 :         if( aSearchIter != m_aContainer.end() )
    1416           0 :             for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); ++aNPIter )
    1417           0 :                 UpdateVector( aSearchIter->first, aSearchIter->second, *aNPIter, sal_False );
    1418             :         else
    1419           0 :             m_aContainer.insert( PairUrlRecord( aIter->first, aIter->second ) );
    1420           0 :     }
    1421           0 : }
    1422             : 
    1423             : //-------------------------------------------------------------------------
    1424             : 
    1425           0 : OUString SAL_CALL PasswordContainer::getImplementationName(  ) throw(uno::RuntimeException)
    1426             : {
    1427           0 :     return impl_getStaticImplementationName();
    1428             : }
    1429             : 
    1430             : //-------------------------------------------------------------------------
    1431             : 
    1432           0 : sal_Bool SAL_CALL PasswordContainer::supportsService( const OUString& ServiceName ) throw(uno::RuntimeException)
    1433             : {
    1434           0 :     if ( ServiceName.compareToAscii("com.sun.star.task.PasswordContainer") == 0 )
    1435           0 :         return sal_True;
    1436             :     else
    1437           0 :         return sal_False;
    1438             : }
    1439             : 
    1440             : //-------------------------------------------------------------------------
    1441             : 
    1442           0 : Sequence< OUString > SAL_CALL PasswordContainer::getSupportedServiceNames(  ) throw(uno::RuntimeException)
    1443             : {
    1444           0 :     return impl_getStaticSupportedServiceNames();
    1445             : }
    1446             : 
    1447             : //-------------------------------------------------------------------------
    1448             : 
    1449           1 : Sequence< OUString > SAL_CALL PasswordContainer::impl_getStaticSupportedServiceNames(  ) throw(uno::RuntimeException)
    1450             : {
    1451           1 :     Sequence< OUString > aRet(1);
    1452           1 :     *aRet.getArray() = OUString("com.sun.star.task.PasswordContainer");
    1453           1 :     return aRet;
    1454             : }
    1455             : 
    1456             : //-------------------------------------------------------------------------
    1457             : 
    1458           2 : OUString SAL_CALL PasswordContainer::impl_getStaticImplementationName() throw(uno::RuntimeException)
    1459             : {
    1460           2 :     return OUString("stardiv.svl.PasswordContainer");
    1461             : }
    1462             : 
    1463             : //-------------------------------------------------------------------------
    1464             : 
    1465           1 : Reference< XInterface > SAL_CALL PasswordContainer::impl_createInstance( const Reference< XMultiServiceFactory >& xServiceManager ) throw( RuntimeException )
    1466             : {
    1467           1 :     return Reference< XInterface >( *new PasswordContainer( xServiceManager ) );
    1468             : }
    1469             : 
    1470             : //-------------------------------------------------------------------------
    1471             : 
    1472           1 : Reference< XSingleServiceFactory > SAL_CALL PasswordContainer::impl_createFactory( const Reference< XMultiServiceFactory >& ServiceManager ) throw(RuntimeException)
    1473             : {
    1474             :     Reference< XSingleServiceFactory > xReturn( ::cppu::createOneInstanceFactory( ServiceManager,
    1475             :                                                         PasswordContainer::impl_getStaticImplementationName(),
    1476             :                                                         PasswordContainer::impl_createInstance,
    1477           1 :                                                         PasswordContainer::impl_getStaticSupportedServiceNames()));
    1478           1 :     return xReturn ;
    1479             : 
    1480             : }
    1481             : 
    1482             : //-------------------------------------------------------------------------
    1483             : //-------------------------------------------------------------------------
    1484             : 
    1485           2 : MasterPasswordRequest_Impl::MasterPasswordRequest_Impl( PasswordRequestMode Mode )
    1486             : {
    1487           2 :     MasterPasswordRequest aRequest;
    1488             : 
    1489           2 :     aRequest.Classification = InteractionClassification_ERROR;
    1490           2 :     aRequest.Mode = Mode;
    1491             : 
    1492           2 :     setRequest( makeAny( aRequest ) );
    1493             : 
    1494             :     // Fill continuations...
    1495           4 :     Sequence< RememberAuthentication > aRememberModes( 1 );
    1496           2 :     aRememberModes[ 0 ] = RememberAuthentication_NO;
    1497             : 
    1498             :     m_xAuthSupplier
    1499           4 :         = new ::ucbhelper::InteractionSupplyAuthentication(
    1500             :                 this,
    1501             :                 sal_False, // bCanSetRealm
    1502             :                 sal_False,  // bCanSetUserName
    1503             :                 sal_True,  // bCanSetPassword
    1504             :                 sal_False, // bCanSetAccount
    1505             :                 aRememberModes, // rRememberPasswordModes
    1506             :                 RememberAuthentication_NO, // eDefaultRememberPasswordMode
    1507             :                 aRememberModes, // rRememberAccountModes
    1508             :                 RememberAuthentication_NO, // eDefaultRememberAccountMode
    1509             :                 sal_False, // bCanUseSystemCredentials
    1510             :                 sal_False  // bDefaultUseSystemCredentials
    1511           4 :             );
    1512             : 
    1513             :     Sequence<
    1514           4 :         Reference< XInteractionContinuation > > aContinuations( 3 );
    1515           2 :     aContinuations[ 0 ] = new ::ucbhelper::InteractionAbort( this );
    1516           2 :     aContinuations[ 1 ] = new ::ucbhelper::InteractionRetry( this );
    1517           2 :     aContinuations[ 2 ] = m_xAuthSupplier.get();
    1518             : 
    1519           4 :     setContinuations( aContinuations );
    1520           2 : }
    1521             : 
    1522             : //-------------------------------------------------------------------------
    1523             : //-------------------------------------------------------------------------
    1524             : 
    1525             : extern "C"
    1526             : {
    1527           1 : SAL_DLLPUBLIC_EXPORT void * SAL_CALL passwordcontainer_component_getFactory (
    1528             :     const sal_Char * pImplementationName,
    1529             :     SAL_UNUSED_PARAMETER void * pServiceManager,
    1530             :     SAL_UNUSED_PARAMETER void * /* pRegistryKey */)
    1531             : {
    1532           1 :     void * pResult = 0;
    1533           1 :     if (pServiceManager)
    1534             :     {
    1535           1 :         Reference< XSingleServiceFactory > xFactory;
    1536           1 :         if (PasswordContainer::impl_getStaticImplementationName().compareToAscii (pImplementationName) == 0)
    1537             :         {
    1538           2 :             xFactory = PasswordContainer::impl_createFactory (
    1539           1 :                 reinterpret_cast< XMultiServiceFactory* >(pServiceManager));
    1540             :         }
    1541           1 :         if (xFactory.is())
    1542             :         {
    1543           1 :             xFactory->acquire();
    1544           1 :             pResult = xFactory.get();
    1545           1 :         }
    1546             :     }
    1547           1 :     return pResult;
    1548             : }
    1549             : 
    1550             : } // extern "C"
    1551             : 
    1552             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10