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