David R. David R. - 1 month ago 17
PHP Question

How to move an eDirectory entry via php?

I have this ldap entry:

cn=blah,ou=apples,ou=people,dc=yay,dc=edu


I need to move that entry to:

cn=blah,ou=oranges,ou=people,dc=yay,dc=edu


My scripts are all PHP so I've been trying to use php.net/ldap_rename

ldap_rename($connection, "cn=blah,ou=apples,ou=people,dc=yay,dc=edu", "cn=blah", "ou=oranges,ou=people,dc=yay,dc=edu", true);


Does not work. It returns false.

This http://us2.php.net/manual/en/function.ldap-rename.php#82393 comment mentions that eDirectory wants to leave the parent as NULL. Like:

ldap_rename($connection, "cn=blah,ou=apples,ou=people,dc=yay,dc=edu", "cn=blah", NULL, true);


That returns TRUE but does not actually move the entry. Not surprising since it's not changing the parent... I'm sure it could change the cn=blah to something else...

I have thought of deleting the entry and recreating it. But that's a painful way to go about it. Writing out and running a LDIF file would also be painful.

So, how do I move an entry from one OU to another, in php, without the pain of my other two options?

What I'm running:


  • Ubuntu 12.04 LTS

  • PHP 5.3.10

  • eDirectory 8.8 is on SLES 11



Edit



So, I found this:


The modrdn change type cannot move an entry to a completely different subtree. To move an entry to a completely different branch, you must create a new entry in the alternative subtree using the old entry's attributes, and then delete the old entry.


From http://www.centos.org/docs/5/html/CDS/ag/8.0/Creating_Directory_Entries-LDIF_Update_Statements.html

I found a couple other pages with similar statements.

So it sounds like I have to make a new entry, copying the attributes, the delete the old one. Like the second painful option I mentioned above.

Answer

Well, I ended up using the "create new entry, delete old one" method. I still think I had another way working a while back, but I can't remember what. So here's a basic move function.

function move($connection, $ldapEntryReference, $new_dn){        
    //First, get the values of the current attributes.
    $attributes = array(); //start attributes array
    $firstattr = ldap_first_attribute($connection, $ldapEntryReference);
    $value = ldap_get_values($connection, $ldapEntryReference, $firstattr);
    $attributes[$firstattr] = $value;
    while($attr = ldap_next_attribute($connection, $ldapEntryReference)) {
        if (strcasecmp($attr, 'ACL') !== 0) { //We don't want ACL attributes since 
                                              //eDir/ldap should deal with them for us.
            if (strcasecmp($attr, 'jpegPhoto') === 0) {
                //binary values need to use the ldap_get_values_len function.
                $value = ldap_get_values_len($this->connection, $ldapEntryReference, $attr);
            } else {
                $value = ldap_get_values($this->connection, $ldapEntryReference, $attr);
            }
            $attributes[$attr] = $value;
        }
    }
    //Create a new entry array with the values.
    $entry = array(); //start entry array.
    foreach($attributes as $key => $value) {
        foreach($value as $key2 => $value2) {
            if (strcasecmp($key2, 'count') !== 0) {//get rid of 'count' indexes
                                                   //ldap_add chokes on them.
                $entry[$key][$key2] = $value2;
            }
        }
    }
    //Add the new entry.
    if (ldap_add($connection, $new_dn, $entry)) {
        //Delete the old entry.
        if (ldap_delete($connection, ldap_get_dn($connection, $ldapEntryReference)) {
            return true;
        } else {
            return false;
        }
    } else {
        return false; 
    }
}

Hopefully this helps someone, sometime.

Comments