/** * Add a set of authentication credentials. * * @param string $userId The userId to add. * @param array $credentials The credentials to be set. * * @throws Horde_Auth_Exception */ public function addUser($userId, $credentials) { if (!empty($this->_params['ad'])) { throw new Horde_Auth_Exception(__CLASS__ . ': Adding users is not supported for Active Directory.'); } if (isset($credentials['ldap'])) { $entry = $credentials['ldap']; $dn = $entry['dn']; /* Remove the dn entry from the array. */ unset($entry['dn']); } else { /* Try this simple default and hope it works. */ $dn = $this->_params['uid'] . '=' . $userId . ',' . $this->_params['basedn']; $entry['cn'] = $userId; $entry['sn'] = $userId; $entry[$this->_params['uid']] = $userId; $entry['objectclass'] = array_merge(array('top'), $this->_params['newuser_objectclass']); $entry['userPassword'] = Horde_Auth::getCryptedPassword($credentials['password'], '', $this->_params['encryption'], 'true'); if ($this->_params['password_expiration'] == 'yes') { $entry['shadowMin'] = $this->_params['minage']; $entry['shadowMax'] = $this->_params['maxage']; $entry['shadowWarning'] = $this->_params['warnage']; $entry['shadowLastChange'] = floor(time() / 86400); } } try { $this->_ldap->add(Horde_Ldap_Entry::createFresh($dn, $entry)); } catch (Horde_Ldap_Exception $e) { throw new Horde_Auth_Exception(sprintf(__CLASS__ . ': Unable to add user "%s". This is what the server said: ', $userId) . $e->getMessage()); } }
/** * Parses the schema of the given subschema entry. * * @param Horde_Ldap_Entry $entry Subschema entry. */ public function parse($entry) { foreach ($this->types as $type => $attr) { // Initialize map type to entry. $type_var = '_' . $attr; $this->{$type_var} = array(); if (!$entry->exists($attr)) { continue; } // Get values for this type. $values = $entry->getValue($attr); if (!is_array($values)) { continue; } foreach ($values as $value) { // 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']; $names[] = $schema_entry['name']; foreach ($names as $name) { $this->{$type_var}[Horde_String::lower($name)] = $schema_entry; } } } $this->_initialized = true; }
/** * Add new object data. * * @param Horde_Kolab_Server_Object $object The object to be added. * @param array $data The attributes of the object * to be added. * * @return NULL * * @throws Horde_Kolab_Server_Exception */ public function add(Horde_Kolab_Server_Object_Interface $object, array $data) { try { $entry = Horde_Ldap_Entry::createFresh($object->getGuid(), $data); $this->_conn->getWrite()->add($entry); } catch (Horde_Ldap_Exception $e) { throw new Horde_Kolab_Server_Exception('Adding object failed!', Horde_Kolab_Server_Exception::SYSTEM, $e); } }
/** * Copies an entry to a new location. * * The entry will be immediately copied. Only attributes you have * selected will be copied. * * @param Horde_Ldap_Entry $entry An LDAP entry. * @param string $newdn New FQF-DN of the entry. * * @return Horde_Ldap_Entry The copied entry. * @throws Horde_Ldap_Exception */ public function copy($entry, $newdn) { if (!$entry instanceof Horde_Ldap_Entry) { throw new Horde_Ldap_Exception('Parameter $entry is expected to be a Horde_Ldap_Entry object'); } $newentry = Horde_Ldap_Entry::createFresh($newdn, $entry->getValues()); $this->add($newentry); return $newentry; }
/** * Get the next entry from the search result. * * This will return a valid Horde_Ldap_Entry object or false, so you can * use this method to easily iterate over the entries inside a while loop. * * @return Horde_Ldap_Entry|false Reference to Horde_Ldap_Entry object or * false if no more entries exist. * @throws Horde_Ldap_Exception */ public function shiftEntry() { if (is_null($this->_entry)) { if (!($this->_entry = @ldap_first_entry($this->_link, $this->_search))) { return false; } $entry = Horde_Ldap_Entry::createConnected($this->_ldap, $this->_entry); } else { if (!($this->_entry = @ldap_next_entry($this->_link, $this->_entry))) { return false; } $entry = Horde_Ldap_Entry::createConnected($this->_ldap, $this->_entry); } return $entry; }
/** * Tests SPL iterator. */ public function testSPLIterator() { $ldap = new Horde_Ldap(self::$ldapcfg['server']); // Some testdata, so we have some entries to search for. $base = self::$ldapcfg['server']['basedn']; $ou1 = Horde_Ldap_Entry::createFresh('ou=Horde_Ldap_Test_search1,' . $base, array('objectClass' => array('top', 'organizationalUnit'), 'ou' => 'Horde_Ldap_Test_search1')); $ou2 = Horde_Ldap_Entry::createFresh('ou=Horde_Ldap_Test_search2,' . $base, array('objectClass' => array('top', 'organizationalUnit'), 'ou' => 'Horde_Ldap_Test_search2')); $ldap->add($ou1); $this->assertTrue($ldap->exists($ou1->dn())); $ldap->add($ou2); $this->assertTrue($ldap->exists($ou2->dn())); /* Search and test each method. */ $search = $ldap->search(null, '(ou=Horde_Ldap*)'); $this->assertInstanceOf('Horde_Ldap_Search', $search); $this->assertEquals(2, $search->count()); // current() is supposed to return first valid element. $e1 = $search->current(); $this->assertInstanceOf('Horde_Ldap_Entry', $e1); $this->assertEquals($e1->dn(), $search->key()); $this->assertTrue($search->valid()); // Shift to next entry. $search->next(); $e2 = $search->current(); $this->assertInstanceOf('Horde_Ldap_Entry', $e2); $this->assertEquals($e2->dn(), $search->key()); $this->assertTrue($search->valid()); // Shift to non existent third entry. $search->next(); $this->assertFalse($search->current()); $this->assertFalse($search->key()); $this->assertFalse($search->valid()); // Rewind and test, which should return the first entry a second time. $search->rewind(); $e1_1 = $search->current(); $this->assertInstanceOf('Horde_Ldap_Entry', $e1_1); $this->assertEquals($e1_1->dn(), $search->key()); $this->assertTrue($search->valid()); $this->assertEquals($e1->dn(), $e1_1->dn()); // Don't rewind but call current, should return first entry again. $e1_2 = $search->current(); $this->assertInstanceOf('Horde_Ldap_Entry', $e1_2); $this->assertEquals($e1_2->dn(), $search->key()); $this->assertTrue($search->valid()); $this->assertEquals($e1->dn(), $e1_2->dn()); // Rewind again and test, which should return the first entry a third // time. $search->rewind(); $e1_3 = $search->current(); $this->assertInstanceOf('Horde_Ldap_Entry', $e1_3); $this->assertEquals($e1_3->dn(), $search->key()); $this->assertTrue($search->valid()); $this->assertEquals($e1->dn(), $e1_3->dn()); /* Try methods on empty search result. */ $search = $ldap->search(null, '(ou=Horde_LdapTest_NotExistentEntry)'); $this->assertInstanceOf('Horde_Ldap_Search', $search); $this->assertEquals(0, $search->count()); $this->assertFalse($search->current()); $this->assertFalse($search->key()); $this->assertFalse($search->valid()); $search->next(); $this->assertFalse($search->current()); $this->assertFalse($search->key()); $this->assertFalse($search->valid()); /* Search and simple iterate through the test entries. Then, rewind * and do it again several times. */ $search2 = $ldap->search(null, '(ou=Horde_Ldap*)'); $this->assertInstanceOf('Horde_Ldap_Search', $search2); $this->assertEquals(2, $search2->count()); for ($i = 0; $i <= 5; $i++) { $counter = 0; foreach ($search2 as $dn => $entry) { $counter++; // Check on type. $this->assertInstanceOf('Horde_Ldap_Entry', $entry); // Check on key. $this->assertThat(strlen($dn), $this->greaterThan(1)); $this->assertEquals($dn, $entry->dn()); } $this->assertEquals($search2->count(), $counter, "Failed at loop {$i}"); // Revert to start. $search2->rewind(); } }
public function testCreateFreshSuccess() { $entry = Horde_Ldap_Entry::createFresh('cn=test', array('attr1' => 'single', 'attr2' => array('mv1', 'mv2'))); $this->assertInstanceOf('Horde_Ldap_Entry', $entry); }
/** * Tests if entry changes are correctly written. */ public function testWriteEntryChanges() { $testentries = $this->_testentries; $testentries[] = Horde_Ldap_Entry::createFresh('cn=foo,ou=example,dc=cno', array('cn' => 'foo')); $testentries[] = Horde_Ldap_Entry::createFresh('cn=footest,ou=example,dc=cno', array('cn' => 'foo')); $testconf = $this->_defaultConfig; $testconf['change'] = 1; /* No changes should produce empty file. */ $ldif = new Horde_Ldap_Ldif($this->_outfile, 'w', $testconf); $this->assertTrue(is_resource($ldif->handle())); $ldif->writeEntry($testentries); $ldif->done(); $this->assertEquals(array(), file($this->_outfile)); /* Changes test. */ // Prepare some changes. $testentries[0]->delete('attr1'); $testentries[0]->delete(array('attr2' => 'baz')); $testentries[0]->delete(array('attr4', 'attr3' => 'bar')); // Prepare some replaces and adds. $testentries[2]->replace(array('attr1' => 'newvaluefor1')); $testentries[2]->replace(array('attr2' => array('newvalue1for2', 'newvalue2for2'))); $testentries[2]->replace(array('attr3' => '')); $testentries[2]->replace(array('newattr' => 'foo')); // Delete whole entry. $testentries[3]->delete(); // Rename and move. $testentries[4]->dn('cn=Bar,ou=example,dc=cno'); $testentries[5]->dn('cn=foobartest,ou=newexample,dc=cno'); // Carry out write. $ldif = new Horde_Ldap_Ldif($this->_outfile, 'w', $testconf); $this->assertTrue(is_resource($ldif->handle())); $ldif->writeEntry($testentries); $ldif->done(); // Compare results. $expected = array_map(array($this, '_lineend'), file(__DIR__ . '/fixtures/changes.ldif')); // Strip 4 starting lines because of comments in the file header. array_splice($expected, 0, 4); $this->assertEquals($expected, file($this->_outfile)); }
/** * Test copy(). */ public function testCopy() { $ldap = new Horde_Ldap(self::$ldapcfg['server']); // Some testdata. $base = self::$ldapcfg['server']['basedn']; $ou1 = Horde_Ldap_Entry::createFresh('ou=Horde_Ldap_Test_pool,' . $base, array('objectClass' => array('top', 'organizationalUnit'), 'ou' => 'Horde_Ldap_Test_copy')); $ou2 = Horde_Ldap_Entry::createFresh('ou=Horde_Ldap_Test_tgt,' . $base, array('objectClass' => array('top', 'organizationalUnit'), 'ou' => 'Horde_Ldap_Test_copy')); $ldap->add($ou1); $this->assertTrue($ldap->exists($ou1->dn())); $ldap->add($ou2); $this->assertTrue($ldap->exists($ou2->dn())); $entry = Horde_Ldap_Entry::createFresh('l=cptest,' . $ou1->dn(), array('objectClass' => array('top', 'locality'), 'l' => 'cptest')); $ldap->add($entry); $ldap->exists($entry->dn()); // Copy over the entry to another tree with rename. $entrycp = $ldap->copy($entry, 'l=test_copied,' . $ou2->dn()); $this->assertInstanceOf('Horde_Ldap_Entry', $entrycp); $this->assertNotEquals($entry->dn(), $entrycp->dn()); $this->assertTrue($ldap->exists($entrycp->dn())); // Copy same again (fails, entry exists). try { $entrycp_f = $ldap->copy($entry, 'l=test_copied,' . $ou2->dn()); $this->fail('Horde_Ldap_Exception expected.'); } catch (Horde_Ldap_Exception $e) { } // Use only DNs to copy (fails). try { $entrycp = $ldap->copy($entry->dn(), 'l=test_copied2,' . $ou2->dn()); $this->fail('Horde_Ldap_Exception expected.'); } catch (Horde_Ldap_Exception $e) { } }
/** * Parse LDIF lines of one entry into an Horde_Ldap_Entry object. * * @todo what about file inclusions and urls? * "jpegphoto:< file:///usr/local/directory/photos/fiona.jpg" * * @param array $lines LDIF lines for one entry. * * @return Horde_Ldap_Entry Horde_Ldap_Entry object for those lines. * @throws Horde_Ldap_Exception */ public function parseLines($lines) { // Parse lines into an array of attributes and build the entry. $attributes = array(); $dn = false; foreach ($lines as $line) { if (!preg_match('/^(\\w+)(:|::|:<)\\s(.+)$/', $line, $matches)) { // Line not in "attr: value" format -> ignore. Maybe we should // rise an error here, but this should be covered by // nextLines() already. A problem arises, if users try to feed // data of several entries to this method - the resulting entry // will get wrong attributes. However, this is already // mentioned in the method documentation above. continue; } $attr = $matches[1]; $delim = $matches[2]; $data = $matches[3]; switch ($delim) { case ':': // Normal data. $attributes[$attr][] = $data; break; case '::': // Base64 data. $attributes[$attr][] = base64_decode($data); break; case ':<': // File inclusion // TODO: Is this the job of the LDAP-client or the server? throw new Horde_Ldap_Exception('File inclusions are currently not supported'); default: throw new Horde_Ldap_Exception('Parsing error: invalid syntax at parsing entry line: ' . $line); } if (Horde_String::lower($attr) == 'dn') { // DN line detected. Save possibly decoded DN. $dn = $attributes[$attr][0]; // Remove wrongly added "dn: " attribute. unset($attributes[$attr]); } } if (!$dn) { throw new Horde_Ldap_Exception('Parsing error: unable to detect DN for entry'); } return Horde_Ldap_Entry::createFresh($dn, $attributes); }
/** * Add a new entryobject to a directory. * * @param Horde_Ldap_Entry $entry Horde_Ldap_Entry * * @return Horde_Ldap_Error|true Horde_Ldap_Error object or true */ public function add($entry) { $this->_checkBound(); $ldap_data = $this->toStorage($entry->getValues()); $guid = $entry->getDn(); $this->_data[$guid] = array('dn' => $guid, 'data' => array_merge($ldap_data, array('dn' => $guid))); }
/** * Creates a new group. * * @param string $name A group name. * @param array $attributes The group's attributes. * * @return mixed The ID of the created group. * @throws Horde_Group_Exception */ protected function _create($name, array $attributes) { $dn = Horde_Ldap::quoteDN(array(array($this->_params['gid'], $name))) . ',' . $this->_params['basedn']; try { $entry = Horde_Ldap_Entry::createFresh($dn, $attributes); $this->_rebind(true); $this->_ldap->add($entry); $this->_rebind(false); return $dn; } catch (Horde_Ldap_Exception $e) { throw new Horde_Group_Exception($e); } }
/** * Creates a new group. * * @param string $name A group name. * @param string $email The group's email address. * * @return mixed The ID of the created group. * @throws Horde_Group_Exception */ protected function _create($name, $email = null) { if ($this->readOnly()) { throw new Horde_Group_Exception('This group backend is read-only.'); } $attributes = array($this->_params['gid'] => $name, 'objectclass' => $this->_params['newgroup_objectclass'], 'gidnumber' => $this->_nextGid()); if (!empty($email)) { $attributes['mail'] = $email; } $dn = Horde_Ldap::quoteDN(array(array($this->_params['gid'], $name))) . ',' . $this->_params['basedn']; try { $entry = Horde_Ldap_Entry::createFresh($dn, $attributes); $this->_rebind(true); $this->_ldap->add($entry); $this->_rebind(false); } catch (Horde_Ldap_Exception $e) { throw new Horde_Group_Exception($e); } return $dn; }