Page MenuHomePhorge

No OneTemporary

Authored By
Unknown
Size
61 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/api/kolab_api_service_form_value.php b/lib/api/kolab_api_service_form_value.php
index c6c7a3f..a8fbd2a 100644
--- a/lib/api/kolab_api_service_form_value.php
+++ b/lib/api/kolab_api_service_form_value.php
@@ -1,1685 +1,1685 @@
<?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 functionality related to HTML forms generation/validation.
*/
class kolab_api_service_form_value extends kolab_api_service
{
const VALIDATE_DEFAULT = 'default';
const VALIDATE_BASIC = 'basic';
const VALIDATE_EXTENDED = 'extended';
const VALIDATE_NONE = 'none';
/**
* Returns service capabilities.
*
* @param string $domain Domain name
*
* @return array Capabilities list
*/
public function capabilities($domain)
{
return array(
'generate' => 'r',
'validate' => 'r',
'select_options' => 'r',
'list_options' => 'r',
);
}
/**
* Generation of auto-filled field values.
*
* @param array $getdata GET parameters
* @param array $postdata POST parameters. Required parameters:
* - attributes: list of attribute names
* - type_id: Type identifier
* - object_type: Object type (user, group, etc.)
*
* @return array Response with attribute name as a key
*/
public function generate($getdata, $postdata)
{
$attribs = $this->object_type_attributes($postdata['object_type'], $postdata['type_id'], $type_key);
$attributes = (array) $postdata['attributes'];
$result = array();
$postdata['type_key'] = $type_key;
foreach ($attributes as $attr_name) {
if (empty($attr_name)) {
continue;
}
$method_name = 'generate_' . str_replace('-', '_', strtolower($attr_name)) . '_' . strtolower($postdata['object_type']);
if (!method_exists($this, $method_name)) {
Log::trace("Method $method_name doesn't exist");
$method_name = 'generate_' . str_replace('-', '_', strtolower($attr_name));
if (!method_exists($this, $method_name)) {
Log::trace("Method $method_name doesn't exist either");
continue;
}
}
Log::trace("Executing method $method_name");
$result[$attr_name] = $this->{$method_name}($postdata, $attribs);
}
Log::trace("Returning result: " . var_export($result, TRUE));
return $result;
}
/**
* 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 list_options($getdata, $postdata)
{
//console($postdata);
$attribs = $this->object_type_attributes($postdata['object_type'], $postdata['type_id'], $key_name);
$attr_name = $postdata['attribute'];
$result = array(
// return search value, so client can match response to request
'search' => $postdata['search'],
'list' => array(),
);
if (empty($attr_name)) {
return $result;
}
if ($key_name) {
$postdata['type_key'] = $key_name;
}
$method_name = 'list_options_' . strtolower($attr_name) . '_' . strtolower($postdata['object_type']);
if (!method_exists($this, $method_name)) {
Log::debug("Method $method_name doesn't exist");
$method_name = 'list_options_' . strtolower($attr_name);
if (!method_exists($this, $method_name)) {
Log::debug("Method $method_name doesn't exist");
return $result;
}
}
//console($method_name);
$result['list'] = $this->{$method_name}($postdata, $attribs);
return $result;
}
/**
* Generation of values for fields of type SELECT.
*
* @param array $getdata GET parameters
* @param array $postdata POST parameters. Required parameters:
* - attributes: list of attribute names
* - type_id: Type identifier
* - object_type: Object type (user, group, etc.)
*
* @return array Response with attribute name as a key
*/
public function select_options($getdata, $postdata)
{
//console("form_value.select_options postdata", $postdata);
$attribs = $this->object_type_attributes($postdata['object_type'], $postdata['type_id'], $key_name);
$attributes = (array) $postdata['attributes'];
$result = array();
if ($key_name) {
$postdata['type_key'] = $key_name;
}
foreach ($attributes as $attr_name) {
if (empty($attr_name)) {
continue;
}
$method_name = 'select_options_' . strtolower($attr_name);
if (method_exists($this, $method_name)) {
$res = $this->{$method_name}($postdata, $attribs);
}
else {
$res = array();
}
if (!is_array($res['list'])) {
$res['list'] = array();
}
$result[$attr_name] = $res;
}
return $result;
}
/**
* Validation of field values.
*
* @param array $getdata GET parameters
* @param array $postdata POST parameters. Required parameters:
* - 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)
{
$attribs = $this->object_type_attributes($postdata['object_type'], $postdata['type_id']);
$result = array();
Log::trace("kolab_api_form_value::validate() \$postdata: " . var_export($postdata, TRUE));
foreach ((array)$postdata as $attr_name => $attr_value) {
if (empty($attr_name) || $attr_name == 'type_id' || $attr_name == 'object_type') {
continue;
}
$method_name = 'validate_' . strtolower($attr_name) . '_' . strtolower($postdata['object_type']);
if (!method_exists($this, $method_name)) {
//console("Method $method_name doesn't exist");
$method_name = 'validate_' . strtolower($attr_name);
if (!method_exists($this, $method_name)) {
$result[$attr_name] = 'OK';
continue;
}
}
$validate = $attribs['form_fields'][$attr_name]['validate'];
// deprecated value: false = VALIDATE_NONE
if ($validate === false) {
$validate = self::VALIDATE_NONE;
}
if ($validate == self::VALIDATE_NONE) {
$result[$attr_name] = $attr_value;
}
else if ($attribs['form_fields'][$attr_name]['optional'] && $attr_value === '') {
$result[$attr_name] = $attr_value;
}
else {
$result[$attr_name] = $this->{$method_name}($attr_value, $postdata, $validate);
}
}
Log::trace("kolab_api_form_value::validate() \$result: " . var_export($result, TRUE));
return $result;
}
private function generate_alias($postdata, $attribs = array())
{
$rcpt_pol_aliases = $this->generate_secondary_mail($postdata, $attribs);
$service = $this->controller->get_service('user');
$user_attrs = $service->user_info(array('id' => $postdata['id']), null);
if (!empty($user_attrs['alias'])) {
$cur_aliases = $user_attrs['alias'];
} else {
$cur_aliases = Array();
}
if (!is_array($cur_aliases)) {
$cur_aliases = (array)($cur_aliases);
}
sort($rcpt_pol_aliases);
sort($cur_aliases);
$form_aliases = array_unique(array_merge($rcpt_pol_aliases, $cur_aliases));
Log::trace("kolab_api_service_form_value::generate_alias() \$form_aliases: " . var_export($form_aliases, TRUE));
return array_values($form_aliases);
}
private function generate_apple_generateduid($postdata, $attribs = array())
{
if (isset($attribs['auto_form_fields']) && isset($attribs['auto_form_fields']['apple-generateduid'])) {
$uuid = exec("uuidgen | tr '[:lower:]' '[:upper:]'");
return $uuid;
}
}
private function generate_astaccountcallerid($postdata, $attribs = array())
{
if (isset($attribs['auto_form_fields']) && isset($attribs['auto_form_fields']['astaccountcallerid'])) {
// Use Data Please
foreach ($attribs['auto_form_fields']['astaccountcallerid']['data'] as $key) {
if (!isset($postdata[$key])) {
throw new Exception("Key not set: " . $key, 12356);
}
}
// TODO: Correct this with what is in 'data'...
return $this->generate_cn($postdata, $attribs);
}
}
private function generate_astaccountdefaultuser($postdata, $attribs = array())
{
if (isset($attribs['auto_form_fields']) && isset($attribs['auto_form_fields']['astaccountdefaultuser'])) {
// Use Data Please
foreach ($attribs['auto_form_fields']['astaccountdefaultuser']['data'] as $key) {
if (!isset($postdata[$key])) {
throw new Exception("Key not set: " . $key, 12356);
}
}
return $this->generate_uid($postdata, $attribs);
}
}
private function generate_astaccountmailbox($postdata, $attribs = array())
{
if (isset($attribs['auto_form_fields']) && isset($attribs['auto_form_fields']['astaccountmailbox'])) {
// Use Data Please
foreach ($attribs['auto_form_fields']['astaccountmailbox']['data'] as $key) {
if (!isset($postdata[$key])) {
throw new Exception("Key not set: " . $key, 12356);
}
}
return $this->generate_uid($postdata, $attribs);
}
}
private function generate_astaccountregistrationcontext($postdata, $attribs = array())
{
if (isset($attribs['auto_form_fields']) && isset($attribs['auto_form_fields']['astaccountregistrationcontext'])) {
// Use Data Please
foreach ($attribs['auto_form_fields']['astaccountregistrationcontext']['data'] as $key) {
if (!isset($postdata[$key])) {
throw new Exception("Key not set: " . $key, 12356);
}
}
return $this->generate_uid($postdata, $attribs);
}
}
private function generate_astaccountregistrationexten($postdata, $attribs = array())
{
if (isset($attribs['auto_form_fields']) && isset($attribs['auto_form_fields']['astaccountregistrationexten'])) {
$search = array(
'params' => array(
'objectclass' => array(
'type' => 'exact',
'value' => 'asterisksipuser',
),
),
);
$auth = Auth::get_instance($_SESSION['user']->get_domain());
$conf = Conf::get_instance();
$users = $auth->list_users(NULL, Array('astaccountregistrationexten'), $search);
$lower_astaccountregistrationexten = $conf->get('astaccountregistrationexten_lower_barrier');
if (!$lower_astaccountregistrationexten) {
$lower_astaccountregistrationexten = 200;
}
// Start at the lower barrier + 1
$lower_astaccountregistrationexten = ($lower_astaccountregistrationexten + 1);
$higher_astaccountregistrationexten = $conf->get('astaccountregistrationexten_higher_barrier');
if (!$higher_astaccountregistrationexten) {
$higher_astaccountregistrationexten = 300;
}
$astaccountregistrationextens = Array();
foreach ($users['list'] as $dn => $attributes) {
if (!array_key_exists('astaccountregistrationexten', $attributes)) {
continue;
}
if ($attributes['astaccountregistrationexten'] > $highest_astaccountregistrationexten) {
$astaccountregistrationextens[] = $attributes['astaccountregistrationexten'];
}
}
for ($i = $lower_astaccountregistrationexten; $i < $higher_astaccountregistrationexten; $i++) {
if (!in_array($i, $astaccountregistrationextens)) {
$astaccountregistrationexten = $i;
break;
}
}
return $astaccountregistrationexten;
}
}
private function generate_cn($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);
}
}
// TODO: Generate using policy from configuration
$cn = trim(trim($postdata['givenname']) . " " . trim($postdata['sn']));
return $cn;
}
}
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());
$cn = trim($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 = $this->unique_attribute_value($resource_found_dn);
//console("resource with mail $mail found", $resource_found_unique_attr);
if ($resource_found_unique_attr == $postdata['id']) {
//console("that's us.");
break;
}
}
$cn = trim($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'])) {
// Use Data Please
foreach ($attribs['auto_form_fields']['displayname']['data'] as $key) {
if (!isset($postdata[$key])) {
throw new Exception("Key not set: " . $key, 12356);
}
}
// TODO: Generate using policy from configuration
$displayname = trim($postdata['givenname']);
$sn = trim($postdata['sn']);
if ($sn) {
$displayname = $sn . ", " . $displayname;
}
// TODO: Figure out what may be sent as an additional comment;
//
// Examples:
//
// - van Meeuwen, Jeroen (Kolab Systems)
// - Doe, John (Contractor)
//
return $displayname;
}
}
private function generate_gidnumber($postdata, $attribs = array())
{
if (isset($attribs['auto_form_fields']) && isset($attribs['auto_form_fields']['gidnumber'])) {
$auth = Auth::get_instance($_SESSION['user']->get_domain());
$conf = Conf::get_instance();
// TODO: Take a policy to use a known group ID, a known group (by name?)
// and/or create user private groups.
// groups search parameters
$params = array('page_size' => 200);
$search = array(
'operator' => 'AND',
'params' => array(
'objectclass' => array(
'type' => 'exact',
'value' => 'posixgroup',
),
'gidnumber' => array(
'type' => '>=',
)
),
);
$highest_gidnumber = $conf->get('gidnumber_lower_barrier');
if (!$highest_gidnumber) {
$highest_gidnumber = 999;
}
do {
$search['params']['gidnumber']['value'] = $highest_gidnumber;
$groups = $auth->list_groups(NULL, array('gidnumber'), $search, $params);
foreach ($groups['list'] as $dn => $attributes) {
if (!array_key_exists('gidnumber', $attributes)) {
continue;
}
if ($attributes['gidnumber'] > $highest_gidnumber) {
$highest_gidnumber = $attributes['gidnumber'];
}
}
}
while ($groups['count'] == $params['page_size']);
$gidnumber = ($highest_gidnumber + 1);
$postdata['gidnumber'] = $gidnumber;
if (empty($postdata['uidnumber'])) {
$uidnumber = $this->generate_uidnumber($postdata, $attribs);
$gidnumber = max($uidnumber, $gidnumber);
}
return $gidnumber;
}
}
private function generate_homedirectory($postdata, $attribs = array())
{
if (isset($attribs['auto_form_fields']) && isset($attribs['auto_form_fields']['homedirectory'])) {
// Use Data Please
foreach ($attribs['auto_form_fields']['homedirectory']['data'] as $key) {
if (!isset($postdata[$key])) {
throw new Exception("Key not set: " . $key, 12356);
}
}
// TODO: Home directory attribute to use
$uid = $this->generate_uid($postdata, $attribs);
// TODO: Home directory base path from configuration?
$conf = Conf::get_instance();
$homedirectory_base = $conf->get($_SESSION['user']->get_domain(), 'homedirectory_base');
if (empty($homedirectory_base)) {
$homedirectory_base = $conf->get('kolab', 'homedirectory_base');
}
if (empty($homedirectory_base)) {
$homedirectory_base = "/home/";
}
if (substr($homedirectory_base, (strlen($homedirectory_base)-1), 1) == "/") {
$homedirectory_base = substr($homedirectory_base, 0, (strlen($homedirectory_base)-1));
}
return $homedirectory_base . '/' . $uid;
}
}
private function generate_kolabtargetfolder_sharedfolder($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);
}
}
// no cn given then return empty
if (!trim($postdata['cn'])) {
return '';
}
// check format (will throw exception)
$this->validate_cn_sharedfolder($postdata['cn']);
$cn = $postdata['cn'];
$imap_hierarchysep = '/';
return $cn ? 'shared' . $imap_hierarchysep . $cn . '@' . $_SESSION['user']->get_domain() : '';
}
}
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);
}
private function generate_mail_group($postdata, $attribs = array())
{
return $this->generate_primary_mail_group($postdata, $attribs);
}
private function generate_mail_resource($postdata, $attribs = array())
{
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-' . $postdata['type_key'] . '-' . strtolower(trim($resourcedata['cn']));
$mail_domain = $_SESSION['user']->get_domain();
$mail = $mail_local . '@' . $mail_domain;
$auth = Auth::get_instance($_SESSION['user']->get_domain());
$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 = $this->unique_attribute_value($resource_found_dn);
//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);
}
private function generate_mailhost($postdata, $attribs = array())
{
if (isset($attribs['auto_form_fields']) && isset($attribs['auto_form_fields']['uidnumber'])) {
// This value is determined by the Kolab Daemon
return '';
}
}
private function generate_password($postdata, $attribs = array())
{
return password_policy::generate_password();
}
private function generate_userpassword($postdata, $attribs = array())
{
return $this->generate_password($postdata, $attribs);
}
private function generate_primary_mail($postdata, $attribs = array())
{
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);
}
}
if (array_key_exists('uid', $attribs['auto_form_fields'])) {
if (!array_key_exists('uid', $postdata)) {
$postdata['uid'] = $this->generate_uid($postdata, $attribs);
}
}
$primary_mail = kolab_recipient_policy::primary_mail($postdata);
$auth = Auth::get_instance();
list($_local, $_domain) = explode("@", $primary_mail);
$local = $_local;
$x = 2;
while (($user_found = $auth->find_recipient($local . "@" . $_domain))) {
Log::trace(__FUNCTION__ . ": An entry with address " . $local . "@" . $_domain . " was found.");
if (!empty($postdata['id'])) {
$user_found_dn = key($user_found);
$user_found_unique_attr = $this->unique_attribute_value($user_found_dn);
if ($user_found_unique_attr == $postdata['id']) {
Log::trace(__FUNCTION__ . ": Entry with address " . $local . "@" . $_domain . " is actually us.");
break;
}
} // empty($postdata['id'])
// Otherwise this is a new user and therefore the entry found with
// this address is definitely not us
$local = $_local . $x;
$x++;
}
$primary_mail = $local . "@" . $_domain;
return $primary_mail;
}
}
private function generate_primary_mail_group($postdata, $attribs = array())
{
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);
}
}
$primary_mail = kolab_recipient_policy::primary_mail_group($postdata);
return $primary_mail;
}
}
private function generate_secondary_mail($postdata, $attribs = array())
{
if (isset($attribs['auto_form_fields'])) {
if (isset($attribs['auto_form_fields']['alias'])) {
$secondary_mail_key = 'alias';
} elseif (isset($attribs['auto_form_fields']['mailalternateaddress'])) {
$secondary_mail_key = 'mailalternateaddress';
} else {
throw new Exception("No valid input for secondary mail address(es)", 478);
}
foreach ($attribs['auto_form_fields'][$secondary_mail_key]['data'] as $key) {
if (!isset($postdata[$key])) {
throw new Exception("Key not set: " . $key, 456789);
}
}
if (array_key_exists('uid', $attribs['auto_form_fields'])) {
if (!array_key_exists('uid', $postdata)) {
$postdata['uid'] = $this->generate_uid($postdata, $attribs);
}
}
if (array_key_exists('mail', $attribs['auto_form_fields'])) {
if (!array_key_exists('mail', $postdata)) {
$postdata['mail'] = $this->generate_primary_mail($postdata, $attribs);
}
}
$auth = Auth::get_instance();
$_secondary_mail_addresses = kolab_recipient_policy::secondary_mail($postdata);
$secondary_mail_addresses = array();
foreach ($_secondary_mail_addresses as $num => $alias) {
list($_local, $_domain) = explode("@", $alias);
$local = $_local;
$x = 2;
while (($user_found = $auth->find_recipient($local . "@" . $_domain))) {
Log::trace(__FUNCTION__ . ": An entry with address " . $local . "@" . $_domain . " was found.");
if (!empty($postdata['id'])) {
$user_found_dn = key($user_found);
$user_found_unique_attr = $this->unique_attribute_value($user_found_dn);
if ($user_found_unique_attr == $postdata['id']) {
Log::trace(__FUNCTION__ . ": Entry with address " . $local . "@" . $_domain . " is actually us.");
break;
}
} // empty($postdata['id'])
// Otherwise this is a new user and therefore the entry found with
// this address is definitely not us
$local = $_local . $x;
$x++;
}
$secondary_mail_addresses[] = $local . "@" . $_domain;
}
if (($key = array_search($postdata['mail'], $secondary_mail_addresses)) !== false) {
Log::trace("Found primary mail as part of the secondary mail addresses");
unset($secondary_mail_addresses[$key]);
}
return array_unique($secondary_mail_addresses);
}
}
private function generate_uid($postdata, $attribs = array())
{
if (isset($attribs['auto_form_fields']) && isset($attribs['auto_form_fields']['uid'])) {
// Use Data Please
foreach ($attribs['auto_form_fields']['uid']['data'] as $key) {
if (!isset($postdata[$key])) {
throw new Exception("Key not set: " . $key, 12356);
}
}
if (empty($postdata['uid'])) {
$postdata['uid'] = trim($postdata['sn']);
}
$userdata = kolab_recipient_policy::normalize_userdata($postdata);
$uid = kolab_recipient_policy::uid($userdata);
Log::debug("uid from recipient policy: " . var_export($uid, TRUE));
$orig_uid = $uid;
$auth = Auth::get_instance($_SESSION['user']->get_domain());
$x = 2;
while (($user_found = $auth->user_find_by_attribute(array('uid' => $uid)))) {
if (!empty($postdata['id'])) {
$user_found_dn = key($user_found);
$user_found_unique_attr = $this->unique_attribute_value($user_found_dn);
//console("user with uid $uid found", $user_found_unique_attr);
if ($user_found_unique_attr == $postdata['id']) {
//console("that's us.");
break;
}
}
$uid = $orig_uid . $x;
$x++;
}
return $uid;
}
}
private function generate_uidnumber($postdata, $attribs = array())
{
if (isset($attribs['auto_form_fields']) && isset($attribs['auto_form_fields']['uidnumber'])) {
$auth = Auth::get_instance($_SESSION['user']->get_domain());
$conf = Conf::get_instance();
// users search parameters
$params = array('page_size' => 200);
$search = array(
'operator' => 'AND',
'params' => array(
'objectclass' => array(
'type' => 'exact',
'value' => 'posixaccount',
),
'uidnumber' => array(
'type' => '>=',
),
),
);
$highest_uidnumber = $conf->get('uidnumber_lower_barrier');
if (!$highest_uidnumber) {
$highest_uidnumber = 999;
}
do {
$search['params']['uidnumber']['value'] = $highest_uidnumber;
$users = $auth->list_users(NULL, array('uidnumber'), $search, $params);
foreach ($users['list'] as $dn => $attributes) {
if (!array_key_exists('uidnumber', $attributes)) {
continue;
}
if ($attributes['uidnumber'] > $highest_uidnumber) {
$highest_uidnumber = $attributes['uidnumber'];
}
}
}
while ($users['count'] == $params['page_size']);
$uidnumber = ($highest_uidnumber + 1);
$postdata['uidnumber'] = $uidnumber;
if (empty($postdata['gidnumber'])) {
$gidnumber = $this->generate_gidnumber($postdata, $attribs);
$uidnumber = max($uidnumber, $gidnumber);
}
return $uidnumber;
}
}
private function list_options_kolabdelegate($postdata, $attribs = array())
{
return $this->_list_options_users($postdata, $attribs);
}
private function list_options_member($postdata, $attribs = array())
{
return $this->_list_options_members($postdata, $attribs);
}
private function list_options_nsrole($postdata, $attribs = array())
{
//console("Listing options for attribute 'nsrole', while the expected attribute to use is 'nsroledn'");
return $this->list_options_nsroledn($postdata, $attribs);
}
private function list_options_nsroledn($postdata, $attribs = Array())
{
// return specified records only, by exact DN attributes
if (!empty($postdata['list'])) {
$data['page_size'] = count($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(
'displayname' => $keyword,
'cn' => $keyword,
'mail' => $keyword,
);
}
$data['attributes'] = array('cn');
$service = $this->controller->get_service('roles');
$result = $service->roles_list(null, $data);
$list = $result['list'];
// convert to key=>value array
foreach ($list as $idx => $value) {
$list[$idx] = $value['cn'];
}
return $list;
}
private function list_options_ou($postdata, $attribs = array())
{
// return specified records only, by exact DN attributes
if (!empty($postdata['list'])) {
$data['page_size'] = count($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(
'entrydn' => $keyword,
'description' => $keyword,
);
}
$data['attributes'] = array('ou', 'entrydn');
$service = $this->controller->get_service('ous');
$result = $service->ous_list(null, $data);
$list = $result['list'];
// convert to key=>value array
foreach ($list as $idx => $value) {
$list[$idx] = kolab_utils::dn2ufn($idx);
}
return $list;
}
private function list_options_owner($postdata, $attribs = array())
{
return $this->_list_options_users($postdata, $attribs);
}
private function list_options_uniquemember($postdata, $attribs = array())
{
$result = $this->_list_options_members($postdata, $attribs);
return $result;
}
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');
}
private function select_options_objectclass($postdata, $attribs = array())
{
$auth = Auth::get_instance();
$list = $auth->schema_classes();
if (is_array($list)) {
sort($list);
}
return array('list' => $list);
}
private function select_options_attribute($postdata, $attribs = array())
{
// if objectClasses aren't specified we'll use all classes already in use
// not all classes in LDAP
if (empty($postdata['classes'])) {
$postdata['classes'] = array();
foreach ($this->supported_types as $type) {
foreach ($this->object_types($type) as $obj_type) {
if ($obj_type['attributes'] && $obj_type['attributes']['fields']) {
$postdata['classes'] = array_merge($postdata['classes'], (array) $obj_type['attributes']['fields']['objectclass']);
}
}
}
}
$postdata['classes'] = array_unique($postdata['classes']);
$auth = Auth::get_instance();
$list = $auth->schema_attributes($postdata['classes']);
if (is_array($list['may'])) {
// return required + optional
if (is_array($list['must']) && !empty($list['must'])) {
$list['may'] = array_unique(array_merge($list['may'], $list['must']));
}
sort($list['may']);
}
return array(
'list' => $list['may'],
'required' => $list['must']
);
}
private function select_options_ou($postdata, $attribs = array())
{
$auth = Auth::get_instance();
$conf = Conf::get_instance();
$unique_attr = self::unique_attribute();
$object_type = $postdata['object_type'];
$object_key = $postdata['type_key'];
$base_dn = $auth->subject_base_dn($object_key, $object_type);
if (!empty($postdata['id'])) {
$subjects = $auth->search($base_dn, '(' . $unique_attr . '=' . $postdata['id'] . ')', 'sub', array('dn'));
if ($subjects) {
$subjects = $subjects->entries(true);
$subject_dn = key($subjects);
$subject_dn_components = kolab_utils::explode_dn($subject_dn);
if ($subject_dn_components) {
array_shift($subject_dn_components);
$default = strtolower(implode(',', $subject_dn_components));
}
}
}
if (empty($default)) {
$default = $base_dn;
}
$result = array();
$params = array(
'type' => $object_key,
'page_size' => 99999,
);
$ous = $auth->list_organizationalunits(null, array(''), null, $params);
if ($ous['count']) {
foreach ($ous['list'] as $ou_dn => $ou_attrs) {
$result[] = strtolower($ou_dn);
}
sort($result);
}
return array(
'list' => $result,
'default' => strtolower($default),
);
}
private function select_options_preferredlanguage($postdata, $attribs = array())
{
$options = $this->_select_options_from_db('preferredlanguage');
$conf = Conf::get_instance();
$default = $conf->get('default_locale');
if (!$default) {
$default = 'en_US';
}
if (!empty($postdata['preferredlanguage'])) {
$default = $postdata['preferredlanguage'];
}
$options['default'] = $default;
return $options;
}
/**
* Checks if specified list of email addresses is already
* in use by another user
*/
private function _email_addresses_in_use($addresses, $attr_name, $postdata)
{
$auth = Auth::get_instance();
foreach ($addresses as $addr) {
if ($users = $auth->find_recipient($addr)) {
Log::trace(__FUNCTION__ . ": An entry with address $addr was found.");
if (!empty($postdata['id']) && count($users) == 1) {
$user_found_dn = key($users);
$user_found_unique_attr = $this->unique_attribute_value($user_found_dn);
if ($user_found_unique_attr == $postdata['id']) {
// check if the address is in another field, we prevent here
// from e.g. adding primary mail address into aliases list
$found = false;
$user = $users[$user_found_dn];
$addr = mb_strtolower($addr);
unset($user[$attr_name]);
foreach ($user as $attr => $list) {
$list = array_map('mb_strtolower', (array) $list);
if (in_array($addr, $list)) {
$found = true;
break;
}
}
if (!$found) {
Log::trace(__FUNCTION__ . ": Entry with address $addr is actually us.");
continue;
}
// @TODO: throw different exception?
}
}
throw new Exception("Email address '$addr' is already in use", 694);
}
}
}
private function validate_alias($value, $postdata = null, $validation_type = null)
{
$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);
}
if ($validation_type == self::VALIDATE_BASIC) {
continue;
}
// 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);
}
}
}
// Check if addresses are not already in use
if ($validation_type == self::VALIDATE_EXTENDED) {
$this->_email_addresses_in_use($value, 'alias', $postdata);
}
return 'OK';
}
private function validate_associateddomain($value, $postdata = array(), $validation_type = null)
{
if (!is_array($value)) {
$value = (array) $value;
}
return $value;
}
private function validate_astaccountrealmedpassword($value, $postdata = array(), $validation_type = null)
{
if (!array_key_exists('userpassword', $postdata) || empty($postdata['userpassword'])) {
return $value;
}
if (!array_key_exists('uid', $postdata) || empty($postdata['uid'])) {
$postdata['uid'] = $this->generate_uid($postdata);
}
$str = $postdata['uid'] . ":" . $_SESSION['user']->get_domain() . ":" . $postdata['userpassword'];
Log::trace("Inserting astaccountrealmedpassword with value md5('" . $str . "');");
return md5($str);
}
private function validate_mail($value, $postdata = array(), $validation_type = null)
{
$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);
}
if ($validation_type == self::VALIDATE_BASIC) {
continue;
}
// 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);
}
}
}
return 'OK';
}
private function validate_mailquota($value, $postdata = array(), $validation_type = null)
{
// convert MB/GB into KB
if (preg_match('/^([0-9]+)\s*(KB|MB|GB)$/i', $value, $m)) {
switch (strtoupper($m[2])) {
case 'KB': $value = $m[1]; break;
case 'MB': $value = $m[1] * 1024; break;
case 'GB': $value = $m[1] * 1024 * 1024; break;
}
}
return (string) intval($value);
}
private function validate_mailalternateaddress($value, $postdata = array(), $validation_type = null)
{
$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);
}
if ($validation_type == self::VALIDATE_BASIC) {
continue;
}
// 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);
}
}
}
return 'OK';
}
private function validate_cn_sharedfolder($value, $postdata = array(), $validation_type = null)
{
if (preg_match('/["\'@%+^]/',$value)) {
throw new Exception("Folder name contains invalid characters: \" ' @ % + ^");
}
return 'OK';
}
private function validate_kolabtargetfolder_sharedfolder($value, $postdata = array(), $validation_type = null)
{
$domains = $this->_get_valid_domains();
if (!preg_match('#^shared/[^"\'\\+@%^]+@('.implode("|",$domains).')$#',$value)) {
throw new Exception("Target IMAP Folder has to match the following format: 'shared/foldername@mydomain.org' and the foldername can't contain invalid characters: \" ' @ % + ^");
}
// TODO: check for duplicate shared folder
// same kolabTargetFolder && type = 'mail || type != mail && folderpart == cn (other)
return 'OK';
}
private function _list_options_members($postdata, $attribs = array())
{
// return specified records only, by exact DN attributes
if (!empty($postdata['list'])) {
$data['page_size'] = count($postdata['list']);
$data['search'] = array(
'params' => array(
'entrydn' => array(
'value' => $postdata['list'],
'type' => 'exact',
),
),
'operator' => 'OR'
);
}
// return records with specified string
else {
$keyword = array('value' => $postdata['search'], 'type' => 'both');
$data['page_size'] = 15;
$data['search'] = array(
'params' => array(
'displayname' => $keyword,
'cn' => $keyword,
'mail' => $keyword,
),
'operator' => 'OR'
);
}
$data['attributes'] = array('displayname', 'cn', 'mail');
$service = $this->controller->get_service('users');
$result = $service->users_list(null, $data);
$list = $result['list'];
// skip groups listing if the list if already full,
// and full list was requested (no paging)
if (empty($keyword) && $result['count'] < $data['page_size']) {
$data['attributes'] = array('cn', 'mail');
$service = $this->controller->get_service('groups');
$result = $service->groups_list(null, $data);
$list = array_merge($list, $result['list']);
}
// convert to key=>value array
foreach ($list as $idx => $value) {
if (!empty($value['displayname'])) {
$list[$idx] = $value['displayname'];
}
else if (!empty($value['cn'])) {
$list[$idx] = $value['cn'];
}
else {
$list[$idx] = '';
}
if (!empty($value['mail'])) {
$list[$idx] .= ' <' . $value['mail'] . '>';
}
$list[$idx] = trim($list[$idx]);
if ($list[$idx] === '') {
unset($list[$idx]);
}
}
// Sort and slice
asort($list);
if (!empty($data['page_size'])) {
$list = array_slice($list, 0, $data['page_size']);
}
return $list;
}
private function _list_options_users($postdata, $attribs = array())
{
// return specified records only, by exact DN attributes
if (!empty($postdata['list'])) {
$data['page_size'] = count($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(
'displayname' => $keyword,
'cn' => $keyword,
'mail' => $keyword,
);
}
$data['attributes'] = array('displayname', 'mail');
$service = $this->controller->get_service('users');
$result = $service->users_list(null, $data);
$list = $result['list'];
$result = array();
$result_key = $postdata['result_key'] ?: 'entrydn';
// convert to key=>value array
foreach ($list as $idx => $value) {
$ret = $value['displayname'];
if (!empty($value['mail'])) {
$ret .= ' <' . $value['mail'] . '>';
}
if ($result_key != 'entrydn') {
$idx = $value[$result_key];
}
$ret = trim($ret);
// sanity check (#3822)
if ($ret !== '') {
$result[$idx] = $ret;
}
}
return $result;
}
private function _list_options_resources($postdata, $attribs = array())
{
// return specified records only, by exact DN attributes
if (!empty($postdata['list'])) {
$data['page_size'] = count($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 {
unset($list[$idx]);
}
}
return $list;
}
private function _select_options_from_db($attribute)
{
if (empty($attribute)) {
return false;
}
$db = SQL::get_instance();
$query = $db->query("SELECT `option_values` FROM `options` WHERE `attribute` = ?", array($attribute));
$result = $db->fetch_assoc($query);
$result = json_decode($result['option_values']);
return array('list' => $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) > 64) {
// local part length exceeded
//console("Local part of email address is longer than permitted");
$valid = false;
} else if (strlen($domain) < 1 || strlen($domain) > 255) {
// domain part length exceeded
//console("Domain part of email address is longer than permitted");
$valid = false;
} else if ($local[0] == '.' || $local[strlen($local)-1] == '.') {
// local part starts or ends with '.'
//console("Local part of email address starts or ends with '.'");
$valid = false;
} else if (preg_match('/\\.\\./', $local)) {
// local part has two consecutive dots
//console("Local part contains two consecutive dots");
$valid = false;
} else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)) {
// character not valid in domain part
//console("Invalid character in domain part");
$valid = false;
} else if (preg_match('/\\.\\./', $domain)) {
// domain part has two consecutive dots
//console("Domain part contains two consecutive dots");
$valid = false;
} else if (strlen($local) > 0) {
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))) {
//console("Unquoted invalid character in local part");
$valid = false;
}
}
}
// if ($valid && !(checkdnsrr($domain,"MX") || checkdnsrr($domain,"A"))) {
// // domain not found in DNS
// $valid = false;
// }
}
return $valid;
}
/**
* Lists the valid domains given a primary domain name space.
*
* Includes the parent domain and any alias or child domains.
* Considers domains that point to the same base dn to be child domains.
*/
private function _get_valid_domains($my_primary_domain = null)
{
$my_primary_domain = $my_primary_domain !== null
? $my_primary_domain
: $_SESSION['user']->get_domain();
$auth = Auth::get_instance();
$conf = Conf::get_instance();
- $all_domains = $auth->list_domains();
+ $all_domains = $auth->list_domains(array(), array(), array('page_size' => 99999));
$all_domains = $all_domains['list'];
$all_basedns = Array();
$dna = $conf->get('domain_name_attribute');
$dra = $conf->get('domain_rootdn_attribute');
Log::trace("_get_valid_domains(" . $my_primary_domain . ")");
$valid_domains = $my_primary_domain ? array($my_primary_domain) : array();
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 (array_key_exists($dra, $domain_attrs)) {
if (array_key_exists($domain_attrs[$dra], $all_basedns)) {
$all_basedns[$domain_attrs[$dra]] = array_merge($all_basedns[$domain_attrs[$dra]], $domain_attrs[$dna]);
} else {
$all_basedns[$domain_attrs[$dra]] = $domain_attrs[$dna];
}
}
}
foreach ($all_basedns as $base_dn => $domains) {
if (in_array($my_primary_domain, $domains)) {
$valid_domains = array_merge($valid_domains, $domains);
}
}
$result = array_unique($valid_domains);
Log::trace("_get_valid_domains result: " . var_export($result, TRUE));
return array_unique($result);
}
private function _validate_email_address_in_any_of_my_domains($mail_address)
{
$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);
}
$my_primary_domain = $_SESSION['user']->get_domain();
if ($email_domain == $my_primary_domain) {
Log::trace("Found email address to be in one of my domains.");
return true;
}
$valid = false;
Log::trace("_validate_email_address_in_any_of_mydomains(\$mail_address = " . var_export($mail_address, TRUE) . ")");
if (in_array($email_domain, $this->_get_valid_domains($my_primary_domain))) {
$valid = true;
}
if ($valid) {
Log::trace("Found email address to be in one of my domains.");
} else {
Log::trace("Found email address to NOT be in one of my domains.");
}
return $valid;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Apr 4, 4:43 AM (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18820415
Default Alt Text
(61 KB)

Event Timeline