Using LDAP XPCOM with XULRunner

By default, XULRunner is built without LDAP XPCOM support. If you want to use LDAP components in your XUL application, you have two options : compile XULRunner with LDAP support enabled, or add LDAP XPCOM directly to your XUL app (in the components directory).

In any case, you will have to build LDAP XPCOM, by adding --enable-ldap build option. See the Build_Documentation for more information about how to build XULRunner. When Configuring Build Options, just add:

ac_add_options --enable-ldap

to your .mozconfig file.

This will create two files in the components directory of the build package:

  • mozldap.dll (or libmozldap.so or...)
  • mozldap.xpt

and two files in the root directory of the build package: On windows:

  • nsldap32v50.dll
  • nsldappr32v50.dll

On linux:

  • libldap50.so
  • libprldap50.so

Those are the native LDAP library.

If you copy as usual those files in the components directory of your XUL app, this can't work. Actually, the LDAP interfaces are available (for exemple, Components.interfaces.nsILDAPConnection is not null), but the components can't be loaded (for example, Components.classes["@mozilla.org/network/ldap-connection;1"] is null). This is due to the fact that the native LDAP library files are not found by the XULRunner process.

The solution is to use the bsmedberg stub, described in Using Dependent Libraries In Extension Components: the component library is just a loader of the real library and all its dependencies, so as all the needed libraries are loaded.

Create a subdirectory extensions/ldapstub in the mozilla source code directory, containing two files, Makefile.in and LDAPStubLoader.cpp:

Makefile.in:

# Copyright (c) 2005 Benjamin Smedberg <benjamin@smedbergs.us>

DEPTH = ../..
srcdir = @srcdir@
topsrcdir = @top_srcdir@
VPATH = @srcdir@

include $(DEPTH)/config/autoconf.mk

MODULE = mozldapstub
LIBRARY_NAME = mozldap_stub
IS_COMPONENT = 1
FORCE_SHARED_LIB = 1

REQUIRES = \
	xpcom \
	string \
	$(NULL)

CPPSRCS = LDAPStubLoader.cpp

EXTRA_DSO_LDOPTS += \
	$(DIST)/lib/$(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX) \
	$(XPCOM_FROZEN_LDOPTS) \
        $(NSPR_LIBS) \
	$(NULL)

include $(topsrcdir)/config/rules.mk

DEFINES += -DMOZ_DLL_PREFIX=\"$(DLL_PREFIX)\"

LDAPStubLoader.cpp:

// Copyright (c) 2005 Benjamin Smedberg <benjamin@smedbergs.us>

#include "nscore.h"
#include "nsModule.h"
#include "prlink.h"
#include "nsILocalFile.h"
#include "nsStringAPI.h"
#include "nsCOMPtr.h"

static char const *const kDependentLibraries[] =
{
#ifdef NS_WIN32
  MOZ_DLL_PREFIX "nsldap32v50" MOZ_DLL_SUFFIX,
  MOZ_DLL_PREFIX "nsldappr32v50" MOZ_DLL_SUFFIX,
#endif //NS_WIN32
#ifdef NS_UNIX
  MOZ_DLL_PREFIX "ldap50" MOZ_DLL_SUFFIX,
  MOZ_DLL_PREFIX "prldap50" MOZ_DLL_SUFFIX,
#endif //NS_UNIX
  nsnull
};

// component.dll on windows, libcomponent.dll on linux
static char kRealComponent[] = MOZ_DLL_PREFIX "mozldap" MOZ_DLL_SUFFIX;

nsresult
NSGetModule(nsIComponentManager* aCompMgr,
            nsIFile* aLocation,
            nsIModule* *aResult)
{
  nsresult rv;

  nsCOMPtr<nsIFile> libraries;
  rv = aLocation->GetParent(getter_AddRefs(libraries));
  if (NS_FAILED(rv))
    return rv;

  nsCOMPtr<nsILocalFile> library(do_QueryInterface(libraries));
  if (!library)
    return NS_ERROR_UNEXPECTED;

  library->SetNativeLeafName(NS_LITERAL_CSTRING("libraries"));
  library->AppendNative(NS_LITERAL_CSTRING("dummy"));

  // loop through and load dependent libraries
  for (char const *const *dependent = kDependentLibraries;
       *dependent;
       ++dependent) {
    library->SetNativeLeafName(nsDependentCString(*dependent));
    PRLibrary *lib;
    library->Load(&lib);
    // 1) We don't care if this failed!
    // 2) We are going to leak this library. We don't care about that either.
  }

  library->SetNativeLeafName(NS_LITERAL_CSTRING(kRealComponent));

  PRLibrary *lib;
  rv = library->Load(&lib);
  if (NS_FAILED(rv))
    return rv;

  nsGetModuleProc getmoduleproc = (nsGetModuleProc)
    PR_FindFunctionSymbol(lib, NS_GET_MODULE_SYMBOL);

  if (!getmoduleproc)
    return NS_ERROR_FAILURE;

  return getmoduleproc(aCompMgr, aLocation, aResult);
}

Then change your .mozconfig to add this line:

ac_add_options --enable-extensions=ldapstub

Rebuild XULRunner. This will create a new file in the components subdirectory of the built package, mozldap_stub.dll (on Windows) or libmozldap_stub.so (on Linux).

Copy mozldap.xpt and mozldap_stub.dll into your components XUL app subdirectory. Create a libraries subdirectory in your XUL app directory, and copy mozldap.dll (or libmozldap.so), and the native LDAP binaries into it.

Don't forget to clean your profile.

You can now use the LDAP components.