1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "passwordcontainer.hxx"
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>
33 #include <rtl/cipher.h>
34 #include <rtl/digest.h>
35 #include <rtl/byteseq.hxx>
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
;
48 static OUString
createIndex( vector
< OUString
> lines
)
51 const sal_Char
* pLine
;
53 for( unsigned int i
= 0; i
< lines
.size(); i
++ )
56 aResult
+= OString( "__" );
57 OString line
= OUStringToOString( lines
[i
], RTL_TEXTENCODING_UTF8
);
58 pLine
= line
.getStr();
62 if (comphelper::string::isalnumAscii(*pLine
))
64 aResult
+= OString( *pLine
);
68 aResult
+= OString("_");
69 aResult
+= OString::number( *pLine
, 16 );
76 return OUString::createFromAscii( aResult
.getStr() );
80 static vector
< OUString
> getInfoFromInd( OUString aInd
)
82 vector
< OUString
> aResult
;
83 sal_Bool aStart
= sal_True
;
85 OString line
= OUStringToOString( aInd
, RTL_TEXTENCODING_ASCII_US
);
86 const sal_Char
* pLine
= line
.getStr();
95 while( *pLine
&& !( pLine
[0] == '_' && pLine
[1] == '_' ))
98 newItem
+= OUString( (sal_Unicode
) *pLine
);
104 for( int i
= 1; i
< 3; i
++ )
107 || ( ( pLine
[i
] < '0' || pLine
[i
] > '9' )
108 && ( pLine
[i
] < 'a' || pLine
[i
] > 'f' )
109 && ( pLine
[i
] < 'A' || pLine
[i
] > 'F' ) ) )
111 OSL_FAIL( "Wrong index syntax!\n" );
115 aNum
+= OUString( (sal_Unicode
) pLine
[i
] );
118 newItem
+= OUString( (sal_Unicode
) aNum
.toUInt32( 16 ) );
122 aResult
.push_back( newItem
);
123 } while( pLine
[0] == '_' && pLine
[1] == '_' );
126 OSL_FAIL( "Wrong index syntax!\n" );
132 static sal_Bool
shorterUrl( OUString
& aURL
)
134 sal_Int32 aInd
= aURL
.lastIndexOf( '/' );
135 if( aInd
> 0 && aURL
.indexOf( "://" ) != aInd
-2 )
137 aURL
= aURL
.copy( 0, aInd
);
145 static OUString
getAsciiLine( const ::rtl::ByteSequence
& buf
)
149 ::rtl::ByteSequence
outbuf( buf
.getLength()*2+1 );
151 for( int ind
= 0; ind
< buf
.getLength(); ind
++ )
153 outbuf
[ind
*2] = ( ((sal_uInt8
)buf
[ind
]) >> 4 ) + 'a';
154 outbuf
[ind
*2+1] = ( ((sal_uInt8
)buf
[ind
]) & 0x0f ) + 'a';
156 outbuf
[buf
.getLength()*2] = '\0';
158 aResult
= OUString::createFromAscii( (sal_Char
*)outbuf
.getArray() );
164 static ::rtl::ByteSequence
getBufFromAsciiLine( OUString line
)
166 OSL_ENSURE( line
.getLength() % 2 == 0, "Wrong syntax!\n" );
167 OString tmpLine
= OUStringToOString( line
, RTL_TEXTENCODING_ASCII_US
);
168 ::rtl::ByteSequence
aResult(line
.getLength()/2);
170 for( int ind
= 0; ind
< tmpLine
.getLength()/2; ind
++ )
172 aResult
[ind
] = ( (sal_uInt8
)( tmpLine
[ind
*2] - 'a' ) << 4 ) | (sal_uInt8
)( tmpLine
[ind
*2+1] - 'a' );
179 static Sequence
< OUString
> copyVectorToSequence( const vector
< OUString
>& original
)
181 Sequence
< OUString
> newOne ( original
.size() );
182 for( unsigned int i
= 0; i
< original
.size() ; i
++ )
183 newOne
[i
] = original
[i
];
188 static vector
< OUString
> copySequenceToVector( const Sequence
< OUString
>& original
)
190 vector
< OUString
> newOne ( original
.getLength() );
191 for( int i
= 0; i
< original
.getLength() ; i
++ )
192 newOne
[i
] = original
[i
];
198 PassMap
StorageItem::getInfo()
202 Sequence
< OUString
> aNodeNames
= ConfigItem::GetNodeNames( OUString("Store") );
203 sal_Int32 aNodeCount
= aNodeNames
.getLength();
204 Sequence
< OUString
> aPropNames( aNodeCount
);
207 for( aNodeInd
= 0; aNodeInd
< aNodeCount
; ++aNodeInd
)
209 aPropNames
[aNodeInd
] = "Store/Passwordstorage['" + aNodeNames
[aNodeInd
] + "']/Password";
212 Sequence
< Any
> aPropertyValues
= ConfigItem::GetProperties( aPropNames
);
214 if( aPropertyValues
.getLength() != aNodeNames
.getLength() )
216 OSL_ENSURE( aPropertyValues
.getLength() == aNodeNames
.getLength(), "Problems during reading\n" );
220 for( aNodeInd
= 0; aNodeInd
< aNodeCount
; ++aNodeInd
)
222 vector
< OUString
> aUrlUsr
= getInfoFromInd( aNodeNames
[aNodeInd
] );
224 if( aUrlUsr
.size() == 2 )
226 OUString aUrl
= aUrlUsr
[0];
227 OUString aName
= aUrlUsr
[1];
230 aPropertyValues
[aNodeInd
] >>= aEPasswd
;
232 PassMap::iterator aIter
= aResult
.find( aUrl
);
233 if( aIter
!= aResult
.end() )
234 aIter
->second
.push_back( NamePassRecord( aName
, aEPasswd
) );
237 NamePassRecord
aNewRecord( aName
, aEPasswd
);
238 list
< NamePassRecord
> listToAdd( 1, aNewRecord
);
240 aResult
.insert( PairUrlRecord( aUrl
, listToAdd
) );
244 OSL_FAIL( "Wrong index sintax!\n" );
251 void StorageItem::setUseStorage( bool bUse
)
253 Sequence
< OUString
> sendNames(1);
254 Sequence
< uno::Any
> sendVals(1);
256 sendNames
[0] = "UseStorage";
258 sendVals
[0] <<= bUse
;
260 ConfigItem::SetModified();
261 ConfigItem::PutProperties( sendNames
, sendVals
);
265 bool StorageItem::useStorage()
267 Sequence
< OUString
> aNodeNames( 1 );
268 aNodeNames
[0] = "UseStorage";
270 Sequence
< Any
> aPropertyValues
= ConfigItem::GetProperties( aNodeNames
);
272 if( aPropertyValues
.getLength() != aNodeNames
.getLength() )
274 OSL_ENSURE( aPropertyValues
.getLength() == aNodeNames
.getLength(), "Problems during reading\n" );
278 bool aResult
= false;
279 aPropertyValues
[0] >>= aResult
;
285 bool StorageItem::getEncodedMP( OUString
& aResult
)
293 Sequence
< OUString
> aNodeNames( 2 );
294 aNodeNames
[0] = "HasMaster";
295 aNodeNames
[1] = "Master";
297 Sequence
< Any
> aPropertyValues
= ConfigItem::GetProperties( aNodeNames
);
299 if( aPropertyValues
.getLength() != aNodeNames
.getLength() )
301 OSL_ENSURE( aPropertyValues
.getLength() == aNodeNames
.getLength(), "Problems during reading\n" );
305 aPropertyValues
[0] >>= hasEncoded
;
306 aPropertyValues
[1] >>= mEncoded
;
314 void StorageItem::setEncodedMP( const OUString
& aEncoded
, bool bAcceptEmpty
)
316 Sequence
< OUString
> sendNames(2);
317 Sequence
< uno::Any
> sendVals(2);
319 sendNames
[0] = "HasMaster";
320 sendNames
[1] = "Master";
322 sal_Bool bHasMaster
= ( !aEncoded
.isEmpty() || bAcceptEmpty
);
323 sendVals
[0] <<= bHasMaster
;
324 sendVals
[1] <<= aEncoded
;
326 ConfigItem::SetModified();
327 ConfigItem::PutProperties( sendNames
, sendVals
);
329 hasEncoded
= bHasMaster
;
334 void StorageItem::remove( const OUString
& aURL
, const OUString
& aName
)
336 vector
< OUString
> forIndex
;
337 forIndex
.push_back( aURL
);
338 forIndex
.push_back( aName
);
340 Sequence
< OUString
> sendSeq(1);
342 sendSeq
[0] = createIndex( forIndex
);
344 ConfigItem::ClearNodeElements( OUString("Store"), sendSeq
);
348 void StorageItem::clear()
350 ConfigItem::ClearNodeSet( OUString("Store") );
354 void StorageItem::update( const OUString
& aURL
, const NamePassRecord
& aRecord
)
356 if ( !aRecord
.HasPasswords( PERSISTENT_RECORD
) )
358 OSL_FAIL( "Unexpected storing of a record!" );
362 vector
< OUString
> forIndex
;
363 forIndex
.push_back( aURL
);
364 forIndex
.push_back( aRecord
.GetUserName() );
366 Sequence
< beans::PropertyValue
> sendSeq(1);
368 sendSeq
[0].Name
= "Store/Passwordstorage['" + createIndex( forIndex
) + "']/Password";
370 sendSeq
[0].Value
<<= aRecord
.GetPersPasswords();
372 ConfigItem::SetModified();
373 ConfigItem::SetSetProperties( OUString("Store"), sendSeq
);
377 void StorageItem::Notify( const Sequence
< OUString
>& )
379 // this feature still should not be used
385 void StorageItem::Commit()
387 // Do nothing, we stored everything we want already
391 PasswordContainer::PasswordContainer( const Reference
<XMultiServiceFactory
>& xServiceFactory
):
392 m_pStorageFile( NULL
)
394 // m_pStorageFile->Notify() can be called
395 ::osl::MutexGuard
aGuard( mMutex
);
397 mComponent
= Reference
< XComponent
>( xServiceFactory
, UNO_QUERY
);
398 mComponent
->addEventListener( this );
400 m_pStorageFile
= new StorageItem( this, OUString("Office.Common/Passwords") );
402 if( m_pStorageFile
->useStorage() )
403 m_aContainer
= m_pStorageFile
->getInfo();
407 PasswordContainer::~PasswordContainer()
409 ::osl::MutexGuard
aGuard( mMutex
);
413 delete m_pStorageFile
;
414 m_pStorageFile
= NULL
;
417 if( mComponent
.is() )
419 mComponent
->removeEventListener(this);
425 void SAL_CALL
PasswordContainer::disposing( const EventObject
& ) throw(RuntimeException
)
427 ::osl::MutexGuard
aGuard( mMutex
);
431 delete m_pStorageFile
;
432 m_pStorageFile
= NULL
;
435 if( mComponent
.is() )
437 //mComponent->removeEventListener(this);
443 vector
< OUString
> PasswordContainer::DecodePasswords( const OUString
& aLine
, const OUString
& aMasterPasswd
) throw(RuntimeException
)
445 if( !aMasterPasswd
.isEmpty() )
447 rtlCipher aDecoder
= rtl_cipher_create (rtl_Cipher_AlgorithmBF
, rtl_Cipher_ModeStream
);
448 OSL_ENSURE( aDecoder
, "Can't create decoder\n" );
452 OSL_ENSURE( aMasterPasswd
.getLength() == RTL_DIGEST_LENGTH_MD5
* 2, "Wrong master password format!\n" );
454 unsigned char code
[RTL_DIGEST_LENGTH_MD5
];
455 for( int ind
= 0; ind
< RTL_DIGEST_LENGTH_MD5
; ind
++ )
456 code
[ ind
] = (char)(aMasterPasswd
.copy( ind
*2, 2 ).toUInt32(16));
458 rtlCipherError result
= rtl_cipher_init (
459 aDecoder
, rtl_Cipher_DirectionDecode
,
460 code
, RTL_DIGEST_LENGTH_MD5
, NULL
, 0 );
462 if( result
== rtl_Cipher_E_None
)
464 ::rtl::ByteSequence aSeq
= getBufFromAsciiLine( aLine
);
466 ::rtl::ByteSequence
resSeq( aSeq
.getLength() );
468 result
= rtl_cipher_decode ( aDecoder
, (sal_uInt8
*)aSeq
.getArray(), aSeq
.getLength(),
469 (sal_uInt8
*)resSeq
.getArray(), resSeq
.getLength() );
471 OUString
aPasswd( ( sal_Char
* )resSeq
.getArray(), resSeq
.getLength(), RTL_TEXTENCODING_UTF8
);
473 rtl_cipher_destroy (aDecoder
);
475 return getInfoFromInd( aPasswd
);
478 rtl_cipher_destroy (aDecoder
);
483 OSL_FAIL( "No master password provided!\n" );
484 // throw special exception
487 // problems with decoding
488 OSL_FAIL( "Problem with decoding\n" );
489 throw RuntimeException("Can't decode!", Reference
< XInterface
>() );
494 OUString
PasswordContainer::EncodePasswords( vector
< OUString
> lines
, const OUString
& aMasterPasswd
) throw(RuntimeException
)
496 if( !aMasterPasswd
.isEmpty() )
498 OString aSeq
= OUStringToOString( createIndex( lines
), RTL_TEXTENCODING_UTF8
);
500 rtlCipher aEncoder
= rtl_cipher_create (rtl_Cipher_AlgorithmBF
, rtl_Cipher_ModeStream
);
501 OSL_ENSURE( aEncoder
, "Can't create encoder\n" );
505 OSL_ENSURE( aMasterPasswd
.getLength() == RTL_DIGEST_LENGTH_MD5
* 2, "Wrong master password format!\n" );
507 unsigned char code
[RTL_DIGEST_LENGTH_MD5
];
508 for( int ind
= 0; ind
< RTL_DIGEST_LENGTH_MD5
; ind
++ )
509 code
[ ind
] = (char)(aMasterPasswd
.copy( ind
*2, 2 ).toUInt32(16));
511 rtlCipherError result
= rtl_cipher_init (
512 aEncoder
, rtl_Cipher_DirectionEncode
,
513 code
, RTL_DIGEST_LENGTH_MD5
, NULL
, 0 );
515 if( result
== rtl_Cipher_E_None
)
517 ::rtl::ByteSequence
resSeq(aSeq
.getLength()+1);
519 result
= rtl_cipher_encode ( aEncoder
, (sal_uInt8
*)aSeq
.getStr(), aSeq
.getLength()+1,
520 (sal_uInt8
*)resSeq
.getArray(), resSeq
.getLength() );
524 rtlCipherError result = rtl_cipher_init (
525 aEncoder, rtl_Cipher_DirectionDecode,
526 code, RTL_DIGEST_LENGTH_MD5, NULL, 0 );
529 if( result == rtl_Cipher_E_None )
531 OUString testOU = getAsciiLine( resSeq );
532 ::rtl::ByteSequence aSeq1 = getBufFromAsciiLine( testOU );
534 ::rtl::ByteSequence resSeq1( aSeq1.getLength() );
536 if( resSeq.getLength() == aSeq1.getLength() )
538 for( int ind = 0; ind < aSeq1.getLength(); ind++ )
539 if( resSeq[ind] != aSeq1[ind] )
543 result = rtl_cipher_decode ( aEncoder, (sal_uInt8*)aSeq1.getArray(), aSeq1.getLength(),
544 (sal_uInt8*)resSeq1.getArray(), resSeq1.getLength() );
546 OUString aPasswd( ( sal_Char* )resSeq1.getArray(), resSeq1.getLength(), RTL_TEXTENCODING_UTF8 );
550 rtl_cipher_destroy (aEncoder
);
552 if( result
== rtl_Cipher_E_None
)
553 return getAsciiLine( resSeq
);
557 rtl_cipher_destroy (aEncoder
);
562 OSL_FAIL( "No master password provided!\n" );
563 // throw special exception
566 // problems with encoding
567 OSL_FAIL( "Problem with encoding\n" );
568 throw RuntimeException("Can't encode!", Reference
< XInterface
>() );
572 void PasswordContainer::UpdateVector( const OUString
& aURL
, list
< NamePassRecord
>& toUpdate
, NamePassRecord
& aRecord
, bool writeFile
) throw(RuntimeException
)
574 for( list
< NamePassRecord
>::iterator aNPIter
= toUpdate
.begin(); aNPIter
!= toUpdate
.end(); ++aNPIter
)
575 if( aNPIter
->GetUserName().equals( aRecord
.GetUserName() ) )
577 if( aRecord
.HasPasswords( MEMORY_RECORD
) )
578 aNPIter
->SetMemPasswords( aRecord
.GetMemPasswords() );
580 if( aRecord
.HasPasswords( PERSISTENT_RECORD
) )
582 aNPIter
->SetPersPasswords( aRecord
.GetPersPasswords() );
586 // the password must be already encoded
587 m_pStorageFile
->update( aURL
, aRecord
); // change existing ( aURL, aName ) record in the configfile
595 if( aRecord
.HasPasswords( PERSISTENT_RECORD
) && writeFile
)
597 // the password must be already encoded
598 m_pStorageFile
->update( aURL
, aRecord
); // add new aName to the existing url
601 toUpdate
.insert( toUpdate
.begin(), aRecord
);
605 UserRecord
PasswordContainer::CopyToUserRecord( const NamePassRecord
& aRecord
, bool& io_bTryToDecode
, const Reference
< XInteractionHandler
>& aHandler
)
607 ::std::vector
< OUString
> aPasswords
;
608 if( aRecord
.HasPasswords( MEMORY_RECORD
) )
609 aPasswords
= aRecord
.GetMemPasswords();
611 if( io_bTryToDecode
&& aRecord
.HasPasswords( PERSISTENT_RECORD
) )
615 ::std::vector
< OUString
> aDecodedPasswords
= DecodePasswords( aRecord
.GetPersPasswords(), GetMasterPassword( aHandler
) );
616 aPasswords
.insert( aPasswords
.end(), aDecodedPasswords
.begin(), aDecodedPasswords
.end() );
618 catch( NoMasterException
& )
620 // if master password could not be detected the entry will be just ignored
621 io_bTryToDecode
= false;
625 return UserRecord( aRecord
.GetUserName(), copyVectorToSequence( aPasswords
) );
629 Sequence
< UserRecord
> PasswordContainer::CopyToUserRecordSequence( const list
< NamePassRecord
>& original
, const Reference
< XInteractionHandler
>& aHandler
) throw(RuntimeException
)
631 Sequence
< UserRecord
> aResult( original
.size() );
633 bool bTryToDecode
= true;
635 for( list
< NamePassRecord
>::const_iterator aNPIter
= original
.begin();
636 aNPIter
!= original
.end();
639 aResult
[nInd
] = CopyToUserRecord( *aNPIter
, bTryToDecode
, aHandler
);
646 void SAL_CALL
PasswordContainer::add( const OUString
& Url
, const OUString
& UserName
, const Sequence
< OUString
>& Passwords
, const Reference
< XInteractionHandler
>& aHandler
) throw(RuntimeException
)
648 ::osl::MutexGuard
aGuard( mMutex
);
650 PrivateAdd( Url
, UserName
, Passwords
, MEMORY_RECORD
, aHandler
);
654 void SAL_CALL
PasswordContainer::addPersistent( const OUString
& Url
, const OUString
& UserName
, const Sequence
< OUString
>& Passwords
, const Reference
< XInteractionHandler
>& aHandler
) throw(RuntimeException
)
656 ::osl::MutexGuard
aGuard( mMutex
);
658 PrivateAdd( Url
, UserName
, Passwords
, PERSISTENT_RECORD
, aHandler
);
662 void PasswordContainer::PrivateAdd( const OUString
& Url
, const OUString
& UserName
, const Sequence
< OUString
>& Passwords
, char Mode
, const Reference
< XInteractionHandler
>& aHandler
) throw(RuntimeException
)
664 NamePassRecord
aRecord( UserName
);
665 ::std::vector
< OUString
> aStorePass
= copySequenceToVector( Passwords
);
667 if( Mode
== PERSISTENT_RECORD
)
668 aRecord
.SetPersPasswords( EncodePasswords( aStorePass
, GetMasterPassword( aHandler
) ) );
669 else if( Mode
== MEMORY_RECORD
)
670 aRecord
.SetMemPasswords( aStorePass
);
673 OSL_FAIL( "Unexpected persistence status!" );
677 if( !m_aContainer
.empty() )
679 PassMap::iterator aIter
= m_aContainer
.find( Url
);
681 if( aIter
!= m_aContainer
.end() )
683 UpdateVector( aIter
->first
, aIter
->second
, aRecord
, sal_True
);
688 list
< NamePassRecord
> listToAdd( 1, aRecord
);
689 m_aContainer
.insert( PairUrlRecord( Url
, listToAdd
) );
691 if( Mode
== PERSISTENT_RECORD
&& m_pStorageFile
&& m_pStorageFile
->useStorage() )
692 m_pStorageFile
->update( Url
, aRecord
);
698 UrlRecord SAL_CALL
PasswordContainer::find( const OUString
& aURL
, const Reference
< XInteractionHandler
>& aHandler
) throw(RuntimeException
)
700 return find( aURL
, OUString(), false, aHandler
);
704 UrlRecord SAL_CALL
PasswordContainer::findForName( const OUString
& aURL
, const OUString
& aName
, const Reference
< XInteractionHandler
>& aHandler
) throw(RuntimeException
)
706 return find( aURL
, aName
, true, aHandler
);
710 Sequence
< UserRecord
> PasswordContainer::FindUsr( const list
< NamePassRecord
>& userlist
, const OUString
& aName
, const Reference
< XInteractionHandler
>& aHandler
) throw(RuntimeException
)
713 for( list
< NamePassRecord
>::const_iterator aNPIter
= userlist
.begin();
714 aNPIter
!= userlist
.end();
717 if( aNPIter
->GetUserName().equals( aName
) )
719 Sequence
< UserRecord
> aResult(1);
720 bool bTryToDecode
= true;
721 aResult
[0] = CopyToUserRecord( *aNPIter
, bTryToDecode
, aHandler
);
727 return Sequence
< UserRecord
>();
731 bool PasswordContainer::createUrlRecord(
732 const PassMap::iterator
& rIter
,
734 const OUString
& aName
,
735 const Reference
< XInteractionHandler
>& aHandler
,
737 throw( RuntimeException
)
741 Sequence
< UserRecord
> aUsrRec
742 = FindUsr( rIter
->second
, aName
, aHandler
);
743 if( aUsrRec
.getLength() )
745 rRec
= UrlRecord( rIter
->first
, aUsrRec
);
753 CopyToUserRecordSequence( rIter
->second
, aHandler
) );
760 UrlRecord
PasswordContainer::find(
761 const OUString
& aURL
,
762 const OUString
& aName
,
763 bool bName
, // only needed to support empty user names
764 const Reference
< XInteractionHandler
>& aHandler
) throw(RuntimeException
)
766 ::osl::MutexGuard
aGuard( mMutex
);
768 if( !m_aContainer
.empty() && !aURL
.isEmpty() )
770 OUString
aUrl( aURL
);
772 // each iteration remove last '/...' section from the aUrl
773 // while it's possible, up to the most left '://'
776 // first look for <url>/somename and then look for <url>/somename/...
777 PassMap::iterator aIter
= m_aContainer
.find( aUrl
);
778 if( aIter
!= m_aContainer
.end() )
781 if ( createUrlRecord( aIter
, bName
, aName
, aHandler
, aRec
) )
786 OUString
tmpUrl( aUrl
);
787 if ( !tmpUrl
.endsWith("/") )
790 aIter
= m_aContainer
.lower_bound( tmpUrl
);
791 if( aIter
!= m_aContainer
.end() && aIter
->first
.match( tmpUrl
) )
794 if ( createUrlRecord( aIter
, bName
, aName
, aHandler
, aRec
) )
799 while( shorterUrl( aUrl
) && !aUrl
.isEmpty() );
805 OUString
PasswordContainer::GetDefaultMasterPassword()
808 for ( sal_Int32 nInd
= 0; nInd
< RTL_DIGEST_LENGTH_MD5
; nInd
++ )
814 OUString
PasswordContainer::RequestPasswordFromUser( PasswordRequestMode aRMode
, const uno::Reference
< task::XInteractionHandler
>& xHandler
)
816 // empty string means that the call was cancelled or just failed
821 ::rtl::Reference
< MasterPasswordRequest_Impl
> xRequest
= new MasterPasswordRequest_Impl( aRMode
);
823 xHandler
->handle( xRequest
.get() );
825 ::rtl::Reference
< ucbhelper::InteractionContinuation
> xSelection
= xRequest
->getSelection();
827 if ( xSelection
.is() )
829 Reference
< XInteractionAbort
> xAbort( xSelection
.get(), UNO_QUERY
);
832 const ::rtl::Reference
< ucbhelper::InteractionSupplyAuthentication
> & xSupp
833 = xRequest
->getAuthenticationSupplier();
835 aResult
= xSupp
->getPassword();
844 OUString
PasswordContainer::GetMasterPassword( const Reference
< XInteractionHandler
>& aHandler
) throw(RuntimeException
)
846 PasswordRequestMode aRMode
= PasswordRequestMode_PASSWORD_ENTER
;
847 if( !m_pStorageFile
|| !m_pStorageFile
->useStorage() )
848 throw NoMasterException("Password storing is not active!", Reference
< XInterface
>(), aRMode
);
850 if( m_aMasterPasswd
.isEmpty() && aHandler
.is() )
853 sal_Bool bAskAgain
= sal_False
;
854 sal_Bool bDefaultPassword
= sal_False
;
856 if( !m_pStorageFile
->getEncodedMP( aEncodedMP
) )
857 aRMode
= PasswordRequestMode_PASSWORD_CREATE
;
858 else if ( aEncodedMP
.isEmpty() )
860 m_aMasterPasswd
= GetDefaultMasterPassword();
861 bDefaultPassword
= sal_True
;
864 if ( !bDefaultPassword
)
867 bAskAgain
= sal_False
;
869 OUString aPass
= RequestPasswordFromUser( aRMode
, aHandler
);
870 if ( !aPass
.isEmpty() )
872 if( aRMode
== PasswordRequestMode_PASSWORD_CREATE
)
874 m_aMasterPasswd
= aPass
;
875 vector
< OUString
> aMaster( 1, m_aMasterPasswd
);
877 m_pStorageFile
->setEncodedMP( EncodePasswords( aMaster
, m_aMasterPasswd
) );
881 vector
< OUString
> aRM( DecodePasswords( aEncodedMP
, aPass
) );
882 if( aRM
.empty() || !aPass
.equals( aRM
[0] ) )
884 bAskAgain
= sal_True
;
885 aRMode
= PasswordRequestMode_PASSWORD_REENTER
;
888 m_aMasterPasswd
= aPass
;
892 } while( bAskAgain
);
896 if ( m_aMasterPasswd
.isEmpty() )
897 throw NoMasterException("No master password!", Reference
< XInterface
>(), aRMode
);
899 return m_aMasterPasswd
;
903 void SAL_CALL
PasswordContainer::remove( const OUString
& aURL
, const OUString
& aName
) throw(RuntimeException
)
905 ::osl::MutexGuard
aGuard( mMutex
);
907 OUString
aUrl( aURL
);
908 if( !m_aContainer
.empty() )
910 PassMap::iterator aIter
= m_aContainer
.find( aUrl
);
912 if( aIter
== m_aContainer
.end() )
914 if( aUrl
.endsWith("/") )
915 aUrl
= aUrl
.copy( 0, aUrl
.getLength() - 1 );
919 aIter
= m_aContainer
.find( aUrl
);
922 if( aIter
!= m_aContainer
.end() )
924 for( list
< NamePassRecord
>::iterator aNPIter
= aIter
->second
.begin(); aNPIter
!= aIter
->second
.end(); ++aNPIter
)
925 if( aNPIter
->GetUserName().equals( aName
) )
927 if( aNPIter
->HasPasswords( PERSISTENT_RECORD
) && m_pStorageFile
)
928 m_pStorageFile
->remove( aURL
, aName
); // remove record ( aURL, aName )
930 // the iterator will not be used any more so it can be removed directly
931 aIter
->second
.erase( aNPIter
);
933 if( aIter
->second
.begin() == aIter
->second
.end() )
934 m_aContainer
.erase( aIter
);
943 void SAL_CALL
PasswordContainer::removePersistent( const OUString
& aURL
, const OUString
& aName
) throw(RuntimeException
)
945 ::osl::MutexGuard
aGuard( mMutex
);
947 OUString
aUrl( aURL
);
948 if( !m_aContainer
.empty() )
950 PassMap::iterator aIter
= m_aContainer
.find( aUrl
);
952 if( aIter
== m_aContainer
.end() )
954 if( aUrl
.endsWith("/") )
955 aUrl
= aUrl
.copy( 0, aUrl
.getLength() - 1 );
959 aIter
= m_aContainer
.find( aUrl
);
962 if( aIter
!= m_aContainer
.end() )
964 for( list
< NamePassRecord
>::iterator aNPIter
= aIter
->second
.begin(); aNPIter
!= aIter
->second
.end(); ++aNPIter
)
965 if( aNPIter
->GetUserName().equals( aName
) )
967 if( aNPIter
->HasPasswords( PERSISTENT_RECORD
) )
969 // TODO/LATER: should the password be converted to MemoryPassword?
970 aNPIter
->RemovePasswords( PERSISTENT_RECORD
);
972 if ( m_pStorageFile
)
973 m_pStorageFile
->remove( aURL
, aName
); // remove record ( aURL, aName )
976 if( !aNPIter
->HasPasswords( MEMORY_RECORD
) )
977 aIter
->second
.erase( aNPIter
);
979 if( aIter
->second
.begin() == aIter
->second
.end() )
980 m_aContainer
.erase( aIter
);
988 void SAL_CALL
PasswordContainer::removeAllPersistent() throw(RuntimeException
)
990 ::osl::MutexGuard
aGuard( mMutex
);
993 m_pStorageFile
->clear();
995 for( PassMap::iterator aIter
= m_aContainer
.begin(); aIter
!= m_aContainer
.end(); )
997 for( list
< NamePassRecord
>::iterator aNPIter
= aIter
->second
.begin(); aNPIter
!= aIter
->second
.end(); )
999 if( aNPIter
->HasPasswords( PERSISTENT_RECORD
) )
1001 // TODO/LATER: should the password be converted to MemoryPassword?
1002 aNPIter
->RemovePasswords( PERSISTENT_RECORD
);
1004 if ( m_pStorageFile
)
1005 m_pStorageFile
->remove( aIter
->first
, aNPIter
->GetUserName() ); // remove record ( aURL, aName )
1008 if( !aNPIter
->HasPasswords( MEMORY_RECORD
) )
1010 list
< NamePassRecord
>::iterator
aIterToDelete( aNPIter
);
1012 aIter
->second
.erase( aIterToDelete
);
1018 if( aIter
->second
.begin() == aIter
->second
.end() )
1020 PassMap::iterator
aIterToDelete( aIter
);
1022 m_aContainer
.erase( aIterToDelete
);
1029 Sequence
< UrlRecord
> SAL_CALL
PasswordContainer::getAllPersistent( const Reference
< XInteractionHandler
>& xHandler
) throw(RuntimeException
)
1031 Sequence
< UrlRecord
> aResult
;
1033 ::osl::MutexGuard
aGuard( mMutex
);
1034 for( PassMap::iterator aIter
= m_aContainer
.begin(); aIter
!= m_aContainer
.end(); ++aIter
)
1036 Sequence
< UserRecord
> aUsers
;
1037 for( list
< NamePassRecord
>::iterator aNPIter
= aIter
->second
.begin(); aNPIter
!= aIter
->second
.end(); ++aNPIter
)
1038 if( aNPIter
->HasPasswords( PERSISTENT_RECORD
) )
1040 sal_Int32 oldLen
= aUsers
.getLength();
1041 aUsers
.realloc( oldLen
+ 1 );
1042 aUsers
[ oldLen
] = UserRecord( aNPIter
->GetUserName(), copyVectorToSequence( DecodePasswords( aNPIter
->GetPersPasswords(), GetMasterPassword( xHandler
) ) ) );
1045 if( aUsers
.getLength() )
1047 sal_Int32 oldLen
= aResult
.getLength();
1048 aResult
.realloc( oldLen
+ 1 );
1049 aResult
[ oldLen
] = UrlRecord( aIter
->first
, aUsers
);
1056 sal_Bool SAL_CALL
PasswordContainer::authorizateWithMasterPassword( const uno::Reference
< task::XInteractionHandler
>& xHandler
)
1057 throw (uno::RuntimeException
)
1059 sal_Bool bResult
= sal_False
;
1060 OUString aEncodedMP
;
1061 uno::Reference
< task::XInteractionHandler
> xTmpHandler
= xHandler
;
1062 ::osl::MutexGuard
aGuard( mMutex
);
1064 // the method should fail if there is no master password
1065 if( m_pStorageFile
&& m_pStorageFile
->useStorage() && m_pStorageFile
->getEncodedMP( aEncodedMP
) )
1067 if ( aEncodedMP
.isEmpty() )
1069 // this is a default master password
1070 // no UI is necessary
1075 if ( !xTmpHandler
.is() )
1077 uno::Reference
< lang::XMultiServiceFactory
> xFactory( mComponent
, uno::UNO_QUERY_THROW
);
1078 uno::Reference
< uno::XComponentContext
> xContext( comphelper::getComponentContext(xFactory
) );
1079 xTmpHandler
.set( InteractionHandler::createWithParent(xContext
, 0), uno::UNO_QUERY_THROW
);
1082 if ( !m_aMasterPasswd
.isEmpty() )
1084 // there is a password, it should be just rechecked
1085 PasswordRequestMode aRMode
= PasswordRequestMode_PASSWORD_ENTER
;
1089 aPass
= RequestPasswordFromUser( aRMode
, xTmpHandler
);
1090 bResult
= ( !aPass
.isEmpty() && aPass
.equals( m_aMasterPasswd
) );
1091 aRMode
= PasswordRequestMode_PASSWORD_REENTER
; // further questions with error notification
1092 } while( !bResult
&& !aPass
.isEmpty() );
1098 // ask for the password, if user provide no correct password an exception will be thrown
1099 bResult
= !GetMasterPassword( xTmpHandler
).isEmpty();
1101 catch( uno::Exception
& )
1110 sal_Bool SAL_CALL
PasswordContainer::changeMasterPassword( const uno::Reference
< task::XInteractionHandler
>& xHandler
)
1111 throw (uno::RuntimeException
)
1113 sal_Bool bResult
= sal_False
;
1114 uno::Reference
< task::XInteractionHandler
> xTmpHandler
= xHandler
;
1115 ::osl::MutexGuard
aGuard( mMutex
);
1117 if ( m_pStorageFile
&& m_pStorageFile
->useStorage() )
1119 if ( !xTmpHandler
.is() )
1121 uno::Reference
< lang::XMultiServiceFactory
> xFactory( mComponent
, uno::UNO_QUERY_THROW
);
1122 uno::Reference
< uno::XComponentContext
> xContext( comphelper::getComponentContext(xFactory
) );
1123 xTmpHandler
.set( InteractionHandler::createWithParent(xContext
, 0), uno::UNO_QUERY_THROW
);
1126 sal_Bool bCanChangePassword
= sal_True
;
1127 // if there is already a stored master password it should be entered by the user before the change happen
1128 OUString aEncodedMP
;
1129 if( !m_aMasterPasswd
.isEmpty() || m_pStorageFile
->getEncodedMP( aEncodedMP
) )
1130 bCanChangePassword
= authorizateWithMasterPassword( xTmpHandler
);
1132 if ( bCanChangePassword
)
1134 // ask for the new password, but do not set it
1135 PasswordRequestMode aRMode
= PasswordRequestMode_PASSWORD_CREATE
;
1136 OUString aPass
= RequestPasswordFromUser( aRMode
, xTmpHandler
);
1138 if ( !aPass
.isEmpty() )
1140 // get all the persistent entries if it is possible
1141 Sequence
< UrlRecord
> aPersistent
= getAllPersistent( uno::Reference
< task::XInteractionHandler
>() );
1143 // remove the master password and the entries persistence
1144 removeMasterPassword();
1146 // store the new master password
1147 m_aMasterPasswd
= aPass
;
1148 vector
< OUString
> aMaster( 1, m_aMasterPasswd
);
1149 m_pStorageFile
->setEncodedMP( EncodePasswords( aMaster
, m_aMasterPasswd
) );
1151 // store all the entries with the new password
1152 for ( int nURLInd
= 0; nURLInd
< aPersistent
.getLength(); nURLInd
++ )
1153 for ( int nNameInd
= 0; nNameInd
< aPersistent
[nURLInd
].UserList
.getLength(); nNameInd
++ )
1154 addPersistent( aPersistent
[nURLInd
].Url
,
1155 aPersistent
[nURLInd
].UserList
[nNameInd
].UserName
,
1156 aPersistent
[nURLInd
].UserList
[nNameInd
].Passwords
,
1157 uno::Reference
< task::XInteractionHandler
>() );
1167 void SAL_CALL
PasswordContainer::removeMasterPassword()
1168 throw (uno::RuntimeException
)
1170 // remove all the stored passwords and the master password
1171 removeAllPersistent();
1173 ::osl::MutexGuard
aGuard( mMutex
);
1174 if ( m_pStorageFile
)
1176 m_aMasterPasswd
= "";
1177 m_pStorageFile
->setEncodedMP( OUString() ); // let the master password be removed from configuration
1181 ::sal_Bool SAL_CALL
PasswordContainer::hasMasterPassword( )
1182 throw (::com::sun::star::uno::RuntimeException
)
1184 ::osl::MutexGuard
aGuard( mMutex
);
1186 if ( !m_pStorageFile
)
1187 throw uno::RuntimeException();
1189 OUString aEncodedMP
;
1190 return ( m_pStorageFile
->useStorage() && m_pStorageFile
->getEncodedMP( aEncodedMP
) );
1193 ::sal_Bool SAL_CALL
PasswordContainer::allowPersistentStoring( ::sal_Bool bAllow
)
1194 throw (::com::sun::star::uno::RuntimeException
)
1196 ::osl::MutexGuard
aGuard( mMutex
);
1198 if ( !m_pStorageFile
)
1199 throw uno::RuntimeException();
1202 removeMasterPassword();
1204 if (m_pStorageFile
->useStorage() == static_cast<bool>(bAllow
))
1207 m_pStorageFile
->setUseStorage( bAllow
);
1211 ::sal_Bool SAL_CALL
PasswordContainer::isPersistentStoringAllowed()
1212 throw (::com::sun::star::uno::RuntimeException
)
1214 ::osl::MutexGuard
aGuard( mMutex
);
1216 if ( !m_pStorageFile
)
1217 throw uno::RuntimeException();
1219 return m_pStorageFile
->useStorage();
1222 ::sal_Bool SAL_CALL
PasswordContainer::useDefaultMasterPassword( const uno::Reference
< task::XInteractionHandler
>& xHandler
)
1223 throw ( uno::RuntimeException
)
1225 sal_Bool bResult
= sal_False
;
1226 uno::Reference
< task::XInteractionHandler
> xTmpHandler
= xHandler
;
1227 ::osl::MutexGuard
aGuard( mMutex
);
1229 if ( m_pStorageFile
&& m_pStorageFile
->useStorage() )
1231 if ( !xTmpHandler
.is() )
1233 uno::Reference
< lang::XMultiServiceFactory
> xFactory( mComponent
, uno::UNO_QUERY_THROW
);
1234 uno::Reference
< uno::XComponentContext
> xContext( comphelper::getComponentContext(xFactory
) );
1235 xTmpHandler
.set( InteractionHandler::createWithParent(xContext
, 0), uno::UNO_QUERY_THROW
);
1238 sal_Bool bCanChangePassword
= sal_True
;
1239 // if there is already a stored nondefault master password it should be entered by the user before the change happen
1240 OUString aEncodedMP
;
1241 if( m_pStorageFile
->getEncodedMP( aEncodedMP
) && !aEncodedMP
.isEmpty() )
1242 bCanChangePassword
= authorizateWithMasterPassword( xTmpHandler
);
1244 if ( bCanChangePassword
)
1246 // generate the default password
1247 OUString aPass
= GetDefaultMasterPassword();
1248 if ( !aPass
.isEmpty() )
1250 // get all the persistent entries if it is possible
1251 Sequence
< UrlRecord
> aPersistent
= getAllPersistent( uno::Reference
< task::XInteractionHandler
>() );
1253 // remove the master password and the entries persistence
1254 removeMasterPassword();
1256 // store the empty string to flag the default master password
1257 m_aMasterPasswd
= aPass
;
1258 m_pStorageFile
->setEncodedMP( OUString(), sal_True
);
1260 // store all the entries with the new password
1261 for ( int nURLInd
= 0; nURLInd
< aPersistent
.getLength(); nURLInd
++ )
1262 for ( int nNameInd
= 0; nNameInd
< aPersistent
[nURLInd
].UserList
.getLength(); nNameInd
++ )
1263 addPersistent( aPersistent
[nURLInd
].Url
,
1264 aPersistent
[nURLInd
].UserList
[nNameInd
].UserName
,
1265 aPersistent
[nURLInd
].UserList
[nNameInd
].Passwords
,
1266 uno::Reference
< task::XInteractionHandler
>() );
1277 ::sal_Bool SAL_CALL
PasswordContainer::isDefaultMasterPasswordUsed()
1278 throw ( uno::RuntimeException
)
1280 ::osl::MutexGuard
aGuard( mMutex
);
1282 if ( !m_pStorageFile
)
1283 throw uno::RuntimeException();
1285 OUString aEncodedMP
;
1286 return ( m_pStorageFile
->useStorage() && m_pStorageFile
->getEncodedMP( aEncodedMP
) && aEncodedMP
.isEmpty() );
1290 void SAL_CALL
PasswordContainer::addUrl( const OUString
& Url
, ::sal_Bool MakePersistent
)
1291 throw (uno::RuntimeException
)
1293 mUrlContainer
.add( Url
, MakePersistent
);
1296 OUString SAL_CALL
PasswordContainer::findUrl( const OUString
& Url
)
1297 throw (uno::RuntimeException
)
1299 return mUrlContainer
.find( Url
);
1302 void SAL_CALL
PasswordContainer::removeUrl( const OUString
& Url
)
1303 throw (uno::RuntimeException
)
1305 mUrlContainer
.remove( Url
);
1308 uno::Sequence
< OUString
> SAL_CALL
PasswordContainer::getUrls( ::sal_Bool OnlyPersistent
)
1309 throw (uno::RuntimeException
)
1311 return mUrlContainer
.list( OnlyPersistent
);
1315 void PasswordContainer::Notify()
1317 ::osl::MutexGuard
aGuard( mMutex
);
1319 PassMap::iterator aIter
;
1321 // remove the cached persistent values in the memory
1322 for( aIter
= m_aContainer
.begin(); aIter
!= m_aContainer
.end(); ++aIter
)
1324 for( list
< NamePassRecord
>::iterator aNPIter
= aIter
->second
.begin(); aNPIter
!= aIter
->second
.end(); )
1326 if( aNPIter
->HasPasswords( PERSISTENT_RECORD
) )
1328 aNPIter
->RemovePasswords( PERSISTENT_RECORD
);
1330 if ( m_pStorageFile
)
1331 m_pStorageFile
->remove( aIter
->first
, aNPIter
->GetUserName() ); // remove record ( aURL, aName )
1334 if( !aNPIter
->HasPasswords( MEMORY_RECORD
) )
1336 list
< NamePassRecord
>::iterator
aIterToDelete( aNPIter
);
1338 aIter
->second
.erase( aIterToDelete
);
1346 if( m_pStorageFile
)
1347 addon
= m_pStorageFile
->getInfo();
1349 for( aIter
= addon
.begin(); aIter
!= addon
.end(); ++aIter
)
1351 PassMap::iterator aSearchIter
= m_aContainer
.find( aIter
->first
);
1352 if( aSearchIter
!= m_aContainer
.end() )
1353 for( list
< NamePassRecord
>::iterator aNPIter
= aIter
->second
.begin(); aNPIter
!= aIter
->second
.end(); ++aNPIter
)
1354 UpdateVector( aSearchIter
->first
, aSearchIter
->second
, *aNPIter
, sal_False
);
1356 m_aContainer
.insert( PairUrlRecord( aIter
->first
, aIter
->second
) );
1361 OUString SAL_CALL
PasswordContainer::getImplementationName( ) throw(uno::RuntimeException
)
1363 return impl_getStaticImplementationName();
1367 sal_Bool SAL_CALL
PasswordContainer::supportsService( const OUString
& ServiceName
) throw(uno::RuntimeException
)
1369 if ( ServiceName
.equalsAscii("com.sun.star.task.PasswordContainer") )
1376 Sequence
< OUString
> SAL_CALL
PasswordContainer::getSupportedServiceNames( ) throw(uno::RuntimeException
)
1378 return impl_getStaticSupportedServiceNames();
1382 Sequence
< OUString
> SAL_CALL
PasswordContainer::impl_getStaticSupportedServiceNames( ) throw(uno::RuntimeException
)
1384 Sequence
< OUString
> aRet(1);
1385 aRet
[0] = "com.sun.star.task.PasswordContainer";
1390 OUString SAL_CALL
PasswordContainer::impl_getStaticImplementationName() throw(uno::RuntimeException
)
1392 return OUString("stardiv.svl.PasswordContainer");
1396 Reference
< XInterface
> SAL_CALL
PasswordContainer::impl_createInstance( const Reference
< XMultiServiceFactory
>& xServiceManager
) throw( RuntimeException
)
1398 return Reference
< XInterface
>( *new PasswordContainer( xServiceManager
) );
1402 Reference
< XSingleServiceFactory
> SAL_CALL
PasswordContainer::impl_createFactory( const Reference
< XMultiServiceFactory
>& ServiceManager
) throw(RuntimeException
)
1404 Reference
< XSingleServiceFactory
> xReturn( ::cppu::createOneInstanceFactory( ServiceManager
,
1405 PasswordContainer::impl_getStaticImplementationName(),
1406 PasswordContainer::impl_createInstance
,
1407 PasswordContainer::impl_getStaticSupportedServiceNames()));
1413 MasterPasswordRequest_Impl::MasterPasswordRequest_Impl( PasswordRequestMode Mode
)
1415 MasterPasswordRequest aRequest
;
1417 aRequest
.Classification
= InteractionClassification_ERROR
;
1418 aRequest
.Mode
= Mode
;
1420 setRequest( makeAny( aRequest
) );
1422 // Fill continuations...
1423 Sequence
< RememberAuthentication
> aRememberModes( 1 );
1424 aRememberModes
[ 0 ] = RememberAuthentication_NO
;
1427 = new ::ucbhelper::InteractionSupplyAuthentication(
1429 sal_False
, // bCanSetRealm
1430 sal_False
, // bCanSetUserName
1431 sal_True
, // bCanSetPassword
1432 sal_False
, // bCanSetAccount
1433 aRememberModes
, // rRememberPasswordModes
1434 RememberAuthentication_NO
, // eDefaultRememberPasswordMode
1435 aRememberModes
, // rRememberAccountModes
1436 RememberAuthentication_NO
, // eDefaultRememberAccountMode
1437 sal_False
, // bCanUseSystemCredentials
1438 sal_False
// bDefaultUseSystemCredentials
1442 Reference
< XInteractionContinuation
> > aContinuations( 3 );
1443 aContinuations
[ 0 ] = new ::ucbhelper::InteractionAbort( this );
1444 aContinuations
[ 1 ] = new ::ucbhelper::InteractionRetry( this );
1445 aContinuations
[ 2 ] = m_xAuthSupplier
.get();
1447 setContinuations( aContinuations
);
1453 SAL_DLLPUBLIC_EXPORT
void * SAL_CALL
passwordcontainer_component_getFactory (
1454 const sal_Char
* pImplementationName
,
1455 SAL_UNUSED_PARAMETER
void * pServiceManager
,
1456 SAL_UNUSED_PARAMETER
void * /* pRegistryKey */)
1459 if (pServiceManager
)
1461 Reference
< XSingleServiceFactory
> xFactory
;
1462 if (PasswordContainer::impl_getStaticImplementationName().equalsAscii(pImplementationName
))
1464 xFactory
= PasswordContainer::impl_createFactory (
1465 reinterpret_cast< XMultiServiceFactory
* >(pServiceManager
));
1469 xFactory
->acquire();
1470 pResult
= xFactory
.get();
1478 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */