merge the formfield patch from ooo-build
[ooovba.git] / extensions / source / config / ldap / ldapuserprofilebe.cxx
blob6e1eebb3770220e4f96926be29390dbeb98843a8
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ldapuserprofilebe.cxx,v $
10 * $Revision: 1.8 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_extensions.hxx"
34 #include "ldapuserprofilebe.hxx"
35 #include "ldapuserprofilelayer.hxx"
36 #include <osl/file.hxx>
37 #include <osl/module.hxx>
38 #include <osl/process.h>
39 #include <rtl/ustrbuf.hxx>
40 #include <rtl/byteseq.h>
42 #ifndef INCLUDED_RTL_INSTANCE_HXX_
43 #include <rtl/instance.hxx>
44 #endif
45 #include <com/sun/star/beans/NamedValue.hpp>
46 #include <osl/security.hxx>
48 //==============================================================================
49 namespace extensions { namespace config { namespace ldap {
52 static void checkIOError(
53 osl::File::RC aErrorCode,
54 const rtl::OUString& aFileUrl)
56 switch (aErrorCode)
58 case osl::File::E_None: // got it
62 break;
63 default:
65 rtl::OUStringBuffer sMsg;
66 sMsg.appendAscii("LdapUserProfileBe: Cannot Read Meta-Configuration file:");
67 sMsg.append(aFileUrl);
68 throw backend::BackendSetupException(sMsg.makeStringAndClear(),
69 NULL, uno::Any());
74 //------------------------------------------------------------------------------
75 #if 0
76 static rtl::OUString getCurrentModuleDirectory() // URL excluding terminating slash
78 rtl::OUString aFileURL;
79 if ( !osl::Module::getUrlFromAddress((void*)&getCurrentModuleDirectory,aFileURL) )
81 OSL_TRACE(false, "Cannot locate current module - using executable instead");
83 OSL_VERIFY(osl_Process_E_None == osl_getExecutableFile(&aFileURL.pData));
86 OSL_ENSURE(0 < aFileURL.lastIndexOf('/'), "Cannot find directory for module URL");
88 return aFileURL.copy(0, aFileURL.lastIndexOf('/') );
90 #endif
91 //------------------------------------------------------------------------------
92 LdapUserProfileBe::LdapUserProfileBe( const uno::Reference<uno::XComponentContext>& xContext)
93 // throw (backend::BackendAccessException, backend::BackendSetupException, RuntimeException)
94 : LdapProfileMutexHolder(),
95 BackendBase(mMutex),
96 mFactory(xContext->getServiceManager(),uno::UNO_QUERY_THROW),
97 mContext(xContext),
98 mLdapSource( new LdapUserProfileSource ),
99 mLoggedOnUser(),
100 mUserDN()
102 LdapDefinition aDefinition;
104 // This whole rigmarole is to prevent an infinite recursion where reading
105 // the configuration for the backend would create another instance of the
106 // backend, which would try and read the configuration which would...
108 osl::Mutex & aInitMutex = rtl::Static< osl::Mutex, LdapUserProfileBe >::get();
109 osl::MutexGuard aInitGuard(aInitMutex);
111 static bool bReentrantCall; // = false
112 OSL_ENSURE(!bReentrantCall, "configuration: Ldap Backend constructor called reentrantly - probably a registration error.");
114 if (!bReentrantCall)
118 bReentrantCall = true ;
119 if (! readLdapConfiguration(aDefinition) )
121 throw backend::BackendSetupException(
122 rtl::OUString::createFromAscii("LdapUserProfileBe- LDAP not configured"),
123 NULL, uno::Any());
126 bReentrantCall = false ;
128 catch (uno::Exception&)
130 bReentrantCall = false;
131 throw;
138 mLdapSource->mConnection.loadModule();
139 mLdapSource->mConnection.connectSimple(aDefinition);
140 //Set the UserDN
141 mUserDN = mLdapSource->mConnection.findUserDn(
142 rtl::OUStringToOString(mLoggedOnUser, RTL_TEXTENCODING_ASCII_US));
144 catch (lang::IllegalArgumentException& exception)
146 throw backend::BackendSetupException(exception.Message, NULL,
147 uno::makeAny(exception)) ;
149 catch (ldap::LdapConnectionException& exception)
151 throw backend::CannotConnectException(exception.Message, NULL,
152 uno::makeAny(exception)) ;
154 catch(ldap::LdapGenericException& exception)
156 mapGenericException(exception) ;
159 initializeMappingTable(
160 rtl::OStringToOUString(aDefinition.mMapping,
161 RTL_TEXTENCODING_ASCII_US));
163 OSL_POSTCOND(mLdapSource->mConnection.isConnected(),"Erroneously constructed a LdapUserProfileBackend without a LDAP connection");
165 //------------------------------------------------------------------------------
166 LdapUserProfileBe::~LdapUserProfileBe()
169 //------------------------------------------------------------------------------
171 void LdapUserProfileBe::initializeMappingTable(const rtl::OUString& aFileMapName)
173 rtl::OUString aMappingFileUrl = getMappingFileUrl(aFileMapName );
175 osl::File aFile (aMappingFileUrl);
176 checkIOError( aFile.open(OpenFlag_Read), aMappingFileUrl);
178 sal_uInt64 nFileLength = 0;
179 checkIOError( aFile.getSize(nFileLength), aMappingFileUrl);
181 sal_uInt32 nDataLength = sal_uInt32(nFileLength);
182 if (nDataLength != nFileLength)
184 throw backend::BackendSetupException(rtl::OUString::createFromAscii
185 ("LdapUserProfileBe - can not read entire Mapping File: too big"),
186 NULL, uno::Any());
189 struct RawBuffer
191 RawBuffer(sal_Size size) : data(rtl_allocateMemory(size)) {}
192 ~RawBuffer() { rtl_freeMemory(data); }
194 void * data;
196 RawBuffer buffer( nDataLength );
198 sal_uInt64 nRead = 0;
199 osl::File::RC result = aFile.read (static_cast<sal_uInt8*>(buffer.data), nDataLength, nRead);
200 if (result != osl::File::E_None)
202 checkIOError( result, aMappingFileUrl );
203 OSL_ASSERT(!"unreached");
206 if (nRead != nDataLength)
208 throw backend::BackendSetupException(rtl::OUString::createFromAscii
209 ("LdapUserProfileBe - can not read entire Mapping File"),
210 NULL, uno::Any());
213 rtl::OString aStrBuffer ( static_cast<char*>(buffer.data), sal_uInt32(nDataLength) );
214 mLdapSource->mProfileMap.source(aStrBuffer);
217 //------------------------------------------------------------------------------
219 static const rtl::OUString kMappingFileSuffix(RTL_CONSTASCII_USTRINGPARAM(
220 "-attr.map"));
222 static const rtl::OUString kMappingUrl(
223 RTL_CONSTASCII_USTRINGPARAM("/modules/com.sun.star.configuration/bootstrap/LdapMappingUrl"));
226 static const sal_Unicode kPathSeparator = '/' ;
227 static const rtl::OUString kBootstrapContextSingletonName(
228 RTL_CONSTASCII_USTRINGPARAM(
229 "/singletons/com.sun.star.configuration.bootstrap.theBootstrapContext"));
231 rtl::OUString LdapUserProfileBe::getMappingFileUrl(const rtl::OUString& aFileMapName) const
233 uno::Any aContext = mContext->getValueByName(kBootstrapContextSingletonName);
234 uno::Reference<uno::XComponentContext> aBootStrapContext;
236 rtl::OUString aFileUrl;
237 if (aContext >>= aBootStrapContext)
238 aBootStrapContext->getValueByName(kMappingUrl) >>= aFileUrl;
240 if (aFileUrl.getLength() == 0 )
242 #if 0
243 static const rtl::OUString kMappingDirectory(RTL_CONSTASCII_USTRINGPARAM( "/share/registry/ldap"));
245 rtl::OUString aModuleUrl = getCurrentModuleDirectory();
246 sal_Int32 nIndex = aModuleUrl.lastIndexOf('/');
247 if (nIndex == 0)
249 throw backend::BackendSetupException(rtl::OUString::createFromAscii
250 ("LdapUserProfileBe - can not access Mapping File"),
251 NULL, uno::Any());
253 rtl::OUString aMappingFileUrl = aModuleUrl.copy(0, nIndex);
254 aMappingFileUrl += kMappingDirectory;
255 aFileUrl = aMappingFileUrl;
256 #else
257 throw backend::BackendSetupException(rtl::OUString::createFromAscii
258 ("LdapUserProfileBe - can not locate Mapping File"),
259 NULL, uno::Any());
260 #endif
263 rtl::OUStringBuffer sFileBuffer(aFileUrl);
264 sFileBuffer.append(kPathSeparator);
265 sFileBuffer.append (aFileMapName);
266 sFileBuffer.append(kMappingFileSuffix);
267 return sFileBuffer.makeStringAndClear();
269 //------------------------------------------------------------------------------
270 void LdapUserProfileBe::mapGenericException(ldap::LdapGenericException& aException)
271 throw (backend::InsufficientAccessRightsException,
272 backend::ConnectionLostException,
273 backend::BackendAccessException)
275 switch (aException.ErrorCode)
277 case LDAP_INSUFFICIENT_ACCESS:
278 throw backend::InsufficientAccessRightsException(aException.Message,
279 NULL, uno::makeAny(aException)) ;
281 case LDAP_SERVER_DOWN:
282 case LDAP_CONNECT_ERROR:
283 throw backend::ConnectionLostException(aException.Message, NULL,
284 uno::makeAny(aException)) ;
285 default:
286 throw backend::BackendAccessException(aException.Message, NULL,
287 uno::makeAny(aException)) ;
290 //------------------------------------------------------------------------------
292 bool LdapUserProfileBe::readLdapConfiguration(LdapDefinition& aDefinition)
294 const rtl::OUString kConfigurationProviderService( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider")) ;
295 const rtl::OUString kReadOnlyViewService( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationAccess")) ;
296 const rtl::OUString kComponent( RTL_CONSTASCII_USTRINGPARAM("org.openoffice.LDAP/UserDirectory"));
297 const rtl::OUString kServerDefiniton(RTL_CONSTASCII_USTRINGPARAM ("ServerDefinition"));
298 const rtl::OUString kServer(RTL_CONSTASCII_USTRINGPARAM ("Server"));
299 const rtl::OUString kPort(RTL_CONSTASCII_USTRINGPARAM("Port"));
300 const rtl::OUString kBaseDN(RTL_CONSTASCII_USTRINGPARAM("BaseDN"));
301 const rtl::OUString kUser(RTL_CONSTASCII_USTRINGPARAM("SearchUser"));
302 const rtl::OUString kPassword(RTL_CONSTASCII_USTRINGPARAM("SearchPassword"));
303 const rtl::OUString kUserObjectClass(RTL_CONSTASCII_USTRINGPARAM("UserObjectClass"));
304 const rtl::OUString kUserUniqueAttr(RTL_CONSTASCII_USTRINGPARAM("UserUniqueAttribute"));
305 const rtl::OUString kMapping(RTL_CONSTASCII_USTRINGPARAM("Mapping"));
306 const rtl::OString kDefaultMappingFile("oo-ldap");
308 uno::Reference< XInterface > xIface;
311 uno::Reference< lang::XMultiServiceFactory > xCfgProvider(
312 mFactory->createInstance(kConfigurationProviderService),
313 uno::UNO_QUERY);
314 OSL_ENSURE(xCfgProvider.is(),"LdapUserProfileBe: could not create the configuration provider");
315 if (!xCfgProvider.is())
316 return false;
318 css::beans::NamedValue aPath(rtl::OUString::createFromAscii("nodepath"), uno::makeAny(kComponent) );
320 uno::Sequence< uno::Any > aArgs(1);
321 aArgs[0] <<= aPath;
323 xIface = xCfgProvider->createInstanceWithArguments(kReadOnlyViewService, aArgs);
325 uno::Reference<container::XNameAccess > xAccess(xIface, uno::UNO_QUERY_THROW);
326 xAccess->getByName(kServerDefiniton) >>= xIface;
328 uno::Reference<container::XNameAccess > xChildAccess(xIface, uno::UNO_QUERY_THROW);
330 if (!getLdapStringParam(xChildAccess, kServer, aDefinition.mServer))
331 return false;
332 if (!getLdapStringParam(xChildAccess, kBaseDN, aDefinition.mBaseDN))
333 return false;
335 aDefinition.mPort=0;
336 xChildAccess->getByName(kPort) >>= aDefinition.mPort ;
337 if (aDefinition.mPort == 0)
338 return false;
340 if (!getLdapStringParam(xAccess, kUserObjectClass, aDefinition.mUserObjectClass))
341 return false;
342 if (!getLdapStringParam(xAccess, kUserUniqueAttr, aDefinition.mUserUniqueAttr))
343 return false;
345 getLdapStringParam(xAccess, kUser, aDefinition.mAnonUser);
346 getLdapStringParam(xAccess, kPassword, aDefinition.mAnonCredentials);
348 if (!getLdapStringParam(xAccess, kMapping, aDefinition.mMapping))
349 aDefinition.mMapping = kDefaultMappingFile;
351 catch (uno::Exception & e)
353 OSL_TRACE("LdapUserProfileBackend: access to configuration data failed: %s",
354 rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
355 return false;
358 osl::Security aSecurityContext;
359 if (!aSecurityContext.getUserName(mLoggedOnUser))
360 OSL_TRACE("LdapUserProfileBackend - could not get Logged on user from system");
362 sal_Int32 nIndex = mLoggedOnUser.indexOf('/');
363 if (nIndex > 0)
364 mLoggedOnUser = mLoggedOnUser.copy(nIndex+1);
366 //Remember to remove
367 OSL_TRACE("Logged on user is %s", rtl::OUStringToOString(mLoggedOnUser,RTL_TEXTENCODING_ASCII_US).getStr());
369 return true;
372 //------------------------------------------------------------------------------
373 bool LdapUserProfileBe::getLdapStringParam(
374 uno::Reference<container::XNameAccess>& xAccess,
375 const rtl::OUString& aLdapSetting,
376 rtl::OString& aServerParameter)
378 rtl::OUString sParam;
379 xAccess->getByName(aLdapSetting) >>= sParam;
380 aServerParameter = rtl::OUStringToOString(sParam, RTL_TEXTENCODING_ASCII_US);
382 return aServerParameter.getLength() != 0;
384 //------------------------------------------------------------------------------
385 uno::Reference<backend::XLayer> SAL_CALL LdapUserProfileBe::getLayer(
386 const rtl::OUString& /*aComponent*/, const rtl::OUString& /*aTimestamp*/)
387 throw (backend::BackendAccessException, lang::IllegalArgumentException,uno::RuntimeException)
389 OSL_PRECOND(mLdapSource->mConnection.isConnected(), "LdapUserProfileBackend invoked without a connection");
390 if (!mLdapSource->mConnection.isConnected())
391 return NULL;
393 const rtl::OString kModificationAttribute = "modifyTimeStamp";
395 rtl::OString aTimeStamp = mLdapSource->mConnection.
396 getSingleAttribute( mUserDN, kModificationAttribute);
398 return new LdapUserProfileLayer(
399 mFactory, mLoggedOnUser, mLdapSource,
400 rtl::OStringToOUString(aTimeStamp, RTL_TEXTENCODING_ASCII_US));
403 //------------------------------------------------------------------------------
404 uno::Reference<backend::XUpdatableLayer> SAL_CALL
405 LdapUserProfileBe::getUpdatableLayer(const rtl::OUString& /*aComponent*/)
406 throw (backend::BackendAccessException,lang::NoSupportException,
407 lang::IllegalArgumentException,uno::RuntimeException)
409 throw lang::NoSupportException(
410 rtl::OUString::createFromAscii(
411 "LdapUserProfileBe: No Update Operation allowed, Read Only access"),
412 *this) ;
414 //------------------------------------------------------------------------------
415 rtl::OUString SAL_CALL LdapUserProfileBe::getLdapUserProfileBeName(void) {
416 return rtl::OUString::createFromAscii("com.sun.star.comp.configuration.backend.LdapUserProfileBe") ;
418 //------------------------------------------------------------------------------
420 rtl::OUString SAL_CALL LdapUserProfileBe::getImplementationName(void)
421 throw (uno::RuntimeException)
423 return getLdapUserProfileBeName() ;
425 //------------------------------------------------------------------------------
427 uno::Sequence<rtl::OUString> SAL_CALL LdapUserProfileBe::getLdapUserProfileBeServiceNames(void)
429 uno::Sequence<rtl::OUString> aServices(2) ;
430 aServices[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.backend.LdapUserProfileBe")) ;
431 aServices[1] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.backend.PlatformBackend")) ;
433 return aServices ;
435 //------------------------------------------------------------------------------
437 sal_Bool SAL_CALL LdapUserProfileBe::supportsService(const rtl::OUString& aServiceName)
438 throw (uno::RuntimeException)
440 uno::Sequence< rtl::OUString > const svc = getLdapUserProfileBeServiceNames();
442 for(sal_Int32 i = 0; i < svc.getLength(); ++i )
443 if(svc[i] == aServiceName)
444 return true;
445 return false;
448 //------------------------------------------------------------------------------
450 uno::Sequence<rtl::OUString>
451 SAL_CALL LdapUserProfileBe::getSupportedServiceNames(void)
452 throw (uno::RuntimeException)
454 return getLdapUserProfileBeServiceNames() ;
456 // ---------------------------------------------------------------------------------------
458 // ---------------------------------------------------------------------------------------