* API/Addressbook/EMailAdmin: full support for active directory as account storage, tested with Samba4 and win2008r2

Trunk commits r42507, r42545, r42556, r42557, r42612, r42630
plugin to support Active Directory to store email configuration (in proxyAddresses attribute, no Exchange schema and support!), also fully autodetecting plugins now in emailadmin/inc directory
This commit is contained in:
Ralf Becker 2013-06-06 07:21:42 +00:00
commit 3e40eaf0cb
50 changed files with 3131 additions and 595 deletions

View File

@ -0,0 +1,203 @@
<?php
/**
* Addressbook - ADS Backend
*
* @link http://www.egroupware.org
* @author Ralf Becker <rb@stylite.de>
* @package addressbook
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
/**
* Active directory backend for accounts (not yet AD contacts)
*
* We use ADS string representation of objectGUID as contact ID and UID.
*
* Unfortunatly Samba4 and active directory of win2008r2 differn on how to search for an objectGUID:
* - Samba4 can only search for string representation eg. (objectGUID=2336A3FC-EDBD-42A2-9EEB-BD7A5DD2804E)
* - win2008r2 can only search for hex representation eg. (objectGUID=\FC\A3\36\23\BD\ED\A2\42\9E\EB\BD\7A\5D\D2\80\4E)
* We could use both filters or-ed together, for now we detect Samba4 and use string GUID for it.
*
* All values used to construct filters need to run through ldap::quote(),
* to be save against LDAP query injection!!!
*/
class addressbook_ads extends addressbook_ldap
{
/**
* LDAP searches only a limited set of attributes for performance reasons,
* you NEED an index for that columns, ToDo: make it configurable
* minimum: $this->columns_to_search = array('n_family','n_given','org_name','email');
*/
var $search_attributes = array(
'n_family','n_middle','n_given','org_name','org_unit',
'adr_one_location','note','email','samaccountname',
);
/**
* Filter used for accounts addressbook
* @var string
*/
var $accountsFilter = '(objectclass=user)';
/**
* Attribute used for DN
*
* @var string
*/
var $dn_attribute='cn';
/**
* Accounts ADS object
*
* @var accounts_ads
*/
protected $accounts_ads;
/**
* ADS is Samba4 (true), otherwise false
*
* @var boolean
*/
public $is_samba4 = false;
/**
* constructor of the class
*
* @param array $ldap_config=null default use from $GLOBALS['egw_info']['server']
* @param resource $ds=null ldap connection to use
*/
function __construct(array $ldap_config=null, $ds=null)
{
//$this->db_data_cols = $this->stock_contact_fields + $this->non_contact_fields;
$this->accountName = $GLOBALS['egw_info']['user']['account_lid'];
if ($ldap_config)
{
$this->ldap_config = $ldap_config;
}
else
{
$this->ldap_config =& $GLOBALS['egw_info']['server'];
}
$this->accounts_ads = $GLOBALS['egw']->accounts->backend;
//$this->personalContactsDN = 'ou=personal,ou=contacts,'. $this->ldap_config['ldap_contact_context'];
//$this->sharedContactsDN = 'ou=shared,ou=contacts,'. $this->ldap_config['ldap_contact_context'];
$this->allContactsDN = $this->accountContactsDN = $this->accounts_ads->ads_context();
if ($ds)
{
$this->ds = $ds;
}
else
{
$this->connect();
}
$this->ldapServerInfo = ldapserverinfo::get($this->ds, $this->ldap_config['ads_host']);
$this->is_samba4 = $this->ldapServerInfo->serverType == SAMBA4_LDAPSERVER;
// AD seems to use user, instead of inetOrgPerson
$this->schema2egw['user'] = $this->schema2egw['inetorgperson'];
$this->schema2egw['user'] += array(
'account_id' => 'objectsid',
'account_lid' => 'samaccountname',
'contact_uid' => 'objectguid',
);
foreach($this->schema2egw as $schema => $attributes)
{
$this->all_attributes = array_merge($this->all_attributes,array_values($attributes));
}
$this->all_attributes = array_values(array_unique($this->all_attributes));
$this->charset = translation::charset();
}
/**
* connect to LDAP server
*
* @param boolean $admin=false true (re-)connect with admin not user credentials, eg. to modify accounts
*/
function connect($admin=false)
{
$this->ds = $this->accounts_ads->ldap_connection();
}
/**
* Return LDAP filter for contact id
*
* @param string $contact_id
* @return string
*/
protected function id_filter($contact_id)
{
// check that GUID eg. from URL contains only valid hex characters and dash
// we cant use ldap::quote() for win2008r2 hex GUID, as it contains backslashes
if (!preg_match('/^[0-9A-Fa-f-]+/', $contact_id))
{
throw new egw_exception_assertion_failed("'$contact_id' is NOT a valid GUID!");
}
// samba4 can only search by string representation of objectGUID, while win2008r2 requires hex representation
return '(objectguid='.($this->is_samba4 ? $contact_id : $this->accounts_ads->objectguid2hex($contact_id)).')';
}
/**
* reads contact data
*
* @param string/array $contact_id contact_id or array with values for id or account_id
* @return array/boolean data if row could be retrived else False
*/
function read($contact_id)
{
if (is_array($contact_id) && isset($contact_id['account_id']) ||
!is_array($contact_id) && substr($contact_id,0,8) == 'account:')
{
$account_id = (int)(is_array($contact_id) ? $contact_id['account_id'] : substr($contact_id,8));
$contact_id = $GLOBALS['egw']->accounts->id2name($account_id, 'person_id');
}
$contact_id = !is_array($contact_id) ? $contact_id :
(isset ($contact_id['id']) ? $contact_id['id'] : $contact_id['uid']);
$rows = $this->_searchLDAP($this->allContactsDN, $filter=$this->id_filter($contact_id), $this->all_attributes, ADDRESSBOOK_ALL);
//error_log(__METHOD__."('$contact_id') _searchLDAP($this->allContactsDN, '$filter',...)=".array2string($rows));
return $rows ? $rows[0] : false;
}
/**
* Special handling for mapping data of ADA user objectclass to eGW contact
*
* Please note: all regular fields are already copied!
*
* @internal
* @param array &$contact already copied fields according to the mapping
* @param array $data eGW contact data
*/
function _user2egw(&$contact, $data)
{
$contact['account_id'] = $this->accounts_ads->objectsid2account_id($data['objectsid']);
$contact['id'] = $contact['contact_uid'] = $this->accounts_ads->objectguid2str($data['objectguid']);
// ignore system accounts
if ($contact['account_id'] < accounts_ads::MIN_ACCOUNT_ID) return false;
$this->_inetorgperson2egw($contact, $data);
}
/**
* Remove attributes we are not allowed to update
*
* @param array $attributes
*/
function sanitize_update(array &$ldapContact)
{
// not allowed and not need to update these in AD
unset($ldapContact['objectguid']);
unset($ldapContact['objectsid']);
parent::sanitize_update($ldapContact);
}
}

View File

@ -59,6 +59,29 @@ class addressbook_ldap
*/
var $sharedContactsDN;
/**
* @var string $accountContactsDN holds the base DN for accounts addressbook
*/
var $accountContactsDN;
/**
* Filter used for accounts addressbook
* @var string
*/
var $accountsFilter = '(objectclass=posixaccount)';
/**
* @var string $allContactsDN holds the base DN of all addressbook
*/
var $allContactsDN;
/**
* Attribute used for DN
*
* @var string
*/
var $dn_attribute='uid';
/**
* @var int $total holds the total count of found rows
*/
@ -71,6 +94,17 @@ class addressbook_ldap
*/
var $charset;
/**
* LDAP searches only a limited set of attributes for performance reasons,
* you NEED an index for that columns, ToDo: make it configurable
* minimum: $this->columns_to_search = array('n_family','n_given','org_name','email');
*/
var $search_attributes = array(
'n_family','n_middle','n_given','org_name','org_unit',
'adr_one_location','adr_two_location','note',
'email','mozillasecondemail','uidnumber',
);
/**
* maps between diverse ldap schema and the eGW internal names
*
@ -82,6 +116,7 @@ class addressbook_ldap
'posixaccount' => array(
'account_id' => 'uidnumber',
'account_lid' => 'uid',
'shadowexpire',
),
'inetorgperson' => array(
'n_fn' => 'cn',
@ -209,6 +244,13 @@ class addressbook_ldap
*/
private $ldap_config;
/**
* LDAP connection
*
* @var resource
*/
var $ds;
/**
* constructor of the class
*
@ -228,8 +270,10 @@ class addressbook_ldap
{
$this->ldap_config =& $GLOBALS['egw_info']['server'];
}
$this->personalContactsDN = 'ou=personal,ou=contacts,'. $this->ldap_config['ldap_contact_context'];
$this->sharedContactsDN = 'ou=shared,ou=contacts,'. $this->ldap_config['ldap_contact_context'];
$this->accountContactsDN = $this->ldap_config['ldap_context'];
$this->allContactsDN = $this->ldap_config['ldap_contact_context'];
$this->personalContactsDN = 'ou=personal,ou=contacts,'. $this->allContactsDN;
$this->sharedContactsDN = 'ou=shared,ou=contacts,'. $this->allContactsDN;
if ($ds)
{
@ -260,14 +304,20 @@ class addressbook_ldap
/**
* connect to LDAP server
*
* @param boolean $admin=false true (re-)connect with admin not user credentials, eg. to modify accounts
*/
function connect()
function connect($admin = false)
{
if ($admin)
{
$this->ds = $GLOBALS['egw']->ldap->ldapConnect();
}
// if ldap is NOT the contact repository, we only do accounts and need to use the account-data
if (substr($GLOBALS['egw_info']['server']['contact_repository'],-4) != 'ldap') // not (ldap or sql-ldap)
elseif (substr($GLOBALS['egw_info']['server']['contact_repository'],-4) != 'ldap') // not (ldap or sql-ldap)
{
$this->ldap_config['ldap_contact_host'] = $this->ldap_config['ldap_host'];
$this->ldap_config['ldap_contact_context'] = $this->ldap_config['ldap_context'];
$this->allContactsDN = $this->ldap_config['ldap_context'];
$this->ds = $GLOBALS['egw']->ldap->ldapConnect();
}
else
@ -304,6 +354,37 @@ class addressbook_ldap
return array_values(array_unique($fields));
}
/**
* Return LDAP filter for contact id
*
* @param string $id
* @return string
*/
protected function id_filter($id)
{
return '(|(entryUUID='.ldap::quote($id).')(uid='.ldap::quote($id).'))';
}
/**
* Return LDAP filter for (multiple) contact ids
*
* @param array|string $ids
* @return string
*/
protected function ids_filter($ids)
{
if (!is_array($ids) || count($ids) == 1)
{
return $this->id_filter(is_array($ids) ? array_shift($ids) : $ids);
}
$filter = array();
foreach($ids as $id)
{
$filter[] = $this->id_filter($id);
}
return '(|'.implode('', $filter).')';
}
/**
* reads contact data
*
@ -319,16 +400,30 @@ class addressbook_ldap
}
else
{
$contact_id = ldap::quote(!is_array($contact_id) ? $contact_id :
(isset ($contact_id['id']) ? $contact_id['id'] : $contact_id['uid']));
$filter = "(|(entryUUID=$contact_id)(uid=$contact_id))";
if (is_array($contact_id)) $contact_id = isset ($contact_id['id']) ? $contact_id['id'] : $contact_id['uid'];
$filter = $this->id_filter($contact_id);
}
$rows = $this->_searchLDAP($this->ldap_config['ldap_contact_context'],
$rows = $this->_searchLDAP($this->allContactsDN,
$filter, $this->all_attributes, ADDRESSBOOK_ALL);
return $rows ? $rows[0] : false;
}
/**
* Remove attributes we are not allowed to update
*
* @param array $attributes
*/
function sanitize_update(array &$ldapContact)
{
// never allow to change the uidNumber (account_id) on update, as it could be misused by eg. xmlrpc or syncml
unset($ldapContact['uidnumber']);
unset($ldapContact['entryuuid']); // not allowed to modify that, no need either
unset($ldapContact['objectClass']);
}
/**
* saves the content of data to the db
*
@ -364,10 +459,10 @@ class addressbook_ldap
$data['account_id'] == $GLOBALS['egw_info']['user']['account_id']))
{
// account
$baseDN = $this->ldap_config['ldap_context'];
$baseDN = $this->accountContactsDN;
$cn = false;
// we need an admin connection
$this->ds = $GLOBALS['egw']->ldap->ldapConnect();
$this->connect(true);
// for sql-ldap we need to account_lid/uid as id, NOT the contact_id in id!
if ($GLOBALS['egw_info']['server']['contact_repository'] == 'sql-ldap')
@ -380,7 +475,6 @@ class addressbook_ldap
error_log("Permission denied, to write: data[owner]=$data[owner], data[account_id]=$data[account_id], account_id=".$GLOBALS['egw_info']['user']['account_id']);
return lang('Permission denied !!!'); // only admin or the user itself is allowd to write accounts!
}
// check if $baseDN exists. If not create it
if (($err = $this->_check_create_dn($baseDN)))
{
@ -388,11 +482,11 @@ class addressbook_ldap
}
// check the existing objectclasses of an entry, none = array() for new ones
$oldObjectclasses = array();
$attributes = array('dn','cn','objectClass','uid','mail');
$attributes = array('dn','cn','objectClass',$this->dn_attribute,'mail');
$contactUID = $this->data[$this->contacts_id];
if(!empty($contactUID) &&
($result = ldap_search($this->ds, $this->ldap_config['ldap_contact_context'],
'(|(entryUUID='.ldap::quote($contactUID).')(uid='.ldap::quote($contactUID).'))', $attributes)) &&
if (!empty($contactUID) &&
($result = ldap_search($this->ds, $base=$this->allContactsDN, $filter=$this->id_filter($contactUID), $attributes)) &&
($oldContactInfo = ldap_get_entries($this->ds, $result)) && $oldContactInfo['count'])
{
unset($oldContactInfo[0]['objectclass']['count']);
@ -402,13 +496,12 @@ class addressbook_ldap
}
$isUpdate = true;
}
if(!$contactUID)
if(empty($contactUID))
{
$this->data[$this->contacts_id] = $contactUID = md5($GLOBALS['egw']->common->randomstring(15));
$ldapContact[$this->contacts_id] = $this->data[$this->contacts_id] = $contactUID = md5($GLOBALS['egw']->common->randomstring(15));
}
$ldapContact['uid'] = $contactUID;
//error_log(__METHOD__."() contactUID='$contactUID', isUpdate=".array2string($isUpdate).", oldContactInfo=".array2string($oldContactInfo));
// add for all supported objectclasses the objectclass and it's attributes
foreach($this->schema2egw as $objectclass => $mapping)
{
@ -448,7 +541,7 @@ class addressbook_ldap
$this->$egw2objectclass($ldapContact,$data,$isUpdate);
}
}
if($isUpdate)
if ($isUpdate)
{
// make sure multiple email-addresses in the mail attribute "survive"
if (isset($ldapContact['mail']) && $oldContactInfo[0]['mail']['count'] > 1)
@ -461,9 +554,6 @@ class addressbook_ldap
// update entry
$dn = $oldContactInfo[0]['dn'];
$needRecreation = false;
// never allow to change the uidNumber (account_id) on update, as it could be misused by eg. xmlrpc or syncml
unset($ldapContact['uidnumber']);
unset($ldapContact['entryuuid']); // not allowed to modify that, no need either
// add missing objectclasses
if($ldapContact['objectClass'] && array_diff($ldapContact['objectClass'],$oldObjectclasses))
@ -486,9 +576,9 @@ class addressbook_ldap
}
// check if we need to rename the DN or need to recreate the contact
$newRDN = 'uid='. ldap::quote($contactUID);
$newRDN = $this->dn_attribute.'='. ldap::quote($ldapContact[$this->dn_attribute]);
$newDN = $newRDN .','. $baseDN;
if(strtolower($dn) != strtolower($newDN) || $needRecreation)
if ($needRecreation)
{
$result = ldap_read($this->ds, $dn, 'objectclass=*');
$oldContact = ldap_get_entries($this->ds, $result);
@ -500,7 +590,7 @@ class addressbook_ldap
$newContact[$key] = $value;
}
}
$newContact['uid'] = $contactUID;
$newContact[$this->dn_attribute] = $ldapContact[$this->dn_attribute];
if(is_array($ldapContact['objectClass']) && count($ldapContact['objectClass']) > 0)
{
@ -523,7 +613,21 @@ class addressbook_ldap
}
$dn = $newDN;
}
unset($ldapContact['objectClass']);
// try renaming entry if content of dn-attribute changed
if (strtolower($dn) != strtolower($newDN) || $ldapContact[$this->dn_attribute] != $oldContactInfo[$this->dn_attribute])
{
if (@ldap_rename($this->ds, $dn, $newRDN, null, true))
{
$dn = $newDN;
}
else
{
error_log(__METHOD__."() ldap_rename or $dn to $newRDN failed! ".ldap_error($this->ds));
}
}
unset($ldapContact[$this->dn_attribute]);
$this->sanitize_update($ldapContact);
if (!@ldap_modify($this->ds, $dn, $ldapContact))
{
@ -535,7 +639,7 @@ class addressbook_ldap
}
else
{
$dn = 'uid='. ldap::quote($ldapContact['uid']) .','. $baseDN;
$dn = $this->dn_attribute.'='. ldap::quote($ldapContact[$this->dn_attribute]) .','. $baseDN;
unset($ldapContact['entryuuid']); // trying to write it, gives an error
if (!@ldap_add($this->ds, $dn, $ldapContact))
@ -572,7 +676,7 @@ class addressbook_ldap
foreach($keys as $entry)
{
$entry = ldap::quote(is_array($entry) ? $entry['id'] : $entry);
if($result = ldap_search($this->ds, $this->ldap_config['ldap_contact_context'],
if($result = ldap_search($this->ds, $this->allContactsDN,
"(|(entryUUID=$entry)(uid=$entry))", $attributes))
{
$contactInfo = ldap_get_entries($this->ds, $result);
@ -606,7 +710,6 @@ class addressbook_ldap
*/
function &search($criteria,$only_keys=True,$order_by='',$extra_cols='',$wildcard='',$empty=False,$op='AND',$start=false,$filter=null,$join='',$need_full_no_count=false)
{
//_debug_array($criteria); print "OrderBY: $order_by";_debug_array($extra_cols);_debug_array($filter);
#$order_by = explode(',',$order_by);
#$order_by = explode(' ',$order_by);
#$sort = $order_by[0];
@ -635,20 +738,19 @@ class addressbook_ldap
}
elseif (!isset($filter['owner']))
{
$searchDN = $this->ldap_config['ldap_contact_context'];
$searchDN = $this->allContactsDN;
$addressbookType = ADDRESSBOOK_ALL;
}
else
{
$searchDN = $this->ldap_config['ldap_context'];
$searchDN = $this->accountContactsDN;
$addressbookType = ADDRESSBOOK_ACCOUNTS;
}
// create the search filter
switch($addressbookType)
{
case ADDRESSBOOK_ACCOUNTS:
$objectFilter = '(objectclass=posixaccount)';
$objectFilter = $this->accountsFilter;
break;
default:
$objectFilter = '(objectclass=inetorgperson)';
@ -666,6 +768,11 @@ class addressbook_ldap
$searchFilter = '';
foreach($criteria as $egwSearchKey => $searchValue)
{
if (in_array($egwSearchKey, array('id','contact_id')))
{
$searchFilter .= $this->ids_filter($searchValue);
continue;
}
foreach($this->schema2egw as $mapping)
{
if(($ldapSearchKey = $mapping[$egwSearchKey]))
@ -687,7 +794,6 @@ class addressbook_ldap
}
$colFilter = $this->_colFilter($filter);
$ldapFilter = "(&$objectFilter$searchFilter$colFilter)";
if (!($rows = $this->_searchLDAP($searchDN, $ldapFilter, $this->all_attributes, $addressbookType)))
{
return $rows;
@ -788,6 +894,11 @@ class addressbook_ldap
}
break;
case 'id':
case 'contact_id':
$filter .= $this->ids_filter($value);
break;
default:
if (!is_int($key))
{
@ -840,16 +951,14 @@ class addressbook_ldap
$this->total = 0;
$_attributes[] = 'entryUUID';
$_attributes[] = 'uid';
$_attributes[] = 'uidNumber';
$_attributes[] = 'objectClass';
$_attributes[] = 'createTimestamp';
$_attributes[] = 'modifyTimestamp';
$_attributes[] = 'creatorsName';
$_attributes[] = 'modifiersName';
$_attributes[] = 'shadowExpire';
//echo "<p>ldap_search($this->ds, $_ldapContext, $_filter, $_attributes, 0, $this->ldapLimit)</p>\n";
//echo "<p>ldap_search($this->ds, '$_ldapContext', '$_filter', ".array2string($_attributes).", 0, $this->ldapLimit)</p>\n";
if($_addressbooktype == ADDRESSBOOK_ALL)
{
$result = ldap_search($this->ds, $_ldapContext, $_filter, $_attributes, 0, $this->ldapLimit);
@ -858,22 +967,13 @@ class addressbook_ldap
{
$result = @ldap_list($this->ds, $_ldapContext, $_filter, $_attributes, 0, $this->ldapLimit);
}
if(!$result) return array();
$entries = ldap_get_entries($this->ds, $result);
if(!$result || !$entries = ldap_get_entries($this->ds, $result)) return array();
$this->total = $entries['count'];
$shadowExpireNow = floor((time()-date('Z'))/86400);
foreach((array)$entries as $i => $entry)
foreach($entries as $i => $entry)
{
if (!is_int($i)) continue; // eg. count
// exclude expired or deactivated accounts
if (isset($entry['shadowexpire']) && $entry['shadowexpire'][0] <= $shadowExpireNow)
{
--$this->total;
continue;
}
$contact = array(
'id' => $entry['uid'][0] ? $entry['uid'][0] : $entry['entryuuid'][0],
'tid' => 'n', // the type id for the addressbook
@ -887,7 +987,7 @@ class addressbook_ldap
}
foreach($this->schema2egw[$objectclass] as $egwFieldName => $ldapFieldName)
{
if(!empty($entry[$ldapFieldName][0]) && !isset($contact[$egwFieldName]))
if(!empty($entry[$ldapFieldName][0]) && !is_int($egwFieldName) && !isset($contact[$egwFieldName]))
{
$contact[$egwFieldName] = translation::convert($entry[$ldapFieldName][0],'utf-8');
}
@ -895,7 +995,11 @@ class addressbook_ldap
$objectclass2egw = '_'.$objectclass.'2egw';
if (method_exists($this,$objectclass2egw))
{
$this->$objectclass2egw($contact,$entry);
if (($ret=$this->$objectclass2egw($contact,$entry)) === false)
{
--$this->total;
continue 2;
}
}
}
// read binary jpegphoto only for one result == call by read
@ -966,7 +1070,7 @@ class addressbook_ldap
/**
* check if $baseDN exists. If not create it
*
* @param string $baseDN cn=xxx,ou=yyy,ou=contacts,$this->ldap_config['ldap_contact_context']
* @param string $baseDN cn=xxx,ou=yyy,ou=contacts,$this->allContactsDN
* @return boolean/string false on success or string with error-message
*/
function _check_create_dn($baseDN)
@ -976,8 +1080,10 @@ class addressbook_ldap
{
return false;
}
//error_log(__METHOD__."('$baseDN') !ldap_read({$this->ds}, '$baseDN', 'objectclass=*') ldap_errno()=".ldap_errno($this->ds).', ldap_error()='.ldap_error($this->ds).get_class($this));
if(ldap_errno($this->ds) != 32 || substr($baseDN,0,3) != 'cn=')
{
error_log(__METHOD__."('$baseDN') baseDN does NOT exist and we cant/wont create it! ldap_errno()=".ldap_errno($this->ds).', ldap_error()='.ldap_error($this->ds));
return $this->_error(__LINE__); // baseDN does NOT exist and we cant/wont create it
}
// create a admin connection to add the needed DN
@ -986,8 +1092,8 @@ class addressbook_ldap
list(,$ou) = explode(',',$baseDN);
foreach(array(
'ou=contacts,'.$this->ldap_config['ldap_contact_context'],
$ou.',ou=contacts,'.$this->ldap_config['ldap_contact_context'],
'ou=contacts,'.$this->allContactsDN,
$ou.',ou=contacts,'.$this->allContactsDN,
$baseDN,
) as $dn)
{
@ -1129,6 +1235,27 @@ class addressbook_ldap
}
}
/**
* Special handling for mapping data of posixAccount objectclass to eGW contact
*
* Please note: all regular fields are already copied!
*
* @internal
* @param array &$contact already copied fields according to the mapping
* @param array $data eGW contact data
*/
function _posixaccount2egw(&$contact,$data)
{
static $shadowExpireNow;
if (!isset($shadowExpireNow)) $shadowExpireNow = floor((time()-date('Z'))/86400);
// exclude expired or deactivated accounts
if (isset($data['shadowexpire']) && $data['shadowexpire'][0] <= $shadowExpireNow)
{
return false;
}
}
/**
* Special handling for mapping data of the mozillaAbPersonAlpha objectclass to eGW contact
*

View File

@ -114,16 +114,6 @@ class addressbook_so
*/
var $memberships;
/**
* LDAP searches only a limited set of attributes for performance reasons,
* you NEED an index for that columns, ToDo: make it configurable
* minimum: $this->columns_to_search = array('n_family','n_given','org_name','email');
*/
var $ldap_search_attributes = array(
'n_family','n_middle','n_given','org_name','org_unit',
'adr_one_location','adr_two_location','note',
'email','mozillasecondemail','uidnumber',
);
/**
* In SQL we can search all columns, though a view make on real sense
*/
@ -232,8 +222,7 @@ class addressbook_so
{
$this->contact_repository = 'ldap';
$this->somain = new addressbook_ldap();
$this->columns_to_search = $this->ldap_search_attributes;
$this->columns_to_search = $this->somain->search_attributes;
}
else // sql or sql->ldap
{
@ -250,12 +239,13 @@ class addressbook_so
{
$this->grants = $this->get_grants($this->user,$contact_app);
}
if ($this->account_repository == 'ldap' && $this->contact_repository == 'sql')
if ($this->account_repository != 'sql' && $this->contact_repository == 'sql')
{
if ($this->account_repository != $this->contact_repository)
{
$this->so_accounts = new addressbook_ldap();
$this->account_cols_to_search = $this->ldap_search_attributes;
$class = 'addressbook_'.$this->account_repository;
$this->so_accounts = new $class();
$this->account_cols_to_search = $this->so_accounts->search_attributes;
}
else
{

View File

@ -0,0 +1,271 @@
#
# qmail-ldap (20030901) ldapv3 directory schema
#
# The offical qmail-ldap OID assigned by IANA is 7914
#
# Created by: David E. Storey <dave@tamos.net>
# Modified and included into qmail-ldap by Andre Oppermann <opi@nrg4u.com>
# Schema fixes by Mike Jackson <mjj@pp.fi>
# Schema fixes by Christian Zoffoli (XMerlin) <czoffoli@xmerlin.org>
#
#
# This schema depends on:
# - core.schema
# - cosine.schema
# - nis.schema
#
# Attribute Type Definitions
attributetype ( 1.3.6.1.4.1.7914.1.2.1.1 NAME 'qmailUID'
DESC 'UID of the user on the mailsystem'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.2.1.2 NAME 'qmailGID'
DESC 'GID of the user on the mailsystem'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.2.1.3 NAME 'mailMessageStore'
DESC 'Path to the maildir/mbox on the mail system'
EQUALITY caseExactIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.2.1.4 NAME 'mailAlternateAddress'
DESC 'Secondary (alias) mailaddresses for the same user'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
#
# mailQuota format is no longer supported from qmail-ldap 20030901 on,
# user mailQuotaSize and mailQuotaCount instead.
#
#attributetype ( 1.3.6.1.4.1.7914.1.2.1.5 NAME 'mailQuota'
# DESC 'The amount of space the user can use until all further messages get bounced.'
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 SINGLE-VALUE )
#
attributetype ( 1.3.6.1.4.1.7914.1.2.1.6 NAME 'mailHost'
DESC 'On which qmail server the messagestore of this user is located.'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE)
attributetype ( 1.3.6.1.4.1.7914.1.2.1.7 NAME 'mailForwardingAddress'
DESC 'Address(es) to forward all incoming messages to.'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
attributetype ( 1.3.6.1.4.1.7914.1.2.1.8 NAME 'deliveryProgramPath'
DESC 'Program to execute for all incoming mails.'
EQUALITY caseExactIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
attributetype ( 1.3.6.1.4.1.7914.1.2.1.9 NAME 'qmailDotMode'
DESC 'Interpretation of .qmail files: both, dotonly, ldaponly, ldapwithprog'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.2.1.10 NAME 'deliveryMode'
DESC 'multi field entries of: nolocal, noforward, noprogram, reply'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} )
attributetype ( 1.3.6.1.4.1.7914.1.2.1.11 NAME 'mailReplyText'
DESC 'A reply text for every incoming message'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{4096} SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.2.1.12 NAME 'accountStatus'
DESC 'The status of a user account: active, noaccess, disabled, deleted'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.2.1.14 NAME 'qmailAccountPurge'
DESC 'The earliest date when a mailMessageStore will be purged'
EQUALITY numericStringMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.2.1.15 NAME 'mailQuotaSize'
DESC 'The size of space the user can have until further messages get bounced.'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.2.1.16 NAME 'mailQuotaCount'
DESC 'The number of messages the user can have until further messages get bounced.'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.2.1.17 NAME 'mailSizeMax'
DESC 'The maximum size of a single messages the user accepts.'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
#
# qmailGroup attributes
#
attributetype ( 1.3.6.1.4.1.7914.1.3.1.1 NAME 'dnmember'
DESC 'Group member specified as distinguished name.'
EQUALITY distinguishedNameMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
attributetype ( 1.3.6.1.4.1.7914.1.3.1.2 NAME 'rfc822member'
DESC 'Group member specified as normal rf822 email address.'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
attributetype ( 1.3.6.1.4.1.7914.1.3.1.3 NAME 'filtermember'
DESC 'Group member specified as ldap search filter.'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{512} )
attributetype ( 1.3.6.1.4.1.7914.1.3.1.4 NAME 'senderconfirm'
DESC 'Sender to Group has to answer confirmation email.'
EQUALITY booleanMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.3.1.5 NAME 'membersonly'
DESC 'Sender to Group must be group member itself.'
EQUALITY booleanMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.3.1.6 NAME 'confirmtext'
DESC 'Text that will be sent with sender confirmation email.'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{4096} SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.3.1.7 NAME 'dnmoderator'
DESC 'Group moderator specified as Distinguished name.'
EQUALITY distinguishedNameMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
attributetype ( 1.3.6.1.4.1.7914.1.3.1.8 NAME 'rfc822moderator'
DESC 'Group moderator specified as normal rfc822 email address.'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
attributetype ( 1.3.6.1.4.1.7914.1.3.1.9 NAME 'moderatortext'
DESC 'Text that will be sent with request for moderation email.'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{4096} SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.3.1.10 NAME 'dnsender'
DESC 'Allowed sender specified as distinguished name.'
EQUALITY distinguishedNameMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
attributetype ( 1.3.6.1.4.1.7914.1.3.1.11 NAME 'rfc822sender'
DESC 'Allowed sender specified as normal rf822 email address.'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
attributetype ( 1.3.6.1.4.1.7914.1.3.1.12 NAME 'filtersender'
DESC 'Allowed sender specified as ldap search filter.'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{512} )
#
# qldapAdmin Attributes
#
attributetype ( 1.3.6.1.4.1.7914.1.4.1.1 NAME 'qladnmanager'
DESC ''
EQUALITY distinguishedNameMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
attributetype ( 1.3.6.1.4.1.7914.1.4.1.2 NAME 'qlaDomainList'
DESC ''
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
attributetype ( 1.3.6.1.4.1.7914.1.4.1.3 NAME 'qlaUidPrefix'
DESC ''
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.4.1.4 NAME 'qlaQmailUid'
DESC ''
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.4.1.5 NAME 'qlaQmailGid'
DESC ''
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.4.1.6 NAME 'qlaMailMStorePrefix'
DESC ''
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.4.1.7 NAME 'qlaMailQuotaSize'
DESC ''
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.4.1.8 NAME 'qlaMailQuotaCount'
DESC ''
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.4.1.9 NAME 'qlaMailSizeMax'
DESC ''
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7914.1.4.1.10 NAME 'qlaMailHostList'
DESC ''
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
# Object Class Definitions
objectclass ( 1.3.6.1.4.1.7914.1.2.2.1 NAME 'qmailUser'
DESC 'QMail-LDAP User'
SUP top
AUXILIARY
MUST ( mail )
MAY ( uid $ mailMessageStore $ homeDirectory $ userPassword $
mailAlternateAddress $ qmailUID $ qmailGID $
mailHost $ mailForwardingAddress $ deliveryProgramPath $
qmailDotMode $ deliveryMode $ mailReplyText $
accountStatus $ qmailAccountPurge $
mailQuotaSize $ mailQuotaCount $ mailSizeMax ) )
objectclass ( 1.3.6.1.4.1.7914.1.3.2.1 NAME 'qmailGroup'
DESC 'QMail-LDAP Group'
SUP top
AUXILIARY
MUST ( mail $ mailAlternateAddress $ mailMessageStore )
MAY ( dnmember $ rfc822member $ filtermember $ senderconfirm $
membersonly $ confirmtext $ dnmoderator $ rfc822moderator $
moderatortext $ dnsender $ rfc822sender $ filtersender) )
objectclass ( 1.3.6.1.4.1.7914.1.4.2.1 NAME 'qldapAdmin'
DESC 'QMail-LDAP Subtree Admin'
SUP top
AUXILIARY
MUST ( qlaDnManager $ qlaDomainList $ qlaMailMStorePrefix $
qlaMailHostList )
MAY ( qlaUidPrefix $ qlaQmailUid $ qlaQmailGid $ qlaMailQuotaSize $
qlaMailQuotaCount $ qlaMailSizeMax ) )

View File

@ -18,6 +18,11 @@ include_once(EGW_SERVER_ROOT."/emailadmin/inc/class.defaultimap.inc.php");
*/
class cyrusimap extends defaultimap
{
/**
* Label shown in EMailAdmin
*/
const DESCRIPTION = 'Cyrus';
/**
* Capabilities of this class (pipe-separated): default, sieve, admin, logintypeemail
*/

View File

@ -20,6 +20,11 @@ include_once(EGW_SERVER_ROOT."/emailadmin/inc/class.defaultimap.inc.php");
*/
class dbmaildbmailuser extends defaultimap
{
/**
* Label shown in EMailAdmin
*/
const DESCRIPTION = 'dbmail (dbmailUser Schema)';
/**
* Capabilities of this class (pipe-separated): default, sieve, admin, logintypeemail
*/

View File

@ -20,6 +20,11 @@ include_once(EGW_SERVER_ROOT."/emailadmin/inc/class.defaultimap.inc.php");
*/
class dbmailqmailuser extends defaultimap
{
/**
* Label shown in EMailAdmin
*/
const DESCRIPTION = 'dbmail (qmailUser Schema)';
/**
* Capabilities of this class (pipe-separated): default, sieve, admin, logintypeemail
*/

View File

@ -27,6 +27,11 @@ define('IMAP_NAMESPACE_ALL' , 'all');
*/
class defaultimap extends Net_IMAP
{
/**
* Label shown in EMailAdmin
*/
const DESCRIPTION = 'standard IMAP server';
/**
* Capabilities of this class (pipe-separated): default, sieve, admin, logintypeemail
*/
@ -183,6 +188,16 @@ class defaultimap extends Net_IMAP
$this->Net_IMAPProtocol();
}
/**
* Return description for EMailAdmin
*
* @return string
*/
public static function description()
{
return static::DESCRIPTION;
}
/**
* Magic method to re-connect with the imapserver, if the object get's restored from the session
*/

View File

@ -412,7 +412,7 @@ class emailadmin_bo extends so_sql
static public function getSMTPServerTypes($extended=true)
{
$retData = array();
foreach(self::$SMTPServerType as $key => $value)
/* foreach(self::$SMTPServerType as $key => $value)
{
if ($extended)
{
@ -420,14 +420,22 @@ class emailadmin_bo extends so_sql
$retData[$key]['description'] = isset($value['description'])?$value['description']:$key;
$retData[$key]['classname'] = isset($value['classname'])?$value['classname']:$key;
}
}
}*/
foreach($GLOBALS['egw']->hooks->process(array(
'location' => 'smtp_server_types',
'extended' => $extended,
),array(),true) as $app => $data)
), array('managementserver', 'emailadmin'), true) as $app => $data)
{
if ($data) $retData += $data;
}
uksort($retData, function($a, $b) {
static $prio = array( // not explicitly mentioned get 0
'emailadmin_smtp' => 9,
'emailadmin_smtp_sql' => 8,
'smtpplesk' => -1,
);
return (int)$prio[$b] - (int)$prio[$a];
});
return $retData;
}
@ -442,7 +450,7 @@ class emailadmin_bo extends so_sql
static public function getIMAPServerTypes($extended=true)
{
$retData = array();
foreach(self::$IMAPServerType as $key => $value)
/* foreach(self::$IMAPServerType as $key => $value)
{
if ($extended)
{
@ -455,14 +463,24 @@ class emailadmin_bo extends so_sql
{
$retData[$key] = $value['description'];
}
}
}*/
foreach($GLOBALS['egw']->hooks->process(array(
'location' => 'imap_server_types',
'extended' => $extended,
),array(),true) as $app => $data)
), array('managementserver', 'emailadmin'), true) as $app => $data)
{
if ($data) $retData += $data;
}
uksort($retData, function($a, $b) {
static $prio = array( // not explicitly mentioned get 0
'defaultimap' => 9,
'managementserver_imap' => 8,
'emailadmin_dovecot' => 7,
'cyrusimap' => 6,
'pleskimap' => -1,
);
return (int)$prio[$b] - (int)$prio[$a];
});
return $retData;
}

View File

@ -22,6 +22,10 @@ include_once(EGW_SERVER_ROOT."/emailadmin/inc/class.defaultimap.inc.php");
*/
class emailadmin_dovecot extends defaultimap
{
/**
* Label shown in EMailAdmin
*/
const DESCRIPTION = 'Dovecot';
/**
* Capabilities of this class (pipe-separated): default, sieve, admin, logintypeemail
*/

View File

@ -119,7 +119,7 @@ class emailadmin_hooks
}
/**
* Add further imap and smtp server plugins to emailadmin
* Detect imap and smtp server plugins from EMailAdmin's inc directory
*
* @param string|array $data location string or array with key 'location' and other params
* @return array
@ -129,74 +129,37 @@ class emailadmin_hooks
$location = is_array($data) ? $data['location'] : $data;
$extended = is_array($data) ? $data['extended'] : false;
switch($location)
$types = array();
foreach(scandir($dir=EGW_INCLUDE_ROOT.'/emailadmin/inc') as $file)
{
case 'imap_server_types':
return array(
'defaultimap' => $extended ? array(
'description' => 'standard IMAP server',
'protocol' => 'imap',
'classname' => 'defaultimap'
) : 'standard IMAP server',
'emailadmin_dovecot' => $extended ? array(
'description' => 'Dovecot',
'classname' => 'emailadmin_dovecot',
'protocol' => 'imap',
) : 'Dovecot',
'cyrusimap' => $extended ? array(
'description' => 'Cyrus IMAP Server',
'protocol' => 'imap',
'classname' => 'cyrusimap'
) : 'Cyrus IMAP Server',
'dbmailqmailuser' => $extended ? array(
'description' => 'DBMail (qmailUser schema)',
'protocol' => 'imap',
'classname' => 'dbmailqmailuser'
) : 'DBMail (qmailUser schema)',
'pleskimap' => $extended ? array(
'description' => 'Plesk IMAP Server (Courier)',
'protocol' => 'imap',
'classname' => 'pleskimap'
) : 'Plesk IMAP Server (Courier)',
'dbmaildbmailuser' => $extended ? array(
'description' => 'DBMail (dbmailUser schema)',
'protocol' => 'imap',
'classname' => 'dbmaildbmailuser'
) : 'DBMail (dbmailUser schema)',
if (!preg_match('/^class\.([^.]*(smtp|imap|postfix|dovecot|dbmail)[^.*]*)\.inc\.php$/', $file, $matches)) continue;
$class_name = $matches[1];
include_once($dir.'/'.$file);
if (!class_exists($class_name)) continue;
$is_imap = $class_name == 'defaultimap' || is_subclass_of($class_name, 'defaultimap');
$is_smtp = $class_name == 'emailadmin_smtp' || is_subclass_of($class_name, 'emailadmin_smtp') && $class_name != 'defaultsmtp';
if ($is_smtp && $location == 'smtp_server_types' || $is_imap && $location == 'imap_server_types')
{
$type = array(
'classname' => $class_name,
'description' => is_callable($function=$class_name.'::description') ? call_user_func($function) : $class_name,
);
case 'smtp_server_types': // nothing yet
return array(
'emailadmin_smtp' => $extended ? array(
'description' => 'standard SMTP-Server',
'classname' => 'emailadmin_smtp'
) : 'standard SMTP-Server',
'emailadmin_smtp_sql' => $extended ? array(
'description' => 'Postfix (SQL)',
'classname' => 'emailadmin_smtp_sql',
) : 'Postfix (SQL)',
'postfixldap' => $extended ? array(
'description' => 'Postfix (qmail Schema)',
'classname' => 'postfixldap'
) : 'Postfix (qmail Schema)',
'emailadmin_smtp_qmail' => $extended ? array(
'description' => 'Postfix (new qmail Schema)',
'classname' => 'emailadmin_smtp_qmail'
) : 'Postfix (new qmail Schema)',
'postfixinetorgperson' => $extended ? array(
'description' => 'Postfix (inetOrgPerson Schema)',
'classname' => 'postfixinetorgperson'
) : 'Postfix (inetOrgPerson Schema)',
'smtpplesk' => $extended ? array(
'description' => 'Plesk SMTP-Server (Qmail)',
'classname' => 'smtpplesk'
) : 'Plesk SMTP-Server (Qmail)',
'postfixdbmailuser' => $extended ? array(
'description' => 'Postfix (dbmail Schema)',
'classname' => 'postfixdbmailuser'
) : 'Postfix (dbmail Schema)',
);
break;
if ($is_imap) $type['protocol'] = 'imap';
$types[$class_name] = $type;
}
}
if (!$extended)
{
foreach($types as $class_name => &$type)
{
$type = $type['description'];
}
}
//error_log(__METHOD__."(".array2string($data).") returning ".array2string($types));
return $types;
}
}

View File

@ -15,6 +15,11 @@
*/
class emailadmin_smtp
{
/**
* Label shown in EMailAdmin
*/
const DESCRIPTION = 'standard SMTP-Server';
/**
* Capabilities of this class (pipe-separated): default, forward
*/
@ -74,6 +79,16 @@ class emailadmin_smtp
$this->accounts = $GLOBALS['egw']->accounts;
}
/**
* Return description for EMailAdmin
*
* @return string
*/
public static function description()
{
return static::DESCRIPTION;
}
/**
* Hook called on account creation
*

View File

@ -0,0 +1,166 @@
<?php
/**
* EGroupware EMailAdmin: Postfix using Active Directorys Exchange attributes
*
* @link http://www.egroupware.org
* @package emailadmin
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @copyright (c) 2013 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
/**
* Postfix using Active Directorys proxyAddresses attribute
* (available without installing Exchange schemas).
*
* This plugin is NOT meant to administrate an Exchange Server using AD!
*
* Aliases, forwards, forward only and quota is stored in
* multivalued attribute proxyAddresses with different prefixes.
*
* Primary mail address is additionally stored in proxyAddresses.
* Disabling mail removes proxyAddresses completly.
*
* @link http://msdn.microsoft.com/en-us/library/ms679424(v=vs.85).aspx
* @link http://www.dovecot.org/list/dovecot/2010-February/046763.html
*/
class emailadmin_smtp_ads extends emailadmin_smtp_ldap
{
/**
* Label shown in EMailAdmin
*/
const DESCRIPTION = 'Active Directory';
/**
* Capabilities of this class (pipe-separated): default, forward
*/
const CAPABILITIES = 'default|forward';
/**
* Name of schema, has to be in the right case!
*/
const SCHEMA = 'top';
/**
* Filter for users
*
* objectCategory is indexed, while objectclass is not!
*/
const USER_FILTER = '(objectCategory=person)';
/**
* Name of schema for groups, has to be in the right case!
*/
const GROUP_SCHEMA = 'group';
/**
* Attribute to enable mail for an account, OR false if existence of ALIAS_ATTR is enough for mail delivery
*/
const MAIL_ENABLE_ATTR = false;
/**
* Attribute for aliases OR false to use mail
*/
const ALIAS_ATTR = 'proxyaddresses';
/**
* Caseinsensitive prefix for aliases (eg. "smtp:"), aliases get added with it and only aliases with it are reported
*/
const ALIAS_PREFIX = 'smtp:';
/**
* Primary mail address required as an alias too: true or false
*/
const REQUIRE_MAIL_AS_ALIAS = true;
/**
* Attribute for forwards OR false if not possible
*/
const FORWARD_ATTR = 'proxyaddresses';
/**
* Caseinsensitive prefix for forwards (eg. "forward:"), forwards get added with it and only forwards with it are reported
*/
const FORWARD_PREFIX = 'forward:';
/**
* Attribute to only forward mail, OR false if not available
*/
const FORWARD_ONLY_ATTR = 'proxyaddresses';
/**
* Value of forward-only attribute, if not set any value will switch forward only on (checked with =*)
*/
const FORWARD_ONLY_VALUE = 'forwardOnly';
/**
* Attribute for mailbox, to which mail gets delivered OR false if not supported
*/
const MAILBOX_ATTR = false;
/**
* Attribute for quota limit of user in MB
*/
const QUOTA_ATTR = 'proxyaddresses';
/**
* Caseinsensitive prefix for quota (eg. "quota:"), quota get added with it and only quota with it are reported
*/
const QUOTA_PREFIX = 'quota:';
/**
* Internal quota in MB is multiplicated with this factor before stored in LDAP
*/
const QUOTA_FACTOR = 1048576;
/**
* Attribute for user name
*/
const USER_ATTR = 'samaccountname';
/**
* Attribute for numeric user id (optional)
*
* No single uidNumber attribute, as we use RID (last part of objectSid attribute) for it.
*/
const USERID_ATTR = false;
/**
* Return LDAP connection
*/
protected function getLdapConnection()
{
static $ldap;
if (is_null($ldap))
{
if (!is_a($GLOBALS['egw']->accounts->backend, 'accounts_ads'))
{
throw new egw_exception_wrong_userinput('Postfix with Active Directory requires accounts stored in ADS!');
}
$ldap = $GLOBALS['egw']->accounts->backend->ldap_connection();
}
return $ldap;
}
/**
* Constructor
*
* @param string $defaultDomain=null
*/
function __construct($defaultDomain=null)
{
parent::__construct($defaultDomain);
$this->setBase($GLOBALS['egw']->accounts->backend->ads_context());
}
/**
* Return description for EMailAdmin
*
* @return string
*/
public static function description()
{
return static::DESCRIPTION;
}
}

View File

@ -5,7 +5,7 @@
* @link http://www.stylite.de
* @package emailadmin
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @copyright (c) 2010-12 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @copyright (c) 2010-13 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
@ -18,8 +18,13 @@
* Aliases are stored as aditional mail Attributes. The primary mail address is the first one.
* This schema does NOT support forwarding or disabling of an account for mail.
*
* Please do NOT copy this class! Extend it and set the constants different
* (incl. protected config var as long as we can not require PHP5.3 for LSB).
* Aliases, forwards, forward-only and quota attribute can be stored in same multivalued attribute
* with different prefixes.
*
* Please do NOT copy this class! Extend it and set the constants different.
*
* Please note: schema names muse use correct case (eg. "inetOrgPerson"),
* while attribute name muse use lowercase, as LDAP returns them as keys in lowercase!
*/
class emailadmin_smtp_ldap extends emailadmin_smtp
{
@ -28,6 +33,16 @@ class emailadmin_smtp_ldap extends emailadmin_smtp
*/
const SCHEMA = 'inetOrgPerson';
/**
* Filter for users
*/
const USER_FILTER = '(objectClass=posixAccount)';
/**
* Name of schema for groups, has to be in the right case!
*/
const GROUP_SCHEMA = 'posixGroup';
/**
* Attribute to enable mail for an account, OR false if existence of ALIAS_ATTR is enough for mail delivery
*/
@ -38,21 +53,36 @@ class emailadmin_smtp_ldap extends emailadmin_smtp
*/
const ALIAS_ATTR = false;
/**
* Caseinsensitive prefix for aliases (eg. "smtp:"), aliases get added with it and only aliases with it are reported
*/
const ALIAS_PREFIX = '';
/**
* Primary mail address required as an alias too: true or false
*/
const REQUIRE_MAIL_AS_ALIAS=false;
const REQUIRE_MAIL_AS_ALIAS = false;
/**
* Attribute for forwards OR false if not possible
*/
const FORWARD_ATTR = false;
/**
* Caseinsensitive prefix for forwards (eg. "forward:"), forwards get added with it and only forwards with it are reported
*/
const FORWARD_PREFIX = '';
/**
* Attribute to only forward mail, OR false if not available
*/
const FORWARD_ONLY_ATTR = false;
/**
* Value of forward-only attribute, if empty any value will switch forward only on (checked with =*)
*/
const FORWARD_ONLY = 'forwardOnly';
/**
* Attribute for mailbox, to which mail gets delivered OR false if not supported
*/
@ -63,55 +93,92 @@ class emailadmin_smtp_ldap extends emailadmin_smtp
*/
const QUOTA_ATTR = false;
/**
* Caseinsensitive prefix for quota (eg. "quota:"), quota get added with it and only quota with it are reported
*/
const QUOTA_PREFIX = '';
/**
* Internal quota in MB is multiplicated with this factor before stored in LDAP
*/
const QUOTA_FACTOR = 1048576;
/**
* Attribute for user name
*/
const USER_ATTR = 'uid';
/**
* Attribute for numeric user id (optional)
*/
const USERID_ATTR = 'uidnumber';
/**
* Base for all searches, defaults to $GLOBALS['egw_info']['server']['ldap_context'] and can be set via setBase($base)
*
* @var string
*/
protected $search_base;
/**
* Special search filter for getUserData only
*
* @var string
*/
protected $search_filter;
/**
* Log all LDAP writes / actions to error_log
*/
var $debug = false;
/**
* LDAP schema configuration
*
* Parent can NOT use constants direct as we have no late static binding in currenlty required PHP 5.2
*
* @var array
*/
protected $config = array(
'schema' => self::SCHEMA,
'mail_enable_attr' => self::MAIL_ENABLE_ATTR,
'mail_enabled' => self::MAIL_ENABLED,
'alias_attr' => self::ALIAS_ATTR,
'require_mail_as_alias' => self::REQUIRE_MAIL_AS_ALIAS,
'forward_attr' => self::FORWARD_ATTR,
'forward_only_attr' => self::FORWARD_ONLY_ATTR,
'forward_only' => self::FORWARD_ONLY,
'mailbox_attr' => self::MAILBOX_ATTR,
'quota_attr' => self::QUOTA_ATTR,
'search_filter' => null,
'search_base' => null,
);
/**
* from here on implementation, please do NOT copy but extend it!
*/
/**
* Set ldap search filter for aliases and forwards
* Constructor
*
* @param string $defaultDomain=null
*/
function __construct($defaultDomain=null)
{
parent::__construct($defaultDomain);
if (empty($this->search_base))
{
$this->setBase($GLOBALS['egw_info']['server']['ldap_context']);
}
}
/**
* Return description for EMailAdmin
*
* @return string
*/
public static function description()
{
return 'LDAP ('.static::SCHEMA.')';
}
/**
* Set ldap search filter for aliases and forwards (getUserData)
*
* @param string $filter
*/
function setFilter($filter)
{
$this->config['search_filter'] = $filter;
$this->search_filter = $filter;
}
/**
* Set ldap search base for aliases and forwards
* Set ldap search base, default $GLOBALS['egw_info']['server']['ldap_context']
*
* @param string $base
*/
function setBase($base)
{
$this->config['search_base'] = $base;
$this->search_base = $base;
}
/**
@ -126,11 +193,11 @@ class emailadmin_smtp_ldap extends emailadmin_smtp
common::email_address($_hookValues['account_firstname'],
$_hookValues['account_lastname'],$_hookValues['account_lid'],$this->defaultDomain);
$ds = $GLOBALS['egw']->ldap->ldapConnect();
$ds = $this->getLdapConnection();
$filter = "uid=".$_hookValues['account_lid'];
$filter = static::USER_ATTR."=".ldap::quote($_hookValues['account_lid']);
if (!($sri = @ldap_search($ds,$GLOBALS['egw_info']['server']['ldap_context'],$filter)))
if (!($sri = @ldap_search($ds, $this->search_base, $filter)))
{
return false;
}
@ -140,9 +207,9 @@ class emailadmin_smtp_ldap extends emailadmin_smtp
unset($objectClasses['count']);
// add our mail schema, if not already set
if(!in_array($this->config['schema'],$objectClasses) && !in_array(strtolower($this->config['schema']),$objectClasses))
if(!in_array(static::SCHEMA,$objectClasses) && !in_array(strtolower(static::SCHEMA),$objectClasses))
{
$objectClasses[] = $this->config['schema'];
$objectClasses[] = static::SCHEMA;
}
// the new code for postfix+cyrus+ldap
$newData = array(
@ -150,19 +217,19 @@ class emailadmin_smtp_ldap extends emailadmin_smtp
'objectclass' => $objectClasses
);
// does schema have explicit alias attribute AND require mail added as alias too
if ($this->config['alias_attr'] && $this->config['require_mail_as_alias'] && $this->config['alias_attr'])
if (static::ALIAS_ATTR && static::REQUIRE_MAIL_AS_ALIAS)
{
$newData[$this->config['alias_attr']] = $mailLocalAddress;
$newData[static::ALIAS_ATTR] = static::ALIAS_PREFIX.$mailLocalAddress;
}
// does schema support enabling/disabling mail via attribute
if ($this->config['mail_enable_attr'])
if (static::MAIL_ENABLE_ATTR)
{
$newData[$this->config['mail_enable_attr']] = $this->config['mail_enabled'];
$newData[static::MAIL_ENABLE_ATTR] = static::MAIL_ENABLED;
}
// does schema support an explicit mailbox name --> set it
if ($this->config['mailbox_attr'])
if (static::MAILBOX_ATTR)
{
$newData[$this->config['mailbox_attr']] = self::mailbox_addr($_hookValues);
$newData[static::MAILBOX_ATTR] = self::mailbox_addr($_hookValues);
}
if (!($ret = ldap_mod_replace($ds, $accountDN, $newData)) || $this->debug)
@ -183,10 +250,10 @@ class emailadmin_smtp_ldap extends emailadmin_smtp
function getAccountEmailAddress($_accountName)
{
$emailAddresses = array();
$ds = $GLOBALS['egw']->ldap->ldapConnect();
$filter = sprintf("(&(uid=%s)(objectclass=posixAccount))",$_accountName);
$attributes = array('dn','mail',$this->config['alias_attr']);
$sri = @ldap_search($ds, $GLOBALS['egw_info']['server']['ldap_context'], $filter, $attributes);
$ds = $this->getLdapConnection();
$filter = '(&'.static::USER_FILTER.'('.static::USER_ATTR.'='.ldap::quote($_accountName).'))';
$attributes = array('dn', 'mail', static::ALIAS_ATTR);
$sri = @ldap_search($ds, $this->search_base, $filter, $attributes);
if ($sri)
{
@ -206,12 +273,10 @@ class emailadmin_smtp_ldap extends emailadmin_smtp
);
}
}
if ($this->config['alias_attr'] && isset($allValues[0][$this->config['alias_attr']]))
if (static::ALIAS_ATTR && isset($allValues[0][static::ALIAS_ATTR]))
{
foreach($allValues[0][$this->config['alias_attr']] as $key => $value)
foreach(self::getAttributePrefix($allValues[0][static::ALIAS_ATTR], static::ALIAS_PREFIX) as $value)
{
if ($key === 'count') continue;
$emailAddresses[] = array(
'name' => $realName,
'address' => $value,
@ -239,24 +304,29 @@ class emailadmin_smtp_ldap extends emailadmin_smtp
*/
function getUserData($user, $match_uid_at_domain=false)
{
$userData = array();
$userData = array(
'mailbox' => array(),
'forward' => array(),
$ldap = $GLOBALS['egw']->ldap->ldapConnect();
);
if (is_numeric($user))
$ldap = $this->getLdapConnection();
if (is_numeric($user) && static::USERID_ATTR)
{
$filter = '(uidnumber='.(int)$user.')';
$filter = '('.static::USERID_ATTR.'='.(int)$user.')';
}
elseif (strpos($user, '@') === false)
{
$filter = '(uid='.ldap::quote($user).')';
if (is_numeric($user)) $user = $GLOBALS['egw']->accounts->id2name($user);
$filter = '(&'.static::USER_FILTER.'('.static::USER_ATTR.'='.ldap::quote($user).'))';
}
else // email address --> build filter by attributes defined in config
{
list($namepart, $domain) = explode('@', $user);
if (!empty($this->config['search_filter']))
if (!empty($this->search_filter))
{
$filter = strtr($this->config['search_filter'], array(
$filter = strtr($this->search_filter, array(
'%s' => ldap::quote($user),
'%u' => ldap::quote($namepart),
'%d' => ldap::quote($domain),
@ -265,57 +335,67 @@ class emailadmin_smtp_ldap extends emailadmin_smtp
else
{
$filter = array('(mail='.ldap::quote($user).')');
if ($match_uid_at_domain) $filter[] = '(uid='.ldap::quote($namepart).')';
if ($this->config['alias_attr'])
if ($match_uid_at_domain) $filter[] = '('.static::USER_ATTR.'='.ldap::quote($namepart).')';
if (static::ALIAS_ATTR)
{
$filter[] = '('.$this->config['alias_attr'].'='.ldap::quote($user).')';
$filter[] = '('.static::ALIAS_ATTR.'='.static::ALIAS_PREFIX.ldap::quote($user).')';
}
$filter = count($filter) > 1 ? '(|'.explode('', $filter).')' : $filter[0];
// if an enable attribute is set, only return enabled accounts
if ($this->config['mail_enable_attr'])
if (static::MAIL_ENABLE_ATTR)
{
$filter = '(&('.$this->config['mail_enable_attr'].'='.
($this->config['mail_enabled'] ? $this->config['mail_enabled'] : '*').")$filter)";
$filter = '(&('.static::MAIL_ENABLE_ATTR.'='.
(static::MAIL_ENABLED ? static::MAIL_ENABLED : '*').")$filter)";
}
}
}
$base = empty($this->config['search_base']) ?
$GLOBALS['egw_info']['server']['ldap_context'] : $this->config['search_base'];
$sri = ldap_search($ldap, $base, $filter, array($this->config['schema']));
$attributes = array_values(array_diff(array(
'mail', 'objectclass', static::USER_ATTR, static::MAIL_ENABLE_ATTR, static::ALIAS_ATTR,
static::MAILBOX_ATTR, static::FORWARD_ATTR, static::FORWARD_ONLY_ATTR, static::QUOTA_ATTR,
), array(false, '')));
$sri = ldap_search($ldap, $this->search_base, $filter, $attributes);
if ($sri)
{
$allValues = ldap_get_entries($ldap, $sri);
if ($this->debug) error_log(__METHOD__."('$user') --> ldap_search(, '$base', '$filter') --> ldap_get_entries=".array2string($allValues[0]));
if ($this->debug) error_log(__METHOD__."('$user') --> ldap_search(, '$this->search_base', '$filter') --> ldap_get_entries=".array2string($allValues[0]));
foreach($allValues as $key => $values)
{
if ($key === 'count') continue;
// groups are always active (if they have an email) and allways forwardOnly
if (in_array('posixGroup', $values['objectclass']))
if (in_array(static::GROUP_SCHEMA, $values['objectclass']))
{
$accountStatus = emailadmin_smtp::MAIL_ENABLED;
$deliveryMode = emailadmin_smtp::FORWARD_ONLY;
}
else // for users we have to check the attributes
{
if ($this->config['mail_enable_attr'])
if (static::MAIL_ENABLE_ATTR)
{
$accountStatus = isset($values[$this->config['mail_enable_attr']]) &&
($this->config['mail_enabled'] && !strcasecmp($values[$this->config['mail_enable_attr']][0], $this->config['mail_enabled']) ||
!$this->config['mail_enabled'] && $values[$this->config['alias_attr']]['count'] > 0) ? emailadmin_smtp::MAIL_ENABLED : '';
$accountStatus = isset($values[static::MAIL_ENABLE_ATTR]) &&
(static::MAIL_ENABLED && !strcasecmp($values[static::MAIL_ENABLE_ATTR][0], static::MAIL_ENABLED) ||
!static::MAIL_ENABLED && $values[static::ALIAS_ATTR]['count'] > 0) ? emailadmin_smtp::MAIL_ENABLED : '';
}
else
{
$accountStatus = $values[$this->config['alias_attr']]['count'] > 0 ? emailadmin_smtp::MAIL_ENABLED : '';
$accountStatus = $values[static::ALIAS_ATTR]['count'] > 0 ? emailadmin_smtp::MAIL_ENABLED : '';
}
if ($this->config['forward_only_attr'])
if (static::FORWARD_ONLY_ATTR)
{
$deliveryMode = isset($values[$this->config['forward_only_attr']]) &&
($this->config['forward_only'] && !strcasecmp($values[$this->config['forward_only_attr']][0], $this->config['forward_only']) ||
!$this->config['forward_only'] && $values[$this->config['forward_only_attr']]['count'] > 0) ? emailadmin_smtp::FORWARD_ONLY : '';
if (static::FORWARD_ONLY) // check caseinsensitiv for existence of that value
{
$deliveryMode = self::getAttributePrefix($values[static::FORWARD_ONLY_ATTR], static::FORWARD_ONLY) ?
emailadmin_smtp::FORWARD_ONLY : '';
}
else // check for existence of any value
{
$deliveryMode = $values[static::FORWARD_ONLY_ATTR]['count'] > 0 ?
emailadmin_smtp::FORWARD_ONLY : '';
}
}
else
{
@ -329,29 +409,28 @@ class emailadmin_smtp_ldap extends emailadmin_smtp
// groups never have a mailbox, accounts can have a deliveryMode of "forwardOnly"
if ($deliveryMode != emailadmin_smtp::FORWARD_ONLY)
{
$userData['uid'][] = $values['uid'][0];
if ($this->config['mailbox_attr'] && isset($values[$this->config['mailbox_attr']]))
$userData[static::USER_ATTR][] = $values[static::USER_ATTR][0];
if (static::MAILBOX_ATTR && isset($values[static::MAILBOX_ATTR]))
{
$userData['mailbox'][] = $values[$this->config['mailbox_attr']][0];
$userData['mailbox'][] = $values[static::MAILBOX_ATTR][0];
}
}
if ($this->config['forward_attr'] && $values[$this->config['forward_attr']])
if (static::FORWARD_ATTR && $values[static::FORWARD_ATTR])
{
$userData['forward'] = array_merge((array)$userData['forward'], $values[$this->config['forward_attr']]);
unset($userData['forward']['count']);
$userData['forward'] = array_merge($userData['forward'],
self::getAttributePrefix($values[static::FORWARD_ATTR], static::FORWARD_PREFIX, false));
}
}
// regular user-data can only be from users, NOT groups
if (in_array('posixGroup', $values['objectclass'])) continue;
if (in_array(static::GROUP_SCHEMA, $values['objectclass'])) continue;
$userData['mailLocalAddress'] = $values['mail'][0];
$userData['accountStatus'] = $accountStatus;
if ($this->config['alias_attr'])
if (static::ALIAS_ATTR)
{
$userData['mailAlternateAddress'] = (array)$values[$this->config['alias_attr']];
unset($userData['mailAlternateAddress']['count']);
$userData['mailAlternateAddress'] = self::getAttributePrefix($values[static::ALIAS_ATTR], static::ALIAS_PREFIX);
}
else
{
@ -361,31 +440,27 @@ class emailadmin_smtp_ldap extends emailadmin_smtp
$userData['mailAlternateAddress'] = array_values($userData['mailAlternateAddress']);
}
$userData['mailForwardingAddress'] = $this->config['forward_attr'] ? $values[$this->config['forward_attr']] : array();
unset($userData['mailForwardingAddress']['count']);
if ($this->config['mailbox_attr']) $userData['mailMessageStore'] = $values[$this->config['mailbox_attr']][0];
if ($this->config['forward_only_attr'])
if (static::FORWARD_ATTR)
{
$userData['deliveryMode'] = isset($values[$this->config['forward_only_attr']]) &&
($this->config['forward_only'] && !strcasecmp($values[$this->config['forward_only_attr']][0], $this->config['forward_only']) ||
!$this->config['forward_only'] && $values[$this->config['forward_only_attr']]['count'] > 0) ? emailadmin_smtp::FORWARD_ONLY : '';
}
else
{
$userData['deliveryMode'] = '';
$userData['mailForwardingAddress'] = self::getAttributePrefix($values[static::FORWARD_ATTR], static::FORWARD_PREFIX);
}
if (static::MAILBOX_ATTR) $userData['mailMessageStore'] = $values[static::MAILBOX_ATTR][0];
$userData['deliveryMode'] = $deliveryMode;
// eg. suse stores all email addresses as aliases
if ($this->config['require_mail_as_alias'] &&
if (static::REQUIRE_MAIL_AS_ALIAS &&
($k = array_search($userData['mailLocalAddress'],$userData['mailAlternateAddress'])) !== false)
{
unset($userData['mailAlternateAddress'][$k]);
}
if ($this->config['quota_attr'] && isset($values[$this->config['quota_attr']]))
if (static::QUOTA_ATTR && isset($values[static::QUOTA_ATTR]))
{
$userData['quotaLimit'] = $values[$this->config['quota_attr']][0] / 1048576;
$userData['quotaLimit'] = self::getAttributePrefix($values[static::QUOTA_ATTR], static::QUOTA_PREFIX);
$userData['quotaLimit'] = array_shift($userData['quotaLimit']);
$userData['quotaLimit'] = $userData['quotaLimit'] ? $userData['quotaLimit'] / static::QUOTA_FACTOR : null;
}
}
}
@ -411,25 +486,32 @@ class emailadmin_smtp_ldap extends emailadmin_smtp
function setUserData($_uidnumber, array $_mailAlternateAddress, array $_mailForwardingAddress, $_deliveryMode,
$_accountStatus, $_mailLocalAddress, $_quota, $_forwarding_only=false, $_setMailbox=null)
{
$filter = 'uidnumber='.(int)$_uidnumber;
if (static::USERID_ATTR)
{
$filter = static::USERID_ATTR.'='.(int)$_uidnumber;
}
else
{
$uid = $GLOBALS['egw']->accounts->id2name($_uidnumber);
$filter = static::USER_ATTR.'='.ldap::quote($uid);
}
$ldap = $this->getLdapConnection();
$ldap = $GLOBALS['egw']->ldap->ldapConnect();
if (!($sri = @ldap_search($ldap,$GLOBALS['egw_info']['server']['ldap_context'],$filter)))
if (!($sri = @ldap_search($ldap, $this->search_base, $filter)))
{
return false;
}
$allValues = ldap_get_entries($ldap, $sri);
$accountDN = $allValues[0]['dn'];
$uid = $allValues[0]['uid'][0];
$uid = $allValues[0][static::USER_ATTR][0];
$objectClasses = $allValues[0]['objectclass'];
unset($objectClasses['count']);
if(!in_array($this->config['schema'],$objectClasses) && !in_array(strtolower($this->config['schema']),$objectClasses))
if(!in_array(static::SCHEMA,$objectClasses) && !in_array(strtolower(static::SCHEMA),$objectClasses))
{
$objectClasses[] = $this->config['schema'];
$objectClasses[] = static::SCHEMA;
$newData['objectclass'] = $objectClasses;
}
@ -438,53 +520,61 @@ class emailadmin_smtp_ldap extends emailadmin_smtp
$newData['mail'] = $_mailLocalAddress;
// does schema have explicit alias attribute
if ($this->config['alias_attr'])
if (static::ALIAS_ATTR)
{
$newData[$this->config['alias_attr']] = (array)$_mailAlternateAddress;
self::setAttributePrefix($newData[static::ALIAS_ATTR], $_mailAlternateAddress, static::ALIAS_PREFIX);
// all email must be stored as alias for suse
if ($this->config['require_mail_as_alias'] && !in_array($_mailLocalAddress,(array)$_mailAlternateAddress))
if (static::REQUIRE_MAIL_AS_ALIAS && !in_array($_mailLocalAddress,(array)$_mailAlternateAddress))
{
$newData[$this->config['alias_attr']][] = $_mailLocalAddress;
self::setAttributePrefix($newData[static::ALIAS_ATTR], $_mailLocalAddress, static::ALIAS_PREFIX);
}
}
// or de we add them - if existing - to mail attr
elseif ($_mailAlternateAddress)
{
$newData['mail'] = array_merge((array)$newData['mail'],(array)$_mailAlternateAddress);
self::setAttributePrefix($newData['mail'], $_mailAlternateAddress, static::ALIAS_PREFIX);
}
// does schema support to store forwards
if ($this->config['forward_attr'])
if (static::FORWARD_ATTR)
{
$newData[$this->config['forward_attr']] = (array)$_mailForwardingAddress;
self::setAttributePrefix($newData[static::FORWARD_ATTR], $_mailForwardingAddress, static::FORWARD_PREFIX);
}
// does schema support only forwarding incomming mail
if ($this->config['forward_only_attr'])
if (static::FORWARD_ONLY_ATTR)
{
$newData[$this->config['forward_only_attr']] = $_deliveryMode ? $this->config['forward_only'] : array();
}
// does schema support enabling/disabling mail via attribute
if ($this->config['mail_enable_attr'])
{
$newData[$this->config['mail_enable_attr']] = $_accountStatus ? $this->config['mail_enabled'] : array();
self::setAttributePrefix($newData[static::FORWARD_ONLY_ATTR],
$_deliveryMode ? (static::FORWARD_ONLY ? static::FORWARD_ONLY : 'forwardOnly') : array());
}
// does schema support an explicit mailbox name --> set it with $uid@$domain
if ($this->config['mailbox_attr'] && empty($allValues[0][$this->config['mailbox_attr']][0]))
if (static::MAILBOX_ATTR && empty($allValues[0][static::MAILBOX_ATTR][0]))
{
$newData[$this->config['mailbox_attr']] = $this->mailbox_addr(array(
$newData[static::MAILBOX_ATTR] = $this->mailbox_addr(array(
'account_id' => $_uidnumber,
'account_lid' => $uid,
'account_email' => $_mailLocalAddress,
));
}
if ($this->config['quota_attr'])
if (static::QUOTA_ATTR)
{
$newData[$this->config['quota_attr']] = (int)$_quota >= 0 ? (int)$_quota*1048576 : array();
self::setAttributePrefix($newData[static::QUOTA_ATTR],
(int)$_quota > 0 ? (int)$_quota*static::QUOTA_FACTOR : array(), static::QUOTA_PREFIX);
}
// does schema support enabling/disabling mail via attribute
if (static::MAIL_ENABLE_ATTR)
{
$newData[static::MAIL_ENABLE_ATTR] = $_accountStatus ? static::MAIL_ENABLED : array();
}
// if we have no mail-enabled attribute, but require primary mail in aliases-attr
// we do NOT write aliases, if mail is not enabled
if (!$_accountStatus && !static::MAIL_ENABLE_ATTR && static::REQUIRE_MAIL_AS_ALIAS)
{
$newData[static::ALIAS_ATTR] = array();
}
// does schema support an explicit mailbox name --> set it, $_setMailbox is given
if ($this->config['mailbox_attr'] && $_setMailbox)
if (static::MAILBOX_ATTR && $_setMailbox)
{
$newData[$this->config['mailbox_attr']] = $_setMailbox;
$newData[static::MAILBOX_ATTR] = $_setMailbox;
}
if ($this->debug) error_log(__METHOD__.'('.array2string(func_get_args()).") --> ldap_mod_replace(,'$accountDN',".array2string($newData).')');
@ -501,14 +591,22 @@ class emailadmin_smtp_ldap extends emailadmin_smtp
*/
function saveSMTPForwarding($_accountID, $_forwardingAddress, $_keepLocalCopy)
{
$ds = $GLOBALS['egw']->ldap->ldapConnect();
$filter = sprintf('(&(uidnumber=%d)(objectclass=posixAccount))',$_accountID);
$attributes = array('dn',$this->config['forward_attr'],'objectclass');
if ($this->config['forward_only_attr'])
$ds = $this->getLdapConnection();
if (static::USERID_ATTR)
{
$attributes[] = $this->config['forward_only_attr'];
$filter = '(&'.static::USER_FILTER.'('.static::USERID_ATTR.'='.(int)$_accountID.'))';
}
$sri = ldap_search($ds, $GLOBALS['egw_info']['server']['ldap_context'], $filter, $attributes);
else
{
$uid = $GLOBALS['egw']->accounts->id2name($_accountID);
$filter = '(&'.static::USER_FILTER.'('.static::USER_ATTR.'='.ldap::quote($uid).'))';
}
$attributes = array('dn', static::FORWARD_ATTR, 'objectclass');
if (static::FORWARD_ONLY_ATTR)
{
$attributes[] = static::FORWARD_ONLY_ATTR;
}
$sri = ldap_search($ds, $this->search_base, $filter, $attributes);
if ($sri)
{
@ -519,46 +617,163 @@ class emailadmin_smtp_ldap extends emailadmin_smtp
unset($newData['objectclass']['count']);
if(!in_array($this->config['schema'],$objectClasses))
if(!in_array(static::SCHEMA,$objectClasses))
{
$newData['objectclass'][] = $this->config['schema'];
$newData['objectclass'][] = static::SCHEMA;
}
if ($this->config['forward_attr'])
if (static::FORWARD_ATTR)
{
// copy all non-forward data (different prefix) to newData, all existing forwards to $forwards
$newData[static::FORWARD_ATTR] = $allValues[0][static::FORWARD_ATTR];
$forwards = self::getAttributePrefix($newData[static::FORWARD_ATTR], static::FORWARD_PREFIX);
if(!empty($_forwardingAddress))
{
if(is_array($allValues[0][$this->config['forward_attr']]))
if($forwards)
{
$newData[$this->config['forward_attr']] = $allValues[0][$this->config['forward_attr']];
unset($newData[$this->config['forward_attr']]['count']);
if (!is_array($_forwardingAddress))
{
// replace the first forwarding address (old behavior)
$newData[$this->config['forward_attr']][0] = $_forwardingAddress;
$forwards[0] = $_forwardingAddress;
}
else
{
// replace all forwarding Addresses
$newData[$this->config['forward_attr']] = $_forwardingAddress;
$forwards = $_forwardingAddress;
}
}
else
{
$newData[$this->config['forward_attr']] = (array)$_forwardingAddress;
$forwards = (array)$_forwardingAddress;
}
if ($this->config['forward_only_attr'])
if (static::FORWARD_ONLY_ATTR)
{
$newData['deliverymode'] = $_keepLocalCopy == 'yes' ? array() : $this->config['forward_only'];
self::getAttributePrefix($newData[static::FORWARD_ONLY_ATTR], static::FORWARD_ONLY);
self::setAttributePrefix($newData[static::FORWARD_ONLY_ATTR],
$_keepLocalCopy == 'yes' ? array() : static::FORWARD_ONLY);
}
}
else
{
$newData[$this->config['forward_attr']] = array();
$forwards = array();
}
// merge in again all new set forwards incl. opt. prefix
self::getAttributePrefix($newData[static::FORWARD_ATTR], $forwards, static::FORWARD_PREFIX);
}
if ($this->debug) error_log(__METHOD__.'('.array2string(func_get_args()).") --> ldap_mod_replace(,'$accountDN',".array2string($newData).')');
return ldap_modify ($ds, $allValues[0]['dn'], $newData);
}
}
/**
* Get configured mailboxes of a domain
*
* @param boolean $return_inactive return mailboxes NOT marked as accountStatus=active too
* @return array uid => name-part of mailMessageStore
*/
function getMailboxes($return_inactive)
{
$ds = $this->getLdapConnection();
$filter = array("(mail=*)");
$attrs = array(static::USER_ATTR, 'mail');
if (static::MAILBOX_ATTR)
{
$filter[] = '('.static::MAILBOX_ATTR.'=*)';
$attrs[] = static::MAILBOX_ATTR;
}
if (!$return_inactive && static::MAIL_ENABLE_ATTR)
{
$filter[] = '('.static::MAIL_ENABLE_ATTR.'='.static::MAIL_ENABLED.')';
}
if (count($filter) > 1)
{
$filter = '(&'.implode('', $filter).')';
}
else
{
$filter = $filter[0];
}
if (!($sr = @ldap_search($ds, $this->search_base, $filter, $attrs)))
{
//error_log("Error ldap_search(\$ds, '$base', '$filter')!");
return array();
}
$entries = ldap_get_entries($ds, $sr);
unset($entries['count']);
$mailboxes = array();
foreach($entries as $entry)
{
if ($entry[static::USER_ATTR][0] == 'anonymous') continue; // anonymous is never a mail-user!
list($mailbox) = explode('@', $entry[static::MAILBOX_ATTR ? static::MAILBOX_ATTR : 'mail'][0]);
$mailboxes[$entry[static::USER_ATTR][0]] = $mailbox;
}
return $mailboxes;
}
/**
* Set values in a given LDAP attribute using an optional prefix
*
* @param array &$attribute on return array with values set and existing values preseved
* @param string|array $values value(s) to set
* @param string $prefix='' prefix to use or ''
*/
protected static function setAttributePrefix(&$attribute, $values, $prefix='')
{
$attribute_in = $attribute;
if (!isset($attribute)) $attribute = array();
if (!is_array($attribute)) $attribute = array($attribute);
foreach((array)$values as $value)
{
$attribute[] = $prefix.$value;
}
//error_log(__METHOD__."(".array2string($attribute_in).", ".array2string($values).", '$prefix') attribute=".array2string($attribute));
}
/**
* Get values having an optional prefix from a given LDAP attribute
*
* @param array &$attribute only "count" and prefixed values get removed, get's reindexed, if values have been removed
* @param string $prefix='' prefix to use or ''
* @param boolean $remove=true remove returned values from $attribute
* @return array with values (prefix removed) or array() if nothing found
*/
protected static function getAttributePrefix(&$attribute, $prefix='', $remove=true)
{
$attribute_in = $attribute;
$values = array();
if (isset($attribute))
{
unset($attribute['count']);
foreach($attribute as $key => $value)
{
if (!$prefix || stripos($value, $prefix) === 0)
{
if ($remove) unset($attribute[$key]);
$values[] = substr($value, strlen($prefix));
}
}
// reindex $attribute, if neccessary
if ($values && $attribute) $attribute = array_values($attribute);
}
//error_log(__METHOD__."(".array2string($attribute_in).", '$prefix', $remove) attribute=".array2string($attribute).' returning '.array2string($values));
return $values;
}
/**
* Return LDAP connection
*/
protected function getLdapConnection()
{
static $ldap;
if (is_null($ldap)) $ldap = $GLOBALS['egw']->ldap->ldapConnect();
return $ldap;
}
}

View File

@ -53,10 +53,6 @@ class emailadmin_smtp_qmail extends emailadmin_smtp_ldap
* Attribute to only forward mail, OR false if not available
*/
const FORWARD_ONLY_ATTR = 'deliverymode';
/**
* Attribute value to only forward mail
*/
const FORWARD_ONLY = 'forwardOnly';
/**
* Attribute for mailbox, to which mail gets delivered OR false if not supported
@ -69,27 +65,12 @@ class emailadmin_smtp_qmail extends emailadmin_smtp_ldap
const QUOTA_ATTR = 'mailquotasize';
/**
* Log all LDAP writes / actions to error_log
*/
var $debug = false;
/**
* LDAP schema configuration
* Return description for EMailAdmin
*
* Parent can NOT use constants direct as we have no late static binding in currenlty required PHP 5.2
*
* @var array
* @return string
*/
protected $config = array(
'schema' => self::SCHEMA,
'mail_enable_attr' => self::MAIL_ENABLE_ATTR,
'mail_enabled' => self::MAIL_ENABLED,
'alias_attr' => self::ALIAS_ATTR,
'require_mail_as_alias' => self::REQUIRE_MAIL_AS_ALIAS,
'forward_attr' => self::FORWARD_ATTR,
'forward_only_attr' => self::FORWARD_ONLY_ATTR,
'forward_only' => self::FORWARD_ONLY,
'mailbox_attr' => self::MAILBOX_ATTR,
'quota_attr' => self::QUOTA_ATTR,
);
public static function description()
{
return 'LDAP (new '.static::SCHEMA.')';
}
}

View File

@ -5,7 +5,7 @@
* @link http://www.stylite.de
* @package emailadmin
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @copyright (c) 2012 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @copyright (c) 2012-13 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
@ -15,6 +15,11 @@
*/
class emailadmin_smtp_sql extends emailadmin_smtp
{
/**
* Label shown in EMailAdmin
*/
const DESCRIPTION = 'SQL';
/**
* Capabilities of this class (pipe-separated): default, forward
*/

View File

@ -33,6 +33,11 @@ include_once(EGW_SERVER_ROOT."/emailadmin/inc/class.defaultimap.inc.php");
class pleskimap extends defaultimap
{
/**
* Label shown in EMailAdmin
*/
const DESCRIPTION = 'Plesk (Courier)';
/**
* @var string $psa_mail_script full path to Plesk's mail.sh (Linux including sudo!) or mail.exe (Windows) interface
*/

View File

@ -5,7 +5,7 @@
* @link http://www.egroupware.org
* @package emailadmin
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @copyright (c) 2010 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @copyright (c) 2010-13 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
@ -54,10 +54,6 @@ class postfixdbmailuser extends emailadmin_smtp_ldap
* Attribute to only forward mail, OR false if not available
*/
const FORWARD_ONLY_ATTR = 'deliverymode';
/**
* Attribute value to only forward mail
*/
const FORWARD_ONLY = 'forwardOnly';
/**
* Attribute for mailbox, to which mail gets delivered OR false if not supported
@ -65,28 +61,4 @@ class postfixdbmailuser extends emailadmin_smtp_ldap
//const MAILBOX_ATTR = 'deliveryprogrampath';
//const MAILBOX_ATTR = 'dbmailuid';
const MAILBOX_ATTR = false;
/**
* Log all LDAP writes / actions to error_log
*/
var $debug = false;
/**
* LDAP schema configuration
*
* Parent can NOT use constants direct as we have no late static binding in currenlty required PHP 5.2
*
* @var array
*/
protected $config = array(
'schema' => self::SCHEMA,
'mail_enable_attr' => self::MAIL_ENABLE_ATTR,
'mail_enabled' => self::MAIL_ENABLED,
'alias_attr' => self::ALIAS_ATTR,
'require_mail_as_alias' => self::REQUIRE_MAIL_AS_ALIAS,
'forward_attr' => self::FORWARD_ATTR,
'forward_only_attr' => self::FORWARD_ONLY_ATTR,
'forward_only' => self::FORWARD_ONLY,
'mailbox_attr' => self::MAILBOX_ATTR,
);
}

View File

@ -5,7 +5,7 @@
* @link http://www.egroupware.org
* @package emailadmin
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @copyright (c) 2010 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @copyright (c) 2010-13 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
@ -54,10 +54,6 @@ class postfixldap extends emailadmin_smtp_ldap
* Attribute to only forward mail, OR false if not available
*/
const FORWARD_ONLY_ATTR = 'deliverymode';
/**
* Attribute value to only forward mail
*/
const FORWARD_ONLY = 'forwardOnly';
/**
* Attribute for mailbox, to which mail gets delivered OR false if not supported
@ -68,29 +64,4 @@ class postfixldap extends emailadmin_smtp_ldap
* Attribute for quota limit of user in MB
*/
const QUOTA_ATTR = 'mailquota';
/**
* Log all LDAP writes / actions to error_log
*/
var $debug = false;
/**
* LDAP schema configuration
*
* Parent can NOT use constants direct as we have no late static binding in currenlty required PHP 5.2
*
* @var array
*/
protected $config = array(
'schema' => self::SCHEMA,
'mail_enable_attr' => self::MAIL_ENABLE_ATTR,
'mail_enabled' => self::MAIL_ENABLED,
'alias_attr' => self::ALIAS_ATTR,
'require_mail_as_alias' => self::REQUIRE_MAIL_AS_ALIAS,
'forward_attr' => self::FORWARD_ATTR,
'forward_only_attr' => self::FORWARD_ONLY_ATTR,
'forward_only' => self::FORWARD_ONLY,
'mailbox_attr' => self::MAILBOX_ATTR,
'quota_attr' => self::QUOTA_ATTR,
);
}

View File

@ -25,6 +25,11 @@ include_once(EGW_SERVER_ROOT."/emailadmin/inc/class.pleskimap.inc.php");
class smtpplesk extends defaultsmtp
{
/**
* Label shown in EMailAdmin
*/
const DESCRIPTION = 'Plesk (Qmail)';
/**
* Capabilities of this class (pipe-separated): default, forward
*/

View File

@ -116,7 +116,7 @@ class uiuserdata
"style='width: 100%;' id='mailRoutingAddress'",
5)
);
if (isset($userData["quotaUsed"]) && $userData["quotaUsed"]>0) $this->t->set_var('lang_qoutainmbyte',lang('qouta size in MByte').'<br><b><i>('.(int)$userData["quotaUsed"].' '.lang('MB used').')</i></b>');
if (isset($userData["quotaUsed"]) && $userData["quotaUsed"]>0) $this->t->set_var('lang_quotainmbyte',lang('Quota size in MByte').'<br><b><i>('.(int)$userData["quotaUsed"].' '.lang('MB used').')</i></b>');
$this->t->set_var("quotaLimit",$userData["quotaLimit"]);
$this->t->set_var("mailLocalAddress",$userData["mailLocalAddress"]);
@ -209,7 +209,7 @@ class uiuserdata
$this->t->set_var('lang_qmaildotmode',lang('qmaildotmode'));
$this->t->set_var('lang_default',lang('default'));
$this->t->set_var('lang_quota_settings',lang('quota settings'));
$this->t->set_var('lang_qoutainmbyte',lang('qouta size in MByte'));
$this->t->set_var('lang_quotainmbyte',lang('Quota size in MByte'));
$this->t->set_var('lang_inmbyte',lang('in MByte'));
$this->t->set_var('lang_0forunlimited',lang('leave empty for no quota'));
$this->t->set_var('lang_forward_only',lang('forward only'));

View File

@ -79,7 +79,7 @@ var langModifyAddress="{lang_update_current_address}";
</td>
</tr>
<tr bgcolor="{tr_color2}">
<td width="200">{lang_qoutainmbyte}</td>
<td width="200">{lang_quotainmbyte}</td>
<td colspan="2">
<input name="quotaLimit" value="{quotaLimit}" style="width:350px;"> ({lang_0forunlimited})
</td>

View File

@ -319,8 +319,7 @@ class accounts
$account_search[$serial]['total'] = $this->total;
}
// search via ldap backend
elseif ($this->config['account_repository'] == 'ldap')
//not correct for php<5.1 elseif ((method_exists($this,'search')) // implements its on search function ==> use it
elseif (method_exists($this->backend, 'search')) // implements its on search function ==> use it
{
$account_search[$serial]['data'] = $this->backend->search($param);
$account_search[$serial]['total'] = $this->total = $this->backend->total;
@ -443,8 +442,7 @@ class accounts
if (($id = $this->backend->save($data)) && $data['account_type'] != 'g')
{
// if we are not on a pure LDAP system, we have to write the account-date via the contacts class now
if (($this->config['account_repository'] != 'ldap' ||
$this->config['contact_repository'] == 'sql-ldap') &&
if (($this->config['account_repository'] == 'sql' || $this->config['contact_repository'] == 'sql-ldap') &&
(!($old = $this->read($data['account_id'])) || // only for new account or changed contact-data
$old['account_firstname'] != $data['account_firstname'] ||
$old['account_lastname'] != $data['account_lastname'] ||
@ -1018,11 +1016,11 @@ class accounts
{
if ($instance->get_type($account_id) == 'u')
{
$account['memberships'] = $instance->backend->memberships($account_id);
if (!isset($account['memberships'])) $account['memberships'] = $instance->backend->memberships($account_id);
}
else
{
$account['members'] = $instance->backend->members($account_id);
if (!isset($account['members'])) $account['members'] = $instance->backend->members($account_id);
}
egw_cache::setInstance(__CLASS__, 'account-'.$account_id, $account, self::READ_CACHE_TIMEOUT);
}

File diff suppressed because it is too large Load Diff

View File

@ -637,7 +637,7 @@ class accounts_ldap
function search($param)
{
//echo "<p>accounts_ldap::search(".print_r($param,true)."): ".microtime()."</p>\n";
$account_search = &$this->cache['account_search'];
$account_search =& accounts::$cache['account_search'];
// check if the query is cached
$serial = serialize($param);
@ -918,7 +918,7 @@ class accounts_ldap
if ($which == 'account_lid' && $account_type !== 'u') // groups only support account_lid
{
$sri = ldap_search($this->ds, $this->group_context, '(&(cn=' . $name . ')(objectclass=posixgroup))');
$sri = ldap_search($this->ds, $this->group_context, '(&(cn=' . $name . ')(objectclass=posixgroup))', array('gidNumber'));
$allValues = ldap_get_entries($this->ds, $sri);
if (@$allValues[0]['gidnumber'][0])
@ -935,7 +935,7 @@ class accounts_ldap
return False;
}
$sri = ldap_search($this->ds, $this->user_context, '(&('.$to_ldap[$which].'=' . $name . ')(objectclass=posixaccount))');
$sri = ldap_search($this->ds, $this->user_context, '(&('.$to_ldap[$which].'=' . $name . ')(objectclass=posixaccount))', array('uidNumber'));
$allValues = ldap_get_entries($this->ds, $sri);

View File

@ -36,42 +36,22 @@ class auth_ads implements auth_backend
return False;
}
if(!$ldap = @ldap_connect($GLOBALS['egw_info']['server']['ads_host']))
{
//echo "<p>Failed connecting to ADS server '".$GLOBALS['egw_info']['server']['ads_host']."' for authenication, execution stopped</p>\n";
$GLOBALS['egw']->log->message('F-Abort, Failed connecting to ADS server for authenication, execution stopped');
$GLOBALS['egw']->log->commit();
return False;
}
//echo "<p>Connected to LDAP server '".$GLOBALS['egw_info']['server']['ads_host']."' for authenication</p>\n";
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
$adldap = accounts_ads::get_adldap();
// bind with username@ads_domain, only if a non-empty password given, in case anonymous search is enabled
if(empty($passwd) || !@ldap_bind($ldap,$username.'@'.$GLOBALS['egw_info']['server']['ads_domain'],$passwd))
if(empty($passwd) || !$adldap->authenticate($username, $passwd))
{
//echo "<p>Cant bind with '$username@".$GLOBALS['egw_info']['server']['ads_domain']."' with PW '$passwd' !!!</p>\n";
//error_log(__METHOD__."('$username', ".(empty($passwd) ? "'') passwd empty" : '$passwd) adldap->authenticate() returned false')." --> returning false");
return False;
}
//echo "<p>Bind with '$username@".$GLOBALS['egw_info']['server']['ads_domain']."' with PW '$passwd'.</p>\n";
$attributes = array('samaccountname','givenName','sn','mail','homeDirectory');
$filter = "(samaccountname=$username)";
// automatic create dn from domain: domain.com ==> DC=domain,DC=com
$base_dn = array();
foreach(explode('.',$GLOBALS['egw_info']['server']['ads_domain']) as $dc)
if (($allValues = $adldap->user()->info($username, $attributes)))
{
$base_dn[] = 'DC='.$dc;
$allValues[0]['objectsid'][0] = $adldap->utilities()->getTextSID($allValues[0]['objectsid'][0]);
}
$base_dn = implode(',',$base_dn);
//error_log(__METHOD__."('$username', \$passwd) allValues=".array2string($allValues));
//echo "<p>Trying ldap_search(,$base_dn,$filter,".print_r($attributes,true)."</p>\n";
$sri = ldap_search($ldap, $base_dn, $filter, $attributes);
$allValues = ldap_get_entries($ldap, $sri);
//_debug_array($allValues);
if ($allValues['count'] > 0)
if ($allValues && $allValues['count'] > 0)
{
if($GLOBALS['egw_info']['server']['case_sensitive_username'] == true)
{
@ -92,6 +72,8 @@ class auth_ads implements auth_backend
}
if ($GLOBALS['egw_info']['server']['auto_create_acct'])
{
$GLOBALS['auto_create_acct']['account_id'] = accounts_ads::sid2account_id($allValues[0]['objectsid'][0]);
// create a global array with all availible info about that account
foreach(array(
'givenname' => 'firstname',
@ -102,6 +84,7 @@ class auth_ads implements auth_backend
$GLOBALS['auto_create_acct'][$acct_name] =
translation::convert($allValues[0][$ldap_name][0],'utf-8');
}
//error_log(__METHOD__."() \$GLOBALS[auto_create_acct]=".array2string($GLOBALS['auto_create_acct']));
return True;
}
}
@ -109,8 +92,38 @@ class auth_ads implements auth_backend
return False;
}
/**
* changes password
*
* @param string $old_passwd must be cleartext
* @param string $new_passwd must be cleartext
* @param int $account_id account id of user whose passwd should be changed
* @return boolean true if password successful changed, false otherwise
*/
function change_password($old_passwd, $new_passwd, $_account_id=0)
{
if (!($adldap = accounts_ads::get_adldap()) || !($adldap->getUseSSL() || $adldap->getUseTLS()))
{
error_log(__METHOD__."('$old_passwd', '$new_passwd', $account_id) adldap=".array2string($adldap)." returning false");
return false; // Cant change passwd in ADS
}
if(!$account_id || $GLOBALS['egw_info']['flags']['currentapp'] == 'login')
{
$admin = false;
$username = $GLOBALS['egw_info']['user']['account_lid'];
}
else
{
$admin = true;
$username = $GLOBALS['egw']->accounts->id2name($account_id);
}
// Check the old_passwd to make sure this is legal
if(!$admin && !$adldap->authenticate($username, $old_passwd))
{
//error_log(__METHOD__."() old password '$old_passwd' for '$username' is wrong!");
return false;
}
return $adldap->user()->password($username, $new_passwd);
}
}

View File

@ -193,83 +193,7 @@ class ldap
//error_log("no ldap server info found");
$ldapbind = @ldap_bind($this->ds, $GLOBALS['egw_info']['server']['ldap_root_dn'], $GLOBALS['egw_info']['server']['ldap_root_pw']);
$filter='(objectclass=*)';
$justthese = array('structuralObjectClass','namingContexts','supportedLDAPVersion','subschemaSubentry');
if(($sr = @ldap_read($this->ds, '', $filter, $justthese)))
{
if($info = ldap_get_entries($this->ds, $sr))
{
$this->ldapServerInfo = new ldapserverinfo($host);
$this->ldapServerInfo->setVersion($supportedLDAPVersion);
// check for naming contexts
if($info[0]['namingcontexts'])
{
for($i=0; $i<$info[0]['namingcontexts']['count']; $i++)
{
$namingcontexts[] = $info[0]['namingcontexts'][$i];
}
$this->ldapServerInfo->setNamingContexts($namingcontexts);
}
// check for ldap server type
if($info[0]['structuralobjectclass'])
{
switch($info[0]['structuralobjectclass'][0])
{
case 'OpenLDAProotDSE':
$ldapServerType = OPENLDAP_LDAPSERVER;
break;
default:
$ldapServerType = UNKNOWN_LDAPSERVER;
break;
}
$this->ldapServerInfo->setServerType($ldapServerType);
}
// check for subschema entry dn
if($info[0]['subschemasubentry'])
{
$subschemasubentry = $info[0]['subschemasubentry'][0];
$this->ldapServerInfo->setSubSchemaEntry($subschemasubentry);
}
// create list of supported objetclasses
if(!empty($subschemasubentry))
{
$filter='(objectclass=*)';
$justthese = array('objectClasses');
if($sr=ldap_read($this->ds, $subschemasubentry, $filter, $justthese))
{
if($info = ldap_get_entries($this->ds, $sr))
{
if($info[0]['objectclasses']) {
for($i=0; $i<$info[0]['objectclasses']['count']; $i++)
{
$pattern = '/^\( (.*) NAME \'(\w*)\' /';
if(preg_match($pattern, $info[0]['objectclasses'][$i], $matches))
{
#_debug_array($matches);
if(count($matches) == 3)
{
$supportedObjectClasses[$matches[1]] = strtolower($matches[2]);
}
}
}
$this->ldapServerInfo->setSupportedObjectClasses($supportedObjectClasses);
}
}
}
}
}
}
else
{
unset($this->ldapServerInfo);
}
$this->ldapServerInfo = ldapserverinfo::get($this->ds, $host, $supportedLDAPVersion);
$this->saveSessionData();
}

View File

@ -13,6 +13,7 @@
define('UNKNOWN_LDAPSERVER',0);
define('OPENLDAP_LDAPSERVER',1);
define('SAMBA4_LDAPSERVER',2);
/**
* Class to store and retrieve information (eg. supported object classes) of a connected ldap server
@ -140,4 +141,92 @@ class ldapserverinfo
}
return false;
}
/**
* Query given ldap connection for available information
*
* @param resource $ds
* @param string $host
* @param int $version 2 or 3
* @return ldapserverinfo
*/
public static function get($ds, $host, $version=3)
{
$filter='(objectclass=*)';
$justthese = array('structuralObjectClass','namingContexts','supportedLDAPVersion','subschemaSubentry','vendorname');
if(($sr = @ldap_read($ds, '', $filter, $justthese)))
{
if($info = ldap_get_entries($ds, $sr))
{
$ldapServerInfo = new ldapserverinfo($host);
$ldapServerInfo->setVersion($version);
// check for naming contexts
if($info[0]['namingcontexts'])
{
for($i=0; $i<$info[0]['namingcontexts']['count']; $i++)
{
$namingcontexts[] = $info[0]['namingcontexts'][$i];
}
$ldapServerInfo->setNamingContexts($namingcontexts);
}
// check for ldap server type
if($info[0]['structuralobjectclass'])
{
switch($info[0]['structuralobjectclass'][0])
{
case 'OpenLDAProotDSE':
$ldapServerType = OPENLDAP_LDAPSERVER;
break;
default:
$ldapServerType = UNKNOWN_LDAPSERVER;
break;
}
$ldapServerInfo->setServerType($ldapServerType);
}
if ($info[0]['vendorname'] && stripos($info[0]['vendorname'][0], 'samba') !== false)
{
$ldapServerInfo->setServerType(SAMBA4_LDAPSERVER);
}
// check for subschema entry dn
if($info[0]['subschemasubentry'])
{
$subschemasubentry = $info[0]['subschemasubentry'][0];
$ldapServerInfo->setSubSchemaEntry($subschemasubentry);
}
// create list of supported objetclasses
if(!empty($subschemasubentry))
{
$filter='(objectclass=*)';
$justthese = array('objectClasses');
if($sr=ldap_read($ds, $subschemasubentry, $filter, $justthese))
{
if($info = ldap_get_entries($ds, $sr))
{
if($info[0]['objectclasses']) {
for($i=0; $i<$info[0]['objectclasses']['count']; $i++)
{
$pattern = '/^\( (.*) NAME \'(\w*)\' /';
if(preg_match($pattern, $info[0]['objectclasses'][$i], $matches))
{
#_debug_array($matches);
if(count($matches) == 3)
{
$supportedObjectClasses[$matches[1]] = strtolower($matches[2]);
}
}
}
$ldapServerInfo->setSupportedObjectClasses($supportedObjectClasses);
}
}
}
}
}
}
return $ldapServerInfo;
}
}

View File

@ -96,10 +96,14 @@ else
if($_POST['delete_all'])
{
/* Now, clear out existing tables */
foreach(array($GLOBALS['egw_setup']->accounts_table,$GLOBALS['egw_setup']->prefs_table,$GLOBALS['egw_setup']->acl_table,'egw_access_log') as $table)
foreach(array($GLOBALS['egw_setup']->accounts_table,$GLOBALS['egw_setup']->acl_table,'egw_access_log') as $table)
{
$GLOBALS['egw_setup']->db->delete($table,'1=1',__LINE__,__FILE__);
}
// keep default and forced prefs from installed apps
$GLOBALS['egw_setup']->db->delete($GLOBALS['egw_setup']->prefs_table,'preferences_owner NOT IN (-1,-2)',__LINE__,__FILE__);
// remove accounts from addressbook
$GLOBALS['egw_setup']->db->delete('egw_addressbook','account_id IS NOT NULL',__LINE__,__FILE__);
}
/* Create the demo groups */
$defaultgroupid = (int)$GLOBALS['egw_setup']->add_account('Default','Default','Group',False,False);

View File

@ -1004,7 +1004,7 @@ class setup
{
// load the configuration from the database
foreach($this->db->select($this->config_table,'config_name,config_value',
"config_name LIKE 'ldap%' OR config_name LIKE 'account_%' OR config_name LIKE '%encryption%' OR config_name='auth_type'",
"config_name LIKE 'ads%' OR config_name LIKE 'ldap%' OR config_name LIKE 'account_%' OR config_name LIKE '%encryption%' OR config_name='auth_type'",
__LINE__,__FILE__) as $row)
{
$GLOBALS['egw_info']['server'][$row['config_name']] = $config[$row['config_name']] = $row['config_value'];

View File

@ -245,7 +245,7 @@ however, the application may still work setup ca Tanmateix, l'aplicació encara
if no acl records for user or any group the user is a member of setup ca Si no hi han registres ACL ni grup per a l'usuari, aleshores és membre de
if safe_mode is turned on, egw is not able to change certain settings on runtime, nor can we load any not yet loaded module. setup ca Si mode_segur està activat, eGW no pot canviar determinades configuracions en temps d'execució ni tampoc podem carregar cap mòdul que no estigui carregat.
if the application has no defined tables, selecting upgrade should remedy the problem setup ca Si l'aplicació no ha definit taules, seleccionant actualitzar hauria de resoldre el problema
if using ads (active directory) authentication setup ca Si feu servir autentificació ADS (Activer Directory)
if using ads (active directory) setup ca Si feu servir autentificació ADS (Activer Directory)
if using ldap setup ca Si feu servir LDAP
if using ldap, do you want to manage homedirectory and loginshell attributes? setup ca Si utilitzeu LDAP, voleu administrar els atributs del directori personal i l'interpret d'ordres?
if you did not receive any errors, your applications have been setup ca Si no heu rebut cap error, les aplicacions han estat

View File

@ -314,7 +314,7 @@ http auth types (comma-separated) to use without login-page, eg. "ntlm" setup cs
if no acl records for user or any group the user is a member of setup cs Pokud nejsou ACL záznamy pro uživatele nebo libovolnou skupinu, které je členem
if safe_mode is turned on, egw is not able to change certain settings on runtime, nor can we load any not yet loaded module. setup cs Pokud je zapnutý režim safe_mode, eGW nemůže za běhu měnit některá nastavení ani načítat dosud nenačtené moduly
if the application has no defined tables, selecting upgrade should remedy the problem setup cs Pokud aplikace nemá definovány tabulky, aktualizace by měla problém napravit
if using ads (active directory) authentication setup cs Při použití ADS (Active Directory) autentikace
if using ads (active directory) setup cs Při použití ADS (Active Directory) autentikace
if using cas (central authentication service): setup cs Při použití CAS (Central Authentication Service):
if using ldap setup cs Při použití LDAP
if using ldap, do you want to manage homedirectory and loginshell attributes? setup cs Chcete při použití LDAP spravovat atributy pro domovský adresář a loginshell?

View File

@ -14,7 +14,7 @@
'%1' is no valid domain name! setup de '%1' ist kein gültiger Domainname!
'%1' is not allowed as %2. arguments of option %3 !!! setup de '%1' ist nicht erlaubt als %2. Parameter für die Option %3 !!!
'%1' must be integer setup de %1 muß ein Integer-Wert sein.
(searching accounts and changing passwords) setup de Benutzerkonten suchen und Passwörter ändern)
(searching accounts and changing passwords) setup de (Benutzerkonten suchen und Passwörter ändern)
*** do not update your database via setup, as the update might be interrupted by the max_execution_time, which leaves your db in an unrecoverable state (your data is lost) !!! setup de *** Updaten Sie NICHT Ihre Datenbank via Setup, da das Update von der max_execution_time (max. Ausführungszeit für Skripte) unterbrochen werden kann. Ihre Datenbank ist dann in einem nicht mehr wiederherstellbaren Zustand (Ihre Daten sind VERLOREN)!!!
*** you have to do the changes manualy in your php.ini (usualy in /etc on linux) in order to get egw fully working !!! setup de *** Sie müssen die Änderungen manuell in Ihrer php.ini Datei (üblicherweise in /etc unter Linux) durchführen, um EGroupware vollständig/fehlerfrei ausführen zu können!!!
00 (disable) setup de 00 (abgeschaltet/empfohlen)
@ -41,6 +41,7 @@ admin first name setup de Admin Vorname
admin last name setup de Admin Nachname
admin password setup de Admin Passwort
admin password to header manager setup de Admin Passwort für Headerverwaltung
admin user setup de Administrator Konto
admin user for header manager setup de Admin Benutzer für Headerverwaltung
admin username setup de Admin Benutzername
admins setup de Administratoren
@ -168,6 +169,7 @@ configuration user setup de Konfigurationsbenutzer
configure now setup de Jetzt konfigurieren
confirm to delete this backup? setup de Bestätigen Sie diese Datensicherung zu löschen?
contain setup de enthält
context to create users setup de Kontext um Benutzer anzulegen
continue setup de Weiter
continue to the header admin setup de Weiter zur Headerverwaltung
convert setup de Konvertieren
@ -243,9 +245,11 @@ domain-name setup de Domainname
don't change, if you already stored files! you will loose them! setup de Nicht ändern, wenn Sie bereits Dateien gespeichert haben! Sie werden Sie verlieren!
dont touch my data setup de Meine Daten nicht verändern
download setup de Herunterladen
easiest way under win2008r2 is to add role "active directory certificate services" and reboot. setup de Unter Win2008r2 geht das am einfachsten durch hinzufügen der Rolle "Active Directory-Zertifikatsdienste" und neu starten.
edit current configuration setup de Gegenwärtige Konfiguration überarbeiten
edit your existing header.inc.php setup de Bearbeiten Ihrer existierenden header.inc.php
edit your header.inc.php setup de Bearbeiten Ihrer header.inc.php
eg. "cn=users,dc=domain,dc=com" for ads domain "domain.com" setup de z.B. "CN=Users,DC=domain,DC=com" für die ADS Domaine "domain.com"
eg. /egroupware or http://domain.com/egroupware, default: %1 setup de zB. /egroupware oder http://domain.com/egroupware, Vorgabe: %1
egroupware administration manual setup de EGroupware Administrationsmanual (nur in englisch)
egroupware api needs a database (schema) update from version %1 to %2! setup de EGroupware API benötigt eine Datenbank (Schema) Aktualisierung von Version %1 auf %2!
@ -296,7 +300,7 @@ filesystem setup de Dateisystem
filesystem (default) setup de Dateisystem (Vorgabe)
force selectbox setup de Auswahl erzwingen
give admin access to all installed apps setup de Admin Zugang zu allen installierten Anwendungen geben
give ldap root dn and password, if you need to create an instance specific admin user, user- or group-context setup de Tragen Sie das LDAP root DN und Passwort ein, wenn Sie einen Instanzspeziefischen Adminbenutzer oder Gruppen-Kontext benötigen
give ldap root dn and password, if you need to create an instance specific admin user, user- or group-context setup de Tragen Sie das LDAP root DN und Passwort ein, wenn Sie einen Instanzspezifischen Adminbenutzer oder Gruppen-Kontext benötigen
gives further options setup de gibt zusätzliche Optionen
go back setup de Zurück gehen
go to setup de Gehen zu
@ -326,7 +330,7 @@ http auth types (comma-separated) to use without login-page, eg. "ntlm" setup de
if no acl records for user or any group the user is a member of setup de Wenn es keinen ACL-Eintrag für einen Benutzer oder eine Gruppe, der er angehört gibt
if safe_mode is turned on, egw is not able to change certain settings on runtime, nor can we load any not yet loaded module. setup de Wenn safe_mode eingeschaltet ist, kann eGW verschiedene Einstellungen nicht mehr zur Laufzeit ändern, noch können wir nicht geladene Erweiterungen (php extensions) laden.
if the application has no defined tables, selecting upgrade should remedy the problem setup de Wenn die Anwendung keine definierten Tabellen hat, wählen Sie überarbeiten. Das Problem sollte damit behoben werden.
if using ads (active directory) authentication setup de Wenn Sie ADS (Active Directory) Authentifizierung benutzen
if using ads (active directory) setup de Wenn Sie ADS (Active Directory) benutzen
if using cas (central authentication service): setup de Wenn Sie CAS (Central Authentication Service) benutzen
if using ldap setup de Wenn Sie LDAP verwenden
if using ldap, do you want to manage homedirectory and loginshell attributes? setup de Wenn Sie LDAP verwenden, wollen Sie Benutzerverzeichnisse und Kommandointerpreter verwalten ?
@ -352,6 +356,7 @@ invalid argument '%1' !!! setup de Ungültiges Argument '%1' !!!
invalid ip address setup de Ungültige IP Adresse
invalid mcrypt algorithm/mode combination setup de Ungültige MCrypt Algorithmus/Modus Kombination
invalid password setup de Ungültiges Passwort
ip or url setup de IP oder URL
is broken setup de ist kaputt
is disabled setup de ist nicht aktiv
is in the webservers docroot setup de ist im Dokumentenverzeichnis (Documentroot) des Webservers
@ -364,14 +369,15 @@ ldap config setup de LDAP-Konfiguration
ldap default homedirectory prefix (e.g. /home for /home/username) setup de LDAP-Vorgabewert für Benutzerverzeichnisse (z.B. /home für /home/username)
ldap default shell (e.g. /bin/bash) setup de LDAP-Vorgabewert für Kommandointerpreter (shell) (z.B. /bin/bash)
ldap dn="%1" with %2 entries deleted. setup de LDAP dn="%1" mit %2 Einträgen gelöscht.
ldap encryption type setup de LDAP-Verschlüsselungstyp
ldap groups context setup de LDAP-Kontext für Gruppe
ldap host setup de LDAP-Host
ldap import setup de LDAP-Import
ldap root password setup de LDAP-Root-Passwort
ldap rootdn setup de LDAP rootdn
ldap encryption type setup de LDAP Verschlüsselungstyp
ldap groups context setup de LDAP Kontext für Gruppe
ldap host setup de LDAP Host
ldap import setup de LDAP Import
ldap root password setup de LDAP Root Passwort
ldap rootdn setup de LDAP Root DN
ldap search filter for accounts, default: "(uid=%user)", %domain=egw-domain setup de LDAP Suchfilter für Benutzerkonten, Vorgabe "(uid=%user)", %domain=eGW Domain
leave empty to keep current. setup de Leer lassen um das existierende Password zu behalten.
leave empty to use default setup de leer lassen um Standard zu benutzen
limit access setup de Zugang beschränken
limit access to setup to the following addresses, networks or hostnames (e.g. 127.0.0.1,10.1.1,myhost.dnydns.org) setup de Zugang zu Setup auf die folgenden IP Adressen, Netzwerke oder Hostnamen beschränken (z.B. 127.0.0.1,10.1.1,myhost.dnydns.org)
list availible values setup de Listen der verfügbaren Werte
@ -410,6 +416,7 @@ mount backup directory to %1 setup de Datensicherungsverzeichnis unter %1 mounte
multi-language support setup setup de Mehr-Sprachen Unterstützung einrichten
name of database setup de Name der Datenbank
name of db user egroupware uses to connect setup de Name des Datenbank-Benutzers den EGroupware verwendet
needs extra configuration on dc and webserver! setup de Benötigt extra Konfiguration auf Domain Controller und Webserver!
never setup de niemals
new setup de Neu
next run setup de nächste Ausführung
@ -439,6 +446,7 @@ one month setup de ein Monat
one week setup de eine Woche
only add languages that are not in the database already setup de Nur Sprachen hinzufügen, die noch nicht in der Datenbank sind
only add new phrases setup de Nur neue Begriffe hinzufügen
optional, if only authentication and anonymous search is enabled setup de optional, wenn nur Authentifizierung UND anonymes Suchen erlaubt ist
or setup de oder
or %1continue to the header admin%2 setup de oder %1mit der Headerverwaltung weiter machen%2
or http://webdav.domain.com (webdav) setup de oder http://webdav.domain.com (für WebDAV)
@ -495,6 +503,8 @@ rejected lines setup de Zurückgewiesene Zeilen
remove setup de Entfernen
remove all setup de Alle Entfernen
rename setup de Umbenennen
required to change passwords setup de erforderlich um Passwörter zu ändern
requires "reset password" privilege, to change passwords! setup de Benötigt "Passwort zurücksetzen" Recht, um Passwörter zu ändern!
requires reinstall or manual repair setup de Erfordert Neuinstallation oder manuelle Reparatur
requires upgrade setup de Erfordert Aktualisierung
resolve setup de Lösen
@ -647,6 +657,8 @@ use cookies to pass sessionid setup de SitzungsId in einem Cookie speichern
use mcrypt to crypt session-data: {off(default) | on},[mcrypt-init-vector(default randomly generated)],[mcrypt-version] setup de benutze mcrypt zur Verschlüsselung der Sitzungsdaten: {off(Vorgabe) | on},[mcrypt Initialisierung(Vorgabe ist zufällig erzeugt)],[mcrypt Version]
use persistent db connections: {on(default) | off} setup de benutze permanente Datenbankverbindung: {on(Vorgabe) | off}
use pure html compliant code (not fully working yet) setup de Vollständig HTML kompatiblen Code verwenden (nicht vollständig implementiert)
use space to separate multiple setup de Leerzeichen benutzen um mehrere anzugeben
use tls or ssl encryption setup de Benutze TLS oder SSL Verschlüsselung
user setup de Benutzer
user account prefix setup de Präfix für Benutzernamen
user for smtp-authentication (leave it empty if no auth required) setup de Benutzer für SMTP-Authentifizierung (leer lassen wenn keine notwendig ist)

View File

@ -41,6 +41,7 @@ admin first name setup en Admin first name
admin last name setup en Admin last name
admin password setup en Admin password
admin password to header manager setup en Admin password to header manager
admin user setup en Admin user
admin user for header manager setup en Admin user for header manager
admin username setup en Admin username
admins setup en Admins
@ -168,6 +169,7 @@ configuration user setup en Configuration user
configure now setup en Configure now
confirm to delete this backup? setup en Confirm to delete this backup?
contain setup en Contain
context to create users setup en Context to create users
continue setup en Continue
continue to the header admin setup en Continue to the Header Admin
convert setup en Convert
@ -243,9 +245,11 @@ domain-name setup en Domain name
don't change, if you already stored files! you will loose them! setup en Don't change, if you already stored files! You will loose them!
dont touch my data setup en Don't touch my data
download setup en Download
easiest way under win2008r2 is to add role "active directory certificate services" and reboot. setup en Easiest way under win2008r2 is to add role "Active Directory Certificate Services" and reboot.
edit current configuration setup en Edit current configuration
edit your existing header.inc.php setup en Edit your existing header.inc.php
edit your header.inc.php setup en Edit your header.inc.php
eg. "cn=users,dc=domain,dc=com" for ads domain "domain.com" setup en eg. "CN=Users,DC=domain,DC=com" for ADS domain "domain.com"
eg. /egroupware or http://domain.com/egroupware, default: %1 setup en eg. /egroupware or http://domain.com/egroupware, default: %1
egroupware administration manual setup en EGroupware administration manual
egroupware api needs a database (schema) update from version %1 to %2! setup en EGroupware API needs a database (schema) update from version %1 to %2!
@ -327,7 +331,7 @@ http auth types (comma-separated) to use without login-page, eg. "ntlm" setup en
if no acl records for user or any group the user is a member of setup en If no ACL records for user or any group the user is a member of
if safe_mode is turned on, egw is not able to change certain settings on runtime, nor can we load any not yet loaded module. setup en If safe_mode is turned on, eGW is not able to change certain settings on runtime, nor can we load any not yet loaded module.
if the application has no defined tables, selecting upgrade should remedy the problem setup en If the application has no defined tables, selecting upgrade should remedy the problem
if using ads (active directory) authentication setup en If using ADS (Active Directory) authentication
if using ads (active directory) setup en If using ADS (Active Directory) authentication
if using cas (central authentication service): setup en if using cas (Central Authentication Service):
if using ldap setup en If using LDAP
if using ldap, do you want to manage homedirectory and loginshell attributes? setup en If using LDAP, do you want to manage home directory and login shell attributes?
@ -353,6 +357,7 @@ invalid argument '%1' !!! setup en Invalid argument '%1' !
invalid ip address setup en Invalid IP address!
invalid mcrypt algorithm/mode combination setup en Invalid Mcrypt Algorithm/Mode combination
invalid password setup en Invalid password!
ip or url setup en IP or URL
is broken setup en is broken
is disabled setup en is disabled
is in the webservers docroot setup en is in the web servers docroot
@ -373,6 +378,7 @@ ldap root password setup en LDAP root password
ldap rootdn setup en LDAP rootdn
ldap search filter for accounts, default: "(uid=%user)", %domain=egw-domain setup en LDAP search filter for accounts, default: "(uid=%user)", %domain=eGW-domain
leave empty to keep current. setup en Leave empty to keep current.
leave empty to use default setup en leave empty to use default
limit access setup en Limit access
limit access to setup to the following addresses, networks or hostnames (e.g. 127.0.0.1,10.1.1,myhost.dnydns.org) setup en Limit access to setup to the following addresses, networks or host names (e.g. 127.0.0.1,10.1.1,myhost.dnydns.org)
list availible values setup en List available values
@ -411,6 +417,7 @@ mount backup directory to %1 setup en Mount backup directory to %1
multi-language support setup setup en Multi language support setup
name of database setup en Name of database
name of db user egroupware uses to connect setup en Name of db user EGroupware uses to connect
needs extra configuration on dc and webserver! setup en Needs extra configuration on DC and webserver!
never setup en Never
new setup en New
next run setup en Next run
@ -440,6 +447,7 @@ one month setup en One month
one week setup en One week
only add languages that are not in the database already setup en Only add languages that are not in the database already
only add new phrases setup en Only add new phrases
optional, if only authentication and anonymous search is enabled setup en optional, if only authentication AND anonymous search is enabled
or setup en or
or %1continue to the header admin%2 setup en or %1Continue to the Header Admin%2
or http://webdav.domain.com (webdav) setup en or http://webdav.domain.com (WebDAV)
@ -496,6 +504,8 @@ rejected lines setup en Rejected lines
remove setup en Remove
remove all setup en Remove all
rename setup en Rename
required to change passwords setup en required to change passwords
requires "reset password" privilege, to change passwords! setup en Requires "Reset Password" privilege, to change passwords!
requires reinstall or manual repair setup en Requires reinstall or manual repair
requires upgrade setup en Requires upgrade
resolve setup en Resolve
@ -648,6 +658,8 @@ use cookies to pass sessionid setup en Use cookies to pass session ID
use mcrypt to crypt session-data: {off(default) | on},[mcrypt-init-vector(default randomly generated)],[mcrypt-version] setup en Use mcrypt to crypt session-data: {off(default) | on},[mcrypt-init-vector(default randomly generated)],[mcrypt-version]
use persistent db connections: {on(default) | off} setup en Use persistent db connections: {on(default) | off}
use pure html compliant code (not fully working yet) setup en Use pure HTML compliant code
use space to separate multiple setup en use space to separate multiple
use tls or ssl encryption setup en Use TLS or SSL encryption
user setup en User
user account prefix setup en User account prefix
user for smtp-authentication (leave it empty if no auth required) setup en User for SMTP-authentication (leave it empty if no auth required)

View File

@ -317,7 +317,7 @@ http auth types (comma-separated) to use without login-page, eg. "ntlm" setup es
if no acl records for user or any group the user is a member of setup es-es Si no hay registros ACL ni grupo para el usuario, entonces es miembro de
if safe_mode is turned on, egw is not able to change certain settings on runtime, nor can we load any not yet loaded module. setup es-es Si está activado safe_mode, eGW no puede cambiar ciertas opciones en modo de ejecución, ni puede cargar ningún módulo que aún no sea cargable.
if the application has no defined tables, selecting upgrade should remedy the problem setup es-es Si la aplicación no ha definido tablas, seleccionando actualizar debería de remediar el problemas
if using ads (active directory) authentication setup es-es Si se usa identificación del Directorio Activo
if using ads (active directory) setup es-es Si se usa identificación del Directorio Activo
if using cas (central authentication service): setup es-es Si se usa CAS (Sistema de identificación centralizado):
if using ldap setup es-es Si usa LDAP
if using ldap, do you want to manage homedirectory and loginshell attributes? setup es-es Si usa LDAP ¿desea administrar los atributos del directorio personal y línea de comandos?

View File

@ -110,7 +110,7 @@ grant access setup et Luba Ligipääs
group setup et grupp
host information setup et Hosti informatsioon
hostname/ip of database server setup et Hostinimi/IP või andmebaasi server
if using ads (active directory) authentication setup et kui kasutad ADS (Active Directory) audentimist
if using ads (active directory) setup et kui kasutad ADS (Active Directory) audentimist
if using ldap setup et kui kasutad LDAP
image type selection order setup et Piltide tüübi sisestamise järjekord
import has been completed! setup et Importimine on lõpetatud!

View File

@ -214,7 +214,7 @@ however, the application may still work setup fa کاربرد ممکن از هن
if no acl records for user or any group the user is a member of setup fa اگر هیچ لیست حق دسترسی برای کاربر یا هیچ گروهی نباشد کابر عضوی خواهد بود از
if safe_mode is turned on, egw is not able to change certain settings on runtime, nor can we load any not yet loaded module. setup fa اگر safe_mode روشن باشد، گروه افزار نمی تواند تغییرات را در زمان اجرا اعمال کند و همچنین نمی توانیم پیمانه های بارگذاری نشده را بارگذاری کنیم
if the application has no defined tables, selecting upgrade should remedy the problem setup fa اگر کاربرد جداول تعریف شده ای نداشته باشد
if using ads (active directory) authentication setup fa اگر از تصدیق بر اساس ADS(Active Directory) استفاده میکنید
if using ads (active directory) setup fa اگر از تصدیق بر اساس ADS(Active Directory) استفاده میکنید
if using ldap setup fa اگر از LDAP استفاده می کنید
if using ldap, do you want to manage homedirectory and loginshell attributes? setup fa اگر از LDAP استفاده می کنید ، آیا می خواهید مشخصات پوشه خانه و پوسته ورود را تنظیم نمائید؟
if you did not receive any errors, your applications have been setup fa اگر شما هیچ پیام خطائی دریافت نکردید کاربرد شما

View File

@ -281,7 +281,7 @@ however, the application may still work setup fi Sovellus voi toimia tästä huo
if no acl records for user or any group the user is a member of setup fi Jos käyttäjällä tai käyttäjän ryhmillä ei ole ACL-tietueita, käyttäjä on tämän ryhmän jäsen:
if safe_mode is turned on, egw is not able to change certain settings on runtime, nor can we load any not yet loaded module. setup fi Jos safe_mode on päällä, eGW ei voi muuttaa kaikkia asetuksia ajon aikana, eikä ladata uusia moduuleita.
if the application has no defined tables, selecting upgrade should remedy the problem setup fi Jos sovelluksella ei ole määriteltyjä tauluja, päivittämisen pitäisi korjata ongelma
if using ads (active directory) authentication setup fi Jos käytetään ADS (Active Directory) -tunnistusta
if using ads (active directory) setup fi Jos käytetään ADS (Active Directory) -tunnistusta
if using cas (central authentication service): setup fi Jos käytetään CAS (Central Authentication Service):
if using ldap setup fi Jos käytetään LDAP-tunnistusta
if using ldap, do you want to manage homedirectory and loginshell attributes? setup fi Jos käytät LDAP-tunnistusta, haluatko hallita kotihakemisto- ja shellattribuutteja?

View File

@ -279,7 +279,7 @@ however, the application may still work setup fr Malgré tout l'application pour
if no acl records for user or any group the user is a member of setup fr Si aucun enregistrement d'ACL pour un utilisateur ou groupe l'utilisateur est un membre de
if safe_mode is turned on, egw is not able to change certain settings on runtime, nor can we load any not yet loaded module. setup fr Si safe_mode est activé, eGroupWare sera incapable de modifier certaines options ou d'activer certains modules.
if the application has no defined tables, selecting upgrade should remedy the problem setup fr Si l'application n'a pas défini de tables, choisir mise à jour devrait résoudre le problème
if using ads (active directory) authentication setup fr Si vous utilisez l'authentification ADS (Active Directory)
if using ads (active directory) setup fr Si vous utilisez l'authentification ADS (Active Directory)
if using cas (central authentication service): setup fr Si vous utilisez l'authentification CAS (Central Authentication Service) :
if using ldap setup fr Si vous utilisez LDAP
if using ldap, do you want to manage homedirectory and loginshell attributes? setup fr Si vous utilisez LDAP, voulez-vous gérer les attributs répertoire d'accueil et shell de connexion?

View File

@ -183,7 +183,7 @@ hostname/ip of database server setup lv Datubāzes zrvera hostvārds/IP
hour (0-24) setup lv stundas (0-24)
however, the application may still work setup lv Kaut gan aplikācija joprojām var strādāt
if no acl records for user or any group the user is a member of setup lv Ja nav ACL ierakstu lietotājam vai kādai grupai, lietotājs pieder
if using ads (active directory) authentication setup lv Ja lieto ADS (aktīvā direktorija) autentifikāciju
if using ads (active directory) setup lv Ja lieto ADS (aktīvā direktorija) autentifikāciju
if using ldap setup lv Ja lieto LDAP
if using ldap, do you want to manage homedirectory and loginshell attributes? setup lv Ja lieto LDAP, vai vēlies pārvaldīt mājasdirektoriju un pieteikuma ailes atribūtus?
if you did not receive any errors, your applications have been setup lv Ja nesaņēmi kļūdu paziņojumus, tava aplikācija ir

View File

@ -296,7 +296,7 @@ http auth types (comma-separated) to use without login-page, eg. "ntlm" setup nl
if no acl records for user or any group the user is a member of setup nl Als er ACL records voor de gebruiker of een willekeurige groep zijn is de gebruiker lid van
if safe_mode is turned on, egw is not able to change certain settings on runtime, nor can we load any not yet loaded module. setup nl Indien safe_mode ingeschakeld is kan eGW bepaalde instellingen niet tijdens runtime wijzen, bovendien kunnen we geen enkele nog niet geladen module laden.
if the application has no defined tables, selecting upgrade should remedy the problem setup nl Indien de toepassing geen tabellen heeft gedefinieerd is het kiezen voor upgrade de oplossing voor dit problemen
if using ads (active directory) authentication setup nl Indien ADS (Active Directory) authenticatie gebruikt wordt
if using ads (active directory) setup nl Indien ADS (Active Directory) authenticatie gebruikt wordt
if using cas (central authentication service): setup nl indien cas gebruikt wordt (Centrale Authenticatie Service)
if using ldap setup nl Indien LDAP gebruikt wordt
if using ldap, do you want to manage homedirectory and loginshell attributes? setup nl Indien LDAP gebruikt wordt, wilt u dan de homedirectory en loginshell attributen beheren?

View File

@ -199,7 +199,7 @@ however, the application may still work setup no Det kan hende programmet fortsa
if no acl records for user or any group the user is a member of setup no Om inga åtkomstregler finns för användaren eller de grupper användaren är medlem av
if safe_mode is turned on, egw is not able to change certain settings on runtime, nor can we load any not yet loaded module. setup no Om Safe Mode är aktiverat kan inte eGW ändra vissa inställningar medans den kör, eller ladda en modul som inte redan är laddad.
if the application has no defined tables, selecting upgrade should remedy the problem setup no Om applikationen saknar definerade tabeller bör du välja att uppgradera den.
if using ads (active directory) authentication setup no Dersom det benyttes ADS (Active Directory) autentisering.
if using ads (active directory) setup no Dersom det benyttes ADS (Active Directory) autentisering.
if using ldap setup no Om LDAP används
if using ldap, do you want to manage homedirectory and loginshell attributes? setup no Om LDAP används, vill du hantera attribut för hemktalog och programskal?
if you did not receive any errors, your applications have been setup no Om du inte såg några fel så har dina applikationer blivit

View File

@ -314,7 +314,7 @@ http auth types (comma-separated) to use without login-page, eg. "ntlm" setup pl
if no acl records for user or any group the user is a member of setup pl Jeśli brak uprawnień dostępu (ACL) dla użytkownika lub jakiejkolwiek grupy, której użytkownik jest członkiem
if safe_mode is turned on, egw is not able to change certain settings on runtime, nor can we load any not yet loaded module. setup pl Jeśli tryb bezpieczny (safe_mode) jest aktywny, eGW nie może zmieniać różnych ustawień poprzez runtime ani nie można załadować do tej pory niezaładowanych modułów.
if the application has no defined tables, selecting upgrade should remedy the problem setup pl Jeśli aplikacja nie ma zdefiniowanych tabel, wybór aktualizacji rozwiąże problem.
if using ads (active directory) authentication setup pl Jeśli używana autoryzacja ADS (Active Directory)
if using ads (active directory) setup pl Jeśli używana autoryzacja ADS (Active Directory)
if using cas (central authentication service): setup pl Jeśli używany CAS (Central Authentication Service):
if using ldap setup pl Jeśli używany LDAP
if using ldap, do you want to manage homedirectory and loginshell attributes? setup pl Jeżeli używasz LDAP, czy chciałbyś administrować katalogiem domowym i atrybutami powłoki?

View File

@ -289,7 +289,7 @@ http auth types (comma-separated) to use without login-page, eg. "ntlm" setup pt
if no acl records for user or any group the user is a member of setup pt-br Caso não exista registro de permissões ou grupo para o usuário ele é membro do
if safe_mode is turned on, egw is not able to change certain settings on runtime, nor can we load any not yet loaded module. setup pt-br Se o modo de segurança estiver ligado, o eGroupware não será capaz de modificar automáticamente determinados valores de configuração, não será possível carregar módulos que ainda não estejam carregados.
if the application has no defined tables, selecting upgrade should remedy the problem setup pt-br Se o aplicativo não têm tabelas definidas, selecionar atualizar deve resolver o problema
if using ads (active directory) authentication setup pt-br Se estiver usando autenticação por ADS (Active Directory)
if using ads (active directory) setup pt-br Se estiver usando autenticação por ADS (Active Directory)
if using ldap setup pt-br Se estiver usando LDAP
if using ldap, do you want to manage homedirectory and loginshell attributes? setup pt-br Se estiver usando LDAP, você deseja definir atributos de diretório base e do interpretador de comandos?
if you did not receive any errors, your applications have been setup pt-br Se não foi exibido nenhum erro, suas aplicações foram

View File

@ -212,7 +212,7 @@ however, the application may still work setup pt No entanto, a aplicação pode
if no acl records for user or any group the user is a member of setup pt Se não existirem registos ACL do utilizador ou grupo, o utilizador é um membro de
if safe_mode is turned on, egw is not able to change certain settings on runtime, nor can we load any not yet loaded module. setup pt Se o modo de segurança estiver activo, o eGroupWare não pode alterar determinadas configurações em execução, nem pode carregar módulos não carregados.
if the application has no defined tables, selecting upgrade should remedy the problem setup pt Se a aplicação não tiver tabelas definidas, actualizar deve resolver o problema
if using ads (active directory) authentication setup pt Se estiver a utilizar a autenticação ADS (Directoria Activa)
if using ads (active directory) setup pt Se estiver a utilizar a autenticação ADS (Directoria Activa)
if using ldap setup pt Se estiver a utilizar LDAP
if using ldap, do you want to manage homedirectory and loginshell attributes? setup pt Se estiver a utilizar LDAP, deseja definir atributos da directoria principal e atributos da Shell de acesso ?
if you did not receive any errors, your applications have been setup pt Se não foi exibido nenhum erro, as suas aplicações foram

View File

@ -284,7 +284,7 @@ http auth types (comma-separated) to use without login-page, eg. "ntlm" setup ru
if no acl records for user or any group the user is a member of setup ru Если нет записей ACL для пользователя или группы, пользователь входит в
if safe_mode is turned on, egw is not able to change certain settings on runtime, nor can we load any not yet loaded module. setup ru Если безопасный режим включен, у eGW нет возможностии менять некоторые настройки при запуске так же как и нет возможности запускать любые еще не загруженные модули.
if the application has no defined tables, selecting upgrade should remedy the problem setup ru Если приложение не имеет заранее определенных таблиц, выбор модернизации скорее всего вызовет ряд проблем
if using ads (active directory) authentication setup ru Используя ADS (Active Directory) идентификацию
if using ads (active directory) setup ru Используя ADS (Active Directory) идентификацию
if using ldap setup ru Используя LDAP
if using ldap, do you want to manage homedirectory and loginshell attributes? setup ru При использовании LDAP,желаете ли вы управлять атрибутами домашних папок и параметрами входа?
if you did not receive any errors, your applications have been setup ru Если вы не получили уведомлений об ошибках,ваше приложение успешно

View File

@ -313,7 +313,7 @@ http auth types (comma-separated) to use without login-page, eg. "ntlm" setup sk
if no acl records for user or any group the user is a member of setup sk Ak pre používateľa neexistujú ACL záznamy, používateľom je členom
if safe_mode is turned on, egw is not able to change certain settings on runtime, nor can we load any not yet loaded module. setup sk Ak je bezpečný režim zapnutý, eGW nedokáže zmeniť niektoré veci za behu, ani nahrať nejaký nenahratý modul.
if the application has no defined tables, selecting upgrade should remedy the problem setup sk Ak aplikácia nemá tabuľky definícií, voľba "aktualizácia" by mala problém vyriešiť
if using ads (active directory) authentication setup sk Ak používate ADS (ActiveDirectory) autentifikáciu
if using ads (active directory) setup sk Ak používate ADS (ActiveDirectory) autentifikáciu
if using cas (central authentication service): setup sk Ak používate cas (Centrálnu Autentifikačnú Službu):
if using ldap setup sk Ak používate LDAP
if using ldap, do you want to manage homedirectory and loginshell attributes? setup sk Ak používate LDAP, chcete spravovať domovský adresár a atribúty login shell?

View File

@ -295,7 +295,7 @@ http auth types (comma-separated) to use without login-page, eg. "ntlm" setup sl
if no acl records for user or any group the user is a member of setup sl Če ni ACL zapisov za uporabnika ali katerokoli skupino, katere član je
if safe_mode is turned on, egw is not able to change certain settings on runtime, nor can we load any not yet loaded module. setup sl Če je vključen način "safe_mode", eGW med delovanjem ne more spremeniti nekaterih nastavitev niti ne more naložiti novih modulov.
if the application has no defined tables, selecting upgrade should remedy the problem setup sl Če aplikacija nima definiranih tabel, potem bi nadgrajevanje moralo rešiti težave.
if using ads (active directory) authentication setup sl Če uporabljate ADS (Aktivni Direktorij ) overovljenje
if using ads (active directory) setup sl Če uporabljate ADS (Aktivni Direktorij ) overovljenje
if using cas (central authentication service): setup sl Če uporabljate cas (Central Authentication Service):
if using ldap setup sl Če uporabljate LDAP
if using ldap, do you want to manage homedirectory and loginshell attributes? setup sl Če uporabljate LDAP, ali želite upravljati domači direktorij in lastnosti prijavne lupine?

View File

@ -268,7 +268,7 @@ however, the application may still work setup sv Applikationen kanske ändå fun
if no acl records for user or any group the user is a member of setup sv Om inga åtkomst regler finns för användaren eller de grupper användaren är medlem av
if safe_mode is turned on, egw is not able to change certain settings on runtime, nor can we load any not yet loaded module. setup sv Om Safe Mode är aktiverat kan inte eGW ändra vissa inställningar medans den kör, eller ladda en modul som inte redan är laddad.
if the application has no defined tables, selecting upgrade should remedy the problem setup sv Om applikationen saknar definerade tabeller bör du välja att uppgradera den.
if using ads (active directory) authentication setup sv Om AD (Active Directory) autenticering används
if using ads (active directory) setup sv Om AD (Active Directory) autenticering används
if using ldap setup sv Om LDAP används
if using ldap, do you want to manage homedirectory and loginshell attributes? setup sv Om LDAP används, vill du hantera attribut för hemktalog och programskal?
if you did not receive any errors, your applications have been setup sv Om du inte såg några fel så har dina applikationer blivit

View File

@ -276,7 +276,7 @@
<select name="newsettings[account_repository]">
<option value="sql"{selected_account_repository_sql}>SQL</option>
<option value="ldap"{selected_account_repository_ldap}>LDAP</option>
<!--<option value="contacts"{selected_account_repository_contacts}>Contacts - EXPERIMENTAL</option>-->
<option value="ads"{selected_account_repository_ads}>Active Directory</option>
</select>
</td>
</tr>
@ -396,7 +396,7 @@
</td>
</tr>
<tr class="row_on">
<tr class="row_off">
<td colspan="2">&nbsp;</td>
</tr>
@ -405,8 +405,11 @@
</tr>
<tr class="row_on">
<td>{lang_LDAP_host}:</td>
<td><input name="newsettings[ldap_host]" value="{value_ldap_host}" /></td>
<td>
{lang_LDAP_host} {lang_IP_or_URL}: (ldap|ldaps|tls)://IP[:port]/<br/>
({lang_use_space_to_separate_multiple}):
</td>
<td><input name="newsettings[ldap_host]" value="{value_ldap_host}" size="40" /></td>
</tr>
<tr class="row_off">
@ -479,11 +482,65 @@
</td>
</tr>
<tr class="row_off">
<td colspan="2">&nbsp;</td>
</tr>
<tr class="th">
<td colspan="2"><b>{lang_If_using_ADS_(Active_Directory)}:</b></td>
</tr>
<tr class="row_off">
<td>{lang_Host/IP_Domain_controler} ({lang_use_space_to_separate_multiple}):</td>
<td><input name="newsettings[ads_host]" value="{value_ads_host}" size="40" /></td>
</tr>
<tr class="row_on">
<td>{lang_Domain_name}:</td>
<td><input name="newsettings[ads_domain]" value="{value_ads_domain}" size="40" /></td>
</tr>
<tr class="row_off">
<td>
{lang_Admin_user}:<br/>
({lang_optional,_if_only_authentication_AND_anonymous_search_is_enabled})<br/>
{lang_Requires_"Reset_Password"_privilege,_to_change_passwords!}
</td>
<td><input name="newsettings[ads_admin_user]" value="{value_ads_admin_user}" size="40" /></td>
</tr>
<tr class="row_on">
<td>{lang_Password}:</td>
<td><input type="password" name="newsettings[ads_admin_passwd]" value="{value_ads_admin_passwd}" size="40" /></td>
</tr>
<tr class="row_off">
<td>
{lang_Use_TLS_or_SSL_encryption} ({lang_required_to_change_passwords}):<br/>
{lang_Needs_extra_configuration_on_DC_and_webserver!}<br/>
({lang_Easiest_way_under_win2008r2_is_to_add_role_"Active_Directory_Certificate_Services"_and_reboot.})
</td>
<td>
<select name="newsettings[ads_connection]">
<option value="">{lang_No}</option>
<option value="tls"{selected_ads_connection_tls}>TLS</option>
<option value="ssl"{selected_ads_connection_ssl}>SSL</option>
</select>
</td>
</tr>
<tr class="row_on">
<td>
{lang_Context_to_create_users}:<br/>
{lang_eg._"CN=Users,DC=domain,DC=com"_for_ADS_domain_"domain.com"}<br/>
({lang_leave_empty_to_use_default})
</td>
<td><input name="newsettings[ads_context]" value="{value_ads_context}" size="80" /></td>
</tr>
<tr class="row_off">
<td colspan="2">&nbsp;</td>
</tr>
<tr class="th">
<td colspan="2"><b>{lang_If_using_CAS_(Central_Authentication_Service):}</b></td>
</tr>
<tr class="row_off">
<tr class="row_on">
<td>{lang_CAS_server_host_name:<br />Example:_sso-cas.univ-rennes1.fr}</td>
<td><input name="newsettings[cas_server_host_name]" value="{value_cas_server_host_name}" size="40" /></td>
</tr>
@ -493,7 +550,7 @@
<td><input name="newsettings[cas_server_port]" value="{value_cas_server_port}" size="40" /></td>
</tr>
<tr class="row_off">
<tr class="row_on">
<td>{lang_CAS_server_uri:}</td>
<td><input name="newsettings[cas_server_uri]" value="{value_cas_server_uri}" size="40" /></td>
</tr>
@ -508,7 +565,7 @@
</td>
</tr>
<tr class="row_off">
<tr class="row_on">
<td>{lang_SSL_validation:}</td>
<td>
<select name="newsettings[cas_ssl_validation]">
@ -528,18 +585,6 @@
<td colspan="2">&nbsp;</td>
</tr>
<tr class="th">
<td colspan="2"><b>{lang_If_using_ADS_(Active_Directory)_authentication}:</b></td>
</tr>
<tr class="row_off">
<td>{lang_Host/IP_Domain_controler}:</td>
<td><input name="newsettings[ads_host]" value="{value_ads_host}" size="40" /></td>
</tr>
<tr class="row_on">
<td>{lang_Domain_name}:</td>
<td><input name="newsettings[ads_domain]" value="{value_ads_domain}" size="40" /></td>
</tr>
<tr class="row_off">
<td colspan="2">&nbsp;</td>
</tr>