summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksander Machniak <machniak@kolabsys.com>2012-06-16 19:28:23 +0200
committerAleksander Machniak <machniak@kolabsys.com>2012-06-16 19:28:23 +0200
commitd985ff4f32cf0ea469b719f0dbc84b7de2ecf91e (patch)
tree078779aa966affa9249bc83314a742588df79560
parent8a403ad59ea258b38bddf128cc6c32576849d9a2 (diff)
parent33a7c6a176fa6162c8f0394896225391f8fe109f (diff)
downloadwebadmin-d985ff4f32cf0ea469b719f0dbc84b7de2ecf91e.tar.gz
Merge branch 'master' of ssh://git.kolab.org/git/kolab-wap
Conflicts: lib/locale/en_US.php
-rw-r--r--.gitignore2
-rwxr-xr-xbin/disable-all-console-messages4
-rwxr-xr-xbin/enable-all-console-messages4
-rw-r--r--doc/kolab_wap-3.0.0.sql54
-rw-r--r--lib/Auth.php63
-rw-r--r--lib/Auth/LDAP.php690
-rw-r--r--lib/Conf.php84
-rw-r--r--lib/User.php2
-rw-r--r--lib/api/kolab_api_service_domain.php145
-rw-r--r--lib/api/kolab_api_service_domains.php1
-rw-r--r--lib/api/kolab_api_service_form_value.php460
-rw-r--r--lib/api/kolab_api_service_group.php2
-rw-r--r--lib/api/kolab_api_service_resource.php185
-rw-r--r--lib/api/kolab_api_service_resource_types.php64
-rw-r--r--lib/api/kolab_api_service_resources.php147
-rw-r--r--lib/api/kolab_api_service_user.php4
-rw-r--r--lib/client/kolab_client_task_domain.php350
-rw-r--r--lib/client/kolab_client_task_group.php4
-rw-r--r--lib/client/kolab_client_task_main.php9
-rw-r--r--lib/client/kolab_client_task_resource.php329
-rw-r--r--lib/client/kolab_client_task_role.php339
-rw-r--r--lib/client/kolab_client_task_user.php18
-rw-r--r--lib/functions.php13
-rw-r--r--lib/kolab_api_controller.php43
-rw-r--r--lib/kolab_api_service.php175
-rw-r--r--lib/kolab_client_api.php26
-rw-r--r--lib/kolab_client_output.php15
-rw-r--r--lib/kolab_client_task.php67
-rw-r--r--lib/kolab_recipient_policy.php26
-rw-r--r--lib/locale/en_US.php205
-rw-r--r--public_html/api/index.php2
-rw-r--r--public_html/js/kolab_admin.js123
-rw-r--r--public_html/skins/default/style.css3
-rw-r--r--public_html/skins/default/templates/domain.html17
-rw-r--r--public_html/skins/default/templates/resource.html17
-rw-r--r--public_html/skins/default/templates/role.html17
36 files changed, 3249 insertions, 460 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9b26e6f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+cache/*.php
+logs/*
diff --git a/bin/disable-all-console-messages b/bin/disable-all-console-messages
new file mode 100755
index 0000000..4af5f3b
--- /dev/null
+++ b/bin/disable-all-console-messages
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+sed -r -i -e 's|^(\s*)console|\1//console|g' `find . -type f -name "*.php"`
+
diff --git a/bin/enable-all-console-messages b/bin/enable-all-console-messages
new file mode 100755
index 0000000..d5640d5
--- /dev/null
+++ b/bin/enable-all-console-messages
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+sed -r -i -e 's|^(\s*)//console|\1console|g' `find . -type f -name "*.php"`
+
diff --git a/doc/kolab_wap-3.0.0.sql b/doc/kolab_wap-3.0.0.sql
index b94eb00..641cadd 100644
--- a/doc/kolab_wap-3.0.0.sql
+++ b/doc/kolab_wap-3.0.0.sql
@@ -1,11 +1,11 @@
-- phpMyAdmin SQL Dump
--- version 3.4.8
+-- version 3.5.1
-- http://www.phpmyadmin.net
--
-- Host: localhost
--- Generation Time: Mar 29, 2012 at 04:24 PM
--- Server version: 5.5.13
--- PHP Version: 5.3.8
+-- Generation Time: May 25, 2012 at 12:21 PM
+-- Server version: 5.5.23
+-- PHP Version: 5.4.1
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
@@ -17,7 +17,7 @@ SET time_zone = "+00:00";
/*!40101 SET NAMES utf8 */;
--
--- Database: `kolab_wap`
+-- Database: `kolab`
--
-- --------------------------------------------------------
@@ -34,15 +34,16 @@ CREATE TABLE IF NOT EXISTS `group_types` (
`attributes` longtext NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
-) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
--
-- Dumping data for table `group_types`
--
INSERT INTO `group_types` (`id`, `key`, `name`, `description`, `attributes`) VALUES
-(1, 'kolab', 'Kolab Distribution Group', 'A Kolab Distribution Group (with mail address)', 's:187:"{"auto_form_fields":{"mail":{"data":["cn"]}},"fields":{"objectclass":["top","groupofuniquenames","kolabgroupofuniquenames"]},"form_fields":{"cn":[],"uniquemember":{"type":"multiselect"}}}";'),
-(2, 'posix', 'POSIX Group', 'A UNIX POSIX Group', 's:166:"{"auto_form_fields":{"gidnumber":[]},"fields":{"objectclass":["top","groupofuniquenames","posixgroup"]},"form_fields":{"cn":[],"uniquemember":{"type":"multiselect"}}}";');
+(1, 'kolab', 'Kolab Distribution Group', 'A Kolab Distribution Group (with mail address)', '{"auto_form_fields":{"mail":{"data":["cn"]}},"fields":{"objectclass":["top","groupofuniquenames","kolabgroupofuniquenames"]},"form_fields":{"cn":[],"uniquemember":{"type":"list","autocomplete":true,"optional":true}}}'),
+(2, '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}}}'),
+(3, '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":[],"mail":{"optional":true},"uniquemember":{"type":"list","autocomplete":true,"optional":true}}}');
-- --------------------------------------------------------
@@ -60,7 +61,35 @@ CREATE TABLE IF NOT EXISTS `options` (
--
INSERT INTO `options` (`attribute`, `option_values`) 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","ru_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"]');
+('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","ru_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"]');
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `resource_types`
+--
+
+CREATE TABLE IF NOT EXISTS `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 DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
+
+--
+-- Dumping data for table `resource_types`
+--
+
+INSERT INTO `resource_types` (`id`, `key`, `name`, `description`, `attributes`) 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":[]}}');
-- --------------------------------------------------------
@@ -76,15 +105,16 @@ CREATE TABLE IF NOT EXISTS `user_types` (
`attributes` longtext NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
-) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
--
-- Dumping data for table `user_types`
--
INSERT INTO `user_types` (`id`, `key`, `name`, `description`, `attributes`) VALUES
-(1, 'kolab', 'Kolab User', 'A Kolab User', '{"auto_form_fields":{"cn":{"data":["givenname","sn"]},"displayname":{"data":["givenname","sn"]},"mail":{"data":["givenname","preferredlanguage","sn"]},"mailalternateaddress":{"data":["givenname","preferredlanguage","sn"]},"mailhost":[],"uid":{"data":["givenname","preferredlanguage","sn"]},"userpassword":[]},"form_fields":{"initials":[],"givenname":[],"mailalternateaddress":{"type":"list"},"nsrole":{"type":"list","autocomplete":true},"preferredlanguage":{"type":"select","values":["en_US","de_DE","de_CH","en_GB","fr_FR"]},"sn":[],"title":[]},"fields":{"objectclass":["top","inetorgperson","organizationalperson","person","kolabinetorgperson"]}}'),
-(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":[]},"form_fields":{"givenname":[],"initials":[],"preferredlanguage":{"type":"select","values_source":"<uri>"},"shell":{"type":"select","values":["/bin/bash","/usr/bin/git-shell","/sbin/nologin"]},"sn":[],"title":[]},"fields":{"objectclass":["top","inetorgperson","organizationalperson","person","posixaccount"]}}');
+(1, 'kolab', 'Kolab User', 'A Kolab User', '{"auto_form_fields":{"cn":{"data":["givenname","sn"]},"displayname":{"data":["givenname","sn"]},"mail":{"data":["givenname","preferredlanguage","sn"]},"alias":{"data":["givenname","preferredlanguage","sn"],"optional":true},"mailhost":{"optional":true},"uid":{"data":["givenname","preferredlanguage","sn"]},"userpassword":{"optional":true}},"form_fields":{"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},"alias":{"type":"list","optional":true},"mailquota":{"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"]}}'),
+(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":{"givenname":[],"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"]}}'),
+(3, 'kolab_posix', 'Mail-enabled POSIX User', 'A mail-enabled POSIX User', '{"auto_form_fields":{"cn":{"data":["givenname","preferredlanguage","sn"]},"displayname":{"data":["givenname","preferredlanguage","sn"]},"gidnumber":[],"homedirectory":{"data":["givenname","preferredlanguage","sn"]},"mail":{"data":["givenname","preferredlanguage","sn"]},"alias":{"data":["givenname","preferredlanguage","sn"],"optional":true},"mailhost":{"optional":true},"uid":{"data":["givenname","preferredlanguage","sn"]},"uidnumber":[],"userpassword":{"optional":true}},"form_fields":{"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"]},"alias":{"type":"list","optional":true},"mailquota":{"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"]}}');
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
diff --git a/lib/Auth.php b/lib/Auth.php
index fd34e97..5176933 100644
--- a/lib/Auth.php
+++ b/lib/Auth.php
@@ -205,6 +205,26 @@ class Auth {
return $this->_auth[$_SESSION['user']->get_domain()]->attribute_details($attributes);
}
+ public function domain_add($domain, $parent_domain=null)
+ {
+ return $this->_auth[$_SESSION['user']->get_domain()]->domain_add($domain, $parent_domain);
+ }
+
+ public function domain_edit($domain, $attributes, $typeid = null)
+ {
+ return $this->_auth[$_SESSION['user']->get_domain()]->domain_edit($domain, $attributes, $typeid);
+ }
+
+ public function domain_find_by_attribute($attribute)
+ {
+ return $this->_auth[$_SESSION['user']->get_domain()]->domain_find_by_attribute($attribute);
+ }
+
+ public function domain_info($domaindata)
+ {
+ return $this->_auth[$_SESSION['user']->get_domain()]->domain_info($domaindata);
+ }
+
public function find_user_groups($member_dn)
{
return $this->_auth[$_SESSION['user']->get_domain()]->find_user_groups($member_dn);
@@ -286,6 +306,19 @@ class Auth {
return $groups;
}
+ public function list_resources($domain = NULL, $attributes = array(), $search = array(), $params = array())
+ {
+ $this->connect($domain);
+ if ($domain === NULL) {
+ $domain = $this->conf->get('primary_domain');
+ }
+
+ $resources = $this->_auth[$domain]->list_resources($attributes, $search, $params);
+
+ return $resources;
+ }
+
+
public function list_roles($domain = NULL, $attributes = array(), $search = array(), $params = array())
{
$this->connect($domain);
@@ -320,6 +353,36 @@ class Auth {
}
}
+ public function resource_add($attributes, $typeid = null)
+ {
+ return $this->_auth[$_SESSION['user']->get_domain()]->resource_add($attributes, $typeid);
+ }
+
+ public function resource_edit($resource, $attributes, $typeid = null)
+ {
+ return $this->_auth[$_SESSION['user']->get_domain()]->resource_edit($resource, $attributes, $typeid);
+ }
+
+ public function resource_delete($subject)
+ {
+ return $this->_auth[$_SESSION['user']->get_domain()]->resource_delete($subject);
+ }
+
+ public function resource_find_by_attribute($attribute)
+ {
+ return $this->_auth[$_SESSION['user']->get_domain()]->resource_find_by_attribute($attribute);
+ }
+
+ public function resource_info($resourcedata)
+ {
+ return $this->_auth[$_SESSION['user']->get_domain()]->resource_info($resourcedata);
+ }
+
+ public function resource_members_list($resourcedata, $recurse = true)
+ {
+ return $this->_auth[$_SESSION['user']->get_domain()]->resource_members_list($resourcedata, $recurse);
+ }
+
public function search()
{
$this->connect($domain);
diff --git a/lib/Auth/LDAP.php b/lib/Auth/LDAP.php
index bcd3491..7146f71 100644
--- a/lib/Auth/LDAP.php
+++ b/lib/Auth/LDAP.php
@@ -72,7 +72,7 @@ class LDAP
$domain = $_SESSION['user']->get_domain();
} catch (Exception $e) {
// TODO: Debug logging
- error_log("Warning, user not authenticated yet");
+ //console("Warning, user not authenticated yet");
}
}
}
@@ -128,7 +128,7 @@ class LDAP
*/
public function authenticate($username, $password)
{
- error_log("LDAP authentication request for $username");
+ //console("LDAP authentication request for $username");
if (!$this->_connect()) {
return false;
@@ -189,17 +189,17 @@ class LDAP
$_SESSION['user']->user_root_dn = $root_dn;
$_SESSION['user']->user_bind_dn = $subject_dn;
$_SESSION['user']->user_bind_pw = $password;
- error_log("Successfully bound with User DN: " . $_SESSION['user']->user_bind_dn);
+ //console("Successfully bound with User DN: " . $_SESSION['user']->user_bind_dn);
}
else {
- error_log("Successfully bound with User DN: " . $subject_dn . " but not saving it to the session");
+ //console("Successfully bound with User DN: " . $subject_dn . " but not saving it to the session");
}
// @TODO: return unique attribute
return $subject_dn;
}
else {
- error_log("LDAP Error: " . $this->_errstr());
+ //console("LDAP Error: " . $this->_errstr());
return false;
}
}
@@ -236,7 +236,7 @@ class LDAP
}
}
} else {
- error_log("No schema details exist for attribute $attribute (which is strange)");
+ //console("No schema details exist for attribute $attribute (which is strange)");
}
// The relevant parts only, please
@@ -292,17 +292,71 @@ class LDAP
}
- public function domain_add($domain, $domain_alias = false, $prepopulate = true)
+ public function domain_add($domain, $parent_domain = false, $prepopulate = true)
{
// Apply some routines for access control to this function here.
- if ($domain_alias) {
- return $this->_domain_add_alias($domain, $domain_alias);
+ if (!empty($parent_domain)) {
+ return $this->_domain_add_alias($domain, $parent_domain);
}
else {
return $this->_domain_add_new($domain, $prepopulate);
}
}
+ public function domain_edit($domain, $attributes, $typeid = null)
+ {
+ // Domain identifier
+ $unique_attr = $this->unique_attribute();
+ $attributes[$unique_attr] = $domain;
+
+ // Now that values have been re-generated where necessary, compare
+ // the new domain attributes to the original domain attributes.
+ $_domain = $this->domain_find_by_attribute(array($unique_attr => $attributes[$unique_attr]));
+
+ if (!$_domain) {
+ //console("Could not find domain");
+ return false;
+ }
+
+ $_domain_dn = key($_domain);
+ $_domain = $this->domain_info($_domain_dn, array_keys($attributes));
+
+ // We should start throwing stuff over the fence here.
+ return $this->modify_entry($_domain_dn, $_domain[$_domain_dn], $attributes);
+ }
+
+ public function domain_find_by_attribute($attribute)
+ {
+ $conf = Conf::get_instance();
+ $base_dn = $conf->get('ldap', 'domain_base_dn');
+ return $this->entry_find_by_attribute($attribute, $base_dn);
+ }
+
+ public function domain_info($domain, $attributes = array('*'))
+ {
+ $conf = Conf::get_instance();
+
+ $domain_dn = $this->entry_dn($domain);
+
+ if (!$domain_dn) {
+ $domain_base_dn = $conf->get('ldap', 'domain_base_dn');
+ $domain_filter = $conf->get('ldap', 'domain_filter');
+ $domain_name_attribute = $conf->get('ldap', 'domain_name_attribute');
+ $domain_filter = "(&$domain_filter($domain_name_attribute=$domain))";
+ $result = self::normalize_result($this->_search($domain_base_dn, $domain_filter, $attributes));
+ } else {
+ $result = self::normalize_result($this->_search($domain_dn, '(objectclass=*)', $attributes));
+ }
+
+ if (!$result) {
+ return false;
+ }
+
+ //console("domain_info() result:", $result);
+
+ return $result;
+ }
+
public function effective_rights($subject)
{
$effective_rights_control_oid = "1.3.6.1.4.1.42.2.27.9.5.2";
@@ -310,7 +364,7 @@ class LDAP
$supported_controls = $this->supported_controls();
if (!in_array($effective_rights_control_oid, $supported_controls)) {
- error_log("No getEffectiveRights control in supportedControls");
+ //console("No getEffectiveRights control in supportedControls");
return $this->legacy_rights($subject);
}
@@ -333,16 +387,20 @@ class LDAP
//console("effective_rights for $subject resolves to $entry_dn");
+ $moz_ldapsearch = "/usr/lib64/mozldap/ldapsearch";
+ if (!is_file($moz_ldapsearch)) {
+ $moz_ldapsearch = "/usr/lib/mozldap/ldapsearch";
+ }
+
$command = array(
- // TODO: Very 64-bit specific
- '/usr/lib64/mozldap/ldapsearch',
+ $moz_ldapsearch,
'-x',
'-h',
$this->_ldap_server,
'-p',
$this->_ldap_port,
'-b',
- $conf->get('base_dn'),
+ '"' . $entry_dn . '"',
'-D',
'"' . $_SESSION['user']->user_bind_dn . '"',
'-w',
@@ -356,7 +414,9 @@ class LDAP
'dn:' . $_SESSION['user']->user_bind_dn // User DN
)
) . '"',
- '"(entrydn=' . $entry_dn . ')"',
+ '-s',
+ 'base',
+ '"(objectclass=*)"',
'"*"',
);
@@ -399,6 +459,28 @@ class LDAP
return $attributes;
}
+ public function find_user_groups($member_dn)
+ {
+ //console(__FILE__ . "(" . __LINE__ . "): " . $member_dn);
+
+ $groups = array();
+
+ $root_dn = $this->domain_root_dn($this->domain);
+
+ // TODO: Do not query for both, it's either one or the other
+ $entries = $this->_search($root_dn, "(|" .
+ "(&(objectclass=groupofnames)(member=$member_dn))" .
+ "(&(objectclass=groupofuniquenames)(uniquemember=$member_dn))" .
+ ")");
+
+ $entries = self::normalize_result($entries);
+
+ foreach ($entries as $entry_dn => $entry_attributes) {
+ $groups[] = $entry_dn;
+ }
+
+ return $groups;
+ }
public function get_attribute($subject_dn, $attribute)
{
@@ -422,6 +504,101 @@ class LDAP
return false;
}
+ public function group_add($attrs, $typeid = null)
+ {
+ if ($typeid == null) {
+ $type_str = 'group';
+ }
+ else {
+ $db = SQL::get_instance();
+ $_key = $db->fetch_assoc($db->query("SELECT `key` FROM group_types WHERE id = ?", $typeid));
+ $type_str = $_key['key'];
+ }
+
+ // Check if the group_type has a specific base DN specified.
+ $base_dn = $this->conf->get($type_str . "_group_base_dn");
+ // If not, take the regular user_base_dn
+ if (!$base_dn)
+ $base_dn = $this->conf->get("group_base_dn");
+
+ // TODO: The rdn is configurable as well.
+ // Use [$type_str . "_"]user_rdn_attr
+ $dn = "cn=" . $attrs['cn'] . "," . $base_dn;
+
+ return $this->_add($dn, $attrs);
+ }
+
+ public function group_delete($group)
+ {
+ $group_dn = $this->entry_dn($group);
+
+ if (!$group_dn) {
+ return false;
+ }
+
+ return $this->_delete($group_dn);
+ }
+
+ public function group_edit($group, $attributes, $typeid = null)
+ {
+/*
+ // Get the type "key" string for the next few settings.
+ if ($typeid == null) {
+ $type_str = 'group';
+ }
+ else {
+ $db = SQL::get_instance();
+ $_key = $db->fetch_assoc($db->query("SELECT `key` FROM group_types WHERE id = ?", $typeid));
+ $type_str = $_key['key'];
+ }
+*/
+ // Group identifier
+ $unique_attr = $this->unique_attribute();
+ $attributes[$unique_attr] = $group;
+
+ // Now that values have been re-generated where necessary, compare
+ // the new group attributes to the original group attributes.
+ $_group = $this->entry_find_by_attribute(array($unique_attr => $attributes[$unique_attr]));
+
+ if (!$_group) {
+ //console("Could not find group");
+ return false;
+ }
+
+ $_group_dn = key($_group);
+ $_group = $this->group_info($_group_dn, array_keys($attributes));
+
+ // We should start throwing stuff over the fence here.
+ return $this->modify_entry($_group_dn, $_group[$_group_dn], $attributes);
+ }
+
+ public function group_find_by_attribute($attribute)
+ {
+ return $this->entry_find_by_attribute($attribute);
+ }
+
+ public function group_info($group, $attributes = array('*'))
+ {
+ $group_dn = $this->entry_dn($group);
+
+ if (!$group_dn) {
+ return false;
+ }
+
+ return self::normalize_result($this->_search($group_dn, '(objectclass=*)', $attributes));
+ }
+
+ public function group_members_list($group, $recurse = true)
+ {
+ $group_dn = $this->entry_dn($group);
+
+ if (!$group_dn) {
+ return false;
+ }
+
+ return $this->_list_group_members($group_dn, null, $recurse);
+ }
+
public function list_domains()
{
$domains = $this->domains_list();
@@ -484,6 +661,37 @@ class LDAP
return $users;
}
+ public function list_resources($attributes = array(), $search = array(), $params = array())
+ {
+ if (!empty($params['sort_by'])) {
+ if (is_array($params['sort_by'])) {
+ foreach ($params['sort_by'] as $attrib) {
+ if (!in_array($attrib, $attributes)) {
+ $attributes[] = $attrib;
+ }
+ }
+ } else {
+ if (!in_array($params['sort_by'], $attributes)) {
+ $attributes[] = $params['sort_by'];
+ }
+ }
+ }
+
+ $resources = $this->resources_list($attributes, $search);
+ $resources = self::normalize_result($resources);
+
+ if (!empty($params['sort_by'])) {
+ $this->sort_result_key = $params['sort_by'];
+ uasort($resources, array($this, 'sort_result'));
+
+ if ($params['sort_order'] == 'DESC') {
+ $resources = array_reverse($resources, true);
+ }
+ }
+
+ return $resources;
+ }
+
public function list_roles($attributes = array(), $search = array(), $params = array())
{
if (!empty($params['sort_by'])) {
@@ -507,218 +715,207 @@ class LDAP
return $roles;
}
- public function user_add($attrs, $typeid = null)
+ public function resource_add($attrs, $typeid = null)
{
if ($typeid == null) {
- $type_str = 'user';
+ $type_str = 'resource';
}
else {
$db = SQL::get_instance();
- $_key = $db->fetch_assoc($db->query("SELECT `key` FROM user_types WHERE id = ?", $typeid));
+ $_key = $db->fetch_assoc($db->query("SELECT `key` FROM resource_types WHERE id = ?", $typeid));
$type_str = $_key['key'];
}
- // Check if the user_type has a specific base DN specified.
- $base_dn = $this->conf->get($this->domain, $type_str . "_user_base_dn");
+ // Check if the resource_type has a specific base DN specified.
+ $base_dn = $this->conf->get($type_str . "_resource_base_dn");
// If not, take the regular user_base_dn
if (!$base_dn)
- $base_dn = $this->conf->get($this->domain, "user_base_dn");
-
- // If no user_base_dn either, take the user type specific from the parent
- // configuration
- if (!$base_dn)
- $base_dn = $this->conf->get('ldap', $type_str . "_user_base_dn");
-
- if (!empty($attrs['ou'])) {
- $base_dn = $attrs['ou'];
- }
+ $base_dn = $this->conf->get("resource_base_dn");
// TODO: The rdn is configurable as well.
// Use [$type_str . "_"]user_rdn_attr
- $dn = "uid=" . $attrs['uid'] . "," . $base_dn;
+ $dn = "cn=" . $attrs['cn'] . "," . $base_dn;
return $this->_add($dn, $attrs);
}
- public function user_edit($user, $attributes, $typeid = null)
+ public function resource_delete($resource)
+ {
+ $resource_dn = $this->entry_dn($resource);
+
+ if (!$resource_dn) {
+ return false;
+ }
+
+ return $this->_delete($resource_dn);
+ }
+
+ public function resource_edit($resource, $attributes, $typeid = null)
{
/*
// Get the type "key" string for the next few settings.
if ($typeid == null) {
- $type_str = 'user';
+ $type_str = 'resource';
}
else {
$db = SQL::get_instance();
- $_key = $db->fetch_assoc($db->query("SELECT `key` FROM user_types WHERE id = ?", $typeid));
+ $_key = $db->fetch_assoc($db->query("SELECT `key` FROM resource_types WHERE id = ?", $typeid));
$type_str = $_key['key'];
}
*/
+ // Group identifier
$unique_attr = $this->unique_attribute();
- $attributes[$unique_attr] = $user;
+ $attributes[$unique_attr] = $resource;
// Now that values have been re-generated where necessary, compare
- // the new group attributes to the original group attributes.
- $_user = $this->entry_find_by_attribute(array($unique_attr => $attributes[$unique_attr]));
+ // the new resource attributes to the original resource attributes.
+ $_resource = $this->entry_find_by_attribute(array($unique_attr => $attributes[$unique_attr]));
- if (!$_user) {
- //console("Could not find user");
+ if (!$_resource) {
+ //console("Could not find resource");
return false;
}
- $_user_dn = key($_user);
- $_user = $this->user_info($_user_dn, array_keys($attributes));
-
- //console("user_edit \$_user", $_user);
+ $_resource_dn = key($_resource);
+ $_resource = $this->resource_info($_resource_dn, array_keys($attributes));
// We should start throwing stuff over the fence here.
- return $this->modify_entry($_user_dn, $_user[$_user_dn], $attributes);
+ return $this->modify_entry($_resource_dn, $_resource[$_resource_dn], $attributes);
}
- public function user_delete($user)
+ public function resource_find_by_attribute($attribute)
{
- $user_dn = $this->entry_dn($user);
-
- if (!$user_dn) {
- return false;
- }
-
- return $this->_delete($user_dn);
+ return $this->entry_find_by_attribute($attribute);
}
/**
- * User attributes
+ * Resource attributes
*
*
*/
- public function user_info($user, $attributes = array('*'))
+ public function resource_info($resource, $attributes = array('*'))
{
- $user_dn = $this->entry_dn($user);
+ $resource_dn = $this->entry_dn($resource);
- if (!$user_dn)
+ if (!$resource_dn)
return false;
- return self::normalize_result($this->_search($user_dn, '(objectclass=*)', $attributes));
+ return self::normalize_result($this->_search($resource_dn, '(objectclass=*)', $attributes));
}
- public function user_find_by_attribute($attribute)
+ public function resource_members_list($resource, $recurse = true)
{
- return $this->entry_find_by_attribute($attribute);
- }
+ $resource_dn = $this->entry_dn($resource);
- public function find_user_groups($member_dn)
- {
- error_log(__FILE__ . "(" . __LINE__ . "): " . $member_dn);
-
- $groups = array();
-
- $root_dn = $this->domain_root_dn($this->domain);
-
- // TODO: Do not query for both, it's either one or the other
- $entries = $this->_search($root_dn, "(|" .
- "(&(objectclass=groupofnames)(member=$member_dn))" .
- "(&(objectclass=groupofuniquenames)(uniquemember=$member_dn))" .
- ")");
-
- $entries = self::normalize_result($entries);
-
- foreach ($entries as $entry_dn => $entry_attributes) {
- $groups[] = $entry_dn;
+ if (!$resource_dn) {
+ return false;
}
- return $groups;
+ return $this->_list_resource_members($resource_dn, null, $recurse);
}
- public function group_add($attrs, $typeid = null)
+ public function user_add($attrs, $typeid = null)
{
if ($typeid == null) {
- $type_str = 'group';
+ $type_str = 'user';
}
else {
$db = SQL::get_instance();
- $_key = $db->fetch_assoc($db->query("SELECT `key` FROM group_types WHERE id = ?", $typeid));
+ $_key = $db->fetch_assoc($db->query("SELECT `key` FROM user_types WHERE id = ?", $typeid));
$type_str = $_key['key'];
}
- // Check if the group_type has a specific base DN specified.
- $base_dn = $this->conf->get($type_str . "_group_base_dn");
+ // Check if the user_type has a specific base DN specified.
+ $base_dn = $this->conf->get($this->domain, $type_str . "_user_base_dn");
// If not, take the regular user_base_dn
- if (!$base_dn)
- $base_dn = $this->conf->get("group_base_dn");
+ if (empty($base_dn))
+ $base_dn = $this->conf->get($this->domain, "user_base_dn");
+
+ // If no user_base_dn either, take the user type specific from the parent
+ // configuration
+ if (empty($base_dn))
+ $base_dn = $this->conf->get('ldap', $type_str . "_user_base_dn");
+
+ // If still no base dn to add the user to... use the toplevel dn
+ if (empty($base_dn))
+ $base_dn = $this->conf->get($this->domain, "base_dn");
+ if (empty($base_dn))
+ $base_dn = $this->conf->get('ldap', "base_dn");
+
+ if (!empty($attrs['ou'])) {
+ $base_dn = $attrs['ou'];
+ }
+
+ //console("Base DN now: $base_dn");
// TODO: The rdn is configurable as well.
// Use [$type_str . "_"]user_rdn_attr
- $dn = "cn=" . $attrs['cn'] . "," . $base_dn;
+ $dn = "uid=" . $attrs['uid'] . "," . $base_dn;
return $this->_add($dn, $attrs);
}
- public function group_edit($group, $attributes, $typeid = null)
+ public function user_edit($user, $attributes, $typeid = null)
{
/*
// Get the type "key" string for the next few settings.
if ($typeid == null) {
- $type_str = 'group';
+ $type_str = 'user';
}
else {
$db = SQL::get_instance();
- $_key = $db->fetch_assoc($db->query("SELECT `key` FROM group_types WHERE id = ?", $typeid));
+ $_key = $db->fetch_assoc($db->query("SELECT `key` FROM user_types WHERE id = ?", $typeid));
$type_str = $_key['key'];
}
*/
- // Group identifier
$unique_attr = $this->unique_attribute();
- $attributes[$unique_attr] = $group;
+ $attributes[$unique_attr] = $user;
// Now that values have been re-generated where necessary, compare
// the new group attributes to the original group attributes.
- $_group = $this->entry_find_by_attribute(array($unique_attr => $attributes[$unique_attr]));
+ $_user = $this->entry_find_by_attribute(array($unique_attr => $attributes[$unique_attr]));
- if (!$_group) {
- //console("Could not find group");
+ if (!$_user) {
+ //console("Could not find user");
return false;
}
- $_group_dn = key($_group);
- $_group = $this->group_info($_group_dn, array_keys($attributes));
-
- // We should start throwing stuff over the fence here.
- return $this->modify_entry($_group_dn, $_group[$_group_dn], $attributes);
- }
-
- public function group_delete($group)
- {
- $group_dn = $this->entry_dn($group);
+ $_user_dn = key($_user);
+ $_user = $this->user_info($_user_dn, array_keys($attributes));
- if (!$group_dn) {
- return false;
- }
+ //console("Auth::LDAP::user_edit() existing \$_user info", $_user);
- return $this->_delete($group_dn);
+ // We should start throwing stuff over the fence here.
+ return $this->modify_entry($_user_dn, $_user[$_user_dn], $attributes);
}
- public function group_info($group, $attributes = array('*'))
+ public function user_delete($user)
{
- $group_dn = $this->entry_dn($group);
+ $user_dn = $this->entry_dn($user);
- if (!$group_dn) {
+ if (!$user_dn) {
return false;
}
- return self::normalize_result($this->_search($group_dn, '(objectclass=*)', $attributes));
+ return $this->_delete($user_dn);
}
- public function group_members_list($group, $recurse = true)
+ /**
+ * User attributes
+ *
+ *
+ */
+ public function user_info($user, $attributes = array('*'))
{
- $group_dn = $this->entry_dn($group);
+ $user_dn = $this->entry_dn($user);
- if (!$group_dn) {
+ if (!$user_dn)
return false;
- }
- return $this->_list_group_members($group_dn, null, $recurse);
+ return self::normalize_result($this->_search($user_dn, '(objectclass=*)', $attributes));
}
- public function group_find_by_attribute($attribute)
+ public function user_find_by_attribute($attribute)
{
return $this->entry_find_by_attribute($attribute);
}
@@ -738,11 +935,11 @@ class LDAP
return false;
}
- error_log("Searching for domain $domain");
- error_log("From domain to root dn");
+ //console("Searching for domain $domain");
+ //console("From domain to root dn");
if (($this->_bind($conf->get('ldap', 'bind_dn'), $conf->get('ldap', 'bind_pw'))) == false) {
- error_log("WARNING: Invalid Service bind credentials supplied");
+ //console("WARNING: Invalid Service bind credentials supplied");
$this->_bind($conf->manager_bind_dn, $conf->manager_bind_pw);
}
@@ -770,7 +967,7 @@ class LDAP
$this->_unbind();
- error_log("Using $domain_rootdn");
+ //console("Using $domain_rootdn");
return $domain_rootdn;
}
@@ -805,16 +1002,16 @@ class LDAP
return $result;
}
- private function _search($base_dn, $search_filter = '(objectClass=*)', $attributes = array('*'))
- {
- return $this->__search($base_dn, $search_filter, $attributes);
- }
-
private function domains_list()
{
$section = $this->conf->get('kolab', 'auth_mechanism');
$base_dn = $this->conf->get($section, 'domain_base_dn');
- $filter = $this->conf->get($section, 'kolab_domain_filter');
+ $filter = $this->conf->get($section, 'domain_filter');
+
+ $kolab_filter = $this->conf->get($section, 'kolab_domain_filter');
+ if (empty($filter) && !empty($kolab_filter)) {
+ $filter = $kolab_filter;
+ }
return $this->_search($base_dn, $filter);
}
@@ -837,7 +1034,7 @@ class LDAP
}
}
- private function entry_find_by_attribute($attribute)
+ private function entry_find_by_attribute($attribute, $base_dn = null)
{
if (empty($attribute) || !is_array($attribute) || count($attribute) > 1) {
return false;
@@ -855,16 +1052,18 @@ class LDAP
$filter .= ")";
- $base_dn = $this->domain_root_dn($this->domain);
+ if (empty($base_dn)) {
+ $base_dn = $this->domain_root_dn($this->domain);
+ }
$result = self::normalize_result($this->_search($base_dn, $filter, array_keys($attribute)));
if (count($result) > 0) {
- error_log("Results found: " . implode(', ', array_keys($result)));
+ //console("Results found: " . implode(', ', array_keys($result)));
return $result;
}
else {
- error_log("No result");
+ //console("No result");
return false;
}
}
@@ -999,7 +1198,7 @@ class LDAP
$rdn_attr = $rdn_components[0];
- //console($rdn_attr);
+ //console("Auth::LDAP::modify_entry() using rdn attribute: " . $rdn_attr);
$mod_array = Array(
"add" => Array(), // For use with ldap_mod_add()
@@ -1009,32 +1208,91 @@ class LDAP
);
// This is me cheating. Remove this special attribute.
- $old_ou = $old_attrs['ou'];
- $new_ou = $new_attrs['ou'];
- unset($old_attrs['ou']);
- unset($new_attrs['ou']);
+ if (array_key_exists('ou', $old_attrs) || array_key_exists('ou', $new_attrs)) {
+ $old_ou = $old_attrs['ou'];
+ $new_ou = $new_attrs['ou'];
+ unset($old_attrs['ou']);
+ unset($new_attrs['ou']);
+ } else {
+ $old_ou = null;
+ $new_ou = null;
+ }
// Compare each attribute value of the old attrs with the corresponding value
// in the new attrs, if any.
foreach ($old_attrs as $attr => $old_attr_value) {
if (array_key_exists($attr, $new_attrs)) {
- $_sort1 = false;
- $_sort2 = false;
- if (is_array($new_attrs[$attr])) {
+ if (is_array($old_attrs[$attr]) && is_array($new_attrs[$attr])) {
$_sort1 = $new_attrs[$attr];
sort($_sort1);
- }
- if (is_array($old_attr_value)) {
$_sort2 = $old_attr_value;
sort($_sort2);
+ } else {
+ $_sort1 = true;
+ $_sort2 = false;
}
if (!($new_attrs[$attr] === $old_attr_value) && !($_sort1 === $_sort2)) {
//console("Attribute $attr changed from", $old_attr_value, "to", $new_attrs[$attr]);
if ($attr === $rdn_attr) {
- $mod_array['rename']['dn'] = $subject_dn;
- $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . $new_attrs[$attr];
+ //console("This attribute is the RDN attribute. Let's see if it is multi-valued, and if the original still exists in the new value.");
+ if (is_array($old_attrs[$attr])) {
+ if (!is_array($new_attrs[$attr])) {
+ if (in_array($new_attrs[$attr], $old_attrs[$attr])) {
+ // TODO: Need to remove all $old_attrs[$attr] values not equal to $new_attrs[$attr], and not equal to the current $rdn_attr value [0]
+
+ //console("old attrs. is array, new attrs. is not array. new attr. exists in old attrs.");
+
+ $rdn_attr_value = array_shift($old_attrs[$attr]);
+ $_attr_to_remove = array();
+
+ foreach ($old_attrs[$attr] as $value) {
+ if (strtolower($value) != strtolower($new_attrs[$attr])) {
+ $_attr_to_remove[] = $value;
+ }
+ }
+
+ //console("Adding to delete attribute $attr values:" . implode(', ', $_attr_to_remove));
+
+ $mod_array['delete'][$attr] = $_attr_to_remove;
+
+ if (strtolower($new_attrs[$attr]) !== strtolower($rdn_attr_value)) {
+ //console("new attrs is not the same as the old rdn value, issuing a rename");
+ $mod_array['rename']['dn'] = $subject_dn;
+ $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . $new_attrs[$attr][0];
+ }
+
+ } else {
+ //console("new attrs is not the same as any of the old rdn value, issuing a full rename");
+ $mod_array['rename']['dn'] = $subject_dn;
+ $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . $new_attrs[$attr];
+ }
+ } else {
+ // TODO: See if the rdn attr. value is still in $new_attrs[$attr]
+ if (in_array($old_attrs[$attr][0], $new_attrs[$attr])) {
+ //console("Simply replacing attr $attr as rnd attr value is preserved.");
+ $mod_array['replace'][$attr] = $new_attrs[$attr];
+ } else {
+ // TODO: This fails.
+ $mod_array['rename']['dn'] = $subject_dn;
+ $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . $new_attrs[$attr][0];
+ $mod_array['delete'][$attr] = $old_attrs[$attr][0];
+ }
+ }
+ } else {
+ if (!is_array($new_attrs[$attr])) {
+ //console("Renaming " . $old_attrs[$attr] . " to " . $new_attrs[$attr]);
+ $mod_array['rename']['dn'] = $subject_dn;
+ $mod_array['rename']['new_rdn'] = $rdn_attr . '=' . $new_attrs[$attr];
+ } else {
+ //console("Adding to replace");
+ // An additional attribute value is being supplied. Just replace and continue.
+ $mod_array['replace'][$attr] = $new_attrs[$attr];
+ continue;
+ }
+ }
+
} else {
if (empty($new_attrs[$attr])) {
switch ($attr) {
@@ -1095,7 +1353,7 @@ class LDAP
$old_ou = implode(',', $subject_dn_components);
}
- if (!(strtolower($old_ou) === strtolower($new_ou))) {
+ 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;
@@ -1117,15 +1375,43 @@ class LDAP
{
$this->_bind($_SESSION['user']->user_bind_dn, $_SESSION['user']->user_bind_pw);
+ //console($attributes);
+
// Opportunities to set false include failed ldap commands.
$result = true;
+ if (is_array($attributes['rename']) && !empty($attributes['rename'])) {
+ $olddn = $attributes['rename']['dn'];
+ $newrdn = $attributes['rename']['new_rdn'];
+ if (!empty($attributes['rename']['new_parent'])) {
+ $new_parent = $attributes['rename']['new_parent'];
+ } else {
+ $new_parent = null;
+ }
+
+ //console("Attempt to rename $olddn to $newrdn,$new_parent");
+
+ $result = ldap_rename($this->conn, $olddn, $newrdn, $new_parent, true);
+ if ($result) {
+ if ($new_parent) {
+ $subject_dn = $newrdn . ',' . $new_parent;
+ } else {
+ $old_parent_dn_components = ldap_explode_dn($olddn, 0);
+ unset($old_parent_dn_components["count"]);
+ $old_rdn = array_shift($old_parent_dn_components);
+ $old_parent_dn = implode(",", $old_parent_dn_components);
+ $subject_dn = $newrdn . ',' . $old_parent_dn;
+ }
+ }
+
+ }
+
if (is_array($attributes['replace']) && !empty($attributes['replace'])) {
$result = ldap_mod_replace($this->conn, $subject_dn, $attributes['replace']);
}
if (!$result) {
- //console("Failed to replace the following attributes", $attributes['replace']);
+ //console("Failed to replace the following attributes on subject " . $subject_dn, $attributes['replace']);
return false;
}
@@ -1148,22 +1434,8 @@ class LDAP
return false;
}
- if (is_array($attributes['rename']) && !empty($attributes['rename'])) {
- $olddn = $attributes['rename']['dn'];
- $newrdn = $attributes['rename']['new_rdn'];
- if (!empty($attributes['rename']['new_parent'])) {
- $new_parent = $attributes['rename']['new_parent'];
- } else {
- $new_parent = null;
- }
-
- //console("Attempt to rename $olddn to $newrdn,$new_parent");
-
- $result = ldap_rename($this->conn, $olddn, $newrdn, $new_parent, true);
- }
-
if (!$result) {
- error_log("LDAP Error: " . $this->_errstr());
+ //console("LDAP Error: " . $this->_errstr());
return false;
}
@@ -1248,6 +1520,32 @@ class LDAP
return $result['']['supportedcontrol'];
}
+ private function resources_list($attributes = array(), $search = array())
+ {
+ $conf = Conf::get_instance();
+
+ $base_dn = $conf->get('resource_base_dn');
+
+ if (!$base_dn)
+ $base_dn = "ou=Resources," . $conf->get('base_dn');
+
+ $filter = $conf->get('resource_filter');
+ if (!$filter)
+ $filter = '(objectclass=*)';
+
+ if (empty($attributes) || !is_array($attributes)) {
+ $attributes = array('*');
+ }
+
+ if ($s_filter = $this->_search_filter($search)) {
+ // join search filter with objectClass filter
+ $filter = '(&' . $filter . $s_filter . ')';
+ }
+
+ return $this->_search($base_dn, $filter, $attributes);
+ }
+
+
private function users_list($attributes = array(), $search = array())
{
$conf = Conf::get_instance();
@@ -1442,6 +1740,33 @@ class LDAP
return true;
}
+ private function _domain_add_alias($domain, $parent)
+ {
+ $conf = Conf::get_instance();
+ $domain_base_dn = $conf->get('ldap', 'domain_base_dn');
+ $domain_filter = $conf->get('ldap', 'domain_filter');
+
+ $domain_name_attribute = $conf->get('ldap', 'domain_name_attribute');
+
+ $domain_filter = '(&(' . $domain_name_attribute . '=' . $parent . ')' . $domain_filter . ')';
+
+ $domain_entry = self::normalize_result($this->_search($domain_base_dn, $domain_filter));
+
+ // TODO: Catch not having found any such parent domain
+
+ $domain_dn = key($domain_entry);
+
+ // private function modify_entry($subject_dn, $old_attrs, $new_attrs)
+
+ $_old_attr = array($domain_name_attribute => $domain_entry[$domain_dn][$domain_name_attribute]);
+ $_new_attr = array($domain_name_attribute => array($domain_entry[$domain_dn][$domain_name_attribute], $domain));
+
+ return $this->modify_entry($domain_dn, $_old_attr, $_new_attr);
+
+
+
+ }
+
/**
* Shortcut to ldap_bind()
*/
@@ -1458,13 +1783,13 @@ class LDAP
}
// TODO: Debug logging
- error_log("->_bind() Binding with $dn");
+ //console("->_bind() Binding with $dn");
$this->bind_dn = $dn;
$this->bind_pw = $pw;
if (($bind_ok = ldap_bind($this->conn, $dn, $pw)) == false) {
- error_log("LDAP Error: " . $this->_errstr());
+ //console("LDAP Error: " . $this->_errstr());
// Issue error message
return false;
}
@@ -1481,14 +1806,16 @@ class LDAP
return true;
}
+ ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 9);
+
// TODO: Debug logging
- error_log("Connecting to " . $this->_ldap_server . " on port " . $this->_ldap_port);
+ //console("Connecting to " . $this->_ldap_server . " on port " . $this->_ldap_port);
$connection = ldap_connect($this->_ldap_server, $this->_ldap_port);
if ($connection == false) {
$this->conn = null;
// TODO: Debug logging
- error_log("Not connected: " . ldap_err2str() . "(no.) " . ldap_errno());
+ //console("Not connected: " . ldap_err2str() . "(no.) " . ldap_errno());
return false;
}
@@ -1497,7 +1824,7 @@ class LDAP
ldap_set_option($this->conn, LDAP_OPT_PROTOCOL_VERSION, 3);
// TODO: Debug logging
- error_log("Connected!");
+ //console("Connected!");
return true;
}
@@ -1580,6 +1907,11 @@ class LDAP
return $ldap_entries;
}
+ private function _search($base_dn, $search_filter = '(objectClass=*)', $attributes = array('*'))
+ {
+ return $this->__search($base_dn, $search_filter, $attributes);
+ }
+
/**
* Shortcut to ldap_search()
*/
@@ -1600,15 +1932,17 @@ class LDAP
}
if (($search_results = @ldap_search($this->conn, $base_dn, $search_filter, $attributes)) == false) {
- //message("Could not search in " . __METHOD__ . " in " . __FILE__ . " on line " . __LINE__ . ": " . $this->_errstr());
+ //console("Could not search in " . __METHOD__ . " in " . __FILE__ . " on line " . __LINE__ . ": " . $this->_errstr());
return false;
}
if (($entries = ldap_get_entries($this->conn, $search_results)) == false) {
- //message("Could not get the results of the search: " . $this->_errstr());
+ //console("Could not get the results of the search: " . $this->_errstr());
return false;
}
+ //console("__search() entries:", $entries);
+
return $entries;
}
@@ -1704,13 +2038,13 @@ class LDAP
*/
private function _probe_root_dn($entry_root_dn)
{
- error_log("Running for entry root dn: " . $entry_root_dn);
+ //console("Running for entry root dn: " . $entry_root_dn);
if (($tmpconn = ldap_connect($this->_ldap_server)) == false) {
//message("LDAP Error: " . $this->_errstr());
return false;
}
- error_log("User DN: " . $_SESSION['user']->user_bind_dn);
+ //console("User DN: " . $_SESSION['user']->user_bind_dn);
if (($bind_success = ldap_bind($tmpconn, $_SESSION['user']->user_bind_dn, $_SESSION['user']->user_bind_pw)) == false) {
//message("LDAP Error: " . $this->_errstr());
@@ -1771,7 +2105,7 @@ class LDAP
$this->_bind($this->conf->get('manager_bind_dn'), $this->conf->get('manager_bind_pw'));
}
- error_log("Searching for a group dn in $root_dn, with search filter: $search_filter");
+ //console("Searching for a group dn in $root_dn, with search filter: $search_filter");
$search_results = ldap_search($this->conn, $root_dn, $search_filter);
@@ -1795,7 +2129,7 @@ class LDAP
$this->_bind($this->conf->get('manager_bind_dn'), $this->conf->get('manager_bind_pw'));
}
- error_log("Searching for a user dn in $root_dn, with search filter: $search_filter");
+ //console("Searching for a user dn in $root_dn, with search filter: $search_filter");
$search_results = ldap_search($this->conn, $root_dn, $search_filter);
@@ -1819,10 +2153,10 @@ class LDAP
if (is_array($entry) && in_array('objectclass', $entry)) {
if (!in_array(array('groupofnames', 'groupofuniquenames', 'groupofurls'), $entry['objectclass'])) {
- error_log("Called _list_groups_members on a non-group!");
+ //console("Called _list_groups_members on a non-group!");
}
else {
- error_log("Called list_group_members(" . $dn . ")");
+ //console("Called list_group_members(" . $dn . ")");
}
}
@@ -1855,7 +2189,7 @@ class LDAP
private function _list_group_member($dn, $members, $recurse = true)
{
- error_log("Called _list_group_member(" . $dn . ")");
+ //console("Called _list_group_member(" . $dn . ")");
$group_members = array();
@@ -1932,7 +2266,7 @@ class LDAP
private function _list_group_memberurl($dn, $memberurls, $recurse = true)
{
- error_log("Called _list_group_memberurl(" . $dn . ")");
+ //console("Called _list_group_memberurl(" . $dn . ")");
// Use the member attributes to return an array of member ldap objects
// NOTE that the member attribute is supposed to contain a DN
@@ -1946,7 +2280,7 @@ class LDAP
foreach ($entries as $entry_dn => $_entry) {
$group_members[$entry_dn] = $_entry;
- error_log("Found " . $entry_dn);
+ //console("Found " . $entry_dn);
if ($recurse) {
// Nested group
@@ -1970,7 +2304,7 @@ class LDAP
*/
private function _parse_memberurl($url)
{
- error_log("Parsing URL: " . $url);
+ //console("Parsing URL: " . $url);
preg_match('/(.*):\/\/(.*)\/(.*)\?(.*)\?(.*)\?(.*)/', $url, $matches);
return $matches;
}
diff --git a/lib/Conf.php b/lib/Conf.php
index 4f1f883..e91110c 100644
--- a/lib/Conf.php
+++ b/lib/Conf.php
@@ -26,8 +26,15 @@
class Conf {
static private $instance;
+ private $_conf = array();
+
const CONFIG_FILE = '/etc/kolab/kolab.conf';
+ const STRING = 0;
+ const BOOL = 1;
+ const INT = 2;
+ const FLOAT = 3;
+
/**
* This implements the 'singleton' design pattern
*
@@ -49,38 +56,28 @@ class Conf {
return;
}
- $_ini_raw = file(self::CONFIG_FILE);
-
- $this->_conf = array();
+ $this->read_config();
- foreach ($_ini_raw as $_line) {
- if (preg_match('/^\[([a-z0-9-_\.]+)\]/', $_line, $matches)) {
- $_cur_section = $matches[1];
- $this->_conf[$_cur_section] = array();
- unset($_cur_key);
- }
+ }
- if (preg_match('/^;/', $_line, $matches)) {
- }
+ public function get($key1, $key2 = null, $type = null)
+ {
+ $value = $this->expand($this->get_raw($key1, $key2));
- if (preg_match('/^([a-z0-9\.-_]+)\s*=\s*(.*)/', $_line, $matches)) {
- if (isset($_cur_section) && !empty($_cur_section)) {
- $_cur_key = $matches[1];
- $this->_conf[$_cur_section][$matches[1]] = isset($matches[2]) ? $matches[2] : '';
- }
- }
+ if ($value === null) {
+ return $value;
+ }
- if (preg_match('/^\s+(.*)$/', $_line, $matches)) {
- if (isset($_cur_key) && !empty($_cur_key)) {
- $this->_conf[$_cur_section][$_cur_key] .= $matches[1];
- }
- }
+ switch ($type) {
+ case self::INT:
+ return intval($value);
+ case self::FLOAT:
+ return floatval($value);
+ case self::BOOL:
+ return (bool) preg_match('/^(true|1|on|enabled|yes)$/i', $value);
}
- }
- public function get($key1, $key2 = NULL)
- {
- return $this->expand($this->get_raw($key1, $key2));
+ return (string) $value;
}
public function get_list($key1, $key2 = NULL)
@@ -130,7 +127,7 @@ class Conf {
return $this->_conf[$domain_section_name][$key1];
}
} catch (Exception $e) {
- $domain_section_name = $this->get('kolab', 'primary_domain');
+ $domain_section_name = $this->get_raw('kolab', 'primary_domain');
if (isset($this->_conf[$domain_section_name][$key1])) {
return $this->_conf[$domain_section_name][$key1];
}
@@ -154,7 +151,7 @@ class Conf {
// error_log("Could not find setting for \$key1: " . $key1 .
// " with \$key2: " . $key2);
- return false;
+ return null;
}
public function expand($str, $custom = FALSE)
@@ -183,4 +180,35 @@ class Conf {
return $str;
}
}
+
+ private function read_config()
+ {
+ $_ini_raw = file(self::CONFIG_FILE);
+
+ $this->_conf = array();
+
+ foreach ($_ini_raw as $_line) {
+ if (preg_match('/^\[([a-z0-9-_\.]+)\]/', $_line, $matches)) {
+ $_cur_section = $matches[1];
+ $this->_conf[$_cur_section] = array();
+ unset($_cur_key);
+ }
+
+ if (preg_match('/^;/', $_line, $matches)) {
+ }
+
+ if (preg_match('/^([a-z0-9\.-_]+)\s*=\s*(.*)/', $_line, $matches)) {
+ if (isset($_cur_section) && !empty($_cur_section)) {
+ $_cur_key = $matches[1];
+ $this->_conf[$_cur_section][$matches[1]] = isset($matches[2]) ? $matches[2] : '';
+ }
+ }
+
+ if (preg_match('/^\s+(.*)$/', $_line, $matches)) {
+ if (isset($_cur_key) && !empty($_cur_key)) {
+ $this->_conf[$_cur_section][$_cur_key] .= $matches[1];
+ }
+ }
+ }
+ }
}
diff --git a/lib/User.php b/lib/User.php
index d4f8ca0..ea6ae0d 100644
--- a/lib/User.php
+++ b/lib/User.php
@@ -97,7 +97,7 @@ class User
public function groups()
{
- //error_log("Called " . __FUNCTION__ . " on line " . __LINE__ . " of " . __FILE__);
+ //console("Called " . __FUNCTION__ . " on line " . __LINE__ . " of " . __FILE__);
//debug_print_backtrace();
if ($this->_groups || (is_array($this->_groups) && count($this->_groups) >= 1)) {
diff --git a/lib/api/kolab_api_service_domain.php b/lib/api/kolab_api_service_domain.php
new file mode 100644
index 0000000..e00de8f
--- /dev/null
+++ b/lib/api/kolab_api_service_domain.php
@@ -0,0 +1,145 @@
+<?php
+/*
+ +--------------------------------------------------------------------------+
+ | This file is part of the Kolab Web Admin Panel |
+ | |
+ | Copyright (C) 2011-2012, 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@kolabsys.com> |
+ | Author: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> |
+ +--------------------------------------------------------------------------+
+*/
+
+/**
+ * Service providing domain mutations
+ */
+class kolab_api_service_domain extends kolab_api_service
+{
+
+ /**
+ * Returns service capabilities.
+ *
+ * @param string $domain Domain name
+ *
+ * @return array Capabilities list
+ */
+ public function capabilities($domain)
+ {
+ return array(
+ 'add' => 'w',
+ 'edit' => 'w',
+ 'delete' => 'w'
+ );
+ }
+
+ public function domain_add($getdata, $postdata)
+ {
+ if (empty($postdata['domain'])) {
+ return;
+ }
+
+ if (empty($postdata['parent'])) {
+ return;
+ }
+
+ $auth = Auth::get_instance();
+ $auth->domain_add($postdata['domain'], $postdata['parent']);
+ }
+
+ public function domain_edit($getdata, $postdata)
+ {
+ //console("domain_edit \$postdata", $postdata);
+
+ $domain_attributes = $this->parse_input_attributes('domain', $postdata);
+ $domain = $postdata['id'];
+
+ $auth = Auth::get_instance();
+ $result = $auth->domain_edit($postdata['id'], $domain_attributes, $postdata['type_id']);
+
+ // @TODO: return unique attribute or all attributes as domain_add()
+ if ($result) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public function domain_effective_rights($getdata, $postdata)
+ {
+ $auth = Auth::get_instance();
+ $conf = Conf::get_instance();
+
+ //console($getdata);
+
+ if (!empty($getdata['domain'])) {
+ $entry_dn = $getdata['domain'];
+
+ $unique_attr = $conf->get('ldap', 'unique_attribute');
+
+ $domain = $auth->domain_find_by_attribute(
+ array($unique_attr => $entry_dn)
+ );
+
+ //console($domain);
+
+ if (!empty($domain)) {
+ $entry_dn = key($domain);
+ }
+
+ } else {
+ $conf = Conf::get_instance();
+ $entry_dn = $conf->get('ldap', 'domain_base_dn');
+ }
+
+ //console("API/domain.effective_rights(); Using entry_dn: " . $entry_dn);
+
+ // TODO: Fix searching the correct base_dn... Perhaps find the entry
+ // first.
+ $effective_rights = $auth->list_rights($entry_dn);
+
+ //console($effective_rights);
+ return $effective_rights;
+ }
+
+ /**
+ * Domain information.
+ *
+ * @param array $get GET parameters
+ * @param array $post POST parameters
+ *
+ * @return array|bool Domain attributes, False on error
+ */
+ public function domain_info($getdata, $postdata)
+ {
+ if (!isset($getdata['domain'])) {
+ return false;
+ }
+
+ $auth = Auth::get_instance();
+ $result = $auth->domain_info($getdata['domain']);
+
+ // normalize result
+ $result = $this->parse_result_attributes('domain', $result);
+
+ //console("API/domain.info() \$result:", $result);
+
+ if ($result) {
+ return $result;
+ }
+
+ return false;
+ }
+}
diff --git a/lib/api/kolab_api_service_domains.php b/lib/api/kolab_api_service_domains.php
index e964936..439e865 100644
--- a/lib/api/kolab_api_service_domains.php
+++ b/lib/api/kolab_api_service_domains.php
@@ -56,6 +56,7 @@ class kolab_api_service_domains extends kolab_api_service
$auth = Auth::get_instance();
$domains = $auth->list_domains();
+ //console($domains);
$count = count($domains);
// pagination
diff --git a/lib/api/kolab_api_service_form_value.php b/lib/api/kolab_api_service_form_value.php
index 614bd18..4aa7b78 100644
--- a/lib/api/kolab_api_service_form_value.php
+++ b/lib/api/kolab_api_service_form_value.php
@@ -88,35 +88,49 @@ class kolab_api_service_form_value extends kolab_api_service
}
/**
- * Validation of field values.
+ * Generation of values for fields of type LIST.
*
* @param array $getdata GET parameters
* @param array $postdata POST parameters. Required parameters:
+ * - attribute: attribute name
* - type_id: Type identifier
* - object_type: Object type (user, group, etc.)
*
* @return array Response with attribute name as a key
*/
- public function validate($getdata, $postdata)
+ public function list_options($getdata, $postdata)
{
- $attribs = $this->object_type_attributes($postdata['object_type'], $postdata['type_id']);
- $result = array();
+ //console($postdata);
- foreach ((array)$postdata as $attr_name => $attr_value) {
- if (empty($attr_name) || $attr_name == 'type_id' || $attr_name == 'object_type') {
- continue;
- }
+ $attribs = $this->object_type_attributes($postdata['object_type'], $postdata['type_id']);
+ $attr_name = $postdata['attribute'];
+ $result = array(
+ // return search value, so client can match response to request
+ 'search' => $postdata['search'],
+ 'list' => array(),
+ );
- $method_name = 'validate_' . strtolower($attr_name);
+ if (empty($attr_name)) {
+ return $result;
+ }
+
+
+ $method_name = 'list_options_' . strtolower($attr_name) . '_' . strtolower($postdata['object_type']);
+
+ if (!method_exists($this, $method_name)) {
+ //console("Method $method_name doesn't exist");
+
+ $method_name = 'list_options_' . strtolower($attr_name);
if (!method_exists($this, $method_name)) {
- $result[$attr_name] = 'OK';
- continue;
+ return $result;
}
-
- $result[$attr_name] = $this->{$method_name}($attr_value);
}
+ //console($method_name);
+
+ $result['list'] = $this->{$method_name}($postdata, $attribs);
+
return $result;
}
@@ -158,43 +172,42 @@ class kolab_api_service_form_value extends kolab_api_service
}
/**
- * Generation of values for fields of type LIST.
+ * Validation of field values.
*
* @param array $getdata GET parameters
* @param array $postdata POST parameters. Required parameters:
- * - attribute: attribute name
* - type_id: Type identifier
* - object_type: Object type (user, group, etc.)
*
* @return array Response with attribute name as a key
*/
- public function list_options($getdata, $postdata)
+ public function validate($getdata, $postdata)
{
- //console($postdata);
+ console("Executing validate() for \$getdata, \$postdata", $getdata, $postdata);
- $attribs = $this->object_type_attributes($postdata['object_type'], $postdata['type_id']);
- $attr_name = $postdata['attribute'];
- $result = array(
- // return search value, so client can match response to request
- 'search' => $postdata['search'],
- 'list' => array(),
- );
+ $attribs = $this->object_type_attributes($postdata['object_type'], $postdata['type_id']);
+ $result = array();
- if (empty($attr_name)) {
- return $result;
- }
+ foreach ((array)$postdata as $attr_name => $attr_value) {
+ if (empty($attr_name) || $attr_name == 'type_id' || $attr_name == 'object_type') {
+ continue;
+ }
- $method_name = 'list_options_' . strtolower($attr_name);
+ $method_name = 'validate_' . strtolower($attr_name) . '_' . strtolower($postdata['object_type']);
- //console($method_name);
+ if (!method_exists($this, $method_name)) {
+ //console("Method $method_name doesn't exist");
- if (!method_exists($this, $method_name)) {
- return $result;
- }
+ $method_name = 'validate_' . strtolower($attr_name);
- //console("Still here");
+ if (!method_exists($this, $method_name)) {
+ $result[$attr_name] = 'OK';
+ continue;
+ }
+ }
- $result['list'] = $this->{$method_name}($postdata, $attribs);
+ $result[$attr_name] = $this->{$method_name}($attr_value);
+ }
return $result;
}
@@ -221,6 +234,46 @@ class kolab_api_service_form_value extends kolab_api_service
}
}
+ private function generate_cn_resource($postdata, $attribs = array())
+ {
+ if (isset($attribs['auto_form_fields']) && isset($attribs['auto_form_fields']['cn'])) {
+ // Use Data Please
+ foreach ($attribs['auto_form_fields']['cn']['data'] as $key) {
+ if (!isset($postdata[$key])) {
+ throw new Exception("Key not set: " . $key, 12356);
+ }
+ }
+
+ $auth = Auth::get_instance($_SESSION['user']->get_domain());
+ $conf = Conf::get_instance();
+
+ $unique_attr = $conf->get('unique_attribute');
+ if (!$unique_attr) {
+ $unique_attr = 'nsuniqueid';
+ }
+
+ $cn = $postdata['cn'];
+
+ $x = 2;
+ while (($resource_found = $auth->resource_find_by_attribute(array('cn' => $cn)))) {
+ if (!empty($postdata['id'])) {
+ $resource_found_dn = key($resource_found);
+ $resource_found_unique_attr = $auth->get_attribute($resource_found_dn, $unique_attr);
+ //console("resource with mail $mail found", $resource_found_unique_attr);
+ if ($resource_found_unique_attr == $postdata['id']) {
+ //console("that's us.");
+ break;
+ }
+ }
+
+ $cn = $postdata['cn'] . ' #' . $x;
+ $x++;
+ }
+
+ return $cn;
+ }
+ }
+
private function generate_displayname($postdata, $attribs = array())
{
if (isset($attribs['auto_form_fields']) && isset($attribs['auto_form_fields']['displayname'])) {
@@ -314,6 +367,24 @@ class kolab_api_service_form_value extends kolab_api_service
}
}
+ private function generate_kolabtargetfolder_resource($postdata, $attribs = array())
+ {
+ if (isset($attribs['auto_form_fields']) && isset($attribs['auto_form_fields']['kolabtargetfolder'])) {
+ // Use Data Please
+ foreach ($attribs['auto_form_fields']['kolabtargetfolder']['data'] as $key) {
+ if (!isset($postdata[$key])) {
+ throw new Exception("Key not set: " . $key, 12356);
+ }
+ }
+
+ // TODO: Detect or from config
+ $imap_hierarchysep = '/';
+ $cn = $this->generate_cn_resource($postdata, $attribs);
+
+ return 'shared' . $imap_hierarchysep . 'Resources' . $imap_hierarchysep . $cn . '@' . $_SESSION['user']->get_domain();
+ }
+ }
+
private function generate_mail($postdata, $attribs = array())
{
return $this->generate_primary_mail($postdata, $attribs);
@@ -324,6 +395,61 @@ class kolab_api_service_form_value extends kolab_api_service
return $this->generate_primary_mail_group($postdata, $attribs);
}
+ private function generate_mail_resource($postdata, $attribs = array())
+ {
+ $db = SQL::get_instance();
+ $result = $db->fetch_assoc($db->query("SELECT `key` FROM `resource_types` WHERE id = ?", $postdata['type_id']));
+
+ $object_type_key = $result['key'];
+
+ if (isset($attribs['auto_form_fields']) && isset($attribs['auto_form_fields']['mail'])) {
+ // Use Data Please
+ foreach ($attribs['auto_form_fields']['mail']['data'] as $key) {
+ if (!isset($postdata[$key])) {
+ throw new Exception("Key not set: " . $key, 12356);
+ }
+ }
+
+ $resourcedata = kolab_recipient_policy::normalize_groupdata($postdata);
+ //console("normalized resource data", $resourcedata);
+
+ // TODO: Normalize $postdata
+ $mail_local = 'resource-' . $object_type_key . '-' . strtolower($resourcedata['cn']);
+ $mail_domain = $_SESSION['user']->get_domain();
+ $mail = $mail_local . '@' . $mail_domain;
+
+ $orig_mail = $mail;
+
+ $auth = Auth::get_instance($_SESSION['user']->get_domain());
+ $conf = Conf::get_instance();
+
+ $unique_attr = $conf->get('unique_attribute');
+ if (!$unique_attr) {
+ $unique_attr = 'nsuniqueid';
+ }
+
+ $x = 2;
+ while (($resource_found = $auth->resource_find_by_attribute(array('mail' => $mail)))) {
+ if (!empty($postdata['id'])) {
+ $resource_found_dn = key($resource_found);
+ $resource_found_unique_attr = $auth->get_attribute($resource_found_dn, $unique_attr);
+ //console("resource with mail $mail found", $resource_found_unique_attr);
+ if ($resource_found_unique_attr == $postdata['id']) {
+ //console("that's us.");
+ break;
+ }
+ }
+
+ $mail = $mail_local . '-' . $x . '@' . $mail_domain;
+ $x++;
+ }
+
+ return $mail;
+
+
+ }
+ }
+
private function generate_mailalternateaddress($postdata, $attribs = array())
{
return $this->generate_secondary_mail($postdata, $attribs);
@@ -389,7 +515,7 @@ class kolab_api_service_form_value extends kolab_api_service
private function generate_secondary_mail($postdata, $attribs = array())
{
- $secondary_mail_address = Array();
+ $secondary_mail_addresses = Array();
if (isset($attribs['auto_form_fields'])) {
if (isset($attribs['auto_form_fields']['alias'])) {
@@ -412,9 +538,17 @@ class kolab_api_service_form_value extends kolab_api_service
}
}
- $secondary_mail = kolab_recipient_policy::secondary_mail($postdata);
+ if (array_key_exists('mail', $attribs['auto_form_fields'])) {
+ if (!array_key_exists('mail', $postdata)) {
+ $postdata['mail'] = $this->generate_primary_mail($postdata, $attribs);
+ }
+ }
+
+ $secondary_mail_addresses = kolab_recipient_policy::secondary_mail($postdata);
- return $secondary_mail;
+ // TODO: Check for uniqueness. Not sure what to do if not unique.
+
+ return $secondary_mail_addresses;
}
}
@@ -434,7 +568,7 @@ class kolab_api_service_form_value extends kolab_api_service
setlocale(LC_ALL, $postdata['preferredlanguage']);
}
/* else {
- console("No locale specified...!");
+ //console("No locale specified...!");
}
*/
@@ -446,7 +580,7 @@ class kolab_api_service_form_value extends kolab_api_service
$auth = Auth::get_instance($_SESSION['user']->get_domain());
$conf = Conf::get_instance();
-
+
$unique_attr = $conf->get('unique_attribute');
if (!$unique_attr) {
$unique_attr = 'nsuniqueid';
@@ -459,6 +593,7 @@ class kolab_api_service_form_value extends kolab_api_service
$user_found_unique_attr = $auth->get_attribute($user_found_dn, $unique_attr);
//console("user with uid $uid found", $user_found_unique_attr);
if ($user_found_unique_attr == $postdata['id']) {
+ //console("that's us.");
break;
}
}
@@ -560,7 +695,7 @@ class kolab_api_service_form_value extends kolab_api_service
private function list_options_nsrole($postdata, $attribs = array())
{
- error_log("Listing options for attribute 'nsrole', while the expected attribute to use is 'nsroledn'");
+ //console("Listing options for attribute 'nsrole', while the expected attribute to use is 'nsroledn'");
return $this->list_options_nsroledn($postdata, $attribs);
}
@@ -605,6 +740,11 @@ class kolab_api_service_form_value extends kolab_api_service
return $this->_list_options_members($postdata, $attribs);
}
+ private function list_options_uniquemember_resource($postdata, $attribs = array())
+ {
+ return $this->_list_options_resources($postdata, $attribs);
+ }
+
private function select_options_c($postdata, $attribs = array())
{
return $this->_select_options_from_db('c');
@@ -670,22 +810,88 @@ class kolab_api_service_form_value extends kolab_api_service
return $options;
}
- private function _select_options_from_db($attribute)
+ private function validate_alias($value)
{
+ $auth = Auth::get_instance();
+ $conf = Conf::get_instance();
+ if (!is_array($value)) {
+ $value = (array)($value);
+ }
- if (empty($attribute)) {
- return false;
+ foreach ($value as $mail_address) {
+ if (!$this->_validate_email_address($mail_address)) {
+ throw new Exception("Invalid email address '$mail_address'", 692);
+ }
+
+ // Only validate the 'alias' attribute is in any of my domain name
+ // spaces if indeed it is listed as a mail attribute.
+ if (in_array('alias', $conf->get_list('mail_attributes'))) {
+ if (!$this->_validate_email_address_in_any_of_my_domains($mail_address)) {
+ throw new Exception("Email address '$mail_address' not in local domain", 693);
+ }
+ }
}
- $db = SQL::get_instance();
- $result = $db->fetch_assoc($db->query("SELECT option_values FROM options WHERE attribute = ?", $attribute));
+ }
- $result = json_decode($result['option_values']);
+ private function validate_mail($value)
+ {
+ $auth = Auth::get_instance();
+ $conf = Conf::get_instance();
+ if (!is_array($value)) {
+ $value = (array)($value);
+ }
- if (empty($result)) {
- return false;
+ foreach ($value as $mail_address) {
+ if (!$this->_validate_email_address($mail_address)) {
+ throw new Exception("Invalid email address '$mail_address'", 692);
+ }
+
+ // Only validate the 'mail' attribute is in any of my domain name
+ // spaces if indeed it is listed as a mail attribute.
+ if (in_array('mail', $conf->get_list('mail_attributes'))) {
+ if (!$this->_validate_email_address_in_any_of_my_domains($mail_address)) {
+ throw new Exception("Email address '$mail_address' not in local domain", 693);
+ }
+ }
+ }
+ }
+
+ private function validate_mailquota($value)
+ {
+ return (int)($value);
+ }
+
+ private function validate_mailalternateaddress($value)
+ {
+ $auth = Auth::get_instance();
+ $conf = Conf::get_instance();
+ if (!is_array($value)) {
+ $value = (array)($value);
+ }
+
+ foreach ($value as $mail_address) {
+ if (!$this->_validate_email_address($mail_address)) {
+ throw new Exception("Invalid email address '$mail_address'", 692);
+ }
+
+ // Only validate the 'mailalternateaddress' attribute is in any of my domain name
+ // spaces if indeed it is listed as a mail attribute.
+ if (in_array('mailalternateaddress', $conf->get_list('mail_attributes'))) {
+ if (!$this->_validate_email_address_in_any_of_my_domains($mail_address)) {
+ throw new Exception("Email address '$mail_address' not in local domain", 693);
+ }
+ }
+ }
+ }
+
+ private function _highest_of_two($one, $two) {
+ if ($one > $two) {
+ return $one;
+ } elseif ($one == $two) {
+ return $one;
} else {
- return $result;
+ return $two;
}
}
@@ -730,7 +936,7 @@ class kolab_api_service_form_value extends kolab_api_service
} elseif (!empty($value['cn'])) {
$list[$idx] = $value['cn'];
} else {
- console("No display name or cn for $idx");
+ //console("No display name or cn for $idx");
}
if (!empty($value['mail'])) {
@@ -741,13 +947,155 @@ class kolab_api_service_form_value extends kolab_api_service
return $list;
}
- private function _highest_of_two($one, $two) {
- if ($one > $two) {
- return $one;
- } elseif ($one == $two) {
- return $one;
+ private function _list_options_resources($postdata, $attribs = array())
+ {
+ // return specified records only, by exact DN attributes
+ if (!empty($postdata['list'])) {
+ $data['search'] = array(
+ 'entrydn' => array(
+ 'value' => $postdata['list'],
+ 'type' => 'exact',
+ ),
+ );
+ }
+ // return records with specified string
+ else {
+ $keyword = array('value' => $postdata['search']);
+ $data['page_size'] = 15;
+ $data['search'] = array(
+ 'cn' => $keyword,
+ );
+ }
+
+ $data['attributes'] = array('cn');
+
+ //console("api/form_value._list_options_resources() searching with data", $data);
+
+ $service = $this->controller->get_service('resources');
+ $result = $service->resources_list(null, $data);
+ $list = $result['list'];
+
+ // convert to key=>value array
+ foreach ($list as $idx => $value) {
+ if (!empty($value['displayname'])) {
+ $list[$idx] = $value['displayname'];
+ } elseif (!empty($value['cn'])) {
+ $list[$idx] = $value['cn'];
+ } else {
+ //console("No display name or cn for $idx");
+ }
+
+ }
+
+ return $list;
+ }
+
+ private function _select_options_from_db($attribute)
+ {
+
+ if (empty($attribute)) {
+ return false;
+ }
+
+ $db = SQL::get_instance();
+ $result = $db->fetch_assoc($db->query("SELECT option_values FROM options WHERE attribute = ?", $attribute));
+
+ $result = json_decode($result['option_values']);
+
+ if (empty($result)) {
+ return false;
} else {
- return $two;
+ return $result;
+ }
+ }
+
+ private function _validate_email_address($mail_address) {
+ $valid = true;
+
+ $at_index = strrpos($mail_address, "@");
+ if (is_bool($at_index) && !$at_index) {
+ $valid = false;
+
+ } else {
+ $domain = substr($mail_address, $at_index+1);
+ $local = substr($mail_address, 0, $at_index);
+
+ if (strlen($local) < 1 || strlen($local) > 64) {
+ // local part length exceeded
+ $valid = false;
+
+ } else if (strlen($domain) < 1 || strlen($domain) > 255) {
+ // domain part length exceeded
+ $valid = false;
+
+ } else if ($local[0] == '.' || $local[strlen($local)-1] == '.') {
+ // local part starts or ends with '.'
+ $valid = false;
+
+ } else if (preg_match('/\\.\\./', $local)) {
+ // local part has two consecutive dots
+ $valid = false;
+
+ } else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)) {
+ // character not valid in domain part
+ $valid = false;
+
+ } else if (preg_match('/\\.\\./', $domain)) {
+ // domain part has two consecutive dots
+ $valid = false;
+
+ } else if (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\","",$local))) {
+ // character not valid in local part unless
+ // local part is quoted
+ if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\","",$local))) {
+ $valid = false;
+ }
+ }
+
+ if ($valid && !(checkdnsrr($domain,"MX") || checkdnsrr($domain,"A"))) {
+ // domain not found in DNS
+ $valid = false;
+ }
+ }
+
+ return $valid;
+ }
+
+ private function _validate_email_address_in_any_of_my_domains($mail_address) {
+ $valid = false;
+
+ $auth = Auth::get_instance();
+ $conf = Conf::get_instance();
+
+ $my_primary_domain = $_SESSION['user']->get_domain();
+ $all_domains = $auth->list_domains();
+
+ $valid_domains = array();
+
+ $dna = $conf->get('domain_name_attribute');
+
+ $at_index = strrpos($mail_address, "@");
+ if (is_bool($at_index) && !$at_index) {
+ throw new Exception("Invalid email address: No domain name space", 235);
+ } else {
+ $email_domain = substr($mail_address, $at_index+1);
}
+
+ foreach ($all_domains as $domain_id => $domain_attrs) {
+ if (!is_array($domain_attrs[$dna])) {
+ $domain_attrs[$dna] = (array)($domain_attrs[$dna]);
+ }
+
+ if (in_array($my_primary_domain, $domain_attrs[$dna])) {
+ $valid_domains = array_merge($valid_domains, $domain_attrs[$dna]);
+ }
+ }
+
+ if (in_array($email_domain, $valid_domains)) {
+ $valid = true;
+ }
+
+ return $valid;
}
+
}
diff --git a/lib/api/kolab_api_service_group.php b/lib/api/kolab_api_service_group.php
index 6e53340..951b98c 100644
--- a/lib/api/kolab_api_service_group.php
+++ b/lib/api/kolab_api_service_group.php
@@ -179,7 +179,7 @@ class kolab_api_service_group extends kolab_api_service
$auth = Auth::get_instance();
if (empty($getdata['group'])) {
- error_log("Empty \$getdata['group']");
+ //console("Empty \$getdata['group']");
return FALSE;
}
diff --git a/lib/api/kolab_api_service_resource.php b/lib/api/kolab_api_service_resource.php
new file mode 100644
index 0000000..9cd3304
--- /dev/null
+++ b/lib/api/kolab_api_service_resource.php
@@ -0,0 +1,185 @@
+<?php
+/*
+ +--------------------------------------------------------------------------+
+ | This file is part of the Kolab Web Admin Panel |
+ | |
+ | Copyright (C) 2011-2012, 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@kolabsys.com> |
+ | Author: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> |
+ +--------------------------------------------------------------------------+
+*/
+
+/**
+ * Service providing resource data management
+ */
+class kolab_api_service_resource extends kolab_api_service
+{
+ /**
+ * Returns service capabilities.
+ *
+ * @param string $domain Domain name
+ *
+ * @return array Capabilities list
+ */
+ public function capabilities($domain)
+ {
+ //console("kolab_api_service_group::capabilities");
+
+ $auth = Auth::get_instance();
+
+ $effective_rights = $auth->list_rights('resource');
+
+ //console("effective_rights", $effective_rights);
+
+ $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['find'] = "r";
+ $rights['find_by_any_attribute'] = "r";
+ $rights['find_by_attribute'] = "r";
+ $rights['find_by_attributes'] = "r";
+ $rights['info'] = "r";
+ }
+
+ $rights['effective_rights'] = "r";
+
+ return $rights;
+ }
+
+ /**
+ * Create resource.
+ *
+ * @param array $get GET parameters
+ * @param array $post POST parameters
+ *
+ * @return array|bool User attributes or False on error.
+ */
+ public function resource_add($getdata, $postdata)
+ {
+ //console("resource_add()", $postdata);
+
+ $resource_attributes = $this->parse_input_attributes('resource', $postdata);
+
+ //console("resource_add()", $resource_attributes);
+
+ // TODO: The cn needs to be unique
+ $auth = Auth::get_instance();
+ $result = $auth->resource_add($resource_attributes, $postdata['type_id']);
+
+ if ($result) {
+ return $resource_attributes;
+ }
+
+ return false;
+ }
+
+ /**
+ * Detete resource.
+ *
+ * @param array $get GET parameters
+ * @param array $post POST parameters
+ *
+ * @return bool True on success, False on failure
+ */
+ public function resource_delete($getdata, $postdata)
+ {
+ //console("resource_delete()", $getdata, $postdata);
+ if (!isset($postdata['resource'])) {
+ return false;
+ }
+
+ // TODO: Input validation
+ $auth = Auth::get_instance();
+ $result = $auth->resource_delete($postdata['resource']);
+
+ if ($result) {
+ return $result;
+ }
+
+ return false;
+ }
+
+ public function resource_edit($getdata, $postdata)
+ {
+ //console("\$postdata to resource_edit()", $postdata);
+
+ $resource_attributes = $this->parse_input_attributes('resource', $postdata);
+
+ //console("\$resource_attributes as result from parse_input_attributes", $resource_attributes);
+
+ $resource = $postdata['id'];
+
+ $auth = Auth::get_instance();
+ $result = $auth->resource_edit($resource, $resource_attributes, $postdata['type_id']);
+
+ // Return the $mod_array
+ if ($result) {
+ return $result;
+ }
+
+ return false;
+
+ }
+
+ public function resource_effective_rights($getdata, $postdata)
+ {
+ $auth = Auth::get_instance();
+ $effective_rights = $auth->list_rights($getdata['resource']);
+ return $effective_rights;
+ }
+
+ /**
+ * User information.
+ *
+ * @param array $get GET parameters
+ * @param array $post POST parameters
+ *
+ * @return array|bool User attributes, False on error
+ */
+ public function resource_info($getdata, $postdata)
+ {
+ if (!isset($getdata['resource'])) {
+ return false;
+ }
+
+ $auth = Auth::get_instance();
+ $result = $auth->resource_info($getdata['resource']);
+
+ // normalize result
+ $result = $this->parse_result_attributes('resource', $result);
+
+ //console($result);
+
+ if ($result) {
+ return $result;
+ }
+
+ return false;
+ }
+}
diff --git a/lib/api/kolab_api_service_resource_types.php b/lib/api/kolab_api_service_resource_types.php
new file mode 100644
index 0000000..69d13ea
--- /dev/null
+++ b/lib/api/kolab_api_service_resource_types.php
@@ -0,0 +1,64 @@
+<?php
+/*
+ +--------------------------------------------------------------------------+
+ | This file is part of the Kolab Web Admin Panel |
+ | |
+ | Copyright (C) 2011-2012, 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@kolabsys.com> |
+ | Author: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> |
+ +--------------------------------------------------------------------------+
+*/
+
+/**
+ *
+ */
+class kolab_api_service_resource_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',
+ );
+ }
+
+ /**
+ * User types listing.
+ *
+ * @param array $get GET parameters
+ * @param array $post POST parameters
+ *
+ * @return array List result with 'list' and 'count' items
+ */
+ public function resource_types_list($get, $post)
+ {
+ $resource_types = $this->object_types('resource');
+
+ //console("api/resource_types_list()", $resource_types);
+
+ return array(
+ 'list' => $resource_types,
+ 'count' => count($resource_types),
+ );
+ }
+}
diff --git a/lib/api/kolab_api_service_resources.php b/lib/api/kolab_api_service_resources.php
new file mode 100644
index 0000000..6bcc7e3
--- /dev/null
+++ b/lib/api/kolab_api_service_resources.php
@@ -0,0 +1,147 @@
+<?php
+/*
+ +--------------------------------------------------------------------------+
+ | This file is part of the Kolab Web Admin Panel |
+ | |
+ | Copyright (C) 2011-2012, 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@kolabsys.com> |
+ | Author: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> |
+ +--------------------------------------------------------------------------+
+*/
+
+/**
+ * Service providing resources listing
+ */
+class kolab_api_service_resources extends kolab_api_service
+{
+ public $list_attribs = array(
+ 'alias',
+ 'cn',
+ 'entrydn',
+ 'mail',
+ 'objectclass',
+ );
+
+
+ /**
+ * Returns service capabilities.
+ *
+ * @param string $domain Domain name
+ *
+ * @return array Capabilities list
+ */
+ public function capabilities($domain)
+ {
+ return array(
+ 'list' => 'r',
+ );
+ }
+
+ /**
+ * Users listing (with searching).
+ *
+ * @param array $get GET parameters
+ * @param array $post POST parameters
+ *
+ * @return array List result with 'list' and 'count' items
+ */
+ public function resources_list($get, $post)
+ {
+ $auth = Auth::get_instance();
+
+ // returned attributes
+ if (!empty($post['attributes']) && is_array($post['attributes'])) {
+ // get only supported attributes
+ $attributes = array_intersect($this->list_attribs, $post['attributes']);
+ // need to fix array keys
+ $attributes = array_values($attributes);
+ }
+ if (empty($attributes)) {
+ $attributes = (array)$this->list_attribs[0];
+ }
+
+ $search = array();
+ $params = array();
+
+ // searching
+ if (!empty($post['search']) && is_array($post['search'])) {
+ $params = $post['search'];
+
+ foreach ($params as $idx => $param) {
+ // get only supported attributes
+ if (!in_array($idx, $this->list_attribs)) {
+ unset($params[$idx]);
+ continue;
+ }
+
+ // search string
+ if (empty($param['value'])) {
+ unset($params[$idx]);
+ continue;
+ }
+ }
+
+ $search['params'] = $params;
+ if (!empty($post['search_operator'])) {
+ $search['operator'] = $post['search_operator'];
+ }
+ }
+
+ if (!empty($post['sort_by'])) {
+ if (is_array($post['sort_by'])) {
+ $params['sort_by'] = Array();
+ foreach ($post['sort_by'] as $attrib) {
+ if (in_array($attrib, $this->list_attribs)) {
+ $params['sort_by'][] = $attrib;
+ }
+ }
+ } else {
+ // check if sort attribute is supported
+ if (in_array($post['sort_by'], $this->list_attribs)) {
+ $params['sort_by'] = $post['sort_by'];
+ }
+ }
+ }
+
+ if (!empty($post['sort_order'])) {
+ $params['sort_order'] = $post['sort_order'] == 'DESC' ? 'DESC' : 'ASC';
+ }
+
+ $resources = $auth->list_resources(null, $attributes, $search, $params);
+ $count = count($resources);
+
+ // pagination
+ if (!empty($post['page_size']) && $count) {
+ $size = (int) $post['page_size'];
+ $page = !empty($post['page']) ? $post['page'] : 1;
+ $page = max(1, (int) $page);
+ $offset = ($page - 1) * $size;
+
+ $resources = array_slice($resources, $offset, $size, true);
+ }
+
+ $result = array(
+ 'list' => $resources,
+ 'count' => $count,
+ );
+
+ //console($result);
+
+ return $result;
+ }
+
+}
diff --git a/lib/api/kolab_api_service_user.php b/lib/api/kolab_api_service_user.php
index 67e7e53..f9adbac 100644
--- a/lib/api/kolab_api_service_user.php
+++ b/lib/api/kolab_api_service_user.php
@@ -84,7 +84,7 @@ class kolab_api_service_user extends kolab_api_service
{
//console("user_add()", $postdata);
- $user_attributes = $this->parse_input_attributes('user', $postdata);
+ $user_attributes = $this->parse_input_attributes('user', $postdata);
//console("user_add()", $user_attributes);
@@ -171,7 +171,7 @@ class kolab_api_service_user extends kolab_api_service
$result = $auth->user_info($getdata['user']);
// normalize result
- $result = $this->parse_result_attributes('user', $result);
+ $result = $this->parse_result_attributes('user', $result);
if ($result) {
return $result;
diff --git a/lib/client/kolab_client_task_domain.php b/lib/client/kolab_client_task_domain.php
new file mode 100644
index 0000000..b8eba82
--- /dev/null
+++ b/lib/client/kolab_client_task_domain.php
@@ -0,0 +1,350 @@
+<?php
+/*
+ +--------------------------------------------------------------------------+
+ | This file is part of the Kolab Web Admin Panel |
+ | |
+ | Copyright (C) 2011-2012, 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@kolabsys.com> |
+ +--------------------------------------------------------------------------+
+*/
+
+class kolab_client_task_domain extends kolab_client_task
+{
+ protected $ajax_only = true;
+
+ protected $menu = array(
+ 'add' => 'domain.add',
+ );
+
+ /**
+ * Default action.
+ */
+ public function action_default()
+ {
+ $this->output->set_object('content', 'domain', true);
+ $this->output->set_object('task_navigation', $this->menu());
+
+ $this->action_list();
+ }
+
+ /**
+ * Groups list action.
+ */
+ public function action_list()
+ {
+ $page_size = 20;
+ $page = (int) self::get_input('page', 'POST');
+ if (!$page || $page < 1) {
+ $page = 1;
+ }
+
+ // request parameters
+ $post = array(
+ 'attributes' => array('associateddomain'),
+// 'sort_order' => 'ASC',
+ 'sort_by' => 'associateddomain',
+ 'page_size' => $page_size,
+ 'page' => $page,
+ );
+
+ // search parameters
+ if (!empty($_POST['search'])) {
+ $search = self::get_input('search', 'POST', true);
+ $field = self::get_input('field', 'POST');
+ $method = self::get_input('method', 'POST');
+
+ $search_request = array(
+ $field => array(
+ 'value' => $search,
+ 'type' => $method,
+ ),
+ );
+ }
+ else if (!empty($_POST['search_request'])) {
+ $search_request = self::get_input('search_request', 'POST');
+ $search_request = @unserialize(base64_decode($search_request));
+ }
+
+ if (!empty($search_request)) {
+ $post['search'] = $search_request;
+ $post['search_operator'] = 'OR';
+ }
+
+ // get domains list
+ $result = $this->api->post('domains.list', null, $post);
+ $count = (int) $result->get('count');
+ $result = (array) $result->get('list');
+
+ // calculate records
+ if ($count) {
+ $start = 1 + max(0, $page - 1) * $page_size;
+ $end = min($start + $page_size - 1, $count);
+ }
+
+ $rows = $head = $foot = array();
+ $cols = array('name');
+ $i = 0;
+
+ // table header
+ $head[0]['cells'][] = array('class' => 'name', 'body' => $this->translate('domain.list'));
+
+ // table footer (navigation)
+ if ($count) {
+ $pages = ceil($count / $page_size);
+ $prev = max(0, $page - 1);
+ $next = $page < $pages ? $page + 1 : 0;
+
+ $count_str = kolab_html::span(array(
+ 'content' => $this->translate('domain.list.records', $start, $end, $count)), true);
+ $prev = kolab_html::a(array(
+ 'class' => 'prev' . ($prev ? '' : ' disabled'),
+ 'href' => '#',
+ 'onclick' => $prev ? "kadm.command('domain.list', {page: $prev})" : "return false",
+ ));
+ $next = kolab_html::a(array(
+ 'class' => 'next' . ($next ? '' : ' disabled'),
+ 'href' => '#',
+ 'onclick' => $next ? "kadm.command('domain.list', {page: $next})" : "return false",
+ ));
+
+ $foot_body = kolab_html::span(array('content' => $prev . $count_str . $next));
+ }
+ $foot[0]['cells'][] = array('class' => 'listnav', 'body' => $foot_body);
+
+ // table body
+ if (!empty($result)) {
+ foreach ($result as $idx => $item) {
+ //console($idx);
+ if (!is_array($item) || empty($item['associateddomain'])) {
+ continue;
+ }
+
+ $i++;
+ $cells = array();
+
+ if (is_array($item['associateddomain'])) {
+ $domain_name = $item['associateddomain'][0];
+ } else {
+ $domain_name = $item['associateddomain'];
+ }
+
+ $cells[] = array('class' => 'name', 'body' => kolab_html::escape($domain_name),
+ 'onclick' => "kadm.command('domain.info', '$idx')");
+ $rows[] = array('id' => $i, 'class' => 'selectable', 'cells' => $cells);
+ }
+ }
+ else {
+ $rows[] = array('cells' => array(
+ 0 => array('class' => 'empty-body', 'body' => $this->translate('domain.norecords')
+ )));
+ }
+
+ $table = kolab_html::table(array(
+ 'id' => 'domainlist',
+ 'class' => 'list',
+ 'head' => $head,
+ 'body' => $rows,
+ 'foot' => $foot,
+ ));
+
+ $this->output->set_env('search_request', $search_request ? base64_encode(serialize($search_request)) : null);
+ $this->output->set_env('list_page', $page);
+ $this->output->set_env('list_count', $count);
+
+ $this->watermark('taskcontent');
+ $this->output->set_object('domainlist', $table);
+ }
+
+ /**
+ * Domain information (form) action.
+ */
+ public function action_info()
+ {
+ $id = $this->get_input('id', 'POST');
+ //console("action_info() on", $id);
+
+ $result = $this->api->get('domain.info', array('domain' => $id));
+ //console("action_info() \$result", $result);
+
+ $domain = $result->get();
+ //console("action_info() \$domain", $domain);
+
+ $output = $this->domain_form(array_keys($domain), $domain);
+
+ $this->output->set_object('taskcontent', $output);
+ }
+
+ /**
+ * Domain adding (form) action.
+ */
+ public function action_add()
+ {
+ $data = $this->get_input('data', 'POST');
+ $output = $this->domain_form(null, $data, true);
+
+ $this->output->set_object('taskcontent', $output);
+ }
+
+ /**
+ * Domain edit/add form.
+ */
+ private function domain_form($attribs, $data = array())
+ {
+ if (empty($attribs['id'])) {
+ $attribs['id'] = 'domain-form';
+ }
+
+ // Form sections
+ $sections = array(
+ 'system' => 'domain.system',
+ 'other' => 'domain.other',
+ );
+
+ // field-to-section map and fields order
+ $fields_map = array(
+ 'type_id' => 'system',
+ 'type_id_name' => 'system',
+ 'associateddomain' => 'system',
+ );
+
+ //console("domain_form() \$data", $data);
+
+ // Prepare fields
+ list($fields, $types, $type) = $this->form_prepare('domain', $data);
+
+ //console("Result from form_prepare", $fields, $types, $type);
+
+ $add_mode = empty($data['id']);
+ $accttypes = array();
+
+ foreach ($types as $idx => $elem) {
+ $accttypes[$idx] = array('value' => $idx, 'content' => $elem['name']);
+ }
+
+ // Add domain type id selector
+ $fields['type_id'] = array(
+ 'section' => 'system',
+ 'type' => kolab_form::INPUT_SELECT,
+ 'options' => $accttypes,
+ 'onchange' => "kadm.domain_save(true, 'system')",
+ );
+
+ // Hide account type selector if there's only one type
+ if (count($accttypes) < 2 || !$add_mode) {
+ $fields['type_id']['type'] = kolab_form::INPUT_HIDDEN;
+ }
+
+ // Create mode
+ if ($add_mode) {
+ // Page title
+ $title = $this->translate('domain.add');
+ }
+ // Edit mode
+ else {
+ $title = $data['primary_domain'];
+
+ // Add domain type name
+ $fields['type_id_name'] = array(
+ 'label' => 'domain.type_id',
+ 'section' => 'system',
+ 'value' => $accttypes[$type]['content'],
+ );
+ }
+
+ // Create form object and populate with fields
+ $form = $this->form_create('domain', $attribs, $sections, $fields, $fields_map, $data, $add_mode);
+
+ //console("domain_form() \$form", $form);
+
+ $form->set_title(kolab_html::escape($title));
+
+ $this->output->add_translation('domain.add.success', 'domain.edit.success', 'domain.delete.success');
+
+ return $form->output();
+ }
+
+ /**
+ * Returns list of domain types.
+ *
+ * @return array List of domain types
+ */
+ public function domain_types()
+ {
+ $result = array(
+ 1 => array(
+ 'key' => 'standard',
+ 'name' => 'Standard domain',
+ 'description' => 'A standard domain name space',
+ 'attributes' => array(
+ 'auto_form_fields' => array(),
+ 'form_fields' => array(
+ 'associateddomain' => array(
+ 'type' => 'list',
+ ),
+ 'inetdomainbasedn' => array(
+ 'optional' => 'true',
+ ),
+ ),
+ 'fields' => array(
+ 'objectclass' => array(
+ 'top',
+ 'domainrelatedobject',
+ ),
+ ),
+ ),
+ ),
+ );
+ //console("domain_types() \$result", $result);
+ return $result;
+ }
+
+ /**
+ * Users search form.
+ *
+ * @return string HTML output of the form
+ */
+ public function search_form()
+ {
+ $form = new kolab_form(array('id' => 'search-form'));
+
+ $form->add_section('criteria', kolab_html::escape($this->translate('search.criteria')));
+ $form->add_element(array(
+ 'section' => 'criteria',
+ 'label' => $this->translate('search.field'),
+ 'name' => 'field',
+ 'type' => kolab_form::INPUT_SELECT,
+ 'options' => array(
+ 'cn' => kolab_html::escape($this->translate('search.name')),
+ 'mail' => kolab_html::escape($this->translate('search.email')),
+ ),
+ ));
+ $form->add_element(array(
+ 'section' => 'criteria',
+ 'label' => $this->translate('search.method'),
+ 'name' => 'method',
+ 'type' => kolab_form::INPUT_SELECT,
+ 'options' => array(
+ 'both' => kolab_html::escape($this->translate('search.contains')),
+ 'exact' => kolab_html::escape($this->translate('search.is')),
+ 'prefix' => kolab_html::escape($this->translate('search.prefix')),
+ ),
+ ));
+
+ return $form->output();
+ }
+
+}
diff --git a/lib/client/kolab_client_task_group.php b/lib/client/kolab_client_task_group.php
index 402fabe..0c6e3d0 100644
--- a/lib/client/kolab_client_task_group.php
+++ b/lib/client/kolab_client_task_group.php
@@ -271,7 +271,7 @@ class kolab_client_task_group extends kolab_client_task
} elseif (!empty($value['cn'])) {
$list[$idx] = $value['cn'];
} else {
- console("No display name or cn for $idx");
+ //console("No display name or cn for $idx");
}
if (!empty($value['mail'])) {
@@ -298,6 +298,8 @@ class kolab_client_task_group extends kolab_client_task
}
}
+ //console($_SESSION['group_types']);
+
return $_SESSION['group_types'];
}
diff --git a/lib/client/kolab_client_task_main.php b/lib/client/kolab_client_task_main.php
index b7b4621..5af9754 100644
--- a/lib/client/kolab_client_task_main.php
+++ b/lib/client/kolab_client_task_main.php
@@ -25,9 +25,12 @@
class kolab_client_task_main extends kolab_client_task
{
protected $menu = array(
- 'user.default' => 'menu.users',
- 'group.default' => 'menu.groups',
- 'about.default' => 'menu.about',
+ 'user.default' => 'menu.users',
+ 'group.default' => 'menu.groups',
+ 'resource.default' => 'menu.resources',
+ 'domain.default' => 'menu.domains',
+ 'role.default' => 'menu.roles',
+ 'about.default' => 'menu.about',
);
diff --git a/lib/client/kolab_client_task_resource.php b/lib/client/kolab_client_task_resource.php
new file mode 100644
index 0000000..5e3f7a2
--- /dev/null
+++ b/lib/client/kolab_client_task_resource.php
@@ -0,0 +1,329 @@
+<?php
+/*
+ +--------------------------------------------------------------------------+
+ | This file is part of the Kolab Web Admin Panel |
+ | |
+ | Copyright (C) 2011-2012, 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@kolabsys.com> |
+ +--------------------------------------------------------------------------+
+*/
+
+class kolab_client_task_resource extends kolab_client_task
+{
+ protected $ajax_only = true;
+
+ protected $menu = array(
+ 'add' => 'resource.add',
+ );
+
+ /**
+ * Default action.
+ */
+ public function action_default()
+ {
+ $this->output->set_object('content', 'resource', true);
+ $this->output->set_object('task_navigation', $this->menu());
+
+ $this->action_list();
+ }
+
+ /**
+ * Users list action.
+ */
+ public function action_list()
+ {
+ $page_size = 20;
+ $page = (int) self::get_input('page', 'POST');
+ if (!$page || $page < 1) {
+ $page = 1;
+ }
+
+ // request parameters
+ $post = array(
+ 'attributes' => array('cn'),
+// 'sort_order' => 'ASC',
+ 'sort_by' => array('cn'),
+ 'page_size' => $page_size,
+ 'page' => $page,
+ );
+
+ // search parameters
+ if (!empty($_POST['search'])) {
+ $search = self::get_input('search', 'POST', true);
+ $field = self::get_input('field', 'POST');
+ $method = self::get_input('method', 'POST');
+
+ $search_request = array(
+ $field => array(
+ 'value' => $search,
+ 'type' => $method,
+ ),
+ );
+ }
+ else if (!empty($_POST['search_request'])) {
+ $search_request = self::get_input('search_request', 'POST');
+ $search_request = @unserialize(base64_decode($search_request));
+ }
+
+ if (!empty($search_request)) {
+ $post['search'] = $search_request;
+ $post['search_operator'] = 'OR';
+ }
+
+ // get resources list
+ $result = $this->api->post('resources.list', null, $post);
+ $count = $result->get('count');
+ $result = (array) $result->get('list');
+
+ //console($result);
+
+ // calculate records
+ if ($count) {
+ $start = 1 + max(0, $page - 1) * $page_size;
+ $end = min($start + $page_size - 1, $count);
+ }
+
+ $rows = $head = $foot = array();
+ $cols = array('name');
+ $i = 0;
+
+ // table header
+ $head[0]['cells'][] = array('class' => 'name', 'body' => $this->translate('resource.list'));
+
+ // table footer (navigation)
+ if ($count) {
+ $pages = ceil($count / $page_size);
+ $prev = max(0, $page - 1);
+ $next = $page < $pages ? $page + 1 : 0;
+
+ $count_str = kolab_html::span(array(
+ 'content' => $this->translate('resource.list.records', $start, $end, $count)), true);
+ $prev = kolab_html::a(array(
+ 'class' => 'prev' . ($prev ? '' : ' disabled'),
+ 'href' => '#',
+ 'onclick' => $prev ? "kadm.command('resource.list', {page: $prev})" : "return false",
+ ));
+ $next = kolab_html::a(array(
+ 'class' => 'next' . ($next ? '' : ' disabled'),
+ 'href' => '#',
+ 'onclick' => $next ? "kadm.command('resource.list', {page: $next})" : "return false",
+ ));
+
+ $foot_body = kolab_html::span(array('content' => $prev . $count_str . $next));
+ }
+ $foot[0]['cells'][] = array('class' => 'listnav', 'body' => $foot_body);
+
+ // table body
+ if (!empty($result)) {
+ foreach ($result as $idx => $item) {
+ if (!is_array($item) || empty($item['cn'])) {
+ continue;
+ }
+
+ $i++;
+ $cells = array();
+ $cells[] = array('class' => 'name', 'body' => kolab_html::escape($item['cn']),
+ 'onclick' => "kadm.command('resource.info', '$idx')");
+ $rows[] = array('id' => $i, 'class' => 'selectable', 'cells' => $cells);
+ }
+ }
+ else {
+ $rows[] = array('cells' => array(
+ 0 => array('class' => 'empty-body', 'body' => $this->translate('resource.norecords')
+ )));
+ }
+
+ $table = kolab_html::table(array(
+ 'id' => 'resourcelist',
+ 'class' => 'list',
+ 'head' => $head,
+ 'body' => $rows,
+ 'foot' => $foot,
+ ));
+
+ $this->output->set_env('search_request', $search_request ? base64_encode(serialize($search_request)) : null);
+ $this->output->set_env('list_page', $page);
+ $this->output->set_env('list_count', $count);
+
+ $this->watermark('taskcontent');
+ $this->output->set_object('resourcelist', $table);
+ }
+
+ /**
+ * Resource adding (form) action.
+ */
+ public function action_add()
+ {
+ $data = $this->get_input('data', 'POST');
+ $output = $this->resource_form(null, $data, true);
+
+ $this->output->set_object('taskcontent', $output);
+ }
+
+ /**
+ * Resource information (form) action.
+ */
+ public function action_info()
+ {
+ $id = $this->get_input('id', 'POST');
+ $result = $this->api->get('resource.info', array('resource' => $id));
+ $resource = $result->get();
+
+ //console("action_info()", $resource);
+
+ $output = $this->resource_form(null, $resource);
+
+ $this->output->set_object('taskcontent', $output);
+ }
+
+ private function resource_form($attribs, $data = array())
+ {
+ if (empty($attribs['id'])) {
+ $attribs['id'] = 'resource-form';
+ }
+
+ //console("resource_form(\$attribs, \$data)", $attribs, $data);
+
+ // Form sections
+ $sections = array(
+ 'system' => 'resource.system',
+ 'other' => 'resource.other',
+ );
+
+ // field-to-section map and fields order
+ $fields_map = array(
+ 'type_id' => 'system',
+ 'type_id_name' => 'system',
+
+ 'cn' => 'system',
+ 'ou' => 'system',
+ 'preferredlanguage' => 'system',
+
+ 'mail' => 'system',
+ 'alias' => 'system',
+ 'mailalternateaddress' => 'system',
+
+ 'member' => 'system',
+ 'uniquemember' => 'system',
+ 'memberurl' => 'system',
+
+ 'nsrole' => 'system',
+ 'nsroledn' => 'system',
+
+ /* Kolab Settings */
+ 'kolabhomeserver' => 'system',
+ 'mailhost' => 'system',
+ 'mailquota' => 'system',
+ 'kolabfreebusyfuture' => 'system',
+ 'kolabinvitationpolicy' => 'system',
+ 'kolabdelegate' => 'system',
+ 'kolaballowsmtprecipient' => 'system',
+ 'kolaballowsmtpsender' => 'system',
+ );
+
+ // Prepare fields
+ list($fields, $types, $type) = $this->form_prepare('resource', $data);
+
+ //console("Result from form_prepare", $fields, $types, $type);
+
+ $add_mode = empty($data['id']);
+ $accttypes = array();
+
+ foreach ($types as $idx => $elem) {
+ $accttypes[$idx] = array('value' => $idx, 'content' => $elem['name']);
+ }
+
+ // Add resource type id selector
+ $fields['type_id'] = array(
+ 'section' => 'system',
+ 'type' => kolab_form::INPUT_SELECT,
+ 'options' => $accttypes,
+ 'onchange' => "kadm.resource_save(true, 'system')",
+ );
+
+ //console($accttypes);
+
+ // 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('resource.add');
+ }
+ // Edit mode
+ else {
+ $title = $data['cn'];
+
+ // Add resource type name
+ $fields['type_id_name'] = array(
+ 'label' => 'resource.type_id',
+ 'section' => 'system',
+ 'value' => $accttypes[$type]['content'],
+ );
+ }
+
+ // Create form object and populate with fields
+ $form = $this->form_create('resource', $attribs, $sections, $fields, $fields_map, $data, $add_mode);
+
+ $form->set_title(kolab_html::escape($title));
+
+ $this->output->add_translation('resource.add.success', 'resource.edit.success', 'resource.delete.success');
+
+ return $form->output();
+ }
+
+ /**
+ * Users search form.
+ *
+ * @return string HTML output of the form
+ */
+ public function search_form()
+ {
+ $form = new kolab_form(array('id' => 'search-form'));
+
+ $form->add_section('criteria', kolab_html::escape($this->translate('search.criteria')));
+ $form->add_element(array(
+ 'section' => 'criteria',
+ 'label' => $this->translate('search.field'),
+ 'name' => 'field',
+ 'type' => kolab_form::INPUT_SELECT,
+ 'options' => array(
+ 'cn' => kolab_html::escape($this->translate('search.name')),
+ 'email' => kolab_html::escape($this->translate('search.email')),
+ 'uid' => kolab_html::escape($this->translate('search.uid')),
+ ),
+ ));
+ $form->add_element(array(
+ 'section' => 'criteria',
+ 'label' => $this->translate('search.method'),
+ 'name' => 'method',
+ 'type' => kolab_form::INPUT_SELECT,
+ 'options' => array(
+ 'both' => kolab_html::escape($this->translate('search.contains')),
+ 'exact' => kolab_html::escape($this->translate('search.is')),
+ 'prefix' => kolab_html::escape($this->translate('search.prefix')),
+ ),
+ ));
+
+ return $form->output();
+ }
+
+}
diff --git a/lib/client/kolab_client_task_role.php b/lib/client/kolab_client_task_role.php
new file mode 100644
index 0000000..d012abd
--- /dev/null
+++ b/lib/client/kolab_client_task_role.php
@@ -0,0 +1,339 @@
+<?php
+/*
+ +--------------------------------------------------------------------------+
+ | This file is part of the Kolab Web Admin Panel |
+ | |
+ | Copyright (C) 2011-2012, 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@kolabsys.com> |
+ +--------------------------------------------------------------------------+
+*/
+
+class kolab_client_task_role extends kolab_client_task
+{
+ protected $ajax_only = true;
+
+ protected $menu = array(
+ 'add' => 'role.add',
+ );
+
+ /**
+ * Default action.
+ */
+ public function action_default()
+ {
+ $this->output->set_object('content', 'role', true);
+ $this->output->set_object('task_navigation', $this->menu());
+
+ $this->action_list();
+ }
+
+ /**
+ * Groups list action.
+ */
+ public function action_list()
+ {
+ $page_size = 20;
+ $page = (int) self::get_input('page', 'POST');
+ if (!$page || $page < 1) {
+ $page = 1;
+ }
+
+ // request parameters
+ $post = array(
+ 'attributes' => array('cn'),
+// 'sort_order' => 'ASC',
+ 'sort_by' => 'cn',
+ 'page_size' => $page_size,
+ 'page' => $page,
+ );
+
+ // search parameters
+ if (!empty($_POST['search'])) {
+ $search = self::get_input('search', 'POST', true);
+ $field = self::get_input('field', 'POST');
+ $method = self::get_input('method', 'POST');
+
+ $search_request = array(
+ $field => array(
+ 'value' => $search,
+ 'type' => $method,
+ ),
+ );
+ }
+ else if (!empty($_POST['search_request'])) {
+ $search_request = self::get_input('search_request', 'POST');
+ $search_request = @unserialize(base64_decode($search_request));
+ }
+
+ if (!empty($search_request)) {
+ $post['search'] = $search_request;
+ $post['search_operator'] = 'OR';
+ }
+
+ // get roles list
+ $result = $this->api->post('roles.list', null, $post);
+ $count = (int) $result->get('count');
+ $result = (array) $result->get('list');
+
+ // calculate records
+ if ($count) {
+ $start = 1 + max(0, $page - 1) * $page_size;
+ $end = min($start + $page_size - 1, $count);
+ }
+
+ $rows = $head = $foot = array();
+ $cols = array('name');
+ $i = 0;
+
+ // table header
+ $head[0]['cells'][] = array('class' => 'name', 'body' => $this->translate('role.list'));
+
+ // table footer (navigation)
+ if ($count) {
+ $pages = ceil($count / $page_size);
+ $prev = max(0, $page - 1);
+ $next = $page < $pages ? $page + 1 : 0;
+
+ $count_str = kolab_html::span(array(
+ 'content' => $this->translate('role.list.records', $start, $end, $count)), true);
+ $prev = kolab_html::a(array(
+ 'class' => 'prev' . ($prev ? '' : ' disabled'),
+ 'href' => '#',
+ 'onclick' => $prev ? "kadm.command('role.list', {page: $prev})" : "return false",
+ ));
+ $next = kolab_html::a(array(
+ 'class' => 'next' . ($next ? '' : ' disabled'),
+ 'href' => '#',
+ 'onclick' => $next ? "kadm.command('role.list', {page: $next})" : "return false",
+ ));
+
+ $foot_body = kolab_html::span(array('content' => $prev . $count_str . $next));
+ }
+ $foot[0]['cells'][] = array('class' => 'listnav', 'body' => $foot_body);
+
+ // table body
+ if (!empty($result)) {
+ foreach ($result as $idx => $item) {
+ if (!is_array($item) || empty($item['cn'])) {
+ continue;
+ }
+
+ $i++;
+ $cells = array();
+ $cells[] = array('class' => 'name', 'body' => kolab_html::escape($item['cn']),
+ 'onclick' => "kadm.command('role.info', '$idx')");
+ $rows[] = array('id' => $i, 'class' => 'selectable', 'cells' => $cells);
+ }
+ }
+ else {
+ $rows[] = array('cells' => array(
+ 0 => array('class' => 'empty-body', 'body' => $this->translate('role.norecords')
+ )));
+ }
+
+ $table = kolab_html::table(array(
+ 'id' => 'rolelist',
+ 'class' => 'list',
+ 'head' => $head,
+ 'body' => $rows,
+ 'foot' => $foot,
+ ));
+
+ $this->output->set_env('search_request', $search_request ? base64_encode(serialize($search_request)) : null);
+ $this->output->set_env('list_page', $page);
+ $this->output->set_env('list_count', $count);
+
+ $this->watermark('taskcontent');
+ $this->output->set_object('rolelist', $table);
+ }
+
+ /**
+ * Group information (form) action.
+ */
+ public function action_info()
+ {
+ $id = $this->get_input('id', 'POST');
+ $result = $this->api->get('role.info', array('role' => $id));
+ $role = $result->get();
+ $output = $this->role_form(null, $role);
+
+ $this->output->set_object('taskcontent', $output);
+ }
+
+ /**
+ * Groups adding (form) action.
+ */
+ public function action_add()
+ {
+ $data = $this->get_input('data', 'POST');
+ $output = $this->role_form(null, $data, true);
+
+ $this->output->set_object('taskcontent', $output);
+ }
+
+ /**
+ * Group edit/add form.
+ */
+ private function role_form($attribs, $data = array())
+ {
+ if (empty($attribs['id'])) {
+ $attribs['id'] = 'role-form';
+ }
+
+ // Form sections
+ $sections = array(
+ 'system' => 'role.system',
+ 'other' => 'role.other',
+ );
+
+ // field-to-section map and fields order
+ $fields_map = array(
+ 'type_id' => 'system',
+ 'type_id_name' => 'system',
+ 'cn' => 'system',
+ 'gidnumber' => 'system',
+ 'mail' => 'system',
+ 'member' => 'system',
+ 'uniquemember' => 'system',
+ 'memberurl' => 'system',
+ );
+
+ // Prepare fields
+ list($fields, $types, $type) = $this->form_prepare('role', $data);
+
+ $add_mode = empty($data['id']);
+ $accttypes = array();
+
+ foreach ($types as $idx => $elem) {
+ $accttypes[$idx] = array('value' => $idx, 'content' => $elem['name']);
+ }
+
+ // Add user type id selector
+ $fields['type_id'] = array(
+ 'section' => 'system',
+ 'type' => kolab_form::INPUT_SELECT,
+ 'options' => $accttypes,
+ 'onchange' => "kadm.role_save(true, 'system')",
+ );
+
+ // Hide account type selector if there's only one type
+ if (count($accttypes) < 2 || !$add_mode) {
+ $fields['type_id']['type'] = kolab_form::INPUT_HIDDEN;
+ }
+
+ // Create mode
+ if ($add_mode) {
+ // Page title
+ $title = $this->translate('role.add');
+ }
+ // Edit mode
+ else {
+ $title = $data['cn'];
+
+ // Add user type name
+ $fields['type_id_name'] = array(
+ 'label' => 'role.type_id',
+ 'section' => 'system',
+ 'value' => $accttypes[$type]['content'],
+ );
+ }
+
+ // Create form object and populate with fields
+ $form = $this->form_create('role', $attribs, $sections, $fields, $fields_map, $data, $add_mode);
+
+ $form->set_title(kolab_html::escape($title));
+
+ $this->output->add_translation('role.add.success', 'role.edit.success', 'role.delete.success');
+
+ return $form->output();
+ }
+
+ private function parse_members($list)
+ {
+ // convert to key=>value array, see kolab_api_service_form_value::list_options_uniquemember()
+ foreach ($list as $idx => $value) {
+ if (!empty($value['displayname'])) {
+ $list[$idx] = $value['displayname'];
+ } elseif (!empty($value['cn'])) {
+ $list[$idx] = $value['cn'];
+ } else {
+ //console("No display name or cn for $idx");
+ }
+
+ if (!empty($value['mail'])) {
+ $list[$idx] .= ' <' . $value['mail'] . '>';
+ }
+ }
+
+ return $list;
+ }
+
+ /**
+ * Returns list of role types.
+ *
+ * @return array List of role types
+ */
+ public function role_types()
+ {
+ if (!isset($_SESSION['role_types'])) {
+ $result = $this->api->post('role_types.list');
+ $list = $result->get('list');
+
+ if (is_array($list)) {
+ $_SESSION['role_types'] = $list;
+ }
+ }
+
+ return $_SESSION['role_types'];
+ }
+
+ /**
+ * Users search form.
+ *
+ * @return string HTML output of the form
+ */
+ public function search_form()
+ {
+ $form = new kolab_form(array('id' => 'search-form'));
+
+ $form->add_section('criteria', kolab_html::escape($this->translate('search.criteria')));
+ $form->add_element(array(
+ 'section' => 'criteria',
+ 'label' => $this->translate('search.field'),
+ 'name' => 'field',
+ 'type' => kolab_form::INPUT_SELECT,
+ 'options' => array(
+ 'cn' => kolab_html::escape($this->translate('search.name')),
+ 'mail' => kolab_html::escape($this->translate('search.email')),
+ ),
+ ));
+ $form->add_element(array(
+ 'section' => 'criteria',
+ 'label' => $this->translate('search.method'),
+ 'name' => 'method',
+ 'type' => kolab_form::INPUT_SELECT,
+ 'options' => array(
+ 'both' => kolab_html::escape($this->translate('search.contains')),
+ 'exact' => kolab_html::escape($this->translate('search.is')),
+ 'prefix' => kolab_html::escape($this->translate('search.prefix')),
+ ),
+ ));
+
+ return $form->output();
+ }
+
+}
diff --git a/lib/client/kolab_client_task_user.php b/lib/client/kolab_client_task_user.php
index 5287006..2e81b65 100644
--- a/lib/client/kolab_client_task_user.php
+++ b/lib/client/kolab_client_task_user.php
@@ -197,6 +197,7 @@ class kolab_client_task_user extends kolab_client_task
'contact_info' => 'user.contact_info',
'system' => 'user.system',
'config' => 'user.config',
+ 'asterisk' => 'user.asterisk',
'other' => 'user.other',
);
@@ -257,11 +258,28 @@ class kolab_client_task_user extends kolab_client_task
'kolabdelegate' => 'config',
'kolaballowsmtprecipient' => 'config',
'kolaballowsmtpsender' => 'config',
+
+ /* Asterisk Settings */
+ 'astaccountallowedcodec' => 'asterisk',
+ 'astaccountcallerid' => 'asterisk',
+ 'astaccountcontext' => 'asterisk',
+ 'astaccountdeny' => 'asterisk',
+ 'astaccounthost' => 'asterisk',
+ 'astaccountnat' => 'asterisk',
+ 'astaccountname' => 'asterisk',
+ 'astaccountqualify' => 'asterisk',
+ 'astaccountrealmedpassword' => 'asterisk',
+ 'astaccountsecret' => 'asterisk',
+ 'astaccounttype' => 'asterisk',
+ 'astcontext' => 'asterisk',
+ 'astextension' => 'asterisk',
);
// Prepare fields
list($fields, $types, $type) = $this->form_prepare('user', $data, array('userpassword2'));
+ //console("Result from form_prepare", $fields, $types, $type);
+
$add_mode = empty($data['id']);
$accttypes = array();
diff --git a/lib/functions.php b/lib/functions.php
index 441752f..9761358 100644
--- a/lib/functions.php
+++ b/lib/functions.php
@@ -108,23 +108,26 @@ function write_log($name, $line)
$logfile = $log_dir . '/' . $name;
$date = date('d-M-Y H:i:s O');
$sess_id = session_id();
- $line = sprintf("[%s]%s: %s\n", $date, $sess_id ? "($sess_id)" : '', $line);
+ $logline = sprintf("[%s]%s: %s\n", $date, $sess_id ? "($sess_id)" : '', $line);
if ($fp = @fopen($logfile, 'a')) {
- fwrite($fp, $line);
+ fwrite($fp, $logline);
fflush($fp);
fclose($fp);
- return true;
+ return;
}
- return false;
+ if ($name == 'errors') {
+ // send error to PHPs error handler if write to file didn't succeed
+ trigger_error($line, E_USER_ERROR);
+ }
}
function timer($time = null, $label = '')
{
$now = microtime(true);
if ($time) {
- console(($label ? $label.' ' : '') . sprintf('%.4f', $now - $time));
+ //console(($label ? $label.' ' : '') . sprintf('%.4f', $now - $time));
}
return $now;
}
diff --git a/lib/kolab_api_controller.php b/lib/kolab_api_controller.php
index 7831971..d96d4ac 100644
--- a/lib/kolab_api_controller.php
+++ b/lib/kolab_api_controller.php
@@ -48,23 +48,27 @@ class kolab_api_controller
);
}
else {
- throw new Exception("Unknown method", 400);
+ throw new Exception("Unknown method " . $_GET['method'], 400);
}
}
else {
- throw new Exception("Unknown service", 400);
+ throw new Exception("Unknown service " . $_GET['service'], 400);
}
// TODO: register services based on config or whatsoever
- $this->add_service('form_value', 'kolab_api_service_form_value');
- $this->add_service('group_types', 'kolab_api_service_group_types');
- $this->add_service('group', 'kolab_api_service_group');
- $this->add_service('groups', 'kolab_api_service_groups');
- $this->add_service('user_types', 'kolab_api_service_user_types');
- $this->add_service('user', 'kolab_api_service_user');
- $this->add_service('users', 'kolab_api_service_users');
- $this->add_service('domains', 'kolab_api_service_domains');
- $this->add_service('roles', 'kolab_api_service_roles');
+ $this->add_service('domain', 'kolab_api_service_domain');
+ $this->add_service('domains', 'kolab_api_service_domains');
+ $this->add_service('form_value', 'kolab_api_service_form_value');
+ $this->add_service('group_types', 'kolab_api_service_group_types');
+ $this->add_service('group', 'kolab_api_service_group');
+ $this->add_service('groups', 'kolab_api_service_groups');
+ $this->add_service('resource_types', 'kolab_api_service_resource_types');
+ $this->add_service('resource', 'kolab_api_service_resource');
+ $this->add_service('resources', 'kolab_api_service_resources');
+ $this->add_service('roles', 'kolab_api_service_roles');
+ $this->add_service('user_types', 'kolab_api_service_user_types');
+ $this->add_service('user', 'kolab_api_service_user');
+ $this->add_service('users', 'kolab_api_service_users');
}
/**
@@ -73,7 +77,7 @@ class kolab_api_controller
public function add_service($service, $handler)
{
if ($this->services[$service]) {
- error_log("Service $service is already registered.");
+ //console("Service $service is already registered.");
return false;
}
@@ -100,7 +104,7 @@ class kolab_api_controller
}
}
- error_log("Unknown service $service");
+ //console("Unknown service $service");
throw new Exception("Unknown service", 400);
}
@@ -132,7 +136,7 @@ class kolab_api_controller
$method = $this->request['method'];
$postdata = @json_decode($postdata, true);
- console("Calling method " . $method . " on service " . $service);
+ //console("Calling method " . $method . " on service " . $service);
// validate user session
if ($service != 'system' || $method != 'authenticate') {
@@ -180,7 +184,7 @@ class kolab_api_controller
$method = $this->request['method'];
$url = rtrim($url, '/') . '/' . $service . '.' . $method;
- console("Proxying " . $url);
+ //console("Proxying " . $url);
$request = new HTTP_Request2();
$url = new Net_URL2($url);
@@ -296,7 +300,9 @@ class kolab_api_controller
*/
private function capabilities()
{
+ //console("system.capabilities called");
$auth = Auth::get_instance();
+
$this->domains = $auth->list_domains();
$result = array();
@@ -304,14 +310,17 @@ class kolab_api_controller
// Should we have no permissions to list domain name spaces,
// we should always return our own.
if (count($this->domains) < 1) {
+ //console("As there is but one domain, we insert our own");
$this->domains[] = $_SESSION['user']->get_domain();
}
+ //console("\$this->domains:", $this->domains);
+
// add capabilities of all registered services
foreach ($this->domains as $domain) {
// TODO: 'associateddomain' is very specific to 389ds based deployments, and this
// is supposed to be very generic.
- $domain_name = is_array($domain) ? $domain['associateddomain'] : $domain;
+ $domain_name = is_array($domain) ? (is_array($domain['associateddomain']) ? $domain['associateddomain'][0] : $domain['associateddomain']) : $domain;
// define our very own capabilities
$actions = array(
'system.quit' => array('type' => 'w'),
@@ -325,6 +334,8 @@ class kolab_api_controller
}
}
+ //console("api capabilities", $domain, $domain_name);
+
$result[$domain_name] = array('actions' => $actions);
}
diff --git a/lib/kolab_api_service.php b/lib/kolab_api_service.php
index d43aa67..7fca044 100644
--- a/lib/kolab_api_service.php
+++ b/lib/kolab_api_service.php
@@ -59,7 +59,7 @@ abstract class kolab_api_service
*/
protected function object_type_attributes($object_name, $type_id, $required = true)
{
- $supported = array('group', 'user');
+ $supported = array('domain', 'group', 'resource', 'role', 'user');
if (!$object_name || !in_array($object_name, $supported)) {
return array();
}
@@ -75,7 +75,29 @@ abstract class kolab_api_service
$object_types = $this->object_types($object_name);
if (empty($object_types[$type_id])) {
- throw new Exception($this->controller->translate($object_name . '.invalidtypeid'), 35);
+ if ($object_name == 'domain') {
+ $result = array(
+ 'auto_form_fields' => array(),
+ 'form_fields' => array(
+ 'associateddomain' => array(
+ 'type' => 'list'
+ ),
+ ),
+ 'fields' => array(
+ 'objectclass' => array(
+ 'top',
+ 'domainrelatedobject',
+ ),
+ ),
+ );
+
+ //console("object_type_attributes('domain', $type_id);", $result);
+
+ return $result;
+
+ } else {
+ throw new Exception($this->controller->translate($object_name . '.invalidtypeid'), 35);
+ }
}
return $object_types[$type_id]['attributes'];
@@ -91,6 +113,8 @@ abstract class kolab_api_service
*/
protected function object_type_id($object_name, $object_class)
{
+ if ($object_name == 'domain') return 1;
+
if (empty($object_class)) {
return null;
}
@@ -119,8 +143,8 @@ abstract class kolab_api_service
$commonalities = count($object_class) - $differences;
$elem_score = $differences > 0 ? ($commonalities / $differences) : $commonalities;
-// console("\$object_class not in \$ref_class (" . $elem['key'] . "): " . implode(", ", $_object_class));
-// console("\$ref_class not in \$object_class (" . $elem['key'] . "): " . implode(", ", $_ref_class));
+ //console("\$object_class not in \$ref_class (" . $elem['key'] . "): " . implode(", ", $_object_class));
+ //console("\$ref_class not in \$object_class (" . $elem['key'] . "): " . implode(", ", $_ref_class));
//console("Score for $object_name type " . $elem['name'] . ": " . $elem_score . "(" . $commonalities . "/" . $differences . ")");
if ($elem_score > $type_score) {
@@ -141,11 +165,12 @@ abstract class kolab_api_service
*/
protected function object_types($object_name)
{
- $supported = array('group', 'user');
+ $supported = array('group', 'resource', 'user');
if (!$object_name || !in_array($object_name, $supported)) {
return array();
}
+
if (!empty($this->cache['object_types']) && !empty($this->cache['object_types'][$object_name])) {
return $this->cache['object_types'][$object_name];
}
@@ -174,70 +199,12 @@ abstract class kolab_api_service
}
}
- return $this->cache['object_types'][$object_name] = $object_types;
- }
-
- /**
- * Parses result attributes
- *
- * @param string $object_name Name of the object (user, group, etc.)
- * @param array $attrs Entry attributes
- *
- * @return array Entry attributes
- */
- protected function parse_result_attributes($object_name, $attrs = array())
- {
- if (empty($attrs) || !is_array($attrs)) {
- return $attrs;
- }
-
- $conf = Conf::get_instance();
- $auth = Auth::get_instance();
- $dn = key($attrs);
- $attrs = $attrs[$dn];
- $extra_attrs = array();
+ //console("Object types for " . $object_name, $object_types);
- // add group type id to the result
- $attrs['type_id'] = $this->object_type_id($object_name, $attrs['objectclass']);
-
- // Search for attributes associated with the type_id that are not part
- // of the results returned earlier. Example: nsrole / nsroledn / aci, etc.
- // @TODO: this should go to LDAP class
- if ($attrs['type_id']) {
- $uta = $this->object_type_attributes($object_name, $attrs['type_id']);
+// return $object_types;
- foreach ((array)$uta as $field_type => $attributes) {
- foreach ($attributes as $attribute => $data) {
- if (!array_key_exists($attribute, $attrs)) {
- $extra_attrs[] = $attribute;
- }
- }
- }
- }
-
- // Insert the persistent, unique attribute
- $unique_attr = $conf->get('unique_attribute');
- if (!$unique_attr) {
- $unique_attr = 'nsuniqueid';
- }
-
- if (!array_key_exists($unique_attr, $attrs)) {
- $extra_attrs[] = $unique_attr;
- }
-
- // Get extra attributes
- if (!empty($extra_attrs)) {
- $extra_attrs = $auth->get_attributes($dn, $extra_attrs);
- if (!empty($extra_attrs)) {
- $attrs = array_merge($attrs, $extra_attrs);
- }
- }
-
- // Replace unique attribute with 'id' key
- $attrs['id'] = $attrs[$unique_attr];
- unset($attrs[$unique_attr]);
+ return $this->cache['object_types'][$object_name] = $object_types;
- return $attrs;
}
/**
@@ -253,8 +220,13 @@ abstract class kolab_api_service
$type_attrs = $this->object_type_attributes($object_name, $attribs['type_id']);
//console("parse_input_attributes", $type_attrs);
+ //console("called with \$attribs", $attribs);
$form_service = $this->controller->get_service('form_value');
+
+ // With the result, start validating the input
+ $form_service->validate(null, $attribs);
+
$result = array();
if (isset($type_attrs['form_fields'])) {
@@ -302,4 +274,75 @@ abstract class kolab_api_service
return $result;
}
+ /**
+ * Parses result attributes
+ *
+ * @param string $object_name Name of the object (user, group, etc.)
+ * @param array $attrs Entry attributes
+ *
+ * @return array Entry attributes
+ */
+ protected function parse_result_attributes($object_name, $attrs = array())
+ {
+ //console("parse_result_attributes($object_name, \$attrs = ", $attrs);
+
+ if (empty($attrs) || !is_array($attrs)) {
+ return $attrs;
+ }
+
+ $conf = Conf::get_instance();
+ $auth = Auth::get_instance();
+ $dn = key($attrs);
+ $attrs = $attrs[$dn];
+ $extra_attrs = array();
+
+ // add group type id to the result
+ $attrs['type_id'] = $this->object_type_id($object_name, $attrs['objectclass']);
+
+ if (empty($attrs['type_id'])) {
+ if ($object_name == 'domain') {
+ $attrs['type_id'] = 1;
+ }
+ }
+
+ // Search for attributes associated with the type_id that are not part
+ // of the results returned earlier. Example: nsrole / nsroledn / aci, etc.
+ // @TODO: this should go to LDAP class
+ if ($attrs['type_id']) {
+ $uta = $this->object_type_attributes($object_name, $attrs['type_id']);
+
+ foreach ((array)$uta as $field_type => $attributes) {
+ foreach ($attributes as $attribute => $data) {
+ if (!array_key_exists($attribute, $attrs)) {
+ $extra_attrs[] = $attribute;
+ }
+ }
+ }
+ }
+
+ // Insert the persistent, unique attribute
+ $unique_attr = $conf->get('unique_attribute');
+ if (!$unique_attr) {
+ $unique_attr = 'nsuniqueid';
+ }
+
+ if (!array_key_exists($unique_attr, $attrs)) {
+ $extra_attrs[] = $unique_attr;
+ }
+
+ // Get extra attributes
+ if (!empty($extra_attrs)) {
+ $extra_attrs = $auth->get_attributes($dn, $extra_attrs);
+ if (!empty($extra_attrs)) {
+ $attrs = array_merge($attrs, $extra_attrs);
+ }
+ }
+
+ // Replace unique attribute with 'id' key
+ $attrs['id'] = $attrs[$unique_attr];
+ unset($attrs[$unique_attr]);
+
+ return $attrs;
+ }
+
}
diff --git a/lib/kolab_client_api.php b/lib/kolab_client_api.php
index b8d101a..359fe73 100644
--- a/lib/kolab_client_api.php
+++ b/lib/kolab_client_api.php
@@ -60,6 +60,28 @@ class kolab_client_api
public function init()
{
$this->request = new HTTP_Request2();
+
+ // Configure connection options
+ $config = Conf::get_instance();
+ $options = array(
+ 'ssl_verify_peer' => Conf::BOOL,
+ 'ssl_verify_host' => Conf::BOOL,
+ 'ssl_cafile' => Conf::STRING,
+ 'ssl_capath' => Conf::STRING,
+ 'ssl_local_cert' => Conf::STRING,
+ 'ssl_passphrase' => Conf::STRING,
+ );
+
+ foreach ($options as $optname => $opttype) {
+ if (($optvalue = $config->get('kolab_wap', $optname, $opttype)) !== null) {
+ try {
+ $this->request->setConfig($optname, $optvalue);
+ }
+ catch (Exception $e) {
+ write_log('errors', $e->getMessage());
+ }
+ }
+ }
}
/**
@@ -128,6 +150,8 @@ class kolab_client_api
$this->request->setMethod(HTTP_Request2::METHOD_GET);
+ //console("GET", $url);
+
return $this->get_response($url);
}
@@ -147,6 +171,8 @@ class kolab_client_api
$this->request->setMethod(HTTP_Request2::METHOD_POST);
$this->request->setBody(@json_encode($post));
+ //console("POST", $url, $post);
+
return $this->get_response($url);
}
diff --git a/lib/kolab_client_output.php b/lib/kolab_client_output.php
index 6454acf..d40c323 100644
--- a/lib/kolab_client_output.php
+++ b/lib/kolab_client_output.php
@@ -51,7 +51,20 @@ class kolab_client_output
*/
private function init()
{
- require_once 'Smarty/Smarty.class.php';
+ $conf = Conf::get_instance();
+
+ $smarty_path = array('Smarty', 'smarty3', 'smarty');
+
+ if ($path = $conf->get('kolab_wap', 'smarty_path')) {
+ array_unshift($smarty_path, $path);
+ }
+
+ foreach ($smarty_path as $path) {
+ @include_once "$path/Smarty.class.php";
+ if (class_exists('Smarty', false)) {
+ break;
+ }
+ }
$SMARTY = new Smarty;
diff --git a/lib/kolab_client_task.php b/lib/kolab_client_task.php
index ab5b191..1740384 100644
--- a/lib/kolab_client_task.php
+++ b/lib/kolab_client_task.php
@@ -351,10 +351,7 @@ class kolab_client_task
$msg . (isset($args['file']) ? sprintf(' in %s on line %d', $args['file'], $args['line']) : ''),
$_SERVER['REQUEST_METHOD']);
- if (!write_log('errors', $log_line)) {
- // send error to PHPs error handler if write_log() didn't succeed
- trigger_error($msg, E_USER_ERROR);
- }
+ write_log('errors', $log_line);
if (!$output) {
return;
@@ -483,7 +480,7 @@ class kolab_client_task
$capabilities = $this->capabilities();
- //console($capabilities);
+ //console("Capabilities", $capabilities);
foreach ($this->menu as $idx => $label) {
//console("$task: $task, idx: $idx, label: $label");
@@ -524,6 +521,31 @@ class kolab_client_task
}
/**
+ * Returns list of resource types.
+ *
+ * @return array List of resource types
+ */
+ protected function resource_types()
+ {
+
+ if (isset($_SESSION['resource_types'])) {
+ return $_SESSION['resource_types'];
+ }
+
+
+ $result = $this->api->post('resource_types.list');
+ $list = $result->get('list');
+
+
+ if (is_array($list) && !$this->config_get('devel_mode')) {
+ $_SESSION['resource_types'] = $list;
+ }
+
+ return $list;
+ }
+
+
+ /**
* Returns list of user types.
*
* @return array List of user types
@@ -541,6 +563,8 @@ class kolab_client_task
$_SESSION['user_types'] = $list;
}
+ //console("user_types() \$list", $list);
+
return $list;
}
@@ -583,6 +607,8 @@ class kolab_client_task
$result = $this->api->post('system.capabilities');
$list = $result->get('list');
+ //console("Capabilities obtained from the API", $list);
+
if (is_array($list)) {
$_SESSION['capabilities'] = $list;
}
@@ -766,7 +792,12 @@ class kolab_client_task
*/
protected function form_prepare($name, &$data, $extra_fields = array())
{
+ //console("Preparing form for $name with data", $data);
+
$types = (array) $this->{$name . '_types'}();
+
+ //console("form_prepare types", $types);
+
$form_id = $attribs['id'];
$add_mode = empty($data['id']);
@@ -963,6 +994,7 @@ class kolab_client_task
$data[$fname] = (array) $data[$fname];
}
+ //console("The data for field $fname at this point is", $data[$fname]);
// request parameters
$post = array(
'list' => $data[$fname],
@@ -976,6 +1008,7 @@ class kolab_client_task
$result = $result->get('list');
$data[$fname] = $result;
+ //console("Set \$data['$fname'] to", $result);
}
}
@@ -1005,13 +1038,24 @@ class kolab_client_task
*/
protected function form_create($name, $attribs, $sections, $fields, $fields_map, $data, $add_mode)
{
+ //console("Creating form for $name with data", $data);
+
+ //console("Assign fields to sections", $fields);
// Assign sections to fields
foreach ($fields as $idx => $field) {
if (!$field['section']) {
$fields[$idx]['section'] = isset($fields_map[$idx]) ? $fields_map[$idx] : 'other';
+ //console("Assigned field $idx to section " . $fields[$idx]['section']);
+/*
+ } else {
+ $fields[$idx]['section'] = 'other';
+ //console("Assigned field $idx to section " . $fields[$idx]['section']);
+*/
}
}
+ //console("Using fields_map", $fields_map);
+
// Sort
foreach ($fields_map as $idx => $val) {
if (array_key_exists($idx, $fields)) {
@@ -1026,13 +1070,19 @@ class kolab_client_task
$fields_map = array_merge($fields_map, $fields);
}
+ //console("Using attribs", $attribs);
+
$form = new kolab_form($attribs);
$assoc_fields = array();
$req_fields = array();
$writeable = 0;
$auto_fields = $this->output->get_env('auto_fields');
- //console("\$auto_fields", $auto_fields);
+
+ //console("form_create() \$attribs", $attribs);
+ //console("form_create() \$auto_fields", $auto_fields);
+
+ //console("Going to walk through sections", $sections);
// Parse elements and add them to the form object
foreach ($sections as $section_idx => $section) {
@@ -1052,6 +1102,9 @@ class kolab_client_task
$field['section'] = $section_idx;
if (empty($field['value']) && !empty($data[$idx])) {
+
+ //console("Using data value", $data[$idx], "for value of field $idx");
+
$field['value'] = $data[$idx];
// Convert data for the list field with autocompletion
@@ -1116,6 +1169,8 @@ class kolab_client_task
}
}
+ //console("Adding field to form", $field);
+
$form->add_element($field);
}
}
diff --git a/lib/kolab_recipient_policy.php b/lib/kolab_recipient_policy.php
index 492df0b..10179d8 100644
--- a/lib/kolab_recipient_policy.php
+++ b/lib/kolab_recipient_policy.php
@@ -44,6 +44,12 @@ class kolab_recipient_policy {
foreach ($groupdata as $key => $value) {
if (isset($groupdata['preferredlanguage'])) {
setlocale(LC_ALL, $groupdata['preferredlanguage']);
+ } else {
+ $conf = Conf::get_instance();
+ $locale = $conf->get('default_locale');
+ if (!empty($locale)) {
+ setlocale(LC_ALL, $locale);
+ }
}
if (!is_array($groupdata[$key])) {
@@ -73,6 +79,12 @@ class kolab_recipient_policy {
if (isset($userdata['preferredlanguage'])) {
setlocale(LC_ALL, $userdata['preferredlanguage']);
+ } else {
+ $conf = Conf::get_instance();
+ $locale = $conf->get('default_locale');
+ if (!empty($locale)) {
+ setlocale(LC_ALL, $locale);
+ }
}
if (!is_array($userdata[$_key])) {
@@ -157,7 +169,7 @@ class kolab_recipient_policy {
);
}
} else {
- console("Key " . $substrings[1][$x] . " does not exist in \$userdata");
+ //console("Key " . $substrings[1][$x] . " does not exist in \$userdata");
}
}
@@ -175,6 +187,9 @@ class kolab_recipient_policy {
);
$userdata = self::normalize_userdata($userdata);
+ if (!array_key_exists('mail', $userdata)) {
+ $userdata['mail'] = self::primary_mail($userdata);
+ }
$conf = Conf::get_instance();
@@ -206,7 +221,7 @@ class kolab_recipient_policy {
if (array_key_exists($substrings[1][$x], $userdata)) {
$userdata[$substrings[1][$x]] = substr($userdata[$substrings[1][$x]], $substrings[2][$x], $substrings[3][$x]);
} else {
- console("Key " . $substrings[1][$x] . " does not exist in \$userdata");
+ //console("Key " . $substrings[1][$x] . " does not exist in \$userdata");
}
$rule = preg_replace(
@@ -234,6 +249,13 @@ class kolab_recipient_policy {
eval("\$result = sprintf('" . $format . "', '" . implode("', '", array_values($result)) . "');");
if ($result = self::parse_email($result)) {
+ // See if the equivalent is already in the 'mail' attribute value(s)
+ if (!empty($userdata['mail'])) {
+ if (strtolower($userdata['mail']) == strtolower($result)) {
+ continue;
+ }
+ }
+
$secondary_mail_addresses[] = $result;
}
}
diff --git a/lib/locale/en_US.php b/lib/locale/en_US.php
index 07e35bb..564803b 100644
--- a/lib/locale/en_US.php
+++ b/lib/locale/en_US.php
@@ -1,25 +1,85 @@
<?php
-$LANG['loading'] = 'Loading...';
-$LANG['saving'] = 'Saving data...';
+$LANG['about.community'] = 'This is the Community Edition of the <b>Kolab Server</b>.';
+$LANG['about.warranty'] = 'It comes with absolutely <b>no warranties</b> and is typically run entirely self supported. You can find help & information on the community <a href="http://kolab.org">web site</a> & <a href="http://wiki.kolab.org">wiki</a>.';
+$LANG['about.support'] = 'Professional support is available from <a href="http://kolabsys.com">Kolab Systems</a>.';
+$LANG['creatorsname'] = 'Created by';
+$LANG['days'] = 'days';
+$LANG['debug'] = 'Debug info';
+$LANG['delete.button'] = 'Delete';
$LANG['deleting'] = 'Deleting data...';
+
+$LANG['domain.add'] = 'Add Domain';
+$LANG['domain.add.success'] = 'Added domain';
+$LANG['domain.associateddomain'] = 'Domain name(s)';
+$LANG['domain.edit'] = 'Edit domain';
+$LANG['domain.edit.success'] = 'Domain updated';
+$LANG['domain.inetdomainbasedn'] = 'Custom Root DN(s)';
+$LANG['domain.list'] = 'Domains List';
+$LANG['domain.list.records'] = '$1 to $2 of $3';
+$LANG['domain.o'] = 'Organization';
+$LANG['domain.other'] = 'Other';
+$LANG['domain.system'] = 'System';
+$LANG['domain.type_id'] = 'Standard Domain';
+
$LANG['error'] = 'Error';
-$LANG['servererror'] = 'Server Error!';
-$LANG['loginerror'] = 'Incorrect username or password!';
-$LANG['internalerror'] = 'Internal system error!';
-$LANG['welcome'] = 'Welcome to the Kolab Groupware Server Maintenance';
-$LANG['reqtime'] = 'Request time: $1 sec.';
-$LANG['debug'] = 'Debug info';
-$LANG['info'] = 'Information';
-$LANG['creatorsname'] = 'Created by';
-$LANG['modifiersname'] = 'Modified by';
-$LANG['session.expired'] = 'Session has expired. Login again, please';
+$LANG['form.required.empty'] = 'Some of the required fields are empty!';
+
+$LANG['group.add'] = 'Add Group';
+$LANG['group.add.success'] = 'Group created successfully.';
+$LANG['group.cn'] = 'Common name';
+$LANG['group.delete.success'] = 'Group deleted successfully.';
+$LANG['group.edit.success'] = 'Group edited successfully.';
+$LANG['group.gidnumber'] = 'Primary group number';
+$LANG['group.list'] = 'Groups List';
+$LANG['group.list.records'] = '$1 to $2 of $3';
+$LANG['group.mail'] = 'Primary Email Address';
+$LANG['group.member'] = 'Member(s)';
+$LANG['group.norecords'] = 'No group records found!';
+$LANG['group.other'] = 'Other';
+$LANG['group.system'] = 'System';
+$LANG['group.type_id'] = 'Group type';
+$LANG['group.uniquemember'] = 'Members';
+
+$LANG['info'] = 'Information';
+$LANG['internalerror'] = 'Internal system error!';
+$LANG['loading'] = 'Loading...';
$LANG['login.username'] = 'Username:';
$LANG['login.password'] = 'Password:';
$LANG['login.login'] = 'Login';
+$LANG['loginerror'] = 'Incorrect username or password!';
+$LANG['MB'] = 'MB';
-$LANG['form.required.empty'] = 'Some of the required fields are empty!';
+$LANG['menu.about'] = 'About';
+$LANG['menu.domains'] = 'Domains';
+$LANG['menu.groups'] = 'Groups';
+$LANG['menu.kolab'] = 'Kolab';
+$LANG['menu.kolabsys'] = 'Kolab Systems';
+$LANG['menu.resources'] = 'Resources';
+$LANG['menu.technology'] = 'Technology';
+$LANG['menu.users'] = 'Users';
+
+$LANG['modifiersname'] = 'Modified by';
+$LANG['password.generate'] = 'Generate password';
+$LANG['reqtime'] = 'Request time: $1 sec.';
+
+$LANG['resource.add'] = 'Add Resource';
+$LANG['resource.add.success'] = 'Added Resource';
+$LANG['resource.cn'] = 'Name';
+$LANG['resource.delete'] = 'Delete Resource';
+$LANG['resource.delete.success'] = 'Successfully deleted Resource';
+$LANG['resource.edit'] = 'Edit Resource';
+$LANG['resource.edit.success'] = 'Successfully updated Resource';
+$LANG['resource.kolabtargetfolder'] = 'Target Folder';
+$LANG['resource.list.records'] = '$1 to $2 of $3';
+$LANG['resource.mail'] = 'Mail Address';
+$LANG['resource.other'] = 'Other';
+$LANG['resource.system'] = 'System';
+$LANG['resource.type_id'] = 'Resource Type';
+$LANG['resource.uniquemember'] = 'Collection Members';
+
+$LANG['saving'] = 'Saving data...';
$LANG['search'] = 'Search';
$LANG['search.criteria'] = 'Search criteria';
@@ -35,106 +95,91 @@ $LANG['search.uid'] = 'UID';
$LANG['search.loading'] = 'Searching...';
$LANG['search.acchars'] = 'At least $min characters required for autocompletion';
-$LANG['menu.users'] = 'Users';
-$LANG['menu.groups'] = 'Groups';
-$LANG['menu.about'] = 'About';
-$LANG['menu.kolab'] = 'Kolab';
-$LANG['menu.kolabsys'] = 'Kolab Systems';
-$LANG['menu.technology'] = 'Technology';
+$LANG['servererror'] = 'Server Error!';
+
+$LANG['session.expired'] = 'Session has expired. Login again, please';
+
+$LANG['submit.button'] = 'Submit';
$LANG['user.add'] = 'Add User';
+$LANG['user.add.success'] = 'User created successfully.';
+$LANG['user.alias'] = 'Secondary Email Address(es)';
+$LANG['user.astaccountallowedcodec'] = 'Allowed codec(s)';
+$LANG['user.astaccountcallerid'] = 'Caller ID';
+$LANG['user.astaccountcontext'] = 'Account Context';
+$LANG['user.astaccountdeny'] = 'Account deny';
+$LANG['user.astaccounthost'] = 'Asterisk Host';
+$LANG['user.astaccountnat'] = 'Account uses NAT';
+$LANG['user.astaccountname'] = 'Asterisk Account Name';
+$LANG['user.astaccountqualify'] = 'Account Qualify';
+$LANG['user.astaccountrealmedpassword'] = 'Realmed Account Password';
+$LANG['user.astaccountsecret'] = 'Plaintext Password';
+$LANG['user.astaccounttype'] = 'Account Type';
+$LANG['user.astcontext'] = 'Asterisk Context';
+$LANG['user.asterisk'] = 'Asterisk SIP';
+$LANG['user.astextension'] = 'Asterisk Extension';
$LANG['user.c'] = 'Country';
+$LANG['user.city'] = 'City';
$LANG['user.cn'] = 'Common name';
$LANG['user.config'] = 'Configuration';
$LANG['user.contact'] = 'Contact';
$LANG['user.contact_info'] = 'Contact Information';
+$LANG['user.country'] = 'Country';
+$LANG['user.country.desc'] = '2 letter code from ISO 3166-1';
+$LANG['user.delete.success'] = 'User deleted successfully.';
+$LANG['user.displayname'] = 'Display name';
+$LANG['user.edit.success'] = 'User edited successfully.';
+$LANG['user.fax'] = 'Fax number';
+$LANG['user.fbinterval'] = 'Free-Busy interval';
+$LANG['user.fbinterval.desc'] = 'Leave blank for default (60 days)';
+$LANG['user.gidnumber'] = 'Primary group number';
+$LANG['user.givenname'] = 'Given name';
+$LANG['user.homedirectory'] = 'Home directory';
$LANG['user.homephone'] = 'Home Phone Number';
+$LANG['user.initials'] = 'Initials';
+$LANG['user.invitation-policy'] = 'Invitation policy';
$LANG['user.kolaballowsmtprecipient'] = 'Recipient(s) Access List';
$LANG['user.kolaballowsmtpsender'] = 'Sender Access List';
$LANG['user.kolabdelegate'] = 'Delegates';
+$LANG['user.kolabhomeserver'] = 'Email Server';
$LANG['user.kolabinvitationpolicy'] = 'Invitation Handling Policy';
$LANG['user.l'] = 'City, Region';
$LANG['user.list'] = 'Users List';
$LANG['user.list.records'] = '$1 to $2 of $3';
+$LANG['user.loginshell'] = 'Shell';
+$LANG['user.mail'] = 'Primary Email Address';
+$LANG['user.mailalternateaddress'] = 'Secondary Email Address(es)';
+$LANG['user.mailhost'] = 'Email Server';
$LANG['user.mailquota'] = 'Quota';
$LANG['user.mailquota.desc'] = 'Leave blank for unlimited';
$LANG['user.mobile'] = 'Mobile Phone Number';
$LANG['user.name'] = 'Name';
$LANG['user.norecords'] = 'No user records found!';
+$LANG['user.nsrole'] = 'Role(s)';
+$LANG['user.nsroledn'] = $LANG['user.nsrole'];
$LANG['user.other'] = 'Other';
$LANG['user.o'] = 'Organization';
+$LANG['user.org'] = 'Organization';
+$LANG['user.orgunit'] = 'Organizational Unit';
$LANG['user.ou'] = 'Organizational Unit';
$LANG['user.pager'] = 'Pager Number';
+$LANG['user.password.mismatch'] = 'Passwords do not match!';
$LANG['user.personal'] = 'Personal';
+$LANG['user.phone'] = 'Phone number';
$LANG['user.postalcode'] = 'Postal Code';
+$LANG['user.postbox'] = 'Postal box';
+$LANG['user.postcode'] = 'Postal code';
+$LANG['user.preferredlanguage'] = 'Native tongue';
+$LANG['user.room'] = 'Room number';
$LANG['user.sn'] = 'Surname';
+$LANG['user.street'] = 'Street';
$LANG['user.system'] = 'System';
$LANG['user.telephonenumber'] = 'Phone Number';
$LANG['user.title'] = 'Job Title';
-$LANG['user.givenname'] = 'Given name';
-$LANG['user.displayname'] = 'Display name';
-$LANG['user.mail'] = 'Primary Email Address';
-$LANG['user.mailhost'] = 'Email Server';
-$LANG['user.kolabhomeserver'] = 'Email Server';
-$LANG['user.initials'] = 'Initials';
-$LANG['user.country'] = 'Country';
-$LANG['user.country.desc'] = '2 letter code from ISO 3166-1';
-$LANG['user.phone'] = 'Phone number';
-$LANG['user.fax'] = 'Fax number';
-$LANG['user.room'] = 'Room number';
-$LANG['user.street'] = 'Street';
-$LANG['user.city'] = 'City';
-$LANG['user.postbox'] = 'Postal box';
-$LANG['user.postcode'] = 'Postal code';
-$LANG['user.org'] = 'Organization';
-$LANG['user.orgunit'] = 'Organizational Unit';
-$LANG['user.fbinterval'] = 'Free-Busy interval';
-$LANG['user.fbinterval.desc'] = 'Leave blank for default (60 days)';
$LANG['user.type_id'] = 'Account type';
-$LANG['user.alias'] = 'Secondary Email Address(es)';
-$LANG['user.mailalternateaddress'] = 'Secondary Email Address(es)';
-$LANG['user.invitation-policy'] = 'Invitation policy';
-$LANG['user.delegate'] = 'Email delegates';
-$LANG['user.delegate.desc'] = 'Others allowed to send emails with a "From" address of this account';
-$LANG['user.smtp-recipients'] = 'Allowed recipients';
-$LANG['user.smtp-recipients.desc'] = 'Restricts allowed recipients of SMTP messages';
$LANG['user.uid'] = 'Unique identity (UID)';
-$LANG['user.nsrole'] = 'Role(s)';
-$LANG['user.nsroledn'] = $LANG['user.nsrole'];
$LANG['user.userpassword'] = 'Password';
$LANG['user.userpassword2'] = 'Confirm password';
-$LANG['user.password.mismatch'] = 'Passwords do not match!';
-$LANG['user.homeserver'] = 'Mailbox home server';
-$LANG['user.add.success'] = 'User created successfully.';
-$LANG['user.delete.success'] = 'User deleted successfully.';
-$LANG['user.edit.success'] = 'User edited successfully.';
-$LANG['user.preferredlanguage'] = 'Native tongue';
-$LANG['user.gidnumber'] = 'Primary group number';
-$LANG['user.homedirectory'] = 'Home directory';
-$LANG['user.loginshell'] = 'Shell';
$LANG['user.uidnumber'] = 'User ID number';
-$LANG['group.add'] = 'Add Group';
-$LANG['group.member'] = 'Member(s)';
-$LANG['group.norecords'] = 'No group records found!';
-$LANG['group.list'] = 'Groups List';
-$LANG['group.list.records'] = '$1 to $2 of $3';
-$LANG['group.cn'] = 'Common name';
-$LANG['group.mail'] = 'Primary Email Address';
-$LANG['group.type_id'] = 'Group type';
-$LANG['group.add.success'] = 'Group created successfully.';
-$LANG['group.delete.success'] = 'Group deleted successfully.';
-$LANG['group.edit.success'] = 'Group edited successfully.';
-$LANG['group.gidnumber'] = 'Primary group number';
-$LANG['group.uniquemember'] = 'Members';
-$LANG['group.system'] = 'System';
-$LANG['group.other'] = 'Other';
-
-$LANG['MB'] = 'MB';
-$LANG['days'] = 'days';
-$LANG['submit.button'] = 'Submit';
-$LANG['delete.button'] = 'Delete';
-$LANG['about.community'] = 'This is the Community Edition of the <b>Kolab Server</b>.';
-$LANG['about.warranty'] = 'It comes with absolutely <b>no warranties</b> and is typically run entirely self supported. You can find help & information on the community <a href="http://kolab.org">web site</a> & <a href="http://wiki.kolab.org">wiki</a>.';
-$LANG['about.support'] = 'Professional support is available from <a href="http://kolabsys.com">Kolab Systems</a>.';
-$LANG['password.generate'] = 'Generate password';
+$LANG['welcome'] = 'Welcome to the Kolab Groupware Server Maintenance';
diff --git a/public_html/api/index.php b/public_html/api/index.php
index cecb2f3..b5be580 100644
--- a/public_html/api/index.php
+++ b/public_html/api/index.php
@@ -32,7 +32,7 @@ try {
$postdata = $_SERVER['REQUEST_METHOD'] == 'POST' ? file_get_contents('php://input') : null;
$controller->dispatch($postdata);
} catch(Exception $e) {
- error_log('API Error: ' . $e->getMessage());
+ //console('API Error: ' . $e->getMessage());
$controller->output->error($e->getMessage(), $e->getCode());
}
diff --git a/public_html/js/kolab_admin.js b/public_html/js/kolab_admin.js
index bc83cac..b640679 100644
--- a/public_html/js/kolab_admin.js
+++ b/public_html/js/kolab_admin.js
@@ -1038,6 +1038,51 @@ function kolab_admin()
return false;
};
+ this.domain_info = function(id)
+ {
+ this.http_post('domain.info', {id: id});
+ };
+
+ this.domain_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('domain.' + 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('domain.' + action, data, 'domain_' + action + '_response');
+ };
+
+ this.domain_add_response = function(response)
+ {
+ if (!this.api_response(response))
+ return;
+
+ this.display_message('domain.add.success');
+ this.command('domain.list', {page: this.env.list_page});
+ };
+
+ this.domain_edit_response = function(response)
+ {
+ if (!this.api_response(response))
+ return;
+
+ this.display_message('domain.edit.success');
+ this.command('domain.list', {page: this.env.list_page});
+ };
+
this.user_info = function(id)
{
this.http_post('user.info', {id: id});
@@ -1200,6 +1245,84 @@ function kolab_admin()
this.command('group.list', {page: this.env.list_page});
};
+ this.resource_info = function(id)
+ {
+ this.http_post('resource.info', {id: id});
+ };
+
+ this.resource_list = function(props)
+ {
+ if (!props)
+ props = {};
+
+ if (props.search === undefined && this.env.search_request)
+ props.search_request = this.env.search_request;
+
+ this.http_post('resource.list', props);
+ };
+
+ this.resource_delete = function(resourceid)
+ {
+ this.set_busy(true, 'deleting');
+ this.api_post('resource.delete', {resource: resourceid}, 'resource_delete_response');
+ };
+
+ this.resource_delete_response = function(response)
+ {
+ if (!this.api_response(response))
+ return;
+
+ var page = this.env.list_page;
+
+ // goto previous page if last user on the current page has been deleted
+ if (this.env.list_count)
+ page -= 1;
+
+ this.display_message('resource.delete.success');
+ this.command('resource.list', {page: page});
+ };
+
+ this.resource_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('resource.' + 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('resource.' + action, data, 'resource_' + action + '_response');
+ };
+
+ this.resource_add_response = function(response)
+ {
+ if (!this.api_response(response))
+ return;
+
+ this.display_message('resource.add.success');
+ this.command('resource.list', {page: this.env.list_page});
+ };
+
+ this.resource_edit_response = function(response)
+ {
+ if (!this.api_response(response))
+ return;
+
+ this.display_message('resource.edit.success');
+ this.command('resource.list', {page: this.env.list_page});
+ };
+
+
this.generate_password = function(fieldname)
{
this.env.password_field = fieldname;
diff --git a/public_html/skins/default/style.css b/public_html/skins/default/style.css
index a3cd8c0..e39ece2 100644
--- a/public_html/skins/default/style.css
+++ b/public_html/skins/default/style.css
@@ -33,6 +33,7 @@ table.list {
border: 1px solid #d0d0d0;
border-spacing: 0;
border-radius: 3px;
+ width: 100%;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
}
@@ -553,7 +554,7 @@ span.listelement input {
span.listarea.disabled span.listelement input,
span.listarea.readonly span.listelement input {
- width: 370px;
+ width: 370px;
}
span.listelement input:focus {
diff --git a/public_html/skins/default/templates/domain.html b/public_html/skins/default/templates/domain.html
new file mode 100644
index 0000000..e658427
--- /dev/null
+++ b/public_html/skins/default/templates/domain.html
@@ -0,0 +1,17 @@
+<div id="toc" class="domain">
+ <div id="search">
+ <div class="searchinput">
+ <input type="text" id="searchinput" name="search" value="{$engine->translate('search')}" />
+ <script type="text/javascript">search_init('domain')</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="domainlist"></div>
+</div>
+<div class="vsplitter">&nbsp;</div>
+<div id="taskcontent" class="domain"></div>
+<div class="clear"></div>
diff --git a/public_html/skins/default/templates/resource.html b/public_html/skins/default/templates/resource.html
new file mode 100644
index 0000000..b2adf2f
--- /dev/null
+++ b/public_html/skins/default/templates/resource.html
@@ -0,0 +1,17 @@
+<div id="toc" class="resource">
+ <div id="search">
+ <div class="searchinput">
+ <input type="text" id="searchinput" name="search" value="{$engine->translate('search')}" />
+ <script type="text/javascript">search_init('resource')</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="resourcelist"></div>
+</div>
+<div class="vsplitter">&nbsp;</div>
+<div id="taskcontent" class="resource"></div>
+<div class="clear"></div>
diff --git a/public_html/skins/default/templates/role.html b/public_html/skins/default/templates/role.html
new file mode 100644
index 0000000..ba8d87e
--- /dev/null
+++ b/public_html/skins/default/templates/role.html
@@ -0,0 +1,17 @@
+<div id="toc" class="role">
+ <div id="search">
+ <div class="searchinput">
+ <input type="text" id="searchinput" name="search" value="{$engine->translate('search')}" />
+ <script type="text/javascript">search_init('role')</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="rolelist"></div>
+</div>
+<div class="vsplitter">&nbsp;</div>
+<div id="taskcontent" class="role"></div>
+<div class="clear"></div>