private function _list_group_members($dn, $entry, $attr, $count)
    {
        // Use the member attributes to return an array of member ldap objects
        // NOTE that the member attribute is supposed to contain a DN
        $group_members = array();
        if (empty($entry[$attr])) {
            return $group_members;
        }

        // read these attributes for all members
        $attrib = $count ? array('dn','objectClass') : $this->prop['list_attributes'];
        $attrib = array_merge($attrib, array_values($this->group_types));
        $attrib[] = 'memberURL';

        $filter = $this->prop['groups']['member_filter'] ?: '(objectclass=*)';

        for ($i=0; $i < $entry[$attr]['count']; $i++) {
            if (empty($entry[$attr][$i]))
                continue;

            $members = $this->ldap->read_entries($entry[$attr][$i], $filter, $attrib);
            if ($members == false) {
                $members = array();
            }

            // for nested groups, call recursively
            $nested_group_members = $this->list_group_members($entry[$attr][$i], $count, $members);

            unset($members['count']);
            $group_members = array_merge($group_members, array_filter($members), $nested_group_members);
        }

        return $group_members;
    }