cvs: peardoc /en/package/networking/net-ldap2 attributes.xml connect.xml entries.xml errorhandling.xml fetching.xml filter.xml introduction.xml ldif.xml search.xml

[email protected] ("Benedikt Hallinger")
Newsgroups php.pear.doc
Message-ID <cvsbeni1243499407@cvsserver>
beni		Thu May 28 08:30:07 2009 UTC

  Added files:                 
    /peardoc/en/package/networking/net-ldap2	attributes.xml connect.xml 
                                            	entries.xml 
                                            	errorhandling.xml 
                                            	fetching.xml filter.xml 
                                            	introduction.xml ldif.xml 
                                            	search.xml 
  Log:
  * New doc for net-ldap2
beni-20090528083007.txt (text/plain, 84 KB)
http://cvs.php.net/viewvc.cgi/peardoc/en/package/networking/net-ldap2/attributes.xml?view=markup&rev=1.1
Index: peardoc/en/package/networking/net-ldap2/attributes.xml
+++ peardoc/en/package/networking/net-ldap2/attributes.xml
<?xml version="1.0" encoding="utf-8"?>
<refentry xmlns="http://docbook.org/ns/docbook" version="lillet" xml:id="package.networking.net-ldap2.attributes">
    <refnamediv>
        <refname>Attributes</refname>
        <refpurpose>Reading/adding/changing/deleting attributes from entries</refpurpose>
    </refnamediv>

   <refsection><info><title>Reading attributes</title></info>
        <para>
           Reading attribute values depends on the selection of those attributes at search time. You can only access attributes that where selected!
           You can read attribute values using either <classname>Net_LDAP2_Entry</classname>'s <function>getValues</function> or <function>getValue</function> method.
           <function>getValue</function> will return an array where the keys are the attributes names.
           If you use <function>getValues</function> you may pass an option:
           <itemizedlist>
              <listitem>
                <para>
                  <literal>'single'</literal>: only the first value is returned as string
                </para>
              </listitem>
              <listitem>
                <para>
                  <literal>'all'</literal>: all values including the value count are returned in an array
                </para>
              </listitem>
              <listitem>
                <para>
                  <literal>'default'</literal>: in all other cases an attribute value with a single value is
                                             returned as string, if it has multiple values it is returned
                                             as an array (without value count)
                </para>
              </listitem>
           </itemizedlist>
           </para>
        <example><info><title>Reading attributes</title></info>

        <programlisting role="php"><![CDATA[
// read Surename, singlevalued
$surename = $entry->getValue('sn', 'single');

// read mail adress which may be multivalued
$mail = $entry->getValue('mail', 'all');
]]></programlisting>
        </example>


   <para>
       If you want to read the distinguished name of an Entry (DN), you must use a different method: <function>dn</function>
      <example><info><title>Reading an entries DN</title></info>

        <programlisting role="php"><![CDATA[
$dn = $entry->dn();
]]></programlisting>
        </example>
    </para>

    </refsection>

    <refsection><info><title>Regular expressions on attributes</title></info>
        <para>
          PEAR::Net_LDAP2 has the unique feature to apply a regular expression match directly against attributes, so
          you do not need to manually fetch all values and run the regex against them.
          Instead, you can use <classname>Net_LDAP2_Entry</classname>'s <function>preg_match</function> function.
          The behavior of this function is the same as PHPs preg_match(), but the $matches array is slightly different.
          It features one dimension more, since it may match for several attribute values if the attribute is multivalued.
          If you pass $matches, be sure to do it via REFERENCE, because otherwise $matches remains empty.
          <function>preg_match</function> returns true or false, depending on match.
        </para>
        <example><info><title>Performing preg_match on attribute values</title></info>

        <programlisting role="php"><![CDATA[
// Look, if the user has an emailadress for 'example', if so,
// we want to display the tld:
// (be sure to pass $matches as reference!)
$matches = array();
if ( $entry->preg_match('mail', '/example\.(.+)/', &$matches) ) {
    // print every TLD found for 'example':
    foreach ($matches as $match) {
        echo $match[1];
    }
}
]]></programlisting>
        </example>

    </refsection>

    <refsection><info><title>General information regarding attribute changing</title></info>
        <para>
            It is important to know how attribute changing works. Modifications to an entry
            through the <classname>Net_LDAP2_Entry</classname>-object are local only.
            After you have made all changes and want to transfer them to the directory server, you must
            call <function>update</function> of the <classname>Net_LDAP2_Entry</classname> object.
            This will return either <literal>TRUE</literal> or an <classname>Net_LDAP2_Error</classname>.
            Another good information is, that you must select attributes at search time
            if you want to add/change/delete attribute values. Otherwise Net_LDAP2 will most likely fail
            silently giving you the wrong assumtion that everything was okay - Net_LDAP2 needs knowledge
            of the attributes it should work with!
        </para>
        <para>Modification of attributes is also possible through <classname>Net_LDAP2</classname>'s <function>modify</function> method.
              This method will call the methods described here on the <classname>Net_LDAP2_Entry</classname> object given, and
              directly calls an <function>update</function> after that, thus performing the changes directly on the server.
              The parameter is an complex array describing the changes to be performed. It is considered for more advanced users,
              because it is more compact, so please refer to the latest API documentation for more information.</para>
    </refsection>

    <refsection><info><title>Adding attributes</title></info>
        <para>
          Adding attrbiute values to an entry is an easy task. You just need to call <function>add</function>!
          The parameter is an array whose keys are the attribute names and values the attributes values.
          If only one attribute value should be added, the second level may be a string.
          If the attribute doesn't exist so far, it will be added, if it exists, the attributes values will be added.
        </para>
        <example><info><title>Adding attributes</title></info>

        <programlisting role="php"><![CDATA[
// Adding several attributes:
$result = $entry->add(
    array(
        'sn'   => 'Doe',
        'gn'   => array('John'),
        'mail' => array('[email protected]', '[email protected]')
    )
);
]]></programlisting>
        </example>

    </refsection>

    <refsection><info><title>Changing attributes</title></info>
        <para>
           Changing values is with the <function>replace</function> method as easy as adding values. However, you have to be a little more careful.
           The expected parameter is an array describing the new absolute state of the named
           attributes. This means, if you specify a <literal>NULL</literal> value for an attribute,
           this attribute will get deleted!
           You may specify single values as string too.
           The keys of the array are expected to be the attributes names.
        </para>
        <example><info><title>Changing attributes</title></info>

        <programlisting role="php"><![CDATA[
// Changing several attributes:
// 'sn' is changed to "Smith", 'gn' gets deleted and mail will
// be changed to te two new adresses
$result = $entry->replace(
    array(
        'sn'   => 'Smith',
        'gn'   => null,
        'mail' => array('[email protected]', '[email protected]')
    )
);
]]></programlisting>
        </example>

    </refsection>

    <refsection><info><title>Deleting attributes</title></info>
        <para>
          Using the <function>delete</function> method you are able to delete specific attributes values as well
          as delete a whole attribute.
          You need to specify the attribute names as array keys, the array values are the values you want to delete.
          If you want to delete whole attributes, specify them as single level array.
          Special care must be taken not to delete the whole entry which will be the case if the parameter array is 
          omitted or set to <literal>NULL</literal>!
          Also, don't mix syntax modes. If you want to delete whole attributes you can't delete specific values from another attribute
          in the same function call.
        </para>
        <example><info><title>Deleting attributes</title></info>

        <programlisting role="php"><![CDATA[
// Delete the whole entry:
$result = $entry->delete();

// Delete the whole telephone number attribute:
$result = $entry->delete('telephoneNumber');

// Delete one specific mail attributes value:
$result = $entry->delete( array('mail' => '[email protected]') );

// Delete mail and telephone attributes as a whole:
$result = $entry->delete( array('mail', 'telephoneNumber') );

// Delete two specific mail adresses:
$result = $entry->delete( array('mail' => array('[email protected]', '[email protected]')) );
]]></programlisting>
        </example>
    </refsection>

    <refsection>
        <title>Changing Objectclasses</title>
        <para>
            Object classes describe the attribute set of an entry with this objectclass set.
            The entry stores the objectclass in a special attribute named "objectClass",
            and of course you may alter that attribute like any other attribute.
        </para>
        <para>
            However, special care must be taken if changing this attribute since
            most directory servers impose rules on the other attributes the object class define.
            For example, it is usually not possible to delete an objectclass if some of the attributes
            the class describes are still in use by the entry.
            This should be not much of a problem with optional attributes, but
            sometimes objectclasses have mandatory attributes set. Also structural objectclasses
            can only be added when creating new entrys. Because of the internal
            architecture of Net_LDAP2 it is currently not possible to resolve those cases.
        </para>
        <para>
            To add or remove objectclasses with mandatory attributes or new structural object classes,
            you need to delete the old entry from the directory server and add the new one with the
            new objectclass and attributes as fresh entry.
        </para>
        <example>
        <title>Changing complex objectclasses</title>
        <programlisting role="php"><![CDATA[
// Let's assume that the objectclass myClass enforce the attribute "fooattr"
// Take care that you have all attributes requested, otherwise the new
// entry will not have all attributes set!
$entry->add(array(
    'objectClass'   => 'myClass',
    'fooatrr'       => 'foo',
    'someotherattr' => array('bar', 'baz')
    ));

// Calling $entry->update() now will not succeed under some circumstances!
// We construct a fresh entry object which is in fact a copy of the already
// existing entry with all changes already applied (the local copy).
// It is important, that at fetching time of $entry all attributes where selected!
// Only the selected attributes will get copied.
$changed_entry = Net_LDAP2_Entry::createFresh($entry->dn(), $entry->getValues());

// Now delete the old entry and add the new one:
$ldap->delete($entry);
$ldap->add($changed_entry);

]]></programlisting>
        </example>
    </refsection>
</refentry>

http://cvs.php.net/viewvc.cgi/peardoc/en/package/networking/net-ldap2/connect.xml?view=markup&rev=1.1
Index: peardoc/en/package/networking/net-ldap2/connect.xml
+++ peardoc/en/package/networking/net-ldap2/connect.xml
<?xml version="1.0" encoding="utf-8"?>
<refentry xmlns="http://docbook.org/ns/docbook" version="lillet" xml:id="package.networking.net-ldap2.connecting">
    <refnamediv>
        <refname>Configuration and connecting</refname>
        <refpurpose>How to configure Net_LDAP2 and connect to an LDAP server</refpurpose>
    </refnamediv>

    <refsection><info><title>Connecting to an LDAP server</title></info>
        
        
        <para>
        To connect to an LDAP server, you should use
        <classname>Net_LDAP2</classname>'s static <function>connect</function> method.
        It takes one parameter, an array full of configuration options,
        and either returns
        a <classname>Net_LDAP2</classname> object if connecting works, or a
        <classname>Net_LDAP2_Error</classname> object in case of a failure.
        </para>
        
        <para>
        The following table lists all configuration options. If the default
        value for an option fits your needs, you don't need add it to your
        configuration array.
        
        <table><title>Possible configuration options</title>
        
        <tgroup cols="3">
            <thead>
            <row>
            <entry>Name</entry>
            <entry>Description</entry>
            <entry>Default</entry>
            </row>
            </thead>
            <tbody>
            <row>
            <entry><literal>host</literal></entry>
            <entry>LDAP server name to connect to. You can provide several hosts in an array in which case the hosts are tried from left to right.</entry>
            <entry><literal>localhost</literal></entry>
            </row>
        
            <row>
            <entry><literal>port</literal></entry>
            <entry>Port on the server</entry>
            <entry>389</entry>
            </row>
        
            <row>
            <entry><literal>version</literal></entry>
            <entry>LDAP version</entry>
            <entry><literal>3</literal></entry>
            </row>
        
            <row>
            <entry><literal>starttls</literal></entry>
            <entry>TLS is started after connecting</entry>
            <entry><literal>false</literal></entry>
            </row>
        
            <row>
            <entry><literal>binddn</literal></entry>
            <entry>The distinguished name to bind as (username)</entry>
            <entry>(none)</entry>
            </row>
        
            <row>
            <entry><literal>bindpw</literal></entry>
            <entry>Password for the <literal>binddn</literal></entry>
            <entry>(none)</entry>
            </row>
        
            <row>
            <entry><literal>basedn</literal></entry>
            <entry>LDAP base name (root directory)</entry>
            <entry>(none)</entry>
            </row>
        
            <row>
            <entry><literal>options</literal></entry>
            <entry>Array of additional ldap options as key-value pairs</entry>
            <entry><literal>array()</literal></entry>
            </row>
        
            <row>
            <entry><literal>filter</literal></entry>
            <entry>
                Default search filter (string or preferably <classname>Net_LDAP2_Filter</classname> object).
                See <link linkend="package.networking.net-ldap2.filter">LDAP filters</link>
            </entry>
            <entry><literal>(objectClass=*)</literal></entry>
            </row>
        
            <row>
            <entry><literal>scope</literal></entry>
            <entry>Default search scope, see <link linkend="package.networking.net-ldap2.search">Search</link></entry>
            <entry><literal>sub</literal></entry>
            </row>
        
            </tbody>
        </tgroup>
        </table>
        </para>
        
        <example><info><title>Connecting to an LDAP server</title></info>
        
        <programlisting role="php"><![CDATA[
// Inclusion of the Net_LDAP2 package:
require_once 'Net/LDAP.php';

// The configuration array:
$config = array (
    'binddn'    => 'cn=admin,ou=users,dc=example,dc=org',
    'bindpw'    => 'password',
    'basedn'    => 'dc=example,dc=org',
    'host'      => 'ldap.example.org'
);

// Connecting using the configuration:
$ldap = Net_LDAP2::connect($config);

// Testing for connection error
if (PEAR::isError($ldap)) {
    die('Could not connect to LDAP-server: '.$ldap->getMessage());
}
]]></programlisting>
        </example>

    </refsection>
</refentry>

http://cvs.php.net/viewvc.cgi/peardoc/en/package/networking/net-ldap2/entries.xml?view=markup&rev=1.1
Index: peardoc/en/package/networking/net-ldap2/entries.xml
+++ peardoc/en/package/networking/net-ldap2/entries.xml
<?xml version="1.0" encoding="utf-8"?>
<refentry xmlns="http://docbook.org/ns/docbook" version="lillet" xml:id="package.networking.net-ldap2.entries">
    <refnamediv>
        <refname>Managing entries</refname>
        <refpurpose>Adding/renaming/moving/deleting entries</refpurpose>
    </refnamediv>

    <refsection><info><title>Adding (fresh or old) entries to the directory</title></info>
        

        <para>
           Adding new entries is performed in two ways. First, you need to establish a fresh <classname>Net_LDAP2_Entry</classname> object.
           After that, you can add that entry like you would add already-existent entries using
           <classname>Net_LDAP2</classname>'s <function>add</function> method.
        </para>

        <example><info><title>Adding a fresh entry</title></info>
        
        <programlisting role="php"><![CDATA[
// Build a new fresh entry:
$dn         = 'cn=new-admin,o=example,dc=org';
$attributes = array(
    'cn'              => 'new-admin',
    'mail'            => array('[email protected]', '[email protected]'),
    'telephoneNumber' => '1234567890'
);
$entry = Net_LDAP2_Entry::createFresh($dn, $attributes);

// Add the entry to the directory:
$ldap->add($entry);
]]></programlisting>
        </example>
    </refsection>


    <refsection><info><title>Renaming or moving entries</title></info>
        

        <para>
        Renaming and/or moving an entry is an operation on the DN of an entry. Moving an entry means, to rename a DN in such a way, that
        the entry becomes a new base-DN. You can rename or move an entry, if you call the <function>dn</function> method of the entry you
        want to relocate. Alternatively, you may call <classname>Net_LDAP2</classname>'s <function>move</function> method that also ca handle
        only DNs. Remember that you must call the entires <function>update</function> method to carry out the move/rename.
        <classname>Net_LDAP2</classname>'s <function>move</function> will move the entry immediately. If you use an entryobject togehter with
        <classname>Net_LDAP2</classname>'s <function>move</function>, you are able to perform cross directory moves.
        </para>
        <example><info><title>Moving an entry using Net_LDAP2_Entry</title></info>
        
        <programlisting role="php"><![CDATA[
// Defining the DN we want to fetch;
$dn    = 'cn=admin,o=example,dc=org';
$newdn = 'cn=admin,o=new-example,dc=org';
$entry = $ldap->getEntry($dn);

$entry->dn($newdn);
]]></programlisting>
        </example>
        <example><info><title>Moving an entry using Net_LDAP2 and Net_LDAP2_Entry</title></info>
        
        <programlisting role="php"><![CDATA[
// Defining the DN we want to fetch;
$dn    = 'cn=admin,o=example,dc=org';
$newdn = 'cn=admin,o=new-example,dc=org';
$entry = $ldap->getEntry($dn);

$ldap->move($entry, $newdn);
]]></programlisting>
        </example>
        <example><info><title>Renaming an entry using Net_LDAP2 and DNs</title></info>
        
        <programlisting role="php"><![CDATA[
// Defining the DN we want to fetch;
$dn    = 'cn=admin,o=example,dc=org';
$newdn = 'cn=admin2,o=new-example,dc=org';

$ldap->move($dn, $newdn);
]]></programlisting>
        </example>
<example><info><title>Performing a cross directory move</title></info>
        
        <programlisting role="php"><![CDATA[
// $ldap_src is the source ldap and $ldap_tgt the target
$dn    = 'cn=admin,o=example,dc=org';
$newdn = 'cn=admin,o=new-example,dc=org';
$entry = $ldap_src->getEntry($dn);

$ldap_src->move($entry, $newdn, $ldap_tgt);
]]></programlisting>
        </example>

    </refsection>

    <refsection><info><title>Deleting entries</title></info>
        

        <para>
          Deleting entries is performed using <classname>Net_LDAP2</classname>'s <function>delete</function> method.
          Just pass the <classname>Net_LDAP2_Entry</classname> object or the DN of the entry you want to delete.
          In the case that the DN contains subentrys, you need to pass <literal>TRUE</literal> as second parameter
          which will make <function>delete</function> delete recursive.
        </para>
        <para>
          A second way exist: You may simply call <function>delete</function> from the <classname>Net_LDAP2_Entry</classname> you want to delete.
          Don't forget that you must call <function>update</function> to carry out the delete in this case.
        </para>

        <example><info><title>Deleting an entry</title></info>
        
        <programlisting role="php"><![CDATA[
$dn  = 'cn=new-admin,o=example,dc=org';
$ldap->delete($dn);
]]></programlisting>
        </example>
        <example><info><title>Deleting an entry using a Net_LDAP2_Entry object</title></info>
        
        <programlisting role="php"><![CDATA[
$entry->delete();
$entry->update();
]]></programlisting>
        </example>
    </refsection>
</refentry>

http://cvs.php.net/viewvc.cgi/peardoc/en/package/networking/net-ldap2/errorhandling.xml?view=markup&rev=1.1
Index: peardoc/en/package/networking/net-ldap2/errorhandling.xml
+++ peardoc/en/package/networking/net-ldap2/errorhandling.xml
<?xml version="1.0" encoding="utf-8"?>
<refentry xmlns="http://docbook.org/ns/docbook" version="lillet" xml:id="package.networking.net-ldap2.errorhandling">
    <refnamediv>
        <refname>Error handling</refname>
        <refpurpose>How handling errors works in Net_LDAP2</refpurpose>
    </refnamediv>
    
    <refsection><info><title>Error handling</title></info>
        
        
        <para>
            Nearly all of Net_LDAPs methods return a <classname>Net_LDAP2_Error</classname> object if something went wrong.
            You always should check for errors after you performed an action to be sure that your
            application doesn't do things you don't want it to do.
        </para>
        
        <para>
            Handling errors is an easy task, you just have to test the return value as
            shown below. If an error occured, you can halt the script for example.
            In other cases, you may just log the error, but what exactly happens depends on
            your specific situation, of course.
        </para>
        <para>
            You can use the <function>getMessage</function> method of the error object to retrieve the error message explaining the problem
            and <function>getCode</function> to get the error code which is usually the LDAP-Error code (see Table below)
            and may be used for automated reaction on errors.
        </para>
        
        <example><info><title>Dealing with errors</title></info>
        
        <programlisting role="php"><![CDATA[
// Perform an arbitrary action:
$result = $ldap->search($searchbase, $filter, $options);

// Check, if an error occured and do something.
// Here we use die() to show the message of the error.
if (PEAR::isError($result)) {
    die($result->getMessage());
}
]]></programlisting>
        </example>

        <table><title>Error codes Net_LDAP2</title>
            
            <tgroup cols="2">
                <thead>
                    <row>
                        <entry>Error code</entry>
                        <entry>Description</entry>
                    </row>
                </thead>
                <tbody>
                    <row><entry>0x00</entry><entry>LDAP_SUCCESS</entry></row>
                    <row><entry>0x01</entry><entry>LDAP_OPERATIONS_ERROR</entry></row>
                    <row><entry>0x02</entry><entry>LDAP_PROTOCOL_ERROR</entry></row>
                    <row><entry>0x03</entry><entry>LDAP_TIMELIMIT_EXCEEDED</entry></row>
                    <row><entry>0x04</entry><entry>LDAP_SIZELIMIT_EXCEEDED</entry></row>
                    <row><entry>0x05</entry><entry>LDAP_COMPARE_FALSE</entry></row>
                    <row><entry>0x06</entry><entry>LDAP_COMPARE_TRUE</entry></row>
                    <row><entry>0x07</entry><entry>LDAP_AUTH_METHOD_NOT_SUPPORTED</entry></row>
                    <row><entry>0x08</entry><entry>LDAP_STRONG_AUTH_REQUIRED</entry></row>
                    <row><entry>0x09</entry><entry>LDAP_PARTIAL_RESULTS</entry></row>
                    <row><entry>0x0a</entry><entry>LDAP_REFERRAL</entry></row>
                    <row><entry>0x0b</entry><entry>LDAP_ADMINLIMIT_EXCEEDED</entry></row>
                    <row><entry>0x0c</entry><entry>LDAP_UNAVAILABLE_CRITICAL_EXTENSION</entry></row>
                    <row><entry>0x0d</entry><entry>LDAP_CONFIDENTIALITY_REQUIRED</entry></row>
                    <row><entry>0x0e</entry><entry>LDAP_SASL_BIND_INPROGRESS</entry></row>
                    <row><entry>0x10</entry><entry>LDAP_NO_SUCH_ATTRIBUTE</entry></row>
                    <row><entry>0x11</entry><entry>LDAP_UNDEFINED_TYPE</entry></row>
                    <row><entry>0x12</entry><entry>LDAP_INAPPROPRIATE_MATCHING</entry></row>
                    <row><entry>0x13</entry><entry>LDAP_CONSTRAINT_VIOLATION</entry></row>
                    <row><entry>0x14</entry><entry>LDAP_TYPE_OR_VALUE_EXISTS</entry></row>
                    <row><entry>0x15</entry><entry>LDAP_INVALID_SYNTAX</entry></row>
                    <row><entry>0x20</entry><entry>LDAP_NO_SUCH_OBJECT</entry></row>
                    <row><entry>0x21</entry><entry>LDAP_ALIAS_PROBLEM</entry></row>
                    <row><entry>0x22</entry><entry>LDAP_INVALID_DN_SYNTAX</entry></row>
                    <row><entry>0x23</entry><entry>LDAP_IS_LEAF</entry></row>
                    <row><entry>0x24</entry><entry>LDAP_ALIAS_DEREF_PROBLEM</entry></row>
                    <row><entry>0x30</entry><entry>LDAP_INAPPROPRIATE_AUTH</entry></row>
                    <row><entry>0x31</entry><entry>LDAP_INVALID_CREDENTIALS</entry></row>
                    <row><entry>0x32</entry><entry>LDAP_INSUFFICIENT_ACCESS</entry></row>
                    <row><entry>0x33</entry><entry>LDAP_BUSY</entry></row>
                    <row><entry>0x34</entry><entry>LDAP_UNAVAILABLE</entry></row>
                    <row><entry>0x35</entry><entry>LDAP_UNWILLING_TO_PERFORM</entry></row>
                    <row><entry>0x36</entry><entry>LDAP_LOOP_DETECT</entry></row>
                    <row><entry>0x3C</entry><entry>LDAP_SORT_CONTROL_MISSING</entry></row>
                    <row><entry>0x3D</entry><entry>LDAP_INDEX_RANGE_ERROR</entry></row>
                    <row><entry>0x40</entry><entry>LDAP_NAMING_VIOLATION</entry></row>
                    <row><entry>0x41</entry><entry>LDAP_OBJECT_CLASS_VIOLATION</entry></row>
                    <row><entry>0x42</entry><entry>LDAP_NOT_ALLOWED_ON_NONLEAF</entry></row>
                    <row><entry>0x43</entry><entry>LDAP_NOT_ALLOWED_ON_RDN</entry></row>
                    <row><entry>0x44</entry><entry>LDAP_ALREADY_EXISTS</entry></row>
                    <row><entry>0x45</entry><entry>LDAP_NO_OBJECT_CLASS_MODS</entry></row>
                    <row><entry>0x46</entry><entry>LDAP_RESULTS_TOO_LARGE</entry></row>
                    <row><entry>0x47</entry><entry>LDAP_AFFECTS_MULTIPLE_DSAS</entry></row>
                    <row><entry>0x50</entry><entry>LDAP_OTHER</entry></row>
                    <row><entry>0x51</entry><entry>LDAP_SERVER_DOWN</entry></row>
                    <row><entry>0x52</entry><entry>LDAP_LOCAL_ERROR</entry></row>
                    <row><entry>0x53</entry><entry>LDAP_ENCODING_ERROR</entry></row>
                    <row><entry>0x54</entry><entry>LDAP_DECODING_ERROR</entry></row>
                    <row><entry>0x55</entry><entry>LDAP_TIMEOUT</entry></row>
                    <row><entry>0x56</entry><entry>LDAP_AUTH_UNKNOWN</entry></row>
                    <row><entry>0x57</entry><entry>LDAP_FILTER_ERROR</entry></row>
                    <row><entry>0x58</entry><entry>LDAP_USER_CANCELLED</entry></row>
                    <row><entry>0x59</entry><entry>LDAP_PARAM_ERROR</entry></row>
                    <row><entry>0x5a</entry><entry>LDAP_NO_MEMORY</entry></row>
                    <row><entry>0x5b</entry><entry>LDAP_CONNECT_ERROR</entry></row>
                    <row><entry>0x5c</entry><entry>LDAP_NOT_SUPPORTED</entry></row>
                    <row><entry>0x5d</entry><entry>LDAP_CONTROL_NOT_FOUND</entry></row>
                    <row><entry>0x5e</entry><entry>LDAP_NO_RESULTS_RETURNED</entry></row>
                    <row><entry>0x5f</entry><entry>LDAP_MORE_RESULTS_TO_RETURN</entry></row>
                    <row><entry>0x60</entry><entry>LDAP_CLIENT_LOOP</entry></row>
                    <row><entry>0x61</entry><entry>LDAP_REFERRAL_LIMIT_EXCEEDED</entry></row>
                    <row><entry>1000</entry><entry>Unknown Net_LDAP2 Error</entry></row>
                </tbody>
            </tgroup>
        </table>
    </refsection>
</refentry>

http://cvs.php.net/viewvc.cgi/peardoc/en/package/networking/net-ldap2/fetching.xml?view=markup&rev=1.1
Index: peardoc/en/package/networking/net-ldap2/fetching.xml
+++ peardoc/en/package/networking/net-ldap2/fetching.xml
<?xml version="1.0" encoding="utf-8"?>
<refentry xmlns="http://docbook.org/ns/docbook" version="lillet" xml:id="package.networking.net-ldap2.fetching">
    <refnamediv>
        <refname>Fetching entries</refname>
        <refpurpose>Retrieving entries directly or from a searchresult</refpurpose>
    </refnamediv>

    <refsection><info><title>Retrieving entries directly</title></info>
        

        <para>
        You can retrieve directory entries in several ways, either directly or from a performed search request.
        If you want to fetch an entry directly, you need to know its absolute distinguished name (DN).

        To directly fetch an known entry from the directory server, you use
        <classname>Net_LDAP2</classname>'s <function>getEntry</function> method.
        It takes two parameters: The DN of the entry and the attributes you want to
        read from the entry.
        It returns a <classname>Net_LDAP2_Entry</classname> object if fetching worked, or a
        <classname>Net_LDAP2_Error</classname> object in case of a failure.
        </para>

        <para>
        You may also check if the entry exists in the server before you fetch it. This can be achieved by
        <classname>Net_LDAP2</classname>'s <function>dnExists</function> which takes the DN to test and returns either true or false.
        </para>

        <example><info><title>Fetching an entry directly</title></info>
        
        <programlisting role="php"><![CDATA[
// Defining the DN we want to fetch;
// we want to select the given- and the surname
$dn = 'cn=admin,o=example,dc=org';
$entry = $ldap->getEntry($dn, array('gn', 'sn'));

// Error checking is important!
if (Net_LDAP2::isError($entry)) {
	die('Could not fetch entry: '.$entry->getMessage());
}
]]></programlisting>
        </example>

    </refsection>


    <refsection><info><title>Retrieving entries from a searchresult</title></info>
        

        <para>
        The second way to retrieve entries is from a searchresult. As described in chapter "<link linkend="package.networking.net-ldap2.search">Search</link>",
        you access the entries of a search result through the <classname>Net_LDAP2_Search</classname>-object resulting from
        <classname>Net_LDAP2</classname>'s <function>search</function> method.
        Each of the following methods return a <classname>Net_LDAP2_Error</classname>-object if something goes wrong, so
        remember to test for errors!
        You have several ways to read the entries:
        <table><title>Possible ways to fetch entries</title>
        
        <tgroup cols="2">
            <thead>
            <row>
            <entry>Method of <classname>Net_LDAP2_Search</classname></entry>
            <entry>Description</entry>
            </row>
            </thead>

            <tbody>
            <row>
            <entry><function>entries</function></entry>
            <entry>This returns the entries at once unsorted.</entry>
            </row>

            <row>
            <entry><function>as_struct</function></entry>
            <entry>This returns all entries as multidimensional array instead of <classname>Net_LDAP2_Entry</classname>-objects.
                   The array keys of the first dimension are the DNs and the value is an array containing all attributes.
                   The array keys of the second level are the attributes names; the value of the second level is an array containing all the
                   attributes values. Note, that even if there are no or just one value, an array is present.</entry>
            </row>

            <row>
            <entry><function>sorted</function></entry>
            <entry>Use this if you want to get the entries at once but sorted. You can sort by several attributes which can contain multiple values.
                   You can of course sort ascending (default) or descending - just pass the PHP constant <literal>SORT_ASC</literal> or <literal>SORT_DESC</literal> as second parameter.</entry>
            </row>

            <row>
            <entry><function>sorted_as_struct</function></entry>
            <entry>Like <function>as_struct</function>, this returns the entries as multidimensional array, but in this case sorted. For parameters, see <function>sorted</function></entry>
            </row>

            <row>
            <entry><function>shiftEntry</function></entry>
            <entry>This returns one entry from the beginning of the search result.
                   Since this returns <literal>FALSE</literal> if all entries are fetched, <function>shiftEntry</function> is perfectly
                   appropriate to get used inside a while-loop.
                   Take care not to mix <function>shiftEntry</function> and <function>popEntry</function>!</entry>
            </row>

            <row>
            <entry><function>popEntry</function></entry>
            <entry>Exactly the same as shiftEntry, but returns the entry from the end of the searchresult. Again, be sure to not mix
                   <function>shiftEntry</function> and <function>popEntry</function>!</entry>
            </row>
            </tbody>
        </tgroup>
        </table>

        To directly fetch an known entry from the directory server, you use
        <classname>Net_LDAP2</classname>'s <function>getEntry</function> method.
        It takes two parameters: The DN of the entry and the attributes you want to
        read from the entry.
        It returns a <classname>Net_LDAP2_Entry</classname> object if fetching worked, or a
        <classname>Net_LDAP2_Error</classname> object in case of a failure.
        </para>

        <para>
        You may also check if the entry exists in the server before you fetch it. This can be achieved by
        <classname>Net_LDAP2</classname>'s <function>dnExists</function> which takes the DN to test and returns either true or false.
        </para>

        <example><info><title>Fetching all entries from searchresult</title></info>
        
        <programlisting role="php"><![CDATA[
// return all entries:
$entry = $search->entries();
]]></programlisting>
        </example>

        <example><info><title>Fetching all entries from searchresult: sorted</title></info>
        
        <programlisting role="php"><![CDATA[
// return sorted by first 'sn' then 'gn', but descending:
$entry = $search->sorted(array('sn', 'gn'), SORT_DESC);
]]></programlisting>
        </example>

        <example><info><title>Fetching entries one by one inside a while loop</title></info>
        
        <programlisting role="php"><![CDATA[
// return entries one by one:
while ( $entry = $search->shiftEntry() ) {
    // do something, like printing the DN of the entry;
    // in a real case, dont forget to test for errors!
    echo "ENTRY: " . $entry->dn();
}
]]></programlisting>
        </example>

    </refsection>

    <refsection><info><title>Retrieving entries via iteration (foreach)</title></info>
        

        <para>
        Since Net_LDAP2 you are able to use PHPs Standard Library (SPL) to iterate over
        search results. This is done easily by just using the <classname>Net_LDAP2_Search</classname>
        search result object inside an foreach loop similar to an array.
        You may optionally retrieve the DN of each entry by the same mechanism you use to
        retrieve the key of an associative array.
        </para>

        <example><info><title>Fetching entries via foreach()</title></info>
        
        <programlisting role="php"><![CDATA[
foreach ($search as $dn => $entry) {
    // do something:
    $sn = $entry->getValue('sn', 'single');
    echo "Fetched DN: $dn; Surname: $sn";
}
]]></programlisting>
        </example>

    </refsection>
</refentry>

http://cvs.php.net/viewvc.cgi/peardoc/en/package/networking/net-ldap2/filter.xml?view=markup&rev=1.1
Index: peardoc/en/package/networking/net-ldap2/filter.xml
+++ peardoc/en/package/networking/net-ldap2/filter.xml
<?xml version="1.0" encoding="utf-8"?>
<refentry xmlns="http://docbook.org/ns/docbook" version="lillet" xml:id="package.networking.net-ldap2.filter">
    <refnamediv>
        <refname>LDAP filters</refname>
        <refpurpose>Introduction to and usage of LDAP filters</refpurpose>
    </refnamediv>
    <refsection><info><title>What are LDAP filters?</title></info>
        
        <para>
            LDAP filters are defined in <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.ietf.org/rfc/rfc2254.txt">RFC 2254</link>
            and can be compared to the WHERE clause in SQL select statements - they filter
            the data returned from some search request - in this case the entries returned from
            the directory server. With Net_LDAP2, you may use plain strings as filters, or preferably,
            the <classname>Net_LDAP2_Filter</classname> class which mostly releases you of the burden to escape yourself and
            to remember all the various special characters needed for constructing and combining filters.
        </para>
        <para>Where and how to use filters is described in chapter <link linkend="package.networking.net-ldap2.search">Search</link>.</para>
    </refsection>

    <refsection><info><title>Some LDIF filter basics</title></info>
        
        <para>
            Although you should preferably use the <classname>Net_LDAP2_Filter</classname> class to
            construct your LDAP filters, some theory may be interesting and helpful in understanding
            how to construct LDAP filters and what they are capable of.
        </para>
        <para>
            Basic LDAP filters are composed of an "[attribute][operator][value]" pair enclosed by round brackets.
            There are several comparison operators available: "=" (equal), "&gt;" (greater), <![CDATA["<"]]> (less),
            "&gt;=" (greater or equal), <![CDATA["<="]]> (less or equal) and "=~" (phonetical similar). The exact match behavior
            is defined by the attribute syntax of the attribute to which the filter should apply.
        </para>
        <example><info><title>Some basic string filters</title></info>
        
        <programlisting role="php"><![CDATA[
// Filter entries whose first name is 'Benedikt':
$filter = '(givenName=Benedikt)';

// Filter entries which have an employeenumber higher or equal than 1424:
$filter = '(employeeNumber>=1424)';

// Filter entries whose first name sounds similar to "Stephane"
// This should also find "Stephen" and "Stefan" (depending on implementation)
$filter = '(givenName=~Stephane)';
]]></programlisting>
    </example>

        <para>
                The value part of the basic filter construct could also include a special character: "*".
                The star acts as placeholder for none, one or several characters at that position.
                "V*lue" would therefore match against "Value", "Vlue", "VaaAaAalue" and so on.
                There are some special named combinations using the star, but they work exactly the same way:
                <table><title>Special named placeholder combinations</title>
                    
                    <tgroup cols="3">
                        <thead>
                            <row>
                                <entry>Name</entry>
                                <entry>Filter</entry>
                                <entry>Description</entry>
                            </row>
                        </thead>
                        <tbody>
                            <row><entry>present</entry><entry>(attr=*)</entry><entry>Also refered to as "any". Finds any entry containing any (unless empty) value for the named attribute.</entry></row>
                            <row><entry>begins</entry><entry>(attr=value*)</entry><entry>value starts with some fixed string</entry></row>
                            <row><entry>ends</entry><entry>(attr=*value)</entry><entry>value ends with some fixed string</entry></row>
                            <row><entry>contains</entry><entry>(attr=*value*)</entry><entry>value contains some fixed string</entry></row>
                        </tbody>
                    </tgroup>
                </table>
        </para>

        <refsection><info><title>Combining string filters</title></info>
            
            <para>
                Basic filters can be combined using the three logical operators <![CDATA["&"]]> (and),
                <![CDATA["|"]]> (or) and <![CDATA["!"]]> (not). Note, that the smallest filter component,
                the basic filter enclosed in round brackets, remains isolated: instead of just adding another
                "[attribute][operator][value]" pair into the brackets, a new bracket level is introduced that
                contains all filter components that should be combined. Note also, that the logical operator
                does stand in front of all filter components, not between them as common in programming languages.
            </para>
            <example><info><title>Combining string filters</title></info>
            
            <programlisting role="php"><![CDATA[
    // Search all 'Benedikt's with phone number 1234567890
    $filter = '(&(givenName=Benedikt)(telephoneNumber=1234567890))';
    
    // Search the same, but exclude person "Benedikt Foobar"
    // Note that the "not" is a logical operator and thus needs its own
    // surrounding bracket. This explains nicely, that each bracket level
    // is evaluated independently from surrounding brackets.
    $filter = '(&(givenName=Benedikt)(telephoneNumber=1234567890)(!(sureName=Foobar)))';
    ]]></programlisting>
            </example>
        </refsection>
    </refsection>

    <refsection><info><title>The Net_LDAP2_Filter class</title></info>
        
        <para>
            As you will read below, there are some special characters inside the LDAP filter definition and thus must
            be escaped. These are mainly the special characters used directly by the filter syntax like braces and
            the logical operators. Despite those, there are some other cases which need special threatment.
            Nearly all of this cases are hidden through the <classname>Net_LDAP2_Filter</classname> class so you
            should only consider using string filters if you need to or you know what you are doing.
            If you need a filter string, you may also use <classname>Net_LDAP2_Filter</classname>s <function>toString</function>
            function after building the filter.
        </para>
        <para>
            The filter class has two different usage models: one for constructing basic filters and
            another to combine them logically. This has to do with the syntax of LDAP filters you may read below.
        </para>
        
        <refsection><info><title>Creating filters</title></info>
            
            <para>
                For creating basic filter components, you need to use the <function>create</function> factory method.
                There, you combine three items: an attribute to filter for, a matching rule for comparison and a value
                that is beeing compared with the servers entries.
                The given value is automatically escaped, so you need take care if you want to use the star placeholder.
                In this case, you need to pass <literal>FALSE</literal> as fourth parameter to <function>create</function>
                which causes <literal>value</literal> to be threaten as-is. This of course also means, that you need to
                escape the parts of the value that may contain restricted characters yourself using
                <classname>Net_LDAP2_Util::</classname><function>escape_filter_value</function>. To learn what characters
                are restricted, refer to <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.ietf.org/rfc/rfc2254.txt">RFC 2254</link> or the documentation of
                <classname>Net_LDAP2_Util::</classname><function>escape_filter_value</function>; otherwise its safe to always escape.
            </para>
            <para>
                The matching rules partly follow the basic filter matching rules described above, but are enhanced to
                make your life easier:
                <table><title>create()s matching rules</title>
                    
                    <tgroup cols="2">
                        <thead>
                            <row>
                                <entry>Rule</entry>
                                <entry>Description</entry>
                            </row>
                        </thead>
                        <tbody>
                            <row><entry>equals</entry><entry>One of <literal>attribute</literal>s values is exactly <literal>value</literal>. Please note that case sensitiviness depends on the matching rule defined in the attributes schema syntax.</entry></row>
                            <row><entry>begins</entry><entry>One of <literal>attribute</literal>s values must begin with <literal>value</literal></entry></row>
                            <row><entry>ends</entry><entry>One of <literal>attribute</literal>s values must end with <literal>value</literal></entry></row>
                            <row><entry>contains</entry><entry>One of <literal>attribute</literal>s values must contain <literal>value</literal></entry></row>
                            <row><entry>present | any</entry><entry>The <literal>attribute</literal> can contain any value but must be existent</entry></row>
                            <row><entry>greater</entry><entry>The <literal>attribute</literal>s value is greater than <literal>value</literal></entry></row>
                            <row><entry>less</entry><entry>The <literal>attribute</literal>s value is less than <literal>value</literal></entry></row>
                            <row><entry>greaterOrEqual</entry><entry>The <literal>attribute</literal>s value is greater or equal than <literal>value</literal></entry></row>
                            <row><entry>lessOrEqual</entry><entry>The <literal>attribute</literal>s value is less or equal than <literal>value</literal></entry></row>
                            <row><entry>approx</entry><entry>One of <literal>attribute</literal>s values sounds similar to <literal>value</literal>. The matching behavior depends on the server implementation.</entry></row>
                        </tbody>
                    </tgroup>
                </table>
            </para>
            <example><info><title>Creating LDAP filters</title></info>
        
        <programlisting role="php"><![CDATA[
// Filter entries whose first name is 'Benedikt':
$filter = Net_LDAP2_Filter::create('givenName', 'equals', 'Benedikt');

// Filter entries whose first name starts with 'Steph':
$filter = Net_LDAP2_Filter::create('givenName', 'begins', 'Steph');

// Filter entries containing 'Lone*'; matching the star character.
// The automatic escaping of $value will conveniently escape the star for us.
$filter = Net_LDAP2_Filter::create('givenName', 'contains', 'Lone*');

// Filter entries containing 'Foo[something]Bar'; not matching the star character.
// For this to work, we need to disable automatic escaping of $value by passing
// false as fourth parameter. This however implies, that we take care of
// proper escaping, which is showed in the example.
$escaped_values = Net_LDAP2_Util::escape_filter_value(array('Foo', 'Bar'));
$foo =& $escaped_values[0];
$bar =& $escaped_values[1];
$filter = Net_LDAP2_Filter::create('givenName', 'contains', "$foo*$bar", false);

// Filter entries whose first name sounds similar to "Stephane"
// This should also find "Stephen" and "Stefan" (depending on implementation)
$filter = '(givenName=~Stephane)';
]]></programlisting>
    </example>
        </refsection>

        <refsection><info><title>Combining filters</title></info>
            
            <para>
                Although the filters can be used stand alone, they can be combined to match sophisticated
                search requiremets. This is done by using the <function>combine</function> to combine
                several present <classname>Net_LDAP2_Filter</classname> objects using a logical operator.
                The execption is the <literal>not</literal> operator since it only allows one filter
                object to be negated.
                <table><title>combine()s operators</title>
                    
                    <tgroup cols="2">
                        <thead>
                            <row>
                                <entry>Rule</entry>
                                <entry>Description</entry>
                            </row>
                        </thead>
                        <tbody>
                            <row><entry>and</entry><entry>All filter components must evaluate to <literal>true</literal> for the combined filter to be <literal>true</literal></entry></row>
                            <row><entry>or</entry><entry>At least one filter component must evaluate to <literal>true</literal> for the combined filter to be <literal>true</literal></entry></row>
                            <row><entry>not</entry><entry>The result of the filter component is inversed (<literal>true</literal> becomes <literal>false</literal> and vice versa).
                                    Note that this operator only accepts one filter object.</entry></row>
                        </tbody>
                    </tgroup>
                </table>

                <example><info><title>Combining LDAP filters</title></info>
                
                    <programlisting role="php"><![CDATA[
// Create some test filters
$filter_benedikt = Net_LDAP2_Filter::create('givenName', 'equals', 'Benedikt');
$filter_steph    = Net_LDAP2_Filter::create('givenName', 'begins', 'Steph');
$filter_foobar   = Net_LDAP2_Filter::create('sureName', 'equals', 'Foobar');
$filter_height   = Net_LDAP2_Filter::create('personHeight', 'greater', '175');

// Negate 'foobar' filter.
// This filters every entry whose sure name is not 'Foobar'
$filter_not_foobar = Net_LDAP2_Filter::combine('not', $filter_foobar);

// Build a 'and' combination to be able to search for people whose
// first names start with 'Steph' and who are are taller than 175
// except those whose surname is 'Foobar'
$filter_stephs_tall = Net_LDAP2_Filter::combine('and',
    array($filter_steph, $filter_height, $filter_not_foobar));

// In any case, add every person whose first name is
// 'Benedikt' to the search result.
$filter_add_benedikt = Net_LDAP2_Filter::combine('or', array($filter_benedikt, $filter_stephs_tall));
]]></programlisting>
                </example>
            </para>
        </refsection>
        <refsection><info><title>Advanced features</title></info>
            
            <para>
                You may need some advanced functionality if you have to deal with string representation of filters.
                <table><title>Advanced methods</title>
                    
                    <tgroup cols="2">
                        <thead>
                            <row>
                                <entry>Method</entry>
                                <entry>Description</entry>
                            </row>
                        </thead>
                        <tbody>
                            <row><entry><function>parse</function></entry><entry>Takes an filter string and parses it into a <classname>Net_LDAP2_Filter</classname> object. It also verifies, that the filter syntax is correct.</entry></row>
                            <row><entry><function>printMe</function></entry><entry>In PERLs interface, this method is called "print" but due to language constraints, we cannot use that name. Prints the string representation of this filter object to standard output or to an optional filehandle passed as parameter.</entry></row>
                            <row><entry><function>toString</function></entry><entry>Returns the string representation of the filter object.</entry></row>
                        </tbody>
                    </tgroup>
                </table>
            </para>
        </refsection>

    </refsection>
</refentry>

http://cvs.php.net/viewvc.cgi/peardoc/en/package/networking/net-ldap2/introduction.xml?view=markup&rev=1.1
Index: peardoc/en/package/networking/net-ldap2/introduction.xml
+++ peardoc/en/package/networking/net-ldap2/introduction.xml
<?xml version="1.0" encoding="utf-8"?>
<refentry xmlns="http://docbook.org/ns/docbook" version="lillet" xml:id="package.networking.net-ldap2.introduction">
    <refnamediv>
        <refname>Introduction</refname>
        <refpurpose>What Net_LDAP2 is and general information</refpurpose>
    </refnamediv>

    <refsection><info><title>Welcome to Net_LDAP2!</title></info>
        
        
        <para>
            Net_LDAP2 is a clone of Perls Net::LDAP package. PEAR Net_LDAP2 for PHP does, besides
            some own features, provide most of Perl Net::LDAP methods.
            Net_LDAP2 allows you to query and manipulate the data stored in directory servers using PHP
            in an object-oriented way.
            A directory server is a database server providing a hierarchical database and is usually
            queried using the LDAP protocol.
        </para>
        <para>
            Net_LDAP2 is intendet as replacement of Net_LDAP.
        </para>
    </refsection>
    <refsection><info><title>Classes of the Net_LDAP2 package</title></info>
        
        <para>
            The following table gives you a short overview which classes are available
            in Net_LDAP2 and what they can be used for. Their relations will be explained too.
            <table><title>Classes of Net_LDAP2</title>
                
                <tgroup cols="2">
                    <thead>
                        <row>
                            <entry>Class name</entry>
                            <entry>Description</entry>
                        </row>
                    </thead>
                    <tbody>
                        <row>
                            <entry><classname>Net_LDAP2</classname></entry>
                            <entry>
                                This is the main class. It enables you to connect and bind to a LDAP-server
                                and to run ldap-querys like searching and manipulating entries.
                                Most common, you will run a search using a LDAP-Filter and will get a
                                <classname>Net_LDAP2_Search</classname>-object.
                                You may also fetch an entry directly, which gives you a <classname>Net_LDAP2_Entry</classname>-object.
                            </entry>
                        </row>
                        <row>
                            <entry><classname>Net_LDAP2_Search</classname></entry>
                            <entry>
                                Objects of this class are returned from search querys. You can use this
                                object to retrieve informations about a search result, like
                                how much entries you have found for the provided filter.
                                You can retrieve the found entries as <classname>Net_LDAP2_Entry</classname>-objects
                                in various forms: sorted, consecutively starting from the end or beginning
                                or unsorted at once.
                            </entry>
                        </row>
                        <row>
                            <entry><classname>Net_LDAP2_Entry</classname></entry>
                            <entry>
                                Objects of this kind are either produced by casting fresh entries manually, by retrieving
                                the result of a LDAP-search or by fetching an entry directly.
                                It gives you the possibility to read and/or manipulate the attributes of an entry which describes
                                the characteristic of the specific object.
                            </entry>
                        </row>
                        <row>
                            <entry><classname>Net_LDAP2_Util</classname></entry>
                            <entry>
                                The utility class contains only static methods, so you should not need to make an instance of it.
                                It features some helpful methods, some of them are used internally by Net_LDAP2 but may
                                be used externally from you as well.
                                The most methods deal with escaping issues, since LDAP has some metacharacters with
                                special meaning so that they usually need to be properly escaped.
                            </entry>
                        </row>
                        <row>
                            <entry><classname>Net_LDAP2_Filter</classname></entry>
                            <entry>
                                You are free to give LDAP-Filters on your own to the <classname>Net_LDAP2</classname>-&gt;search() method,
                                however this has some drawbacks (including escaping issues).
                                For this reason, you can use the <classname>Net_LDAP2_Filter</classname> class to easily
                                build and combine your filters.
                                LDAP filters are extensively explained at the chapter <link linkend="package.networking.net-ldap2.filter">LDAP filters</link>.
                            </entry>
                        </row>
                        <row>
                            <entry><classname>Net_LDAP2_Error</classname></entry>
                            <entry>
                                This is a error class. Most methods of Net_LDAP2 will return a object of this class
                                if something went wrong. You can use this object to identify errors and to get
                                detailed knowledge on what went wrong. See <link linkend="package.networking.net-ldap2.errorhandling">Errorhandling</link>
                                for more information.
                            </entry>
                        </row>
                        <row>
                            <entry><classname>Net_LDAP2_LDIF</classname></entry>
                            <entry>
                                LDIF files are human readable, plain text files containing directory data and/or change commands,
                                much like an SQL file. Unlike SQL files, it is data centric, not action centric.
                                <classname>Net_LDAP2_LDIF</classname> enables you to convert between <classname>Net_LDAP2_Entry</classname>-objects
                                and LDIF files. Please note, that Net_LDAP2_LDIF has a little different error handling explained later.
                            </entry>
                        </row>
                    </tbody>
                </tgroup>
            </table>
        </para>
    </refsection>
</refentry>

http://cvs.php.net/viewvc.cgi/peardoc/en/package/networking/net-ldap2/ldif.xml?view=markup&rev=1.1
Index: peardoc/en/package/networking/net-ldap2/ldif.xml
+++ peardoc/en/package/networking/net-ldap2/ldif.xml
<?xml version="1.0" encoding="utf-8"?>
<refentry xmlns="http://docbook.org/ns/docbook" version="lillet" xml:id="package.networking.net-ldap2.ldif">
    <refnamediv>
        <refname>LDIF files</refname>
        <refpurpose>Converting between Net_LDAP2_Entries and LDIF files</refpurpose>
    </refnamediv>
    <refsection><info><title>Avaible since</title></info>
        
        <para>LDIF support was added to Net_LDAP2 in release 1.1.0a1.</para>
    </refsection>

    <refsection><info><title>What are LDIF files?</title></info>
        

        <para>
            LDIF files are in detail described at <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.ietf.org/rfc/rfc2849.txt">RFC 2849</link>.
            Shortly, they contain directory data in an plain text, human readable kind, much like
            a SQL file does. However, unlike SQL files LDIF files are mostly data based, not action based.
            There are two different LDIF file contents, which can be mixed freely - content and change files.
            The first and most often used one is the LDIF content file:
        </para>
        <example><info><title>Example LDIF content file</title></info>
        
        <programlisting role="text"><![CDATA[
#
# This is a content LDIF file.
# It contains one single entry featuring several
# attributes and one comment (this one).
# attr1, attr4 and cn are single valued, the others are
# multivalued. objectclass is a special case, LDAP servers
# will interpret this operational attribute to define the
# classes the object will belong to and thus, which attributes
# it may contain. the OCL-attribute is usually multivalued.
#
version: 1
dn: cn=test1,ou=example,dc=cno
objectclass: someobjectclass
attr1: 12345
attr2: 1234
attr2: baz
attr3: foo
attr3: bar
attr4: brrrzztt
cn: test1
]]></programlisting>
        </example>



        <para>
            LDIF files could describe not only the data an entry contains, but also various
            changes to the entry itself. If such an LDIF file would then be given to a
            LDAP server, he would interpret those changes instead just importing the data.
            Note in the example below, that even though LDIF content and LDIF change files could be
            mixed freely, this is not true for individual entries: a specific entry may be either
            describing content or changes, but not both.
        </para>
    <example><info><title>Example LDIF change file</title></info>
        
        <programlisting role="text"><![CDATA[
#
# This is a content+change LDIF file.
# It does contain the (shortened) entry from the example above to show
# that LDIF files can contain multiple entry modes.
# The second entry is a change entry. In this case, some
# operations will be done on the entries attributes.
#
version: 1
dn: cn=test1,ou=example,dc=cno
objectclass: someobjectclass
attr1: 12345
cn: test1

# Delete attr1, replace values of attr2 and add new attribute attr42
# The attribute "changetype" is special: it says, what to do with
# this entries dataset. It could also be "delete" or "add" to delete
# a whole entry or to add a completely fresh one. "modrdn" will
# move the entry to a new location once the LDIF file is imported.
dn: cn=test2,ou=example,dc=cno
changetype: modify
delete: attr1
-
replace: attr2
attr2: 123456_newtest
-
add: attr42
attr42: the answer
]]></programlisting>
        </example>
    </refsection>

    <refsection><info><title>Error handling when using Net_LDAP2_LDIF</title></info>
        

        <para>
            Before we can start using Net_LDAP2_LDIF we must say some short words about how
            error handling works. Net_LDAP2_LDIF was designed to have mostly the same API as
            the original PERL Net::LDAP::LDIF has. Because of this, the methods of Net_LDAP2_LDIF
            do not return a Net_LDAP2_Error object. You must use the <function>error</function> method
            that will return a Net_LDAP2_Error object in case of failure or true in case everything was ok.
            In LDIF reading mode, you can additionally use <function>error_lines</function> to get knowledge
            about where in the input file the error occured.
        </para>
    </refsection>

    <refsection><info><title>Construction and options</title></info>
        

        <para>
            Regardless if you want to read or write a LDIF file, you always have to use the constructor
            of Net_LDAP2_LDIF to initialize your access to the LDIF file.
            You need to pass at least one parameter to <function>Net_LDAP2_LDIF</function>:
            the path of the file that should be read or written. You may pass the open mode as second parameter.
            The possible file open modes are "r" (read), "w" (write, clears the file first) and "a" (append to the end).
            In case you omit the open mode, read mode is assumed.
            The third optional parameter is an associative array containing one or several of the following
            options:
            <table><title>Possible configuration options</title>
                
                <tgroup cols="3">
                    <thead>
                    <row>
                    <entry>Name</entry>
                    <entry>Description</entry>
                    <entry>Default</entry>
                    </row>
                    </thead>
                    <tbody>
                    <row>
                    <entry><literal>encode</literal></entry>
                    <entry>Some DN values in LDIF cannot be written verbatim and have to be encoded in some way.
                        Possible values are: "none", "canonical" and "base64" (RFC default)</entry>
                    <entry><literal>base64</literal></entry>
                    </row>
                    <row>
                    <entry><literal>onerror</literal></entry>
                    <entry>What should be done on errors? "undef" will let error handling in your hands, in this
                        case you use <function>error</function> and <function>error_lines</function> to process errors manually.
                        "die" aborts the script printing the error - this is sometimes useful for CLI scripts.
                        "warn" just prints out the error but continues like "undef" would.</entry>
                    <entry><literal>undef</literal></entry>
                    </row>
                    <row>
                    <entry><literal>change</literal></entry>
                    <entry>Turning this to "1" (true) will tell Net_LDAP2_LDIF to write change sets instead of content files.</entry>
                    <entry><literal>false</literal></entry>
                    </row>
                    <row>
                    <entry><literal>lowercase</literal></entry>
                    <entry>Set this to true to convert attribute names to lowercase when writing.</entry>
                    <entry><literal>0</literal></entry>
                    </row>
                    <row>
                    <entry><literal>sort</literal></entry>
                    <entry>If true, sort attribute names when writing entries according to the rule:
                        objectclass first then all other attributes alphabetically sorted by attribute name</entry>
                    <entry><literal>0</literal></entry>
                    </row>
                    <row>
                    <entry><literal>version</literal></entry>
                    <entry>Set the LDIF version to write to the resulting LDIF file.
                        According to RFC 2849 currently the only legal value for this option is 1 currently.</entry>
                    <entry><literal>1</literal></entry>
                    </row>
                    <row>
                    <entry><literal>wrap</literal></entry>
                    <entry> Number of columns where output line wrapping shall occur.
                        Setting it to 40 or lower inhibits wrapping. Useful for better human readability of
                        the resulting file.</entry>
                    <entry><literal>78</literal></entry>
                    </row>
                    <row>
                    <entry><literal>raw</literal></entry>
                    <entry>Using this option, you are able to tell Net_LDAP2_LDIF which attributes to treat
                        as binary data. If you pass in entries having a valid LDAP connection
                        (eg from some Net_LDAP2->search() operation) this additionally will be detected by
                        automatic checks against the schema.</entry>
                    <entry>empty</entry>
                    </row>
                    </tbody>
                </tgroup>
            </table>
            For advanced users: instead of passing a file path, you also may pass an already initialized file handle.
            In this case, the mode parameter will be ignored. You may use this, if you want to mix LDIF content and
            LDIF change mode by using two Net_LDAP2_LDIF instances to write to the same filehandle, but it could
            be very useful in other cases too. To initialize the second instance of Net_LDAP2_LDIF, you can use
            <function>handle</function> to get the filehandle from the first instance.
       </para>
    </refsection>

    <refsection><info><title>Reading a LDIF file into Net_LDAP2_Entry-objects</title></info>
        

        <para>
        One of the two modes how Net_LDAP2_LDIF can be used is to read a LDIF file and parse its
        contents into an array of Net_LDAP2_Entry objects. This is done using the
        <function>read_entry</function>-method which will return the next entry. If you want to fetch all
        entries, you use the <function>eof</function> to detect the end of the input file:
        </para>
        <example><info><title>Parsing a LDIF file into Net_LDAP2_Entry objects</title></info>
        
        <programlisting role="php"><![CDATA[
// open some LDIF file for reading
$ldif = new Net_LDAP2_LDIF('somefile.ldif', 'r');
if ($ldif->error()) {
    $error_o = $ldif->error(); // get Net_LDAP2_Error object on error
            die('ERROR: '.$error_o->getMessage());
}

// parse the entries of the LDIF file into objects
 do {
    $entry = $ldif->read_entry();
    if ($ldif->error()) {
        // in case of error, print error.
        // here we use the shorthand parameter, so error()
        // returns a string instead of a Net_LDAP2_Object
        die('ERROR AT INPUT LINE '.$ldif->error_lines().': '.$ldif->error(true));
    } else {
        // No error: do something with the entry
        // Here we just print the entries DN
        echo 'sucessfully parsed '.$entry->dn();
    }
} while (!$ldif->eof());

// We should call done() once we are finished
$ldif->done();

]]></programlisting>
        </example>
    </refsection>

    <refsection><info><title>Writing Net_LDAP2_Entry objects to a LDIF content file</title></info>
        

        <para>
          Writing an LDIF file is very easy too. Just pass the entries you want to have written
          to the <function>write_entry</function>-method. Beware, that if you have opened the file in "w" write mode
          this will clear any previous data of that file. Use "a" (append) if you just want add data.
        </para>
        <example><info><title>Writing entries</title></info>
        
        <programlisting role="php"><![CDATA[
        // Assume we have some valid Net_LDAP2_Entry objects inside $entries
        // $entries = array( ... );

        // open some file for writing
        $ldif = new Net_LDAP2_LDIF('somewritefile.ldif', 'w');
        if ($ldif->error()) die('ERROR: '.$error_o->getMessage());

        // write the data and check for error
        // you could pass one single Net_LDAP2_Entry object or
        // several objects inside an array
        $ldif->write_entry($entries);
        if ($ldif->error()) die('WRITE ERROR: '.$error_o->getMessage());

]]></programlisting>
        </example>
    </refsection>

        <refsection><info><title>Writing Net_LDAP2_Entry objects to a LDIF change file</title></info>
        

        <para>
          The process of writing changes is exactly the same like writing entry contents.
          However there are two differences: Firstly you need to pass the "changes" option
          and secondly, the entries you want to write need changes. Entries not containing
          changes will silently be ignored since there is nothing to write.
        </para>
        <example><info><title>Writing entry changes</title></info>
        
        <programlisting role="php"><![CDATA[
        // cast some test data and three entries
        $testattrs = array(
                'attr1' => '1234',
                'attr2' => 'foo',
                'attr3' => array('bar', 'baz')
            );
        $entries = array(
                Net_LDAP2_Entry::createFresh('cn=foo,dc=example,dc=cno',
                    array_merge(array('cn' => 'foo'), $testattrs)),
                Net_LDAP2_Entry::createFresh('cn=bar,dc=example,dc=cno',
                    array_merge(array('cn' => 'bar'), $testattrs)),
                Net_LDAP2_Entry::createFresh('cn=baz,dc=example,dc=cno',
                    array_merge(array('cn' => 'baz'), $testattrs))
            );

        // make some changes to the first and the last entry
        $entries[0]->add(array('someattr' => 'added'));
        $entries[0]->replace(array('attr1' => 'replaced'));
        $entries[2]->delete(array('attr2'));
        $entries[2]->delete(array('attr3' => 'bar'));

        // open some file for writing, but in change mode
        $ldif = new Net_LDAP2_LDIF('somewritefile.ldif', 'w', array('change' => true));
        if ($ldif->error()) die('ERROR: '.$error_o->getMessage());

        // write the data and check for error
        // you could pass one single Net_LDAP2_Entry object or
        // several objects inside an array
        $ldif->write_entry($entries);
        if ($ldif->error()) die('WRITE ERROR: '.$error_o->getMessage());

        // Now, only two entries are contained in the LDIF file,
        // cn=foo,dc=example,dc=cno and cn=baz,dc=example,dc=cno.
        // cn=bar,dc=example,dc=cno had no changes and was skipped.
]]></programlisting>
        </example>
        <example><info><title>Resulting LDIF change file</title></info>
        
        <programlisting role="text"><![CDATA[
version: 1
dn: cn=foo,dc=example,dc=cno
changetype: modify
add: someattr
someattr: added
-
replace: attr1
attr1: replaced
-

dn: cn=baz,dc=example,dc=cno
changetype: modify
delete: attr2
-
delete: attr3
attr3: bar
-
]]></programlisting>
        </example>
        </refsection>

        <refsection><info><title>Fetching LDIF data</title></info>
        

        <para>
          Sometimes you are interested in the lines inside the LDIF file. For those cases you can use the
          <function>current_lines</function> and <function>next_lines</function> methods.
          They work in the current context, which may be confusing:
          <function>current_lines</function> will always return the lines that have built up the current
          <classname>Net_LDAP2_Entry</classname> object when called <function>current_entry</function> after <function>read_entry</function>
          has been called.
          <function>next_lines</function> will always return the lines, that will build up the next entry from the
          current point of view, meaning "relative to the entry that was just been read". However, you can override this by
          activating the "force" parameter of <function>next_lines</function> which allows you to loop over all entries.
          <function>current_entry</function> behaves exactly like <function>current_lines</function>.
        </para>
        <para>
            If you think, that the lines you have read would be better in form of an <classname>Net_LDAP2_Entry</classname> object,
            use the <function>parseLines</function> method to parse those lines into an entry. This is a
            good way if you need just a few specific entries of a large LDIF file.
        </para>

        <example><info><title>Reading LDIF lines</title></info>
        
        <programlisting role="php"><![CDATA[
// open some LDIF file for reading
// (error checking code is ommitted in this example for
//  better readability - in production, test for errors!)
$ldif = new Net_LDAP2_LDIF('somefile.ldif', 'r');

// since nothing has been read until now, this will
// return an empty array
$empty_array = $ldif->current_lines();

// so let's read the first entries data
$first_entry_lines = $ldif->next_lines();

// if we call it again, we will not read ahead to the
// second entry - we again read the first one!
$first_entry_lines_again = $ldif->next_lines();

// If we call current_lines() now, we haven't read ahead
// like we learned from the last statement.
$empty_array_again = $ldif->current_lines();

// If we want to shift, we must use
// the read_entry() method, which will read ahead.
$first_entry = $ldif->read_entry();

// Now, current_lines() returns the lines of the
// first entry and next_lines() the lines of the second:
$first_entry_lines  = $ldif->current_lines();
$second_entry_lines = $ldif->next_lines();

// There is another way to shift the lines which is faster if
// you are just interested in the LDIFs content - you
// need to pass the "force" parameter to next_lines():
$third_entry_lines  = $ldif->next_lines(true);
$fourth_entry_lines = $ldif->next_lines(true);
$fifth_entry_lines  = $ldif->next_lines(true);

// If you want to convert the lines to an Net_LDAP2_Entry,
// you may do so anytime by using parseLines()
$fourth_entry = $ldif->parseLines($fourth_entry_lines);

// Since we shifted manually only the lines,
// current_lines() will return the lines that built up the
// last (e.g. the first entry) Net_LDAP2_Entry object:
$first_entry_lines  = $ldif->current_lines();

// If we decide to read the next entry, we can do that:
$sixth_entry = $ldif->read_entry();

// current_lines() is shifted now:
$sixth_entry_lines = $ldif->current_lines();

]]></programlisting>
        </example>
    </refsection>
</refentry>

http://cvs.php.net/viewvc.cgi/peardoc/en/package/networking/net-ldap2/search.xml?view=markup&rev=1.1
Index: peardoc/en/package/networking/net-ldap2/search.xml
+++ peardoc/en/package/networking/net-ldap2/search.xml
<?xml version="1.0" encoding="utf-8"?>
<refentry xmlns="http://docbook.org/ns/docbook" version="lillet" xml:id="package.networking.net-ldap2.search">
    <refnamediv>
        <refname>Search</refname>
        <refpurpose>Searching entries</refpurpose>
    </refnamediv>

    <refsection><info><title>A short note on DNs</title></info>
        
        <para>
            It may be possible that restricted characters (",", "+", """, "\", "<![CDATA[<]]>", "&gt;", ";", "#", "=", space or a hexpair) are used in attributes or values inside the DN.
            You should have a look to the APIdoc of <classname>Net_LDAP2_Util::</classname><function>escape_dn_value</function>,
            <classname>Net_LDAP2_Util::</classname><function>unescape_dn_value</function>, <classname>Net_LDAP2_Util::</classname><function>ldap_explode_dn</function> and <classname>Net_LDAP2_Util::</classname><function>canonical_dn</function>.
            These functions can be used to safely handle DNs.
        </para>
    </refsection>

    <refsection><info><title>Searching some entries</title></info>
        
        <para>
        After connecting to the server, you can use <classname>Net_LDAP2</classname>'s
        <function>search</function> method to search the directory. The method takes
        three parameters:
        <itemizedlist>
        <listitem>
            <para>
            <literal>$base</literal> is the base search DN. If kept
            <literal>null</literal>, the default base DN configured when connecting
            is used.
            </para>
        </listitem>
        
        <listitem>
            <para>
            <literal>$filter</literal> is the query filter that determines which
            results are returned. It is either a string (experts use only) or better a <classname>Net_LDAP2_Filter</classname>-object.
            <classname>Net_LDAP2_Filter</classname> automatically deals with LDAP-Filter escaping issues.
            LDAP filters are extensively explained at the chapter <link linkend="package.networking.net-ldap2.filter">LDAP filters</link>.
            </para>
        </listitem>
        
        <listitem>
            <para>
            <literal>$params</literal> is an array of configuration options for
            the current query.
            <table><title>Possible configuration parameters</title>
            
            <tgroup cols="3">
            <thead>
                <row>
                <entry>Name</entry>
                <entry>Description</entry>
                <entry>Default</entry>
                </row>
            </thead>
            <tbody>
                <row>
                <entry><literal>scope</literal></entry>
                <entry>
                The scope used for searching:
                <itemizedlist>
                <listitem>
                    <para>
                    <literal>base</literal> - Just one entry
                    </para>
                </listitem>
        
                <listitem>
                    <para>
                    <literal>sub</literal> - The whole tree
                    </para>
                </listitem>
        
                <listitem>
                    <para>
                    <literal>one</literal> - Immediately below
                    <literal>$base</literal>
                    </para>
                </listitem>
        
                </itemizedlist>
                </entry>
                <entry><literal>sub</literal></entry>
                </row>
        
                <row>
                <entry><literal>sizelimit</literal></entry>
                <entry>Number of entries returned at maximum</entry>
                <entry><literal>0</literal> (no limit)</entry>
                </row>
        
                <row>
                <entry><literal>timelimit</literal></entry>
                <entry>Seconds to spent for searching</entry>
                <entry><literal>0</literal> (no limit)</entry>
                </row>
        
                <row>
                <entry><literal>attrsonly</literal></entry>
                <entry>If <literal>true</literal>, only attribute names are returned</entry>
                <entry><literal>false</literal></entry>
                </row>
        
                <row>
                <entry><literal>attributes</literal></entry>
                <entry>
                Array of attribute names, which the entry should contain.
                It is good practice to limit this to just the ones you need.
                </entry>
                <entry><literal>array()</literal> (all attributes)</entry>
                </row>
        
            </tbody>
            </tgroup>
            </table>
            </para>
        </listitem>
        
        </itemizedlist>
        
        The <function>search</function> method will return either a <classname>Net_LDAP2_Search</classname> object or a <classname>Net_LDAP2_Error</classname>.
        You can use the <classname>Net_LDAP2_Search</classname>-object to trigger further actions
        like counting how many entries where found or to retrieve the found entries.
        </para>
        
        <example><info><title>Making a search query</title></info>
        
        <programlisting role="php"><![CDATA[
// Building a very basic filter
// we want to find all Entries whose surnames start with "Joe":
$filter = Net_LDAP2_Filter::create('sn', 'begins',  'Joe');

// We define a custom searchbase here. If you pass NULL, the basedn provided
// in the Net_LDAP2 configuration will be used. This is often not what you want.
$searchbase = 'ou=addressbook,dc=example,dc=org';

// Some options:
// We search all subtrees beneath 'ou=addressbook,dc=example,dc=org'
// and we select the attribute 'sn'. It is a good practice to limit the
// requested attributes to only those you actually want to use later.
// However, note that it is faster to select unneeded attributes than
// refetching an entry later to just get those attributes.
$options = array(
    'scope' => 'sub',
    'attributes' => array('sn')
);

// Perform the search!
$search = $ldap->search($searchbase, $filter, $options);

// Test for search errors:
if (PEAR::isError($search)) {
    die($search->getMessage() . "\n");
}

// Say how many entries we have found:
echo "Found " . $search->count() . " entries!";

]]></programlisting>
        </example>
    </refsection>
</refentry>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.