517 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
		
		
			
		
	
	
			517 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								/* vim: set expandtab tabstop=4 shiftwidth=4: */
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								* File containing the Net_LDAP2_Schema interface class.
							 | 
						||
| 
								 | 
							
								*
							 | 
						||
| 
								 | 
							
								* PHP version 5
							 | 
						||
| 
								 | 
							
								*
							 | 
						||
| 
								 | 
							
								* @category  Net
							 | 
						||
| 
								 | 
							
								* @package   Net_LDAP2
							 | 
						||
| 
								 | 
							
								* @author    Jan Wagner <wagner@netsols.de>
							 | 
						||
| 
								 | 
							
								* @author    Benedikt Hallinger <beni@php.net>
							 | 
						||
| 
								 | 
							
								* @copyright 2009 Jan Wagner, Benedikt Hallinger
							 | 
						||
| 
								 | 
							
								* @license   http://www.gnu.org/licenses/lgpl-3.0.txt LGPLv3
							 | 
						||
| 
								 | 
							
								* @version   SVN: $Id: Schema.php 286718 2009-08-03 07:30:49Z beni $
							 | 
						||
| 
								 | 
							
								* @link      http://pear.php.net/package/Net_LDAP2/
							 | 
						||
| 
								 | 
							
								* @todo see the comment at the end of the file
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								* Includes
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								require_once 'PEAR.php';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								* Syntax definitions
							 | 
						||
| 
								 | 
							
								*
							 | 
						||
| 
								 | 
							
								* Please don't forget to add binary attributes to isBinary() below
							 | 
						||
| 
								 | 
							
								* to support proper value fetching from Net_LDAP2_Entry
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								define('NET_LDAP2_SYNTAX_BOOLEAN',            '1.3.6.1.4.1.1466.115.121.1.7');
							 | 
						||
| 
								 | 
							
								define('NET_LDAP2_SYNTAX_DIRECTORY_STRING',   '1.3.6.1.4.1.1466.115.121.1.15');
							 | 
						||
| 
								 | 
							
								define('NET_LDAP2_SYNTAX_DISTINGUISHED_NAME', '1.3.6.1.4.1.1466.115.121.1.12');
							 | 
						||
| 
								 | 
							
								define('NET_LDAP2_SYNTAX_INTEGER',            '1.3.6.1.4.1.1466.115.121.1.27');
							 | 
						||
| 
								 | 
							
								define('NET_LDAP2_SYNTAX_JPEG',               '1.3.6.1.4.1.1466.115.121.1.28');
							 | 
						||
| 
								 | 
							
								define('NET_LDAP2_SYNTAX_NUMERIC_STRING',     '1.3.6.1.4.1.1466.115.121.1.36');
							 | 
						||
| 
								 | 
							
								define('NET_LDAP2_SYNTAX_OID',                '1.3.6.1.4.1.1466.115.121.1.38');
							 | 
						||
| 
								 | 
							
								define('NET_LDAP2_SYNTAX_OCTET_STRING',       '1.3.6.1.4.1.1466.115.121.1.40');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								* Load an LDAP Schema and provide information
							 | 
						||
| 
								 | 
							
								*
							 | 
						||
| 
								 | 
							
								* This class takes a Subschema entry, parses this information
							 | 
						||
| 
								 | 
							
								* and makes it available in an array. Most of the code has been
							 | 
						||
| 
								 | 
							
								* inspired by perl-ldap( http://perl-ldap.sourceforge.net).
							 | 
						||
| 
								 | 
							
								* You will find portions of their implementation in here.
							 | 
						||
| 
								 | 
							
								*
							 | 
						||
| 
								 | 
							
								* @category Net
							 | 
						||
| 
								 | 
							
								* @package  Net_LDAP2
							 | 
						||
| 
								 | 
							
								* @author   Jan Wagner <wagner@netsols.de>
							 | 
						||
| 
								 | 
							
								* @author   Benedikt Hallinger <beni@php.net>
							 | 
						||
| 
								 | 
							
								* @license  http://www.gnu.org/copyleft/lesser.html LGPL
							 | 
						||
| 
								 | 
							
								* @link     http://pear.php.net/package/Net_LDAP22/
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								class Net_LDAP2_Schema extends PEAR
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								    * Map of entry types to ldap attributes of subschema entry
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @access public
							 | 
						||
| 
								 | 
							
								    * @var array
							 | 
						||
| 
								 | 
							
								    */
							 | 
						||
| 
								 | 
							
								    public $types = array(
							 | 
						||
| 
								 | 
							
								            'attribute'        => 'attributeTypes',
							 | 
						||
| 
								 | 
							
								            'ditcontentrule'   => 'dITContentRules',
							 | 
						||
| 
								 | 
							
								            'ditstructurerule' => 'dITStructureRules',
							 | 
						||
| 
								 | 
							
								            'matchingrule'     => 'matchingRules',
							 | 
						||
| 
								 | 
							
								            'matchingruleuse'  => 'matchingRuleUse',
							 | 
						||
| 
								 | 
							
								            'nameform'         => 'nameForms',
							 | 
						||
| 
								 | 
							
								            'objectclass'      => 'objectClasses',
							 | 
						||
| 
								 | 
							
								            'syntax'           => 'ldapSyntaxes'
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								    * Array of entries belonging to this type
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @access protected
							 | 
						||
| 
								 | 
							
								    * @var array
							 | 
						||
| 
								 | 
							
								    */
							 | 
						||
| 
								 | 
							
								    protected $_attributeTypes    = array();
							 | 
						||
| 
								 | 
							
								    protected $_matchingRules     = array();
							 | 
						||
| 
								 | 
							
								    protected $_matchingRuleUse   = array();
							 | 
						||
| 
								 | 
							
								    protected $_ldapSyntaxes      = array();
							 | 
						||
| 
								 | 
							
								    protected $_objectClasses     = array();
							 | 
						||
| 
								 | 
							
								    protected $_dITContentRules   = array();
							 | 
						||
| 
								 | 
							
								    protected $_dITStructureRules = array();
							 | 
						||
| 
								 | 
							
								    protected $_nameForms         = array();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								    * hash of all fetched oids
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @access protected
							 | 
						||
| 
								 | 
							
								    * @var array
							 | 
						||
| 
								 | 
							
								    */
							 | 
						||
| 
								 | 
							
								    protected $_oids = array();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								    * Tells if the schema is initialized
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @access protected
							 | 
						||
| 
								 | 
							
								    * @var boolean
							 | 
						||
| 
								 | 
							
								    * @see parse(), get()
							 | 
						||
| 
								 | 
							
								    */
							 | 
						||
| 
								 | 
							
								    protected $_initialized = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								    * Constructor of the class
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @access protected
							 | 
						||
| 
								 | 
							
								    */
							 | 
						||
| 
								 | 
							
								    protected function __construct()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $this->PEAR('Net_LDAP2_Error'); // default error class
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								    * Fetch the Schema from an LDAP connection
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @param Net_LDAP2 $ldap LDAP connection
							 | 
						||
| 
								 | 
							
								    * @param string    $dn   (optional) Subschema entry dn
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @access public
							 | 
						||
| 
								 | 
							
								    * @return Net_LDAP2_Schema|NET_LDAP2_Error
							 | 
						||
| 
								 | 
							
								    */
							 | 
						||
| 
								 | 
							
								    public function fetch($ldap, $dn = null)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (!$ldap instanceof Net_LDAP2) {
							 | 
						||
| 
								 | 
							
								            return PEAR::raiseError("Unable to fetch Schema: Parameter \$ldap must be a Net_LDAP2 object!");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $schema_o = new Net_LDAP2_Schema();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (is_null($dn)) {
							 | 
						||
| 
								 | 
							
								            // get the subschema entry via root dse
							 | 
						||
| 
								 | 
							
								            $dse = $ldap->rootDSE(array('subschemaSubentry'));
							 | 
						||
| 
								 | 
							
								            if (false == Net_LDAP2::isError($dse)) {
							 | 
						||
| 
								 | 
							
								                $base = $dse->getValue('subschemaSubentry', 'single');
							 | 
						||
| 
								 | 
							
								                if (!Net_LDAP2::isError($base)) {
							 | 
						||
| 
								 | 
							
								                    $dn = $base;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Support for buggy LDAP servers (e.g. Siemens DirX 6.x) that incorrectly
							 | 
						||
| 
								 | 
							
								        // call this entry subSchemaSubentry instead of subschemaSubentry.
							 | 
						||
| 
								 | 
							
								        // Note the correct case/spelling as per RFC 2251.
							 | 
						||
| 
								 | 
							
								        if (is_null($dn)) {
							 | 
						||
| 
								 | 
							
								            // get the subschema entry via root dse
							 | 
						||
| 
								 | 
							
								            $dse = $ldap->rootDSE(array('subSchemaSubentry'));
							 | 
						||
| 
								 | 
							
								            if (false == Net_LDAP2::isError($dse)) {
							 | 
						||
| 
								 | 
							
								                $base = $dse->getValue('subSchemaSubentry', 'single');
							 | 
						||
| 
								 | 
							
								                if (!Net_LDAP2::isError($base)) {
							 | 
						||
| 
								 | 
							
								                    $dn = $base;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Final fallback case where there is no subschemaSubentry attribute
							 | 
						||
| 
								 | 
							
								        // in the root DSE (this is a bug for an LDAP v3 server so report this
							 | 
						||
| 
								 | 
							
								        // to your LDAP vendor if you get this far).
							 | 
						||
| 
								 | 
							
								        if (is_null($dn)) {
							 | 
						||
| 
								 | 
							
								            $dn = 'cn=Subschema';
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // fetch the subschema entry
							 | 
						||
| 
								 | 
							
								        $result = $ldap->search($dn, '(objectClass=*)',
							 | 
						||
| 
								 | 
							
								                                array('attributes' => array_values($schema_o->types),
							 | 
						||
| 
								 | 
							
								                                        'scope' => 'base'));
							 | 
						||
| 
								 | 
							
								        if (Net_LDAP2::isError($result)) {
							 | 
						||
| 
								 | 
							
								            return $result;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $entry = $result->shiftEntry();
							 | 
						||
| 
								 | 
							
								        if (!$entry instanceof Net_LDAP2_Entry) {
							 | 
						||
| 
								 | 
							
								            return PEAR::raiseError('Could not fetch Subschema entry');
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $schema_o->parse($entry);
							 | 
						||
| 
								 | 
							
								        return $schema_o;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								    * Return a hash of entries for the given type
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * Returns a hash of entry for th givene type. Types may be:
							 | 
						||
| 
								 | 
							
								    * objectclasses, attributes, ditcontentrules, ditstructurerules, matchingrules,
							 | 
						||
| 
								 | 
							
								    * matchingruleuses, nameforms, syntaxes
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @param string $type Type to fetch
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @access public
							 | 
						||
| 
								 | 
							
								    * @return array|Net_LDAP2_Error Array or Net_LDAP2_Error
							 | 
						||
| 
								 | 
							
								    */
							 | 
						||
| 
								 | 
							
								    public function &getAll($type)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $map = array('objectclasses'     => &$this->_objectClasses,
							 | 
						||
| 
								 | 
							
								                     'attributes'        => &$this->_attributeTypes,
							 | 
						||
| 
								 | 
							
								                     'ditcontentrules'   => &$this->_dITContentRules,
							 | 
						||
| 
								 | 
							
								                     'ditstructurerules' => &$this->_dITStructureRules,
							 | 
						||
| 
								 | 
							
								                     'matchingrules'     => &$this->_matchingRules,
							 | 
						||
| 
								 | 
							
								                     'matchingruleuses'  => &$this->_matchingRuleUse,
							 | 
						||
| 
								 | 
							
								                     'nameforms'         => &$this->_nameForms,
							 | 
						||
| 
								 | 
							
								                     'syntaxes'          => &$this->_ldapSyntaxes );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $key = strtolower($type);
							 | 
						||
| 
								 | 
							
								        $ret = ((key_exists($key, $map)) ? $map[$key] : PEAR::raiseError("Unknown type $type"));
							 | 
						||
| 
								 | 
							
								        return $ret;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								    * Return a specific entry
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @param string $type Type of name
							 | 
						||
| 
								 | 
							
								    * @param string $name Name or OID to fetch
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @access public
							 | 
						||
| 
								 | 
							
								    * @return mixed Entry or Net_LDAP2_Error
							 | 
						||
| 
								 | 
							
								    */
							 | 
						||
| 
								 | 
							
								    public function &get($type, $name)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if ($this->_initialized) {
							 | 
						||
| 
								 | 
							
								            $type = strtolower($type);
							 | 
						||
| 
								 | 
							
								            if (false == key_exists($type, $this->types)) {
							 | 
						||
| 
								 | 
							
								                return PEAR::raiseError("No such type $type");
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            $name     = strtolower($name);
							 | 
						||
| 
								 | 
							
								            $type_var = &$this->{'_' . $this->types[$type]};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (key_exists($name, $type_var)) {
							 | 
						||
| 
								 | 
							
								                return $type_var[$name];
							 | 
						||
| 
								 | 
							
								            } elseif (key_exists($name, $this->_oids) && $this->_oids[$name]['type'] == $type) {
							 | 
						||
| 
								 | 
							
								                return $this->_oids[$name];
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                return PEAR::raiseError("Could not find $type $name");
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            $return = null;
							 | 
						||
| 
								 | 
							
								            return $return;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								    * Fetches attributes that MAY be present in the given objectclass
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @param string $oc Name or OID of objectclass
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @access public
							 | 
						||
| 
								 | 
							
								    * @return array|Net_LDAP2_Error Array with attributes or Net_LDAP2_Error
							 | 
						||
| 
								 | 
							
								    */
							 | 
						||
| 
								 | 
							
								    public function may($oc)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return $this->_getAttr($oc, 'may');
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								    * Fetches attributes that MUST be present in the given objectclass
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @param string $oc Name or OID of objectclass
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @access public
							 | 
						||
| 
								 | 
							
								    * @return array|Net_LDAP2_Error Array with attributes or Net_LDAP2_Error
							 | 
						||
| 
								 | 
							
								    */
							 | 
						||
| 
								 | 
							
								    public function must($oc)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return $this->_getAttr($oc, 'must');
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								    * Fetches the given attribute from the given objectclass
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @param string $oc   Name or OID of objectclass
							 | 
						||
| 
								 | 
							
								    * @param string $attr Name of attribute to fetch
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @access protected
							 | 
						||
| 
								 | 
							
								    * @return array|Net_LDAP2_Error The attribute or Net_LDAP2_Error
							 | 
						||
| 
								 | 
							
								    */
							 | 
						||
| 
								 | 
							
								    protected function _getAttr($oc, $attr)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $oc = strtolower($oc);
							 | 
						||
| 
								 | 
							
								        if (key_exists($oc, $this->_objectClasses) && key_exists($attr, $this->_objectClasses[$oc])) {
							 | 
						||
| 
								 | 
							
								            return $this->_objectClasses[$oc][$attr];
							 | 
						||
| 
								 | 
							
								        } elseif (key_exists($oc, $this->_oids) &&
							 | 
						||
| 
								 | 
							
								                $this->_oids[$oc]['type'] == 'objectclass' &&
							 | 
						||
| 
								 | 
							
								                key_exists($attr, $this->_oids[$oc])) {
							 | 
						||
| 
								 | 
							
								            return $this->_oids[$oc][$attr];
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            return PEAR::raiseError("Could not find $attr attributes for $oc ");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								    * Returns the name(s) of the immediate superclass(es)
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @param string $oc Name or OID of objectclass
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @access public
							 | 
						||
| 
								 | 
							
								    * @return array|Net_LDAP2_Error  Array of names or Net_LDAP2_Error
							 | 
						||
| 
								 | 
							
								    */
							 | 
						||
| 
								 | 
							
								    public function superclass($oc)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $o = $this->get('objectclass', $oc);
							 | 
						||
| 
								 | 
							
								        if (Net_LDAP2::isError($o)) {
							 | 
						||
| 
								 | 
							
								            return $o;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return (key_exists('sup', $o) ? $o['sup'] : array());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								    * Parses the schema of the given Subschema entry
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @param Net_LDAP2_Entry &$entry Subschema entry
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @access public
							 | 
						||
| 
								 | 
							
								    * @return void
							 | 
						||
| 
								 | 
							
								    */
							 | 
						||
| 
								 | 
							
								    public function parse(&$entry)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        foreach ($this->types as $type => $attr) {
							 | 
						||
| 
								 | 
							
								            // initialize map type to entry
							 | 
						||
| 
								 | 
							
								            $type_var          = '_' . $attr;
							 | 
						||
| 
								 | 
							
								            $this->{$type_var} = array();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // get values for this type
							 | 
						||
| 
								 | 
							
								            if ($entry->exists($attr)) {
							 | 
						||
| 
								 | 
							
								                $values = $entry->getValue($attr);
							 | 
						||
| 
								 | 
							
								                if (is_array($values)) {
							 | 
						||
| 
								 | 
							
								                    foreach ($values as $value) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                        unset($schema_entry); // this was a real mess without it
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                        // get the schema entry
							 | 
						||
| 
								 | 
							
								                        $schema_entry = $this->_parse_entry($value);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                        // set the type
							 | 
						||
| 
								 | 
							
								                        $schema_entry['type'] = $type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                        // save a ref in $_oids
							 | 
						||
| 
								 | 
							
								                        $this->_oids[$schema_entry['oid']] = &$schema_entry;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                        // save refs for all names in type map
							 | 
						||
| 
								 | 
							
								                        $names = $schema_entry['aliases'];
							 | 
						||
| 
								 | 
							
								                        array_push($names, $schema_entry['name']);
							 | 
						||
| 
								 | 
							
								                        foreach ($names as $name) {
							 | 
						||
| 
								 | 
							
								                            $this->{$type_var}[strtolower($name)] = &$schema_entry;
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        $this->_initialized = true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								    * Parses an attribute value into a schema entry
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @param string $value Attribute value
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @access protected
							 | 
						||
| 
								 | 
							
								    * @return array|false Schema entry array or false
							 | 
						||
| 
								 | 
							
								    */
							 | 
						||
| 
								 | 
							
								    protected function &_parse_entry($value)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        // tokens that have no value associated
							 | 
						||
| 
								 | 
							
								        $noValue = array('single-value',
							 | 
						||
| 
								 | 
							
								                         'obsolete',
							 | 
						||
| 
								 | 
							
								                         'collective',
							 | 
						||
| 
								 | 
							
								                         'no-user-modification',
							 | 
						||
| 
								 | 
							
								                         'abstract',
							 | 
						||
| 
								 | 
							
								                         'structural',
							 | 
						||
| 
								 | 
							
								                         'auxiliary');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // tokens that can have multiple values
							 | 
						||
| 
								 | 
							
								        $multiValue = array('must', 'may', 'sup');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $schema_entry = array('aliases' => array()); // initilization
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $tokens = $this->_tokenize($value); // get an array of tokens
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // remove surrounding brackets
							 | 
						||
| 
								 | 
							
								        if ($tokens[0] == '(') array_shift($tokens);
							 | 
						||
| 
								 | 
							
								        if ($tokens[count($tokens) - 1] == ')') array_pop($tokens); // -1 doesnt work on arrays :-(
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $schema_entry['oid'] = array_shift($tokens); // first token is the oid
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // cycle over the tokens until none are left
							 | 
						||
| 
								 | 
							
								        while (count($tokens) > 0) {
							 | 
						||
| 
								 | 
							
								            $token = strtolower(array_shift($tokens));
							 | 
						||
| 
								 | 
							
								            if (in_array($token, $noValue)) {
							 | 
						||
| 
								 | 
							
								                $schema_entry[$token] = 1; // single value token
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                // this one follows a string or a list if it is multivalued
							 | 
						||
| 
								 | 
							
								                if (($schema_entry[$token] = array_shift($tokens)) == '(') {
							 | 
						||
| 
								 | 
							
								                    // this creates the list of values and cycles through the tokens
							 | 
						||
| 
								 | 
							
								                    // until the end of the list is reached ')'
							 | 
						||
| 
								 | 
							
								                    $schema_entry[$token] = array();
							 | 
						||
| 
								 | 
							
								                    while ($tmp = array_shift($tokens)) {
							 | 
						||
| 
								 | 
							
								                        if ($tmp == ')') break;
							 | 
						||
| 
								 | 
							
								                        if ($tmp != '$') array_push($schema_entry[$token], $tmp);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                // create a array if the value should be multivalued but was not
							 | 
						||
| 
								 | 
							
								                if (in_array($token, $multiValue) && !is_array($schema_entry[$token])) {
							 | 
						||
| 
								 | 
							
								                    $schema_entry[$token] = array($schema_entry[$token]);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        // get max length from syntax
							 | 
						||
| 
								 | 
							
								        if (key_exists('syntax', $schema_entry)) {
							 | 
						||
| 
								 | 
							
								            if (preg_match('/{(\d+)}/', $schema_entry['syntax'], $matches)) {
							 | 
						||
| 
								 | 
							
								                $schema_entry['max_length'] = $matches[1];
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        // force a name
							 | 
						||
| 
								 | 
							
								        if (empty($schema_entry['name'])) {
							 | 
						||
| 
								 | 
							
								            $schema_entry['name'] = $schema_entry['oid'];
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        // make one name the default and put the other ones into aliases
							 | 
						||
| 
								 | 
							
								        if (is_array($schema_entry['name'])) {
							 | 
						||
| 
								 | 
							
								            $aliases                 = $schema_entry['name'];
							 | 
						||
| 
								 | 
							
								            $schema_entry['name']    = array_shift($aliases);
							 | 
						||
| 
								 | 
							
								            $schema_entry['aliases'] = $aliases;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return $schema_entry;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								    * Tokenizes the given value into an array of tokens
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @param string $value String to parse
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @access protected
							 | 
						||
| 
								 | 
							
								    * @return array Array of tokens
							 | 
						||
| 
								 | 
							
								    */
							 | 
						||
| 
								 | 
							
								    protected function _tokenize($value)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $tokens  = array();       // array of tokens
							 | 
						||
| 
								 | 
							
								        $matches = array();       // matches[0] full pattern match, [1,2,3] subpatterns
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // this one is taken from perl-ldap, modified for php
							 | 
						||
| 
								 | 
							
								        $pattern = "/\s* (?:([()]) | ([^'\s()]+) | '((?:[^']+|'[^\s)])*)') \s*/x";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /**
							 | 
						||
| 
								 | 
							
								         * This one matches one big pattern wherin only one of the three subpatterns matched
							 | 
						||
| 
								 | 
							
								         * We are interested in the subpatterns that matched. If it matched its value will be
							 | 
						||
| 
								 | 
							
								         * non-empty and so it is a token. Tokens may be round brackets, a string, or a string
							 | 
						||
| 
								 | 
							
								         * enclosed by '
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        preg_match_all($pattern, $value, $matches);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for ($i = 0; $i < count($matches[0]); $i++) {     // number of tokens (full pattern match)
							 | 
						||
| 
								 | 
							
								            for ($j = 1; $j < 4; $j++) {                  // each subpattern
							 | 
						||
| 
								 | 
							
								                if (null != trim($matches[$j][$i])) {     // pattern match in this subpattern
							 | 
						||
| 
								 | 
							
								                    $tokens[$i] = trim($matches[$j][$i]); // this is the token
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return $tokens;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								    * Returns wether a attribute syntax is binary or not
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * This method gets used by Net_LDAP2_Entry to decide which
							 | 
						||
| 
								 | 
							
								    * PHP function needs to be used to fetch the value in the
							 | 
						||
| 
								 | 
							
								    * proper format (e.g. binary or string)
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @param string $attribute The name of the attribute (eg.: 'sn')
							 | 
						||
| 
								 | 
							
								    *
							 | 
						||
| 
								 | 
							
								    * @access public
							 | 
						||
| 
								 | 
							
								    * @return boolean
							 | 
						||
| 
								 | 
							
								    */
							 | 
						||
| 
								 | 
							
								    public function isBinary($attribute)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $return = false; // default to false
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // This list contains all syntax that should be treaten as
							 | 
						||
| 
								 | 
							
								        // containing binary values
							 | 
						||
| 
								 | 
							
								        // The Syntax Definitons go into constants at the top of this page
							 | 
						||
| 
								 | 
							
								        $syntax_binary = array(
							 | 
						||
| 
								 | 
							
								                           NET_LDAP2_SYNTAX_OCTET_STRING,
							 | 
						||
| 
								 | 
							
								                           NET_LDAP2_SYNTAX_JPEG
							 | 
						||
| 
								 | 
							
								                         );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Check Syntax
							 | 
						||
| 
								 | 
							
								        $attr_s = $this->get('attribute', $attribute);
							 | 
						||
| 
								 | 
							
								        if (Net_LDAP2::isError($attr_s)) {
							 | 
						||
| 
								 | 
							
								            // Attribute not found in schema
							 | 
						||
| 
								 | 
							
								            $return = false; // consider attr not binary
							 | 
						||
| 
								 | 
							
								        } elseif (isset($attr_s['syntax']) && in_array($attr_s['syntax'], $syntax_binary)) {
							 | 
						||
| 
								 | 
							
								            // Syntax is defined as binary in schema
							 | 
						||
| 
								 | 
							
								            $return = true;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            // Syntax not defined as binary, or not found
							 | 
						||
| 
								 | 
							
								            // if attribute is a subtype, check superior attribute syntaxes
							 | 
						||
| 
								 | 
							
								            if (isset($attr_s['sup'])) {
							 | 
						||
| 
								 | 
							
								                foreach ($attr_s['sup'] as $superattr) {
							 | 
						||
| 
								 | 
							
								                    $return = $this->isBinary($superattr);
							 | 
						||
| 
								 | 
							
								                    if ($return) {
							 | 
						||
| 
								 | 
							
								                        break; // stop checking parents since we are binary
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return $return;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // [TODO] add method that allows us to see to which objectclasses a certain attribute belongs to
							 | 
						||
| 
								 | 
							
								    // it should return the result structured, e.g. sorted in "may" and "must". Optionally it should
							 | 
						||
| 
								 | 
							
								    // be able to return it just "flat", e.g. array_merge()d.
							 | 
						||
| 
								 | 
							
								    // We could use get_all() to achieve this easily, i think
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								?>
							 |