17 juin 2005

Tutoriel pour Net_LDAP, une classe PEAR permettant l'accès à un annuaire LDAP

1. Installation d'un serveur LDAP

Sur mon système Linux Mandrake 10, les packages à installer sont openldap-clients, openldap-servers et php-ldap. Ce qui se traduit en ligne de commande par :


% sudo urpmi openldap-clients openldap-servers php-ldap
(...)

2. Configurer le serveur

Le fichier /etc/openldap/slapd.conf doit être modifier. Voici un exemple de fichier minimum.


include         /etc/openldap/schema/core.schema
include         /etc/openldap/schema/cosine.schema
include         /etc/openldap/schema/inetorgperson.schema
include         /etc/openldap/schema/misc.schema
include         /etc/openldap/schema/openldap.schema 

pidfile         /var/openldap/run/slapd.pid
argsfile        /var/openldap/run/slapd.args

database        bdb
suffix          "dc=example,dc=com"
rootdn          "cn=admin,dc=example,dc=com"
rootpw          secret

directory       /var/openldap/openldap-data
index           objectClass     eq

3. Démarrer le serveur

Le script de lancement se trouve dans le répertoire /etc/init.d


% /etc/init.d start
(...)
% ldapsearch -x # ou ldapsearch si vous avez activé SASL
(...)

4. Charger l'annuaire

Voici un fichier ldif à télécharger et à charger à l'aide de la commande slapadd.


% slapadd -l exemple-ldif.txt
(...)
% slapcat
(...)

5. Installer le package PEAR Net_LDAP

Bien que signaler en version beta, ce package est presque stable au moment ou j'écris ces lignes. Certaines fonctionnalités avancées ne sont pas disponibles, et les quelques soucis que j'ai rencontrés risque d'être corrigés dans les jours qui viennent. Pour l'installer :


% pear install Net_Ldap

6. Se connecter

La méthode statique «connect» permet d'établir une connexion. L'ensemble des paramètres doivent être dans un tableau.


require_once('Net/Ldap.php');

$ldap_params = array(
    'base'     => 'dc=example,dc=com',
    'dn'       => 'cn=admin,dc=example,dc=com',
    'password' => 'secret',
    'host'     => 'localhost'
);

$ldap = Net_Ldap::connect( $ldap_params );
if (PEAR::isError( $ldap )) die($ldap->getMessage());

// ...

7. Ajouter une entrée


$at = array (
    'objectclass'  => array('top','person','inetOrgPerson'),
    'cn'           => 'Jean Claude Dusse',
    'sn'           => 'Dusse',
    'uid'          => 'jcd',
    'givenName'    => 'Jean Claude',
    'userPassword' => '{plain}mdp',
    'description'  => 'blablabla'
);

$newdn = 'cn=' . $at['cn'] . ',ou=user,' . $ldap_params['base'];

$ldap = Net_Ldap::connect( $ldap_params );
if (PEAR::isError( $ldap )) die($ldap->getMessage());

$newentry = new Net_LDAP_Entry();
$newentry->add( $at );
$newentry->dn( $newdn );

$ret = @$ldap->add( $newentry );
if (PEAR::isError( $ret )) die($ret->getMessage());

$ldap->done();

8. Rechercher

Attention, il faut préciser avant la recherche quels attributs on souhaitera récupérer. Pour cela, on donne la liste des attributs dans un tableau.


$ldap = Net_Ldap::connect( $ldap_params );
if (PEAR::isError( $ldap )) die($ldap->getMessage());

$search_params = array(
'attributes'=>array('mail', 'uid', 'cn')
);

// Dans une seul branche
// $rsch = $ldap->search('ou=user,'.$ldpa_params['base'],'(mail=touv@ouvaton.org)',$search_params);

// Dans tout l'annuaire
$srch = $ldap->search( null, '(uid=jcd)', $search_params );

$nb = $srch->count();
echo "$nb entrée(s) trouvée(s)<br>\n";

$entry = $srch->shiftEntry();
$cn  = $entry->get_value( 'cn',  'single' );
$uid = $entry->get_value( 'uid', 'single' );

var_dump( $cn );
var_dump( $uid );

$srch->done();
$ldap->done();

9. Modification

Deux types de modifications :

  • mise à jour d'un attributs
  • ajout ou suppression d'attributs

Pour mettre à jour un attribut, on effectue une recherche, on récupére l'attribut concerné et on utilise la méthode «replace»


$search_params = array(
'attributes'=>array('givenName', 'uid', 'cn')
);

// Dans tout l'annuaire
$srch = $ldap->search( null, '(uid=jcd)', $search_params );

$entry = $srch->shiftEntry();
$entry->replace( array(
    'givenName'=>array('Jean-Claude')) 
);
$ret = $entry->update();
if (Net_Ldap::isError( $ret )) die($ret->getMessage());

$srch->done();
$ldap->done();

Pour ajouter, supprimer des attributs on utilsie la méthode «modify».


$dn = 'cn=Jean Claude Dusse,ou=user,dc=example,dc=com';

// Ajout
$ret = $ldap->modify( $dn, array('add' => array('street' => 'Place Stan' )));
if (Net_Ldap::isError( $ret )) die($ret->getMessage());

$ret = $ldap->modify( $dn, array('add' => array('mail' => 'truc@example.com' )));
if (Net_Ldap::isError( $ret )) die($ret->getMessage());

// Ajout ou Modification
$ret = @$ldap->modify( $dn, array('replace' => array('street' => 'Place Stanislas' )));
if (Net_Ldap::isError( $ret )) die($ret->getMessage());

$ret = @$ldap->modify( $dn, array( 'replace' => array('replace' => array('mail' => 'jcd@example.com')) ));
if (Net_Ldap::isError($ret)) die($ret->getMessage());

// Supression
$ret = $ldap->modify( $dn, array( 'delete' => array('street' => array()) ));
if (Net_Ldap::isError( $ret )) die($ret->getMessage());

$ret = $ldap->modify( $dn, array( 'delete' => array('mail' => array()) ));
if (Net_Ldap::isError( $ret )) die($ret->getMessage());

10. Suppression

Avant de supprimer, une entrée il faut vérifier qu'elle n'existe pas, sinon gare aux messages d'erreurs...


$dn = 'cn=Jean BOURG,ou=agenda,dc=example,dc=com';

$ret = $ldap->delete($dn, array('recursive'=>false));
if (Net_Ldap::isError($ret)) die($ret->getMessage());

$ldap->done();

11. Autres Fonctionnalités

Il existe d'autres méthodes, notamment pour régler la connexion au serveur. Vous trouverez leurs descriptions dans la phpdoc du package.

14 juin 2005

xmllint, un couteau suisse pour les fichiers XML

L'utilitaire xmllint fourni avec la librairie multi-platorme libxml2 permet de manipuler, valider, formater des fichiers XML. Visite guidée :

Indenter un fichier


% xmllint data.xml --format

Valider un fichier XML contenant une DTD.


% xmllint data.xml --valid

Valider un fichier XML

avec une DTD externe :


% xmllint data.xml --dtdvalid data.dtd  --noout

avec un schéma XML


% xmllint data.xml --schema schema.xsd  --noout 

avec du RelaxNG


% xmllint data.xml --relaxng RNGnotice.rng --noout 

L'option --noout permet d'afficher uniquement les informations de validation.

Naviguer dans un fichier XML

Vous allez pouvoir à l'aide d'expression xpath naviguer dynamiquement dans votre fichier xml. Démonstration :

Toutes les options :


thouveni@localhost% xmllint --shell stow.xml 
/ > help
        base         display XML base of the node
        setbase URI  change the XML base of the node
        bye          leave shell
        cat [node]   display node or current node
        cd [path]    change directory to path or to root
        dir [path]   dumps informations about the node (namespace, attributes, content)
        du [path]    show the structure of the subtree under path or the current node
        exit         leave shell
        help         display this help
        free         display memory usage
        load [name]  load a new document with name
        ls [path]    list contents of path or the current directory
        xpath expr   evaluate the XPath expression in that context and print the result
        pwd          display current working directory
        quit         leave shell
        save [name]  save this document to name or the original name
        write [name] write the current node to the filename
        validate     check the document for errors
        relaxng rng  validate the document agaisnt the Relax-NG schemas
        grep string  search for a string in the subtree
/ > 

Naviguer avec xpath


thouveni@localhost% xmllint --shell stow.xml
/ > cd /slides/foil[2]/title
title > ls
t--       16 Principe de base
title > cd ../..
slides > ls
t--        5      
---        9 slidesinfo
t--        6       
---       13 foil
t--        5      
---       13 foil
t--        5      
---       13 foil
t--        5      
---       13 foil
t--        5      
---        7 foil
t--        1  
slides > dir
ELEMENT slides
slides > cd ..
/ > cat //foil[2]/title
 -------
<title>Principe de base</title>
/ >