summaryrefslogtreecommitdiff
path: root/php-kolab/Kolab_Server/mapping.patch
diff options
context:
space:
mode:
authorGunnar Wrobel <wrobel@pardus.de>2009-04-23 06:32:38 (GMT)
committerGunnar Wrobel <wrobel@pardus.de>2009-04-23 06:32:38 (GMT)
commit74fc84529fa8c943fc4a244c89d66bbafc9d8129 (patch)
treef6793fea5120c00c6d803f870103b9ba5449ff1a /php-kolab/Kolab_Server/mapping.patch
parent18f30b5b90cdfe12ef2df1f0b0c12723a6257d05 (diff)
downloadserver-74fc84529fa8c943fc4a244c89d66bbafc9d8129.tar.gz
Support for configurable mapping of LDAP attributes.
Diffstat (limited to 'php-kolab/Kolab_Server/mapping.patch')
-rw-r--r--php-kolab/Kolab_Server/mapping.patch791
1 files changed, 791 insertions, 0 deletions
diff --git a/php-kolab/Kolab_Server/mapping.patch b/php-kolab/Kolab_Server/mapping.patch
new file mode 100644
index 0000000..3f19ab5
--- /dev/null
+++ b/php-kolab/Kolab_Server/mapping.patch
@@ -0,0 +1,791 @@
+diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server.php b/framework/Kolab_Server/lib/Horde/Kolab/Server.php
+index 941cbe6..4d77f11 100644
+--- a/framework/Kolab_Server/lib/Horde/Kolab/Server.php
++++ b/framework/Kolab_Server/lib/Horde/Kolab/Server.php
+@@ -159,9 +159,12 @@ class Horde_Kolab_Server {
+ $driver = 'ldap';
+
+ $server_params = array('server' => $conf['kolab']['ldap']['server'],
+- 'base_dn' => $conf['kolab']['ldap']['basedn'],
+- 'uid' => $conf['kolab']['ldap']['phpdn'],
+- 'pass' => $conf['kolab']['ldap']['phppw']);
++ 'base_dn' => $conf['kolab']['ldap']['basedn'],
++ 'uid' => $conf['kolab']['ldap']['phpdn'],
++ 'pass' => $conf['kolab']['ldap']['phppw']);
++ if (isset($conf['kolab']['ldap']['map'])) {
++ $server_params['map'] = $conf['kolab']['ldap']['map'];
++ }
+ } else {
+ $driver = null;
+ $server_params = array();
+@@ -473,7 +476,7 @@ class Horde_Kolab_Server {
+ function uidForId($id,
+ $restrict = KOLAB_SERVER_RESULT_SINGLE)
+ {
+- return $this->uidForAttr('uid', $id);
++ return $this->uidForAttr(KOLAB_ATTR_SID, $id);
+ }
+
+ /**
+@@ -513,7 +516,7 @@ class Horde_Kolab_Server {
+ */
+ function uidForIdOrMail($id)
+ {
+- $uid = $this->uidForAttr('uid', $id);
++ $uid = $this->uidForAttr(KOLAB_ATTR_SID, $id);
+ if (!$uid) {
+ $uid = $this->uidForAttr('mail', $id);
+ }
+@@ -562,7 +565,7 @@ class Horde_Kolab_Server {
+ */
+ function uidForMailOrIdOrAlias($id)
+ {
+- $uid = $this->uidForAttr('uid', $id);
++ $uid = $this->uidForAttr(KOLAB_ATTR_SID, $id);
+ if (!$uid) {
+ $uid = $this->uidForAttr('mail', $id);
+ if (!$uid) {
+diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object.php
+index 2b1237c..27993cc 100644
+--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object.php
++++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object.php
+@@ -26,6 +26,7 @@ define('KOLAB_OBJECT_USER', 'Horde_Kolab_Server_Object_user');
+ define('KOLAB_OBJECT_SERVER', 'Horde_Kolab_Server_Object_server');
+
+ /** Define the possible Kolab object attributes */
++define('KOLAB_ATTR_OC', 'objectClass');
+ define('KOLAB_ATTR_UID', 'dn');
+ define('KOLAB_ATTR_ID', 'id');
+ define('KOLAB_ATTR_SN', 'sn');
+@@ -35,6 +36,7 @@ define('KOLAB_ATTR_FN', 'fn');
+ define('KOLAB_ATTR_LNFN', 'lnfn');
+ define('KOLAB_ATTR_FNLN', 'fnln');
+ define('KOLAB_ATTR_MAIL', 'mail');
++define('KOLAB_ATTR_ALIAS', 'alias');
+ define('KOLAB_ATTR_SID', 'uid');
+ define('KOLAB_ATTR_ACL', 'acl');
+ define('KOLAB_ATTR_MEMBER', 'member');
+diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/address.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/address.php
+index 697a0c0..59d9ad4 100644
+--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/address.php
++++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/address.php
+@@ -33,13 +33,6 @@
+ class Horde_Kolab_Server_Object_address extends Horde_Kolab_Server_Object {
+
+ /**
+- * The LDAP filter to retrieve this object type
+- *
+- * @var string
+- */
+- var $filter = '(&(objectclass=inetOrgPerson)(!(uid=*))(sn=*))';
+-
+- /**
+ * The attributes supported by this class
+ *
+ * @var array
+@@ -86,6 +79,32 @@ class Horde_Kolab_Server_Object_address extends Horde_Kolab_Server_Object {
+ );
+
+ /**
++ * The LDAP filter to retrieve this object type
++ *
++ * @return string
++ */
++ function getFilter()
++ {
++ $criteria = array('AND' => array(
++ array('field' => KOLAB_ATTR_SN,
++ 'op' => '=',
++ 'test' => '*'),
++ array('field' => KOLAB_ATTR_OC,
++ 'op' => '=',
++ 'test' => KOLAB_OC_INETORGPERSON),
++ array('NOT' => array(
++ array('field' => KOLAB_ATTR_SID,
++ 'op' => '=',
++ 'test' => '*'),
++ ),
++ ),
++ ),
++ );
++ return $criteria;
++ }
++
++
++ /**
+ * Convert the object attributes to a hash.
+ *
+ * @param string $attrs The attributes to return.
+diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/adminrole.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/adminrole.php
+index cebfba2..f0b9f46 100644
+--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/adminrole.php
++++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/adminrole.php
+@@ -32,13 +32,6 @@
+ class Horde_Kolab_Server_Object_adminrole extends Horde_Kolab_Server_Object {
+
+ /**
+- * The LDAP filter to retrieve this object type
+- *
+- * @var string
+- */
+- var $filter = '(&(cn=*)(objectClass=inetOrgPerson)(!(uid=manager))(sn=*))';
+-
+- /**
+ * The attributes supported by this class
+ *
+ * @var array
+@@ -87,6 +80,34 @@ class Horde_Kolab_Server_Object_adminrole extends Horde_Kolab_Server_Object {
+ );
+
+ /**
++ * The LDAP filter to retrieve this object type
++ *
++ * @return string
++ */
++ function getFilter()
++ {
++ $criteria = array('AND' => array(
++ array('field' => KOLAB_ATTR_CN,
++ 'op' => '=',
++ 'test' => '*'),
++ array('field' => KOLAB_ATTR_SN,
++ 'op' => '=',
++ 'test' => '*'),
++ array('field' => KOLAB_ATTR_OC,
++ 'op' => '=',
++ 'test' => KOLAB_OC_INETORGPERSON),
++ array('NOT' => array(
++ array('field' => KOLAB_ATTR_SID,
++ 'op' => '=',
++ 'test' => 'manager'),
++ ),
++ ),
++ ),
++ );
++ return $criteria;
++ }
++
++ /**
+ * Convert the object attributes to a hash.
+ *
+ * @param string $attrs The attributes to return.
+diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/distlist.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/distlist.php
+index e2c1c3e..04889b0 100644
+--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/distlist.php
++++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/distlist.php
+@@ -34,14 +34,6 @@ require_once 'Horde/Kolab/Server/Object/group.php';
+ class Horde_Kolab_Server_Object_distlist extends Horde_Kolab_Server_Object_group {
+
+ /**
+- * The LDAP filter to retrieve this object type
+- *
+- * @var string
+- */
+- var $filter = '(&(objectClass=kolabGroupOfNames)(mail=*))';
+-
+-
+- /**
+ * The attributes required when creating an object of this class.
+ *
+ * @var array
+@@ -49,4 +41,26 @@ class Horde_Kolab_Server_Object_distlist extends Horde_Kolab_Server_Object_group
+ var $_required_attributes = array(
+ KOLAB_ATTR_MAIL,
+ );
++
++ /**
++ * Return the filter string to retrieve this object type.
++ *
++ * @static
++ *
++ * @return string The filter to retrieve this object type from the server
++ * database.
++ */
++ public static function getFilter()
++ {
++ $criteria = array('AND' => array(
++ array('field' => KOLAB_ATTR_MAIL,
++ 'op' => '=',
++ 'test' => '*'),
++ array('field' => KOLAB_ATTR_OC,
++ 'op' => '=',
++ 'test' => KOLAB_OC_KOLABGROUPOFNAMES),
++ ),
++ );
++ return $criteria;
++ }
+ };
+diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/group.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/group.php
+index e72604a..ea3d370 100644
+--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/group.php
++++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/group.php
+@@ -32,13 +32,6 @@
+ class Horde_Kolab_Server_Object_group extends Horde_Kolab_Server_Object {
+
+ /**
+- * The LDAP filter to retrieve this object type
+- *
+- * @var string
+- */
+- var $filter = '(objectClass=kolabGroupOfNames)';
+-
+- /**
+ * The attributes supported by this class
+ *
+ * @var array
+@@ -104,6 +97,22 @@ class Horde_Kolab_Server_Object_group extends Horde_Kolab_Server_Object {
+ }
+
+ /**
++ * Return the filter string to retrieve this object type.
++ *
++ * @return string The filter to retrieve this object type from the server
++ * database.
++ */
++ public static function getFilter()
++ {
++ $criteria = array('AND' => array(array('field' => KOLAB_ATTR_OC,
++ 'op' => '=',
++ 'test' => KOLAB_OC_KOLABGROUPOFNAMES),
++ ),
++ );
++ return $criteria;
++ }
++
++ /**
+ * Convert the object attributes to a hash.
+ *
+ * @param string $attrs The attributes to return.
+diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/server.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/server.php
+index 23549d5..b52a587 100644
+--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/server.php
++++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/server.php
+@@ -32,11 +32,26 @@
+ class Horde_Kolab_Server_Object_server extends Horde_Kolab_Server_Object {
+
+ /**
+- * The LDAP filter to retrieve this object type
++ * Return the filter string to retrieve this object type.
+ *
+- * @var string
++ * @static
++ *
++ * @return string The filter to retrieve this object type from the server
++ * database.
+ */
+- var $filter = '(&((k=kolab))(objectclass=kolab))';
++ public static function getFilter()
++ {
++ $criteria = array('AND' => array(
++ array('field' => 'k',
++ 'op' => '=',
++ 'test' => 'kolab'),
++ array('field' => KOLAB_ATTR_OC,
++ 'op' => '=',
++ 'test' => KOLAB_OC_KOLAB),
++ ),
++ );
++ return $criteria;
++ }
+
+ /**
+ * The attributes supported by this class
+diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/sharedfolder.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/sharedfolder.php
+index 81a68f6..ea8994b 100644
+--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/sharedfolder.php
++++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/sharedfolder.php
+@@ -33,13 +33,6 @@
+ class Horde_Kolab_Server_Object_sharedfolder extends Horde_Kolab_Server_Object {
+
+ /**
+- * The LDAP filter to retrieve this object type
+- *
+- * @var string
+- */
+- var $filter = '(objectClass=kolabSharedFolder)';
+-
+- /**
+ * The attributes supported by this class
+ *
+ * @var array
+@@ -89,6 +82,22 @@ class Horde_Kolab_Server_Object_sharedfolder extends Horde_Kolab_Server_Object {
+ }
+
+ /**
++ * Return the filter string to retrieve this object type.
++ *
++ * @return string The filter to retrieve this object type from the server
++ * database.
++ */
++ public static function getFilter()
++ {
++ $criteria = array('AND' => array(array('field' => KOLAB_ATTR_OC,
++ 'op' => '=',
++ 'test' => KOLAB_OC_KOLABSHAREDFOLDER),
++ ),
++ );
++ return $criteria;
++ }
++
++ /**
+ * Convert the object attributes to a hash.
+ *
+ * @param string $attrs The attributes to return.
+diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/user.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/user.php
+index a02b7fe..c648f65 100644
+--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/user.php
++++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/user.php
+@@ -33,13 +33,6 @@
+ class Horde_Kolab_Server_Object_user extends Horde_Kolab_Server_Object {
+
+ /**
+- * The LDAP filter to retrieve this object type
+- *
+- * @var string
+- */
+- var $filter = '(&(objectClass=kolabInetOrgPerson)(uid=*)(mail=*)(sn=*))';
+-
+- /**
+ * The attributes supported by this class
+ *
+ * @var array
+@@ -154,6 +147,31 @@ class Horde_Kolab_Server_Object_user extends Horde_Kolab_Server_Object {
+ }
+
+ /**
++ * The LDAP filter to retrieve this object type
++ *
++ * @return string
++ */
++ function getFilter()
++ {
++ $criteria = array('AND' => array(
++ array('field' => KOLAB_ATTR_SN,
++ 'op' => '=',
++ 'test' => '*'),
++ array('field' => KOLAB_ATTR_MAIL,
++ 'op' => '=',
++ 'test' => '*'),
++ array('field' => KOLAB_ATTR_SID,
++ 'op' => '=',
++ 'test' => '*'),
++ array('field' => KOLAB_ATTR_OC,
++ 'op' => '=',
++ 'test' => KOLAB_OC_KOLABINETORGPERSON),
++ ),
++ );
++ return $criteria;
++ }
++
++ /**
+ * Convert the object attributes to a hash.
+ *
+ * @param string $attrs The attributes to return.
+diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/ldap.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/ldap.php
+index eee8f52..ddc953f 100644
+--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/ldap.php
++++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/ldap.php
+@@ -210,6 +210,7 @@ class Horde_Kolab_Server_ldap extends Horde_Kolab_Server {
+ }
+
+ if (isset($attrs)) {
++ $this->mapKeys($attrs);
+ $result = @ldap_read($this->_connection, $dn, '(objectclass=*)', $attrs);
+ } else {
+ $result = @ldap_read($this->_connection, $dn, '(objectclass=*)');
+@@ -230,6 +231,9 @@ class Horde_Kolab_Server_ldap extends Horde_Kolab_Server {
+ $dn, $this->_error()));
+ }
+ ldap_free_result($result);
++
++ $this->unmapAttributes($object);
++
+ return $object;
+ }
+
+@@ -250,6 +254,8 @@ class Horde_Kolab_Server_ldap extends Horde_Kolab_Server {
+ }
+ }
+
++ $this->mapAttributes($data);
++
+ return @ldap_add($this->_connection, $dn, $data);
+ }
+
+@@ -681,9 +687,25 @@ class Horde_Kolab_Server_ldap extends Horde_Kolab_Server {
+ */
+ function mailForIdOrMail($id)
+ {
+- $filter = '(&(objectClass=kolabInetOrgPerson)(|(uid='.
+- Horde_LDAP::quote($id) . ')(mail=' .
+- Horde_LDAP::quote($id) . ')))';
++ $criteria = array('AND' =>
++ array(
++ array('field' => KOLAB_ATTR_OC,
++ 'op' => '=',
++ 'test' => KOLAB_OC_KOLABINETORGPERSON),
++ array('OR' =>
++ array(
++ array('field' => KOLAB_ATTR_SID,
++ 'op' => '=',
++ 'test' => $id),
++ array('field' => KOLAB_ATTR_MAIL,
++ 'op' => '=',
++ 'test' => $id),
++ ),
++ ),
++ ),
++ );
++ $filter = $this->searchQuery($criteria);
++
+ $result = $this->_attrsForFilter($filter, array('mail'),
+ KOLAB_SERVER_RESULT_STRICT);
+ if (is_a($result, 'PEAR_Error')) {
+@@ -702,9 +724,24 @@ class Horde_Kolab_Server_ldap extends Horde_Kolab_Server {
+ */
+ function uidForIdOrMail($id)
+ {
+- $filter = '(&(objectClass=kolabInetOrgPerson)(|(uid='.
+- Horde_LDAP::quote($id) . ')(mail=' .
+- Horde_LDAP::quote($id) . ')))';
++ $criteria = array('AND' =>
++ array(
++ array('field' => KOLAB_ATTR_OC,
++ 'op' => '=',
++ 'test' => KOLAB_OC_KOLABINETORGPERSON),
++ array('OR' =>
++ array(
++ array('field' => KOLAB_ATTR_SID,
++ 'op' => '=',
++ 'test' => $id),
++ array('field' => KOLAB_ATTR_MAIL,
++ 'op' => '=',
++ 'test' => $id),
++ ),
++ ),
++ ),
++ );
++ $filter = $this->searchQuery($criteria);
+ return $this->_dnForFilter($filter, KOLAB_SERVER_RESULT_STRICT);
+ }
+
+@@ -717,9 +754,25 @@ class Horde_Kolab_Server_ldap extends Horde_Kolab_Server {
+ */
+ function addrsForIdOrMail($id)
+ {
+- $filter = '(&(objectClass=kolabInetOrgPerson)(|(mail='
+- . Horde_LDAP::quote($id) . ')(uid='
+- . Horde_LDAP::quote($id) . ')))';
++ $criteria = array('AND' =>
++ array(
++ array('field' => KOLAB_ATTR_OC,
++ 'op' => '=',
++ 'test' => KOLAB_OC_KOLABINETORGPERSON),
++ array('OR' =>
++ array(
++ array('field' => KOLAB_ATTR_SID,
++ 'op' => '=',
++ 'test' => $id),
++ array('field' => KOLAB_ATTR_MAIL,
++ 'op' => '=',
++ 'test' => $id),
++ ),
++ ),
++ ),
++ );
++ $filter = $this->searchQuery($criteria);
++
+ $result = $this->_attrsForFilter($filter, array('mail', 'alias'),
+ KOLAB_SERVER_RESULT_STRICT);
+ if (empty($result)) {
+@@ -768,10 +821,27 @@ class Horde_Kolab_Server_ldap extends Horde_Kolab_Server {
+ */
+ function uidForMailAddress($mail)
+ {
+- $filter = '(&(objectClass=kolabInetOrgPerson)(|(uid='.
+- Horde_LDAP::quote($mail) . ')(mail=' .
+- Horde_LDAP::quote($mail) . ')(alias=' .
+- Horde_LDAP::quote($mail) . ')))';
++ $criteria = array('AND' =>
++ array(
++ array('field' => KOLAB_ATTR_OC,
++ 'op' => '=',
++ 'test' => KOLAB_OC_KOLABINETORGPERSON),
++ array('OR' =>
++ array(
++ array('field' => KOLAB_ATTR_ALIAS,
++ 'op' => '=',
++ 'test' => $mail),
++ array('field' => KOLAB_ATTR_MAIL,
++ 'op' => '=',
++ 'test' => $mail),
++ array('field' => KOLAB_ATTR_SID,
++ 'op' => '=',
++ 'test' => $mail),
++ ),
++ ),
++ ),
++ );
++ $filter = $this->searchQuery($criteria);
+ return $this->_dnForFilter($filter);
+ }
+
+@@ -874,7 +944,13 @@ class Horde_Kolab_Server_ldap extends Horde_Kolab_Server {
+ return $result;
+ }
+ $vars = get_class_vars($type);
+- $filter = $vars['filter'];
++ $methods = get_class_methods($type);
++ if (!in_array('getFilter', $methods)) {
++ $filter = $vars['filter'];
++ } else {
++ $criteria = call_user_func(array($type, 'getFilter'));
++ $filter = $this->searchQuery($criteria);
++ }
+ $sort = $vars['sort_by'];
+
+ if (isset($params['sort'])) {
+@@ -993,4 +1069,176 @@ class Horde_Kolab_Server_ldap extends Horde_Kolab_Server {
+ }
+ }
+
++ /**
++ * Build a search query.
++ *
++ * Taken from the Turba LDAP driver.
++ *
++ * @param array $criteria The array of criteria.
++ *
++ * @return string An LDAP query filter.
++ */
++ public function searchQuery($criteria)
++ {
++ require_once 'Net/LDAP2.php';
++
++ /* Accept everything. */
++ $filter = '(' . strtolower(KOLAB_ATTR_OC) . '=*)';
++
++ /* Build the LDAP filter. */
++ if (count($criteria)) {
++ $f = $this->buildSearchQuery($criteria);
++ if (is_a($f, 'Net_LDAP2_Filter')) {
++ $filter = $f->asString();
++ }
++ }
++ return $filter;
++ }
++
++ /**
++ * Build a piece of a search query.
++ *
++ * Taken from the Turba LDAP driver.
++ *
++ * @param array $criteria The array of criteria.
++ *
++ * @return string An LDAP query fragment.
++ */
++ protected function &buildSearchQuery($criteria)
++ {
++ if (isset($criteria['field'])) {
++ require_once 'Horde/String.php';
++ require_once 'Horde/NLS.php';
++ $rhs = $criteria['test'];
++ /* Keep this in for reference as we did not really test servers with different encoding yet */
++ //$rhs = String::convertCharset($criteria['test'], NLS::getCharset(), $this->params['charset']);
++ switch ($criteria['op']) {
++ case '=':
++ $op = 'equals';
++ break;
++ }
++ return Net_LDAP2_Filter::create($this->mapField($criteria['field']),
++ $op, $rhs);
++ }
++ foreach ($criteria as $key => $vals) {
++ if (!empty($vals['OR'])
++ || !empty($vals['AND'])
++ || !empty($vals['NOT'])) {
++ $parts = $this->buildSearchQuery($vals);
++ if (count($parts) > 1) {
++ if (!empty($vals['OR'])) {
++ $operator = '|';
++ } else if (!empty($vals['NOT'])) {
++ $operator = '!';
++ } else {
++ $operator = '&';
++ }
++ return Net_LDAP2_Filter::combine($operator, $parts);
++ } else {
++ return $parts[0];
++ }
++ } else {
++ $parts = array();
++ foreach ($vals as $test) {
++ $parts[] = &$this->buildSearchQuery($test);
++ }
++ switch ($key) {
++ case 'OR':
++ $operator = '|';
++ break;
++ case 'AND':
++ $operator = '&';
++ break;
++ case 'NOT':
++ $operator = '!';
++ break;
++ }
++ if (count($parts) > 1) {
++ return Net_LDAP2_Filter::combine($operator, $parts);
++ } else if ($operator == '!') {
++ return Net_LDAP2_Filter::combine($operator, $parts[0]);
++ } else {
++ return $parts[0];
++ }
++ }
++ }
++ }
++
++ /**
++ * Map attributes defined within this library their their real world
++ * counterparts.
++ *
++ * @param array $data The data that has been read and needs to be mapped.
++ *
++ * @return NULL
++ */
++ protected function unmapAttributes(&$data)
++ {
++ if (!empty($this->_params['map'])) {
++ foreach ($this->_params['map'] as $attribute => $map) {
++ if (isset($data[$map])) {
++ $data[$attribute] = $data[$map];
++ unset($data[$map]);
++ }
++ }
++ }
++ }
++
++ /**
++ * Map attributes defined within this library into their real world
++ * counterparts.
++ *
++ * @param array $data The data to be written.
++ *
++ * @return NULL
++ */
++ protected function mapAttributes(&$data)
++ {
++ if (!empty($this->_params['map'])) {
++ foreach ($this->_params['map'] as $attribute => $map) {
++ if (isset($data[$attribute])) {
++ $data[$map] = $data[$attribute];
++ unset($data[$attribute]);
++ }
++ }
++ }
++ }
++
++ /**
++ * Map attribute keys defined within this library into their real world
++ * counterparts.
++ *
++ * @param array $keys The attribute keys.
++ *
++ * @return NULL
++ */
++ protected function mapKeys(&$keys)
++ {
++ if (!empty($this->_params['map'])) {
++ foreach ($this->_params['map'] as $attribute => $map) {
++ if (in_array($attribute, $keys)) {
++ $keys = array_diff($keys, array($attribute));
++ $keys[] = $map;
++ }
++ }
++ }
++ }
++
++ /**
++ * Map a single attribute key defined within this library into its real
++ * world counterpart.
++ *
++ * @param array $field The attribute name.
++ *
++ * @return The real name of this attribute on the server we connect to.
++ */
++ protected function mapField($field)
++ {
++ if (!empty($this->_params['map'])
++ && isset($this->_params['map'][$field])) {
++ return $this->_params['map'][$field];
++ }
++ return $field;
++ }
++
+ }
+diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/test.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/test.php
+index 0127069..8d6d522 100644
+--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/test.php
++++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/test.php
+@@ -247,6 +247,10 @@ class Horde_Kolab_Server_test extends Horde_Kolab_Server_ldap {
+ }
+ }
+
++ if (!empty($attributes)) {
++ $this->mapKeys($attributes);
++ }
++
+ $filter = $this->_parse($filter);
+ if (is_a($filter, 'PEAR_Error')) {
+ return $filter;
+@@ -265,6 +269,8 @@ class Horde_Kolab_Server_test extends Horde_Kolab_Server_ldap {
+ $result = $subtree;
+ }
+
++ $this->unmapAttributes($result);
++
+ return $result;
+ }
+
+@@ -286,7 +292,8 @@ class Horde_Kolab_Server_test extends Horde_Kolab_Server_ldap {
+ switch ($filter['log']) {
+ case '=':
+ $value = $element['data'][$filter['att']];
+- if (($filter['val'] == '*' && !empty($value))
++ if ((($filter['val'] == '*' || $filter['val'] == '\2a')
++ && !empty($value))
+ || $value == $filter['val']
+ || (is_array($value)
+ && in_array($filter['val'], $value))) {
+@@ -390,8 +397,12 @@ class Horde_Kolab_Server_test extends Horde_Kolab_Server_ldap {
+ $dn));
+ }
+ if (empty($attrs)) {
+- return $GLOBALS['KOLAB_SERVER_TEST_DATA'][$dn]['data'];
++ $data = $GLOBALS['KOLAB_SERVER_TEST_DATA'][$dn]['data'];
++ $this->unmapAttributes($data);
++ return $data;
+ } else {
++ $this->mapKeys($attrs);
++
+ $result = array();
+ $data = $GLOBALS['KOLAB_SERVER_TEST_DATA'][$dn]['data'];
+
+@@ -401,6 +412,9 @@ class Horde_Kolab_Server_test extends Horde_Kolab_Server_ldap {
+ array_push($result, $attr);
+ }
+ }
++
++ $this->unmapAttributes($result);
++
+ $result['count'] = 1;
+ return $result;
+ }
+@@ -423,6 +437,8 @@ class Horde_Kolab_Server_test extends Horde_Kolab_Server_ldap {
+ }
+ }
+
++ $this->mapAttributes($data);
++
+ $ldap_data = array();
+ foreach ($data as $key => $val) {
+ if (!is_array($val)) {