doc/kolab_wap-3.1.sql doc/kolab_wap.sql doc/sample-insert-ou_types.php lib/api lib/Auth lib/Auth.php lib/client lib/ext lib/kolab_api_controller.php lib/kolab_api_service.php lib/kolab_client_task.php lib/locale public_html/js public_html/skins

Aleksander Machniak machniak at kolabsys.com
Thu Feb 27 11:32:46 CET 2014


 doc/kolab_wap-3.1.sql                       |  191 ------------------------
 doc/kolab_wap.sql                           |  219 ++++++++++++++++++++++++++++
 doc/sample-insert-ou_types.php              |   35 ++++
 lib/Auth.php                                |   46 +++--
 lib/Auth/LDAP.php                           |   73 ++++++++-
 lib/api/kolab_api_service_form_value.php    |    4 
 lib/api/kolab_api_service_ou.php            |  212 +++++++++++++++++++++++++++
 lib/api/kolab_api_service_ou_types.php      |   62 +++++++
 lib/api/kolab_api_service_ous.php           |   73 +++++++++
 lib/client/kolab_client_task_main.php       |    1 
 lib/client/kolab_client_task_ou.php         |  149 +++++++++++++++++++
 lib/ext/Net/LDAP3.php                       |   20 +-
 lib/kolab_api_controller.php                |    3 
 lib/kolab_api_service.php                   |    4 
 lib/kolab_client_task.php                   |    2 
 lib/locale/en_US.php                        |   14 +
 public_html/js/kolab_admin.js               |   52 ++++++
 public_html/skins/default/templates/ou.html |   17 ++
 18 files changed, 953 insertions(+), 224 deletions(-)

New commits:
commit 181e61d2d947e5487694b0b8d5a709125245db48
Author: Aleksander Machniak <machniak at kolabsys.com>
Date:   Thu Feb 27 11:31:39 2014 +0100

    Implemented OU structure management (Request #1745)

diff --git a/doc/kolab_wap-3.1.sql b/doc/kolab_wap-3.1.sql
deleted file mode 100644
index b4ba825..0000000
--- a/doc/kolab_wap-3.1.sql
+++ /dev/null
@@ -1,191 +0,0 @@
--- MySQL dump 10.13  Distrib 5.1.69, for redhat-linux-gnu (x86_64)
---
--- Host: localhost    Database: kolab
--- ------------------------------------------------------
--- Server version	5.1.69
-
-/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
-/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
-/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
-/*!40101 SET NAMES utf8 */;
-/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
-/*!40103 SET TIME_ZONE='+00:00' */;
-/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
-/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
-/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-
---
--- Table structure for table `group_types`
---
-
-DROP TABLE IF EXISTS `group_types`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `group_types` (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `key` text NOT NULL,
-  `name` varchar(256) NOT NULL,
-  `description` text NOT NULL,
-  `attributes` longtext NOT NULL,
-  PRIMARY KEY (`id`),
-  UNIQUE KEY `name` (`name`)
-) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
-/*!40101 SET character_set_client = @saved_cs_client */;
-
---
--- Dumping data for table `group_types`
---
-
-LOCK TABLES `group_types` WRITE;
-/*!40000 ALTER TABLE `group_types` DISABLE KEYS */;
-INSERT INTO `group_types` VALUES (1,'kolab','Kolab Distribution Group (Static)','A static Kolab Distribution Group (with mail address)','{\"auto_form_fields\":{\"mail\":{\"data\":[\"cn\"]}},\"fields\":{\"objectclass\":[\"top\",\"groupofuniquenames\",\"kolabgroupofuniquenames\"]},\"form_fields\":{\"cn\":[],\"kolaballowsmtprecipient\":{\"type\":\"list\",\"optional\":true},\"kolaballowsmtpsender\":{\"type\":\"list\",\"optional\":true},\"uniquemember\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true}}}'),(2,'kolab_dynamic','Kolab Distribution Group (Dynamic)','A dynamic Kolab Distribution Group (with mail address)','{\"auto_form_fields\":{\"mail\":{\"data\":[\"cn\"]}},\"fields\":{\"objectclass\":[\"top\",\"groupofurls\",\"kolabgroupofuniquenames\"]},\"form_fields\":{\"cn\":[],\"kolaballowsmtprecipient\":{\"type\":\"list\",\"optional\":true},\"kolaballowsmtpsender\":{\"type\":\"list\",\"optional\":true},\"memberurl\":{\"type\":\"ldap_url\",\"optional\":true},\"uniqueme
 mber\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true}}}'),(3,'posix','(Pure) POSIX Group','A pure UNIX POSIX Group','{\"auto_form_fields\":{\"gidnumber\":[]},\"fields\":{\"objectclass\":[\"top\",\"groupofuniquenames\",\"posixgroup\"]},\"form_fields\":{\"cn\":[],\"uniquemember\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true}}}'),(4,'posix_mail','Mail-enabled POSIX Group','A Kolab and also UNIX POSIX Group','{\"auto_form_fields\":{\"gidnumber\":[],\"mail\":{\"data\":[\"cn\"]}},\"fields\":{\"objectclass\":[\"top\",\"groupofuniquenames\",\"kolabgroupofuniquenames\",\"posixgroup\"]},\"form_fields\":{\"cn\":[],\"kolaballowsmtprecipient\":{\"type\":\"list\",\"optional\":true},\"kolaballowsmtpsender\":{\"type\":\"list\",\"optional\":true},\"mail\":{\"optional\":true},\"uniquemember\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true}}}'),(5,'simple','Simple Group (Static)','A simple, traditional LDAP group with a static list of members','{\"auto_fo
 rm_fields\":[],\"fields\":{\"objectclass\":[\"top\",\"groupofuniquenames\"]},\"form_fields\":{\"cn\":[],\"uniquemember\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true}}}');
-/*!40000 ALTER TABLE `group_types` ENABLE KEYS */;
-UNLOCK TABLES;
-
---
--- Table structure for table `options`
---
-
-DROP TABLE IF EXISTS `options`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `options` (
-  `attribute` varchar(128) NOT NULL,
-  `option_values` text NOT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-/*!40101 SET character_set_client = @saved_cs_client */;
-
---
--- Dumping data for table `options`
---
-
-LOCK TABLES `options` WRITE;
-/*!40000 ALTER TABLE `options` DISABLE KEYS */;
-INSERT INTO `options` VALUES ('preferredlanguage','[\"aa_DJ\",\"aa_ER\",\"aa_ET\",\"af_ZA\",\"am_ET\",\"an_ES\",\"ar_AE\",\"ar_BH\",\"ar_DZ\",\"ar_EG\",\"ar_IN\",\"ar_IQ\",\"ar_JO\",\"ar_KW\",\"ar_LB\",\"ar_LY\",\"ar_MA\",\"ar_OM\",\"ar_QA\",\"ar_SA\",\"ar_SD\",\"ar_SY\",\"ar_TN\",\"ar_YE\",\"as_IN\",\"az_AZ\",\"be_BY\",\"bg_BG\",\"bn_BD\",\"bn_IN\",\"bokmal\",\"br_FR\",\"bs_BA\",\"byn_ER\",\"C\",\"ca_AD\",\"ca_ES\",\"ca_FR\",\"ca_IT\",\"catalan\",\"croatian\",\"csb_PL\",\"cs_CZ\",\"cy_GB\",\"czech\",\"da_DK\",\"danish\",\"dansk\",\"de_AT\",\"de_BE\",\"de_CH\",\"de_DE\",\"de_LU\",\"deutsch\",\"dutch\",\"dz_BT\",\"eesti\",\"el_CY\",\"el_GR\",\"en_AU\",\"en_BW\",\"en_CA\",\"en_DK\",\"en_GB\",\"en_HK\",\"en_IE\",\"en_IN\",\"en_NZ\",\"en_PH\",\"en_SG\",\"en_US\",\"en_ZA\",\"en_ZW\",\"es_AR\",\"es_BO\",\"es_CL\",\"es_CO\",\"es_CR\",\"es_DO\",\"es_EC\",\"es_ES\",\"es_GT\",\"es_HN\",\"es_MX\",\"es_NI\",\"es_PA\",\"es_PE\",\"es_PR\",\"es_PY\",\"es_SV\",\"estonian\",\"es_US\",\"es_UY
 \",\"es_VE\",\"et_EE\",\"eu_ES\",\"fa_IR\",\"fi_FI\",\"finnish\",\"fo_FO\",\"fr_BE\",\"fr_CA\",\"fr_CH\",\"french\",\"fr_FR\",\"fr_LU\",\"fy_NL\",\"ga_IE\",\"galego\",\"galician\",\"gd_GB\",\"german\",\"gez_ER\",\"gez_ET\",\"gl_ES\",\"greek\",\"gu_IN\",\"gv_GB\",\"hebrew\",\"he_IL\",\"hi_IN\",\"hr_HR\",\"hrvatski\",\"hsb_DE\",\"hu_HU\",\"hungarian\",\"hy_AM\",\"icelandic\",\"id_ID\",\"is_IS\",\"italian\",\"it_CH\",\"it_IT\",\"iw_IL\",\"ja_JP\",\"japanese\",\"ka_GE\",\"kk_KZ\",\"kl_GL\",\"km_KH\",\"kn_IN\",\"ko_KR\",\"korean\",\"ku_TR\",\"kw_GB\",\"ky_KG\",\"lg_UG\",\"lithuanian\",\"lo_LA\",\"lt_LT\",\"lv_LV\",\"mai_IN\",\"mg_MG\",\"mi_NZ\",\"mk_MK\",\"ml_IN\",\"mn_MN\",\"mr_IN\",\"ms_MY\",\"mt_MT\",\"nb_NO\",\"ne_NP\",\"nl_BE\",\"nl_NL\",\"nn_NO\",\"no_NO\",\"norwegian\",\"nr_ZA\",\"nso_ZA\",\"nynorsk\",\"oc_FR\",\"om_ET\",\"om_KE\",\"or_IN\",\"pa_IN\",\"pa_PK\",\"pl_PL\",\"polish\",\"portuguese\",\"POSIX\",\"pt_BR\",\"pt_PT\",\"romanian\",\"ro_RO\",\"ru_RU\",\"russian\",\"r
 u_UA\",\"rw_RW\",\"se_NO\",\"sid_ET\",\"si_LK\",\"sk_SK\",\"slovak\",\"slovene\",\"slovenian\",\"sl_SI\",\"so_DJ\",\"so_ET\",\"so_KE\",\"so_SO\",\"spanish\",\"sq_AL\",\"sr_CS\",\"sr_ME\",\"sr_RS\",\"ss_ZA\",\"st_ZA\",\"sv_FI\",\"sv_SE\",\"swedish\",\"ta_IN\",\"te_IN\",\"tg_TJ\",\"thai\",\"th_TH\",\"ti_ER\",\"ti_ET\",\"tig_ER\",\"tl_PH\",\"tn_ZA\",\"tr_CY\",\"tr_TR\",\"ts_ZA\",\"tt_RU\",\"turkish\",\"uk_UA\",\"ur_PK\",\"uz_UZ\",\"ve_ZA\",\"vi_VN\",\"wa_BE\",\"xh_ZA\",\"yi_US\",\"zh_CN\",\"zh_HK\",\"zh_SG\",\"zh_TW\",\"zu_ZA\"]'),('c','[\"AD\",\"AE\",\"AF\",\"AG\",\"AI\",\"AL\",\"AM\",\"AO\",\"AQ\",\"AR\",\"AS\",\"AT\",\"AU\",\"AW\",\"AX\",\"AZ\",\"BA\",\"BB\",\"BD\",\"BE\",\"BF\",\"BG\",\"BH\",\"BI\",\"BJ\",\"BL\",\"BM\",\"BN\",\"BO\",\"BQ\",\"BR\",\"BS\",\"BT\",\"BV\",\"BW\",\"BY\",\"BZ\",\"CA\",\"CC\",\"CD\",\"CF\",\"CG\",\"CH\",\"CI\",\"CK\",\"CL\",\"CM\",\"CN\",\"CO\",\"CR\",\"CU\",\"CV\",\"CW\",\"CX\",\"CY\",\"CZ\",\"DE\",\"DJ\",\"DK\",\"DM\",\"DO\",\"DZ\",\"EC\",\"EE\",
 \"EG\",\"EH\",\"ER\",\"ES\",\"ET\",\"FI\",\"FJ\",\"FK\",\"FM\",\"FO\",\"FR\",\"GA\",\"GB\",\"GD\",\"GE\",\"GF\",\"GG\",\"GH\",\"GI\",\"GL\",\"GM\",\"GN\",\"GP\",\"GQ\",\"GR\",\"GS\",\"GT\",\"GU\",\"GW\",\"GY\",\"HK\",\"HM\",\"HN\",\"HR\",\"HT\",\"HU\",\"ID\",\"IE\",\"IL\",\"IM\",\"IN\",\"IO\",\"IQ\",\"IR\",\"IS\",\"IT\",\"JE\",\"JM\",\"JO\",\"JP\",\"KE\",\"KG\",\"KH\",\"KI\",\"KM\",\"KN\",\"KP\",\"KR\",\"KW\",\"KY\",\"KZ\",\"LA\",\"LB\",\"LC\",\"LI\",\"LK\",\"LR\",\"LS\",\"LT\",\"LU\",\"LV\",\"LY\",\"MA\",\"MC\",\"MD\",\"ME\",\"MG\",\"MH\",\"MK\",\"ML\",\"MM\",\"MN\",\"MO\",\"MP\",\"MQ\",\"MR\",\"MS\",\"MT\",\"MT\",\"MU\",\"MV\",\"MW\",\"MX\",\"MY\",\"MZ\",\"NA\",\"NC\",\"NE\",\"NF\",\"NG\",\"NI\",\"NL\",\"NO\",\"NP\",\"NR\",\"NU\",\"NZ\",\"OM\",\"PA\",\"PE\",\"PF\",\"PG\",\"PH\",\"PK\",\"PL\",\"PM\",\"PN\",\"PR\",\"PS\",\"PT\",\"PW\",\"PY\",\"QA\",\"RE\",\"RO\",\"RS\",\"RU\",\"RW\",\"SA\",\"SB\",\"SC\",\"SD\",\"SE\",\"SG\",\"SH\",\"SI\",\"SJ\",\"SK\",\"SL\",\"SM\",\"SN\",\"
 SO\",\"SR\",\"SS\",\"ST\",\"SV\",\"SX\",\"SY\",\"SZ\",\"TC\",\"TD\",\"TF\",\"TG\",\"TH\",\"TJ\",\"TK\",\"TL\",\"TM\",\"TN\",\"TO\",\"TR\",\"TT\",\"TV\",\"TW\",\"TZ\",\"UA\",\"UG\",\"UM\",\"US\",\"UY\",\"UZ\",\"VA\",\"VA\",\"VC\",\"VE\",\"VG\",\"VI\",\"VN\",\"VU\",\"WF\",\"WS\",\"YE\",\"YT\",\"YU\",\"ZA\",\"ZM\",\"ZW\"]');
-/*!40000 ALTER TABLE `options` ENABLE KEYS */;
-UNLOCK TABLES;
-
---
--- Table structure for table `resource_types`
---
-
-DROP TABLE IF EXISTS `resource_types`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `resource_types` (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `key` text NOT NULL,
-  `name` varchar(256) NOT NULL,
-  `description` text NOT NULL,
-  `attributes` longtext NOT NULL,
-  PRIMARY KEY (`id`),
-  UNIQUE KEY `name` (`name`)
-) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
-/*!40101 SET character_set_client = @saved_cs_client */;
-
---
--- Dumping data for table `resource_types`
---
-
-LOCK TABLES `resource_types` WRITE;
-/*!40000 ALTER TABLE `resource_types` DISABLE KEYS */;
-INSERT INTO `resource_types` VALUES (1,'collection','Resource Collection','A collection or pool of resources','{\"auto_form_fields\":{\"mail\":{\"data\":[\"cn\"]}},\"fields\":{\"objectclass\":[\"top\",\"groupofuniquenames\",\"kolabgroupofuniquenames\"]},\"form_fields\":{\"cn\":[],\"uniquemember\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true}}}'),(2,'car','Car','A car','{\"auto_form_fields\":{\"cn\":{\"data\":[\"cn\"]},\"kolabtargetfolder\":{\"data\":[\"cn\"]},\"mail\":{\"data\":[\"cn\"]}},\"fields\":{\"objectclass\":[\"top\",\"kolabsharedfolder\",\"mailrecipient\"],\"kolabfoldertype\":[\"event\"]},\"form_fields\":{\"cn\":[]}}'),(3,'confroom','Conference Room','A conference room','{\"auto_form_fields\":{\"cn\":{\"data\":[\"cn\"]},\"kolabtargetfolder\":{\"data\":[\"cn\"]},\"mail\":{\"data\":[\"cn\"]}},\"fields\":{\"objectclass\":[\"top\",\"kolabsharedfolder\",\"mailrecipient\"],\"kolabfoldertype\":[\"event\"]},\"form_fields\":{\"cn\":[]}}'),(4,'beamer','Beamer','
 A portable beamer','{\"auto_form_fields\":{\"cn\":{\"data\":[\"cn\"]},\"kolabtargetfolder\":{\"data\":[\"cn\"]},\"mail\":{\"data\":[\"cn\"]}},\"fields\":{\"objectclass\":[\"top\",\"kolabsharedfolder\",\"mailrecipient\"],\"kolabfoldertype\":[\"event\"]},\"form_fields\":{\"cn\":[]}}'),(5,'footballtickets','Football Season Tickets','Season tickets to the game (pretty good seats too!)','{\"auto_form_fields\":{\"cn\":{\"data\":[\"cn\"]},\"kolabtargetfolder\":{\"data\":[\"cn\"]},\"mail\":{\"data\":[\"cn\"]}},\"fields\":{\"objectclass\":[\"top\",\"kolabsharedfolder\",\"mailrecipient\"],\"kolabfoldertype\":[\"event\"]},\"form_fields\":{\"cn\":[]}}');
-/*!40000 ALTER TABLE `resource_types` ENABLE KEYS */;
-UNLOCK TABLES;
-
---
--- Table structure for table `role_types`
---
-
-DROP TABLE IF EXISTS `role_types`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `role_types` (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `key` text NOT NULL,
-  `name` varchar(256) NOT NULL,
-  `description` text NOT NULL,
-  `attributes` longtext NOT NULL,
-  PRIMARY KEY (`id`),
-  UNIQUE KEY `name` (`name`)
-) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
-/*!40101 SET character_set_client = @saved_cs_client */;
-
---
--- Dumping data for table `role_types`
---
-
-LOCK TABLES `role_types` WRITE;
-/*!40000 ALTER TABLE `role_types` DISABLE KEYS */;
-INSERT INTO `role_types` VALUES (1,'simple_managed','Standard Role','A standard role definition','{\"auto_form_fields\":[],\"fields\":{\"objectclass\":[\"top\",\"ldapsubentry\",\"nsroledefinition\",\"nssimpleroledefinition\",\"nsmanagedroledefinition\"]},\"form_fields\":{\"cn\":[],\"description\":[]}}');
-/*!40000 ALTER TABLE `role_types` ENABLE KEYS */;
-UNLOCK TABLES;
-
---
--- Table structure for table `sharedfolder_types`
---
-
-DROP TABLE IF EXISTS `sharedfolder_types`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `sharedfolder_types` (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `key` text NOT NULL,
-  `name` varchar(256) NOT NULL,
-  `description` text NOT NULL,
-  `attributes` longtext NOT NULL,
-  PRIMARY KEY (`id`),
-  UNIQUE KEY `name` (`name`)
-) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
-/*!40101 SET character_set_client = @saved_cs_client */;
-
---
--- Dumping data for table `sharedfolder_types`
---
-
-LOCK TABLES `sharedfolder_types` WRITE;
-/*!40000 ALTER TABLE `sharedfolder_types` DISABLE KEYS */;
-INSERT INTO `sharedfolder_types` VALUES (1,'addressbook','Shared Address Book','A shared address book','{\"auto_form_fields\":[],\"fields\":{\"kolabfoldertype\":[\"contact\"],\"objectclass\":[\"top\",\"kolabsharedfolder\"]},\"form_fields\":{\"cn\":[]}}'),(2,'calendar','Shared Calendar','A shared calendar','{\"auto_form_fields\":[],\"fields\":{\"kolabfoldertype\":[\"event\"],\"objectclass\":[\"top\",\"kolabsharedfolder\"]},\"form_fields\":{\"cn\":[]}}'),(3,'journal','Shared Journal','A shared journal','{\"auto_form_fields\":[],\"fields\":{\"kolabfoldertype\":[\"journal\"],\"objectclass\":[\"top\",\"kolabsharedfolder\"]},\"form_fields\":{\"cn\":[]}}'),(4,'task','Shared Tasks','A shared tasks folder','{\"auto_form_fields\":[],\"fields\":{\"kolabfoldertype\":[\"task\"],\"objectclass\":[\"top\",\"kolabsharedfolder\"]},\"form_fields\":{\"cn\":[]}}'),(5,'mail','Shared Mail Folder','A shared mail folder','{\"auto_form_fields\":[],\"fields\":{\"kolabfoldertype\":[\"mail\"],\"objectcl
 ass\":[\"top\",\"kolabsharedfolder\",\"mailrecipient\"]},\"form_fields\":{\"cn\":[],\"alias\":{\"type\":\"list\",\"optional\":true},\"kolabdelegate\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true},\"kolaballowsmtprecipient\":{\"type\":\"list\",\"optional\":true},\"kolaballowsmtpsender\":{\"type\":\"list\",\"optional\":true},\"kolabtargetfolder\":[],\"mail\":[]}}');
-/*!40000 ALTER TABLE `sharedfolder_types` ENABLE KEYS */;
-UNLOCK TABLES;
-
---
--- Table structure for table `user_types`
---
-
-DROP TABLE IF EXISTS `user_types`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `user_types` (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `key` text NOT NULL,
-  `name` varchar(256) NOT NULL,
-  `description` text NOT NULL,
-  `attributes` longtext NOT NULL,
-  `used_for` varchar(16) DEFAULT NULL,
-  PRIMARY KEY (`id`),
-  UNIQUE KEY `name` (`name`)
-) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
-/*!40101 SET character_set_client = @saved_cs_client */;
-
---
--- Dumping data for table `user_types`
---
-
-LOCK TABLES `user_types` WRITE;
-/*!40000 ALTER TABLE `user_types` DISABLE KEYS */;
-INSERT INTO `user_types` VALUES (1,'kolab','Kolab User','A Kolab User','{\"auto_form_fields\":{\"alias\":{\"type\":\"list\",\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"cn\":{\"data\":[\"givenname\",\"sn\"]},\"displayname\":{\"data\":[\"givenname\",\"sn\"]},\"mail\":{\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"mailhost\":{\"optional\":true},\"uid\":{\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"userpassword\":{\"optional\":true}},\"form_fields\":{\"alias\":{\"optional\":true},\"givenname\":[],\"initials\":{\"optional\":true},\"kolabdelegate\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true},\"kolabinvitationpolicy\":{\"type\":\"select\",\"values\":[\"\",\"ACT_MANUAL\",\"ACT_REJECT\"],\"optional\":true},\"kolaballowsmtprecipient\":{\"type\":\"list\",\"optional\":true},\"kolaballowsmtpsender\":{\"type\":\"list\",\"optional\":true},\"l\":{\"optional\":true},\"mailalternateaddress\":{\"type\":\"list\",\"optional\":true},\"mailquota\
 ":{\"type\":\"text-quota\",\"optional\":true},\"mobile\":{\"optional\":true},\"nsroledn\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true},\"o\":{\"optional\":true},\"ou\":{\"type\":\"select\"},\"pager\":{\"optional\":true},\"postalcode\":{\"optional\":true},\"preferredlanguage\":{\"type\":\"select\"},\"sn\":[],\"street\":{\"optional\":true},\"telephonenumber\":{\"optional\":true},\"title\":{\"optional\":true},\"userpassword\":{\"optional\":true}},\"fields\":{\"objectclass\":[\"top\",\"inetorgperson\",\"kolabinetorgperson\",\"mailrecipient\",\"organizationalperson\",\"person\"]}}',NULL),(2,'posix','POSIX User','A POSIX user (with a home directory and shell access)','{\"auto_form_fields\":{\"cn\":{\"data\":[\"givenname\",\"sn\"]},\"displayname\":{\"data\":[\"givenname\",\"sn\"]},\"gidnumber\":[],\"homedirectory\":{\"data\":[\"givenname\",\"sn\"]},\"uid\":{\"data\":[\"givenname\",\"sn\"]},\"uidnumber\":[],\"userpassword\":{\"optional\":true}},\"form_fields\":{\"give
 nname\":[],\"initials\":{\"optional\":true},\"preferredlanguage\":{\"type\":\"select\",\"values\":[\"en_US\",\"de_DE\",\"de_CH\",\"en_GB\",\"fi_FI\",\"fr_FR\",\"hu_HU\"]},\"loginshell\":{\"type\":\"select\",\"values\":[\"/bin/bash\",\"/usr/bin/git-shell\",\"/sbin/nologin\"]},\"ou\":{\"type\":\"select\"},\"sn\":[],\"title\":{\"optional\":true},\"userpassword\":{\"optional\":true}},\"fields\":{\"objectclass\":[\"top\",\"inetorgperson\",\"organizationalperson\",\"person\",\"posixaccount\"]}}',NULL),(3,'kolab_posix','Mail-enabled POSIX User','A mail-enabled POSIX User','{\"auto_form_fields\":{\"alias\":{\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"cn\":{\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"displayname\":{\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"gidnumber\":[],\"homedirectory\":{\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"mail\":{\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"mailhost\":{\"optional\":true},\"u
 id\":{\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"uidnumber\":[],\"userpassword\":{\"optional\":true}},\"form_fields\":{\"alias\":{\"optional\":true},\"givenname\":[],\"initials\":{\"optional\":true},\"kolabdelegate\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true},\"kolabinvitationpolicy\":{\"type\":\"select\",\"values\":[\"\",\"ACT_MANUAL\",\"ACT_REJECT\"],\"optional\":true},\"kolaballowsmtprecipient\":{\"type\":\"list\",\"optional\":true},\"kolaballowsmtpsender\":{\"type\":\"list\",\"optional\":true},\"l\":{\"optional\":true},\"loginshell\":{\"type\":\"select\",\"values\":[\"/bin/bash\",\"/usr/bin/git-shell\",\"/sbin/nologin\"]},\"mailalternateaddress\":{\"type\":\"list\",\"optional\":true},\"mailquota\":{\"type\":\"text-quota\",\"optional\":true},\"mobile\":{\"optional\":true},\"nsroledn\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true},\"o\":{\"optional\":true},\"ou\":{\"type\":\"select\"},\"pager\":{\"optional\":true},\"postalcode\"
 :{\"optional\":true},\"preferredlanguage\":{\"type\":\"select\"},\"sn\":[],\"street\":{\"optional\":true},\"telephonenumber\":{\"optional\":true},\"title\":{\"optional\":true},\"userpassword\":{\"optional\":true}},\"fields\":{\"objectclass\":[\"top\",\"inetorgperson\",\"kolabinetorgperson\",\"mailrecipient\",\"organizationalperson\",\"person\",\"posixaccount\"]}}',NULL),(4,'contact','Contact','A global address book contact','{\"auto_form_fields\":{\"cn\":{\"data\":[\"givenname\",\"sn\"]},\"displayname\":{\"data\":[\"givenname\",\"sn\"]},\"uid\":{\"data\":[\"givenname\",\"sn\"]},\"userpassword\":{\"optional\":true}},\"form_fields\":{\"cn\":{\"optional\":true},\"displayname\":{\"optional\":true},\"givenname\":[],\"initials\":{\"optional\":true},\"l\":{\"optional\":true},\"mail\":{\"type\":\"list\",\"optional\":true},\"mailalternateaddress\":{\"type\":\"list\",\"optional\":true},\"mobile\":{\"optional\":true},\"o\":{\"optional\":true},\"ou\":{\"type\":\"select\"},\"pager\":{\"o
 ptional\":true},\"postalcode\":{\"optional\":true},\"sn\":[],\"street\":{\"optional\":true},\"telephonenumber\":{\"optional\":true},\"title\":{\"optional\":true},\"userpassword\":{\"optional\":true}},\"fields\":{\"objectclass\":[\"top\",\"inetorgperson\",\"mailrecipient\",\"organizationalperson\",\"person\"]}}',NULL),(5,'forwarding','Mail Forwarding','A mail forwarding account (forwarding only!)','{\"auto_form_fields\":{\"cn\":{\"data\":[\"givenname\",\"sn\"]},\"displayname\":{\"data\":[\"givenname\",\"sn\"]},\"uid\":{\"data\":[\"givenname\",\"sn\"]},\"userpassword\":{\"optional\":true}},\"form_fields\":{\"cn\":{\"optional\":true},\"displayname\":{\"optional\":true},\"givenname\":[],\"initials\":{\"optional\":true},\"l\":{\"optional\":true},\"mail\":{\"type\":\"list\",\"optional\":true},\"mailalternateaddress\":{\"type\":\"list\",\"optional\":true},\"mailforwardingaddress\":{\"type\":\"list\"},\"mobile\":{\"optional\":true},\"o\":{\"optional\":true},\"ou\":{\"type\":\"select
 \"},\"pager\":{\"optional\":true},\"postalcode\":{\"optional\":true},\"sn\":[],\"street\":{\"optional\":true},\"telephonenumber\":{\"optional\":true},\"title\":{\"optional\":true},\"userpassword\":{\"optional\":true}},\"fields\":{\"objectclass\":[\"top\",\"inetorgperson\",\"mailrecipient\",\"organizationalperson\",\"person\"]}}',NULL);
-/*!40000 ALTER TABLE `user_types` ENABLE KEYS */;
-UNLOCK TABLES;
-/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
-
-/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
-/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
-/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
-/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
-/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
-/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
-/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-
--- Dump completed on 2013-11-15 12:19:12
diff --git a/doc/kolab_wap.sql b/doc/kolab_wap.sql
new file mode 100644
index 0000000..c863883
--- /dev/null
+++ b/doc/kolab_wap.sql
@@ -0,0 +1,219 @@
+-- MySQL dump 10.13  Distrib 5.1.69, for redhat-linux-gnu (x86_64)
+--
+-- Host: localhost    Database: kolab
+-- ------------------------------------------------------
+-- Server version	5.1.69
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `group_types`
+--
+
+DROP TABLE IF EXISTS `group_types`;
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `group_types` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `key` text NOT NULL,
+  `name` varchar(256) NOT NULL,
+  `description` text NOT NULL,
+  `attributes` longtext NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `group_types`
+--
+
+LOCK TABLES `group_types` WRITE;
+/*!40000 ALTER TABLE `group_types` DISABLE KEYS */;
+INSERT INTO `group_types` VALUES (1,'kolab','Kolab Distribution Group (Static)','A static Kolab Distribution Group (with mail address)','{\"auto_form_fields\":{\"mail\":{\"data\":[\"cn\"]}},\"fields\":{\"objectclass\":[\"top\",\"groupofuniquenames\",\"kolabgroupofuniquenames\"]},\"form_fields\":{\"cn\":[],\"kolaballowsmtprecipient\":{\"type\":\"list\",\"optional\":true},\"kolaballowsmtpsender\":{\"type\":\"list\",\"optional\":true},\"uniquemember\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true}}}'),(2,'kolab_dynamic','Kolab Distribution Group (Dynamic)','A dynamic Kolab Distribution Group (with mail address)','{\"auto_form_fields\":{\"mail\":{\"data\":[\"cn\"]}},\"fields\":{\"objectclass\":[\"top\",\"groupofurls\",\"kolabgroupofuniquenames\"]},\"form_fields\":{\"cn\":[],\"kolaballowsmtprecipient\":{\"type\":\"list\",\"optional\":true},\"kolaballowsmtpsender\":{\"type\":\"list\",\"optional\":true},\"memberurl\":{\"type\":\"ldap_url\",\"optional\":true},\"uniqueme
 mber\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true}}}'),(3,'posix','(Pure) POSIX Group','A pure UNIX POSIX Group','{\"auto_form_fields\":{\"gidnumber\":[]},\"fields\":{\"objectclass\":[\"top\",\"groupofuniquenames\",\"posixgroup\"]},\"form_fields\":{\"cn\":[],\"uniquemember\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true}}}'),(4,'posix_mail','Mail-enabled POSIX Group','A Kolab and also UNIX POSIX Group','{\"auto_form_fields\":{\"gidnumber\":[],\"mail\":{\"data\":[\"cn\"]}},\"fields\":{\"objectclass\":[\"top\",\"groupofuniquenames\",\"kolabgroupofuniquenames\",\"posixgroup\"]},\"form_fields\":{\"cn\":[],\"kolaballowsmtprecipient\":{\"type\":\"list\",\"optional\":true},\"kolaballowsmtpsender\":{\"type\":\"list\",\"optional\":true},\"mail\":{\"optional\":true},\"uniquemember\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true}}}'),(5,'simple','Simple Group (Static)','A simple, traditional LDAP group with a static list of members','{\"auto_fo
 rm_fields\":[],\"fields\":{\"objectclass\":[\"top\",\"groupofuniquenames\"]},\"form_fields\":{\"cn\":[],\"uniquemember\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true}}}');
+/*!40000 ALTER TABLE `group_types` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `options`
+--
+
+DROP TABLE IF EXISTS `options`;
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `options` (
+  `attribute` varchar(128) NOT NULL,
+  `option_values` text NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `options`
+--
+
+LOCK TABLES `options` WRITE;
+/*!40000 ALTER TABLE `options` DISABLE KEYS */;
+INSERT INTO `options` VALUES ('preferredlanguage','[\"aa_DJ\",\"aa_ER\",\"aa_ET\",\"af_ZA\",\"am_ET\",\"an_ES\",\"ar_AE\",\"ar_BH\",\"ar_DZ\",\"ar_EG\",\"ar_IN\",\"ar_IQ\",\"ar_JO\",\"ar_KW\",\"ar_LB\",\"ar_LY\",\"ar_MA\",\"ar_OM\",\"ar_QA\",\"ar_SA\",\"ar_SD\",\"ar_SY\",\"ar_TN\",\"ar_YE\",\"as_IN\",\"az_AZ\",\"be_BY\",\"bg_BG\",\"bn_BD\",\"bn_IN\",\"bokmal\",\"br_FR\",\"bs_BA\",\"byn_ER\",\"C\",\"ca_AD\",\"ca_ES\",\"ca_FR\",\"ca_IT\",\"catalan\",\"croatian\",\"csb_PL\",\"cs_CZ\",\"cy_GB\",\"czech\",\"da_DK\",\"danish\",\"dansk\",\"de_AT\",\"de_BE\",\"de_CH\",\"de_DE\",\"de_LU\",\"deutsch\",\"dutch\",\"dz_BT\",\"eesti\",\"el_CY\",\"el_GR\",\"en_AU\",\"en_BW\",\"en_CA\",\"en_DK\",\"en_GB\",\"en_HK\",\"en_IE\",\"en_IN\",\"en_NZ\",\"en_PH\",\"en_SG\",\"en_US\",\"en_ZA\",\"en_ZW\",\"es_AR\",\"es_BO\",\"es_CL\",\"es_CO\",\"es_CR\",\"es_DO\",\"es_EC\",\"es_ES\",\"es_GT\",\"es_HN\",\"es_MX\",\"es_NI\",\"es_PA\",\"es_PE\",\"es_PR\",\"es_PY\",\"es_SV\",\"estonian\",\"es_US\",\"es_UY
 \",\"es_VE\",\"et_EE\",\"eu_ES\",\"fa_IR\",\"fi_FI\",\"finnish\",\"fo_FO\",\"fr_BE\",\"fr_CA\",\"fr_CH\",\"french\",\"fr_FR\",\"fr_LU\",\"fy_NL\",\"ga_IE\",\"galego\",\"galician\",\"gd_GB\",\"german\",\"gez_ER\",\"gez_ET\",\"gl_ES\",\"greek\",\"gu_IN\",\"gv_GB\",\"hebrew\",\"he_IL\",\"hi_IN\",\"hr_HR\",\"hrvatski\",\"hsb_DE\",\"hu_HU\",\"hungarian\",\"hy_AM\",\"icelandic\",\"id_ID\",\"is_IS\",\"italian\",\"it_CH\",\"it_IT\",\"iw_IL\",\"ja_JP\",\"japanese\",\"ka_GE\",\"kk_KZ\",\"kl_GL\",\"km_KH\",\"kn_IN\",\"ko_KR\",\"korean\",\"ku_TR\",\"kw_GB\",\"ky_KG\",\"lg_UG\",\"lithuanian\",\"lo_LA\",\"lt_LT\",\"lv_LV\",\"mai_IN\",\"mg_MG\",\"mi_NZ\",\"mk_MK\",\"ml_IN\",\"mn_MN\",\"mr_IN\",\"ms_MY\",\"mt_MT\",\"nb_NO\",\"ne_NP\",\"nl_BE\",\"nl_NL\",\"nn_NO\",\"no_NO\",\"norwegian\",\"nr_ZA\",\"nso_ZA\",\"nynorsk\",\"oc_FR\",\"om_ET\",\"om_KE\",\"or_IN\",\"pa_IN\",\"pa_PK\",\"pl_PL\",\"polish\",\"portuguese\",\"POSIX\",\"pt_BR\",\"pt_PT\",\"romanian\",\"ro_RO\",\"ru_RU\",\"russian\",\"r
 u_UA\",\"rw_RW\",\"se_NO\",\"sid_ET\",\"si_LK\",\"sk_SK\",\"slovak\",\"slovene\",\"slovenian\",\"sl_SI\",\"so_DJ\",\"so_ET\",\"so_KE\",\"so_SO\",\"spanish\",\"sq_AL\",\"sr_CS\",\"sr_ME\",\"sr_RS\",\"ss_ZA\",\"st_ZA\",\"sv_FI\",\"sv_SE\",\"swedish\",\"ta_IN\",\"te_IN\",\"tg_TJ\",\"thai\",\"th_TH\",\"ti_ER\",\"ti_ET\",\"tig_ER\",\"tl_PH\",\"tn_ZA\",\"tr_CY\",\"tr_TR\",\"ts_ZA\",\"tt_RU\",\"turkish\",\"uk_UA\",\"ur_PK\",\"uz_UZ\",\"ve_ZA\",\"vi_VN\",\"wa_BE\",\"xh_ZA\",\"yi_US\",\"zh_CN\",\"zh_HK\",\"zh_SG\",\"zh_TW\",\"zu_ZA\"]'),('c','[\"AD\",\"AE\",\"AF\",\"AG\",\"AI\",\"AL\",\"AM\",\"AO\",\"AQ\",\"AR\",\"AS\",\"AT\",\"AU\",\"AW\",\"AX\",\"AZ\",\"BA\",\"BB\",\"BD\",\"BE\",\"BF\",\"BG\",\"BH\",\"BI\",\"BJ\",\"BL\",\"BM\",\"BN\",\"BO\",\"BQ\",\"BR\",\"BS\",\"BT\",\"BV\",\"BW\",\"BY\",\"BZ\",\"CA\",\"CC\",\"CD\",\"CF\",\"CG\",\"CH\",\"CI\",\"CK\",\"CL\",\"CM\",\"CN\",\"CO\",\"CR\",\"CU\",\"CV\",\"CW\",\"CX\",\"CY\",\"CZ\",\"DE\",\"DJ\",\"DK\",\"DM\",\"DO\",\"DZ\",\"EC\",\"EE\",
 \"EG\",\"EH\",\"ER\",\"ES\",\"ET\",\"FI\",\"FJ\",\"FK\",\"FM\",\"FO\",\"FR\",\"GA\",\"GB\",\"GD\",\"GE\",\"GF\",\"GG\",\"GH\",\"GI\",\"GL\",\"GM\",\"GN\",\"GP\",\"GQ\",\"GR\",\"GS\",\"GT\",\"GU\",\"GW\",\"GY\",\"HK\",\"HM\",\"HN\",\"HR\",\"HT\",\"HU\",\"ID\",\"IE\",\"IL\",\"IM\",\"IN\",\"IO\",\"IQ\",\"IR\",\"IS\",\"IT\",\"JE\",\"JM\",\"JO\",\"JP\",\"KE\",\"KG\",\"KH\",\"KI\",\"KM\",\"KN\",\"KP\",\"KR\",\"KW\",\"KY\",\"KZ\",\"LA\",\"LB\",\"LC\",\"LI\",\"LK\",\"LR\",\"LS\",\"LT\",\"LU\",\"LV\",\"LY\",\"MA\",\"MC\",\"MD\",\"ME\",\"MG\",\"MH\",\"MK\",\"ML\",\"MM\",\"MN\",\"MO\",\"MP\",\"MQ\",\"MR\",\"MS\",\"MT\",\"MT\",\"MU\",\"MV\",\"MW\",\"MX\",\"MY\",\"MZ\",\"NA\",\"NC\",\"NE\",\"NF\",\"NG\",\"NI\",\"NL\",\"NO\",\"NP\",\"NR\",\"NU\",\"NZ\",\"OM\",\"PA\",\"PE\",\"PF\",\"PG\",\"PH\",\"PK\",\"PL\",\"PM\",\"PN\",\"PR\",\"PS\",\"PT\",\"PW\",\"PY\",\"QA\",\"RE\",\"RO\",\"RS\",\"RU\",\"RW\",\"SA\",\"SB\",\"SC\",\"SD\",\"SE\",\"SG\",\"SH\",\"SI\",\"SJ\",\"SK\",\"SL\",\"SM\",\"SN\",\"
 SO\",\"SR\",\"SS\",\"ST\",\"SV\",\"SX\",\"SY\",\"SZ\",\"TC\",\"TD\",\"TF\",\"TG\",\"TH\",\"TJ\",\"TK\",\"TL\",\"TM\",\"TN\",\"TO\",\"TR\",\"TT\",\"TV\",\"TW\",\"TZ\",\"UA\",\"UG\",\"UM\",\"US\",\"UY\",\"UZ\",\"VA\",\"VA\",\"VC\",\"VE\",\"VG\",\"VI\",\"VN\",\"VU\",\"WF\",\"WS\",\"YE\",\"YT\",\"YU\",\"ZA\",\"ZM\",\"ZW\"]');
+/*!40000 ALTER TABLE `options` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ou_types`
+--
+
+DROP TABLE IF EXISTS `ou_types`;
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `ou_types` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `key` text NOT NULL,
+  `name` varchar(256) NOT NULL,
+  `description` text NOT NULL,
+  `attributes` longtext NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `ou_types`
+--
+
+LOCK TABLES `ou_types` WRITE;
+/*!40000 ALTER TABLE `ou_types` DISABLE KEYS */;
+INSERT INTO `ou_types` VALUES (1,'unit','Standard Organizational Unit','A standard organizational unit definition','{\"auto_form_fields\":[],\"fields\":{\"objectclass\":[\"top\",\"organizationalunit\"]},\"form_fields\":{\"ou\":[],\"description\":[]}}');
+/*!40000 ALTER TABLE `ou_types` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `resource_types`
+--
+
+DROP TABLE IF EXISTS `resource_types`;
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `resource_types` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `key` text NOT NULL,
+  `name` varchar(256) NOT NULL,
+  `description` text NOT NULL,
+  `attributes` longtext NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `resource_types`
+--
+
+LOCK TABLES `resource_types` WRITE;
+/*!40000 ALTER TABLE `resource_types` DISABLE KEYS */;
+INSERT INTO `resource_types` VALUES (1,'collection','Resource Collection','A collection or pool of resources','{\"auto_form_fields\":{\"mail\":{\"data\":[\"cn\"]}},\"fields\":{\"objectclass\":[\"top\",\"groupofuniquenames\",\"kolabgroupofuniquenames\"]},\"form_fields\":{\"cn\":[],\"uniquemember\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true}}}'),(2,'car','Car','A car','{\"auto_form_fields\":{\"cn\":{\"data\":[\"cn\"]},\"kolabtargetfolder\":{\"data\":[\"cn\"]},\"mail\":{\"data\":[\"cn\"]}},\"fields\":{\"objectclass\":[\"top\",\"kolabsharedfolder\",\"mailrecipient\"],\"kolabfoldertype\":[\"event\"]},\"form_fields\":{\"cn\":[]}}'),(3,'confroom','Conference Room','A conference room','{\"auto_form_fields\":{\"cn\":{\"data\":[\"cn\"]},\"kolabtargetfolder\":{\"data\":[\"cn\"]},\"mail\":{\"data\":[\"cn\"]}},\"fields\":{\"objectclass\":[\"top\",\"kolabsharedfolder\",\"mailrecipient\"],\"kolabfoldertype\":[\"event\"]},\"form_fields\":{\"cn\":[]}}'),(4,'beamer','Beamer','
 A portable beamer','{\"auto_form_fields\":{\"cn\":{\"data\":[\"cn\"]},\"kolabtargetfolder\":{\"data\":[\"cn\"]},\"mail\":{\"data\":[\"cn\"]}},\"fields\":{\"objectclass\":[\"top\",\"kolabsharedfolder\",\"mailrecipient\"],\"kolabfoldertype\":[\"event\"]},\"form_fields\":{\"cn\":[]}}'),(5,'footballtickets','Football Season Tickets','Season tickets to the game (pretty good seats too!)','{\"auto_form_fields\":{\"cn\":{\"data\":[\"cn\"]},\"kolabtargetfolder\":{\"data\":[\"cn\"]},\"mail\":{\"data\":[\"cn\"]}},\"fields\":{\"objectclass\":[\"top\",\"kolabsharedfolder\",\"mailrecipient\"],\"kolabfoldertype\":[\"event\"]},\"form_fields\":{\"cn\":[]}}');
+/*!40000 ALTER TABLE `resource_types` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `role_types`
+--
+
+DROP TABLE IF EXISTS `role_types`;
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `role_types` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `key` text NOT NULL,
+  `name` varchar(256) NOT NULL,
+  `description` text NOT NULL,
+  `attributes` longtext NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `role_types`
+--
+
+LOCK TABLES `role_types` WRITE;
+/*!40000 ALTER TABLE `role_types` DISABLE KEYS */;
+INSERT INTO `role_types` VALUES (1,'simple_managed','Standard Role','A standard role definition','{\"auto_form_fields\":[],\"fields\":{\"objectclass\":[\"top\",\"ldapsubentry\",\"nsroledefinition\",\"nssimpleroledefinition\",\"nsmanagedroledefinition\"]},\"form_fields\":{\"cn\":[],\"description\":[]}}');
+/*!40000 ALTER TABLE `role_types` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sharedfolder_types`
+--
+
+DROP TABLE IF EXISTS `sharedfolder_types`;
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `sharedfolder_types` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `key` text NOT NULL,
+  `name` varchar(256) NOT NULL,
+  `description` text NOT NULL,
+  `attributes` longtext NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sharedfolder_types`
+--
+
+LOCK TABLES `sharedfolder_types` WRITE;
+/*!40000 ALTER TABLE `sharedfolder_types` DISABLE KEYS */;
+INSERT INTO `sharedfolder_types` VALUES (1,'addressbook','Shared Address Book','A shared address book','{\"auto_form_fields\":[],\"fields\":{\"kolabfoldertype\":[\"contact\"],\"objectclass\":[\"top\",\"kolabsharedfolder\"]},\"form_fields\":{\"cn\":[]}}'),(2,'calendar','Shared Calendar','A shared calendar','{\"auto_form_fields\":[],\"fields\":{\"kolabfoldertype\":[\"event\"],\"objectclass\":[\"top\",\"kolabsharedfolder\"]},\"form_fields\":{\"cn\":[]}}'),(3,'journal','Shared Journal','A shared journal','{\"auto_form_fields\":[],\"fields\":{\"kolabfoldertype\":[\"journal\"],\"objectclass\":[\"top\",\"kolabsharedfolder\"]},\"form_fields\":{\"cn\":[]}}'),(4,'task','Shared Tasks','A shared tasks folder','{\"auto_form_fields\":[],\"fields\":{\"kolabfoldertype\":[\"task\"],\"objectclass\":[\"top\",\"kolabsharedfolder\"]},\"form_fields\":{\"cn\":[]}}'),(5,'mail','Shared Mail Folder','A shared mail folder','{\"auto_form_fields\":[],\"fields\":{\"kolabfoldertype\":[\"mail\"],\"objectcl
 ass\":[\"top\",\"kolabsharedfolder\",\"mailrecipient\"]},\"form_fields\":{\"cn\":[],\"alias\":{\"type\":\"list\",\"optional\":true},\"kolabdelegate\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true},\"kolaballowsmtprecipient\":{\"type\":\"list\",\"optional\":true},\"kolaballowsmtpsender\":{\"type\":\"list\",\"optional\":true},\"kolabtargetfolder\":[],\"mail\":[]}}');
+/*!40000 ALTER TABLE `sharedfolder_types` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `user_types`
+--
+
+DROP TABLE IF EXISTS `user_types`;
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `user_types` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `key` text NOT NULL,
+  `name` varchar(256) NOT NULL,
+  `description` text NOT NULL,
+  `attributes` longtext NOT NULL,
+  `used_for` varchar(16) DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `user_types`
+--
+
+LOCK TABLES `user_types` WRITE;
+/*!40000 ALTER TABLE `user_types` DISABLE KEYS */;
+INSERT INTO `user_types` VALUES (1,'kolab','Kolab User','A Kolab User','{\"auto_form_fields\":{\"alias\":{\"type\":\"list\",\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"cn\":{\"data\":[\"givenname\",\"sn\"]},\"displayname\":{\"data\":[\"givenname\",\"sn\"]},\"mail\":{\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"mailhost\":{\"optional\":true},\"uid\":{\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"userpassword\":{\"optional\":true}},\"form_fields\":{\"alias\":{\"optional\":true},\"givenname\":[],\"initials\":{\"optional\":true},\"kolabdelegate\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true},\"kolabinvitationpolicy\":{\"type\":\"select\",\"values\":[\"\",\"ACT_MANUAL\",\"ACT_REJECT\"],\"optional\":true},\"kolaballowsmtprecipient\":{\"type\":\"list\",\"optional\":true},\"kolaballowsmtpsender\":{\"type\":\"list\",\"optional\":true},\"l\":{\"optional\":true},\"mailalternateaddress\":{\"type\":\"list\",\"optional\":true},\"mailquota\
 ":{\"type\":\"text-quota\",\"optional\":true},\"mobile\":{\"optional\":true},\"nsroledn\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true},\"o\":{\"optional\":true},\"ou\":{\"type\":\"select\"},\"pager\":{\"optional\":true},\"postalcode\":{\"optional\":true},\"preferredlanguage\":{\"type\":\"select\"},\"sn\":[],\"street\":{\"optional\":true},\"telephonenumber\":{\"optional\":true},\"title\":{\"optional\":true},\"userpassword\":{\"optional\":true}},\"fields\":{\"objectclass\":[\"top\",\"inetorgperson\",\"kolabinetorgperson\",\"mailrecipient\",\"organizationalperson\",\"person\"]}}',NULL),(2,'posix','POSIX User','A POSIX user (with a home directory and shell access)','{\"auto_form_fields\":{\"cn\":{\"data\":[\"givenname\",\"sn\"]},\"displayname\":{\"data\":[\"givenname\",\"sn\"]},\"gidnumber\":[],\"homedirectory\":{\"data\":[\"givenname\",\"sn\"]},\"uid\":{\"data\":[\"givenname\",\"sn\"]},\"uidnumber\":[],\"userpassword\":{\"optional\":true}},\"form_fields\":{\"give
 nname\":[],\"initials\":{\"optional\":true},\"preferredlanguage\":{\"type\":\"select\",\"values\":[\"en_US\",\"de_DE\",\"de_CH\",\"en_GB\",\"fi_FI\",\"fr_FR\",\"hu_HU\"]},\"loginshell\":{\"type\":\"select\",\"values\":[\"/bin/bash\",\"/usr/bin/git-shell\",\"/sbin/nologin\"]},\"ou\":{\"type\":\"select\"},\"sn\":[],\"title\":{\"optional\":true},\"userpassword\":{\"optional\":true}},\"fields\":{\"objectclass\":[\"top\",\"inetorgperson\",\"organizationalperson\",\"person\",\"posixaccount\"]}}',NULL),(3,'kolab_posix','Mail-enabled POSIX User','A mail-enabled POSIX User','{\"auto_form_fields\":{\"alias\":{\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"cn\":{\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"displayname\":{\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"gidnumber\":[],\"homedirectory\":{\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"mail\":{\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"mailhost\":{\"optional\":true},\"u
 id\":{\"data\":[\"givenname\",\"preferredlanguage\",\"sn\"]},\"uidnumber\":[],\"userpassword\":{\"optional\":true}},\"form_fields\":{\"alias\":{\"optional\":true},\"givenname\":[],\"initials\":{\"optional\":true},\"kolabdelegate\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true},\"kolabinvitationpolicy\":{\"type\":\"select\",\"values\":[\"\",\"ACT_MANUAL\",\"ACT_REJECT\"],\"optional\":true},\"kolaballowsmtprecipient\":{\"type\":\"list\",\"optional\":true},\"kolaballowsmtpsender\":{\"type\":\"list\",\"optional\":true},\"l\":{\"optional\":true},\"loginshell\":{\"type\":\"select\",\"values\":[\"/bin/bash\",\"/usr/bin/git-shell\",\"/sbin/nologin\"]},\"mailalternateaddress\":{\"type\":\"list\",\"optional\":true},\"mailquota\":{\"type\":\"text-quota\",\"optional\":true},\"mobile\":{\"optional\":true},\"nsroledn\":{\"type\":\"list\",\"autocomplete\":true,\"optional\":true},\"o\":{\"optional\":true},\"ou\":{\"type\":\"select\"},\"pager\":{\"optional\":true},\"postalcode\"
 :{\"optional\":true},\"preferredlanguage\":{\"type\":\"select\"},\"sn\":[],\"street\":{\"optional\":true},\"telephonenumber\":{\"optional\":true},\"title\":{\"optional\":true},\"userpassword\":{\"optional\":true}},\"fields\":{\"objectclass\":[\"top\",\"inetorgperson\",\"kolabinetorgperson\",\"mailrecipient\",\"organizationalperson\",\"person\",\"posixaccount\"]}}',NULL),(4,'contact','Contact','A global address book contact','{\"auto_form_fields\":{\"cn\":{\"data\":[\"givenname\",\"sn\"]},\"displayname\":{\"data\":[\"givenname\",\"sn\"]},\"uid\":{\"data\":[\"givenname\",\"sn\"]},\"userpassword\":{\"optional\":true}},\"form_fields\":{\"cn\":{\"optional\":true},\"displayname\":{\"optional\":true},\"givenname\":[],\"initials\":{\"optional\":true},\"l\":{\"optional\":true},\"mail\":{\"type\":\"list\",\"optional\":true},\"mailalternateaddress\":{\"type\":\"list\",\"optional\":true},\"mobile\":{\"optional\":true},\"o\":{\"optional\":true},\"ou\":{\"type\":\"select\"},\"pager\":{\"o
 ptional\":true},\"postalcode\":{\"optional\":true},\"sn\":[],\"street\":{\"optional\":true},\"telephonenumber\":{\"optional\":true},\"title\":{\"optional\":true},\"userpassword\":{\"optional\":true}},\"fields\":{\"objectclass\":[\"top\",\"inetorgperson\",\"mailrecipient\",\"organizationalperson\",\"person\"]}}',NULL),(5,'forwarding','Mail Forwarding','A mail forwarding account (forwarding only!)','{\"auto_form_fields\":{\"cn\":{\"data\":[\"givenname\",\"sn\"]},\"displayname\":{\"data\":[\"givenname\",\"sn\"]},\"uid\":{\"data\":[\"givenname\",\"sn\"]},\"userpassword\":{\"optional\":true}},\"form_fields\":{\"cn\":{\"optional\":true},\"displayname\":{\"optional\":true},\"givenname\":[],\"initials\":{\"optional\":true},\"l\":{\"optional\":true},\"mail\":{\"type\":\"list\",\"optional\":true},\"mailalternateaddress\":{\"type\":\"list\",\"optional\":true},\"mailforwardingaddress\":{\"type\":\"list\"},\"mobile\":{\"optional\":true},\"o\":{\"optional\":true},\"ou\":{\"type\":\"select
 \"},\"pager\":{\"optional\":true},\"postalcode\":{\"optional\":true},\"sn\":[],\"street\":{\"optional\":true},\"telephonenumber\":{\"optional\":true},\"title\":{\"optional\":true},\"userpassword\":{\"optional\":true}},\"fields\":{\"objectclass\":[\"top\",\"inetorgperson\",\"mailrecipient\",\"organizationalperson\",\"person\"]}}',NULL);
+/*!40000 ALTER TABLE `user_types` ENABLE KEYS */;
+UNLOCK TABLES;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+-- Dump completed on 2014-02-26 10:20:01
diff --git a/doc/sample-insert-ou_types.php b/doc/sample-insert-ou_types.php
new file mode 100644
index 0000000..9f61936
--- /dev/null
+++ b/doc/sample-insert-ou_types.php
@@ -0,0 +1,35 @@
+#!/usr/bin/php
+<?php
+
+    if (isset($_SERVER["REQUEST_METHOD"]) && !empty($SERVER["REQUEST_METHOD"])) {
+        die("Not intended for execution through the webserver, sorry!");
+    }
+
+    require_once("lib/functions.php");
+
+    $db   = SQL::get_instance();
+
+    $result = $db->query("TRUNCATE `ou_types`");
+
+    $attributes = Array(
+            "auto_form_fields" => Array(
+                ),
+            "fields" => Array(
+                    "objectclass" => Array(
+                            "top",
+                            "organizationalunit",
+                        ),
+                ),
+            "form_fields" => Array(
+                    "ou" => Array(),
+                    "description" => Array(
+                        "optional" => true,
+                    ),
+                ),
+        );
+
+    $result = $db->query("INSERT INTO `ou_types` (`key`, `name`, `description`, `attributes`) " .
+                "VALUES ('simple_managed','Standard Organizational Unit', 'A standard organizational unit definition'," .
+                "'" . json_encode($attributes) . "')");
+
+?>
diff --git a/lib/Auth.php b/lib/Auth.php
index 4aee7ad..fa6c455 100644
--- a/lib/Auth.php
+++ b/lib/Auth.php
@@ -320,31 +320,39 @@ class Auth {
         return $this->auth_instance($domain)->list_roles($attributes, $search, $params);
     }
 
+    public function list_organizationalunits($domain = NULL, $attributes = array(), $search = array(), $params = array())
+    {
+        return $this->auth_instance($domain)->list_organizationalunits($attributes, $search, $params);
+    }
+
     public function list_sharedfolders($domain = NULL, $attributes = array(), $search = array(), $params = array())
     {
         return $this->auth_instance($domain)->list_sharedfolders($attributes, $search, $params);
     }
 
-    public function primary_for_valid_domain($domain)
+    public function organizationalunit_add($attributes, $typeid = null)
     {
-        $this->domains = $this->list_domains();
+        return $this->auth_instance()->organizationalunit_add($attributes, $typeid);
+    }
 
-        if (array_key_exists($domain, $this->domains)) {
-            return $domain;
-        }
-        else if (in_array($domain, $this->domains)) {
-            // We know it's not a key!
-            foreach ($this->domains as $parent_domain => $child_domains) {
-                if (in_array($domain, $child_domains)) {
-                    return $parent_domain;
-                }
-            }
+    public function organizationalunit_edit($resource, $attributes, $typeid = null)
+    {
+        return $this->auth_instance()->organizationalunit_edit($resource, $attributes, $typeid);
+    }
 
-            return FALSE;
-        }
-        else {
-            return FALSE;
-        }
+    public function organizationalunit_delete($subject)
+    {
+        return $this->auth_instance()->organizationalunit_delete($subject);
+    }
+
+    public function organizationalunit_find_by_attribute($attribute)
+    {
+        return $this->auth_instance()->organizationalunit_find_by_attribute($attribute);
+    }
+
+    public function organizationalunit_info($resourcedata)
+    {
+        return $this->auth_instance()->organizationalunit_info($resourcedata);
     }
 
     public function resource_add($attributes, $typeid = null)
@@ -372,9 +380,9 @@ class Auth {
         return $this->auth_instance()->resource_info($resourcedata);
     }
 
-    public function role_add($role)
+    public function role_add($role, $typeid = null)
     {
-        return $this->auth_instance()->role_add($role);
+        return $this->auth_instance()->role_add($role, $typeid = null);
     }
 
     public function role_edit($role, $attributes, $typeid = null)
diff --git a/lib/Auth/LDAP.php b/lib/Auth/LDAP.php
index 243c4ab..5e708cd 100644
--- a/lib/Auth/LDAP.php
+++ b/lib/Auth/LDAP.php
@@ -495,6 +495,7 @@ class LDAP extends Net_LDAP3 {
                 break;
 
             case "group":
+            case "ou":
             case "resource":
             case "role":
             case "sharedfolder":
@@ -650,6 +651,20 @@ class LDAP extends Net_LDAP3 {
         return $this->_list($base_dn, $filter, 'sub', $attributes, $search, $params);
     }
 
+    public function list_organizationalunits($attributes = array(), $search = array(), $params = array())
+    {
+        $this->_log(LOG_DEBUG, "Auth::LDAP::list_organizationalunits(" . var_export($attributes, true) . ", " . var_export($search, true) . ", " . var_export($params, true));
+
+        $base_dn = $this->_subject_base_dn('ou');
+        $filter  = $this->conf->get('ou_filter');
+
+        if (!$filter) {
+            $filter = "(objectclass=organizationalunit)";
+        }
+
+        return $this->_list($base_dn, $filter, 'sub', $attributes, $search, $params);
+    }
+
     public function list_resources($attributes = array(), $search = array(), $params = array())
     {
         $this->_log(LOG_DEBUG, "Auth::LDAP::list_resources(" . var_export($attributes, true) . ", " . var_export($search, true) . ", " . var_export($params, true));
@@ -706,12 +721,64 @@ class LDAP extends Net_LDAP3 {
         return $this->_list($base_dn, $filter, 'sub', $attributes, $search, $params);
     }
 
+    public function organizationalunit_add($attrs, $typeid = null)
+    {
+        $base_dn = $this->entry_base_dn('ou', $typeid);
+
+        // TODO: The rdn is configurable as well.
+        // Use [$type_str . "_"]ou_rdn_attr
+        $dn = "ou=" . $attrs['ou'] . "," . $base_dn;
+
+        return $this->entry_add($dn, $attrs);
+    }
+
+    public function organizationalunit_edit($ou, $attributes, $typeid = null)
+    {
+        $ou = $this->organizationalunit_info($ou, array_keys($attributes));
+
+        if (empty($ou)) {
+            return false;
+        }
+
+        $dn = key($ou);
+
+        // We should start throwing stuff over the fence here.
+        return $this->modify_entry($dn, $ou[$dn], $attributes);
+    }
+
+    public function organizationalunit_delete($ou)
+    {
+        return $this->entry_delete($ou, array('objectclass' => 'organizationalunit'));
+    }
+
+    public function organizationalunit_find_by_attribute($attribute)
+    {
+        $attribute['objectclass'] = 'organizationalunit';
+        return $this->entry_find_by_attribute($attribute);
+    }
+
+    public function organizationalunit_info($ou, $attributes = array('*'))
+    {
+        $this->_log(LOG_DEBUG, "Auth::LDAP::organizationalunit_info() for unit " . var_export($ou, true));
+        $this->bind($_SESSION['user']->user_bind_dn, $_SESSION['user']->user_bind_pw);
+
+        $dn = $this->entry_dn($ou, array('objectclass' => 'organizationalunit'));
+
+        if (!$dn) {
+            return false;
+        }
+
+        $this->read_prepare($attributes);
+
+        return $this->_read($dn, $attributes);
+    }
+
     public function resource_add($attrs, $typeid = null)
     {
         $base_dn = $this->entry_base_dn('resource', $typeid);
 
         // TODO: The rdn is configurable as well.
-        // Use [$type_str . "_"]user_rdn_attr
+        // Use [$type_str . "_"]resource_rdn_attr
         $dn = "cn=" . $attrs['cn'] . "," . $base_dn;
 
         return $this->entry_add($dn, $attrs);
@@ -757,12 +824,12 @@ class LDAP extends Net_LDAP3 {
         return $this->_read($resource_dn, $attributes);
     }
 
-    public function role_add($attrs)
+    public function role_add($attrs, $typeid = null)
     {
         $base_dn = $this->entry_base_dn('role', $typeid);
 
         // TODO: The rdn is configurable as well.
-        // Use [$type_str . "_"]user_rdn_attr
+        // Use [$type_str . "_"]role_rdn_attr
         $dn = "cn=" . $attrs['cn'] . "," . $base_dn;
 
         return $this->entry_add($dn, $attrs);
diff --git a/lib/api/kolab_api_service_form_value.php b/lib/api/kolab_api_service_form_value.php
index c93e75e..07eb20b 100644
--- a/lib/api/kolab_api_service_form_value.php
+++ b/lib/api/kolab_api_service_form_value.php
@@ -1147,11 +1147,9 @@ class kolab_api_service_form_value extends kolab_api_service
     private function validate_associateddomain($value, $postdata = array(), $validation_type = null)
     {
         if (!is_array($value)) {
-            $value = (array)($value);
+            $value = (array) $value;
         }
 
-        //console("form_value.validate_associateddomain(\$value)", $value);
-
         return $value;
     }
 
diff --git a/lib/api/kolab_api_service_ou.php b/lib/api/kolab_api_service_ou.php
new file mode 100644
index 0000000..fdfd9ee
--- /dev/null
+++ b/lib/api/kolab_api_service_ou.php
@@ -0,0 +1,212 @@
+<?php
+/*
+ +--------------------------------------------------------------------------+
+ | This file is part of the Kolab Web Admin Panel                           |
+ |                                                                          |
+ | Copyright (C) 2011-2014, Kolab Systems AG                                |
+ |                                                                          |
+ | This program is free software: you can redistribute it and/or modify     |
+ | it under the terms of the GNU Affero General Public License as published |
+ | by the Free Software Foundation, either version 3 of the License, or     |
+ | (at your option) any later version.                                      |
+ |                                                                          |
+ | This program is distributed in the hope that it will be useful,          |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of           |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the             |
+ | GNU Affero General Public License for more details.                      |
+ |                                                                          |
+ | You should have received a copy of the GNU Affero General Public License |
+ | along with this program. If not, see <http://www.gnu.org/licenses/>      |
+ +--------------------------------------------------------------------------+
+ | Author: Aleksander Machniak <machniak at kolabsys.com>                      |
+ | Author: Jeroen van Meeuwen <vanmeeuwen at kolabsys.com>                     |
+ +--------------------------------------------------------------------------+
+*/
+
+/**
+ *
+ */
+class kolab_api_service_ou extends kolab_api_service
+{
+    /**
+     * Returns service capabilities.
+     *
+     * @param string $domain Domain name
+     *
+     * @return array Capabilities list
+     */
+    public function capabilities($domain)
+    {
+        $auth             = Auth::get_instance($domain);
+        $effective_rights = $auth->list_rights('ou');
+        $rights           = array();
+
+        if (in_array('add', $effective_rights['entryLevelRights'])) {
+            $rights['add'] = "w";
+        }
+
+        if (in_array('delete', $effective_rights['entryLevelRights'])) {
+            $rights['delete'] = "w";
+        }
+
+        if (in_array('modrdn', $effective_rights['entryLevelRights'])) {
+            $rights['edit'] = "w";
+        }
+
+        if (in_array('read', $effective_rights['entryLevelRights'])) {
+            $rights['info'] = "r";
+            $rights['find'] = "r";
+            $rights['members_list'] = "r";
+        }
+
+        $rights['effective_rights'] = "r";
+
+        return $rights;
+    }
+
+    /**
+     * Create organizational unit.
+     *
+     * @param array $get   GET parameters
+     * @param array $post  POST parameters
+     *
+     * @return array|bool Unit attributes or False on failure
+     */
+    public function ou_add($getdata, $postdata)
+    {
+        $unit_attributes = $this->parse_input_attributes('ou', $postdata);
+
+        $auth   = Auth::get_instance();
+        $result = $auth->organizationalunit_add($unit_attributes, $postdata['type_id']);
+
+        if ($result) {
+            return $unit_attributes;
+        }
+
+        return FALSE;
+    }
+
+    /**
+     * Delete organizational unit.
+     *
+     * @param array $get   GET parameters
+     * @param array $post  POST parameters
+     *
+     * @return bool True on success, False on failure
+     */
+    public function ou_delete($getdata, $postdata)
+    {
+        if (empty($postdata['id'])) {
+            return FALSE;
+        }
+
+        // TODO: Input validation
+        $auth   = Auth::get_instance();
+        $result = $auth->organizationalunit_delete($postdata['id']);
+
+        if ($result) {
+            return $result;
+        }
+
+        return FALSE;
+    }
+
+    public function ou_edit($getdata, $postdata)
+    {
+        $unit_attributes = $this->parse_input_attributes('ou', $postdata);
+        $unit            = $postdata['id'];
+
+        $auth   = Auth::get_instance();
+        $result = $auth->organizationalunit_edit($postdata['id'], $unit_attributes, $postdata['type_id']);
+
+        // @TODO: return unique attribute or all attributes as ou_add()
+        if ($result) {
+            return true;
+        }
+
+        return false;
+    }
+
+    public function ou_effective_rights($getdata, $postdata)
+    {
+        $auth = Auth::get_instance();
+
+        // Org. units are special in that they are ldapsubentries.
+        if (!empty($getdata['id'])) {
+            $unique_attr = $this->unique_attribute();
+            $unit        = $auth->organizationalunit_find_by_attribute(array($unique_attr => $getdata['id']));
+
+            if (is_array($unit) && count($unit) == 1) {
+                $unit_dn = key($unit);
+            }
+        }
+
+        $effective_rights = $auth->list_rights(empty($unit_dn) ? 'ou' : $unit_dn);
+
+        return $effective_rights;
+    }
+
+    /**
+     * Organizational unit information.
+     *
+     * @param array $get   GET parameters
+     * @param array $post  POST parameters
+     *
+     * @return array|bool Unit attributes or False on failure
+     */
+    public function ou_info($getdata, $postdata)
+    {
+        if (empty($getdata['id'])) {
+            return false;
+        }
+
+        $auth   = Auth::get_instance();
+        $result = $auth->organizationalunit_info($getdata['id']);
+
+        // normalize result
+        $result = $this->parse_result_attributes('ou', $result);
+
+        if ($result) {
+            return $result;
+        }
+
+        return false;
+    }
+
+    /**
+     * Find organizational unit and return its data.
+     * It is a combination of ou.info and ous.list with search capabilities
+     * If the search returns only one record we'll return unit data.
+     *
+     * @param array $get   GET parameters
+     * @param array $post  POST parameters
+     *
+     * @return array|bool Unit attributes, False on error
+     */
+    public function ou_find($get, $post)
+    {
+        $auth       = Auth::get_instance();
+        $attributes = array('');
+        $params     = array('page_size' => 2);
+        $search     = $this->parse_list_search($post);
+
+        // find OU(s)
+        $units = $auth->list_ous(null, $attributes, $search, $params);
+
+        if (empty($units) || empty($units['list']) || $units['count'] > 1) {
+            return false;
+        }
+
+        // get OU data
+        $result = $auth->organizationalunit_info(key($units['list']));
+
+        // normalize result
+        $result = $this->parse_result_attributes('ou', $result);
+
+        if ($result) {
+            return $result;
+        }
+
+        return false;
+    }
+}
diff --git a/lib/api/kolab_api_service_ou_types.php b/lib/api/kolab_api_service_ou_types.php
new file mode 100644
index 0000000..5d3b154
--- /dev/null
+++ b/lib/api/kolab_api_service_ou_types.php
@@ -0,0 +1,62 @@
+<?php
+/*
+ +--------------------------------------------------------------------------+
+ | This file is part of the Kolab Web Admin Panel                           |
+ |                                                                          |
+ | Copyright (C) 2011-2014, Kolab Systems AG                                |
+ |                                                                          |
+ | This program is free software: you can redistribute it and/or modify     |
+ | it under the terms of the GNU Affero General Public License as published |
+ | by the Free Software Foundation, either version 3 of the License, or     |
+ | (at your option) any later version.                                      |
+ |                                                                          |
+ | This program is distributed in the hope that it will be useful,          |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of           |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the             |
+ | GNU Affero General Public License for more details.                      |
+ |                                                                          |
+ | You should have received a copy of the GNU Affero General Public License |
+ | along with this program. If not, see <http://www.gnu.org/licenses/>      |
+ +--------------------------------------------------------------------------+
+ | Author: Aleksander Machniak <machniak at kolabsys.com>                      |
+ | Author: Jeroen van Meeuwen <vanmeeuwen at kolabsys.com>                     |
+ +--------------------------------------------------------------------------+
+*/
+
+/**
+ *
+ */
+class kolab_api_service_ou_types extends kolab_api_service
+{
+    /**
+     * Returns service capabilities.
+     *
+     * @param string $domain Domain name
+     *
+     * @return array Capabilities list
+     */
+    public function capabilities($domain)
+    {
+        return array(
+            'list' => 'r',
+        );
+    }
+
+    /**
+     * Organizational unit types listing.
+     *
+     * @param array $get   GET parameters
+     * @param array $post  POST parameters
+     *
+     * @return array List result with 'list' and 'count' items
+     */
+    public function ou_types_list($get, $post)
+    {
+        $ou_types = $this->object_types('ou');
+
+        return array(
+            'list'  => $ou_types,
+            'count' => count($ou_types),
+        );
+    }
+}
diff --git a/lib/api/kolab_api_service_ous.php b/lib/api/kolab_api_service_ous.php
new file mode 100644
index 0000000..f6f4a62
--- /dev/null
+++ b/lib/api/kolab_api_service_ous.php
@@ -0,0 +1,73 @@
+<?php
+/*
+ +--------------------------------------------------------------------------+
+ | This file is part of the Kolab Web Admin Panel                           |
+ |                                                                          |
+ | Copyright (C) 2011-2014, Kolab Systems AG                                |
+ |                                                                          |
+ | This program is free software: you can redistribute it and/or modify     |
+ | it under the terms of the GNU Affero General Public License as published |
+ | by the Free Software Foundation, either version 3 of the License, or     |
+ | (at your option) any later version.                                      |
+ |                                                                          |
+ | This program is distributed in the hope that it will be useful,          |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of           |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the             |
+ | GNU Affero General Public License for more details.                      |
+ |                                                                          |
+ | You should have received a copy of the GNU Affero General Public License |
+ | along with this program. If not, see <http://www.gnu.org/licenses/>      |
+ +--------------------------------------------------------------------------+
+ | Author: Aleksander Machniak <machniak at kolabsys.com>                      |
+ | Author: Jeroen van Meeuwen <vanmeeuwen at kolabsys.com>                     |
+ +--------------------------------------------------------------------------+
+*/
+
+/**
+ * Service providing roles listing
+ */
+class kolab_api_service_ous extends kolab_api_service
+{
+    public $list_attribs = array(
+        'ou',
+        'objectclass',
+        'entrydn',
+        'description',
+    );
+
+    /**
+     * Returns service capabilities.
+     *
+     * @param string $domain Domain name
+     *
+     * @return array Capabilities list
+     */
+    public function capabilities($domain)
+    {
+        return array(
+            'list' => 'r',
+        );
+    }
+
+    /**
+     * Organizational units listing (with searching).
+     *
+     * @param array $get   GET parameters
+     * @param array $post  POST parameters
+     *
+     * @return array List result with 'list' and 'count' items
+     */
+    public function ous_list($get, $post)
+    {
+        $auth = Auth::get_instance();
+
+        $attributes = $this->parse_list_attributes($post);
+        $params     = $this->parse_list_params($post);
+        $search     = $this->parse_list_search($post);
+
+        $units = $auth->list_organizationalunits(null, $attributes, $search, $params);
+        $units = $this->parse_list_result($units);
+
+        return $units;
+    }
+}
diff --git a/lib/client/kolab_client_task_main.php b/lib/client/kolab_client_task_main.php
index e31f1f9..4590c61 100644
--- a/lib/client/kolab_client_task_main.php
+++ b/lib/client/kolab_client_task_main.php
@@ -31,6 +31,7 @@ class kolab_client_task_main extends kolab_client_task
         'role'          => 'roles',
         'resource'      => 'resources',
         'sharedfolder'  => 'sharedfolders',
+        'ou'            => 'ous',
         'settings'      => 'settings',
         'about'         => 'about',
     );
diff --git a/lib/client/kolab_client_task_ou.php b/lib/client/kolab_client_task_ou.php
new file mode 100644
index 0000000..67c1df3
--- /dev/null
+++ b/lib/client/kolab_client_task_ou.php
@@ -0,0 +1,149 @@
+<?php
+/*
+ +--------------------------------------------------------------------------+
+ | This file is part of the Kolab Web Admin Panel                           |
+ |                                                                          |
+ | Copyright (C) 2011-2014, Kolab Systems AG                                |
+ |                                                                          |
+ | This program is free software: you can redistribute it and/or modify     |
+ | it under the terms of the GNU Affero General Public License as published |
+ | by the Free Software Foundation, either version 3 of the License, or     |
+ | (at your option) any later version.                                      |
+ |                                                                          |
+ | This program is distributed in the hope that it will be useful,          |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of           |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the             |
+ | GNU Affero General Public License for more details.                      |
+ |                                                                          |
+ | You should have received a copy of the GNU Affero General Public License |
+ | along with this program. If not, see <http://www.gnu.org/licenses/>      |
+ +--------------------------------------------------------------------------+
+ | Author: Aleksander Machniak <machniak at kolabsys.com>                      |
+ +--------------------------------------------------------------------------+
+*/
+
+class kolab_client_task_ou extends kolab_client_task
+{
+    protected $ajax_only = true;
+
+    protected $menu = array(
+        'add'  => 'ou.add',
+    );
+
+    protected $list_attribs   = array('ou');
+    protected $search_attribs = array('name'  => array('ou'));
+
+
+    /**
+     * Default action.
+     */
+    public function action_default()
+    {
+        $this->output->set_object('content', 'ou', true);
+        $this->output->set_object('task_navigation', $this->menu());
+
+        $this->action_list();
+
+        // display form to add OU if logged-in user has right to do so
+        $caps = $this->get_capability('actions');
+        if (!empty($caps['ou.add'])) {
+            $this->action_add();
+        }
+        else {
+            $this->output->command('set_watermark', 'taskcontent');
+        }
+    }
+
+    /**
+     * Organizational unit adding (form) action.
+     */
+    public function action_add()
+    {
+        $data   = $this->get_input('data', 'POST');
+        $output = $this->ou_form(null, $data, true);
+
+        $this->output->set_object('taskcontent', $output);
+    }
+
+    /**
+     * Organizational unit information (form) action.
+     */
+    public function action_info()
+    {
+        $id         = $this->get_input('id', 'POST');
+        $result     = $this->api_get('ou.info', array('id' => $id));
+        $resource   = $result->get();
+        $output     = $this->ou_form(null, $resource);
+
+        $this->output->set_object('taskcontent', $output);
+    }
+
+    private function ou_form($attribs, $data = array())
+    {
+        if (empty($attribs['id'])) {
+            $attribs['id'] = 'ou-form';
+        }
+
+        // Form sections
+        $sections = array(
+            'system' => 'ou.system',
+            'other'  => 'ou.other',
+        );
+
+        // field-to-section map and fields order
+        $fields_map = array(
+            'type_id'                   => 'system',
+            'type_id_name'              => 'system',
+            'ou'                        => 'system',
+            'description'               => 'system',
+        );
+
+        // Prepare fields
+        list($fields, $types, $type) = $this->form_prepare('ou', $data);
+
+        $add_mode  = empty($data['id']);
+        $accttypes = array();
+
+        foreach ($types as $idx => $elem) {
+            $accttypes[$idx] = array('value' => $idx, 'content' => $elem['name']);
+        }
+
+        // Add OU type id selector
+        $fields['type_id'] = array(
+            'section'  => 'system',
+            'type'     => kolab_form::INPUT_SELECT,
+            'options'  => $accttypes,
+            'onchange' => "kadm.ou_save(true, 'system')",
+        );
+
+        // Hide account type selector if there's only one type
+        if (count($accttypes) < 2 || !$add_mode) {
+            //console("setting type_id form type to hidden");
+            $fields['type_id']['type'] = kolab_form::INPUT_HIDDEN;
+        }
+
+        // Create mode
+        if ($add_mode) {
+            // Page title
+            $title = $this->translate('ou.add');
+        }
+        // Edit mode
+        else {
+            $title = $data['ou'];
+
+            // Add OU type name
+            $fields['type_id_name'] = array(
+                'label'    => 'ou.type_id',
+                'section'  => 'system',
+                'value'    => $accttypes[$type]['content'],
+            );
+        }
+
+        // Create form object and populate with fields
+        $form = $this->form_create('ou', $attribs, $sections, $fields, $fields_map, $data, $add_mode);
+
+        $form->set_title(kolab_html::escape($title));
+
+        return $form->output();
+    }
+}
diff --git a/lib/ext/Net/LDAP3.php b/lib/ext/Net/LDAP3.php
index 774a59c..52d8626 100644
--- a/lib/ext/Net/LDAP3.php
+++ b/lib/ext/Net/LDAP3.php
@@ -1420,11 +1420,21 @@ class Net_LDAP3
             $old_ou = implode(',', $subject_dn_components);
         }
 
-        if (!(empty($old_ou) || empty($new_ou)) && !(strtolower($old_ou) === strtolower($new_ou))) {
-            $mod_array['rename']['new_parent'] = $new_ou;
-            if (empty($mod_array['rename']['dn']) || empty($mod_array['rename']['new_rdn'])) {
-                $mod_array['rename']['dn'] = $subject_dn;
-                $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . $new_attrs[$rdn_attr];
+        if ((!empty($old_ou) || !empty($new_ou)) && strtolower($old_ou) !== strtolower($new_ou)) {
+            // object is an organizational unit
+            if (strpos($subject_dn, 'ou=' . $old_ou) === 0) {
+                $mod_array['rename']['new_parent'] = substr($subject_dn, strlen('ou=' . $old_ou) + 1);
+                if (empty($mod_array['rename']['dn']) || empty($mod_array['rename']['new_rdn'])) {
+                    $mod_array['rename']['dn']      = $subject_dn;
+                    $mod_array['rename']['new_rdn'] = 'ou=' . $new_ou;
+                }
+            }
+            else {
+                $mod_array['rename']['new_parent'] = $new_ou;
+                if (empty($mod_array['rename']['dn']) || empty($mod_array['rename']['new_rdn'])) {
+                    $mod_array['rename']['dn']      = $subject_dn;
+                    $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . $new_attrs[$rdn_attr];
+                }
             }
         }
 
diff --git a/lib/kolab_api_controller.php b/lib/kolab_api_controller.php
index 3b6766d..80d5d0f 100644
--- a/lib/kolab_api_controller.php
+++ b/lib/kolab_api_controller.php
@@ -65,6 +65,9 @@ class kolab_api_controller
         $this->add_service('group',             'kolab_api_service_group');
         $this->add_service('group_types',       'kolab_api_service_group_types');
         $this->add_service('groups',            'kolab_api_service_groups');
+        $this->add_service('ou',                'kolab_api_service_ou');
+        $this->add_service('ou_types',          'kolab_api_service_ou_types');
+        $this->add_service('ous',               'kolab_api_service_ous');
         $this->add_service('resource',          'kolab_api_service_resource');
         $this->add_service('resource_types',    'kolab_api_service_resource_types');
         $this->add_service('resources',         'kolab_api_service_resources');
diff --git a/lib/kolab_api_service.php b/lib/kolab_api_service.php
index 858e643..0e01a9e 100644
--- a/lib/kolab_api_service.php
+++ b/lib/kolab_api_service.php
@@ -32,8 +32,8 @@ abstract class kolab_api_service
     protected $conf;
     protected $controller;
     protected $db;
-    protected $supported_types_db = array('group', 'resource', 'role', 'sharedfolder', 'user');
-    protected $supported_types    = array('domain', 'group', 'resource', 'role', 'sharedfolder', 'user');
+    protected $supported_types_db = array('ou', 'group', 'resource', 'role', 'sharedfolder', 'user');
+    protected $supported_types    = array('domain', 'ou', 'group', 'resource', 'role', 'sharedfolder', 'user');
 
     /**
      * Class constructor.
diff --git a/lib/kolab_client_task.php b/lib/kolab_client_task.php
index 8f4ef5d..c9bcae9 100644
--- a/lib/kolab_client_task.php
+++ b/lib/kolab_client_task.php
@@ -46,7 +46,7 @@ class kolab_client_task
     protected $menu         = array();
     protected $cache        = array();
     protected $devel_mode   = false;
-    protected $object_types = array('user', 'group', 'role', 'resource', 'sharedfolder', 'domain');
+    protected $object_types = array('user', 'group', 'role', 'resource', 'sharedfolder', 'ou', 'domain');
     protected $page_size    = 20;
     protected $list_attribs = array();
     protected $list_module;
diff --git a/lib/locale/en_US.php b/lib/locale/en_US.php
index 7f59947..c89fd2c 100644
--- a/lib/locale/en_US.php
+++ b/lib/locale/en_US.php
@@ -125,6 +125,7 @@ $LANG['MB'] = 'MB';
 $LANG['menu.about'] = 'About';
 $LANG['menu.domains'] = 'Domains';
 $LANG['menu.groups'] = 'Groups';
+$LANG['menu.ous'] = 'Units';
 $LANG['menu.resources'] = 'Resources';
 $LANG['menu.roles'] = 'Roles';
 $LANG['menu.settings'] = 'Settings';
@@ -135,6 +136,18 @@ $LANG['modifiersname'] = 'Modified by';
 $LANG['password.generate'] = 'Generate password';
 $LANG['reqtime'] = 'Request time: $1 sec.';
 
+$LANG['ou.add'] = 'Add Unit';
+$LANG['ou.add.success'] = 'Unit created successfully.';
+$LANG['ou.ou'] = 'Unit Name';
+$LANG['ou.delete.confirm'] = 'Are you sure, you want to delete this organizational unit?';
+$LANG['ou.delete.success'] = 'Unit deleted successfully.';
+$LANG['ou.description'] = 'Unit Description';
+$LANG['ou.edit.success'] = 'Unit updated successfully.';
+$LANG['ou.list'] = 'Organizational Unit List';
+$LANG['ou.norecords'] = 'No organizational unit records found!';
+$LANG['ou.system'] = 'Details';
+$LANG['ou.type_id'] = 'Unit Type';
+
 $LANG['resource.add'] = 'Add Resource';
 $LANG['resource.add.success'] = 'Resource created successfully.';
 $LANG['resource.cn'] = 'Name';
@@ -237,6 +250,7 @@ $LANG['type.name'] = 'Name';
 $LANG['type.norecords'] = 'No object type records found!';
 $LANG['type.objectclass'] = 'Object class';
 $LANG['type.object_type'] = 'Object type';
+$LANG['type.ou'] = 'Ogranizational Unit';
 $LANG['type.properties'] = 'Properties';
 $LANG['type.resource'] = 'Resource';
 $LANG['type.role'] = 'Role';
diff --git a/public_html/js/kolab_admin.js b/public_html/js/kolab_admin.js
index 87f355b..c9836c8 100644
--- a/public_html/js/kolab_admin.js
+++ b/public_html/js/kolab_admin.js
@@ -1583,6 +1583,58 @@ function kolab_admin()
     this.response_handler(response, 'group.edit', 'group.list');
   };
 
+  this.ou_info = function(id)
+  {
+    this.http_post('ou.info', {id: id});
+  };
+
+  this.ou_list = function(props)
+  {
+    this.list_handler('ou', props);
+  };
+
+  this.ou_delete = function(id)
+  {
+    this.delete_handler(id, 'ou');
+  };
+
+  this.ou_save = function(reload, section)
+  {
+    var data = this.serialize_form('#'+this.env.form_id),
+      action = data.id ? 'edit' : 'add';
+
+    if (reload) {
+      data.section = section;
+      this.http_post('ou.' + action, {data: data});
+      return;
+    }
+
+    this.form_error_clear();
+
+    if (!this.check_required_fields(data)) {
+      this.display_message('form.required.empty', 'error');
+      return;
+    }
+
+    this.set_busy(true, 'saving');
+    this.api_post('ou.' + action, data, 'ou_' + action + '_response');
+  };
+
+  this.ou_delete_response = function(response)
+  {
+    this.response_handler(response, 'ou.delete', 'ou.list');
+  };
+
+  this.ou_add_response = function(response)
+  {
+    this.response_handler(response, 'ou.add', 'ou.list');
+  };
+
+  this.ou_edit_response = function(response)
+  {
+    this.response_handler(response, 'ou.edit', 'ou.list');
+  };
+
   this.resource_info = function(id)
   {
     this.http_post('resource.info', {id: id});
diff --git a/public_html/skins/default/templates/ou.html b/public_html/skins/default/templates/ou.html
new file mode 100644
index 0000000..6928c6c
--- /dev/null
+++ b/public_html/skins/default/templates/ou.html
@@ -0,0 +1,17 @@
+<div id="toc" class="ou">
+    <div id="search">
+        <div class="searchinput">
+            <input type="text" id="searchinput" name="search" value="{$engine->translate('search')}" />
+            <script type="text/javascript">search_init('ou.list')</script>
+            <span class="searchactions">
+                <span id="search-details" title="{$engine->translate('search.criteria')}" onclick="search_details()"></span>
+                <span id="search-reset" title="{$engine->translate('search.reset')}" onclick="search_reset()"></span>
+            </span>
+        </div>
+        <div class="searchdetails">{$engine->search_form()}</div>
+    </div>
+    <div id="oulist"></div>
+</div>
+<div class="vsplitter"> </div>
+<div id="taskcontent" class="ou"></div>
+<div class="clear"></div>




More information about the commits mailing list