diff options
Diffstat (limited to 'svl/source/passwordcontainer/passwordcontainer.cxx')
-rw-r--r-- | svl/source/passwordcontainer/passwordcontainer.cxx | 1588 |
1 files changed, 1588 insertions, 0 deletions
diff --git a/svl/source/passwordcontainer/passwordcontainer.cxx b/svl/source/passwordcontainer/passwordcontainer.cxx new file mode 100644 index 000000000000..4d629958e5bf --- /dev/null +++ b/svl/source/passwordcontainer/passwordcontainer.cxx @@ -0,0 +1,1588 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: passwordcontainer.cxx,v $ + * $Revision: 1.17 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svl.hxx" + +#include "passwordcontainer.hxx" + +#include <unotools/pathoptions.hxx> +#include "cppuhelper/factory.hxx" +#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/task/MasterPasswordRequest.hpp> +#include <com/sun/star/task/NoMasterException.hpp> + +#include <rtl/cipher.h> +#include <rtl/digest.h> +#include <rtl/byteseq.hxx> + +#ifndef _TOOLS_INETSTRM_HXX +// @@@ #include <inetstrm.hxx> +#endif + +using namespace std; +using namespace osl; +using namespace utl; +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::registry; +using namespace com::sun::star::lang; +using namespace com::sun::star::task; +using namespace com::sun::star::ucb; + +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- + +static ::rtl::OUString createIndex( vector< ::rtl::OUString > lines ) +{ + ::rtl::OString aResult; + const sal_Char* pLine; + + for( unsigned int i = 0; i < lines.size(); i++ ) + { + if( i ) + aResult += ::rtl::OString( "__" ); + ::rtl::OString line = ::rtl::OUStringToOString( lines[i], RTL_TEXTENCODING_UTF8 ); + pLine = line.getStr(); + + while( *pLine ) + { + if( ( *pLine >= 'A' && *pLine <= 'Z' ) + || ( *pLine >= 'a' && *pLine <= 'z' ) + || ( *pLine >= '0' && *pLine <= '9' ) ) + { + aResult += ::rtl::OString::valueOf( *pLine ); + } + else + { + aResult += ::rtl::OString("_"); + aResult += ::rtl::OString::valueOf( (sal_Int32) *pLine, 16 ); + } + + pLine++; + } + } + + return ::rtl::OUString::createFromAscii( aResult.getStr() ); +} + +//------------------------------------------------------------------------- + +static vector< ::rtl::OUString > getInfoFromInd( ::rtl::OUString aInd ) +{ + vector< ::rtl::OUString > aResult; + sal_Bool aStart = sal_True; + + ::rtl::OString line = ::rtl::OUStringToOString( aInd, RTL_TEXTENCODING_ASCII_US ); + const sal_Char* pLine = line.getStr(); + do + { + ::rtl::OUString newItem; + if( !aStart ) + pLine += 2; + else + aStart = sal_False; + + while( *pLine && !( pLine[0] == '_' && pLine[1] == '_' )) + if( *pLine != '_' ) + { + newItem += ::rtl::OUString::valueOf( (sal_Unicode) *pLine ); + pLine++; + } + else + { + ::rtl::OUString aNum; + for( int i = 1; i < 3; i++ ) + { + if( !pLine[i] + || ( ( pLine[i] < '0' || pLine[i] > '9' ) + && ( pLine[i] < 'a' || pLine[i] > 'f' ) + && ( pLine[i] < 'A' || pLine[i] > 'F' ) ) ) + { + OSL_ENSURE( sal_False, "Wrong index syntax!\n" ); + return aResult; + } + + aNum += ::rtl::OUString::valueOf( (sal_Unicode) pLine[i] ); + } + + newItem += ::rtl::OUString::valueOf( (sal_Unicode) aNum.toInt32( 16 ) ); + pLine += 3; + } + + aResult.push_back( newItem ); + } while( pLine[0] == '_' && pLine[1] == '_' ); + + if( *pLine ) + OSL_ENSURE( sal_False, "Wrong index syntax!\n" ); + + return aResult; +} + +//------------------------------------------------------------------------- + +static sal_Bool shorterUrl( ::rtl::OUString& aURL ) +{ + sal_Int32 aInd = aURL.lastIndexOf( sal_Unicode( '/' ) ); + if( aInd > 0 && aURL.indexOf( ::rtl::OUString::createFromAscii( "://" ) ) != aInd-2 ) + { + aURL = aURL.copy( 0, aInd ); + return sal_True; + } + + return sal_False; +} + +//------------------------------------------------------------------------- + +static ::rtl::OUString getAsciiLine( const ::rtl::ByteSequence& buf ) +{ + ::rtl::OUString aResult; + + ::rtl::ByteSequence outbuf( buf.getLength()*2+1 ); + + for( int ind = 0; ind < buf.getLength(); ind++ ) + { + outbuf[ind*2] = ( ((sal_uInt8)buf[ind]) >> 4 ) + 'a'; + outbuf[ind*2+1] = ( ((sal_uInt8)buf[ind]) & 0x0f ) + 'a'; + } + outbuf[buf.getLength()*2] = '\0'; + + aResult = ::rtl::OUString::createFromAscii( (sal_Char*)outbuf.getArray() ); + + return aResult; +} + +//------------------------------------------------------------------------- + +static ::rtl::ByteSequence getBufFromAsciiLine( ::rtl::OUString line ) +{ + OSL_ENSURE( line.getLength() % 2 == 0, "Wrong syntax!\n" ); + ::rtl::OString tmpLine = ::rtl::OUStringToOString( line, RTL_TEXTENCODING_ASCII_US ); + ::rtl::ByteSequence aResult(line.getLength()/2); + + for( int ind = 0; ind < tmpLine.getLength()/2; ind++ ) + { + aResult[ind] = ( (sal_uInt8)( tmpLine.getStr()[ind*2] - 'a' ) << 4 ) | (sal_uInt8)( tmpLine.getStr()[ind*2+1] - 'a' ); + } + + return aResult; +} + +//------------------------------------------------------------------------- + +static Sequence< ::rtl::OUString > copyVectorToSequence( const vector< ::rtl::OUString >& original ) +{ + Sequence< ::rtl::OUString > newOne ( original.size() ); + for( unsigned int i = 0; i < original.size() ; i++ ) + newOne[i] = original[i]; + + return newOne; +} + +static vector< ::rtl::OUString > copySequenceToVector( const Sequence< ::rtl::OUString >& original ) +{ + vector< ::rtl::OUString > newOne ( original.getLength() ); + for( int i = 0; i < original.getLength() ; i++ ) + newOne[i] = original[i]; + + return newOne; +} + +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- + +PassMap StorageItem::getInfo() +{ + PassMap aResult; + + Sequence< ::rtl::OUString > aNodeNames = ConfigItem::GetNodeNames( ::rtl::OUString::createFromAscii("Store") ); + sal_Int32 aNodeCount = aNodeNames.getLength(); + Sequence< ::rtl::OUString > aPropNames( aNodeCount ); + sal_Int32 aNodeInd; + + for( aNodeInd = 0; aNodeInd < aNodeCount; ++aNodeInd ) + { + aPropNames[aNodeInd] = ::rtl::OUString::createFromAscii( "Store/Passwordstorage['" ); + aPropNames[aNodeInd] += aNodeNames[aNodeInd]; + aPropNames[aNodeInd] += ::rtl::OUString::createFromAscii( "']/Password" ); + } + + Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aPropNames ); + + if( aPropertyValues.getLength() != aNodeNames.getLength() ) + { + OSL_ENSURE( aPropertyValues.getLength() == aNodeNames.getLength(), "Problems during reading\n" ); + return aResult; + } + + for( aNodeInd = 0; aNodeInd < aNodeCount; ++aNodeInd ) + { + vector< ::rtl::OUString > aUrlUsr = getInfoFromInd( aNodeNames[aNodeInd] ); + + if( aUrlUsr.size() == 2 ) + { + ::rtl::OUString aUrl = aUrlUsr[0]; + ::rtl::OUString aName = aUrlUsr[1]; + + ::rtl::OUString aEPasswd; + aPropertyValues[aNodeInd] >>= aEPasswd; + + PassMap::iterator aIter = aResult.find( aUrl ); + if( aIter != aResult.end() ) + aIter->second.push_back( NamePassRecord( aName, aEPasswd ) ); + else + { + NamePassRecord aNewRecord( aName, aEPasswd ); + list< NamePassRecord > listToAdd( 1, aNewRecord ); + + aResult.insert( PairUrlRecord( aUrl, listToAdd ) ); + } + } + else + OSL_ENSURE( sal_False, "Wrong index sintax!\n" ); + } + + return aResult; +} + +//------------------------------------------------------------------------- + +void StorageItem::setUseStorage( sal_Bool bUse ) +{ + Sequence< ::rtl::OUString > sendNames(1); + Sequence< uno::Any > sendVals(1); + + sendNames[0] = ::rtl::OUString::createFromAscii( "UseStorage" ); + + sendVals[0] <<= bUse; + + ConfigItem::SetModified(); + ConfigItem::PutProperties( sendNames, sendVals ); +} + +//------------------------------------------------------------------------- + +sal_Bool StorageItem::useStorage() +{ + Sequence< ::rtl::OUString > aNodeNames( 1 ); + aNodeNames[0] = ::rtl::OUString::createFromAscii( "UseStorage" ); + + Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aNodeNames ); + + if( aPropertyValues.getLength() != aNodeNames.getLength() ) + { + OSL_ENSURE( aPropertyValues.getLength() == aNodeNames.getLength(), "Problems during reading\n" ); + return sal_False; + } + + sal_Bool aResult = false; + aPropertyValues[0] >>= aResult; + + return aResult; +} + +//------------------------------------------------------------------------- + +sal_Bool StorageItem::getEncodedMP( ::rtl::OUString& aResult ) +{ + if( hasEncoded ) + { + aResult = mEncoded; + return sal_True; + } + + Sequence< ::rtl::OUString > aNodeNames( 2 ); + aNodeNames[0] = ::rtl::OUString::createFromAscii( "HasMaster" ); + aNodeNames[1] = ::rtl::OUString::createFromAscii( "Master" ); + + Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aNodeNames ); + + if( aPropertyValues.getLength() != aNodeNames.getLength() ) + { + OSL_ENSURE( aPropertyValues.getLength() == aNodeNames.getLength(), "Problems during reading\n" ); + return sal_False; + } + + aPropertyValues[0] >>= hasEncoded; + aPropertyValues[1] >>= mEncoded; + + aResult = mEncoded; + + return hasEncoded; +} + +//------------------------------------------------------------------------- + +void StorageItem::setEncodedMP( const ::rtl::OUString& aEncoded, sal_Bool bAcceptEmpty ) +{ + Sequence< ::rtl::OUString > sendNames(2); + Sequence< uno::Any > sendVals(2); + + sendNames[0] = ::rtl::OUString::createFromAscii( "HasMaster" ); + sendNames[1] = ::rtl::OUString::createFromAscii( "Master" ); + + sal_Bool bHasMaster = ( aEncoded.getLength() > 0 || bAcceptEmpty ); + sendVals[0] <<= bHasMaster; + sendVals[1] <<= aEncoded; + + ConfigItem::SetModified(); + ConfigItem::PutProperties( sendNames, sendVals ); + + hasEncoded = bHasMaster; + mEncoded = aEncoded; +} + +//------------------------------------------------------------------------- + +void StorageItem::remove( const ::rtl::OUString& aURL, const ::rtl::OUString& aName ) +{ + vector < ::rtl::OUString > forIndex; + forIndex.push_back( aURL ); + forIndex.push_back( aName ); + + Sequence< ::rtl::OUString > sendSeq(1); + + sendSeq[0] = createIndex( forIndex ); + // sendSeq[0] = ::rtl::OUString::createFromAscii( "Store/Passwordstorage['" ); + // sendSeq[0] += createIndex( forIndex ); + // sendSeq[0] += ::rtl::OUString::createFromAscii( "']" ); + + ConfigItem::ClearNodeElements( ::rtl::OUString::createFromAscii( "Store" ), sendSeq ); +} + +//------------------------------------------------------------------------- + +void StorageItem::clear() +{ + Sequence< ::rtl::OUString > sendSeq(1); + + ConfigItem::ClearNodeSet( ::rtl::OUString::createFromAscii( "Store" ) ); +} + +//------------------------------------------------------------------------- + +void StorageItem::update( const ::rtl::OUString& aURL, const NamePassRecord& aRecord ) +{ + if ( !aRecord.HasPasswords( PERSISTENT_RECORD ) ) + { + OSL_ASSERT( "Unexpected storing of a record!" ); + return; + } + + vector < ::rtl::OUString > forIndex; + forIndex.push_back( aURL ); + forIndex.push_back( aRecord.GetUserName() ); + + Sequence< beans::PropertyValue > sendSeq(1); + + sendSeq[0].Name = ::rtl::OUString::createFromAscii( "Store/Passwordstorage['" ); + sendSeq[0].Name += createIndex( forIndex ); + sendSeq[0].Name += ::rtl::OUString::createFromAscii( "']/Password" ); + + sendSeq[0].Value <<= aRecord.GetPersPasswords(); + + ConfigItem::SetModified(); + ConfigItem::SetSetProperties( ::rtl::OUString::createFromAscii( "Store" ), sendSeq ); +} + +//------------------------------------------------------------------------- + +void StorageItem::Notify( const Sequence< ::rtl::OUString >& ) +{ + // this feature still should not be used + if( mainCont ) + mainCont->Notify(); +} + +//------------------------------------------------------------------------- + +void StorageItem::Commit() +{ + // Do nothing, we stored everything we want already +} + +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- + +PasswordContainer::PasswordContainer( const Reference<XMultiServiceFactory>& xServiceFactory ): + m_pStorageFile( NULL ) +{ + // m_pStorageFile->Notify() can be called + ::osl::MutexGuard aGuard( mMutex ); + + mComponent = Reference< XComponent >( xServiceFactory, UNO_QUERY ); + mComponent->addEventListener( this ); + + m_pStorageFile = new StorageItem( this, ::rtl::OUString::createFromAscii( "Office.Common/Passwords" ) ); + if( m_pStorageFile ) + if( m_pStorageFile->useStorage() ) + m_aContainer = m_pStorageFile->getInfo(); +} + +//------------------------------------------------------------------------- + +PasswordContainer::~PasswordContainer() +{ + ::osl::MutexGuard aGuard( mMutex ); + + if( m_pStorageFile ) + { + delete m_pStorageFile; + m_pStorageFile = NULL; + } + + if( mComponent.is() ) + { + mComponent->removeEventListener(this); + mComponent = Reference< XComponent >(); + } +} + +//------------------------------------------------------------------------- + +void SAL_CALL PasswordContainer::disposing( const EventObject& ) throw(RuntimeException) +{ + ::osl::MutexGuard aGuard( mMutex ); + + if( m_pStorageFile ) + { + delete m_pStorageFile; + m_pStorageFile = NULL; + } + + if( mComponent.is() ) + { + //mComponent->removeEventListener(this); + mComponent = Reference< XComponent >(); + } +} + +//------------------------------------------------------------------------- + +vector< ::rtl::OUString > PasswordContainer::DecodePasswords( const ::rtl::OUString& aLine, const ::rtl::OUString& aMasterPasswd ) throw(RuntimeException) +{ + if( aMasterPasswd.getLength() ) + { + rtlCipher aDecoder = rtl_cipher_create (rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream ); + OSL_ENSURE( aDecoder, "Can't create decoder\n" ); + + if( aDecoder ) + { + OSL_ENSURE( aMasterPasswd.getLength() == RTL_DIGEST_LENGTH_MD5 * 2, "Wrong master password format!\n" ); + + unsigned char code[RTL_DIGEST_LENGTH_MD5]; + for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) + code[ ind ] = (char)(aMasterPasswd.copy( ind*2, 2 ).toInt32(16)); + + rtlCipherError result = rtl_cipher_init ( + aDecoder, rtl_Cipher_DirectionDecode, + code, RTL_DIGEST_LENGTH_MD5, NULL, 0 ); + + if( result == rtl_Cipher_E_None ) + { + ::rtl::ByteSequence aSeq = getBufFromAsciiLine( aLine ); + + ::rtl::ByteSequence resSeq( aSeq.getLength() ); + + result = rtl_cipher_decode ( aDecoder, (sal_uInt8*)aSeq.getArray(), aSeq.getLength(), + (sal_uInt8*)resSeq.getArray(), resSeq.getLength() ); + + ::rtl::OUString aPasswd( ( sal_Char* )resSeq.getArray(), resSeq.getLength(), RTL_TEXTENCODING_UTF8 ); + + rtl_cipher_destroy (aDecoder); + + return getInfoFromInd( aPasswd ); + } + + rtl_cipher_destroy (aDecoder); + } + } + else + { + OSL_ENSURE( sal_False, "No master password provided!\n" ); + // throw special exception + } + + // problems with decoding + OSL_ENSURE( sal_False, "Problem with decoding\n" ); + throw RuntimeException( ::rtl::OUString::createFromAscii( "Can't decode!" ), Reference< XInterface >() ); +} + + +//------------------------------------------------------------------------- + +::rtl::OUString PasswordContainer::EncodePasswords( vector< ::rtl::OUString > lines, const ::rtl::OUString& aMasterPasswd ) throw(RuntimeException) +{ + if( aMasterPasswd.getLength() ) + { + ::rtl::OString aSeq = ::rtl::OUStringToOString( createIndex( lines ), RTL_TEXTENCODING_UTF8 ); + + rtlCipher aEncoder = rtl_cipher_create (rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream ); + OSL_ENSURE( aEncoder, "Can't create encoder\n" ); + + if( aEncoder ) + { + OSL_ENSURE( aMasterPasswd.getLength() == RTL_DIGEST_LENGTH_MD5 * 2, "Wrong master password format!\n" ); + + unsigned char code[RTL_DIGEST_LENGTH_MD5]; + for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) + code[ ind ] = (char)(aMasterPasswd.copy( ind*2, 2 ).toInt32(16)); + + rtlCipherError result = rtl_cipher_init ( + aEncoder, rtl_Cipher_DirectionEncode, + code, RTL_DIGEST_LENGTH_MD5, NULL, 0 ); + + if( result == rtl_Cipher_E_None ) + { + ::rtl::ByteSequence resSeq(aSeq.getLength()+1); + + result = rtl_cipher_encode ( aEncoder, (sal_uInt8*)aSeq.getStr(), aSeq.getLength()+1, + (sal_uInt8*)resSeq.getArray(), resSeq.getLength() ); + +/* + //test + rtlCipherError result = rtl_cipher_init ( + aEncoder, rtl_Cipher_DirectionDecode, + code, RTL_DIGEST_LENGTH_MD5, NULL, 0 ); + + + if( result == rtl_Cipher_E_None ) + { + ::rtl::OUString testOU = getAsciiLine( resSeq ); + ::rtl::ByteSequence aSeq1 = getBufFromAsciiLine( testOU ); + + ::rtl::ByteSequence resSeq1( aSeq1.getLength() ); + + if( resSeq.getLength() == aSeq1.getLength() ) + { + for( int ind = 0; ind < aSeq1.getLength(); ind++ ) + if( resSeq[ind] != aSeq1[ind] ) + testOU = ::rtl::OUString(); + } + + result = rtl_cipher_decode ( aEncoder, (sal_uInt8*)aSeq1.getArray(), aSeq1.getLength(), + (sal_uInt8*)resSeq1.getArray(), resSeq1.getLength() ); + + ::rtl::OUString aPasswd( ( sal_Char* )resSeq1.getArray(), resSeq1.getLength(), RTL_TEXTENCODING_UTF8 ); + } +*/ + + rtl_cipher_destroy (aEncoder); + + if( result == rtl_Cipher_E_None ) + return getAsciiLine( resSeq ); + + } + + rtl_cipher_destroy (aEncoder); + } + } + else + { + OSL_ENSURE( sal_False, "No master password provided!\n" ); + // throw special exception + } + + // problems with encoding + OSL_ENSURE( sal_False, "Problem with encoding\n" ); + throw RuntimeException( ::rtl::OUString::createFromAscii( "Can't encode!" ), Reference< XInterface >() ); +} + +//------------------------------------------------------------------------- + +void PasswordContainer::UpdateVector( const ::rtl::OUString& aURL, list< NamePassRecord >& toUpdate, NamePassRecord& aRecord, sal_Bool writeFile ) throw(RuntimeException) +{ + for( list< NamePassRecord >::iterator aNPIter = toUpdate.begin(); aNPIter != toUpdate.end(); aNPIter++ ) + if( aNPIter->GetUserName().equals( aRecord.GetUserName() ) ) + { + if( aRecord.HasPasswords( MEMORY_RECORD ) ) + aNPIter->SetMemPasswords( aRecord.GetMemPasswords() ); + + if( aRecord.HasPasswords( PERSISTENT_RECORD ) ) + { + aNPIter->SetPersPasswords( aRecord.GetPersPasswords() ); + + if( writeFile ) + { + // the password must be already encoded + m_pStorageFile->update( aURL, aRecord ); // change existing ( aURL, aName ) record in the configfile + } + } + + return; + } + + + if( aRecord.HasPasswords( PERSISTENT_RECORD ) && writeFile ) + { + // the password must be already encoded + m_pStorageFile->update( aURL, aRecord ); // add new aName to the existing url + } + + toUpdate.insert( toUpdate.begin(), aRecord ); +} + +//------------------------------------------------------------------------- + +UserRecord PasswordContainer::CopyToUserRecord( const NamePassRecord& aRecord, sal_Bool& io_bTryToDecode, const Reference< XInteractionHandler >& aHandler ) +{ + ::std::vector< ::rtl::OUString > aPasswords; + if( aRecord.HasPasswords( MEMORY_RECORD ) ) + aPasswords = aRecord.GetMemPasswords(); + + if( io_bTryToDecode && aRecord.HasPasswords( PERSISTENT_RECORD ) ) + { + try + { + ::std::vector< ::rtl::OUString > aDecodedPasswords = DecodePasswords( aRecord.GetPersPasswords(), GetMasterPassword( aHandler ) ); + aPasswords.insert( aPasswords.end(), aDecodedPasswords.begin(), aDecodedPasswords.end() ); + } + catch( NoMasterException& ) + { + // if master password could not be detected the entry will be just ignored + io_bTryToDecode = sal_False; + } + } + + return UserRecord( aRecord.GetUserName(), copyVectorToSequence( aPasswords ) ); +} + +//------------------------------------------------------------------------- + +Sequence< UserRecord > PasswordContainer::CopyToUserRecordSequence( const list< NamePassRecord >& original, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) +{ + Sequence< UserRecord > aResult( original.size() ); + sal_uInt32 nInd = 0; + sal_Bool bTryToDecode = sal_True; + + for( list< NamePassRecord >::const_iterator aNPIter = original.begin(); + aNPIter != original.end(); + aNPIter++, nInd++ ) + { + aResult[nInd] = CopyToUserRecord( *aNPIter, bTryToDecode, aHandler ); + } + + return aResult; +} + +//------------------------------------------------------------------------- + +void SAL_CALL PasswordContainer::add( const ::rtl::OUString& Url, const ::rtl::OUString& UserName, const Sequence< ::rtl::OUString >& Passwords, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) +{ + ::osl::MutexGuard aGuard( mMutex ); + + PrivateAdd( Url, UserName, Passwords, MEMORY_RECORD, aHandler ); +} + +//------------------------------------------------------------------------- + +void SAL_CALL PasswordContainer::addPersistent( const ::rtl::OUString& Url, const ::rtl::OUString& UserName, const Sequence< ::rtl::OUString >& Passwords, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) +{ + ::osl::MutexGuard aGuard( mMutex ); + + PrivateAdd( Url, UserName, Passwords, PERSISTENT_RECORD, aHandler ); +} + +//------------------------------------------------------------------------- + +void PasswordContainer::PrivateAdd( const ::rtl::OUString& Url, const ::rtl::OUString& UserName, const Sequence< ::rtl::OUString >& Passwords, char Mode, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) +{ + NamePassRecord aRecord( UserName ); + ::std::vector< ::rtl::OUString > aStorePass = copySequenceToVector( Passwords ); + + if( Mode == PERSISTENT_RECORD ) + aRecord.SetPersPasswords( EncodePasswords( aStorePass, GetMasterPassword( aHandler ) ) ); + else if( Mode == MEMORY_RECORD ) + aRecord.SetMemPasswords( aStorePass ); + else + { + OSL_ASSERT( "Unexpected persistence status!" ); + return; + } + + if( !m_aContainer.empty() ) + { + PassMap::iterator aIter = m_aContainer.find( Url ); + + if( aIter != m_aContainer.end() ) + { + UpdateVector( aIter->first, aIter->second, aRecord, sal_True ); + return; + } + } + + list< NamePassRecord > listToAdd( 1, aRecord ); + m_aContainer.insert( PairUrlRecord( Url, listToAdd ) ); + + if( Mode == PERSISTENT_RECORD && m_pStorageFile && m_pStorageFile->useStorage() ) + m_pStorageFile->update( Url, aRecord ); + +} + +//------------------------------------------------------------------------- + + +UrlRecord SAL_CALL PasswordContainer::find( const ::rtl::OUString& aURL, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) +{ + return find( aURL, rtl::OUString(), false, aHandler ); +} + +//------------------------------------------------------------------------- + +UrlRecord SAL_CALL PasswordContainer::findForName( const ::rtl::OUString& aURL, const ::rtl::OUString& aName, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) +{ + return find( aURL, aName, true, aHandler ); +} + +//------------------------------------------------------------------------- + +Sequence< UserRecord > PasswordContainer::FindUsr( const list< NamePassRecord >& userlist, const ::rtl::OUString& aName, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) +{ + sal_uInt32 nInd = 0; + for( list< NamePassRecord >::const_iterator aNPIter = userlist.begin(); + aNPIter != userlist.end(); + aNPIter++, nInd++ ) + { + if( aNPIter->GetUserName().equals( aName ) ) + { + Sequence< UserRecord > aResult(1); + sal_Bool bTryToDecode = sal_True; + aResult[0] = CopyToUserRecord( *aNPIter, bTryToDecode, aHandler ); + + return aResult; + } + } + + return Sequence< UserRecord >(); +} + +//------------------------------------------------------------------------- + +bool PasswordContainer::createUrlRecord( + const PassMap::iterator & rIter, + bool bName, + const ::rtl::OUString & aName, + const Reference< XInteractionHandler >& aHandler, + UrlRecord & rRec ) + throw( RuntimeException ) +{ + if ( bName ) + { + Sequence< UserRecord > aUsrRec + = FindUsr( rIter->second, aName, aHandler ); + if( aUsrRec.getLength() ) + { + rRec = UrlRecord( rIter->first, aUsrRec ); + return true; + } + } + else + { + rRec = UrlRecord( + rIter->first, + CopyToUserRecordSequence( rIter->second, aHandler ) ); + return true; + } + return false; +} + +//------------------------------------------------------------------------- + +UrlRecord PasswordContainer::find( + const ::rtl::OUString& aURL, + const ::rtl::OUString& aName, + bool bName, // only needed to support empty user names + const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) +{ + ::osl::MutexGuard aGuard( mMutex ); + + if( !m_aContainer.empty() && aURL.getLength() ) + { + ::rtl::OUString aUrl( aURL ); + + // each iteration remove last '/...' section from the aUrl + // while it's possible, up to the most left '://' + do + { + // first look for <url>/somename and then look for <url>/somename/... + PassMap::iterator aIter = m_aContainer.find( aUrl ); + if( aIter != m_aContainer.end() ) + { + UrlRecord aRec; + if ( createUrlRecord( aIter, bName, aName, aHandler, aRec ) ) + return aRec; + } + else + { + ::rtl::OUString tmpUrl( aUrl ); + if ( tmpUrl.getStr()[tmpUrl.getLength() - 1] != (sal_Unicode)'/' ) + tmpUrl += ::rtl::OUString::createFromAscii( "/" ); + + aIter = m_aContainer.lower_bound( tmpUrl ); + if( aIter != m_aContainer.end() && aIter->first.match( tmpUrl ) ) + { + UrlRecord aRec; + if ( createUrlRecord( aIter, bName, aName, aHandler, aRec ) ) + return aRec; + } + } + } + while( shorterUrl( aUrl ) && aUrl.getLength() ); + } + + return UrlRecord(); +} + +//------------------------------------------------------------------------- +::rtl::OUString PasswordContainer::GetDefaultMasterPassword() +{ + ::rtl::OUString aResult; + for ( sal_Int32 nInd = 0; nInd < RTL_DIGEST_LENGTH_MD5; nInd++ ) + aResult += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "aa" ) ); + + return aResult; +} + +//------------------------------------------------------------------------- +::rtl::OUString PasswordContainer::RequestPasswordFromUser( PasswordRequestMode aRMode, const uno::Reference< task::XInteractionHandler >& xHandler ) +{ + // empty string means that the call was cancelled or just failed + ::rtl::OUString aResult; + + if ( xHandler.is() ) + { + ::rtl::Reference< MasterPasswordRequest_Impl > xRequest = new MasterPasswordRequest_Impl( aRMode ); + + xHandler->handle( xRequest.get() ); + + ::rtl::Reference< ucbhelper::InteractionContinuation > xSelection = xRequest->getSelection(); + + if ( xSelection.is() ) + { + Reference< XInteractionAbort > xAbort( xSelection.get(), UNO_QUERY ); + if ( !xAbort.is() ) + { + const ::rtl::Reference< ucbhelper::InteractionSupplyAuthentication > & xSupp + = xRequest->getAuthenticationSupplier(); + + aResult = xSupp->getPassword(); + } + } + } + + return aResult; +} + +//------------------------------------------------------------------------- + +::rtl::OUString PasswordContainer::GetMasterPassword( const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) +{ + PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_ENTER; + if( !m_pStorageFile || !m_pStorageFile->useStorage() ) + throw NoMasterException( ::rtl::OUString::createFromAscii( "Password storing is not active!" ), Reference< XInterface >(), aRMode ); + + if( !m_aMasterPasswd.getLength() && aHandler.is() ) + { + ::rtl::OUString aEncodedMP; + sal_Bool bAskAgain = sal_False; + sal_Bool bDefaultPassword = sal_False; + + if( !m_pStorageFile->getEncodedMP( aEncodedMP ) ) + aRMode = PasswordRequestMode_PASSWORD_CREATE; + else if ( !aEncodedMP.getLength() ) + { + m_aMasterPasswd = GetDefaultMasterPassword(); + bDefaultPassword = sal_True; + } + + if ( !bDefaultPassword ) + { + do { + bAskAgain = sal_False; + + ::rtl::OUString aPass = RequestPasswordFromUser( aRMode, aHandler ); + if ( aPass.getLength() ) + { + if( aRMode == PasswordRequestMode_PASSWORD_CREATE ) + { + m_aMasterPasswd = aPass; + vector< ::rtl::OUString > aMaster( 1, m_aMasterPasswd ); + + m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, m_aMasterPasswd ) ); + } + else + { + vector< ::rtl::OUString > aRM( DecodePasswords( aEncodedMP, aPass ) ); + if( !aRM.size() || !aPass.equals( aRM[0] ) ) + { + bAskAgain = sal_True; + aRMode = PasswordRequestMode_PASSWORD_REENTER; + } + else + m_aMasterPasswd = aPass; + } + } + + } while( bAskAgain ); + } + } + + if ( !m_aMasterPasswd.getLength() ) + throw NoMasterException( ::rtl::OUString::createFromAscii( "No master password!" ), Reference< XInterface >(), aRMode ); + + return m_aMasterPasswd; +} + +//------------------------------------------------------------------------- + +void SAL_CALL PasswordContainer::remove( const ::rtl::OUString& aURL, const ::rtl::OUString& aName ) throw(RuntimeException) +{ + ::osl::MutexGuard aGuard( mMutex ); + + ::rtl::OUString aUrl( aURL ); + if( !m_aContainer.empty() ) + { + PassMap::iterator aIter = m_aContainer.find( aUrl ); + + if( aIter == m_aContainer.end() ) + { + sal_Int32 aInd = aUrl.lastIndexOf( sal_Unicode( '/' ) ); + if( aInd > 0 && aUrl.getLength()-1 == aInd ) + aUrl = aUrl.copy( 0, aUrl.getLength() - 1 ); + else + aUrl += ::rtl::OUString::createFromAscii( "/" ); + + aIter = m_aContainer.find( aUrl ); + } + + if( aIter != m_aContainer.end() ) + { + for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ ) + if( aNPIter->GetUserName().equals( aName ) ) + { + if( aNPIter->HasPasswords( PERSISTENT_RECORD ) && m_pStorageFile ) + m_pStorageFile->remove( aURL, aName ); // remove record ( aURL, aName ) + + // the iterator will not be used any more so it can be removed directly + aIter->second.erase( aNPIter ); + + if( aIter->second.begin() == aIter->second.end() ) + m_aContainer.erase( aIter ); + + return; + } + } + } +} + +//------------------------------------------------------------------------- + +void SAL_CALL PasswordContainer::removePersistent( const ::rtl::OUString& aURL, const ::rtl::OUString& aName ) throw(RuntimeException) +{ + ::osl::MutexGuard aGuard( mMutex ); + + ::rtl::OUString aUrl( aURL ); + if( !m_aContainer.empty() ) + { + PassMap::iterator aIter = m_aContainer.find( aUrl ); + + if( aIter == m_aContainer.end() ) + { + sal_Int32 aInd = aUrl.lastIndexOf( sal_Unicode( '/' ) ); + if( aInd > 0 && aUrl.getLength()-1 == aInd ) + aUrl = aUrl.copy( 0, aUrl.getLength() - 1 ); + else + aUrl += ::rtl::OUString::createFromAscii( "/" ); + + aIter = m_aContainer.find( aUrl ); + } + + if( aIter != m_aContainer.end() ) + { + for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ ) + if( aNPIter->GetUserName().equals( aName ) ) + { + if( aNPIter->HasPasswords( PERSISTENT_RECORD ) ) + { + // TODO/LATER: should the password be converted to MemoryPassword? + aNPIter->RemovePasswords( PERSISTENT_RECORD ); + + if ( m_pStorageFile ) + m_pStorageFile->remove( aURL, aName ); // remove record ( aURL, aName ) + } + + if( !aNPIter->HasPasswords( MEMORY_RECORD ) ) + aIter->second.erase( aNPIter ); + + if( aIter->second.begin() == aIter->second.end() ) + m_aContainer.erase( aIter ); + + return; + } + } + } +} +//------------------------------------------------------------------------- + +void SAL_CALL PasswordContainer::removeAllPersistent() throw(RuntimeException) +{ + ::osl::MutexGuard aGuard( mMutex ); + + if( m_pStorageFile ) + m_pStorageFile->clear(); + + for( PassMap::iterator aIter = m_aContainer.begin(); aIter != m_aContainer.end(); ) + { + for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); ) + { + if( aNPIter->HasPasswords( PERSISTENT_RECORD ) ) + { + // TODO/LATER: should the password be converted to MemoryPassword? + aNPIter->RemovePasswords( PERSISTENT_RECORD ); + + if ( m_pStorageFile ) + m_pStorageFile->remove( aIter->first, aNPIter->GetUserName() ); // remove record ( aURL, aName ) + } + + if( !aNPIter->HasPasswords( MEMORY_RECORD ) ) + { + list< NamePassRecord >::iterator aIterToDelete( aNPIter ); + aNPIter++; + aIter->second.erase( aIterToDelete ); + } + else + aNPIter++; + } + + if( aIter->second.begin() == aIter->second.end() ) + { + PassMap::iterator aIterToDelete( aIter ); + aIter++; + m_aContainer.erase( aIterToDelete ); + } + else + aIter++; + } +} +//------------------------------------------------------------------------- + +Sequence< UrlRecord > SAL_CALL PasswordContainer::getAllPersistent( const Reference< XInteractionHandler >& xHandler ) throw(RuntimeException) +{ + Sequence< UrlRecord > aResult; + + ::osl::MutexGuard aGuard( mMutex ); + for( PassMap::iterator aIter = m_aContainer.begin(); aIter != m_aContainer.end(); aIter++ ) + { + Sequence< UserRecord > aUsers; + for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ ) + if( aNPIter->HasPasswords( PERSISTENT_RECORD ) ) + { + sal_Int32 oldLen = aUsers.getLength(); + aUsers.realloc( oldLen + 1 ); + aUsers[ oldLen ] = UserRecord( aNPIter->GetUserName(), copyVectorToSequence( DecodePasswords( aNPIter->GetPersPasswords(), GetMasterPassword( xHandler ) ) ) ); + } + + if( aUsers.getLength() ) + { + sal_Int32 oldLen = aResult.getLength(); + aResult.realloc( oldLen + 1 ); + aResult[ oldLen ] = UrlRecord( aIter->first, aUsers ); + } + } + + return aResult; +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL PasswordContainer::authorizateWithMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler ) + throw (uno::RuntimeException) +{ + sal_Bool bResult = sal_False; + ::rtl::OUString aEncodedMP; + uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler; + ::osl::MutexGuard aGuard( mMutex ); + + // the method should fail if there is no master password + if( m_pStorageFile && m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) ) + { + if ( !aEncodedMP.getLength() ) + { + // this is a default master password + // no UI is necessary + bResult = sal_True; + } + else + { + if ( !xTmpHandler.is() ) + { + uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW ); + xTmpHandler.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ), uno::UNO_QUERY_THROW ); + } + + if ( m_aMasterPasswd.getLength() ) + { + // there is a password, it should be just rechecked + PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_ENTER; + ::rtl::OUString aPass; + + do { + aPass = RequestPasswordFromUser( aRMode, xTmpHandler ); + bResult = ( aPass.getLength() && aPass.equals( m_aMasterPasswd ) ); + aRMode = PasswordRequestMode_PASSWORD_REENTER; // further questions with error notification + } while( !bResult && aPass.getLength() ); + } + else + { + try + { + // ask for the password, if user provide no correct password an exception will be thrown + bResult = ( GetMasterPassword( xTmpHandler ).getLength() > 0 ); + } + catch( uno::Exception& ) + {} + } + } + } + + return bResult; +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL PasswordContainer::changeMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler ) + throw (uno::RuntimeException) +{ + sal_Bool bResult = sal_False; + uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler; + ::osl::MutexGuard aGuard( mMutex ); + + if ( m_pStorageFile && m_pStorageFile->useStorage() ) + { + if ( !xTmpHandler.is() ) + { + uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW ); + xTmpHandler.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ), uno::UNO_QUERY_THROW ); + } + + sal_Bool bCanChangePassword = sal_True; + // if there is already a stored master password it should be entered by the user before the change happen + ::rtl::OUString aEncodedMP; + if( m_aMasterPasswd.getLength() || m_pStorageFile->getEncodedMP( aEncodedMP ) ) + bCanChangePassword = authorizateWithMasterPassword( xTmpHandler ); + + if ( bCanChangePassword ) + { + // ask for the new password, but do not set it + PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_CREATE; + ::rtl::OUString aPass = RequestPasswordFromUser( aRMode, xTmpHandler ); + + if ( aPass.getLength() ) + { + // get all the persistent entries if it is possible + Sequence< UrlRecord > aPersistent = getAllPersistent( uno::Reference< task::XInteractionHandler >() ); + + // remove the master password and the entries persistence + removeMasterPassword(); + + // store the new master password + m_aMasterPasswd = aPass; + vector< ::rtl::OUString > aMaster( 1, m_aMasterPasswd ); + m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, m_aMasterPasswd ) ); + + // store all the entries with the new password + for ( int nURLInd = 0; nURLInd < aPersistent.getLength(); nURLInd++ ) + for ( int nNameInd = 0; nNameInd< aPersistent[nURLInd].UserList.getLength(); nNameInd++ ) + addPersistent( aPersistent[nURLInd].Url, + aPersistent[nURLInd].UserList[nNameInd].UserName, + aPersistent[nURLInd].UserList[nNameInd].Passwords, + uno::Reference< task::XInteractionHandler >() ); + + bResult = sal_True; + } + } + } + + return bResult; +} + +//------------------------------------------------------------------------- +void SAL_CALL PasswordContainer::removeMasterPassword() + throw (uno::RuntimeException) +{ + // remove all the stored passwords and the master password + removeAllPersistent(); + + ::osl::MutexGuard aGuard( mMutex ); + if ( m_pStorageFile ) + { + m_aMasterPasswd = ::rtl::OUString(); + m_pStorageFile->setEncodedMP( ::rtl::OUString() ); // let the master password be removed from configuration + } +} + +//------------------------------------------------------------------------- +::sal_Bool SAL_CALL PasswordContainer::hasMasterPassword( ) + throw (::com::sun::star::uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( mMutex ); + + if ( !m_pStorageFile ) + throw uno::RuntimeException(); + + ::rtl::OUString aEncodedMP; + return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) ); +} + +//------------------------------------------------------------------------- +::sal_Bool SAL_CALL PasswordContainer::allowPersistentStoring( ::sal_Bool bAllow ) + throw (::com::sun::star::uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( mMutex ); + + if ( !m_pStorageFile ) + throw uno::RuntimeException(); + + if ( !bAllow ) + removeMasterPassword(); + + if ( m_pStorageFile->useStorage() == bAllow ) + return bAllow; + + m_pStorageFile->setUseStorage( bAllow ); + return !bAllow; +} + +//------------------------------------------------------------------------- +::sal_Bool SAL_CALL PasswordContainer::isPersistentStoringAllowed() + throw (::com::sun::star::uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( mMutex ); + + if ( !m_pStorageFile ) + throw uno::RuntimeException(); + + return m_pStorageFile->useStorage(); +} + +//------------------------------------------------------------------------- +::sal_Bool SAL_CALL PasswordContainer::useDefaultMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler ) + throw ( uno::RuntimeException ) +{ + sal_Bool bResult = sal_False; + uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler; + ::osl::MutexGuard aGuard( mMutex ); + + if ( m_pStorageFile && m_pStorageFile->useStorage() ) + { + if ( !xTmpHandler.is() ) + { + uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW ); + xTmpHandler.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ), uno::UNO_QUERY_THROW ); + } + + sal_Bool bCanChangePassword = sal_True; + // if there is already a stored nondefault master password it should be entered by the user before the change happen + ::rtl::OUString aEncodedMP; + if( m_pStorageFile->getEncodedMP( aEncodedMP ) && aEncodedMP.getLength() ) + bCanChangePassword = authorizateWithMasterPassword( xTmpHandler ); + + if ( bCanChangePassword ) + { + // generate the default password + ::rtl::OUString aPass = GetDefaultMasterPassword(); + if ( aPass.getLength() ) + { + // get all the persistent entries if it is possible + Sequence< UrlRecord > aPersistent = getAllPersistent( uno::Reference< task::XInteractionHandler >() ); + + // remove the master password and the entries persistence + removeMasterPassword(); + + // store the empty string to flag the default master password + m_aMasterPasswd = aPass; + m_pStorageFile->setEncodedMP( ::rtl::OUString(), sal_True ); + + // store all the entries with the new password + for ( int nURLInd = 0; nURLInd < aPersistent.getLength(); nURLInd++ ) + for ( int nNameInd = 0; nNameInd< aPersistent[nURLInd].UserList.getLength(); nNameInd++ ) + addPersistent( aPersistent[nURLInd].Url, + aPersistent[nURLInd].UserList[nNameInd].UserName, + aPersistent[nURLInd].UserList[nNameInd].Passwords, + uno::Reference< task::XInteractionHandler >() ); + + bResult = sal_True; + } + } + } + + return bResult; + +} + +//------------------------------------------------------------------------- +::sal_Bool SAL_CALL PasswordContainer::isDefaultMasterPasswordUsed() + throw ( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( mMutex ); + + if ( !m_pStorageFile ) + throw uno::RuntimeException(); + + ::rtl::OUString aEncodedMP; + return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) && !aEncodedMP.getLength() ); +} + + +//------------------------------------------------------------------------- +void SAL_CALL PasswordContainer::addUrl( const ::rtl::OUString& Url, ::sal_Bool MakePersistent ) + throw (uno::RuntimeException) +{ + mUrlContainer.add( Url, MakePersistent ); +} + +//------------------------------------------------------------------------- +::rtl::OUString SAL_CALL PasswordContainer::findUrl( const ::rtl::OUString& Url ) + throw (uno::RuntimeException) +{ + return mUrlContainer.find( Url ); +} + +//------------------------------------------------------------------------- +void SAL_CALL PasswordContainer::removeUrl( const ::rtl::OUString& Url ) + throw (uno::RuntimeException) +{ + mUrlContainer.remove( Url ); +} + +//------------------------------------------------------------------------- +uno::Sequence< ::rtl::OUString > SAL_CALL PasswordContainer::getUrls( ::sal_Bool OnlyPersistent ) + throw (uno::RuntimeException) +{ + return mUrlContainer.list( OnlyPersistent ); +} + +//------------------------------------------------------------------------- + +void PasswordContainer::Notify() +{ + ::osl::MutexGuard aGuard( mMutex ); + + PassMap::iterator aIter; + + // remove the cached persistent values in the memory + for( aIter = m_aContainer.begin(); aIter != m_aContainer.end(); aIter++ ) + { + for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); ) + { + if( aNPIter->HasPasswords( PERSISTENT_RECORD ) ) + { + aNPIter->RemovePasswords( PERSISTENT_RECORD ); + + if ( m_pStorageFile ) + m_pStorageFile->remove( aIter->first, aNPIter->GetUserName() ); // remove record ( aURL, aName ) + } + + if( !aNPIter->HasPasswords( MEMORY_RECORD ) ) + { + list< NamePassRecord >::iterator aIterToDelete( aNPIter ); + aNPIter++; + aIter->second.erase( aIterToDelete ); + } + else + aNPIter++; + } + } + + PassMap addon; + if( m_pStorageFile ) + addon = m_pStorageFile->getInfo(); + + for( aIter = addon.begin(); aIter != addon.end(); aIter++ ) + { + PassMap::iterator aSearchIter = m_aContainer.find( aIter->first ); + if( aSearchIter != m_aContainer.end() ) + for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ ) + UpdateVector( aSearchIter->first, aSearchIter->second, *aNPIter, sal_False ); + else + m_aContainer.insert( PairUrlRecord( aIter->first, aIter->second ) ); + } +} + +//------------------------------------------------------------------------- + +::rtl::OUString SAL_CALL PasswordContainer::getImplementationName( ) throw(uno::RuntimeException) +{ + return impl_getStaticImplementationName(); +} + +//------------------------------------------------------------------------- + +sal_Bool SAL_CALL PasswordContainer::supportsService( const ::rtl::OUString& ServiceName ) throw(uno::RuntimeException) +{ + if ( ServiceName.compareToAscii("com.sun.star.task.PasswordContainer") == 0 ) + return sal_True; + else + return sal_False; +} + +//------------------------------------------------------------------------- + +Sequence< ::rtl::OUString > SAL_CALL PasswordContainer::getSupportedServiceNames( ) throw(uno::RuntimeException) +{ + return impl_getStaticSupportedServiceNames(); +} + +//------------------------------------------------------------------------- + +Sequence< ::rtl::OUString > SAL_CALL PasswordContainer::impl_getStaticSupportedServiceNames( ) throw(uno::RuntimeException) +{ + Sequence< ::rtl::OUString > aRet(1); + *aRet.getArray() = ::rtl::OUString::createFromAscii("com.sun.star.task.PasswordContainer"); + return aRet; +} + +//------------------------------------------------------------------------- + +::rtl::OUString SAL_CALL PasswordContainer::impl_getStaticImplementationName() throw(uno::RuntimeException) +{ + return ::rtl::OUString::createFromAscii("stardiv.svl.PasswordContainer"); +} + +//------------------------------------------------------------------------- + +Reference< XInterface > SAL_CALL PasswordContainer::impl_createInstance( const Reference< XMultiServiceFactory >& xServiceManager ) throw( RuntimeException ) +{ + return Reference< XInterface >( *new PasswordContainer( xServiceManager ) ); +} + +//------------------------------------------------------------------------- + +Reference< XSingleServiceFactory > SAL_CALL PasswordContainer::impl_createFactory( const Reference< XMultiServiceFactory >& ServiceManager ) throw(RuntimeException) +{ + Reference< XSingleServiceFactory > xReturn( ::cppu::createOneInstanceFactory( ServiceManager, + PasswordContainer::impl_getStaticImplementationName(), + PasswordContainer::impl_createInstance, + PasswordContainer::impl_getStaticSupportedServiceNames())); + return xReturn ; + +} + +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- + +MasterPasswordRequest_Impl::MasterPasswordRequest_Impl( PasswordRequestMode Mode ) +{ + MasterPasswordRequest aRequest; + + aRequest.Classification = InteractionClassification_ERROR; + aRequest.Mode = Mode; + + setRequest( makeAny( aRequest ) ); + + // Fill continuations... + Sequence< RememberAuthentication > aRememberModes( 1 ); + aRememberModes[ 0 ] = RememberAuthentication_NO; + + m_xAuthSupplier + = new ::ucbhelper::InteractionSupplyAuthentication( + this, + sal_False, // bCanSetRealm + sal_False, // bCanSetUserName + sal_True, // bCanSetPassword + sal_False, // bCanSetAccount + aRememberModes, // rRememberPasswordModes + RememberAuthentication_NO, // eDefaultRememberPasswordMode + aRememberModes, // rRememberAccountModes + RememberAuthentication_NO, // eDefaultRememberAccountMode + sal_False, // bCanUseSystemCredentials + sal_False // bDefaultUseSystemCredentials + ); + + Sequence< + Reference< XInteractionContinuation > > aContinuations( 3 ); + aContinuations[ 0 ] = new ::ucbhelper::InteractionAbort( this ); + aContinuations[ 1 ] = new ::ucbhelper::InteractionRetry( this ); + aContinuations[ 2 ] = m_xAuthSupplier.get(); + + setContinuations( aContinuations ); +} + +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- + +extern "C" +{ +SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment ( + const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo ( + void * /* pServiceManager */, void * pRegistryKey) +{ + if (pRegistryKey) + { + Reference< XRegistryKey > xRegistryKey ( + reinterpret_cast< XRegistryKey* >( pRegistryKey )); + Reference< XRegistryKey > xNewKey; + + xNewKey = xRegistryKey->createKey( + ::rtl::OUString::createFromAscii( "/stardiv.svl.PasswordContainer/UNO/SERVICES" )); + xNewKey->createKey( ::rtl::OUString::createFromAscii("com.sun.star.task.PasswordContainer")); + + return sal_True; + } + return sal_False; +} + +SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory ( + const sal_Char * pImplementationName, void * pServiceManager, void * /* pRegistryKey */) +{ + void * pResult = 0; + if (pServiceManager) + { + Reference< XSingleServiceFactory > xFactory; + if (PasswordContainer::impl_getStaticImplementationName().compareToAscii (pImplementationName) == 0) + { + xFactory = PasswordContainer::impl_createFactory ( + reinterpret_cast< XMultiServiceFactory* >(pServiceManager)); + } + if (xFactory.is()) + { + xFactory->acquire(); + pResult = xFactory.get(); + } + } + return pResult; +} + +} // extern "C" |