1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "syscreds.hxx"
25 #include "com/sun/star/beans/PropertyValue.hpp"
26 
27 using namespace com::sun::star;
28 
SysCredentialsConfigItem(SysCredentialsConfig * pOwner)29 SysCredentialsConfigItem::SysCredentialsConfigItem(
30     SysCredentialsConfig * pOwner )
31 : utl::ConfigItem( rtl::OUString::createFromAscii( "Office.Common/Passwords" ),
32                    CONFIG_MODE_IMMEDIATE_UPDATE ),
33   m_bInited( false ),
34   m_pOwner( pOwner )
35 {
36     uno::Sequence< ::rtl::OUString > aNode( 1 );
37     aNode[ 0 ] = rtl::OUString::createFromAscii(
38         "Office.Common/Passwords/AuthenticateUsingSystemCredentials" );
39     EnableNotification( aNode );
40 }
41 
42 //virtual
Notify(const uno::Sequence<rtl::OUString> &)43 void SysCredentialsConfigItem::Notify(
44     const uno::Sequence< rtl::OUString > & /*seqPropertyNames*/ )
45 {
46     {
47         ::osl::MutexGuard aGuard( m_aMutex );
48         m_bInited = false;
49         // rebuild m_seqURLs
50         getSystemCredentialsURLs();
51     }
52     m_pOwner->persistentConfigChanged();
53 }
54 
Commit()55 void SysCredentialsConfigItem::Commit()
56 {
57 	// does nothing
58 }
59 
60 uno::Sequence< rtl::OUString >
getSystemCredentialsURLs()61 SysCredentialsConfigItem::getSystemCredentialsURLs()
62 {
63     ::osl::MutexGuard aGuard( m_aMutex );
64     if ( !m_bInited )
65     {
66         // read config item
67         uno::Sequence< ::rtl::OUString > aPropNames( 1 );
68         aPropNames[ 0 ] = rtl::OUString::createFromAscii(
69             "AuthenticateUsingSystemCredentials" );
70         uno::Sequence< uno::Any > aAnyValues(
71             utl::ConfigItem::GetProperties( aPropNames ) );
72 
73         OSL_ENSURE(
74             aAnyValues.getLength() == 1,
75             "SysCredentialsConfigItem::getSystemCredentialsURLs: "
76             "Error reading config item!" );
77 
78         uno::Sequence< rtl::OUString > aValues;
79         if ( ( aAnyValues[ 0 ] >>= aValues ) ||
80              ( !aAnyValues[ 0 ].hasValue() ) )
81         {
82             m_seqURLs = aValues;
83             m_bInited = true;
84         }
85     }
86     return m_seqURLs;
87 }
88 
setSystemCredentialsURLs(const uno::Sequence<rtl::OUString> & seqURLList)89 void SysCredentialsConfigItem::setSystemCredentialsURLs(
90     const uno::Sequence< rtl::OUString > & seqURLList )
91 {
92     ::osl::MutexGuard aGuard( m_aMutex );
93 
94     // write config item.
95     uno::Sequence< rtl::OUString > aPropNames( 1 );
96     uno::Sequence< uno::Any > aPropValues( 1 );
97     aPropNames[ 0 ]
98         = ::rtl::OUString::createFromAscii(
99             "AuthenticateUsingSystemCredentials" );
100     aPropValues[ 0 ] <<= seqURLList;
101 
102     utl::ConfigItem::SetModified();
103     utl::ConfigItem::PutProperties( aPropNames, aPropValues );
104 
105     m_seqURLs = seqURLList;
106     m_bInited = true;
107 }
108 
109 //============================================================================
110 
111 namespace
112 {
113     // TODO: This code is actually copied from svl/source/passwordcontainer.cxx
removeLastSegment(::rtl::OUString & aURL)114     bool removeLastSegment( ::rtl::OUString & aURL )
115     {
116         sal_Int32 aInd = aURL.lastIndexOf( sal_Unicode( '/' ) );
117 
118         if( aInd > 0  )
119         {
120             sal_Int32 aPrevInd = aURL.lastIndexOf( sal_Unicode( '/' ), aInd );
121             if ( aURL.indexOf( ::rtl::OUString::createFromAscii( "://" ) )
122                     != aPrevInd - 2 ||
123                  aInd != aURL.getLength() - 1 )
124             {
125                 aURL = aURL.copy( 0, aInd );
126                 return true;
127             }
128         }
129 
130         return false;
131     }
132 
findURL(StringSet const & rContainer,rtl::OUString const & aURL,rtl::OUString & aResult)133     bool findURL( StringSet const & rContainer, rtl::OUString const & aURL, rtl::OUString & aResult )
134     {
135         // TODO: This code is actually copied from svl/source/passwordcontainer.cxx
136         if( !rContainer.empty() && aURL.getLength() )
137         {
138             ::rtl::OUString aUrl( aURL );
139 
140             // each iteration remove last '/...' section from the aUrl
141             // while it's possible, up to the most left '://'
142             do
143             {
144                 // first look for <url>/somename and then look for <url>/somename/...
145                 StringSet::const_iterator aIter = rContainer.find( aUrl );
146                 if( aIter != rContainer.end() )
147                 {
148                     aResult = *aIter;
149                     return true;
150                 }
151                 else
152                 {
153                     ::rtl::OUString tmpUrl( aUrl );
154                     if ( tmpUrl.getStr()[tmpUrl.getLength() - 1] != (sal_Unicode)'/' )
155                       tmpUrl += ::rtl::OUString::createFromAscii( "/" );
156 
157                     aIter = rContainer.lower_bound( tmpUrl );
158                     if( aIter != rContainer.end() && aIter->match( tmpUrl ) )
159                     {
160                         aResult = *aIter;
161                         return true;
162                     }
163                 }
164             }
165             while( removeLastSegment( aUrl ) && aUrl.getLength() );
166         }
167         aResult = rtl::OUString();
168         return false;
169     }
170 
171 } // namespace
172 
SysCredentialsConfig()173 SysCredentialsConfig::SysCredentialsConfig()
174 : m_aConfigItem( this ),
175   m_bCfgInited( false )
176 {
177 }
178 
initCfg()179 void SysCredentialsConfig::initCfg()
180 {
181     osl::MutexGuard aGuard( m_aMutex );
182     if ( !m_bCfgInited )
183     {
184         uno::Sequence< rtl::OUString > aURLs(
185             m_aConfigItem.getSystemCredentialsURLs() );
186         for ( sal_Int32 n = 0; n < aURLs.getLength(); ++n )
187             m_aCfgContainer.insert( aURLs[ n ] );
188 
189         m_bCfgInited = true;
190     }
191 }
192 
writeCfg()193 void SysCredentialsConfig::writeCfg()
194 {
195     osl::MutexGuard aGuard( m_aMutex );
196 
197     OSL_ENSURE( m_bCfgInited, "SysCredentialsConfig::writeCfg : not initialized!" );
198 
199     uno::Sequence< rtl::OUString > aURLs( m_aCfgContainer.size() );
200     StringSet::const_iterator it = m_aCfgContainer.begin();
201     const StringSet::const_iterator end = m_aCfgContainer.end();
202     sal_Int32 n = 0;
203 
204     while ( it != end )
205     {
206         aURLs[ n ] = *it;
207         ++it;
208         ++n;
209     }
210 
211     m_aConfigItem.setSystemCredentialsURLs( aURLs );
212 }
213 
find(rtl::OUString const & aURL)214 rtl::OUString SysCredentialsConfig::find( rtl::OUString const & aURL )
215 {
216     osl::MutexGuard aGuard( m_aMutex );
217     rtl::OUString aResult;
218     if ( findURL( m_aMemContainer, aURL, aResult ) )
219         return aResult;
220 
221     initCfg();
222     if ( findURL( m_aCfgContainer, aURL, aResult ) )
223         return aResult;
224 
225     return rtl::OUString();
226 }
227 
add(rtl::OUString const & rURL,bool bPersistent)228 void SysCredentialsConfig::add( rtl::OUString const & rURL, bool bPersistent )
229 {
230     ::osl::MutexGuard aGuard( m_aMutex );
231 
232     if ( bPersistent )
233     {
234         m_aMemContainer.erase( rURL );
235 
236         initCfg();
237         m_aCfgContainer.insert( rURL );
238         writeCfg();
239     }
240     else
241     {
242         initCfg();
243         if ( m_aCfgContainer.erase( rURL ) > 0 )
244             writeCfg();
245 
246         m_aMemContainer.insert( rURL );
247     }
248 }
249 
remove(rtl::OUString const & rURL)250 void SysCredentialsConfig::remove( rtl::OUString const & rURL )
251 {
252     m_aMemContainer.erase( rURL );
253 
254     initCfg();
255     if ( m_aCfgContainer.erase( rURL ) > 0 )
256         writeCfg();
257 }
258 
list(bool bOnlyPersistent)259 uno::Sequence< rtl::OUString > SysCredentialsConfig::list( bool bOnlyPersistent )
260 {
261     initCfg();
262     sal_Int32 nCount = m_aCfgContainer.size()
263                      + ( bOnlyPersistent ? 0 : m_aMemContainer.size() );
264     uno::Sequence< rtl::OUString > aResult( nCount );
265 
266     StringSet::const_iterator it = m_aCfgContainer.begin();
267     StringSet::const_iterator end = m_aCfgContainer.end();
268     sal_Int32 n = 0;
269 
270     while ( it != end )
271     {
272         aResult[ n ] = *it;
273         ++it;
274         ++n;
275     }
276 
277     if ( !bOnlyPersistent )
278     {
279         it = m_aMemContainer.begin();
280         end = m_aMemContainer.end();
281 
282         while ( it != end )
283         {
284             aResult[ n ] = *it;
285             ++it;
286             ++n;
287         }
288     }
289     return aResult;
290 }
291 
persistentConfigChanged()292 void SysCredentialsConfig::persistentConfigChanged()
293 {
294     ::osl::MutexGuard aGuard( m_aMutex );
295     m_bCfgInited = false; // re-init on demand.
296 }
297