654 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			PHP
		
	
	
	
			
		
		
	
	
			654 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			PHP
		
	
	
	
<?php
 | 
						|
/**
 | 
						|
 * Classes and functions for communication of Data Stores
 | 
						|
 *
 | 
						|
 * @author The phpLDAPadmin development team
 | 
						|
 * @package phpLDAPadmin
 | 
						|
 */
 | 
						|
 | 
						|
/**
 | 
						|
 * This abstract class provides variables and methods for LDAP datastores for use by PLA.
 | 
						|
 *
 | 
						|
 * @package phpLDAPadmin
 | 
						|
 * @subpackage DataStore
 | 
						|
 */
 | 
						|
class ldap_pla extends myldap {
 | 
						|
	# Attributes that should be treated as MAY attributes, even though the scheme has them as MUST attributes.
 | 
						|
	private $force_may = array();
 | 
						|
 | 
						|
	function __construct($index) {
 | 
						|
		parent::__construct($index);
 | 
						|
 | 
						|
		$this->default->appearance['password_hash'] = array(
 | 
						|
			'desc'=>'Default HASH to use for passwords',
 | 
						|
			'default'=>'md5');
 | 
						|
 | 
						|
		$this->default->appearance['show_create'] = array(
 | 
						|
			'desc'=>'Whether to show the "Create new Entry here" in the tree browser',
 | 
						|
			'default'=>true);
 | 
						|
 | 
						|
		$this->default->login['fallback_dn'] = array(
 | 
						|
			'desc'=>'If the attribute base login fails, see if a DN was entered',
 | 
						|
			'default'=>false);
 | 
						|
 | 
						|
		$this->default->query['disable_default'] = array(
 | 
						|
			'desc'=>'Configuration to disable the default query template',
 | 
						|
			'default'=>false);
 | 
						|
 | 
						|
		$this->default->query['custom_only'] = array(
 | 
						|
			'desc'=>'Configuration to force the usage of custom query templates',
 | 
						|
			'default'=>false);
 | 
						|
 | 
						|
		$this->default->server['branch_rename'] = array(
 | 
						|
			'desc'=>'Enable renaming of branches',
 | 
						|
			'default'=>false);
 | 
						|
 | 
						|
		$this->default->server['custom_attrs'] = array(
 | 
						|
			'desc'=>'Custom operational attributes to be treated as regular attributes',
 | 
						|
			'default'=>array(''));
 | 
						|
 | 
						|
		$this->default->server['custom_sys_attrs'] = array(
 | 
						|
			'desc'=>'Custom operational attributes to be treated as internal attributes',
 | 
						|
			'default'=>array('+'));
 | 
						|
 | 
						|
		$this->default->server['jpeg_attributes'] = array(
 | 
						|
			'desc'=>'Additional attributes to treat as Jpeg Attributes',
 | 
						|
			'default'=>array());
 | 
						|
 | 
						|
		# This was added in case the LDAP server doesnt provide them with a base +,* query.
 | 
						|
		$this->default->server['root_dse_attributes'] = array(
 | 
						|
			'desc'=>'RootDSE attributes for use when displaying server info',
 | 
						|
			'default'=>array(
 | 
						|
				'namingContexts',
 | 
						|
				'subschemaSubentry',
 | 
						|
				'altServer',
 | 
						|
				'supportedExtension',
 | 
						|
				'supportedControl',
 | 
						|
				'supportedSASLMechanisms',
 | 
						|
				'supportedLDAPVersion',
 | 
						|
				'currentTime',
 | 
						|
				'dsServiceName',
 | 
						|
				'defaultNamingContext',
 | 
						|
				'schemaNamingContext',
 | 
						|
				'configurationNamingContext',
 | 
						|
				'rootDomainNamingContext',
 | 
						|
				'supportedLDAPPolicies',
 | 
						|
				'highestCommittedUSN',
 | 
						|
				'dnsHostName',
 | 
						|
				'ldapServiceName',
 | 
						|
				'serverName',
 | 
						|
				'supportedCapabilities',
 | 
						|
				'changeLog',
 | 
						|
				'tlsAvailableCipherSuites',
 | 
						|
				'tlsImplementationVersion',
 | 
						|
				'supportedSASLMechanisms',
 | 
						|
				'dsaVersion',
 | 
						|
				'myAccessPoint',
 | 
						|
				'dseType',
 | 
						|
				'+',
 | 
						|
				'*'
 | 
						|
			));
 | 
						|
 | 
						|
		# Settings for auto_number
 | 
						|
		$this->default->auto_number['enable'] = array(
 | 
						|
			'desc'=>'Enable the AUTO UID feature',
 | 
						|
			'default'=>true);
 | 
						|
 | 
						|
		$this->default->auto_number['mechanism'] = array(
 | 
						|
			'desc'=>'Mechanism to use to search for automatic numbers',
 | 
						|
			'default'=>'search');
 | 
						|
 | 
						|
		$this->default->auto_number['search_base'] = array(
 | 
						|
			'desc'=>'Base DN to use for search mechanisms',
 | 
						|
			'default'=>null);
 | 
						|
 | 
						|
		$this->default->auto_number['min'] = array(
 | 
						|
			'desc'=>'Minimum number to start with',
 | 
						|
			'default'=>array('uidNumber'=>1000,'gidNumber'=>500));
 | 
						|
 | 
						|
		$this->default->auto_number['dn'] = array(
 | 
						|
			'desc'=>'DN to use when evaluating numbers',
 | 
						|
			'default'=>null);
 | 
						|
 | 
						|
		$this->default->auto_number['pass'] = array(
 | 
						|
			'desc'=>'Password for DN to use when evaluating numbers',
 | 
						|
			'default'=>null);
 | 
						|
 | 
						|
		$this->default->unique['attrs'] = array(
 | 
						|
			'desc'=>'Attributes to check for uniqueness before allowing updates',
 | 
						|
			'default'=>array('mail','uid','uidNumber'));
 | 
						|
 | 
						|
		$this->default->unique['dn'] = array(
 | 
						|
			'desc'=>'DN to use when evaluating attribute uniqueness',
 | 
						|
			'default'=>null);
 | 
						|
 | 
						|
		$this->default->unique['pass'] = array(
 | 
						|
			'desc'=>'Password for DN to use when evaluating attribute uniqueness',
 | 
						|
			'default'=>null);
 | 
						|
	}
 | 
						|
 | 
						|
	public function __get($key) {
 | 
						|
		switch ($key) {
 | 
						|
			case 'name':
 | 
						|
				return $this->getValue('server','name');
 | 
						|
 | 
						|
			default:
 | 
						|
				system_message(array(
 | 
						|
					'title'=>('Unknown request for Object value.'),
 | 
						|
					'body'=>sprintf(('Attempt to obtain value %s from %s'),$key,get_class($this)),
 | 
						|
					'type'=>'error'));
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Gets whether the admin has configured phpLDAPadmin to show the "Create New" link in the tree viewer.
 | 
						|
	 * <code>
 | 
						|
	 *	$servers->setValue('appearance','show_create',true|false);
 | 
						|
	 * </code>
 | 
						|
	 * If NOT set, then default to show the Create New item.
 | 
						|
	 * If IS set, then return the value (it should be true or false).
 | 
						|
	 *
 | 
						|
	 * The entry creation command must be available.
 | 
						|
	 * <code>
 | 
						|
	 *	$config->custom->commands['script'] = array('create' => true);
 | 
						|
	 * </code>
 | 
						|
	 *
 | 
						|
	 * @return boolean true if the feature is enabled and false otherwise.
 | 
						|
	 */
 | 
						|
	function isShowCreateEnabled() {
 | 
						|
		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
 | 
						|
			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
 | 
						|
 | 
						|
		if (! $_SESSION[APPCONFIG]->isCommandAvailable('script','create'))
 | 
						|
			return false;
 | 
						|
		else
 | 
						|
			return $this->getValue('appearance','show_create');
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Fetch whether the user has configured a certain server login to be non anonymous
 | 
						|
	 *
 | 
						|
	 * <code>
 | 
						|
	 *	$servers->setValue('login','anon_bind',true|false);
 | 
						|
	 * </code>
 | 
						|
	 *
 | 
						|
	 * @return boolean
 | 
						|
	 */
 | 
						|
	public function isAnonBindAllowed() {
 | 
						|
		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
 | 
						|
			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
 | 
						|
 | 
						|
		# If only_login_allowed_dns is set, then we cant have anonymous.
 | 
						|
		if (count($this->getValue('login','allowed_dns')) > 0)
 | 
						|
			$return = false;
 | 
						|
		else
 | 
						|
			$return = $this->getValue('login','anon_bind');
 | 
						|
 | 
						|
		if (DEBUG_ENABLED)
 | 
						|
			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$return);
 | 
						|
 | 
						|
		return $return;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Returns true if the user has configured the specified server to enable branch (non-leaf) renames.
 | 
						|
	 *
 | 
						|
	 * This is configured in config.php thus:
 | 
						|
	 * <code>
 | 
						|
	 *	$servers->setValue('server','branch_rename',true|false);
 | 
						|
	 * </code>
 | 
						|
	 *
 | 
						|
	 * @return boolean
 | 
						|
	 */
 | 
						|
	function isBranchRenameEnabled() {
 | 
						|
		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
 | 
						|
			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
 | 
						|
 | 
						|
 		return $this->getValue('server','branch_rename');
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Determines if an attribute's value can contain multiple lines. Attributes that fall
 | 
						|
	 * in this multi-line category may be configured in config.php. Hence, this function
 | 
						|
	 * accesses the global variable $_SESSION[APPCONFIG]->custom->appearance['multi_line_attributes'];
 | 
						|
	 *
 | 
						|
	 * Usage example:
 | 
						|
	 * <code>
 | 
						|
	 *	if ($ldapserver->isMultiLineAttr('postalAddress'))
 | 
						|
	 *		echo '<textarea name="postalAddress"></textarea>';
 | 
						|
	 *	else
 | 
						|
	 *		echo '<input name="postalAddress" type="text">';
 | 
						|
	 * </code>
 | 
						|
	 *
 | 
						|
	 * @param string The name of the attribute of interested (case insensivite)
 | 
						|
	 * @param string (optional) The current value of the attribute (speeds up the process by searching for carriage returns already in the attribute value)
 | 
						|
	 * @return boolean
 | 
						|
	 */
 | 
						|
	function isMultiLineAttr($attr_name,$val=null) {
 | 
						|
		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
 | 
						|
			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
 | 
						|
 | 
						|
		# Set default return
 | 
						|
		$return = false;
 | 
						|
 | 
						|
		# First, check the optional val param for a \n or a \r
 | 
						|
		if (! is_null($val) && (strpos($val,"\n") || strpos($val,"\r")))
 | 
						|
			$return = true;
 | 
						|
 | 
						|
		# Next, compare strictly by name first
 | 
						|
		else
 | 
						|
			foreach ($_SESSION[APPCONFIG]->getValue('appearance','multi_line_attributes') as $multi_line_attr_name)
 | 
						|
				if (strcasecmp($multi_line_attr_name,$attr_name) == 0) {
 | 
						|
					$return = true;
 | 
						|
					break;
 | 
						|
				}
 | 
						|
 | 
						|
		# If unfound, compare by syntax OID
 | 
						|
		if (! $return) {
 | 
						|
			$sattr = $this->getSchemaAttribute($attr_name);
 | 
						|
 | 
						|
			if ($sattr) {
 | 
						|
				$syntax_oid = $sattr->getSyntaxOID();
 | 
						|
 | 
						|
				if ($syntax_oid)
 | 
						|
					foreach ($_SESSION[APPCONFIG]->getValue('appearance','multi_line_syntax_oids') as $multi_line_syntax_oid)
 | 
						|
						if ($multi_line_syntax_oid == $syntax_oid) {
 | 
						|
							$return = true;
 | 
						|
							break;
 | 
						|
						}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if (DEBUG_ENABLED)
 | 
						|
			debug_log('Returning (%s)',17,0,__FILE__,__LINE__,__METHOD__,$return);
 | 
						|
 | 
						|
		return $return;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Returns true if the specified attribute is configured according to
 | 
						|
	 * the test enabled in config.php
 | 
						|
	 *
 | 
						|
	 * @param string The name of the attribute to test.
 | 
						|
	 * @param array The attributes to test against.
 | 
						|
	 * @param dn A DN that is exempt from these tests.
 | 
						|
	 * @return boolean
 | 
						|
	 */
 | 
						|
	private function isAttrTest($attr,$attrs,$except_dn) {
 | 
						|
		$attr = trim($attr);
 | 
						|
		if (! trim($attr) || ! count($attrs))
 | 
						|
			return false;
 | 
						|
 | 
						|
		# Is the user excluded?
 | 
						|
		if ($except_dn && $this->userIsMember($this->getLogin(),$except_dn))
 | 
						|
			return false;
 | 
						|
 | 
						|
		foreach ($attrs as $attr_name)
 | 
						|
			if (strcasecmp($attr,trim($attr_name)) == 0)
 | 
						|
				return true;
 | 
						|
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Returns true if the specified attribute is configured as read only
 | 
						|
	 * in config.php.
 | 
						|
	 * Attributes are configured as read-only in config.php thus:
 | 
						|
	 * <code>
 | 
						|
	 *	$config->custom->appearance['readonly_attrs'] = array('objectClass');
 | 
						|
	 * </code>
 | 
						|
	 *
 | 
						|
	 * @param string The name of the attribute to test.
 | 
						|
	 * @return boolean
 | 
						|
	 */
 | 
						|
	public function isAttrReadOnly($attr) {
 | 
						|
		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
 | 
						|
			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
 | 
						|
 | 
						|
		$attrs = $_SESSION[APPCONFIG]->getValue('appearance','readonly_attrs');
 | 
						|
		$except_dn = $_SESSION[APPCONFIG]->getValue('appearance','readonly_attrs_exempt');
 | 
						|
 | 
						|
		return $this->isAttrTest($attr,$attrs,$except_dn);
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Returns true if the specified attribute is configured as hidden
 | 
						|
	 * in config.php.
 | 
						|
	 * Attributes are configured as hidden in config.php thus:
 | 
						|
	 * <code>
 | 
						|
	 *	$config->custom->appearance['hide_attrs'] = array('objectClass');
 | 
						|
	 * </code>
 | 
						|
	 *
 | 
						|
	 * @param string The name of the attribute to test.
 | 
						|
	 * @return boolean
 | 
						|
	 */
 | 
						|
	public function isAttrHidden($attr) {
 | 
						|
		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
 | 
						|
			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
 | 
						|
 | 
						|
		$attrs = $_SESSION[APPCONFIG]->getValue('appearance','hide_attrs');
 | 
						|
		$except_dn = $_SESSION[APPCONFIG]->getValue('appearance','hide_attrs_exempt');
 | 
						|
 | 
						|
		return $this->isAttrTest($attr,$attrs,$except_dn);
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Add objects
 | 
						|
	 */
 | 
						|
	public function add($dn,$entry_array,$method=null) {
 | 
						|
		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
 | 
						|
			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
 | 
						|
 | 
						|
		foreach ($entry_array as $attr => $val)
 | 
						|
			$entry_array[$attr] = dn_unescape($val);
 | 
						|
 | 
						|
		$result = false;
 | 
						|
 | 
						|
		# Check our unique attributes.
 | 
						|
		if (! $this->checkUniqueAttrs($dn,$entry_array))
 | 
						|
			return false;
 | 
						|
 | 
						|
		if (run_hook('pre_entry_create',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attrs'=>$entry_array))) {
 | 
						|
			$result = @ldap_add($this->connect($method),dn_escape($dn),$entry_array);
 | 
						|
 | 
						|
			if ($result) {
 | 
						|
				# Update the tree
 | 
						|
				$tree = get_cached_item($this->index,'tree');
 | 
						|
 | 
						|
				# If we created the base, delete it, then add it back
 | 
						|
				if (get_request('create_base'))
 | 
						|
					$tree->delEntry($dn);
 | 
						|
 | 
						|
				$tree->addEntry($dn);
 | 
						|
 | 
						|
				set_cached_item($this->index,'tree','null',$tree);
 | 
						|
 | 
						|
				run_hook('post_entry_create',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attrs'=>$entry_array));
 | 
						|
 | 
						|
			} else {
 | 
						|
				system_message(array(
 | 
						|
					'title'=>_('Could not add the object to the LDAP server.'),
 | 
						|
					'body'=>ldap_error_msg($this->getErrorMessage(null),$this->getErrorNum(null)),
 | 
						|
					'type'=>'error'));
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		return $result;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Delete objects
 | 
						|
	 */
 | 
						|
	public function delete($dn,$method=null) {
 | 
						|
		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
 | 
						|
			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
 | 
						|
 | 
						|
		$result = false;
 | 
						|
 | 
						|
		if (run_hook('pre_entry_delete',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn))) {
 | 
						|
			$result = @ldap_delete($this->connect($method),dn_escape($dn));
 | 
						|
 | 
						|
			if ($result) {
 | 
						|
				# Update the tree
 | 
						|
				$tree = get_cached_item($this->index,'tree');
 | 
						|
				$tree->delEntry($dn);
 | 
						|
 | 
						|
				set_cached_item($this->index,'tree','null',$tree);
 | 
						|
 | 
						|
				run_hook('post_entry_delete',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn));
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		return $result;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Rename objects
 | 
						|
	 */
 | 
						|
	public function rename($dn,$new_rdn,$container,$deleteoldrdn,$method=null) {
 | 
						|
		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
 | 
						|
			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
 | 
						|
 | 
						|
		$result = false;
 | 
						|
 | 
						|
		if (run_hook('pre_entry_rename',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'rdn'=>$new_rdn,'container'=>$container))) {
 | 
						|
			$result = @ldap_rename($this->connect($method),$dn,$new_rdn,$container,$deleteoldrdn);
 | 
						|
 | 
						|
			if ($result) {
 | 
						|
				# Update the tree
 | 
						|
				$tree = get_cached_item($this->index,'tree');
 | 
						|
				$newdn = sprintf('%s,%s',$new_rdn,$container);
 | 
						|
				$tree->renameEntry($dn,$newdn);
 | 
						|
 | 
						|
				set_cached_item($this->index,'tree','null',$tree);
 | 
						|
 | 
						|
				run_hook('post_entry_rename',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'rdn'=>$new_rdn,'container'=>$container));
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		return $result;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Modify objects
 | 
						|
	 */
 | 
						|
	public function modify($dn,$attrs,$method=null) {
 | 
						|
		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
 | 
						|
			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
 | 
						|
 | 
						|
		# Check our unique attributes.
 | 
						|
		if (! $this->checkUniqueAttrs($dn,$attrs))
 | 
						|
			return false;
 | 
						|
 | 
						|
		$result = false;
 | 
						|
		$summary = array();
 | 
						|
		$current_attrs = $this->getDNAttrValues($dn,$method,LDAP_DEREF_NEVER,array('*'));
 | 
						|
 | 
						|
		# Go through our attributes and call our hooks for each attribute changing its value
 | 
						|
		foreach ($attrs as $attr => $values) {
 | 
						|
			# For new attributes
 | 
						|
			if (count($values) && ! isset($current_attrs[$attr])) {
 | 
						|
				if (! run_hook('pre_attr_add',
 | 
						|
					array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'newvalue'=>$values))) {
 | 
						|
 | 
						|
					unset($attrs[$attr]);
 | 
						|
					system_message(array(
 | 
						|
						'title'=>('Attribute not added'),
 | 
						|
						'body'=>sprintf('%s (<b>%s</b>)',('Hook pre_attr_add prevented attribute from being added'),$attr),
 | 
						|
						'type'=>'warn'));
 | 
						|
 | 
						|
				} else
 | 
						|
					$summary['add'][$attr]['new'] = $values;
 | 
						|
 | 
						|
			# For modify attributes
 | 
						|
			} elseif (count($values)) {
 | 
						|
				if (! run_hook('pre_attr_modify',
 | 
						|
					array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'oldvalue'=>$current_attrs[$attr],'newvalue'=>$values))) {
 | 
						|
 | 
						|
					unset($attrs[$attr]);
 | 
						|
					system_message(array(
 | 
						|
						'title'=>('Attribute not modified'),
 | 
						|
						'body'=>sprintf('%s (<b>%s</b>)',('Hook pre_attr_modify prevented attribute from being modified'),$attr),
 | 
						|
						'type'=>'warn'));
 | 
						|
 | 
						|
				} else {
 | 
						|
					$summary['modify'][$attr]['new'] = $values;
 | 
						|
					$summary['modify'][$attr]['old'] = $current_attrs[$attr];
 | 
						|
				}
 | 
						|
 | 
						|
			# For delete attributes
 | 
						|
			} else {
 | 
						|
				if (! run_hook('pre_attr_delete',
 | 
						|
					array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'oldvalue'=>$current_attrs[$attr]))) {
 | 
						|
 | 
						|
					unset($attrs[$attr]);
 | 
						|
					system_message(array(
 | 
						|
						'title'=>('Attribute not deleted'),
 | 
						|
						'body'=>sprintf('%s (<b>%s</b>)',('Hook pre_attr_delete prevented attribute from being deleted'),$attr),
 | 
						|
						'type'=>'warn'));
 | 
						|
 | 
						|
				} else
 | 
						|
					$summary['delete'][$attr]['old'] = $current_attrs[$attr];
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if (! count($attrs))
 | 
						|
			return false;
 | 
						|
 | 
						|
		if (run_hook('pre_entry_modify',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attrs'=>$attrs))) {
 | 
						|
			$result = @ldap_modify($this->connect($method),$dn,$attrs);
 | 
						|
 | 
						|
			if ($result) {
 | 
						|
				run_hook('post_entry_modify',array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attrs'=>$attrs));
 | 
						|
 | 
						|
				foreach (array('add','modify','delete') as $mode)
 | 
						|
					if (isset($summary[$mode]))
 | 
						|
						foreach ($summary[$mode] as $attr => $values)
 | 
						|
							switch ($mode) {
 | 
						|
								case 'add':
 | 
						|
									run_hook(sprintf('post_attr_%s',$mode),
 | 
						|
										array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'newvalue'=>$values['new']));
 | 
						|
									break;
 | 
						|
 | 
						|
								case 'modify':
 | 
						|
									run_hook(sprintf('post_attr_%s',$mode),
 | 
						|
										array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'oldvalue'=>$values['old'],'newvalue'=>$values['new']));
 | 
						|
									break;
 | 
						|
 | 
						|
								case 'delete':
 | 
						|
									run_hook(sprintf('post_attr_%s',$mode),
 | 
						|
										array('server_id'=>$this->index,'method'=>$method,'dn'=>$dn,'attr'=>$attr,'oldvalue'=>$values['old']));
 | 
						|
									break;
 | 
						|
 | 
						|
								default:
 | 
						|
									debug_dump_backtrace(sprintf('Unkown mode %s',$mode),1);
 | 
						|
							}
 | 
						|
			} else {
 | 
						|
				system_message(array(
 | 
						|
					'title'=>_('Could not perform ldap_modify operation.'),
 | 
						|
					'body'=>ldap_error_msg($this->getErrorMessage($method),$this->getErrorNum($method)),
 | 
						|
					'type'=>'error'));
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		return $result;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Returns true if the specified attribute is configured as unique
 | 
						|
	 * in config.php.
 | 
						|
	 * Attributes are configured as hidden in config.php thus:
 | 
						|
	 * <code>
 | 
						|
	 *	$servers->setValue('unique','attrs',array('mail','uid','uidNumber'));
 | 
						|
	 * </code>
 | 
						|
	 *
 | 
						|
	 * @param string $attr The name of the attribute to test.
 | 
						|
	 * @return boolean
 | 
						|
	 */
 | 
						|
	public function isAttrUnique($attr) {
 | 
						|
		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
 | 
						|
			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
 | 
						|
 | 
						|
		# Should this attribute value be unique
 | 
						|
		if (in_array_ignore_case($attr,$this->getValue('unique','attrs')))
 | 
						|
			return true;
 | 
						|
		else
 | 
						|
			return false;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * This function will check whether the value for an attribute being changed
 | 
						|
	 * is already assigned to another DN.
 | 
						|
	 *
 | 
						|
	 * Returns the bad value, or null if all values are OK
 | 
						|
	 *
 | 
						|
	 * @param dn DN that is being changed
 | 
						|
	 * @param string Attribute being changed
 | 
						|
	 * @param string|array New values for the attribute
 | 
						|
	 */
 | 
						|
	public function checkUniqueAttrs($dn,$attrs) {
 | 
						|
		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
 | 
						|
			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
 | 
						|
 | 
						|
		# If none of the attributes are defined unique, we'll return immediately;
 | 
						|
		if (! $checkattrs = array_intersect(arrayLower($this->getValue('unique','attrs')),array_keys(array_change_key_case($attrs))))
 | 
						|
			return true;
 | 
						|
 | 
						|
		# Check see and use our alternate uid_dn and password if we have it.
 | 
						|
		if (! $this->login($this->getValue('unique','dn'),$this->getValue('unique','pass'),'unique')) {
 | 
						|
			system_message(array(
 | 
						|
				'title'=>('UNIQUE invalid login/password'),
 | 
						|
				'body'=>sprintf('%s (<b>%s</b>)',('Unable to connect to LDAP server with the unique login/password, please check your configuration.'),
 | 
						|
					$this->getName()),
 | 
						|
				'type'=>'warn'));
 | 
						|
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
 | 
						|
		$query = array();
 | 
						|
 | 
						|
		# Build our search filter to double check each attribute.
 | 
						|
		$query['filter'] = '(|';
 | 
						|
		foreach ($checkattrs as $attr)
 | 
						|
			foreach ($attrs[$attr] as $val)
 | 
						|
				if ($val)
 | 
						|
					$query['filter'] .= sprintf('(%s=%s)',$attr,$val);
 | 
						|
		$query['filter'] .= ')';
 | 
						|
 | 
						|
		$query['attrs'] = $checkattrs;
 | 
						|
 | 
						|
		# Search through our bases and see if we have match
 | 
						|
		foreach ($this->getBaseDN() as $base) {
 | 
						|
			$query['base'] = $base;
 | 
						|
 | 
						|
			# Do the search
 | 
						|
			$results = $this->query($query,'unique');
 | 
						|
 | 
						|
			# If we have a match.
 | 
						|
			if (count($results))
 | 
						|
				foreach ($results as $values)
 | 
						|
					# If one of the attributes is owned to somebody else, then we may as well die here.
 | 
						|
					if ($values['dn'] != $dn) {
 | 
						|
						$href = sprintf('cmd.php?cmd=query_engine&server_id=%s&filter=%s&scope=sub&query=none&format=list&search=true',$this->index,$query['filter']);
 | 
						|
 | 
						|
						system_message(array(
 | 
						|
							'title'=>('Attribute value would not be unique'),
 | 
						|
							'body'=>sprintf('%s (<b><a href="%s">%s</a></b>)',
 | 
						|
								('This update has been or will be cancelled, it would result in an attribute value not being unique. You might like to search the LDAP server for the offending entry.'),
 | 
						|
								htmlspecialchars($href),
 | 
						|
								_('Search')),
 | 
						|
							'type'=>'warn'));
 | 
						|
 | 
						|
						return false;
 | 
						|
					}
 | 
						|
		}
 | 
						|
 | 
						|
		# If we get here, then it must be OK?
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Check if the session timeout has occured for this LDAP server.
 | 
						|
	 */
 | 
						|
	public function isSessionValid() {
 | 
						|
		if (DEBUG_ENABLED && (($fargs=func_get_args())||$fargs='NOARGS'))
 | 
						|
			debug_log('Entered (%%)',17,0,__FILE__,__LINE__,__METHOD__,$fargs);
 | 
						|
 | 
						|
		# If inactiveTime() returns a value, we need to check that it has not expired.
 | 
						|
		if (is_null($this->inactivityTime()) || ! $this->isLoggedIn())
 | 
						|
			return true;
 | 
						|
 | 
						|
		# If session has expired
 | 
						|
		if ((isset($_SESSION['ACTIVITY'][$this->getIndex()])) && ($_SESSION['ACTIVITY'][$this->getIndex()] < time())) {
 | 
						|
			$this->logout();
 | 
						|
			unset($_SESSION['ACTIVITY'][$this->getIndex()]);
 | 
						|
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
 | 
						|
		$_SESSION['ACTIVITY'][$this->getIndex()] = $this->inactivityTime();
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
}
 | 
						|
?>
 |