|
Viewing a directory schema
LDAP v3 exposes a directory's schema information in a special
entry in the root DN. You use the directory root subschemaSubentry attribute
to access this information.
The following ColdFusion query shows how to get and display the
directory schema. It displays information from the schema’s object
class and attribute type definitions. For object classes, it displays
the class name, superior class, required attribute types, and optional
attribute types. For attribute types, it displays the type name,
type description, and whether the type is single- or multivalued.
The example does not display all the information in the schema.
For example, it does not display the matching rules. It also does
not display the object class IDs, attribute type IDs, attribute
type syntax IDs, or the object class descriptions. (The object class
description values are all “Standard Object Class.”)
Note: To be able to view the schema for an LDAP server,
the server must support LDAP v3
This example does not work on iPlanet Directory Server 5.0. It
does work on a 4.x server.
View the schema for an LDAP directoryCreate
a file that looks like the following:
<html>
<head>
<title>LDAP Schema</title>
</head>
<body>
<!--- Start at Root DSE to get the subschemaSubentry attribute. --->
<cfldap
name="EntryList"
server="ldap.mycorp.com"
action="query"
attributes="subschemaSubentry"
scope="base"
start="">
<!--- Use the DN from the subschemaSubEntry attribute to get the schema. --->
<cfldap
name="EntryList2"
server="ldap.mycorp.com"
action="query"
attributes="objectclasses, attributetypes"
scope="base"
filter="objectclass=*"
start=#entryList.subschemaSubentry#>
<!--- Only one record is returned, so query loop is not required. --->
<h2>Object Classes</h2>
<table border="1">
<tr>
<th>Name</th>
<th>Superior class</th>
<th>Must have</th>
<th>May have</th>
</tr>
<cfloop index = "thisElement" list = #Entrylist2.objectclasses#>
<cfscript>
thiselement = Trim(thisElement);
nameloc = Find("NAME", thisElement);
descloc = Find("DESC", thisElement);
suploc = Find("SUP", thisElement);
mustloc = Find("MUST", thisElement);
mayloc = Find("MAY", thisElement);
endloc = Len(thisElement);
</cfscript>
<tr>
<td><cfoutput>#Mid(thisElement, nameloc+6, descloc-nameloc-8)#
</cfoutput></td>
<cfif #suploc# NEQ 0>
<td><cfoutput>#Mid(thisElement, suploc+5, mustloc-suploc-7)#
</cfoutput></td>
<cfelse>
<td>NONE</td>
</cfif>
<cfif #mayloc# NEQ 0>
<td><cfoutput>#Replace(Mid(thisElement, mustloc+6,
mayloc-mustloc-9), " $ ", ", ", "all")#</cfoutput></td>
<td><cfoutput>#Replace(Mid(thisElement, mayloc+5, endloc-mayloc-8),
" $ ", ", ", "all")#</cfoutput></td>
<cfelse>
<td><cfoutput>#Replace(Mid(thisElement, mustloc+6,
endloc-mustloc-9), " $ ", ", ", "all")#</cfoutput></td>
<td>NONE</td>
</cfif>
</tr>
</cfloop>
</table>
<br><br>
<h2>Attribute Types</h2>
<table border="1" >
<tr>
<th>Name</th>
<th>Description</th>
<th>multivalued?</th>
</tr>
<cfloop index = "thisElement"
list = #ReplaceNoCase(EntryList2.attributeTypes, ", alias", "<br> Alias",
"all")# delimiters = ",">
<cfscript>
thiselement = Trim(thisElement);
nameloc = Find("NAME", thisElement);
descloc = Find("DESC", thisElement);
syntaxloc = Find("SYNTAX", thisElement);
singleloc = Find("SINGLE", thisElement);
endloc = Len(thisElement);
</cfscript>
<tr>
<td><cfoutput>#Mid(thisElement, nameloc+6, descloc-nameloc-8)#
</cfoutput></td>
<td><cfoutput>#Mid(thisElement, descloc+6, syntaxloc-descloc-8)#
</cfoutput></td>
<cfif #singleloc# EQ 0>
<td><cfoutput>Yes</cfoutput></td>
<cfelse>
<td><cfoutput>No</cfoutput></td>
</cfif>
</tr>
</cfloop>
</table>
</body>
</html>
Change the server from ldap.mycorp.com to
your LDAP server. You might also need to specify a user ID and password
in the cfldap tag.
Save the template as ldapschema.cfm in myapps under
your web root directory and view it in your browser.
Reviewing the codeThe following table describes the code and its
function:
Code
|
Description
|
<cfldap
name="EntryList"
server="ldap.mycorp.com"
action="query"
attributes="subschemaSubentry"
scope="base"
start="">
|
Gets the value of the subschemaSubentry
attribute from the root of the directory server. The value is the
DN of the schema.
|
<cfldap
name="EntryList2"
server="ldap.mycorp.com"
action="query"
attributes="objectclasses, attributetypes"
scope="base"
filter="objectclass=*"
start=#entryList.subschemaSubentry#>
|
Uses the schema DN to get the objectclasses
and attributetypes attributes from the schema.
|
<h2>Object Classes</h2>
<table border="1">
<tr>
<th>Name</th>
<th>Superior class</th>
<th>Must have</th>
<th>May have</th>
</tr>
<cfloop index = "thisElement" list = #Entrylist2.objectclasses#>
<cfscript>
thiselement = Trim(thisElement);
nameloc = Find("NAME", thisElement);
descloc = Find("DESC", thisElement);
suploc = Find("SUP", thisElement);
mustloc = Find("MUST", thisElement);
mayloc = Find("MAY", thisElement);
endloc = Len(thisElement);
</cfscript>
|
Displays the object class name, superior
class, required attributes, and optional attributes for each object
class in a table.
The schema contains the definitions of all
object classes in a comma delimited list, so the code uses a list
type cfloop tag.
The thisElement
variable contains the object class definition. Trim off any leading
or trailing spaces, then use the class definition field keywords
in Find functions to get the starting
locations of the required fields, including the Object class ID.
(The ID is not displayed.)
Gets the length of the thisElement string
for use in later calculations.
|
<tr>
<td><cfoutput>#Mid(thisElement, nameloc+6, descloc-nameloc-8)#
</cfoutput></td>
<cfif #suploc# NEQ 0>
<td><cfoutput>#Mid(thisElement, suploc+5, mustloc-suploc-7)#
</cfoutput></td>
<cfelse>
<td>NONE</td>
</cfif>
<cfif #mayloc# NEQ 0>
<td><cfoutput>#Replace(Mid(thisElement, mustloc+6,
mayloc-mustloc-9), " $ ", ", ", "all")#</cfoutput></td>
<td><cfoutput>#Replace(Mid(thisElement, mayloc+5, endloc-mayloc-8),
" $ ", ", ", "all")#</cfoutput></td>
<cfelse>
<td><cfoutput>#Replace(Mid(thisElement, mustloc+6,
endloc-mustloc-9), " $ ", ", ", "all")#</cfoutput></td>
<td>NONE</td>
</cfif>
</tr>
</cfloop>
</table>
|
Displays the field values. Uses the Mid function
to extract individual field values from the thisElement string.
The
top object class does not have a superior class entry. Handles this special
case by testing the suploc location variable. If the value is not 0,
handles normally, otherwise, output "NONE".
There might not
be any optional attributes. Handles this case similarly to the superior
class. The calculation of the location of required attributes uses
the location of the optional attributes if the field exists; otherwise,
uses the end of the object class definition string.
|
<h2>Attribute Types</h2>
<table border="1" >
<tr>
<th>Name</th>
<th>Description</th>
<th>multivalued?</th>
</tr>
<cfloop index = "thisElement"
list = #ReplaceNoCase(EntryList2.attributeTypes, ", alias", "<br> Alias",
"all")# delimiters = ",">
<cfscript>
thiselement = Trim(thisElement);
nameloc = Find("NAME", thisElement);
descloc = Find("DESC", thisElement);
syntaxloc = Find("SYNTAX", thisElement);
singleloc = Find("SINGLE", thisElement);
endloc = Len(thisElement);
</cfscript>
<tr>
<td><cfoutput>#Mid(thisElement, nameloc+6, descloc-nameloc-8)#
</cfoutput></td>
<td><cfoutput>#Mid(thisElement, descloc+6, syntaxloc-descloc-8)#
</cfoutput></td>
<cfif #singleloc# EQ 0>
<td><cfoutput>Yes</cfoutput></td>
<cfelse>
<td><cfoutput>No</cfoutput></td>
</cfif>
</tr>
</cfloop>
|
Does the same types of calculations for
the attribute types as for the object classes.
The
attribute type field can contain the text ", alias for....". This
text includes a comma, which also delimits attribute entries. Use
the REReplaceNoCase function
to replace any comma that precedes the word "alias" with an HTML <br> tag.
The
attribute definition includes a numeric syntax identifier, which the
code does not display, but uses its location in calculating the
locations of the other fields.
|
|