/** * Writes a DN to the filehandle * * @param string $dn DN to write * * @access private * @return void */ function _writeDN($dn) { // prepare DN if ($this->_options['encode'] == 'base64') { $dn = $this->_convertDN($dn) . PHP_EOL; } elseif ($this->_options['encode'] == 'canonical') { $dn = Net_LDAP_Util::canonical_dn($dn, array('casefold' => 'none')) . PHP_EOL; } else { $dn = $dn . PHP_EOL; } $this->_writeLine($dn, 'Net_LDAP_LDIF error: unable to write DN of entry ' . $this->_entrynum); }
/** * Undoes the conversion done by {@link escape_filter_value()}. * * Converts any sequences of a backslash followed by two hex digits into the corresponding character. * * @static * @param array $values Array of values to escape * @return array Array $values, but unescaped */ function unescape_filter_value($values = array()) { // Parameter validation if (!is_array($values)) { $values = array($values); } foreach ($values as $key => $value) { // Translate hex code into ascii $values[$key] = Net_LDAP_Util::hex2asc($value); } return $values; }
/** * This can be used to escape a string to provide a valid LDAP-Filter. * * LDAP will only recognise certain characters as the * character istself if they are properly escaped. This is * what this method does. * The method can be called statically, so you can use it outside * for your own purposes (eg for escaping only parts of strings) * * In fact, this is just a shorthand to {@link Net_LDAP_Util::escape_filter_value()}. * For upward compatibiliy reasons you are strongly encouraged to use the escape * methods provided by the Net_LDAP_Util class. * * @param string $value Any string who should be escaped * * @static * @return string The string $string, but escaped * @deprecated Do not use this method anymore, instead use Net_LDAP_Util::escape_filter_value() directly */ function escape($value) { $return = Net_LDAP_Util::escape_filter_value(array($value)); return $return[0]; }
/** * Execute a LDAP query stement and fetch all results. * * @param mixed $query The SQL query as a string or an array. * @param string $configPath The config path; used for exception messages. * * @return array An array of records. * @throws XML_Query2XML_LDAPException If Net_LDAP::search() returns an error. * @see XML_Query2XML_Driver::getAllRecords() */ public function getAllRecords($query, $configPath) { $base = null; $filter = null; $options = array(); if (isset($query['base'])) { $base = $query['base']; } if (isset($query['filter'])) { $filter = $query['filter']; } if (isset($query['options'])) { $options = $query['options']; } if (isset($options['query2xml_placeholder'])) { $placeholder = $options['query2xml_placeholder']; } else { $placeholder = '?'; } unset($options['query2xml_placeholder']); if (isset($query['data']) && is_array($query['data'])) { $data = Net_LDAP_Util::escape_filter_value($query['data']); $base = self::_replacePlaceholders($base, $data, $placeholder); if (is_string($filter)) { $filter = self::_replacePlaceholders($filter, $data, $placeholder); } } $search = $this->_ldap->search($base, $filter, $options); if (PEAR::isError($search)) { /* * unit test: getXML/throwLDAPException_queryError.phpt */ throw new XML_Query2XML_LDAPException($configPath . ': Could not run LDAP search query: ' . $search->toString()); } $records = array(); $entries = $search->entries(); foreach ($entries as $key => $entry) { $records[] = $entry->getValues(); } $search->done(); $records = self::_processMultiValueAttributes($records); // set missing attriubtes to null if (isset($options['attributes']) && is_array($options['attributes'])) { foreach ($options['attributes'] as $attribute) { for ($i = 0; $i < count($records); $i++) { if (!array_key_exists($attribute, $records[$i])) { $records[$i][$attribute] = null; } } } } return $records; }
/** * Update the entry on the directory server * * @access public * @param Net_LDAP $ldap (optional) If you provide a Net_LDAP object, be sure to PASS IT VIA REFERENCE! * @return true|Net_LDAP_Error * @todo Entry rename with a DN containing special characters needs testing! */ function update($ldap = false) { if (!$ldap) { // If object is not provided, then use this entrys ldap object $ldap =& $this->_ldap; } else { if (!is_a($ldap, 'Net_LDAP')) { $ldap = false; // throw error } else { // store the provided ldap object internally, if we haven't got one already if (!$this->_ldap) { $this->_ldap =& $ldap; } } } // ensure we have a valid LDAP object if (!is_a($ldap, 'Net_LDAP')) { return PEAR::raiseError("Need a Net_LDAP object as parameter"); } $link = $ldap->getLink(); /* * Delete the entry */ if (true === $this->_delete) { return $ldap->delete($this); } /* * New entry */ if (true === $this->_new) { $msg = $ldap->add($this); if (Net_LDAP::isError($msg)) { return $msg; } $this->_new = false; $this->_changes['add'] = array(); $this->_changes['delete'] = array(); $this->_changes['replace'] = array(); $this->_original = $this->_attributes; $return = true; return $return; } /* * Rename/move entry */ if (false == is_null($this->_newdn)) { if ($ldap->getLDAPVersion() !== 3) { return PEAR::raiseError("Renaming/Moving an entry is only supported in LDAPv3"); } // make dn relative to parent (needed for ldap rename) $parent = Net_LDAP_Util::ldap_explode_dn($this->_newdn, array('casefolding' => 'none', 'reverse' => false, 'onlyvalues' => false)); if (Net_LDAP::isError($parent)) { return $parent; } $child = array_shift($parent); // maybe the dn consist of a multivalued RDN, we must build the dn in this case // because the $child-RDN is an array! if (is_array($child)) { $child = Net_LDAP_Util::canonical_dn($child); } $parent = Net_LDAP_Util::canonical_dn($parent); // rename if (false == @ldap_rename($link, $this->_dn, $child, $parent, true)) { return PEAR::raiseError("Entry not renamed: " . @ldap_error($link), @ldap_errno($link)); } // reflect changes to local copy $this->_dn = $this->_newdn; $this->_newdn = null; } /* * Carry out modifications to the entry */ // ADD foreach ($this->_changes["add"] as $attr => $value) { // if attribute exists, add new values if ($this->exists($attr)) { if (false === @ldap_mod_add($link, $this->dn(), array($attr => $value))) { return PEAR::raiseError("Could not add new values to attribute {$attr}: " . @ldap_error($link), @ldap_errno($link)); } } else { // new attribute if (false === @ldap_modify($link, $this->dn(), array($attr => $value))) { return PEAR::raiseError("Could not add new attribute {$attr}: " . @ldap_error($link), @ldap_errno($link)); } } // all went well here, I guess unset($this->_changes["add"][$attr]); } // DELETE foreach ($this->_changes["delete"] as $attr => $value) { // In LDAPv3 you need to specify the old values for deleting if (is_null($value) && $ldap->getLDAPVersion() === 3) { $value = $this->_original[$attr]; } if (false === @ldap_mod_del($link, $this->dn(), array($attr => $value))) { return PEAR::raiseError("Could not delete attribute {$attr}: " . @ldap_error($link), @ldap_errno($link)); } unset($this->_changes["delete"][$attr]); } // REPLACE foreach ($this->_changes["replace"] as $attr => $value) { if (false === @ldap_modify($link, $this->dn(), array($attr => $value))) { return PEAR::raiseError("Could not replace attribute {$attr} values: " . @ldap_error($link), @ldap_errno($link)); } unset($this->_changes["replace"][$attr]); } // all went well, so _original (server) becomes _attributes (local copy) $this->_original = $this->_attributes; $return = true; return $return; }
/** * Tell if a DN does exist in the directory * * @param string $dn The DN of the object to test * * @return boolean|Net_LDAP_Error */ function dnExists($dn) { if (!is_string($dn)) { return PEAR::raiseError('$dn is expected to be a string but is ' . gettype($dn) . ' ' . get_class($dn)); } // make dn relative to parent $base = Net_LDAP_Util::ldap_explode_dn($dn, array('casefold' => 'none', 'reverse' => false, 'onlyvalues' => false)); if (Net_LDAP::isError($base)) { return $base; } $entry_rdn = array_shift($base); if (is_array($entry_rdn)) { // maybe the dn consist of a multivalued RDN, we must build the dn in this case // because the $entry_rdn is an array! $filter_dn = Net_LDAP_Util::canonical_dn($entry_rdn); } $base = Net_LDAP_Util::canonical_dn($base); $result = @ldap_list($this->_link, $base, $entry_rdn, array(), 1, 1); if (@ldap_count_entries($this->_link, $result)) { return true; } if (ldap_errno($this->_link) == 32) { return false; } if (ldap_errno($this->_link) != 0) { return PEAR::raiseError(ldap_error($this->_link), ldap_errno($this->_link)); } return false; }
/** * Split an multivalued RDN value into an Array * * A RDN can contain multiple values, spearated by a plus sign. * This function returns each separate ocl=value pair of the RDN part. * * If no multivalued RDN is detected, a array containing only * the original rdn part is returned. * * For example, the multivalued RDN 'OU=Sales+CN=J. Smith' is exploded to: * <kbd>array([0] => 'OU=Sales', [1] => 'CN=J. Smith')</kbd> * * The method trys to be smart if it encounters unescaped "+" characters, but may fail, * so ensure escaped "+"es in attr names and attr values. * * [BUG] If you use string mode and have a multivalued RDN with unescaped plus characters * and there is a unescaped plus sign at the end of an value followed by an * attribute name containing an unescaped plus, then you will get wrong splitting: * $rdn = 'OU=Sales+C+N=J. Smith'; * returns: * array('OU=Sales+C', 'N=J. Smith'); * The "C+" is treaten as value of the first pair instead as attr name of the second pair. * To prevent this, escape correctly. * * @param string $rdn Part of an (multivalued) escaped RDN (eg. ou=foo OR ou=foo+cn=bar) * * @static * @return array Array with the components of the multivalued RDN or Error */ function split_rdn_multival($rdn) { $rdns = preg_split('/(?<!\\\\)\\+/', $rdn); $rdns = Net_LDAP_Util::_correct_dn_splitting($rdns, '+'); return array_values($rdns); }
/** * Tell if a dn already exists * * @param string $dn The DN of the object to test * @return boolean */ function dnExists($dn) { // make dn relative to parent $base = Net_LDAP_Util::ldap_explode_dn($this->_newdn, array('casefolding' => 'none', 'reverse' => false, 'onlyvalues' => false)); if (Net_LDAP::isError($base)) { return $base; } $filter = array_shift($base); // maybe the dn consist of a multivalued RDN, we must build the dn in this case // because the $child-RDN is an array! if (is_array($filter)) { $filter = Net_LDAP_Util::canonical_dn($filter); } $base = Net_LDAP_Util::canonical_dn($base); $result = @ldap_list($this->_link, $base, $filter, array(), 1, 1); if (ldap_errno($this->_link) == 32) { $return = false; return $return; } if (ldap_errno($this->_link) != 0) { PEAR::raiseError(ldap_error($this->_link), ldap_errno($this->_link)); } if (@ldap_count_entries($this->_link, $result)) { $return = true; return $return; } $return = false; return $return; }