mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-07 08:34:29 +01:00
move all tables to new api and update api to 16.1
This commit is contained in:
parent
adb748d6e7
commit
2baf654e14
@ -1,19 +0,0 @@
|
||||
<?php
|
||||
/**************************************************************************\
|
||||
* eGroupWare *
|
||||
* http://www.egroupware.org *
|
||||
* Written by Mark Peters <skeeter@phpgroupware.org> *
|
||||
* -------------------------------------------- *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
\**************************************************************************/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
if((int)$GLOBALS['hook_values']['account_id'] > 0)
|
||||
{
|
||||
$GLOBALS['egw']->accounts->delete((int)$GLOBALS['hook_values']['account_id']);
|
||||
$GLOBALS['egw']->acl->delete_account((int)$GLOBALS['hook_values']['account_id']);
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
<?php
|
||||
/**************************************************************************\
|
||||
* eGroupWare - Admin *
|
||||
* http://www.egroupware.org *
|
||||
* This application written by Miles Lott <milos@groupwhere.org> *
|
||||
* This file is ported to the topmenu hook by Pim Snel pim@lingewoud.nl *
|
||||
* -------------------------------------------- *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
\**************************************************************************/
|
||||
|
||||
/* $Id: hook_after_navbar.inc.php 20071 2005-12-01 20:21:16Z ralfbecker $ */
|
||||
|
||||
/* Check currentapp and API upgrade status */
|
||||
if( (isset($GLOBALS['egw_info']['server']['checkappversions']) && $GLOBALS['egw_info']['server']['checkappversions']))
|
||||
{
|
||||
if((isset($GLOBALS['egw_info']['user']['apps']['admin']) &&
|
||||
$GLOBALS['egw_info']['user']['apps']['admin']) ||
|
||||
$GLOBALS['egw_info']['server']['checkappversions'] == 'All')
|
||||
{
|
||||
$_returnhtml = array();
|
||||
$app_name = $GLOBALS['egw_info']['flags']['currentapp'];
|
||||
$GLOBALS['egw']->db->query("SELECT app_name,app_version FROM egw_applications WHERE app_name='$app_name' OR app_name='phpgwapi'",__LINE__,__FILE__);
|
||||
while($GLOBALS['egw']->db->next_record())
|
||||
{
|
||||
$_db_version = $GLOBALS['egw']->db->f('app_version');
|
||||
$app_name = $GLOBALS['egw']->db->f('app_name');
|
||||
$_versionfile = $GLOBALS['egw']->common->get_app_dir($app_name) . '/setup/setup.inc.php';
|
||||
if(file_exists($_versionfile))
|
||||
{
|
||||
include($_versionfile);
|
||||
$_file_version = $setup_info[$app_name]['version'];
|
||||
unset($setup_info);
|
||||
|
||||
if(amorethanb($_file_version, $_db_version))
|
||||
{
|
||||
if($app_name == 'phpgwapi' )
|
||||
{
|
||||
$_returnhtml[$app_name] = lang('The API requires an upgrade');
|
||||
}
|
||||
else
|
||||
{
|
||||
$_returnhtml[$app_name] = lang('This application requires an upgrade') . ": \n <br />" . lang('Please run setup to become current') . '.' . "\n";
|
||||
}
|
||||
}
|
||||
unset($_file_version);
|
||||
}
|
||||
unset($_db_version);
|
||||
unset($_versionfile);
|
||||
}
|
||||
|
||||
if(count($_returnhtml)>0)
|
||||
{
|
||||
$icon_newmsg = $GLOBALS['egw']->common->image('admin','navbar18');
|
||||
//$link_inbox = $GLOBALS['egw']->link('/index.php','menuaction=messenger.uimessenger.inbox');
|
||||
$lang_msg = '<p style="text-align: center;">'.implode('<br />',$_returnhtml)."</p>\n";
|
||||
|
||||
$GLOBALS['egw']->framework->topmenu_info_icon('admin_new_msg',$icon_newmsg,'',true,$lang_msg);
|
||||
}
|
||||
|
||||
unset($_returnhtml);
|
||||
unset($_html);
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
/* Basic information about this app */
|
||||
$setup_info['api']['name'] = 'api';
|
||||
$setup_info['api']['title'] = 'EGroupware API';
|
||||
$setup_info['api']['version'] = '14.3.907';
|
||||
$setup_info['api']['version'] = '16.1';
|
||||
$setup_info['api']['versions']['current_header'] = '1.29';
|
||||
$setup_info['api']['enable'] = 3;
|
||||
$setup_info['api']['app_order'] = 1;
|
||||
@ -22,7 +22,7 @@ $setup_info['api']['maintainer'] = $setup_info['api']['author'] = array(
|
||||
'email' => 'egroupware-developers@lists.sourceforge.net',
|
||||
);
|
||||
|
||||
/* The tables this app creates
|
||||
// The tables this app creates
|
||||
$setup_info['api']['tables'][] = 'egw_config';
|
||||
$setup_info['api']['tables'][] = 'egw_applications';
|
||||
$setup_info['api']['tables'][] = 'egw_acl';
|
||||
@ -31,7 +31,6 @@ $setup_info['api']['tables'][] = 'egw_preferences';
|
||||
$setup_info['api']['tables'][] = 'egw_access_log';
|
||||
$setup_info['api']['tables'][] = 'egw_languages';
|
||||
$setup_info['api']['tables'][] = 'egw_lang';
|
||||
$setup_info['api']['tables'][] = 'egw_nextid';
|
||||
$setup_info['api']['tables'][] = 'egw_categories';
|
||||
$setup_info['api']['tables'][] = 'egw_history_log';
|
||||
$setup_info['api']['tables'][] = 'egw_async';
|
||||
@ -45,7 +44,13 @@ $setup_info['api']['tables'][] = 'egw_locks';
|
||||
$setup_info['api']['tables'][] = 'egw_sqlfs_props';
|
||||
$setup_info['api']['tables'][] = 'egw_customfields';
|
||||
$setup_info['api']['tables'][] = 'egw_sharing';
|
||||
*/
|
||||
$setup_info['api']['tables'][] = 'egw_mailaccounts';
|
||||
$setup_info['api']['tables'][] = 'egw_ea_accounts';
|
||||
$setup_info['api']['tables'][] = 'egw_ea_credentials';
|
||||
$setup_info['api']['tables'][] = 'egw_ea_identities';
|
||||
$setup_info['api']['tables'][] = 'egw_ea_valid';
|
||||
$setup_info['api']['tables'][] = 'egw_ea_notifications';
|
||||
|
||||
// hooks used by vfs_home_hooks to manage user- and group-directories for the new stream based VFS
|
||||
$setup_info['api']['hooks']['addaccount'] = array('EGroupware\\Api\\Vfs\\Hooks::addAccount', 'EGroupware\\Api\\Mail\\Hooks::addaccount');
|
||||
$setup_info['api']['hooks']['deleteaccount'] = array('EGroupware\\Api\\Vfs\\Hooks::deleteAccount', 'EGroupware\\Api\\Mail\\Hooks::deleteaccount');
|
||||
@ -59,52 +64,52 @@ $setup_info['api']['hooks']['changepassword'] = 'EGroupware\\Api\\Mail\\Hooks::c
|
||||
$setup_info['api']['check_install'] = array(
|
||||
'' => array(
|
||||
'func' => 'pear_check',
|
||||
'from' => 'EMailAdmin',
|
||||
'from' => 'Api/Mail',
|
||||
),
|
||||
'pear.horde.org/Horde_Imap_Client' => array(
|
||||
'func' => 'pear_check',
|
||||
'from' => 'EMailAdmin',
|
||||
'from' => 'Api/Mail',
|
||||
'version' => '2.24.2',
|
||||
),
|
||||
'pear.horde.org/Horde_Nls' => array(
|
||||
'func' => 'pear_check',
|
||||
'from' => 'EMailAdmin',
|
||||
'from' => 'Api/Mail',
|
||||
'version' => '2.0.3',
|
||||
),
|
||||
'pear.horde.org/Horde_Mail' => array(
|
||||
'func' => 'pear_check',
|
||||
'from' => 'EMailAdmin',
|
||||
'from' => 'Api/Mail',
|
||||
'version' => '2.1.2',
|
||||
),
|
||||
'pear.horde.org/Horde_Smtp' => array(
|
||||
'func' => 'pear_check',
|
||||
'from' => 'EMailAdmin',
|
||||
'from' => 'Api/Mail',
|
||||
'version' => '1.3.0',
|
||||
),
|
||||
'pear.horde.org/Horde_ManageSieve' => array(
|
||||
'func' => 'pear_check',
|
||||
'from' => 'EMailAdmin',
|
||||
'from' => 'Api/Mail',
|
||||
'version' => '1.0.1',
|
||||
),
|
||||
// next 4 are required for TNEF support
|
||||
'pear.horde.org/Horde_Compress' => array(
|
||||
'func' => 'pear_check',
|
||||
'from' => 'EMailAdmin',
|
||||
'from' => 'Api/Mail',
|
||||
'version' => '2.0.8',
|
||||
),
|
||||
'pear.horde.org/Horde_Icalendar' => array(
|
||||
'func' => 'pear_check',
|
||||
'from' => 'EMailAdmin',
|
||||
'from' => 'Api/Mail',
|
||||
'version' => '2.0.0',
|
||||
),
|
||||
'pear.horde.org/Horde_Mapi' => array(
|
||||
'func' => 'pear_check',
|
||||
'from' => 'EMailAdmin',
|
||||
'from' => 'Api/Mail',
|
||||
'version' => '1.0.0',
|
||||
),
|
||||
'bcmath' => array(
|
||||
'func' => 'extension_check',
|
||||
'from' => 'EMailAdmin',
|
||||
'from' => 'Api/Mail',
|
||||
),
|
||||
);
|
||||
|
||||
|
511
api/setup/tables_current.inc.php
Normal file
511
api/setup/tables_current.inc.php
Normal file
@ -0,0 +1,511 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware - API Setup
|
||||
*
|
||||
* Current DB schema
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @package api
|
||||
* @subpackage setup
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
$phpgw_baseline = array(
|
||||
'egw_config' => array(
|
||||
'fd' => array(
|
||||
'config_app' => array('type' => 'ascii','precision' => '16','nullable' => False),
|
||||
'config_name' => array('type' => 'ascii','precision' => '32','nullable' => False),
|
||||
'config_value' => array('type' => 'text')
|
||||
),
|
||||
'pk' => array('config_app','config_name'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_applications' => array(
|
||||
'fd' => array(
|
||||
'app_id' => array('type' => 'auto','precision' => '4','nullable' => False),
|
||||
'app_name' => array('type' => 'ascii','precision' => '16','nullable' => False),
|
||||
'app_enabled' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'app_order' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'app_tables' => array('type' => 'ascii','precision' => '8192','nullable' => False),
|
||||
'app_version' => array('type' => 'ascii','precision' => '20','nullable' => False,'default' => '0.0'),
|
||||
'app_icon' => array('type' => 'ascii','precision' => '32'),
|
||||
'app_icon_app' => array('type' => 'ascii','precision' => '16'),
|
||||
'app_index' => array('type' => 'ascii','precision' => '64')
|
||||
),
|
||||
'pk' => array('app_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(array('app_enabled','app_order')),
|
||||
'uc' => array('app_name')
|
||||
),
|
||||
'egw_acl' => array(
|
||||
'fd' => array(
|
||||
'acl_appname' => array('type' => 'ascii','precision' => '16','nullable' => False),
|
||||
'acl_location' => array('type' => 'ascii','meta' => 'account','precision' => '16','nullable' => False),
|
||||
'acl_account' => array('type' => 'int','meta' => 'account','precision' => '4','nullable' => False),
|
||||
'acl_rights' => array('type' => 'int','precision' => '4'),
|
||||
'acl_id' => array('type' => 'auto','nullable' => False)
|
||||
),
|
||||
'pk' => array('acl_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array('acl_account',array('acl_location','acl_account'),array('acl_appname','acl_account')),
|
||||
'uc' => array(array('acl_appname','acl_location','acl_account'))
|
||||
),
|
||||
'egw_accounts' => array(
|
||||
'fd' => array(
|
||||
'account_id' => array('type' => 'auto','meta' => 'account-abs','nullable' => False),
|
||||
'account_lid' => array('type' => 'varchar','precision' => '64','nullable' => False),
|
||||
'account_pwd' => array('type' => 'varchar','precision' => '128','nullable' => False),
|
||||
'account_lastlogin' => array('type' => 'int','precision' => '4'),
|
||||
'account_lastloginfrom' => array('type' => 'ascii','precision' => '48','comment' => 'ip'),
|
||||
'account_lastpwd_change' => array('type' => 'int','precision' => '4'),
|
||||
'account_status' => array('type' => 'char','precision' => '1','nullable' => False,'default' => 'A'),
|
||||
'account_expires' => array('type' => 'int','precision' => '4'),
|
||||
'account_type' => array('type' => 'char','precision' => '1'),
|
||||
'account_primary_group' => array('type' => 'int','meta' => 'group','precision' => '4','nullable' => False,'default' => '0'),
|
||||
'account_description' => array('type' => 'varchar','precision' => '255','comment' => 'group description')
|
||||
),
|
||||
'pk' => array('account_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array('account_lid')
|
||||
),
|
||||
'egw_preferences' => array(
|
||||
'fd' => array(
|
||||
'preference_owner' => array('type' => 'int','meta' => 'account-prefs','precision' => '4','nullable' => False),
|
||||
'preference_app' => array('type' => 'ascii','precision' => '16','nullable' => False),
|
||||
'preference_value' => array('type' => 'text','nullable' => False),
|
||||
'preference_id' => array('type' => 'auto','nullable' => False)
|
||||
),
|
||||
'pk' => array('preference_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array(array('preference_owner','preference_app'))
|
||||
),
|
||||
'egw_access_log' => array(
|
||||
'fd' => array(
|
||||
'sessionid' => array('type' => 'auto','nullable' => False,'comment' => 'primary key'),
|
||||
'loginid' => array('type' => 'varchar','precision' => '64','nullable' => False,'comment' => 'username used to login'),
|
||||
'ip' => array('type' => 'ascii','precision' => '48','nullable' => False,'comment' => 'ip of user'),
|
||||
'li' => array('type' => 'int','meta' => 'timestamp','precision' => '8','nullable' => False,'comment' => 'TS if login'),
|
||||
'lo' => array('type' => 'int','meta' => 'timestamp','precision' => '8','comment' => 'TD of logout'),
|
||||
'account_id' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False,'default' => '0','comment' => 'numerical account id'),
|
||||
'session_dla' => array('type' => 'int','meta' => 'timestamp','precision' => '8','comment' => 'TS of last user action'),
|
||||
'session_action' => array('type' => 'ascii','precision' => '64','comment' => 'menuaction or path of last user action'),
|
||||
'session_php' => array('type' => 'ascii','precision' => '64','nullable' => False,'comment' => 'php session-id or error-message'),
|
||||
'notification_heartbeat' => array('type' => 'int','meta' => 'timestamp','precision' => '8','comment' => 'TS of last notification request'),
|
||||
'user_agent' => array('type' => 'ascii','precision' => '255','comment' => 'User-agent of browser/device')
|
||||
),
|
||||
'pk' => array('sessionid'),
|
||||
'fk' => array(),
|
||||
'ix' => array('li','lo','session_dla','session_php','notification_heartbeat',array('account_id','ip','li'),array('account_id','loginid','li')),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_languages' => array(
|
||||
'fd' => array(
|
||||
'lang_id' => array('type' => 'ascii','precision' => '5','nullable' => False),
|
||||
'lang_name' => array('type' => 'varchar','precision' => '50','nullable' => False)
|
||||
),
|
||||
'pk' => array('lang_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_lang' => array(
|
||||
'fd' => array(
|
||||
'lang' => array('type' => 'varchar','precision' => '5','nullable' => False,'default' => ''),
|
||||
'app_name' => array('type' => 'ascii','precision' => '16','nullable' => False,'default' => 'common'),
|
||||
'message_id' => array('type' => 'ascii','precision' => '128','nullable' => False,'default' => ''),
|
||||
'content' => array('type' => 'varchar','precision' => '8192'),
|
||||
'lang_id' => array('type' => 'auto','nullable' => False)
|
||||
),
|
||||
'pk' => array('lang_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array(array('lang','app_name','message_id'))
|
||||
),
|
||||
'egw_categories' => array(
|
||||
'fd' => array(
|
||||
'cat_id' => array('type' => 'auto','meta' => 'category','precision' => '4','nullable' => False),
|
||||
'cat_main' => array('type' => 'int','meta' => 'category','precision' => '4','nullable' => False,'default' => '0'),
|
||||
'cat_parent' => array('type' => 'int','meta' => 'category','precision' => '4','nullable' => False,'default' => '0'),
|
||||
'cat_level' => array('type' => 'int','precision' => '2','nullable' => False,'default' => '0'),
|
||||
'cat_owner' => array('type' => 'ascii','meta' => 'account-commasep','precision' => '255','nullable' => False,'default' => '0'),
|
||||
'cat_access' => array('type' => 'ascii','precision' => '7'),
|
||||
'cat_appname' => array('type' => 'ascii','precision' => '16','nullable' => False),
|
||||
'cat_name' => array('type' => 'varchar','precision' => '150','nullable' => False),
|
||||
'cat_description' => array('type' => 'varchar','precision' => '255','nullable' => False),
|
||||
'cat_data' => array('type' => 'varchar','precision' => '8192'),
|
||||
'last_mod' => array('type' => 'int','meta' => 'timestamp','precision' => '8','nullable' => False)
|
||||
),
|
||||
'pk' => array('cat_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(array('cat_appname','cat_owner','cat_parent','cat_level')),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_history_log' => array(
|
||||
'fd' => array(
|
||||
'history_id' => array('type' => 'auto','precision' => '4','nullable' => False),
|
||||
'history_record_id' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'history_appname' => array('type' => 'ascii','precision' => '16','nullable' => False),
|
||||
'history_owner' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False),
|
||||
'history_status' => array('type' => 'varchar','precision' => '32','nullable' => False),
|
||||
'history_new_value' => array('type' => 'text','nullable' => False),
|
||||
'history_timestamp' => array('type' => 'timestamp','nullable' => False,'default' => 'current_timestamp'),
|
||||
'history_old_value' => array('type' => 'text','nullable' => False),
|
||||
'sessionid' => array('type' => 'int','precision' => '4','comment' => 'primary key to egw_access_log')
|
||||
),
|
||||
'pk' => array('history_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(array('history_appname','history_record_id','history_id')),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_async' => array(
|
||||
'fd' => array(
|
||||
'async_id' => array('type' => 'ascii','precision' => '64','nullable' => False),
|
||||
'async_next' => array('type' => 'int','meta' => 'timestamp','precision' => '4','nullable' => False,'comment' => 'timestamp of next run'),
|
||||
'async_times' => array('type' => 'ascii','precision' => '255','nullable' => False,'comment' => 'serialized array with values for keys hour,min,day,month,year'),
|
||||
'async_method' => array('type' => 'ascii','precision' => '80','nullable' => False,'comment' => 'app.class.method class::method to execute'),
|
||||
'async_data' => array('type' => 'varchar','precision' => '8192','nullable' => False,'comment' => 'serialized array with data to pass to method'),
|
||||
'async_account_id' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False,'default' => '0','comment' => 'creator of job'),
|
||||
'async_auto_id' => array('type' => 'auto','nullable' => False)
|
||||
),
|
||||
'pk' => array('async_auto_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array('async_id')
|
||||
),
|
||||
'egw_links' => array(
|
||||
'fd' => array(
|
||||
'link_id' => array('type' => 'auto','nullable' => False),
|
||||
'link_app1' => array('type' => 'ascii','precision' => '16','nullable' => False),
|
||||
'link_id1' => array('type' => 'ascii','meta' => array("link_app1='home-accounts'" => 'account'),'precision' => '64','nullable' => False),
|
||||
'link_app2' => array('type' => 'ascii','precision' => '16','nullable' => False),
|
||||
'link_id2' => array('type' => 'ascii','meta' => array("link_app2='home-accounts'" => 'account'),'precision' => '64','nullable' => False),
|
||||
'link_remark' => array('type' => 'varchar','precision' => '100'),
|
||||
'link_lastmod' => array('type' => 'int','meta' => 'timestamp','precision' => '8','nullable' => False),
|
||||
'link_owner' => array('type' => 'int','meta' => 'account','precision' => '4','nullable' => False),
|
||||
'deleted' => array('type' => 'timestamp')
|
||||
),
|
||||
'pk' => array('link_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array('deleted',array('link_app1','link_id1','link_lastmod'),array('link_app2','link_id2','link_lastmod')),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_addressbook' => array(
|
||||
'fd' => array(
|
||||
'contact_id' => array('type' => 'auto','nullable' => False),
|
||||
'contact_tid' => array('type' => 'char','precision' => '1','default' => 'n'),
|
||||
'contact_owner' => array('type' => 'int','meta' => 'account','precision' => '8','nullable' => False,'comment' => 'account or group id of the adressbook'),
|
||||
'contact_private' => array('type' => 'int','precision' => '1','default' => '0','comment' => 'privat or personal'),
|
||||
'cat_id' => array('type' => 'ascii','meta' => 'category','precision' => '255','comment' => 'Category(s)'),
|
||||
'n_family' => array('type' => 'varchar','precision' => '64','comment' => 'Family name'),
|
||||
'n_given' => array('type' => 'varchar','precision' => '64','comment' => 'Given Name'),
|
||||
'n_middle' => array('type' => 'varchar','precision' => '64'),
|
||||
'n_prefix' => array('type' => 'varchar','precision' => '64','comment' => 'Prefix'),
|
||||
'n_suffix' => array('type' => 'varchar','precision' => '64','comment' => 'Suffix'),
|
||||
'n_fn' => array('type' => 'varchar','precision' => '128','comment' => 'Full name'),
|
||||
'n_fileas' => array('type' => 'varchar','precision' => '255','comment' => 'sort as'),
|
||||
'contact_bday' => array('type' => 'varchar','precision' => '12','comment' => 'Birtday'),
|
||||
'org_name' => array('type' => 'varchar','precision' => '128','comment' => 'Organisation'),
|
||||
'org_unit' => array('type' => 'varchar','precision' => '64','comment' => 'Department'),
|
||||
'contact_title' => array('type' => 'varchar','precision' => '64','comment' => 'jobtittle'),
|
||||
'contact_role' => array('type' => 'varchar','precision' => '64','comment' => 'role'),
|
||||
'contact_assistent' => array('type' => 'varchar','precision' => '64','comment' => 'Name of the Assistent (for phone number)'),
|
||||
'contact_room' => array('type' => 'varchar','precision' => '64','comment' => 'room'),
|
||||
'adr_one_street' => array('type' => 'varchar','precision' => '64','comment' => 'street (business)'),
|
||||
'adr_one_street2' => array('type' => 'varchar','precision' => '64','comment' => 'street (business) - 2. line'),
|
||||
'adr_one_locality' => array('type' => 'varchar','precision' => '64','comment' => 'city (business)'),
|
||||
'adr_one_region' => array('type' => 'varchar','precision' => '64','comment' => 'region (business)'),
|
||||
'adr_one_postalcode' => array('type' => 'varchar','precision' => '64','comment' => 'postalcode (business)'),
|
||||
'adr_one_countryname' => array('type' => 'varchar','precision' => '64','comment' => 'countryname (business)'),
|
||||
'contact_label' => array('type' => 'text','comment' => 'currently not used'),
|
||||
'adr_two_street' => array('type' => 'varchar','precision' => '64','comment' => 'street (private)'),
|
||||
'adr_two_street2' => array('type' => 'varchar','precision' => '64','comment' => 'street (private) - 2. line'),
|
||||
'adr_two_locality' => array('type' => 'varchar','precision' => '64','comment' => 'city (private)'),
|
||||
'adr_two_region' => array('type' => 'varchar','precision' => '64','comment' => 'region (private)'),
|
||||
'adr_two_postalcode' => array('type' => 'varchar','precision' => '64','comment' => 'postalcode (private)'),
|
||||
'adr_two_countryname' => array('type' => 'varchar','precision' => '64','comment' => 'countryname (private)'),
|
||||
'tel_work' => array('type' => 'varchar','precision' => '40','comment' => 'phone-number (business)'),
|
||||
'tel_cell' => array('type' => 'varchar','precision' => '40','comment' => 'mobil phone (business)'),
|
||||
'tel_fax' => array('type' => 'varchar','precision' => '40','comment' => 'fax-number (business)'),
|
||||
'tel_assistent' => array('type' => 'varchar','precision' => '40','comment' => 'phone-number assistent'),
|
||||
'tel_car' => array('type' => 'varchar','precision' => '40'),
|
||||
'tel_pager' => array('type' => 'varchar','precision' => '40','comment' => 'pager'),
|
||||
'tel_home' => array('type' => 'varchar','precision' => '40','comment' => 'phone-number (private)'),
|
||||
'tel_fax_home' => array('type' => 'varchar','precision' => '40','comment' => 'fax-number (private)'),
|
||||
'tel_cell_private' => array('type' => 'varchar','precision' => '40','comment' => 'mobil phone (private)'),
|
||||
'tel_other' => array('type' => 'varchar','precision' => '40','comment' => 'other phone'),
|
||||
'tel_prefer' => array('type' => 'varchar','precision' => '32','comment' => 'prefered phone-number'),
|
||||
'contact_email' => array('type' => 'varchar','precision' => '128','comment' => 'email address (business)'),
|
||||
'contact_email_home' => array('type' => 'varchar','precision' => '128','comment' => 'email address (private)'),
|
||||
'contact_url' => array('type' => 'varchar','precision' => '128','comment' => 'website (business)'),
|
||||
'contact_url_home' => array('type' => 'varchar','precision' => '128','comment' => 'website (private)'),
|
||||
'contact_freebusy_uri' => array('type' => 'ascii','precision' => '128','comment' => 'freebusy-url for calendar of the contact'),
|
||||
'contact_calendar_uri' => array('type' => 'ascii','precision' => '128','comment' => 'url for users calendar - currently not used'),
|
||||
'contact_note' => array('type' => 'varchar','precision' => '8192','comment' => 'notes field'),
|
||||
'contact_tz' => array('type' => 'varchar','precision' => '8','comment' => 'timezone difference'),
|
||||
'contact_geo' => array('type' => 'ascii','precision' => '32','comment' => 'currently not used'),
|
||||
'contact_pubkey' => array('type' => 'ascii','precision' => '16384','comment' => 'public key'),
|
||||
'contact_created' => array('type' => 'int','meta' => 'timestamp','precision' => '8','comment' => 'timestamp of the creation'),
|
||||
'contact_creator' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False,'comment' => 'account id of the creator'),
|
||||
'contact_modified' => array('type' => 'int','meta' => 'timestamp','precision' => '8','nullable' => False,'comment' => 'timestamp of the last modified'),
|
||||
'contact_modifier' => array('type' => 'int','meta' => 'user','precision' => '4','comment' => 'account id of the last modified'),
|
||||
'contact_jpegphoto' => array('type' => 'blob','comment' => 'photo of the contact (attachment)'),
|
||||
'account_id' => array('type' => 'int','meta' => 'user','precision' => '4','comment' => 'account id'),
|
||||
'contact_etag' => array('type' => 'int','precision' => '4','default' => '0','comment' => 'etag of the changes'),
|
||||
'contact_uid' => array('type' => 'ascii','precision' => '128','comment' => 'unique id of the contact'),
|
||||
'adr_one_countrycode' => array('type' => 'ascii','precision' => '2','comment' => 'countrycode (business)'),
|
||||
'adr_two_countrycode' => array('type' => 'ascii','precision' => '2','comment' => 'countrycode (private)'),
|
||||
'carddav_name' => array('type' => 'ascii','precision' => '128','comment' => 'name part of CardDAV URL, if specified by client')
|
||||
),
|
||||
'pk' => array('contact_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array('contact_owner','cat_id','n_fileas','contact_modified','contact_uid','carddav_name',array('n_family','n_given'),array('n_given','n_family'),array('org_name','n_family','n_given')),
|
||||
'uc' => array('account_id')
|
||||
),
|
||||
'egw_addressbook_extra' => array(
|
||||
'fd' => array(
|
||||
'contact_id' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'contact_owner' => array('type' => 'int','meta' => 'account','precision' => '8'),
|
||||
'contact_name' => array('type' => 'varchar','meta' => 'cfname','precision' => '64','nullable' => False,'comment' => 'custom-field name'),
|
||||
'contact_value' => array('type' => 'varchar','meta' => 'cfvalue','precision' => '16384','comment' => 'custom-field value'),
|
||||
'contact_extra_id' => array('type' => 'auto','nullable' => False)
|
||||
),
|
||||
'pk' => array('contact_extra_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array('contact_name',array('contact_id','contact_name')),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_addressbook_lists' => array(
|
||||
'fd' => array(
|
||||
'list_id' => array('type' => 'auto','nullable' => False),
|
||||
'list_name' => array('type' => 'varchar','precision' => '80','nullable' => False),
|
||||
'list_owner' => array('type' => 'int','meta' => 'account','precision' => '4','nullable' => False),
|
||||
'list_created' => array('type' => 'int','meta' => 'timestamp','precision' => '8'),
|
||||
'list_creator' => array('type' => 'int','meta' => 'user','precision' => '4'),
|
||||
'list_uid' => array('type' => 'ascii','precision' => '128'),
|
||||
'list_carddav_name' => array('type' => 'ascii','precision' => '128'),
|
||||
'list_etag' => array('type' => 'int','precision' => '4','nullable' => False,'default' => '0'),
|
||||
'list_modified' => array('type' => 'timestamp','nullable' => False,'default' => 'current_timestamp'),
|
||||
'list_modifier' => array('type' => 'int','meta' => 'user','precision' => '4')
|
||||
),
|
||||
'pk' => array('list_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array('list_uid','list_carddav_name',array('list_owner','list_name'))
|
||||
),
|
||||
'egw_addressbook2list' => array(
|
||||
'fd' => array(
|
||||
'contact_id' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'list_id' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'list_added' => array('type' => 'int','meta' => 'timestamp','precision' => '8'),
|
||||
'list_added_by' => array('type' => 'int','meta' => 'user','precision' => '4')
|
||||
),
|
||||
'pk' => array('contact_id','list_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_sqlfs' => array(
|
||||
'fd' => array(
|
||||
'fs_id' => array('type' => 'auto','nullable' => False),
|
||||
'fs_dir' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'fs_name' => array('type' => 'varchar','precision' => '200','nullable' => False),
|
||||
'fs_mode' => array('type' => 'int','precision' => '2','nullable' => False),
|
||||
'fs_uid' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False,'default' => '0'),
|
||||
'fs_gid' => array('type' => 'int','meta' => 'group-abs','precision' => '4','nullable' => False,'default' => '0'),
|
||||
'fs_created' => array('type' => 'timestamp','precision' => '8','nullable' => False),
|
||||
'fs_modified' => array('type' => 'timestamp','precision' => '8','nullable' => False),
|
||||
'fs_mime' => array('type' => 'ascii','precision' => '96','nullable' => False),
|
||||
'fs_size' => array('type' => 'int','precision' => '8','nullable' => False),
|
||||
'fs_creator' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False),
|
||||
'fs_modifier' => array('type' => 'int','meta' => 'user','precision' => '4'),
|
||||
'fs_active' => array('type' => 'bool','nullable' => False,'default' => 't'),
|
||||
'fs_content' => array('type' => 'blob'),
|
||||
'fs_link' => array('type' => 'varchar','precision' => '255')
|
||||
),
|
||||
'pk' => array('fs_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(array('fs_dir','fs_active','fs_name(16)')),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_locks' => array(
|
||||
'fd' => array(
|
||||
'lock_token' => array('type' => 'ascii','precision' => '64','nullable' => False),
|
||||
'lock_path' => array('type' => 'varchar','precision' => '255','nullable' => False),
|
||||
'lock_expires' => array('type' => 'int','meta' => 'timestamp','precision' => '8','nullable' => False),
|
||||
'lock_owner' => array('type' => 'varchar','precision' => '255'),
|
||||
'lock_recursive' => array('type' => 'bool','nullable' => False,'default' => '0'),
|
||||
'lock_write' => array('type' => 'bool','nullable' => False,'default' => '0'),
|
||||
'lock_exclusive' => array('type' => 'bool','nullable' => False,'default' => '0'),
|
||||
'lock_created' => array('type' => 'int','meta' => 'timestamp','precision' => '8','default' => '0'),
|
||||
'lock_modified' => array('type' => 'int','meta' => 'timestamp','precision' => '8','default' => '0'),
|
||||
'lock_id' => array('type' => 'auto','nullable' => False)
|
||||
),
|
||||
'pk' => array('lock_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array('lock_path','lock_expires'),
|
||||
'uc' => array('lock_token')
|
||||
),
|
||||
'egw_sqlfs_props' => array(
|
||||
'fd' => array(
|
||||
'fs_id' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'prop_namespace' => array('type' => 'ascii','precision' => '64','nullable' => False),
|
||||
'prop_name' => array('type' => 'ascii','precision' => '64','nullable' => False),
|
||||
'prop_value' => array('type' => 'varchar','precision' => '16384'),
|
||||
'prop_id' => array('type' => 'auto','nullable' => False)
|
||||
),
|
||||
'pk' => array('prop_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(array('fs_id','prop_namespace','prop_name')),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_customfields' => array(
|
||||
'fd' => array(
|
||||
'cf_id' => array('type' => 'auto','nullable' => False),
|
||||
'cf_app' => array('type' => 'ascii','precision' => '16','nullable' => False,'comment' => 'app-name cf belongs too'),
|
||||
'cf_name' => array('type' => 'varchar','precision' => '128','nullable' => False,'comment' => 'internal name'),
|
||||
'cf_label' => array('type' => 'varchar','precision' => '128','comment' => 'label to display'),
|
||||
'cf_type' => array('type' => 'varchar','precision' => '64','nullable' => False,'default' => 'text','comment' => 'type of field'),
|
||||
'cf_type2' => array('type' => 'varchar','precision' => '2048','comment' => 'comma-separated subtypes of app, cf is valid for'),
|
||||
'cf_help' => array('type' => 'varchar','precision' => '256','comment' => 'helptext'),
|
||||
'cf_values' => array('type' => 'varchar','precision' => '8096','comment' => 'json object with value label pairs'),
|
||||
'cf_len' => array('type' => 'int','precision' => '2','comment' => 'length or columns of field'),
|
||||
'cf_rows' => array('type' => 'int','precision' => '2','comment' => 'rows of field'),
|
||||
'cf_order' => array('type' => 'int','precision' => '2','comment' => 'order to display fields'),
|
||||
'cf_needed' => array('type' => 'bool','default' => '0','comment' => 'field is required'),
|
||||
'cf_private' => array('type' => 'ascii','meta' => 'account-commasep','precision' => '2048','comment' => 'comma-separated account_id'),
|
||||
'cf_modifier' => array('type' => 'int','meta' => 'account','precision' => '4','comment' => 'last modifier'),
|
||||
'cf_modified' => array('type' => 'timestamp','default' => 'current_timestamp','comment' => 'last modification time'),
|
||||
'cf_tab' => array('type' => 'varchar','precision' => '64','comment' => 'tab customfield should be shown')
|
||||
),
|
||||
'pk' => array('cf_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(array('cf_app','cf_order')),
|
||||
'uc' => array(array('cf_app','cf_name'))
|
||||
),
|
||||
'egw_sharing' => array(
|
||||
'fd' => array(
|
||||
'share_id' => array('type' => 'auto','nullable' => False,'comment' => 'auto-id'),
|
||||
'share_token' => array('type' => 'ascii','precision' => '64','nullable' => False,'comment' => 'secure token'),
|
||||
'share_path' => array('type' => 'varchar','precision' => '255','nullable' => False,'comment' => 'path to share'),
|
||||
'share_owner' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False,'comment' => 'owner of share'),
|
||||
'share_expires' => array('type' => 'date','comment' => 'expire date of share'),
|
||||
'share_writable' => array('type' => 'int','precision' => '1','nullable' => False,'default' => '0','comment' => '0=readable, 1=writable'),
|
||||
'share_with' => array('type' => 'varchar','precision' => '4096','comment' => 'email addresses, comma seperated'),
|
||||
'share_passwd' => array('type' => 'varchar','precision' => '128','comment' => 'optional password-hash'),
|
||||
'share_created' => array('type' => 'timestamp','nullable' => False,'comment' => 'creation date'),
|
||||
'share_last_accessed' => array('type' => 'timestamp','comment' => 'last access of share')
|
||||
),
|
||||
'pk' => array('share_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array('share_token')
|
||||
),
|
||||
'egw_mailaccounts' => array(
|
||||
'fd' => array(
|
||||
'mail_id' => array('type' => 'auto','nullable' => False,'comment' => 'the id'),
|
||||
'account_id' => array('type' => 'int','meta' => 'account','precision' => '4','nullable' => False,'comment' => 'account id of the owner, can be user AND group'),
|
||||
'mail_type' => array('type' => 'int','precision' => '1','nullable' => False,'comment' => '0=active, 1=alias, 2=forward, 3=forwardOnly, 4=quota'),
|
||||
'mail_value' => array('type' => 'ascii','precision' => '128','nullable' => False,'comment' => 'the value (that should be) corresponding to the mail_type')
|
||||
),
|
||||
'pk' => array('mail_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array('mail_value',array('account_id','mail_type')),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_ea_accounts' => array(
|
||||
'fd' => array(
|
||||
'acc_id' => array('type' => 'auto','nullable' => False),
|
||||
'acc_name' => array('type' => 'varchar','precision' => '80','comment' => 'description'),
|
||||
'ident_id' => array('type' => 'int','precision' => '4','nullable' => False,'comment' => 'standard identity'),
|
||||
'acc_imap_host' => array('type' => 'ascii','precision' => '128','nullable' => False,'comment' => 'imap hostname'),
|
||||
'acc_imap_ssl' => array('type' => 'int','precision' => '1','nullable' => False,'default' => '0','comment' => '0=none, 1=starttls, 2=tls, 3=ssl, &8=validate certificate'),
|
||||
'acc_imap_port' => array('type' => 'int','precision' => '4','nullable' => False,'default' => '143','comment' => 'imap port'),
|
||||
'acc_sieve_enabled' => array('type' => 'bool','default' => '0','comment' => 'sieve enabled'),
|
||||
'acc_sieve_host' => array('type' => 'ascii','precision' => '128','comment' => 'sieve host, default imap_host'),
|
||||
'acc_sieve_port' => array('type' => 'int','precision' => '4','default' => '4190'),
|
||||
'acc_folder_sent' => array('type' => 'varchar','precision' => '128','comment' => 'sent folder'),
|
||||
'acc_folder_trash' => array('type' => 'varchar','precision' => '128','comment' => 'trash folder'),
|
||||
'acc_folder_draft' => array('type' => 'varchar','precision' => '128','comment' => 'draft folder'),
|
||||
'acc_folder_template' => array('type' => 'varchar','precision' => '128','comment' => 'template folder'),
|
||||
'acc_smtp_host' => array('type' => 'varchar','precision' => '128','comment' => 'smtp hostname'),
|
||||
'acc_smtp_ssl' => array('type' => 'int','precision' => '1','nullable' => False,'default' => '0','comment' => '0=none, 1=starttls, 2=tls, 3=ssl, &8=validate certificate'),
|
||||
'acc_smtp_port' => array('type' => 'int','precision' => '4','nullable' => False,'default' => '25','comment' => 'smtp port'),
|
||||
'acc_smtp_type' => array('type' => 'ascii','precision' => '32','default' => 'emailadmin_smtp','comment' => 'smtp class to use'),
|
||||
'acc_imap_type' => array('type' => 'ascii','precision' => '32','default' => 'emailadmin_imap','comment' => 'imap class to use'),
|
||||
'acc_imap_logintype' => array('type' => 'ascii','precision' => '20','comment' => 'standard, vmailmgr, admin, uidNumber'),
|
||||
'acc_domain' => array('type' => 'varchar','precision' => '100','comment' => 'domain name'),
|
||||
'acc_further_identities' => array('type' => 'bool','nullable' => False,'default' => '1','comment' => '0=no, 1=yes'),
|
||||
'acc_user_editable' => array('type' => 'bool','nullable' => False,'default' => '1','comment' => '0=no, 1=yes'),
|
||||
'acc_sieve_ssl' => array('type' => 'int','precision' => '1','default' => '1','comment' => '0=none, 1=starttls, 2=tls, 3=ssl, &8=validate certificate'),
|
||||
'acc_modified' => array('type' => 'timestamp','nullable' => False,'default' => 'current_timestamp'),
|
||||
'acc_modifier' => array('type' => 'int','meta' => 'user','precision' => '4'),
|
||||
'acc_smtp_auth_session' => array('type' => 'bool','comment' => '0=no, 1=yes, use username/pw from current user'),
|
||||
'acc_folder_junk' => array('type' => 'varchar','precision' => '128','comment' => 'junk folder'),
|
||||
'acc_imap_default_quota' => array('type' => 'int','precision' => '4','comment' => 'default quota, if no user specific one set'),
|
||||
'acc_imap_timeout' => array('type' => 'int','precision' => '2','comment' => 'timeout for imap connection'),
|
||||
'acc_user_forward' => array('type' => 'bool','default' => '0','comment' => 'allow user to define forwards')
|
||||
),
|
||||
'pk' => array('acc_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_ea_credentials' => array(
|
||||
'fd' => array(
|
||||
'cred_id' => array('type' => 'auto','nullable' => False),
|
||||
'acc_id' => array('type' => 'int','precision' => '4','nullable' => False,'comment' => 'into egw_ea_accounts'),
|
||||
'cred_type' => array('type' => 'int','precision' => '1','nullable' => False,'comment' => '&1=imap, &2=smtp, &4=admin'),
|
||||
'account_id' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False,'comment' => 'account_id or 0=all'),
|
||||
'cred_username' => array('type' => 'varchar','precision' => '80','nullable' => False,'comment' => 'username'),
|
||||
'cred_password' => array('type' => 'varchar','precision' => '80','comment' => 'password encrypted'),
|
||||
'cred_pw_enc' => array('type' => 'int','precision' => '1','default' => '0','comment' => '0=not, 1=user pw, 2=system')
|
||||
),
|
||||
'pk' => array('cred_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array(array('acc_id','account_id','cred_type'))
|
||||
),
|
||||
'egw_ea_identities' => array(
|
||||
'fd' => array(
|
||||
'ident_id' => array('type' => 'auto','nullable' => False),
|
||||
'acc_id' => array('type' => 'int','precision' => '4','nullable' => False,'comment' => 'for which account'),
|
||||
'ident_realname' => array('type' => 'varchar','precision' => '128','nullable' => False,'comment' => 'real name'),
|
||||
'ident_email' => array('type' => 'varchar','precision' => '128','comment' => 'email address'),
|
||||
'ident_org' => array('type' => 'varchar','precision' => '128','comment' => 'organisation'),
|
||||
'ident_signature' => array('type' => 'text','comment' => 'signature text'),
|
||||
'account_id' => array('type' => 'int','meta' => 'account','precision' => '4','nullable' => False,'default' => '0','comment' => '0=all users of give mail account'),
|
||||
'ident_name' => array('type' => 'varchar','precision' => '128','comment' => 'name of identity to display')
|
||||
),
|
||||
'pk' => array('ident_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_ea_valid' => array(
|
||||
'fd' => array(
|
||||
'acc_id' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'account_id' => array('type' => 'int','meta' => 'account','precision' => '4','nullable' => False)
|
||||
),
|
||||
'pk' => array(),
|
||||
'fk' => array(),
|
||||
'ix' => array(array('account_id','acc_id')),
|
||||
'uc' => array(array('acc_id','account_id'))
|
||||
),
|
||||
'egw_ea_notifications' => array(
|
||||
'fd' => array(
|
||||
'notif_id' => array('type' => 'auto','nullable' => False),
|
||||
'acc_id' => array('type' => 'int','precision' => '4','nullable' => False,'comment' => 'mail account'),
|
||||
'account_id' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False,'comment' => 'user account'),
|
||||
'notif_folder' => array('type' => 'varchar','precision' => '255','nullable' => False,'comment' => 'folder name')
|
||||
),
|
||||
'pk' => array('notif_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(array('account_id','acc_id')),
|
||||
'uc' => array()
|
||||
),
|
||||
);
|
@ -86,7 +86,6 @@ class Config
|
||||
{
|
||||
if (is_array($this->config_data))
|
||||
{
|
||||
self::$db->lock(array(config::TABLE));
|
||||
foreach($this->config_data as $name => $value)
|
||||
{
|
||||
self::save_value($name, $value, $this->appname, false);
|
||||
@ -99,7 +98,6 @@ class Config
|
||||
//self::$db->delete(config::TABLE,array('config_app'=>$this->appname,'config_name'=>$name),__LINE__,__FILE__);
|
||||
}
|
||||
}
|
||||
self::$db->unlock();
|
||||
|
||||
if ($this->appname == 'phpgwapi' && method_exists($GLOBALS['egw'],'invalidate_session_cache')) // egw object in setup is limited
|
||||
{
|
||||
|
@ -15,9 +15,6 @@ namespace EGroupware\Api\Contacts;
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
// explicitly reference classes still in phpgwapi
|
||||
use common; // common::generate_uid
|
||||
|
||||
/**
|
||||
* Contacts - SQL storage
|
||||
*/
|
||||
@ -72,10 +69,10 @@ class Sql extends Api\Storage
|
||||
*/
|
||||
function __construct(Api\Db $db=null)
|
||||
{
|
||||
parent::__construct('phpgwapi', 'egw_addressbook', self::EXTRA_TABLE,
|
||||
parent::__construct('api', 'egw_addressbook', self::EXTRA_TABLE,
|
||||
'contact_', '_name', '_value', '_id', $db);
|
||||
|
||||
// Get custom fields from addressbook instead of phpgwapi
|
||||
// Get custom fields from addressbook instead of api
|
||||
$this->customfields = Api\Storage\Customfields::get('addressbook');
|
||||
|
||||
if ($GLOBALS['egw_info']['server']['account_repository'])
|
||||
@ -599,7 +596,7 @@ class Sql extends Api\Storage
|
||||
$update = array();
|
||||
if (!isset($data['list_uid']))
|
||||
{
|
||||
$update['list_uid'] = $data['list_uid'] = common::generate_uid('addresbook-lists', $list_id);
|
||||
$update['list_uid'] = $data['list_uid'] = Api\CalDAV::generate_uid('addresbook-lists', $list_id);
|
||||
}
|
||||
if (!isset($data['list_carddav_name']))
|
||||
{
|
||||
@ -766,7 +763,7 @@ class Sql extends Api\Storage
|
||||
// enforce a minium uid strength
|
||||
if (is_array($contact) && (!isset($contact['uid'])
|
||||
|| strlen($contact['uid']) < $minimum_uid_length)) {
|
||||
parent::update(array('uid' => common::generate_uid('addressbook',$contact['id'])));
|
||||
parent::update(array('uid' => Api\CalDAV::generate_uid('addressbook',$contact['id'])));
|
||||
}
|
||||
return $contact;
|
||||
}
|
||||
@ -818,7 +815,7 @@ class Sql extends Api\Storage
|
||||
// enforce a minium uid strength
|
||||
if (!isset($this->data['uid']) || strlen($this->data['uid']) < $minimum_uid_length)
|
||||
{
|
||||
$update['uid'] = common::generate_uid('addressbook',$this->data['id']);
|
||||
$update['uid'] = Api\CalDAV::generate_uid('addressbook',$this->data['id']);
|
||||
//echo "<p>set uid={$this->data['uid']}, etag={$this->data['etag']}</p>";
|
||||
}
|
||||
// set carddav_name, if not given by caller
|
||||
|
@ -263,8 +263,8 @@ class Storage
|
||||
}
|
||||
if ($this->contact_repository == 'sql' || $this->contact_repository == 'sql-ldap')
|
||||
{
|
||||
$tda2list = $this->db->get_table_definitions('phpgwapi','egw_addressbook2list');
|
||||
$tdlists = $this->db->get_table_definitions('phpgwapi','egw_addressbook_lists');
|
||||
$tda2list = $this->db->get_table_definitions('api','egw_addressbook2list');
|
||||
$tdlists = $this->db->get_table_definitions('api','egw_addressbook_lists');
|
||||
$this->distributionlist_tabledef = array('fd' => array(
|
||||
$this->distri_id => $tda2list['fd'][$this->distri_id],
|
||||
$this->distri_owner => $tdlists['fd'][$this->distri_owner],
|
||||
@ -872,7 +872,7 @@ class Storage
|
||||
*/
|
||||
function get_fields($type='all',$contact_id=null,$owner=null)
|
||||
{
|
||||
$def = $this->db->get_table_definitions('phpgwapi','egw_addressbook');
|
||||
$def = $this->db->get_table_definitions('api','egw_addressbook');
|
||||
|
||||
$all_fields = array();
|
||||
foreach(array_keys($def['fd']) as $field)
|
||||
|
@ -992,11 +992,10 @@ class Db
|
||||
echo "<p>db::index_names() not yet implemented for db-type '$this->Type'</p>\n";
|
||||
return $indices;
|
||||
}
|
||||
$this->query("SELECT relname FROM pg_class WHERE NOT relname ~ 'pg_.*' AND relkind ='i' ORDER BY relname");
|
||||
while ($this->next_record())
|
||||
foreach($this->query("SELECT relname FROM pg_class WHERE NOT relname ~ 'pg_.*' AND relkind ='i' ORDER BY relname") as $row)
|
||||
{
|
||||
$indices[] = array(
|
||||
'index_name' => $this->f(0),
|
||||
'index_name' => $row[0],
|
||||
'tablespace_name' => $this->Database,
|
||||
'database' => $this->Database,
|
||||
);
|
||||
@ -1541,7 +1540,7 @@ class Db
|
||||
* Application name used by the API
|
||||
*
|
||||
*/
|
||||
const API_APPNAME = 'phpgwapi';
|
||||
const API_APPNAME = 'api';
|
||||
/**
|
||||
* Default app, if no app specified in select, insert, delete, ...
|
||||
*
|
||||
@ -1559,6 +1558,9 @@ class Db
|
||||
*/
|
||||
function set_app($app)
|
||||
{
|
||||
// ease the transition to api
|
||||
if ($app == 'phpgwapi') $app = 'api';
|
||||
|
||||
if ($this === $GLOBALS['egw']->db && $app != self::API_APPNAME)
|
||||
{
|
||||
// prevent that anyone switches the global db object to an other app
|
||||
@ -1581,6 +1583,9 @@ class Db
|
||||
*/
|
||||
function get_table_definitions($app=False,$table=False)
|
||||
{
|
||||
// ease the transition to api
|
||||
if ($app === 'phpgwapi') $app = 'api';
|
||||
|
||||
static $all_app_data = array();
|
||||
if ($app === true && $table)
|
||||
{
|
||||
@ -1710,8 +1715,7 @@ class Db
|
||||
}
|
||||
// fall through !!!
|
||||
default:
|
||||
$this->select($table,'count(*)',$where,$line,$file);
|
||||
if ($this->next_record() && $this->f(0))
|
||||
if ($this->select($table,'count(*)',$where,$line,$file)->fetchColumn())
|
||||
{
|
||||
return !!$this->update($table,$data,$where,$line,$file,$app,$use_prepared_statement,$table_def);
|
||||
}
|
||||
|
@ -118,41 +118,23 @@ class Backup
|
||||
{
|
||||
if ($GLOBALS['egw_setup']->config_table && $GLOBALS['egw_setup']->table_exist(array($GLOBALS['egw_setup']->config_table)))
|
||||
{
|
||||
$this->db->query("SELECT config_value FROM {$GLOBALS['egw_setup']->config_table} WHERE config_app='phpgwapi' AND config_name='backup_dir'",__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
if (!($this->backup_dir = $this->db->f(0)))
|
||||
{
|
||||
$this->db->query("SELECT config_value FROM {$GLOBALS['egw_setup']->config_table} WHERE config_app='phpgwapi' AND config_name='files_dir'",__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
$this->backup_dir = $this->db->f(0).'/db_backup';
|
||||
}
|
||||
$this->db->query("SELECT config_value FROM {$GLOBALS['egw_setup']->config_table} WHERE config_app='phpgwapi' AND config_name='files_dir'",__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
if (!($this->files_dir = $this->db->f(0)))
|
||||
if (!($this->files_dir = $this->db->query("SELECT config_value FROM {$GLOBALS['egw_setup']->config_table} WHERE config_app='phpgwapi' AND config_name='files_dir'",__LINE__,__FILE__)->fetchColumn()))
|
||||
{
|
||||
error_log(__METHOD__."->"."No files Directory set/found");
|
||||
}
|
||||
$this->db->query("SELECT config_value FROM {$GLOBALS['egw_setup']->config_table} WHERE config_app='phpgwapi' AND config_name='system_charset'",__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
$this->charset = $this->db->f(0);
|
||||
if (!$this->charset)
|
||||
if (!($this->backup_dir = $this->db->query("SELECT config_value FROM {$GLOBALS['egw_setup']->config_table} WHERE config_app='phpgwapi' AND config_name='backup_dir'",__LINE__,__FILE__)->fetchColumn()))
|
||||
{
|
||||
$this->db->query("SELECT content FROM {$GLOBALS['egw_setup']->lang_table} WHERE message_id='charset' AND app_name='common' AND lang!='en'",__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
$this->charset = $this->db->f(0);
|
||||
$this->backup_dir = $this->files_dir.'/db_backup';
|
||||
}
|
||||
$this->db->select($GLOBALS['egw_setup']->applications_table,'app_version',array('app_name'=>'phpgwapi'),__LINE__,__FILE__);
|
||||
$this->api_version = $this->db->next_record() ? $this->db->f(0) : false;
|
||||
/* Backup settings */
|
||||
$this->db->query("SELECT config_value FROM {$GLOBALS['egw_setup']->config_table} WHERE config_app='phpgwapi' AND config_name='backup_mincount'",__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
$this->backup_mincount = $this->db->f(0);
|
||||
$this->charset = $this->db->query("SELECT config_value FROM {$GLOBALS['egw_setup']->config_table} WHERE config_app='phpgwapi' AND config_name='system_charset'",__LINE__,__FILE__)->fetchColumn();
|
||||
$this->api_version = $this->db->select($GLOBALS['egw_setup']->applications_table,'app_version',array('app_name'=>array('api','phpgwapi')),
|
||||
__LINE__,__FILE__,0,'ORDER BY app_name ASC')->fetchColumn();
|
||||
// Backup settings
|
||||
$this->backup_mincount = $this->db->query("SELECT config_value FROM {$GLOBALS['egw_setup']->config_table} WHERE config_app='phpgwapi' AND config_name='backup_mincount'",__LINE__,__FILE__)->fetchColumn();
|
||||
// backup files too
|
||||
$this->db->query("SELECT config_value FROM {$GLOBALS['egw_setup']->config_table} WHERE config_app='phpgwapi' AND config_name='backup_files'",__LINE__,__FILE__);
|
||||
$this->db->next_record();
|
||||
$this->backup_files = (bool)$this->db->f(0);
|
||||
$this->backup_files = (bool)$this->db->query("SELECT config_value FROM {$GLOBALS['egw_setup']->config_table} WHERE config_app='phpgwapi' AND config_name='backup_files'",__LINE__,__FILE__)->fetchColumn();
|
||||
}
|
||||
if (!$this->charset) $this->charset = 'iso-8859-1';
|
||||
if (!$this->charset) $this->charset = 'utf-8';
|
||||
}
|
||||
else // called from eGW
|
||||
{
|
||||
@ -163,9 +145,9 @@ class Backup
|
||||
$this->files_dir = $GLOBALS['egw_info']['server']['files_dir'];
|
||||
$this->backup_mincount = $GLOBALS['egw_info']['server']['backup_mincount'];
|
||||
$this->backup_files = $GLOBALS['egw_info']['server']['backup_files'];
|
||||
$this->charset = $GLOBALS['egw']->translation->charset();
|
||||
$this->charset = Api\Translation::charset();
|
||||
|
||||
$this->api_version = $GLOBALS['egw_info']['apps']['phpgwapi']['version'];
|
||||
$this->api_version = $GLOBALS['egw_info']['apps'][isset($GLOBALS['egw_info']['apps']['api'])?'api':'phpgwapi']['version'];
|
||||
}
|
||||
// Set a default value if not set.
|
||||
if (!isset($this->backup_mincount))
|
||||
|
@ -204,7 +204,7 @@ class Hooks
|
||||
*
|
||||
* @param boolan $force_rescan =false true: do not use instance cache
|
||||
*/
|
||||
protected static function read($force_rescan=false)
|
||||
public static function read($force_rescan=false)
|
||||
{
|
||||
//$starttime = microtime(true);
|
||||
if ($force_rescan) Cache::unsetInstance(__CLASS__, 'locations');
|
||||
|
@ -181,6 +181,9 @@ class Base
|
||||
*/
|
||||
function __construct($app='',$table='',Api\Db $db=null,$column_prefix='',$no_clone=false,$timestamp_type=null)
|
||||
{
|
||||
// ease the transition to api
|
||||
if ($app == 'phpgwapi') $app = 'api';
|
||||
|
||||
if ($no_clone)
|
||||
{
|
||||
$this->db = is_object($db) ? $db : $GLOBALS['egw']->db;
|
||||
|
@ -154,11 +154,8 @@ class module_calendar_month extends Module
|
||||
$site_urls[] = ($_SERVER['HTTPS'] ? 'https://' : 'http://') . $_SERVER['SERVER_ADDR'] . $sitemgr_path;
|
||||
$site_urls[] = $site_url = ($_SERVER['HTTPS'] ? 'https://' : 'http://') . $_SERVER['SERVER_NAME'] . $sitemgr_path;
|
||||
|
||||
$GLOBALS['egw']->db->select('egw_sitemgr_sites','anonymous_user,anonymous_passwd,site_id',
|
||||
array('site_url' => $site_urls),__LINE__,__FILE__,false,'','sitemgr');
|
||||
|
||||
$GLOBALS['egw']->db->next_record();
|
||||
$anon_user = $this->accounts->name2id($GLOBALS['egw']->db->f('anonymous_user'),'account_lid','u');
|
||||
$anon_user = $this->accounts->name2id($GLOBALS['egw']->db->select('egw_sitemgr_sites','anonymous_user,anonymous_passwd,site_id',
|
||||
array('site_url' => $site_urls),__LINE__,__FILE__,false,'','sitemgr')->fetchColumn(),'account_lid','u');
|
||||
}
|
||||
|
||||
$anon_groups = $this->accounts->memberships($anon_user,true);
|
||||
|
@ -103,7 +103,7 @@ foreach(array(
|
||||
'etemplate_widget_taglist' => 'Api\\Etemplate\\Widget\\Taglist',
|
||||
'etemplate_widget_file' => 'Api\\Etemplate\\Widget\\File',
|
||||
'etemplate_widget_vfs' => 'Api\\Etemplate\\Widget\\Vfs',
|
||||
'etemplate_requst' => 'Api\\Etemplate\\Request',
|
||||
'etemplate_request' => 'Api\\Etemplate\\Request',
|
||||
'nextmatch_widget::category_action' => 'Api\\Etemplate\\Widget\\Nextmatch::category_action',
|
||||
// so_sql and friends
|
||||
'so_sql' => 'Api\\Storage\\Base',
|
||||
|
71
doc/mail/dbmail.schema
Normal file
71
doc/mail/dbmail.schema
Normal file
@ -0,0 +1,71 @@
|
||||
#
|
||||
# dbmail-ldap v3 directory schema
|
||||
#
|
||||
# Based on the Qmail schema
|
||||
# Modified for dbmail by Paul Stevens <paul@nfg.nl>
|
||||
# Modified for dbmail by Lars Kneschke <lkneschke@metaways.de> too
|
||||
#
|
||||
# This schema depends on:
|
||||
# - core.schema
|
||||
# - cosine.schema
|
||||
# - nis.schema
|
||||
#
|
||||
# This schema conflicts with
|
||||
# - qmailuser.schema
|
||||
|
||||
# Attribute Type Definitions
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.12340.6.2.1.1 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.12340.6.2.1.2 NAME 'mailForwardingAddress'
|
||||
DESC 'Address(es) to forward all incoming messages to.'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.12340.6.2.1.3 NAME 'mailHost'
|
||||
DESC 'Name or address of the MTA host to use for recipient'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.12340.6.2.1.4 NAME 'dbmailUID'
|
||||
DESC 'UID of the user on the mailsystem'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.12340.6.2.1.5 NAME 'dbmailGID'
|
||||
DESC 'GID of the user on the mailsystem'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.12340.6.2.1.6 NAME 'mailAlternateAddress'
|
||||
DESC 'Secondary (alias) mailaddresses for the same user'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.12340.6.2.1.7 NAME 'deliveryMode'
|
||||
DESC 'multi field entries of: normal, forwardonly'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.12340.6.2.1.8 NAME 'accountStatus'
|
||||
DESC 'The status of a user account: active, disabled'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 SINGLE-VALUE )
|
||||
|
||||
# Object Class Definitions
|
||||
|
||||
objectclass ( 1.3.6.1.4.1.12340.6.2.2.1 NAME 'dbmailUser'
|
||||
DESC 'DBMail-LDAP User' SUP top AUXILIARY
|
||||
MUST ( uid $ mail )
|
||||
MAY ( userPassword $ uidNumber $ gidNumber $ mailQuota $ mailForwardingAddress $ mailHost $ mailAlternateAddress $ dbmailUID $ dbmailGID $ deliveryMode $ accountStatus ) )
|
||||
|
||||
objectclass ( 1.3.6.1.4.1.12340.6.2.2.2 NAME 'dbmailForwardingAddress'
|
||||
DESC 'DBMail-LDAP Forwarding Address' SUP top AUXILIARY
|
||||
MUST ( mail $ mailForwardingAddress ) )
|
330
doc/mail/dovecot_checkpassword_ads.php
Executable file
330
doc/mail/dovecot_checkpassword_ads.php
Executable file
@ -0,0 +1,330 @@
|
||||
#!/usr/bin/php -Cq
|
||||
<?php
|
||||
/**
|
||||
* EGroupware -checkpasswd for Dovecot and Active Directory
|
||||
*
|
||||
* Quota is stored with "quota:" prefix in multivalued proxyAddresses attribute.
|
||||
* Group-memberships are passed to Dovecot to use them in ACL.
|
||||
*
|
||||
* Reads descriptor 3 through end of file and then closes descriptor 3.
|
||||
* There must be at most 512 bytes of data before end of file.
|
||||
*
|
||||
* The information supplied on descriptor 3 is a login name terminated by \0, a password terminated by \0,
|
||||
* a timestamp terminated by \0, and possibly more data.
|
||||
* There are no other restrictions on the form of the login name, password, and timestamp.
|
||||
*
|
||||
* If the password is unacceptable, checkpassword exits 1. If checkpassword is misused, it may instead exit 2.
|
||||
* If user is not found, checkpassword exits 3.
|
||||
* If there is a temporary problem checking the password, checkpassword exits 111.
|
||||
*
|
||||
* If the password is acceptable, checkpassword runs prog. prog consists of one or more arguments.
|
||||
*
|
||||
* Following enviroment variables are used by Dovecot:
|
||||
* - SERVICE: contains eg. imap, pop3 or smtp
|
||||
* - TCPLOCALIP and TCPREMOTEIP: Client socket's IP addresses if available
|
||||
* Following is document, but does NOT work:
|
||||
* - MASTER_USER: If master login is attempted. This means that the password contains the master user's password and the normal username contains the user who master wants to log in as.
|
||||
* Found working:
|
||||
* - AUTH_LOGIN_USER: If master login is attempted. This means that username/password are from master, AUTH_LOGIN_USER is user master wants to log in as.
|
||||
*
|
||||
* Following enviroment variables are used on return:
|
||||
* - USER: modified user name
|
||||
* - HOME: mail_home
|
||||
* - EXTRA: userdb extra fields eg. "system_groups_user=... userdb_quota_rule=*:storage=10000"
|
||||
*
|
||||
* @author rb(at)stylite.de
|
||||
* @copyright (c) 2012-13 by rb(at)stylite.de
|
||||
* @package emailadmin
|
||||
* @link http://wiki2.dovecot.org/AuthDatabase/CheckPassword
|
||||
* @link http://cr.yp.to/checkpwd/interface.html
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
// protect from being called via HTTP
|
||||
if (php_sapi_name() !== 'cli') die('This is a command line only script!');
|
||||
|
||||
// uncomment to write to log-file, otherwise errors go to stderr
|
||||
//$log = '/var/log/dovecot_checkpassword.log';
|
||||
//$log_verbose = true; // error's are always logged, set to true to log auth failures and success too
|
||||
|
||||
// ldap server settings
|
||||
$ldap_uri = 'ldaps://10.7.102.13/';
|
||||
$ldap_base = 'CN=Users,DC=gruene,DC=intern';
|
||||
$bind_dn = "CN=Administrator,$ldap_base";
|
||||
//$bind_dn = "Administrator@gruene.intern";
|
||||
//$bind_pw = 'secret';
|
||||
$version = 3;
|
||||
$use_tls = false;
|
||||
$search_base = $ldap_base;//'o=%d,dc=egroupware';
|
||||
$passdb_filter = $userdb_filter = '(&(objectCategory=person)(sAMAccountName=%s))';
|
||||
// %d for domain and %s for username given by Dovecot is set automatic
|
||||
$user_attrs = array(
|
||||
'%u' => 'samaccountname', // do NOT remove!
|
||||
// '%n' => 'uidnumber',
|
||||
// '%h' => 'mailmessagestore',
|
||||
'%q' => '{quota:}proxyaddresses',
|
||||
'%x' => 'dn',
|
||||
);
|
||||
$user_name = '%u'; // '%u@%d';
|
||||
$user_home = '/var/dovecot/imap/gruene/%u'; //'/var/dovecot/imap/%d/%u'; // mailbox location
|
||||
$extra = array(
|
||||
'userdb_quota_rule' => '*:bytes=%q',
|
||||
/* only for director
|
||||
'proxy' => 'Y',
|
||||
'nologin' => 'Y',
|
||||
'nopassword' => 'Y',
|
||||
*/
|
||||
);
|
||||
// get host by not set l attribute
|
||||
/* only for director
|
||||
$host_filter = 'o=%d';
|
||||
$host_base = 'dc=egroupware';
|
||||
$host_attr = 'l';
|
||||
$host_default = '10.40.8.200';
|
||||
*/
|
||||
|
||||
// to return Dovecot extra system_groups_user
|
||||
$group_base = $ldap_base;
|
||||
$group_filter = '(&(objectCategory=group)(member=%x))';
|
||||
$group_attr = 'cn';
|
||||
$group_append = ''; //'@%d';
|
||||
|
||||
$master_dn = $bind_dn; //"cn=admin,dc=egroupware";
|
||||
//$domain_master_dn = "cn=admin,o=%d,dc=egroupware";
|
||||
|
||||
ini_set('display_errors',false);
|
||||
error_reporting(E_ALL & ~E_NOTICE);
|
||||
if ($log) ini_set('error_log',$log);
|
||||
|
||||
if ($_SERVER['argc'] < 2)
|
||||
{
|
||||
fwrite(STDERR,"\nUsage: {$_SERVER['argv'][0]} prog-to-exec\n\n");
|
||||
fwrite(STDERR,"To test run:\n");
|
||||
fwrite(STDERR,"echo -en 'username\\0000''password\\0000' | {$_SERVER['argv'][0]} env 3<&0 ; echo $?\n");
|
||||
fwrite(STDERR,"echo -en 'username\\0000' | AUTHORIZED=1 {$_SERVER['argv'][0]} env 3<&0 ; echo $?\n");
|
||||
fwrite(STDERR,"echo -en '(dovecode-admin@domain|dovecot|cyrus)\\0000''master-password\\0000' | AUTH_LOGIN_USER=username {$_SERVER['argv'][0]} env 3<&0 ; echo $?\n\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
list($username,$password) = explode("\0",file_get_contents('php://fd/3'));
|
||||
if (isset($_SERVER['AUTH_LOGIN_USER']))
|
||||
{
|
||||
$master = $username;
|
||||
$username = $_SERVER['AUTH_LOGIN_USER'];
|
||||
}
|
||||
//error_log("dovecot_checkpassword '{$_SERVER['argv'][1]}': username='$username', password='$password', master='$master'");
|
||||
|
||||
$ds = ldap_connect($ldap_uri);
|
||||
if ($version) ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, $version);
|
||||
if ($use_tls) ldap_start_tls($ds);
|
||||
|
||||
if (!@ldap_bind($ds, $bind_dn, $bind_pw))
|
||||
{
|
||||
error_log("Can't connect to LDAP server $ldap_uri!");
|
||||
exit(111); // 111 = temporary problem
|
||||
}
|
||||
list(,$domain) = explode('@',$username);
|
||||
if (preg_match('/^(.*)\.imapc$/',$domain,$matches))
|
||||
{
|
||||
$domain = $matches[1];
|
||||
|
||||
$username = explode('.', $username);
|
||||
array_pop($username);
|
||||
$username = implode('.',$username);
|
||||
|
||||
$user_home = '/var/tmp/imapc-%d/%s';
|
||||
$extra = array(
|
||||
'userdb_mail' => 'imapc:/var/tmp/imapc-'.$domain.'/'.$username,
|
||||
//'userdb_imapc_password' => $password,
|
||||
//'userdb_imapc_host' => 'hugo.de',
|
||||
);
|
||||
}
|
||||
|
||||
$replace = array(
|
||||
'%d' => $domain,
|
||||
'%s' => $username,
|
||||
);
|
||||
$base = strtr($search_base, $replace);
|
||||
|
||||
if (($passdb_query = !isset($_SERVER['AUTHORIZED']) || $_SERVER['AUTHORIZED'] != 1))
|
||||
{
|
||||
$filter = $passdb_filter;
|
||||
|
||||
// authenticate with master user/password
|
||||
// master user name is hardcoded "dovecot", "cyrus" or "dovecot-admin@domain" and mapped currently to cn=admin,[o=domain,]dc=egroupware
|
||||
if (isset($master))
|
||||
{
|
||||
list($n,$d) = explode('@', $master);
|
||||
if (!($n === 'dovecot-admin' && $d === $domain || in_array($master,array('dovecot','cyrus'))))
|
||||
{
|
||||
// no valid master-user for given domain
|
||||
exit(1);
|
||||
}
|
||||
$dn = $d ? strtr($domain_master_dn,array('%d'=>$domain)) : $master_dn;
|
||||
if (!@ldap_bind($ds, $dn, $password))
|
||||
{
|
||||
if ($log_verbose) error_log("Can't bind as '$dn' with password '$password'! Authentication as master '$master' for user '$username' failed!");
|
||||
exit(111); // 111 = temporary problem
|
||||
}
|
||||
if ($log_verbose) error_log("Authentication as master '$master' for user '$username' succeeded!");
|
||||
$passdb_query = false;
|
||||
$filter = $userdb_filter;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$filter = $userdb_filter;
|
||||
putenv('AUTHORIZED=2');
|
||||
}
|
||||
$filter = strtr($filter, quote($replace));
|
||||
|
||||
// remove prefixes eg. "{quota:}proxyaddresses"
|
||||
$attrs = $user_attrs;
|
||||
foreach($attrs as &$a) if ($a[0] == '{') list(,$a) = explode('}', $a);
|
||||
|
||||
if (!($sr = ldap_search($ds, $base, $filter, array_values($attrs))))
|
||||
{
|
||||
error_log("Error ldap_search(\$ds, '$base', '$filter')!");
|
||||
exit(111); // 111 = temporary problem
|
||||
}
|
||||
$entries = ldap_get_entries($ds, $sr);
|
||||
|
||||
if (!$entries['count'])
|
||||
{
|
||||
if ($log_verbose) error_log("User '$username' NOT found!");
|
||||
exit(3);
|
||||
}
|
||||
|
||||
if ($entries['count'] > 1)
|
||||
{
|
||||
// should not happen for passdb, but could happen for aliases ...
|
||||
error_log("Error ldap_search(\$ds, '$base', '$filter') returned more then one user!");
|
||||
exit(111); // 111 = temporary problem
|
||||
}
|
||||
//print_r($entries);
|
||||
|
||||
if ($passdb_query)
|
||||
{
|
||||
// now authenticate user by trying to bind to found dn with given password
|
||||
if (!@ldap_bind($ds, $entries[0]['dn'], $password))
|
||||
{
|
||||
if ($log_verbose) error_log("Can't bind as '{$entries[0]['dn']}' with password '$password'! Authentication for user '$username' failed!");
|
||||
exit(1);
|
||||
}
|
||||
if ($log_verbose) error_log("Successfull authentication user '$username' dn='{$entries[0]['dn']}'.");
|
||||
}
|
||||
else // user-db query, no authentication
|
||||
{
|
||||
if ($log_verbose) error_log("User-db query for user '$username' dn='{$entries[0]['dn']}'.");
|
||||
}
|
||||
|
||||
// add additional placeholders from $user_attrs
|
||||
foreach($user_attrs as $placeholder => $attr)
|
||||
{
|
||||
if ($attr[0] == '{') // prefix given --> ignore all values without and remove it
|
||||
{
|
||||
list($prefix, $attr) = explode('}', substr($attr, 1));
|
||||
foreach($entries[0][$attr] as $key => $value)
|
||||
{
|
||||
if ($key === 'count') continue;
|
||||
if (strpos($value, $prefix) !== 0) continue;
|
||||
$replace[$placeholder] = substr($value, strlen($prefix));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$replace[$placeholder] = is_array($entries[0][$attr]) ? $entries[0][$attr][0] : $entries[0][$attr];
|
||||
}
|
||||
}
|
||||
|
||||
// search memberships
|
||||
if (isset($group_base) && $group_filter && $group_attr)
|
||||
{
|
||||
$base = strtr($group_base, $replace);
|
||||
$filter = strtr($group_filter, quote($replace));
|
||||
$append = strtr($group_append, $replace);
|
||||
if (($sr = ldap_search($ds, $base, $filter, array($group_attr))) &&
|
||||
($groups = ldap_get_entries($ds, $sr)) && $groups['count'])
|
||||
{
|
||||
//print_r($groups);
|
||||
$system_groups_user = array();
|
||||
foreach($groups as $key => $group)
|
||||
{
|
||||
if ($key === 'count') continue;
|
||||
$system_groups_user[] = $group[$group_attr][0].$append;
|
||||
}
|
||||
$extra['system_groups_user'] = implode(',', $system_groups_user); // todo: check separator
|
||||
}
|
||||
else
|
||||
{
|
||||
error_log("Error searching for memberships ldap_search(\$ds, '$base', '$filter')!");
|
||||
}
|
||||
}
|
||||
|
||||
// set host attribute for director to old imap
|
||||
if (isset($host_base) && isset($host_filter))
|
||||
{
|
||||
if (!($sr = ldap_search($ds, $host_base, $filter=strtr($host_filter, quote($replace)), array($host_attr))))
|
||||
{
|
||||
error_log("Error ldap_search(\$ds, '$host_base', '$filter')!");
|
||||
exit(111); // 111 = temporary problem
|
||||
}
|
||||
$entries = ldap_get_entries($ds, $sr);
|
||||
if ($entries['count'] && !isset($entries[0][$host_attr]))
|
||||
{
|
||||
$extra['host'] = $host_default;
|
||||
}
|
||||
}
|
||||
// close ldap connection
|
||||
ldap_unbind($ds);
|
||||
|
||||
// build command to run
|
||||
array_shift($_SERVER['argv']);
|
||||
$cmd = array_shift($_SERVER['argv']);
|
||||
foreach($_SERVER['argv'] as $arg)
|
||||
{
|
||||
$cmd .= ' '.escapeshellarg($arg);
|
||||
}
|
||||
|
||||
// setting USER, HOME, EXTRA
|
||||
putenv('USER='.strtr($user_name, $replace));
|
||||
if ($user_home) putenv('HOME='.strtr($user_home, $replace));
|
||||
if ($extra)
|
||||
{
|
||||
foreach($extra as $name => $value)
|
||||
{
|
||||
if (($pos = strpos($value,'%')) !== false)
|
||||
{
|
||||
// check if replacement is set, otherwise skip whole extra-value
|
||||
if (!isset($replace[substr($value,$pos,2)]))
|
||||
{
|
||||
unset($extra[$name]);
|
||||
continue;
|
||||
}
|
||||
$value = strtr($value,$replace);
|
||||
}
|
||||
putenv($name.'='.$value);
|
||||
}
|
||||
putenv('EXTRA='.implode(' ', array_keys($extra)));
|
||||
}
|
||||
|
||||
// call given command and exit with it's exit-status
|
||||
passthru($cmd, $ret);
|
||||
|
||||
exit($ret);
|
||||
|
||||
/**
|
||||
* escapes a string for use in searchfilters meant for ldap_search.
|
||||
*
|
||||
* Escaped Characters are: '*', '(', ')', ' ', '\', NUL
|
||||
* It's actually a PHP-Bug, that we have to escape space.
|
||||
* For all other Characters, refer to RFC2254.
|
||||
*
|
||||
* @param string|array $string either a string to be escaped, or an array of values to be escaped
|
||||
* @return string
|
||||
*/
|
||||
function quote($string)
|
||||
{
|
||||
return str_replace(array('\\','*','(',')','\0',' '),array('\\\\','\*','\(','\)','\\0','\20'),$string);
|
||||
}
|
754
doc/mail/main.cf
Normal file
754
doc/mail/main.cf
Normal file
@ -0,0 +1,754 @@
|
||||
# Global Postfix configuration file. This file lists only a subset
|
||||
# of all 300+ parameters. See the sample-xxx.cf files for a full list.
|
||||
#
|
||||
# The general format is lines with parameter = value pairs. Lines
|
||||
# that begin with whitespace continue the previous line. A value can
|
||||
# contain references to other $names or ${name}s.
|
||||
#
|
||||
# NOTE - CHANGE NO MORE THAN 2-3 PARAMETERS AT A TIME, AND TEST IF
|
||||
# POSTFIX STILL WORKS AFTER EVERY CHANGE.
|
||||
|
||||
# SOFT BOUNCE
|
||||
#
|
||||
# The soft_bounce parameter provides a limited safety net for
|
||||
# testing. When soft_bounce is enabled, mail will remain queued that
|
||||
# would otherwise bounce. This parameter disables locally-generated
|
||||
# bounces, and prevents the SMTP server from rejecting mail permanently
|
||||
# (by changing 5xx replies into 4xx replies). However, soft_bounce
|
||||
# is no cure for address rewriting mistakes or mail routing mistakes.
|
||||
#
|
||||
#soft_bounce = no
|
||||
|
||||
# LOCAL PATHNAME INFORMATION
|
||||
#
|
||||
# The queue_directory specifies the location of the Postfix queue.
|
||||
# This is also the root directory of Postfix daemons that run chrooted.
|
||||
# See the files in examples/chroot-setup for setting up Postfix chroot
|
||||
# environments on different UNIX systems.
|
||||
#
|
||||
queue_directory = /var/spool/postfix
|
||||
|
||||
# The command_directory parameter specifies the location of all
|
||||
# postXXX commands.
|
||||
#
|
||||
command_directory = /usr/sbin
|
||||
|
||||
# The daemon_directory parameter specifies the location of all Postfix
|
||||
# daemon programs (i.e. programs listed in the master.cf file). This
|
||||
# directory must be owned by root.
|
||||
#
|
||||
daemon_directory = /usr/lib/postfix
|
||||
|
||||
# QUEUE AND PROCESS OWNERSHIP
|
||||
#
|
||||
# The mail_owner parameter specifies the owner of the Postfix queue
|
||||
# and of most Postfix daemon processes. Specify the name of a user
|
||||
# account THAT DOES NOT SHARE ITS USER OR GROUP ID WITH OTHER ACCOUNTS
|
||||
# AND THAT OWNS NO OTHER FILES OR PROCESSES ON THE SYSTEM. In
|
||||
# particular, don't specify nobody or daemon. PLEASE USE A DEDICATED
|
||||
# USER.
|
||||
#
|
||||
mail_owner = postfix
|
||||
|
||||
# The default_privs parameter specifies the default rights used by
|
||||
# the local delivery agent for delivery to external file or command.
|
||||
# These rights are used in the absence of a recipient user context.
|
||||
# DO NOT SPECIFY A PRIVILEGED USER OR THE POSTFIX OWNER.
|
||||
#
|
||||
#default_privs = nobody
|
||||
|
||||
# INTERNET HOST AND DOMAIN NAMES
|
||||
#
|
||||
# The myhostname parameter specifies the internet hostname of this
|
||||
# mail system. The default is to use the fully-qualified domain name
|
||||
# from gethostname(). $myhostname is used as a default value for many
|
||||
# other configuration parameters.
|
||||
#
|
||||
#myhostname = host.domain.tld
|
||||
#myhostname = virtual.domain.tld
|
||||
|
||||
# The mydomain parameter specifies the local internet domain name.
|
||||
# The default is to use $myhostname minus the first component.
|
||||
# $mydomain is used as a default value for many other configuration
|
||||
# parameters.
|
||||
#
|
||||
#mydomain = domain.tld
|
||||
|
||||
# SENDING MAIL
|
||||
#
|
||||
# The myorigin parameter specifies the domain that locally-posted
|
||||
# mail appears to come from. The default is to append $myhostname,
|
||||
# which is fine for small sites. If you run a domain with multiple
|
||||
# machines, you should (1) change this to $mydomain and (2) set up
|
||||
# a domain-wide alias database that aliases each user to
|
||||
# user@that.users.mailhost.
|
||||
#
|
||||
# For the sake of consistency between sender and recipient addresses,
|
||||
# myorigin also specifies the default domain name that is appended
|
||||
# to recipient addresses that have no @domain part.
|
||||
#
|
||||
#myorigin = $myhostname
|
||||
#myorigin = $mydomain
|
||||
|
||||
# RECEIVING MAIL
|
||||
|
||||
# The inet_interfaces parameter specifies the network interface
|
||||
# addresses that this mail system receives mail on. By default,
|
||||
# the software claims all active interfaces on the machine. The
|
||||
# parameter also controls delivery of mail to user@[ip.address].
|
||||
#
|
||||
# See also the proxy_interfaces parameter, for network addresses that
|
||||
# are forwarded to us via a proxy or network address translator.
|
||||
#
|
||||
# Note: you need to stop/start Postfix when this parameter changes.
|
||||
#
|
||||
#inet_interfaces = all
|
||||
#inet_interfaces = $myhostname
|
||||
#inet_interfaces = $myhostname, localhost
|
||||
|
||||
# The proxy_interfaces parameter specifies the network interface
|
||||
# addresses that this mail system receives mail on by way of a
|
||||
# proxy or network address translation unit. This setting extends
|
||||
# the address list specified with the inet_interfaces parameter.
|
||||
#
|
||||
# You must specify your proxy/NAT addresses when your system is a
|
||||
# backup MX host for other domains, otherwise mail delivery loops
|
||||
# will happen when the primary MX host is down.
|
||||
#
|
||||
#proxy_interfaces =
|
||||
#proxy_interfaces = 1.2.3.4
|
||||
|
||||
# The mydestination parameter specifies the list of domains that this
|
||||
# machine considers itself the final destination for.
|
||||
#
|
||||
# These domains are routed to the delivery agent specified with the
|
||||
# local_transport parameter setting. By default, that is the UNIX
|
||||
# compatible delivery agent that lookups all recipients in /etc/passwd
|
||||
# and /etc/aliases or their equivalent.
|
||||
#
|
||||
# The default is $myhostname + localhost.$mydomain. On a mail domain
|
||||
# gateway, you should also include $mydomain.
|
||||
#
|
||||
# Do not specify the names of virtual domains - those domains are
|
||||
# specified elsewhere (see sample-virtual.cf).
|
||||
#
|
||||
# Do not specify the names of domains that this machine is backup MX
|
||||
# host for. Specify those names via the relay_domains settings for
|
||||
# the SMTP server, or use permit_mx_backup if you are lazy (see
|
||||
# sample-smtpd.cf).
|
||||
#
|
||||
# The local machine is always the final destination for mail addressed
|
||||
# to user@[the.net.work.address] of an interface that the mail system
|
||||
# receives mail on (see the inet_interfaces parameter).
|
||||
#
|
||||
# Specify a list of host or domain names, /file/name or type:table
|
||||
# patterns, separated by commas and/or whitespace. A /file/name
|
||||
# pattern is replaced by its contents; a type:table is matched when
|
||||
# a name matches a lookup key (the right-hand side is ignored).
|
||||
# Continue long lines by starting the next line with whitespace.
|
||||
#
|
||||
# DO NOT LIST RELAY DESTINATIONS IN MYDESTINATION.
|
||||
# SPECIFY RELAY DESTINATIONS IN RELAY_DOMAINS.
|
||||
#
|
||||
# See also below, section "REJECTING MAIL FOR UNKNOWN LOCAL USERS".
|
||||
#
|
||||
#mydestination = $myhostname, localhost.$mydomain
|
||||
#mydestination = $myhostname, localhost.$mydomain $mydomain
|
||||
#mydestination = $myhostname, localhost.$mydomain, $mydomain,
|
||||
# mail.$mydomain, www.$mydomain, ftp.$mydomain
|
||||
mydestination = $myhostname, localhost.$mydomain $mydomain,
|
||||
kneschke.de, phpgw.de, egroupware.org, linux-at-work.de, lists.kneschke.de
|
||||
|
||||
# REJECTING MAIL FOR UNKNOWN LOCAL USERS
|
||||
#
|
||||
# The local_recipient_maps parameter specifies optional lookup tables
|
||||
# with all names or addresses of users that are local with respect
|
||||
# to $mydestination and $inet_interfaces.
|
||||
#
|
||||
# If this parameter is defined, then the SMTP server will reject
|
||||
# mail for unknown local users. This parameter is defined by default.
|
||||
#
|
||||
# To turn off local recipient checking in the SMTP server, specify
|
||||
# local_recipient_maps = (i.e. empty).
|
||||
#
|
||||
# The default setting assumes that you use the default Postfix local
|
||||
# delivery agent for local delivery. You need to update the
|
||||
# local_recipient_maps setting if:
|
||||
#
|
||||
# - You define $mydestination domain recipients in files other than
|
||||
# /etc/passwd, /etc/aliases, or the $virtual_alias_maps files.
|
||||
# For example, you define $mydestination domain recipients in
|
||||
# the $virtual_mailbox_maps files.
|
||||
#
|
||||
# - You redefine the local delivery agent in master.cf.
|
||||
#
|
||||
# - You redefine the "local_transport" setting in main.cf.
|
||||
#
|
||||
# - You use the "luser_relay", "mailbox_transport", or "fallback_transport"
|
||||
# feature of the Postfix local delivery agent (see sample-local.cf).
|
||||
#
|
||||
# Details are described in the LOCAL_RECIPIENT_README file.
|
||||
#
|
||||
# Beware: if the Postfix SMTP server runs chrooted, you probably have
|
||||
# to access the passwd file via the proxymap service, in order to
|
||||
# overcome chroot restrictions. The alternative, having a copy of
|
||||
# the system passwd file in the chroot jail is just not practical.
|
||||
#
|
||||
# The right-hand side of the lookup tables is conveniently ignored.
|
||||
# In the left-hand side, specify a bare username, an @domain.tld
|
||||
# wild-card, or specify a user@domain.tld address.
|
||||
#
|
||||
#local_recipient_maps = unix:passwd.byname $alias_maps
|
||||
#local_recipient_maps = proxy:unix:passwd.byname $alias_maps
|
||||
#local_recipient_maps =
|
||||
|
||||
# The unknown_local_recipient_reject_code specifies the SMTP server
|
||||
# response code when a recipient domain matches $mydestination or
|
||||
# $inet_interfaces, while $local_recipient_maps is non-empty and the
|
||||
# recipient address or address local-part is not found.
|
||||
#
|
||||
# The default setting is 550 (reject mail) but it is safer to start
|
||||
# with 450 (try again later) until you are certain that your
|
||||
# local_recipient_maps settings are OK.
|
||||
#
|
||||
unknown_local_recipient_reject_code = 550
|
||||
#unknown_local_recipient_reject_code = 450
|
||||
|
||||
# TRUST AND RELAY CONTROL
|
||||
|
||||
# The mynetworks parameter specifies the list of "trusted" SMTP
|
||||
# clients that have more privileges than "strangers".
|
||||
#
|
||||
# In particular, "trusted" SMTP clients are allowed to relay mail
|
||||
# through Postfix. See the smtpd_recipient_restrictions parameter
|
||||
# in file sample-smtpd.cf.
|
||||
#
|
||||
# You can specify the list of "trusted" network addresses by hand
|
||||
# or you can let Postfix do it for you (which is the default).
|
||||
#
|
||||
# By default (mynetworks_style = subnet), Postfix "trusts" SMTP
|
||||
# clients in the same IP subnetworks as the local machine.
|
||||
# On Linux, this does works correctly only with interfaces specified
|
||||
# with the "ifconfig" command.
|
||||
#
|
||||
# Specify "mynetworks_style = class" when Postfix should "trust" SMTP
|
||||
# clients in the same IP class A/B/C networks as the local machine.
|
||||
# Don't do this with a dialup site - it would cause Postfix to "trust"
|
||||
# your entire provider's network. Instead, specify an explicit
|
||||
# mynetworks list by hand, as described below.
|
||||
#
|
||||
# Specify "mynetworks_style = host" when Postfix should "trust"
|
||||
# only the local machine.
|
||||
#
|
||||
#mynetworks_style = class
|
||||
#mynetworks_style = subnet
|
||||
#mynetworks_style = host
|
||||
|
||||
# Alternatively, you can specify the mynetworks list by hand, in
|
||||
# which case Postfix ignores the mynetworks_style setting.
|
||||
#
|
||||
# Specify an explicit list of network/netmask patterns, where the
|
||||
# mask specifies the number of bits in the network part of a host
|
||||
# address.
|
||||
#
|
||||
# You can also specify the absolute pathname of a pattern file instead
|
||||
# of listing the patterns here. Specify type:table for table-based lookups
|
||||
# (the value on the table right-hand side is not used).
|
||||
#
|
||||
#mynetworks = 168.100.189.0/28, 127.0.0.0/8
|
||||
#mynetworks = $config_directory/mynetworks
|
||||
#mynetworks = hash:/etc/postfix/network_table
|
||||
|
||||
# The relay_domains parameter restricts what destinations this system will
|
||||
# relay mail to. See the smtpd_recipient_restrictions restriction in the
|
||||
# file sample-smtpd.cf for detailed information.
|
||||
#
|
||||
# By default, Postfix relays mail
|
||||
# - from "trusted" clients (IP address matches $mynetworks) to any destination,
|
||||
# - from "untrusted" clients to destinations that match $relay_domains or
|
||||
# subdomains thereof, except addresses with sender-specified routing.
|
||||
# The default relay_domains value is $mydestination.
|
||||
#
|
||||
# In addition to the above, the Postfix SMTP server by default accepts mail
|
||||
# that Postfix is final destination for:
|
||||
# - destinations that match $inet_interfaces,
|
||||
# - destinations that match $mydestination
|
||||
# - destinations that match $virtual_alias_domains,
|
||||
# - destinations that match $virtual_mailbox_domains.
|
||||
# These destinations do not need to be listed in $relay_domains.
|
||||
#
|
||||
# Specify a list of hosts or domains, /file/name patterns or type:name
|
||||
# lookup tables, separated by commas and/or whitespace. Continue
|
||||
# long lines by starting the next line with whitespace. A file name
|
||||
# is replaced by its contents; a type:name table is matched when a
|
||||
# (parent) domain appears as lookup key.
|
||||
#
|
||||
# NOTE: Postfix will not automatically forward mail for domains that
|
||||
# list this system as their primary or backup MX host. See the
|
||||
# permit_mx_backup restriction in the file sample-smtpd.cf.
|
||||
#
|
||||
#relay_domains = $mydestination
|
||||
|
||||
# INTERNET OR INTRANET
|
||||
|
||||
# The relayhost parameter specifies the default host to send mail to
|
||||
# when no entry is matched in the optional transport(5) table. When
|
||||
# no relayhost is given, mail is routed directly to the destination.
|
||||
#
|
||||
# On an intranet, specify the organizational domain name. If your
|
||||
# internal DNS uses no MX records, specify the name of the intranet
|
||||
# gateway host instead.
|
||||
#
|
||||
# In the case of SMTP, specify a domain, host, host:port, [host]:port,
|
||||
# [address] or [address]:port; the form [host] turns off MX lookups.
|
||||
#
|
||||
# If you're connected via UUCP, see also the default_transport parameter.
|
||||
#
|
||||
#relayhost = $mydomain
|
||||
#relayhost = gateway.my.domain
|
||||
#relayhost = uucphost
|
||||
#relayhost = [an.ip.add.ress]
|
||||
|
||||
# REJECTING UNKNOWN RELAY USERS
|
||||
#
|
||||
# The relay_recipient_maps parameter specifies optional lookup tables
|
||||
# with all addresses in the domains that match $relay_domains.
|
||||
#
|
||||
# If this parameter is defined, then the SMTP server will reject
|
||||
# mail for unknown relay users. This feature is off by default.
|
||||
#
|
||||
# The right-hand side of the lookup tables is conveniently ignored.
|
||||
# In the left-hand side, specify an @domain.tld wild-card, or specify
|
||||
# a user@domain.tld address.
|
||||
#
|
||||
#relay_recipient_maps = hash:/etc/postfix/relay_recipients
|
||||
|
||||
# INPUT RATE CONTROL
|
||||
#
|
||||
# The in_flow_delay configuration parameter implements mail input
|
||||
# flow control. This feature is turned on by default, although it
|
||||
# still needs further development (it's disabled on SCO UNIX due
|
||||
# to an SCO bug).
|
||||
#
|
||||
# A Postfix process will pause for $in_flow_delay seconds before
|
||||
# accepting a new message, when the message arrival rate exceeds the
|
||||
# message delivery rate. With the default 100 SMTP server process
|
||||
# limit, this limits the mail inflow to 100 messages a second more
|
||||
# than the number of messages delivered per second.
|
||||
#
|
||||
# Specify 0 to disable the feature. Valid delays are 0..10.
|
||||
#
|
||||
#in_flow_delay = 1s
|
||||
|
||||
# ADDRESS REWRITING
|
||||
#
|
||||
# Insert text from sample-rewrite.cf if you need to do address
|
||||
# masquerading.
|
||||
#
|
||||
# Insert text from sample-canonical.cf if you need to do address
|
||||
# rewriting, or if you need username->Firstname.Lastname mapping.
|
||||
|
||||
# ADDRESS REDIRECTION (VIRTUAL DOMAIN)
|
||||
#
|
||||
# Insert text from sample-virtual.cf if you need virtual domain support.
|
||||
|
||||
# "USER HAS MOVED" BOUNCE MESSAGES
|
||||
#
|
||||
# Insert text from sample-relocated.cf if you need "user has moved"
|
||||
# style bounce messages. Alternatively, you can bounce recipients
|
||||
# with an SMTP server access table. See sample-smtpd.cf.
|
||||
|
||||
# TRANSPORT MAP
|
||||
#
|
||||
# Insert text from sample-transport.cf if you need explicit routing.
|
||||
|
||||
# ALIAS DATABASE
|
||||
#
|
||||
# The alias_maps parameter specifies the list of alias databases used
|
||||
# by the local delivery agent. The default list is system dependent.
|
||||
#
|
||||
# On systems with NIS, the default is to search the local alias
|
||||
# database, then the NIS alias database. See aliases(5) for syntax
|
||||
# details.
|
||||
#
|
||||
# If you change the alias database, run "postalias /etc/aliases" (or
|
||||
# wherever your system stores the mail alias file), or simply run
|
||||
# "newaliases" to build the necessary DBM or DB file.
|
||||
#
|
||||
# It will take a minute or so before changes become visible. Use
|
||||
# "postfix reload" to eliminate the delay.
|
||||
#
|
||||
#alias_maps = dbm:/etc/aliases
|
||||
#alias_maps = hash:/etc/aliases
|
||||
#alias_maps = hash:/etc/aliases, nis:mail.aliases
|
||||
#alias_maps = netinfo:/aliases
|
||||
|
||||
# The alias_database parameter specifies the alias database(s) that
|
||||
# are built with "newaliases" or "sendmail -bi". This is a separate
|
||||
# configuration parameter, because alias_maps (see above) may specify
|
||||
# tables that are not necessarily all under control by Postfix.
|
||||
#
|
||||
#alias_database = dbm:/etc/aliases
|
||||
#alias_database = dbm:/etc/mail/aliases
|
||||
#alias_database = hash:/etc/aliases
|
||||
#alias_database = hash:/etc/aliases, hash:/opt/majordomo/aliases
|
||||
|
||||
# ADDRESS EXTENSIONS (e.g., user+foo)
|
||||
#
|
||||
# The recipient_delimiter parameter specifies the separator between
|
||||
# user names and address extensions (user+foo). See canonical(5),
|
||||
# local(8), relocated(5) and virtual(5) for the effects this has on
|
||||
# aliases, canonical, virtual, relocated and .forward file lookups.
|
||||
# Basically, the software tries user+foo and .forward+foo before
|
||||
# trying user and .forward.
|
||||
#
|
||||
#recipient_delimiter = +
|
||||
|
||||
# DELIVERY TO MAILBOX
|
||||
#
|
||||
# The home_mailbox parameter specifies the optional pathname of a
|
||||
# mailbox file relative to a user's home directory. The default
|
||||
# mailbox file is /var/spool/mail/user or /var/mail/user. Specify
|
||||
# "Maildir/" for qmail-style delivery (the / is required).
|
||||
#
|
||||
#home_mailbox = Mailbox
|
||||
#home_mailbox = Maildir/
|
||||
|
||||
# The mail_spool_directory parameter specifies the directory where
|
||||
# UNIX-style mailboxes are kept. The default setting depends on the
|
||||
# system type.
|
||||
#
|
||||
#mail_spool_directory = /var/mail
|
||||
#mail_spool_directory = /var/spool/mail
|
||||
|
||||
# The mailbox_command parameter specifies the optional external
|
||||
# command to use instead of mailbox delivery. The command is run as
|
||||
# the recipient with proper HOME, SHELL and LOGNAME environment settings.
|
||||
# Exception: delivery for root is done as $default_user.
|
||||
#
|
||||
# Other environment variables of interest: USER (recipient username),
|
||||
# EXTENSION (address extension), DOMAIN (domain part of address),
|
||||
# and LOCAL (the address localpart).
|
||||
#
|
||||
# Unlike other Postfix configuration parameters, the mailbox_command
|
||||
# parameter is not subjected to $parameter substitutions. This is to
|
||||
# make it easier to specify shell syntax (see example below).
|
||||
#
|
||||
# Avoid shell meta characters because they will force Postfix to run
|
||||
# an expensive shell process. Procmail alone is expensive enough.
|
||||
#
|
||||
# IF YOU USE THIS TO DELIVER MAIL SYSTEM-WIDE, YOU MUST SET UP AN
|
||||
# ALIAS THAT FORWARDS MAIL FOR ROOT TO A REAL USER.
|
||||
#
|
||||
#mailbox_command = /some/where/procmail
|
||||
#mailbox_command = /some/where/procmail -a "$EXTENSION"
|
||||
|
||||
# The mailbox_transport specifies the optional transport in master.cf
|
||||
# to use after processing aliases and .forward files. This parameter
|
||||
# has precedence over the mailbox_command, fallback_transport and
|
||||
# luser_relay parameters.
|
||||
#
|
||||
# Specify a string of the form transport:nexthop, where transport is
|
||||
# the name of a mail delivery transport defined in master.cf. The
|
||||
# :nexthop part is optional. For more details see the sample transport
|
||||
# configuration file.
|
||||
#
|
||||
# NOTE: if you use this feature for accounts not in the UNIX password
|
||||
# file, then you must update the "local_recipient_maps" setting in
|
||||
# the main.cf file, otherwise the SMTP server will reject mail for
|
||||
# non-UNIX accounts with "User unknown in local recipient table".
|
||||
#
|
||||
#mailbox_transport = lmtp:unix:/file/name
|
||||
mailbox_transport = lmtp:unix:/var/imap/socket/lmtp
|
||||
#mailbox_transport = cyrus
|
||||
|
||||
# The fallback_transport specifies the optional transport in master.cf
|
||||
# to use for recipients that are not found in the UNIX passwd database.
|
||||
# This parameter has precedence over the luser_relay parameter.
|
||||
#
|
||||
# Specify a string of the form transport:nexthop, where transport is
|
||||
# the name of a mail delivery transport defined in master.cf. The
|
||||
# :nexthop part is optional. For more details see the sample transport
|
||||
# configuration file.
|
||||
#
|
||||
# NOTE: if you use this feature for accounts not in the UNIX password
|
||||
# file, then you must update the "local_recipient_maps" setting in
|
||||
# the main.cf file, otherwise the SMTP server will reject mail for
|
||||
# non-UNIX accounts with "User unknown in local recipient table".
|
||||
#
|
||||
#fallback_transport = lmtp:unix:/file/name
|
||||
#fallback_transport = cyrus
|
||||
#fallback_transport =
|
||||
|
||||
# The luser_relay parameter specifies an optional destination address
|
||||
# for unknown recipients. By default, mail for unknown@$mydestination
|
||||
# and unknown@[$inet_interfaces] is returned as undeliverable.
|
||||
#
|
||||
# The following expansions are done on luser_relay: $user (recipient
|
||||
# username), $shell (recipient shell), $home (recipient home directory),
|
||||
# $recipient (full recipient address), $extension (recipient address
|
||||
# extension), $domain (recipient domain), $local (entire recipient
|
||||
# localpart), $recipient_delimiter. Specify ${name?value} or
|
||||
# ${name:value} to expand value only when $name does (does not) exist.
|
||||
#
|
||||
# luser_relay works only for the default Postfix local delivery agent.
|
||||
#
|
||||
# NOTE: if you use this feature for accounts not in the UNIX password
|
||||
# file, then you must specify "local_recipient_maps =" (i.e. empty) in
|
||||
# the main.cf file, otherwise the SMTP server will reject mail for
|
||||
# non-UNIX accounts with "User unknown in local recipient table".
|
||||
#
|
||||
#luser_relay = $user@other.host
|
||||
#luser_relay = $local@other.host
|
||||
#luser_relay = admin+$local
|
||||
|
||||
# JUNK MAIL CONTROLS
|
||||
#
|
||||
# The controls listed here are only a very small subset. See the file
|
||||
# sample-smtpd.cf for an elaborate list of anti-UCE controls.
|
||||
|
||||
# The header_checks parameter specifies an optional table with patterns
|
||||
# that each logical message header is matched against, including
|
||||
# headers that span multiple physical lines.
|
||||
#
|
||||
# By default, these patterns also apply to MIME headers and to the
|
||||
# headers of attached messages. With older Postfix versions, MIME and
|
||||
# attached message headers were treated as body text.
|
||||
#
|
||||
# For details, see the sample-filter.cf file.
|
||||
#
|
||||
#header_checks = regexp:/etc/postfix/header_checks
|
||||
|
||||
# FAST ETRN SERVICE
|
||||
#
|
||||
# Postfix maintains per-destination logfiles with information about
|
||||
# deferred mail, so that mail can be flushed quickly with the SMTP
|
||||
# "ETRN domain.tld" command, or by executing "sendmail -qRdomain.tld".
|
||||
#
|
||||
# By default, Postfix maintains deferred mail logfile information
|
||||
# only for destinations that Postfix is willing to relay to (as
|
||||
# specified in the relay_domains parameter). For other destinations,
|
||||
# Postfix attempts to deliver ALL queued mail after receiving the
|
||||
# SMTP "ETRN domain.tld" command, or after execution of "sendmail
|
||||
# -qRdomain.tld". This can be slow when a lot of mail is queued.
|
||||
#
|
||||
# The fast_flush_domains parameter controls what destinations are
|
||||
# eligible for this "fast ETRN/sendmail -qR" service.
|
||||
#
|
||||
#fast_flush_domains = $relay_domains
|
||||
#fast_flush_domains =
|
||||
|
||||
# The disable_vrfy_command parameter allows you to disable the SMTP
|
||||
# VRFY command. This stops some techniques used by spammers to harvest
|
||||
# email addresses.
|
||||
#
|
||||
disable_vrfy_command = yes
|
||||
|
||||
# SHOW SOFTWARE VERSION OR NOT
|
||||
#
|
||||
# The smtpd_banner parameter specifies the text that follows the 220
|
||||
# code in the SMTP server's greeting banner. Some people like to see
|
||||
# the mail version advertised. By default, Postfix shows no version.
|
||||
#
|
||||
# You MUST specify $myhostname at the start of the text. That is an
|
||||
# RFC requirement. Postfix itself does not care.
|
||||
#
|
||||
#smtpd_banner = $myhostname ESMTP $mail_name
|
||||
#smtpd_banner = $myhostname ESMTP $mail_name ($mail_version)
|
||||
|
||||
# PARALLEL DELIVERY TO THE SAME DESTINATION
|
||||
#
|
||||
# How many parallel deliveries to the same user or domain? With local
|
||||
# delivery, it does not make sense to do massively parallel delivery
|
||||
# to the same user, because mailbox updates must happen sequentially,
|
||||
# and expensive pipelines in .forward files can cause disasters when
|
||||
# too many are run at the same time. With SMTP deliveries, 10
|
||||
# simultaneous connections to the same domain could be sufficient to
|
||||
# raise eyebrows.
|
||||
#
|
||||
# Each message delivery transport has its XXX_destination_concurrency_limit
|
||||
# parameter. The default is $default_destination_concurrency_limit for
|
||||
# most delivery transports. For the local delivery agent the default is 2.
|
||||
|
||||
#local_destination_concurrency_limit = 2
|
||||
#default_destination_concurrency_limit = 20
|
||||
|
||||
# DEBUGGING CONTROL
|
||||
#
|
||||
# The debug_peer_level parameter specifies the increment in verbose
|
||||
# logging level when an SMTP client or server host name or address
|
||||
# matches a pattern in the debug_peer_list parameter.
|
||||
#
|
||||
debug_peer_level = 2
|
||||
|
||||
# The debug_peer_list parameter specifies an optional list of domain
|
||||
# or network patterns, /file/name patterns or type:name tables. When
|
||||
# an SMTP client or server host name or address matches a pattern,
|
||||
# increase the verbose logging level by the amount specified in the
|
||||
# debug_peer_level parameter.
|
||||
#
|
||||
#debug_peer_list = 127.0.0.1
|
||||
#debug_peer_list = some.domain
|
||||
|
||||
# The debugger_command specifies the external command that is executed
|
||||
# when a Postfix daemon program is run with the -D option.
|
||||
#
|
||||
# Use "command .. & sleep 5" so that the debugger can attach before
|
||||
# the process marches on. If you use an X-based debugger, be sure to
|
||||
# set up your XAUTHORITY environment variable before starting Postfix.
|
||||
#
|
||||
debugger_command =
|
||||
PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
|
||||
xxgdb $daemon_directory/$process_name $process_id & sleep 5
|
||||
|
||||
# If you don't have X installed on the Postfix machine, try:
|
||||
# debugger_command =
|
||||
# PATH=/bin:/usr/bin:/usr/local/bin; export PATH; (echo cont;
|
||||
# echo where) | gdb $daemon_directory/$process_name $process_id 2>&1
|
||||
# >$config_directory/$process_name.$process_id.log & sleep 5
|
||||
|
||||
# INSTALL-TIME CONFIGURATION INFORMATION
|
||||
#
|
||||
# The following parameters are used when installing a new Postfix version.
|
||||
#
|
||||
# sendmail_path: The full pathname of the Postfix sendmail command.
|
||||
# This is the Sendmail-compatible mail posting interface.
|
||||
#
|
||||
sendmail_path = /usr/sbin/sendmail
|
||||
|
||||
# newaliases_path: The full pathname of the Postfix newaliases command.
|
||||
# This is the Sendmail-compatible command to build alias databases.
|
||||
#
|
||||
newaliases_path = /usr/bin/newaliases
|
||||
|
||||
# mailq_path: The full pathname of the Postfix mailq command. This
|
||||
# is the Sendmail-compatible mail queue listing command.
|
||||
#
|
||||
mailq_path = /usr/bin/mailq
|
||||
|
||||
# setgid_group: The group for mail submission and queue management
|
||||
# commands. This must be a group name with a numerical group ID that
|
||||
# is not shared with other accounts, not even with the Postfix account.
|
||||
#
|
||||
setgid_group = postdrop
|
||||
|
||||
# manpage_directory: The location of the Postfix on-line manual pages.
|
||||
#
|
||||
manpage_directory = /usr/share/man
|
||||
|
||||
# sample_directory: The location of the Postfix sample configuration files.
|
||||
#
|
||||
sample_directory = /usr/share/doc/postfix-2.0.19/sample
|
||||
|
||||
# readme_directory: The location of the Postfix README files.
|
||||
#
|
||||
readme_directory = /usr/share/doc/postfix-2.0.19/readme
|
||||
default_destination_concurrency_limit = 2
|
||||
#alias_database = hash:/etc/mail/aliases
|
||||
local_destination_concurrency_limit = 2
|
||||
alias_maps = hash:/etc/mail/aliases
|
||||
|
||||
content_filter = smtp-amavis:[127.0.0.1]:10024
|
||||
queue_minfree = 100000000
|
||||
message_size_limit = 50000000
|
||||
mailbox_size_limit = 500000000
|
||||
smtpd_helo_required=yes
|
||||
smtpd_helo_restrictions=permit_mynetworks, reject_invalid_hostname, reject_invalid_hostname
|
||||
smtpd_sender_restrictions=permit_mynetworks, reject_unknown_sender_domain, reject_non_fqdn_sender
|
||||
|
||||
virtual_maps = ldap:aliases, ldap:mailboxes
|
||||
|
||||
aliases_server_host = 127.0.0.1
|
||||
aliases_search_base = dc=domain,dc=loc
|
||||
aliases_query_filter = (&(|(mail=%s)(mailalternateaddress=%s))(objectclass=posixaccount)(deliveryMode=forwardonly)(accountstatus=active))
|
||||
aliases_bind_dn = cn=thepostfixadmin,dc=domain,dc=loc
|
||||
aliases_bind_pw = thepassword
|
||||
aliases_result_attribute = mailforwardingaddress
|
||||
aliases_version = 3
|
||||
|
||||
mailboxes_server_host = 127.0.0.1
|
||||
mailboxes_search_base = dc=domain,dc=loc
|
||||
mailboxes_query_filter = (&(|(mail=%s)(mailalternateaddress=%s))(objectclass=posixaccount)(accountstatus=active))
|
||||
mailboxes_bind_dn = cn=thepostfixadmin,dc=domain,dc=loc
|
||||
mailboxes_bind_pw = thepassword
|
||||
mailboxes_result_attribute = uid, mailforwardingaddress
|
||||
mailboxes_version = 3
|
||||
|
||||
|
||||
#SMTPD mit SASL-Authentification verwenden
|
||||
smtpd_sasl_auth_enable = yes
|
||||
|
||||
#Zusatz-Optionen: Keine anonyme-Anmeldung verwenden
|
||||
smtpd_sasl_security_options = noanonymous
|
||||
|
||||
#Wieder ein Workaround für ältere Clients und Outlook
|
||||
broken_sasl_auth_clients = yes
|
||||
|
||||
# ODER meine Netze und SASL erlauben
|
||||
smtpd_recipient_restrictions =
|
||||
permit_mynetworks,
|
||||
permit_sasl_authenticated,
|
||||
reject_rbl_client relays.ordb.org,
|
||||
reject_rbl_client sbl-xbl.spamhaus.org,
|
||||
reject_rbl_client opm.blitzed.org,
|
||||
reject_rbl_client dnsbl.njabl.org,
|
||||
reject_rbl_client blackholes.wirehub.net,
|
||||
reject_rbl_client list.dsbl.org,
|
||||
reject_rbl_client dnsbl.sorbs.net,
|
||||
reject_unauth_destination,
|
||||
reject_non_fqdn_sender,
|
||||
reject_non_fqdn_recipient,
|
||||
reject_unauth_pipelining,
|
||||
reject_unknown_sender_domain,
|
||||
reject_unknown_recipient_domain
|
||||
|
||||
# reject_unknown_client
|
||||
# reject_rbl_client proxies.relays.monkeys.com,
|
||||
|
||||
# incoming SSL
|
||||
smtpd_use_tls = yes
|
||||
#smtpd_tls_auth_only = yes
|
||||
smtpd_tls_key_file = /etc/ssl/private/smtp.linux-at-work.de/smtp.linux-at-work.de.key
|
||||
smtpd_tls_cert_file = /etc/ssl/private/smtp.linux-at-work.de/smtp.linux-at-work.de.crt
|
||||
smtpd_tls_CAfile = /etc/ssl/certs/ca-cert.pem
|
||||
smtpd_tls_loglevel = 1
|
||||
smtpd_tls_received_header = yes
|
||||
smtpd_tls_session_cache_timeout = 3600s
|
||||
tls_random_source = dev:/dev/urandom
|
||||
|
||||
#outgoing SSL
|
||||
smtp_tls_key_file = /etc/ssl/private/smtp.linux-at-work.de/smtp.linux-at-work.de.key
|
||||
smtp_tls_cert_file = /etc/ssl/private/smtp.linux-at-work.de/smtp.linux-at-work.de.crt
|
||||
smtp_tls_CAfile = /etc/ssl/certs/ca-cert.pem
|
||||
smtp_tls_CApath = /etc/ssl/certs
|
||||
smtp_tls_loglevel = 2
|
||||
# The server and client negotiate a session, which takes some computer time
|
||||
# and network bandwidth. The session is cached only in the smtpd process
|
||||
# actually using this session and is lost when the process dies.
|
||||
# To share the session information between the smtp processes, a disc based
|
||||
# session cache can be used based on the SDBM databases (routines included
|
||||
# in Postfix/TLS). Since concurrent writing must be supported, only SDBM
|
||||
# can be used.
|
||||
#
|
||||
smtp_tls_session_cache_database = sdbm:/etc/postfix/smtp_scache
|
||||
|
||||
# By default TLS is disabled, so no difference to plain postfix is visible.
|
||||
# If you enable TLS it will be used when offered by the server.
|
||||
# WARNING: I didn't have access to other software (except those explicitely
|
||||
# listed) to test the interaction. On corresponding mailing list
|
||||
# there was a discussion going on about MS exchange servers offering
|
||||
# STARTTLS even if it is not configured, so it might be wise to not
|
||||
# use this option on your central mail hub, as you don't know in advance
|
||||
# whether you are going to hit such host. Use the recipient/site specific
|
||||
# options instead.
|
||||
# HINT: I have it switched on on my mailservers and did experience one
|
||||
# single failure since client side TLS is implemented. (There was one
|
||||
# misconfired MS Exchange server; I contacted ths admin.) Hence, I am happy
|
||||
# with it running all the time, but I am interested in testing anyway.
|
||||
# You have been warned, however :-)
|
||||
#
|
||||
# In case of failure, a "4xx" code is issued and the mail stays in the queue.
|
||||
#
|
||||
# Explicitely switch it on here, if you want it.
|
||||
#
|
||||
#smtp_use_tls = yes
|
408
doc/mail/postfix_tcp_map_ads.php
Executable file
408
doc/mail/postfix_tcp_map_ads.php
Executable file
@ -0,0 +1,408 @@
|
||||
#!/usr/bin/php -Cq
|
||||
<?php
|
||||
/**
|
||||
* EGroupware - tcp-map for Postfix and Active Directory
|
||||
*
|
||||
* Using multivalued proxyAddresses attribute as implemented in Api\Mail\Smtp\Ads:
|
||||
* - "smtp:<email>" allows to receive mail for given <email>
|
||||
* (includes aliases AND primary email)
|
||||
* - "forward:<email>" forwards received mail to given <email>
|
||||
* (requires account to have at an "smtp:<email>" value!)
|
||||
* - ("forwardOnly" is used for no local mailbox, only forwards, not implemented!)
|
||||
* - ("quota:<quota>" is used to store quota)
|
||||
*
|
||||
* Groups can be used as distribution lists by assigning them an
|
||||
* email address via there mail attribute (no proxyAddress)
|
||||
*
|
||||
* PROTOCOL DESCRIPTION
|
||||
* The TCP map class implements a very simple protocol: the
|
||||
* client sends a request, and the server sends one reply.
|
||||
* Requests and replies are sent as one line of ASCII text,
|
||||
* terminated by the ASCII newline character. Request and
|
||||
* reply parameters (see below) are separated by whitespace.
|
||||
*
|
||||
* REQUEST FORMAT
|
||||
* Each request specifies a command, a lookup key, and possi-
|
||||
* bly a lookup result.
|
||||
*
|
||||
* get SPACE key NEWLINE
|
||||
* Look up data under the specified key.
|
||||
*
|
||||
* put SPACE key SPACE value NEWLINE
|
||||
* This request is currently not implemented.
|
||||
*
|
||||
* REPLY FORMAT
|
||||
* Each reply specifies a status code and text. Replies must
|
||||
* be no longer than 4096 characters including the newline
|
||||
* terminator.
|
||||
*
|
||||
* 500 SPACE text NEWLINE
|
||||
* In case of a lookup request, the requested data
|
||||
* does not exist. In case of an update request, the
|
||||
* request was rejected. The text describes the
|
||||
* nature of the problem.
|
||||
*
|
||||
* 400 SPACE text NEWLINE
|
||||
* This indicates an error condition. The text
|
||||
* describes the nature of the problem. The client
|
||||
* should retry the request later.
|
||||
*
|
||||
* 200 SPACE text NEWLINE
|
||||
* The request was successful. In the case of a lookup
|
||||
* request, the text contains an encoded version of
|
||||
* the requested data.
|
||||
*
|
||||
* ENCODING
|
||||
* In request and reply parameters, the character %, each
|
||||
* non-printing character, and each whitespace character must
|
||||
* be replaced by %XX, where XX is the corresponding ASCII
|
||||
* hexadecimal character value. The hexadecimal codes can be
|
||||
* specified in any case (upper, lower, mixed).
|
||||
*
|
||||
* The Postfix client always encodes a request. The server
|
||||
* may omit the encoding as long as the reply is guaranteed
|
||||
* to not contain the % or NEWLINE character.
|
||||
*
|
||||
* @author rb(at)stylite.de
|
||||
* @copyright (c) 2012-13 by rb(at)stylite.de
|
||||
* @package emailadmin
|
||||
* @link http://www.postfix.org/tcp_table.5.html
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
// protect from being called via HTTP
|
||||
if (php_sapi_name() !== 'cli') die('This is a command line only script!');
|
||||
|
||||
// our defaults
|
||||
$default_host = 'localhost';
|
||||
$verbose = false;
|
||||
|
||||
// allow only clients matching that preg to access, should be only mserver IP
|
||||
//$only_client = '/^10\.40\.8\.210:/';
|
||||
|
||||
// uncomment to write to log-file, otherwise errors go to stderr
|
||||
//$log = 'syslog'; // or not set (stderr) or filename '/var/log/postfix_tcp_map.log';
|
||||
//$log_verbose = true; // error's are always logged, set to true to log failures and success too
|
||||
|
||||
// ldap server settings
|
||||
$ldap_uri = 'ldaps://10.7.102.13/';
|
||||
$base = 'CN=Users,DC=gruene,DC=intern';
|
||||
//$bind_dn = "CN=Administrator,$base";
|
||||
//$bind_dn = "Administrator@gruene.intern";
|
||||
//$bind_pw = 'secret';
|
||||
$version = 3;
|
||||
$use_tls = false;
|
||||
// supported maps
|
||||
$maps = array(
|
||||
// virtual mailbox map
|
||||
'mailboxes' => array(
|
||||
'base' => $base,
|
||||
'filter' => '(&(objectCategory=person)(proxyAddresses=smtp:%s))',
|
||||
'attrs' => 'samaccountname', // result-attrs must be lowercase!
|
||||
'port' => 2001,
|
||||
),
|
||||
// virtual alias maps
|
||||
'aliases' => array(
|
||||
'base' => $base,
|
||||
'filter' => '(&(objectCategory=person)(proxyAddresses=smtp:%s))',
|
||||
'attrs' => array('samaccountname','{forward:}proxyaddresses'),
|
||||
'port' => 2002,
|
||||
),
|
||||
// groups as distribution list
|
||||
'groups' => array(
|
||||
'base' => $base,
|
||||
'filter' => '(&(objectCategory=group)(mail=%s))',
|
||||
'attrs' => 'dn',
|
||||
// continue with resulting dn
|
||||
'filter1' => '(&(objectCategory=person)(proxyAddresses=smtp:*)(memberOf=%s))',
|
||||
'attrs1' => array('samaccountname','{forward:}proxyaddresses'),
|
||||
'port' => 2003,
|
||||
),
|
||||
);
|
||||
|
||||
ini_set('display_errors',false);
|
||||
error_reporting(E_ALL & ~E_NOTICE);
|
||||
if ($log) ini_set('error_log',$log);
|
||||
|
||||
function usage($extra=null)
|
||||
{
|
||||
global $maps;
|
||||
fwrite(STDERR, "\nUsage: $cmd [-v|--verbose] [-h|--help] [-l|--log (syslog|path)] [-q|--query <email-addresse> (mailboxes|alias|groups)] [host]\n\n");
|
||||
fwrite(STDERR, print_r($maps,true)."\n");
|
||||
if ($extra) fwrite(STDERR, "\n\n$extra\n\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
$cmd = basename(array_shift($_SERVER['argv']));
|
||||
|
||||
while (($arg = array_shift($_SERVER['argv'])) && $arg[0] == '-')
|
||||
{
|
||||
switch($arg)
|
||||
{
|
||||
case '-v': case '--verbose':
|
||||
$verbose = $log_verbose = true;
|
||||
break;
|
||||
|
||||
case '-h': case '--help':
|
||||
usage();
|
||||
break;
|
||||
|
||||
case '-l': case '--log':
|
||||
$log = array_shift($_SERVER['argv']);
|
||||
break;
|
||||
|
||||
case '-q': case '--query':
|
||||
if (count($_SERVER['argv']) == 2) // need 2 arguments
|
||||
{
|
||||
$request = 'get '.array_shift($_SERVER['argv'])."\n";
|
||||
$map = array_shift($_SERVER['argv']);
|
||||
echo respond($request, $map)."\n";
|
||||
exit;
|
||||
}
|
||||
usage();
|
||||
break;
|
||||
|
||||
default:
|
||||
usage("Unknown option '$arg'!");
|
||||
}
|
||||
}
|
||||
if ($_SERVER['argv']) usage();
|
||||
|
||||
if ($arg)
|
||||
{
|
||||
$host = $arg;
|
||||
}
|
||||
else
|
||||
{
|
||||
$host = $default_host;
|
||||
}
|
||||
|
||||
if ($verbose) echo "using $host\n";
|
||||
|
||||
$servers = $clients = $buffers = array();
|
||||
|
||||
// Create the server socket
|
||||
foreach($maps as $map => $data)
|
||||
{
|
||||
$addr = 'tcp://'.$host.':'.$data['port'];
|
||||
if (!($server = stream_socket_server($addr, $errno, $errstr)))
|
||||
{
|
||||
fwrite(STDERR, date('Y-m-d H:i:s').": Error calling stream_socket_server('$addr')!\n");
|
||||
fwrite(STDERR, $errstr." ($errno)\n");
|
||||
exit($errno);
|
||||
}
|
||||
$servers[$data['port']] = $server;
|
||||
$clients[$data['port']] = array();
|
||||
}
|
||||
while (true) // mail loop of tcp server --> never exits
|
||||
{
|
||||
$read = $servers;
|
||||
if ($clients) $read = array_merge($read, call_user_func_array('array_merge', array_values($clients)));
|
||||
if ($verbose) print 'about to call socket_select(array('.implode(',',$read).', ...) waiting... ';
|
||||
if (stream_select($read, $write=null, $except=null, null)) // null = block forever
|
||||
{
|
||||
foreach($read as $sock)
|
||||
{
|
||||
if (($port = array_search($sock, $servers)) !== false)
|
||||
{
|
||||
$client = stream_socket_accept($sock,$timeout,$client_addr); // @ required to get not timeout warning!
|
||||
|
||||
if ($verbose) echo "accepted connection $client from $client_addr on port $port\n";
|
||||
|
||||
if ($only_client && !preg_match($only_client,$client_addr))
|
||||
{
|
||||
fwrite($client,"Go away!\r\n");
|
||||
fclose($client);
|
||||
error_log(date('Y-m-d H:i:s').": Connection $client from wrong client $client_addr (does NOT match '$only_client') --> terminated");
|
||||
continue;
|
||||
}
|
||||
$clients[$port][] = $client;
|
||||
}
|
||||
elseif (feof($sock)) // client connection closed
|
||||
{
|
||||
if ($verbose) echo "client $sock closed connection\n";
|
||||
|
||||
foreach($clients as $port => &$socks)
|
||||
{
|
||||
if (($key = array_search($sock, $socks, true)) !== false)
|
||||
{
|
||||
unset($socks[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // client send something
|
||||
{
|
||||
$buffer =& $buffers[$sock];
|
||||
|
||||
$buffer .= fread($sock, 8096);
|
||||
|
||||
if (strpos($buffer, "\n") !== false)
|
||||
{
|
||||
list($request, $buffer) = explode("\n", $buffer, 2);
|
||||
|
||||
foreach($maps as $map => $data)
|
||||
{
|
||||
if (($key = array_search($sock, $clients[$data['port']], true)) !== false)
|
||||
{
|
||||
if ($verbose) echo date('Y-m-d H:i:s').": client send: $request for map $map\n";
|
||||
|
||||
// Respond to client
|
||||
fwrite($sock, respond($request, $map));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($except)
|
||||
{
|
||||
echo "Exception: "; print_r($except);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// timeout expired
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* escapes a string for use in searchfilters meant for ldap_search.
|
||||
*
|
||||
* Escaped Characters are: '*', '(', ')', ' ', '\', NUL
|
||||
* It's actually a PHP-Bug, that we have to escape space.
|
||||
* For all other Characters, refer to RFC2254.
|
||||
*
|
||||
* @param string|array $string either a string to be escaped, or an array of values to be escaped
|
||||
* @return string
|
||||
*/
|
||||
function quote($string)
|
||||
{
|
||||
return str_replace(array('\\','*','(',')','\0',' '),array('\\\\','\*','\(','\)','\\0','\20'),$string);
|
||||
}
|
||||
|
||||
function respond($request, $map, $extra='', $reconnect=false)
|
||||
{
|
||||
static $ds;
|
||||
global $ldap_uri, $version, $use_tls, $bind_dn, $bind_pw;
|
||||
global $maps, $log_verbose;
|
||||
|
||||
if (($map == 'aliases' || $map == 'groups') && strpos($request,'@') === false && !$extra)
|
||||
{
|
||||
return "500 No domain aliases yet\n";
|
||||
}
|
||||
if (!isset($ds) || $reconnect)
|
||||
{
|
||||
$ds = ldap_connect($ldap_uri);
|
||||
if ($version) ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, $version);
|
||||
if ($use_tls) ldap_start_tls($ds);
|
||||
|
||||
if (!@ldap_bind($ds, $bind_dn, $bind_pw))
|
||||
{
|
||||
error_log("$map: Can't connect to LDAP server $ldap_uri!");
|
||||
$ds = null;
|
||||
return "400 Can't connect to LDAP server $ldap_uri!\n"; // 400 (temp.) error
|
||||
}
|
||||
}
|
||||
if (!preg_match('/^get ([^\n]+)\n?$/', $request, $matches))
|
||||
{
|
||||
error_log("$map: Wrong format '$request'!");
|
||||
return "400 Wrong format '$request'!\n"; // 400 (temp.) error
|
||||
}
|
||||
$username = $matches[1];
|
||||
|
||||
list($name,$domain) = explode('@',$username);
|
||||
|
||||
/* check if we are responsible for the given domain
|
||||
if ($domain && $map != 'domains' && (int)($response = respond("get $domain", 'domains')) != 200)
|
||||
{
|
||||
return $response;
|
||||
}*/
|
||||
$replace = array(
|
||||
'%n' => quote($name),
|
||||
'%d' => quote($domain),
|
||||
'%s' => quote($username),
|
||||
);
|
||||
$base = strtr($maps[$map]['base'], $replace);
|
||||
$filter = strtr($maps[$map]['filter'.$extra], $replace);
|
||||
$prefix = isset($maps[$map]['prefix'.$extra]) ? str_replace(array('%n','%d','%s'),array($name,$domain,$username),$maps[$map]['prefix']) : '';
|
||||
$search_attrs = $attrs = (array)$maps[$map]['attrs'.$extra];
|
||||
// remove prefix like "{smtp:}proxyaddresses"
|
||||
foreach($search_attrs as &$attr)
|
||||
{
|
||||
if ($attr[0] == '{') list(,$attr) = explode('}', $attr);
|
||||
}
|
||||
unset($attr);
|
||||
|
||||
if (!($sr = @ldap_search($ds, $base, $filter, $search_attrs)))
|
||||
{
|
||||
$errno = ldap_errno($ds);
|
||||
$error = ldap_error($ds).' ('.$errno.')';
|
||||
|
||||
if ($errno == -1) // eg. -1 lost connection to ldap
|
||||
{
|
||||
// as DC closes connections quickly, first try to reconnect once, before returning a temp. failure
|
||||
if (!$reconnect) return respond($request, $map, $extra, true);
|
||||
|
||||
error_log("$map: get '$username' --> 400 $error: !ldap_search(\$ds, '$base', '$filter')");
|
||||
ldap_close($ds);
|
||||
$ds = null; // force new connection on next lookup
|
||||
return "400 $error\n"; // 400 (temp.) error
|
||||
}
|
||||
else // happens if base containing domain does not exist
|
||||
{
|
||||
if ($log_verbose) error_log("$map: get '$username' --> 500 Not found: $error: !ldap_search(\$ds, '$base', '$filter')");
|
||||
return "500 Not found: $error\n"; // 500 not found
|
||||
}
|
||||
}
|
||||
$entries = ldap_get_entries($ds, $sr);
|
||||
|
||||
if (!$entries['count'])
|
||||
{
|
||||
if ($log_verbose) error_log("$map: get '$username' --> 500 not found ldap_search(\$ds, '$base', '$filter') no entries");
|
||||
return "500 Not found\n"; // 500: Query returned no result
|
||||
}
|
||||
$response = array();
|
||||
foreach($entries as $key => $entry)
|
||||
{
|
||||
if ($key === 'count') continue;
|
||||
|
||||
foreach($attrs as $attr)
|
||||
{
|
||||
unset($filter_prefix);
|
||||
if ($attr[0] == '{')
|
||||
{
|
||||
list($filter_prefix, $attr) = explode('}', substr($attr, 1));
|
||||
}
|
||||
foreach((array)$entry[$attr] as $k => $mail)
|
||||
{
|
||||
if ($k !== 'count' && ($mail = trim($mail)))
|
||||
{
|
||||
if ($filter_prefix)
|
||||
{
|
||||
if (stripos($mail, $filter_prefix) === 0)
|
||||
{
|
||||
$mail = substr($mail, strlen($filter_prefix));
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$response[] = isset($maps[$map]['return']) ? $maps[$map]['return'] : $prefix.$mail;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$response)
|
||||
{
|
||||
if ($log_verbose) error_log("$map: get '$username' --> 500 not found ldap_search(\$ds, '$base', '$filter') no response");
|
||||
return "500 Not found\n"; // 500: Query returned no result
|
||||
}
|
||||
if (isset($maps[$map]['filter'.(1+$extra)]) && isset($maps[$map]['attrs'.(1+$extra)]))
|
||||
{
|
||||
return respond('get '.$response[0], $map, 1+$extra);
|
||||
}
|
||||
$response = '200 '.implode(',',$response)."\n";
|
||||
if ($log_verbose) error_log("$map: get '$username' --> $response");
|
||||
return $response;
|
||||
}
|
271
doc/mail/qmail.new.schema
Normal file
271
doc/mail/qmail.new.schema
Normal 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 ) )
|
103
doc/mail/qmailuser.schema
Normal file
103
doc/mail/qmailuser.schema
Normal file
@ -0,0 +1,103 @@
|
||||
#
|
||||
# qmail-ldap v3 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>
|
||||
#
|
||||
#
|
||||
# This schema depends on:
|
||||
# - core.schema
|
||||
# - cosine.schema
|
||||
# - nis.schema
|
||||
#
|
||||
|
||||
#
|
||||
# Example from new format
|
||||
#
|
||||
# attributetype ( 1.3.6.1.1.1.1.0 NAME 'uidNumber'
|
||||
# DESC 'An integer uniquely identifying a user in an administrative domain'
|
||||
# EQUALITY integerMatch
|
||||
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
|
||||
|
||||
# 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
|
||||
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.4 NAME 'mailAlternateAddress'
|
||||
DESC 'Secondary (alias) mailaddresses for the same user'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
|
||||
|
||||
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.'
|
||||
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.9 NAME 'qmailDotMode'
|
||||
DESC 'Interpretation of .qmail files: both, dotonly, ldaponly, ldapwithprog, none'
|
||||
EQUALITY caseIgnoreMatch
|
||||
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.10 NAME 'deliveryMode'
|
||||
DESC 'multi field entries of: normal, forwardonly, nombox, localdelivery, reply, echo'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.7914.1.2.1.11 NAME 'mailReplyText'
|
||||
DESC 'A reply text for every incoming message'
|
||||
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, nopop, disabled, deleted'
|
||||
EQUALITY caseIgnoreMatch
|
||||
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.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 )
|
||||
|
||||
# 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 $ uid )
|
||||
MAY ( mailMessageStore $ homeDirectory $ userPassword $
|
||||
mailAlternateAddress $ qmailUID $ qmailGID $ mailQuota $
|
||||
mailHost $ mailForwardingAddress $ deliveryProgramPath $
|
||||
qmailDotMode $ deliveryMode $ mailReplyText $
|
||||
accountStatus $ qmailAccountPurge ) )
|
19
doc/mail/smartsieve-NOTICE
Normal file
19
doc/mail/smartsieve-NOTICE
Normal file
@ -0,0 +1,19 @@
|
||||
SMARTSIEVE - SIEVE SCRIPT MANAGER
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2002 Stephen Grier <stephengrier@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
16
doc/mail/tcpmaps.conf
Normal file
16
doc/mail/tcpmaps.conf
Normal file
@ -0,0 +1,16 @@
|
||||
# # Start it with:
|
||||
# # initctl reload-configuration
|
||||
# # initctl start tcpmaps
|
||||
|
||||
|
||||
description "TCPMAP"
|
||||
author "Ralf und Wim"
|
||||
|
||||
start on runlevel [235] or starting postfix
|
||||
stop on runlevel [S016]
|
||||
|
||||
#pre-start exec /etc/vmware-tools/services.sh start
|
||||
#post-stop exec /etc/vmware-tools/services.sh stop
|
||||
respawn
|
||||
instance tcpmaps
|
||||
exec /usr/local/bin/postfix_tcp_map_ads.php --log syslog localhost
|
@ -655,17 +655,17 @@ function set_univention_defaults()
|
||||
$domain = array_shift($domains);
|
||||
// set "use auth with session credentials",tls,"not user editable","further identities"
|
||||
$config['smtpserver'] = "$mailserver,465,,,yes,tls,no,yes";
|
||||
$config['smtp'] = ',emailadmin_smtp_univention';
|
||||
$config['smtp'] = ',Smtp\\Univention';
|
||||
$config['mailserver'] = "$mailserver,993,$domain,email,tls";
|
||||
if (_ucr_get('mail/dovecot') == 'yes')
|
||||
{
|
||||
$config['imap'] = /*'cyrus,'._ucr_secret('cyrus')*/','.',emailadmin_imap_dovecot';
|
||||
$config['imap'] = /*'cyrus,'._ucr_secret('cyrus')*/','.',Imap\\Dovecot';
|
||||
// default with sieve port to 4190, as config is only available on host mailserver app is installed
|
||||
if (!($sieve_port = _ucr_get('mail/dovecot/sieve/port'))) $sieve_port = 4190;
|
||||
}
|
||||
else
|
||||
{
|
||||
$config['imap'] = /*'cyrus,'._ucr_secret('cyrus')*/','.',emailadmin_imap_cyrus';
|
||||
$config['imap'] = /*'cyrus,'._ucr_secret('cyrus')*/','.',Imap\\Cyrus';
|
||||
// default with sieve port to 4190, as config is only available on host mailserver app is installed
|
||||
if (!($sieve_port = _ucr_get('mail/cyrus/sieve/port'))) $sieve_port = 4190;
|
||||
}
|
||||
|
@ -429,7 +429,6 @@ class infolog_so
|
||||
$this->db->delete($this->info_table,array('info_id'=>$info_id),__LINE__,__FILE__);
|
||||
$this->db->delete($this->extra_table,array('info_id'=>$info_id),__LINE__,__FILE__);
|
||||
egw_link::unlink(0,'infolog',$info_id);
|
||||
egw_index::delete('infolog',$info_id);
|
||||
|
||||
if ($this->data['info_id'] == $info_id)
|
||||
{
|
||||
@ -439,13 +438,12 @@ class infolog_so
|
||||
if ($delete_children)
|
||||
{
|
||||
$db2 = clone($this->db); // we need an extra result-set
|
||||
$db2->select($this->info_table,'info_id',array(
|
||||
foreach($db2->select($this->info_table,'info_id',array(
|
||||
'info_id_parent' => $info_id,
|
||||
'info_owner' => $this->user,
|
||||
),__LINE__,__FILE__);
|
||||
while ($db2->next_record())
|
||||
),__LINE__,__FILE__) as $row)
|
||||
{
|
||||
$this->delete($db2->f(0),$delete_children);
|
||||
$this->delete($row['info_id'], $delete_children);
|
||||
}
|
||||
}
|
||||
// set parent_id to $new_parent or 0 for all not deleted children
|
||||
@ -625,10 +623,6 @@ class infolog_so
|
||||
// echo "<p>soinfolog.write this->data= "; _debug_array($this->data);
|
||||
//error_log("### soinfolog::write(".print_r($to_write,true).") where=".print_r($where,true)." returning id=".$this->data['info_id']);
|
||||
|
||||
// update the index
|
||||
//egw_index::save('infolog',$this->data['info_id'],$this->data['info_owner'],$this->data,$this->data['info_cat'],
|
||||
// array('info_uid','info_type','info_status','info_confirm','info_access'));
|
||||
|
||||
return $this->data['info_id'];
|
||||
}
|
||||
|
||||
@ -806,23 +800,6 @@ class infolog_so
|
||||
if ($query['query']) $query['search'] = $query['query']; // allow both names
|
||||
if ($query['search']) // we search in _from, _subject, _des and _extra_value for $query
|
||||
{
|
||||
/* new code join the index
|
||||
if (ctype_digit($query['search'])) // search by ticket-number (numbers get never indexed!)
|
||||
{
|
||||
$sql_query = 'AND info_id='.(int)$query['search'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$join = egw_index::sql_join_ids_by_keyword($query['search'],'infolog','info_id');
|
||||
}
|
||||
*/
|
||||
/* new code with info_id IN (subquery) --> way to slow
|
||||
$sql_query .= 'AND info_id IN ('.
|
||||
egw_index::sql_ids_by_keyword(explode(' ',$query['search']),egw_index::MATCH_CONTAINS,'infolog').
|
||||
// add search string itself, if it is numeric, to allow to search for a info_id/ticket number
|
||||
ctype_digit($query['search'] ? ' UNION (SELECT '.$this->db->quote($query['search']).')' : '').')';
|
||||
*/
|
||||
/* old code searching the table direct */
|
||||
$columns = array('info_from','info_addr','info_location','info_subject','info_extra_value');
|
||||
// at the moment MaxDB 7.5 cant cast nor search text columns, it's suppost to change in 7.6
|
||||
if ($this->db->capabilities['like_on_text']) $columns[] = 'info_des';
|
||||
@ -953,19 +930,17 @@ class infolog_so
|
||||
{
|
||||
$users = array();
|
||||
|
||||
$this->db->select($this->info_table,'DISTINCT info_owner',array(
|
||||
foreach($this->db->select($this->info_table,'DISTINCT info_owner',array(
|
||||
str_replace(' AND ','',$this->statusFilter('open')),
|
||||
'(ABS(info_startdate-'.time().')<'.(4*24*60*60).' OR '. // start_day within 4 days
|
||||
'ABS(info_enddate-'.time().')<'.(4*24*60*60).')', // end_day within 4 days
|
||||
),__LINE__,__FILE__);
|
||||
while ($this->db->next_record())
|
||||
),__LINE__,__FILE__) as $row)
|
||||
{
|
||||
$users[] = $this->db->f(0);
|
||||
$users[] = $row['info_responsible'];
|
||||
}
|
||||
$this->db->select($this->info_table,'DISTINCT info_responsible',$this->statusFilter('open',false),__LINE__,__FILE__);
|
||||
while ($this->db->next_record())
|
||||
foreach($this->db->select($this->info_table,'DISTINCT info_responsible',$this->statusFilter('open',false),__LINE__,__FILE__) as $row)
|
||||
{
|
||||
foreach(explode(',',$this->db->f(0)) as $responsible)
|
||||
foreach(explode(',', $row['info_responsible']) as $responsible)
|
||||
{
|
||||
if ($GLOBALS['egw']->accounts->get_type($responsible) == 'g')
|
||||
{
|
||||
|
@ -44,12 +44,8 @@ $setup_info['mail']['depends'][] = array(
|
||||
'versions' => Array('14.1')
|
||||
);
|
||||
$setup_info['mail']['depends'][] = array(
|
||||
'appname' => 'etemplate',
|
||||
'versions' => Array('14.1')
|
||||
);
|
||||
$setup_info['mail']['depends'][] = array(
|
||||
'appname' => 'emailadmin',
|
||||
'versions' => Array('14.1')
|
||||
'appname' => 'api',
|
||||
'versions' => Array('16.1')
|
||||
);
|
||||
// installation checks for mail
|
||||
$setup_info['mail']['check_install'] = array(
|
||||
|
@ -82,12 +82,13 @@ class egw extends egw_minimal
|
||||
function setup($domain_names,$createsessionobject=True)
|
||||
{
|
||||
// create the DB-object
|
||||
$this->db = new egw_db($GLOBALS['egw_info']['server']);
|
||||
// as SiteMgr, Wiki, KnowledgeBase and probably more still use eg next_record(), we stick with Db\Deprecated for now
|
||||
$this->db = new Api\Db\Deprecated($GLOBALS['egw_info']['server']);
|
||||
if ($this->debug)
|
||||
{
|
||||
$this->db->Debug = 1;
|
||||
}
|
||||
$this->db->set_app('phpgwapi');
|
||||
$this->db->set_app(Api\Db::API_APPNAME);
|
||||
|
||||
// check if eGW is already setup, if not redirect to setup/
|
||||
try {
|
||||
|
@ -1,386 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* API - eGW wide index over all applications (super-index)
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage link
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* eGW wide index over all applications (superindex)
|
||||
*
|
||||
* This index allows a fulltext search over all applications (or of cause also a single app).
|
||||
* Whenever an applications stores an entry it calls:
|
||||
*
|
||||
* boolean egw_index::save($app,$id,$owner,array $fields,array $cat_id=null),
|
||||
*
|
||||
* which calls, as the application do when is deletes an entry (!),
|
||||
*
|
||||
* boolean egw_index::delete($app,$id)
|
||||
*
|
||||
* and then splits all fields into keywords and add these to the index by
|
||||
*
|
||||
* boolean private egw_index::add($app,$id,$keyword).
|
||||
*
|
||||
* Applications can then use the index to search for a given keyword (and optional application):
|
||||
*
|
||||
* array egw_index::search($keyword,$app=null) or
|
||||
*
|
||||
* foreach(new egw_index($keyword,$app=null) as $app_id => $title)
|
||||
*
|
||||
* To also allow to search by a category or keyword part of it, the index also tracks the categories
|
||||
* of the entries. Applications can choose to only use it for category storage, or cat do it redundant in
|
||||
* there own table too. To retrieve the categories of one or multiple entries:
|
||||
*
|
||||
* array egw_index::cats($app,$ids)
|
||||
*
|
||||
* Applications can use a sql (sub-)query to get the id's of there app matching a certain keyword and
|
||||
* include that in there own queries:
|
||||
*
|
||||
* string egw_index::sql_ids_by_keyword($app,$keyword)
|
||||
*
|
||||
* Please note: the index knows nothing about ACL, so it's the task of the application to ensure ACL rights.
|
||||
*/
|
||||
|
||||
class egw_index implements IteratorAggregate
|
||||
{
|
||||
const INDEX_TABLE = 'egw_index';
|
||||
const KEYWORD_TABLE = 'egw_index_keywords';
|
||||
const INDEX_CAT_TABLE = 'egw_cat2entry';
|
||||
const CAT_TABLE = 'egw_categories';
|
||||
const SEPARATORS = "/[ ,;.:\"'!\/?=()+*><|\n\r-]+/";
|
||||
const MIN_KEYWORD_LEN = 4;
|
||||
|
||||
/**
|
||||
* Private reference to the global db object
|
||||
*
|
||||
* @var egw_db
|
||||
*/
|
||||
private static $db;
|
||||
/**
|
||||
* Search parameters of the constructor
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $search_params;
|
||||
|
||||
/**
|
||||
* Constructor for the search iterator
|
||||
*
|
||||
* @param string $keyword
|
||||
* @param string $app=null
|
||||
* @param string $order='app' ordered by column: 'owner', 'id', 'app' (default)
|
||||
* @param string $sort='ASC' sorting 'ASC' (default) or 'DESC'
|
||||
* @param int $start=null if not null return limited resultset starting with row $start
|
||||
* @param int $num_rows=0 number of rows for a limited resultset, defaul maxmatches from the user prefs
|
||||
*/
|
||||
function __construct($keyword,$app=null,$order='title',$sort='ASC',$start=null,$num_rows=0)
|
||||
{
|
||||
$this->search_params = func_get_args();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the result of egw_index::search() as ArrayIterator
|
||||
*
|
||||
* @return ArrayIterator
|
||||
*/
|
||||
function getIterator()
|
||||
{
|
||||
return new ArrayIterator(call_user_func_array(array(__CLASS__,'search'),$this->search_params));
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for keywords
|
||||
*
|
||||
* @param string $keyword
|
||||
* @param string $app=null
|
||||
* @param string $order='app' ordered by column: 'keyword', 'id', 'app' (default)
|
||||
* @param string $sort='ASC' sorting 'ASC' (default) or 'DESC'
|
||||
* @param int $start=null if not null return limited resultset starting with row $start
|
||||
* @param int $num_rows=null number of rows for a limited resultset, defaul maxmatches from the user prefs
|
||||
* @return array with "$app:$id" or $id => $title pairs
|
||||
*/
|
||||
static function &search($keyword,$app=null,$order='title',$sort='ASC',$start=null,$num_rows=null)
|
||||
{
|
||||
if (!in_array(strtoupper($sort),array('ASC','DESC'))) $sort = 'ASC';
|
||||
if (substr($order,0,3) != 'si_') $order = 'si_'.$order;
|
||||
if (!in_array($order,array('si_app','si_id','si_owner'))) $order = 'si_app';
|
||||
|
||||
$rs = self::$db->union(array(
|
||||
array(
|
||||
'table' => self::INDEX_TABLE,
|
||||
'cols' => 'si_app,si_app_id,si_owner',
|
||||
'where' => array('keyword' => $keyword)+
|
||||
($app ? array('ce_app' => $app) : array()),
|
||||
),
|
||||
array(
|
||||
'table' => self::INDEX_CAT_TABLE,
|
||||
'cols' => 'ce_app,ce_app_id,ce_owner',
|
||||
'where' => array('cat_id IN (SELECT cat_id FROM '.self::CAT_TABLE.' WHERE cat_title '.
|
||||
self::$db->capabilities['case_insensitive_like'].' '.self::$db->quote('%'.$keyword.'%').')')+
|
||||
($app ? array('ce_app' => $app) : array()),
|
||||
),
|
||||
),__LINE__,__FILE__,$order.' '.$sort,$start,$num_rows);
|
||||
|
||||
// agregate the ids by app
|
||||
$app_ids = $titles = $rows = array();
|
||||
foreach($rs as $row)
|
||||
{
|
||||
$app_ids[$row['si_app']] = $row['si_app_id'];
|
||||
$rows[] = $row;
|
||||
}
|
||||
unset($rs);
|
||||
|
||||
// query the titles app-wise
|
||||
foreach($app_ids as $id_app => $ids)
|
||||
{
|
||||
$titles[$id_app] = bolink::titles($id_app,$ids);
|
||||
}
|
||||
$matches = array();
|
||||
foreach($rows as $row)
|
||||
{
|
||||
$key = $app ? $row['si_app_id'] : $row['si_app'].':'.$row['si_app_id'];
|
||||
$title = $titles[$row['si_app']][$row['si_app_id']];
|
||||
if (is_null($title)) // entry does not exist
|
||||
{
|
||||
self::delete($row['si_app'],$row['si_app_id']);
|
||||
error_log(__METHOD__.": not existing entry (is_null(title($row[si_app],$row[si_app_id])) deleted from index!");
|
||||
continue;
|
||||
}
|
||||
elseif($title === false)
|
||||
{
|
||||
$title = lang('Not readable %1 entry of user %2',lang($row['si_app']),$GLOBALS['egw']->common->grab_owner_name($row['si_owner']));
|
||||
}
|
||||
$matches[$key] = $title;
|
||||
}
|
||||
return $matches;
|
||||
//return iterator_to_array(new egw_index($keyword,$app,$order,$sort,$start,$num_rows),true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the keywords for an entry in the index
|
||||
*
|
||||
* @param string $app
|
||||
* @param string|int $id
|
||||
* @param string $owner eGW account_id of the owner of the entry, used to create a "private entry of ..." title
|
||||
* @param array $fields
|
||||
* @param array|int|string $cat_ids=null optional cat_id(s) either comma-separated or as array
|
||||
* @param array $ignore_fields=array() keys of fields NOT to index
|
||||
* @return int|boolean false on error, othwerwise number off added keywords
|
||||
*/
|
||||
static function save($app,$id,$owner,array $fields,$cat_ids=null,array $ignore_fields=array())
|
||||
{
|
||||
if (!$app || !$id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// collect the keywords of all fields
|
||||
$keywords = array();
|
||||
foreach($fields as $field)
|
||||
{
|
||||
if ($ignore_fields && in_array($field, $ignore_fields)) continue;
|
||||
|
||||
foreach(preg_split(self::SEPARATORS, $field) as $keyword)
|
||||
{
|
||||
if (!in_array($keyword,$keywords) && strlen($keyword) >= self::MIN_KEYWORD_LEN && !is_numeric($keyword))
|
||||
{
|
||||
$keywords[] = $keyword;
|
||||
}
|
||||
}
|
||||
}
|
||||
// delete evtl. existing current keywords
|
||||
self::delete($app,$id);
|
||||
|
||||
// add the keywords
|
||||
foreach($keywords as $key => &$keyword)
|
||||
{
|
||||
if (!self::add($app,$id,$keyword,$owner)) // add can reject keywords
|
||||
{
|
||||
unset($keywords[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// delete the existing cats
|
||||
self::delete_cats($app,$id);
|
||||
|
||||
// add the cats
|
||||
if ($cat_ids)
|
||||
{
|
||||
self::add_cats($app,$id,$cat_ids,$owner);
|
||||
}
|
||||
return count($keywords);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the keywords for an entry or an entire application
|
||||
*
|
||||
* @param string $app
|
||||
* @param string|int $id=null
|
||||
*/
|
||||
static function delete($app,$id=null)
|
||||
{
|
||||
if (!$app)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
$where = array('si_app' => $app);
|
||||
if ($id)
|
||||
{
|
||||
$where['si_app_id'] = $id;
|
||||
}
|
||||
return !!self::$db->delete(self::INDEX_TABLE,$where,__LINE__,__FILE__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cats of an entry or multiple entries
|
||||
*
|
||||
* @param string $app
|
||||
* @param string|int|array $ids
|
||||
* @return array with cats or single id or id => array with cats pairs
|
||||
*/
|
||||
static function cats($app,$ids)
|
||||
{
|
||||
if (!$app || !$ids)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
$cats = array();
|
||||
foreach(self::$db->select(self::INDEX_CAT_TABLE,'cat_id,ce_app_id',array(
|
||||
'ce_app' => $app,
|
||||
'ce_app_id' => $ids,
|
||||
),__LINE__,__FILE__) as $row)
|
||||
{
|
||||
$cats[$row['ce_app_id']][] = $row['cat_id'];
|
||||
}
|
||||
return is_array($ids) ? $cats : $cats[(int)$ids];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL to fetch (eg. as subquery) the id's of a given app matching a keyword
|
||||
*
|
||||
* @param string $keyword
|
||||
* @param string $app
|
||||
* @return string
|
||||
*/
|
||||
static function sql_ids_by_keyword($keyword,$app)
|
||||
{
|
||||
return '(SELECT si_id FROM '.self::INDEX_TABLE.' WHERE si_app='.self::$db->quote($app).
|
||||
' AND si_keyword = '.self::$db->quote($keyword).') UNION '.
|
||||
'(SELECT ce_id FROM '.self::INDEX_CAT_TABLE.' WHERE si_app='.self::$db->quote($app).
|
||||
' AND cat_id IN (SELECT cat_id FROM '.self::CAT_TABLE.' WHERE cat_title '.self::$db->capabilities['case_insensitive_like'].' '.
|
||||
self::$db->quote('%'.$keyword.'%').'))';
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores one keyword for an entry in the index
|
||||
*
|
||||
* @todo reject keywords which are common words ...
|
||||
* @param string $app
|
||||
* @param string|int $id
|
||||
* @param string $keyword
|
||||
* @param int $owner=null
|
||||
* @return boolean true if keyword added, false if it was rejected in future
|
||||
*/
|
||||
static private function add($app,$id,$keyword,$owner=null)
|
||||
{
|
||||
// todo: reject keywords which are common words, not sure how to do that for all languages
|
||||
// mayby we can come up with some own little statistic analysis:
|
||||
// all keywords more common then N % of the entries get deleted and moved to a separate table ...
|
||||
if (!($si = self::$db->select(self::KEYWORD_TABLE, '*', array('si_keyword' => $keyword))->fetch()))
|
||||
{
|
||||
self::$db->insert(self::KEYWORD_TABLE, array(
|
||||
'si_keyword' => $keyword,
|
||||
), false, __LINE__, __FILE__);
|
||||
|
||||
$si_id = self::$db->get_last_insert_id(self::KEYWORD_TABLE, 'si_id');
|
||||
}
|
||||
elseif ($si['si_ignore'])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$si_id = $si['si_id'];
|
||||
}
|
||||
self::$db->insert(self::INDEX_TABLE,array(
|
||||
'si_app' => $app,
|
||||
'si_app_id' => $id,
|
||||
'si_id' => $si_id,
|
||||
'si_owner' => $owner,
|
||||
),false,__LINE__,__FILE__);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the cat_id(s) for an entry
|
||||
*
|
||||
* @param string $app
|
||||
* @param string|int $id
|
||||
* @param array|int|string $cat_ids=null optional cat_id(s) either comma-separated or as array
|
||||
* @param int $owner=null
|
||||
* @return boolean true on success, false on error
|
||||
*/
|
||||
static private function add_cats($app,$id,$cat_ids,$owner=null)
|
||||
{
|
||||
if (!$app)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!$cat_ids)
|
||||
{
|
||||
return true; // nothing to do
|
||||
}
|
||||
foreach(is_array($cat_ids) ? $cat_ids : explode(',',$cat_ids) as $cat_id)
|
||||
{
|
||||
self::$db->insert(self::INDEX_CAT_TABLE,array(
|
||||
'cat_id' => $cat_id,
|
||||
'ce_app' => $app,
|
||||
'ce_app_id' => $id,
|
||||
'ce_owner' => $owner,
|
||||
),false,__LINE__,__FILE__);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the cat for an entry or an entire application
|
||||
*
|
||||
* @param string $app
|
||||
* @param string|int $id=null
|
||||
*/
|
||||
static private function delete_cats($app,$id=null)
|
||||
{
|
||||
if (!$app)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
$where = array('ce_app' => $app);
|
||||
if ($id)
|
||||
{
|
||||
$where['ce_app_id'] = $id;
|
||||
}
|
||||
return !!self::$db->delete(self::INDEX_CAT_TABLE,$where,__LINE__,__FILE__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init our static vars
|
||||
*/
|
||||
static function _init_static()
|
||||
{
|
||||
if (!is_object($GLOBALS['egw_setup']))
|
||||
{
|
||||
self::$db = $GLOBALS['egw']->db;
|
||||
}
|
||||
else
|
||||
{
|
||||
self::$db = $GLOBALS['egw_setup']->db;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
egw_index::_init_static();
|
@ -11,8 +11,8 @@
|
||||
|
||||
/* Basic information about this app */
|
||||
$setup_info['phpgwapi']['name'] = 'phpgwapi';
|
||||
$setup_info['phpgwapi']['title'] = 'EGroupware old API';
|
||||
$setup_info['phpgwapi']['version'] = '14.3.908';
|
||||
$setup_info['phpgwapi']['title'] = 'old EGroupware API';
|
||||
$setup_info['phpgwapi']['version'] = '14.3.909';
|
||||
$setup_info['phpgwapi']['versions']['current_header'] = '1.29';
|
||||
$setup_info['phpgwapi']['enable'] = 3;
|
||||
$setup_info['phpgwapi']['app_order'] = 1;
|
||||
@ -22,28 +22,8 @@ $setup_info['phpgwapi']['maintainer'] = $setup_info['phpgwapi']['author'] = arra
|
||||
'email' => 'egroupware-developers@lists.sourceforge.net',
|
||||
);
|
||||
|
||||
/* The tables this app creates */
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_config';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_applications';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_acl';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_accounts';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_preferences';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_access_log';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_languages';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_lang';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_categories';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_history_log';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_async';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_links';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_addressbook';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_addressbook_extra';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_addressbook_lists';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_addressbook2list';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_sqlfs';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_index_keywords';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_index';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_cat2entry';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_locks';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_sqlfs_props';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_customfields';
|
||||
$setup_info['phpgwapi']['tables'][] = 'egw_sharing';
|
||||
// old Api depends on new one
|
||||
$setup_info['phpgwapi']['depends']['api'] = array(
|
||||
'appname' => 'api',
|
||||
'versions' => Array('16.1')
|
||||
);
|
||||
|
@ -11,433 +11,4 @@
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
$phpgw_baseline = array(
|
||||
'egw_config' => array(
|
||||
'fd' => array(
|
||||
'config_app' => array('type' => 'ascii','precision' => '16','nullable' => False),
|
||||
'config_name' => array('type' => 'ascii','precision' => '32','nullable' => False),
|
||||
'config_value' => array('type' => 'text')
|
||||
),
|
||||
'pk' => array('config_app','config_name'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_applications' => array(
|
||||
'fd' => array(
|
||||
'app_id' => array('type' => 'auto','precision' => '4','nullable' => False),
|
||||
'app_name' => array('type' => 'ascii','precision' => '16','nullable' => False),
|
||||
'app_enabled' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'app_order' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'app_tables' => array('type' => 'ascii','precision' => '8192','nullable' => False),
|
||||
'app_version' => array('type' => 'ascii','precision' => '20','nullable' => False,'default' => '0.0'),
|
||||
'app_icon' => array('type' => 'ascii','precision' => '32'),
|
||||
'app_icon_app' => array('type' => 'ascii','precision' => '16'),
|
||||
'app_index' => array('type' => 'ascii','precision' => '64')
|
||||
),
|
||||
'pk' => array('app_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(array('app_enabled','app_order')),
|
||||
'uc' => array('app_name')
|
||||
),
|
||||
'egw_acl' => array(
|
||||
'fd' => array(
|
||||
'acl_appname' => array('type' => 'ascii','precision' => '16','nullable' => False),
|
||||
'acl_location' => array('type' => 'ascii','meta' => 'account','precision' => '16','nullable' => False),
|
||||
'acl_account' => array('type' => 'int','meta' => 'account','precision' => '4','nullable' => False),
|
||||
'acl_rights' => array('type' => 'int','precision' => '4'),
|
||||
'acl_id' => array('type' => 'auto','nullable' => False)
|
||||
),
|
||||
'pk' => array('acl_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array('acl_account',array('acl_location','acl_account'),array('acl_appname','acl_account')),
|
||||
'uc' => array(array('acl_appname','acl_location','acl_account'))
|
||||
),
|
||||
'egw_accounts' => array(
|
||||
'fd' => array(
|
||||
'account_id' => array('type' => 'auto','meta' => 'account-abs','nullable' => False),
|
||||
'account_lid' => array('type' => 'varchar','precision' => '64','nullable' => False),
|
||||
'account_pwd' => array('type' => 'varchar','precision' => '128','nullable' => False),
|
||||
'account_lastlogin' => array('type' => 'int','precision' => '4'),
|
||||
'account_lastloginfrom' => array('type' => 'ascii','precision' => '48','comment' => 'ip'),
|
||||
'account_lastpwd_change' => array('type' => 'int','precision' => '4'),
|
||||
'account_status' => array('type' => 'char','precision' => '1','nullable' => False,'default' => 'A'),
|
||||
'account_expires' => array('type' => 'int','precision' => '4'),
|
||||
'account_type' => array('type' => 'char','precision' => '1'),
|
||||
'account_primary_group' => array('type' => 'int','meta' => 'group','precision' => '4','nullable' => False,'default' => '0'),
|
||||
'account_description' => array('type' => 'varchar','precision' => '255','comment' => 'group description')
|
||||
),
|
||||
'pk' => array('account_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array('account_lid')
|
||||
),
|
||||
'egw_preferences' => array(
|
||||
'fd' => array(
|
||||
'preference_owner' => array('type' => 'int','meta' => 'account-prefs','precision' => '4','nullable' => False),
|
||||
'preference_app' => array('type' => 'ascii','precision' => '16','nullable' => False),
|
||||
'preference_value' => array('type' => 'text','nullable' => False),
|
||||
'preference_id' => array('type' => 'auto','nullable' => False)
|
||||
),
|
||||
'pk' => array('preference_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array(array('preference_owner','preference_app'))
|
||||
),
|
||||
'egw_access_log' => array(
|
||||
'fd' => array(
|
||||
'sessionid' => array('type' => 'auto','nullable' => False,'comment' => 'primary key'),
|
||||
'loginid' => array('type' => 'varchar','precision' => '64','nullable' => False,'comment' => 'username used to login'),
|
||||
'ip' => array('type' => 'ascii','precision' => '48','nullable' => False,'comment' => 'ip of user'),
|
||||
'li' => array('type' => 'int','meta' => 'timestamp','precision' => '8','nullable' => False,'comment' => 'TS if login'),
|
||||
'lo' => array('type' => 'int','meta' => 'timestamp','precision' => '8','comment' => 'TD of logout'),
|
||||
'account_id' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False,'default' => '0','comment' => 'numerical account id'),
|
||||
'session_dla' => array('type' => 'int','meta' => 'timestamp','precision' => '8','comment' => 'TS of last user action'),
|
||||
'session_action' => array('type' => 'ascii','precision' => '64','comment' => 'menuaction or path of last user action'),
|
||||
'session_php' => array('type' => 'ascii','precision' => '64','nullable' => False,'comment' => 'php session-id or error-message'),
|
||||
'notification_heartbeat' => array('type' => 'int','meta' => 'timestamp','precision' => '8','comment' => 'TS of last notification request'),
|
||||
'user_agent' => array('type' => 'ascii','precision' => '255','comment' => 'User-agent of browser/device')
|
||||
),
|
||||
'pk' => array('sessionid'),
|
||||
'fk' => array(),
|
||||
'ix' => array('li','lo','session_dla','session_php','notification_heartbeat',array('account_id','ip','li'),array('account_id','loginid','li')),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_languages' => array(
|
||||
'fd' => array(
|
||||
'lang_id' => array('type' => 'ascii','precision' => '5','nullable' => False),
|
||||
'lang_name' => array('type' => 'varchar','precision' => '50','nullable' => False)
|
||||
),
|
||||
'pk' => array('lang_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_lang' => array(
|
||||
'fd' => array(
|
||||
'lang' => array('type' => 'varchar','precision' => '5','nullable' => False,'default' => ''),
|
||||
'app_name' => array('type' => 'ascii','precision' => '16','nullable' => False,'default' => 'common'),
|
||||
'message_id' => array('type' => 'ascii','precision' => '128','nullable' => False,'default' => ''),
|
||||
'content' => array('type' => 'varchar','precision' => '8192'),
|
||||
'lang_id' => array('type' => 'auto','nullable' => False)
|
||||
),
|
||||
'pk' => array('lang_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array(array('lang','app_name','message_id'))
|
||||
),
|
||||
'egw_categories' => array(
|
||||
'fd' => array(
|
||||
'cat_id' => array('type' => 'auto','meta' => 'category','precision' => '4','nullable' => False),
|
||||
'cat_main' => array('type' => 'int','meta' => 'category','precision' => '4','nullable' => False,'default' => '0'),
|
||||
'cat_parent' => array('type' => 'int','meta' => 'category','precision' => '4','nullable' => False,'default' => '0'),
|
||||
'cat_level' => array('type' => 'int','precision' => '2','nullable' => False,'default' => '0'),
|
||||
'cat_owner' => array('type' => 'ascii','meta' => 'account-commasep','precision' => '255','nullable' => False,'default' => '0'),
|
||||
'cat_access' => array('type' => 'ascii','precision' => '7'),
|
||||
'cat_appname' => array('type' => 'ascii','precision' => '16','nullable' => False),
|
||||
'cat_name' => array('type' => 'varchar','precision' => '150','nullable' => False),
|
||||
'cat_description' => array('type' => 'varchar','precision' => '255','nullable' => False),
|
||||
'cat_data' => array('type' => 'varchar','precision' => '8192'),
|
||||
'last_mod' => array('type' => 'int','meta' => 'timestamp','precision' => '8','nullable' => False)
|
||||
),
|
||||
'pk' => array('cat_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(array('cat_appname','cat_owner','cat_parent','cat_level')),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_history_log' => array(
|
||||
'fd' => array(
|
||||
'history_id' => array('type' => 'auto','precision' => '4','nullable' => False),
|
||||
'history_record_id' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'history_appname' => array('type' => 'ascii','precision' => '16','nullable' => False),
|
||||
'history_owner' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False),
|
||||
'history_status' => array('type' => 'varchar','precision' => '32','nullable' => False),
|
||||
'history_new_value' => array('type' => 'text','nullable' => False),
|
||||
'history_timestamp' => array('type' => 'timestamp','nullable' => False,'default' => 'current_timestamp'),
|
||||
'history_old_value' => array('type' => 'text','nullable' => False),
|
||||
'sessionid' => array('type' => 'int','precision' => '4','comment' => 'primary key to egw_access_log')
|
||||
),
|
||||
'pk' => array('history_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(array('history_appname','history_record_id','history_id')),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_async' => array(
|
||||
'fd' => array(
|
||||
'async_id' => array('type' => 'ascii','precision' => '64','nullable' => False),
|
||||
'async_next' => array('type' => 'int','meta' => 'timestamp','precision' => '4','nullable' => False,'comment' => 'timestamp of next run'),
|
||||
'async_times' => array('type' => 'ascii','precision' => '255','nullable' => False,'comment' => 'serialized array with values for keys hour,min,day,month,year'),
|
||||
'async_method' => array('type' => 'ascii','precision' => '80','nullable' => False,'comment' => 'app.class.method class::method to execute'),
|
||||
'async_data' => array('type' => 'varchar','precision' => '8192','nullable' => False,'comment' => 'serialized array with data to pass to method'),
|
||||
'async_account_id' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False,'default' => '0','comment' => 'creator of job'),
|
||||
'async_auto_id' => array('type' => 'auto','nullable' => False)
|
||||
),
|
||||
'pk' => array('async_auto_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array('async_id')
|
||||
),
|
||||
'egw_links' => array(
|
||||
'fd' => array(
|
||||
'link_id' => array('type' => 'auto','nullable' => False),
|
||||
'link_app1' => array('type' => 'ascii','precision' => '16','nullable' => False),
|
||||
'link_id1' => array('type' => 'ascii','meta' => array("link_app1='home-accounts'" => 'account'),'precision' => '64','nullable' => False),
|
||||
'link_app2' => array('type' => 'ascii','precision' => '16','nullable' => False),
|
||||
'link_id2' => array('type' => 'ascii','meta' => array("link_app2='home-accounts'" => 'account'),'precision' => '64','nullable' => False),
|
||||
'link_remark' => array('type' => 'varchar','precision' => '100'),
|
||||
'link_lastmod' => array('type' => 'int','meta' => 'timestamp','precision' => '8','nullable' => False),
|
||||
'link_owner' => array('type' => 'int','meta' => 'account','precision' => '4','nullable' => False),
|
||||
'deleted' => array('type' => 'timestamp')
|
||||
),
|
||||
'pk' => array('link_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array('deleted',array('link_app1','link_id1','link_lastmod'),array('link_app2','link_id2','link_lastmod')),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_addressbook' => array(
|
||||
'fd' => array(
|
||||
'contact_id' => array('type' => 'auto','nullable' => False),
|
||||
'contact_tid' => array('type' => 'char','precision' => '1','default' => 'n'),
|
||||
'contact_owner' => array('type' => 'int','meta' => 'account','precision' => '8','nullable' => False,'comment' => 'account or group id of the adressbook'),
|
||||
'contact_private' => array('type' => 'int','precision' => '1','default' => '0','comment' => 'privat or personal'),
|
||||
'cat_id' => array('type' => 'ascii','meta' => 'category','precision' => '255','comment' => 'Category(s)'),
|
||||
'n_family' => array('type' => 'varchar','precision' => '64','comment' => 'Family name'),
|
||||
'n_given' => array('type' => 'varchar','precision' => '64','comment' => 'Given Name'),
|
||||
'n_middle' => array('type' => 'varchar','precision' => '64'),
|
||||
'n_prefix' => array('type' => 'varchar','precision' => '64','comment' => 'Prefix'),
|
||||
'n_suffix' => array('type' => 'varchar','precision' => '64','comment' => 'Suffix'),
|
||||
'n_fn' => array('type' => 'varchar','precision' => '128','comment' => 'Full name'),
|
||||
'n_fileas' => array('type' => 'varchar','precision' => '255','comment' => 'sort as'),
|
||||
'contact_bday' => array('type' => 'varchar','precision' => '12','comment' => 'Birtday'),
|
||||
'org_name' => array('type' => 'varchar','precision' => '128','comment' => 'Organisation'),
|
||||
'org_unit' => array('type' => 'varchar','precision' => '64','comment' => 'Department'),
|
||||
'contact_title' => array('type' => 'varchar','precision' => '64','comment' => 'jobtittle'),
|
||||
'contact_role' => array('type' => 'varchar','precision' => '64','comment' => 'role'),
|
||||
'contact_assistent' => array('type' => 'varchar','precision' => '64','comment' => 'Name of the Assistent (for phone number)'),
|
||||
'contact_room' => array('type' => 'varchar','precision' => '64','comment' => 'room'),
|
||||
'adr_one_street' => array('type' => 'varchar','precision' => '64','comment' => 'street (business)'),
|
||||
'adr_one_street2' => array('type' => 'varchar','precision' => '64','comment' => 'street (business) - 2. line'),
|
||||
'adr_one_locality' => array('type' => 'varchar','precision' => '64','comment' => 'city (business)'),
|
||||
'adr_one_region' => array('type' => 'varchar','precision' => '64','comment' => 'region (business)'),
|
||||
'adr_one_postalcode' => array('type' => 'varchar','precision' => '64','comment' => 'postalcode (business)'),
|
||||
'adr_one_countryname' => array('type' => 'varchar','precision' => '64','comment' => 'countryname (business)'),
|
||||
'contact_label' => array('type' => 'text','comment' => 'currently not used'),
|
||||
'adr_two_street' => array('type' => 'varchar','precision' => '64','comment' => 'street (private)'),
|
||||
'adr_two_street2' => array('type' => 'varchar','precision' => '64','comment' => 'street (private) - 2. line'),
|
||||
'adr_two_locality' => array('type' => 'varchar','precision' => '64','comment' => 'city (private)'),
|
||||
'adr_two_region' => array('type' => 'varchar','precision' => '64','comment' => 'region (private)'),
|
||||
'adr_two_postalcode' => array('type' => 'varchar','precision' => '64','comment' => 'postalcode (private)'),
|
||||
'adr_two_countryname' => array('type' => 'varchar','precision' => '64','comment' => 'countryname (private)'),
|
||||
'tel_work' => array('type' => 'varchar','precision' => '40','comment' => 'phone-number (business)'),
|
||||
'tel_cell' => array('type' => 'varchar','precision' => '40','comment' => 'mobil phone (business)'),
|
||||
'tel_fax' => array('type' => 'varchar','precision' => '40','comment' => 'fax-number (business)'),
|
||||
'tel_assistent' => array('type' => 'varchar','precision' => '40','comment' => 'phone-number assistent'),
|
||||
'tel_car' => array('type' => 'varchar','precision' => '40'),
|
||||
'tel_pager' => array('type' => 'varchar','precision' => '40','comment' => 'pager'),
|
||||
'tel_home' => array('type' => 'varchar','precision' => '40','comment' => 'phone-number (private)'),
|
||||
'tel_fax_home' => array('type' => 'varchar','precision' => '40','comment' => 'fax-number (private)'),
|
||||
'tel_cell_private' => array('type' => 'varchar','precision' => '40','comment' => 'mobil phone (private)'),
|
||||
'tel_other' => array('type' => 'varchar','precision' => '40','comment' => 'other phone'),
|
||||
'tel_prefer' => array('type' => 'varchar','precision' => '32','comment' => 'prefered phone-number'),
|
||||
'contact_email' => array('type' => 'varchar','precision' => '128','comment' => 'email address (business)'),
|
||||
'contact_email_home' => array('type' => 'varchar','precision' => '128','comment' => 'email address (private)'),
|
||||
'contact_url' => array('type' => 'varchar','precision' => '128','comment' => 'website (business)'),
|
||||
'contact_url_home' => array('type' => 'varchar','precision' => '128','comment' => 'website (private)'),
|
||||
'contact_freebusy_uri' => array('type' => 'ascii','precision' => '128','comment' => 'freebusy-url for calendar of the contact'),
|
||||
'contact_calendar_uri' => array('type' => 'ascii','precision' => '128','comment' => 'url for users calendar - currently not used'),
|
||||
'contact_note' => array('type' => 'varchar','precision' => '8192','comment' => 'notes field'),
|
||||
'contact_tz' => array('type' => 'varchar','precision' => '8','comment' => 'timezone difference'),
|
||||
'contact_geo' => array('type' => 'ascii','precision' => '32','comment' => 'currently not used'),
|
||||
'contact_pubkey' => array('type' => 'ascii','precision' => '16384','comment' => 'public key'),
|
||||
'contact_created' => array('type' => 'int','meta' => 'timestamp','precision' => '8','comment' => 'timestamp of the creation'),
|
||||
'contact_creator' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False,'comment' => 'account id of the creator'),
|
||||
'contact_modified' => array('type' => 'int','meta' => 'timestamp','precision' => '8','nullable' => False,'comment' => 'timestamp of the last modified'),
|
||||
'contact_modifier' => array('type' => 'int','meta' => 'user','precision' => '4','comment' => 'account id of the last modified'),
|
||||
'contact_jpegphoto' => array('type' => 'blob','comment' => 'photo of the contact (attachment)'),
|
||||
'account_id' => array('type' => 'int','meta' => 'user','precision' => '4','comment' => 'account id'),
|
||||
'contact_etag' => array('type' => 'int','precision' => '4','default' => '0','comment' => 'etag of the changes'),
|
||||
'contact_uid' => array('type' => 'ascii','precision' => '128','comment' => 'unique id of the contact'),
|
||||
'adr_one_countrycode' => array('type' => 'ascii','precision' => '2','comment' => 'countrycode (business)'),
|
||||
'adr_two_countrycode' => array('type' => 'ascii','precision' => '2','comment' => 'countrycode (private)'),
|
||||
'carddav_name' => array('type' => 'ascii','precision' => '128','comment' => 'name part of CardDAV URL, if specified by client')
|
||||
),
|
||||
'pk' => array('contact_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array('contact_owner','cat_id','n_fileas','contact_modified','contact_uid','carddav_name',array('n_family','n_given'),array('n_given','n_family'),array('org_name','n_family','n_given')),
|
||||
'uc' => array('account_id')
|
||||
),
|
||||
'egw_addressbook_extra' => array(
|
||||
'fd' => array(
|
||||
'contact_id' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'contact_owner' => array('type' => 'int','meta' => 'account','precision' => '8'),
|
||||
'contact_name' => array('type' => 'varchar','meta' => 'cfname','precision' => '64','nullable' => False,'comment' => 'custom-field name'),
|
||||
'contact_value' => array('type' => 'varchar','meta' => 'cfvalue','precision' => '16384','comment' => 'custom-field value'),
|
||||
'contact_extra_id' => array('type' => 'auto','nullable' => False)
|
||||
),
|
||||
'pk' => array('contact_extra_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array('contact_name',array('contact_id','contact_name')),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_addressbook_lists' => array(
|
||||
'fd' => array(
|
||||
'list_id' => array('type' => 'auto','nullable' => False),
|
||||
'list_name' => array('type' => 'varchar','precision' => '80','nullable' => False),
|
||||
'list_owner' => array('type' => 'int','meta' => 'account','precision' => '4','nullable' => False),
|
||||
'list_created' => array('type' => 'int','meta' => 'timestamp','precision' => '8'),
|
||||
'list_creator' => array('type' => 'int','meta' => 'user','precision' => '4'),
|
||||
'list_uid' => array('type' => 'ascii','precision' => '128'),
|
||||
'list_carddav_name' => array('type' => 'ascii','precision' => '128'),
|
||||
'list_etag' => array('type' => 'int','precision' => '4','nullable' => False,'default' => '0'),
|
||||
'list_modified' => array('type' => 'timestamp','nullable' => False,'default' => 'current_timestamp'),
|
||||
'list_modifier' => array('type' => 'int','meta' => 'user','precision' => '4')
|
||||
),
|
||||
'pk' => array('list_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array('list_uid','list_carddav_name',array('list_owner','list_name'))
|
||||
),
|
||||
'egw_addressbook2list' => array(
|
||||
'fd' => array(
|
||||
'contact_id' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'list_id' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'list_added' => array('type' => 'int','meta' => 'timestamp','precision' => '8'),
|
||||
'list_added_by' => array('type' => 'int','meta' => 'user','precision' => '4')
|
||||
),
|
||||
'pk' => array('contact_id','list_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_sqlfs' => array(
|
||||
'fd' => array(
|
||||
'fs_id' => array('type' => 'auto','nullable' => False),
|
||||
'fs_dir' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'fs_name' => array('type' => 'varchar','precision' => '200','nullable' => False),
|
||||
'fs_mode' => array('type' => 'int','precision' => '2','nullable' => False),
|
||||
'fs_uid' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False,'default' => '0'),
|
||||
'fs_gid' => array('type' => 'int','meta' => 'group-abs','precision' => '4','nullable' => False,'default' => '0'),
|
||||
'fs_created' => array('type' => 'timestamp','precision' => '8','nullable' => False),
|
||||
'fs_modified' => array('type' => 'timestamp','precision' => '8','nullable' => False),
|
||||
'fs_mime' => array('type' => 'ascii','precision' => '96','nullable' => False),
|
||||
'fs_size' => array('type' => 'int','precision' => '8','nullable' => False),
|
||||
'fs_creator' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False),
|
||||
'fs_modifier' => array('type' => 'int','meta' => 'user','precision' => '4'),
|
||||
'fs_active' => array('type' => 'bool','nullable' => False,'default' => 't'),
|
||||
'fs_content' => array('type' => 'blob'),
|
||||
'fs_link' => array('type' => 'varchar','precision' => '255')
|
||||
),
|
||||
'pk' => array('fs_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(array('fs_dir','fs_active','fs_name(16)')),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_index_keywords' => array(
|
||||
'fd' => array(
|
||||
'si_id' => array('type' => 'auto','nullable' => False),
|
||||
'si_keyword' => array('type' => 'varchar','precision' => '64','nullable' => False),
|
||||
'si_ignore' => array('type' => 'bool')
|
||||
),
|
||||
'pk' => array('si_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array('si_keyword')
|
||||
),
|
||||
'egw_index' => array(
|
||||
'fd' => array(
|
||||
'si_app' => array('type' => 'varchar','precision' => '25','nullable' => False),
|
||||
'si_app_id' => array('type' => 'varchar','precision' => '50','nullable' => False),
|
||||
'si_id' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'si_owner' => array('type' => 'int','meta' => 'account','precision' => '4','nullable' => False)
|
||||
),
|
||||
'pk' => array('si_app','si_app_id','si_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array('si_id'),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_cat2entry' => array(
|
||||
'fd' => array(
|
||||
'ce_app' => array('type' => 'varchar','precision' => '25','nullable' => False),
|
||||
'ce_app_id' => array('type' => 'varchar','precision' => '50','nullable' => False),
|
||||
'cat_id' => array('type' => 'int','meta' => 'category','precision' => '4','nullable' => False),
|
||||
'ce_owner' => array('type' => 'int','meta' => 'account','precision' => '4','nullable' => False)
|
||||
),
|
||||
'pk' => array('ce_app','ce_app_id','cat_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array('cat_id'),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_locks' => array(
|
||||
'fd' => array(
|
||||
'lock_token' => array('type' => 'ascii','precision' => '64','nullable' => False),
|
||||
'lock_path' => array('type' => 'varchar','precision' => '255','nullable' => False),
|
||||
'lock_expires' => array('type' => 'int','meta' => 'timestamp','precision' => '8','nullable' => False),
|
||||
'lock_owner' => array('type' => 'varchar','precision' => '255'),
|
||||
'lock_recursive' => array('type' => 'bool','nullable' => False,'default' => '0'),
|
||||
'lock_write' => array('type' => 'bool','nullable' => False,'default' => '0'),
|
||||
'lock_exclusive' => array('type' => 'bool','nullable' => False,'default' => '0'),
|
||||
'lock_created' => array('type' => 'int','meta' => 'timestamp','precision' => '8','default' => '0'),
|
||||
'lock_modified' => array('type' => 'int','meta' => 'timestamp','precision' => '8','default' => '0'),
|
||||
'lock_id' => array('type' => 'auto','nullable' => False)
|
||||
),
|
||||
'pk' => array('lock_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array('lock_path','lock_expires'),
|
||||
'uc' => array('lock_token')
|
||||
),
|
||||
'egw_sqlfs_props' => array(
|
||||
'fd' => array(
|
||||
'fs_id' => array('type' => 'int','precision' => '4','nullable' => False),
|
||||
'prop_namespace' => array('type' => 'ascii','precision' => '64','nullable' => False),
|
||||
'prop_name' => array('type' => 'ascii','precision' => '64','nullable' => False),
|
||||
'prop_value' => array('type' => 'varchar','precision' => '16384'),
|
||||
'prop_id' => array('type' => 'auto','nullable' => False)
|
||||
),
|
||||
'pk' => array('prop_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(array('fs_id','prop_namespace','prop_name')),
|
||||
'uc' => array()
|
||||
),
|
||||
'egw_customfields' => array(
|
||||
'fd' => array(
|
||||
'cf_id' => array('type' => 'auto','nullable' => False),
|
||||
'cf_app' => array('type' => 'ascii','precision' => '16','nullable' => False,'comment' => 'app-name cf belongs too'),
|
||||
'cf_name' => array('type' => 'varchar','precision' => '128','nullable' => False,'comment' => 'internal name'),
|
||||
'cf_label' => array('type' => 'varchar','precision' => '128','comment' => 'label to display'),
|
||||
'cf_type' => array('type' => 'varchar','precision' => '64','nullable' => False,'default' => 'text','comment' => 'type of field'),
|
||||
'cf_type2' => array('type' => 'varchar','precision' => '2048','comment' => 'comma-separated subtypes of app, cf is valid for'),
|
||||
'cf_help' => array('type' => 'varchar','precision' => '256','comment' => 'helptext'),
|
||||
'cf_values' => array('type' => 'varchar','precision' => '8096','comment' => 'json object with value label pairs'),
|
||||
'cf_len' => array('type' => 'int','precision' => '2','comment' => 'length or columns of field'),
|
||||
'cf_rows' => array('type' => 'int','precision' => '2','comment' => 'rows of field'),
|
||||
'cf_order' => array('type' => 'int','precision' => '2','comment' => 'order to display fields'),
|
||||
'cf_needed' => array('type' => 'bool','default' => '0','comment' => 'field is required'),
|
||||
'cf_private' => array('type' => 'ascii','meta' => 'account-commasep','precision' => '2048','comment' => 'comma-separated account_id'),
|
||||
'cf_modifier' => array('type' => 'int','meta' => 'account','precision' => '4','comment' => 'last modifier'),
|
||||
'cf_modified' => array('type' => 'timestamp','default' => 'current_timestamp','comment' => 'last modification time'),
|
||||
'cf_tab' => array('type' => 'varchar','precision' => '64','comment' => 'tab customfield should be shown')
|
||||
),
|
||||
'pk' => array('cf_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(array('cf_app','cf_order')),
|
||||
'uc' => array(array('cf_app','cf_name'))
|
||||
),
|
||||
'egw_sharing' => array(
|
||||
'fd' => array(
|
||||
'share_id' => array('type' => 'auto','nullable' => False,'comment' => 'auto-id'),
|
||||
'share_token' => array('type' => 'ascii','precision' => '64','nullable' => False,'comment' => 'secure token'),
|
||||
'share_path' => array('type' => 'varchar','precision' => '255','nullable' => False,'comment' => 'path to share'),
|
||||
'share_owner' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False,'comment' => 'owner of share'),
|
||||
'share_expires' => array('type' => 'date','comment' => 'expire date of share'),
|
||||
'share_writable' => array('type' => 'int','precision' => '1','nullable' => False,'default' => '0','comment' => '0=readable, 1=writable'),
|
||||
'share_with' => array('type' => 'varchar','precision' => '4096','comment' => 'email addresses, comma seperated'),
|
||||
'share_passwd' => array('type' => 'varchar','precision' => '128','comment' => 'optional password-hash'),
|
||||
'share_created' => array('type' => 'timestamp','nullable' => False,'comment' => 'creation date'),
|
||||
'share_last_accessed' => array('type' => 'timestamp','comment' => 'last access of share')
|
||||
),
|
||||
'pk' => array('share_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array(),
|
||||
'uc' => array('share_token')
|
||||
)
|
||||
);
|
||||
$phpgw_baseline = array();
|
||||
|
@ -1052,7 +1052,7 @@ function phpgwapi_upgrade14_3_906()
|
||||
}
|
||||
|
||||
/**
|
||||
* Move content of (usually empty or for LDAP 2 rows) egw_nextid table to egw_config table and drop it
|
||||
* Drop no longer used egw_hooks table
|
||||
*/
|
||||
function phpgwapi_upgrade14_3_907()
|
||||
{
|
||||
@ -1060,3 +1060,17 @@ function phpgwapi_upgrade14_3_907()
|
||||
|
||||
return $GLOBALS['setup_info']['phpgwapi']['currentver'] = '14.3.908';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Drop never used index tables
|
||||
*/
|
||||
function phpgwapi_upgrade14_3_908()
|
||||
{
|
||||
$GLOBALS['egw_setup']->oProc->DropTable('egw_index_keywords');
|
||||
$GLOBALS['egw_setup']->oProc->DropTable('egw_index');
|
||||
$GLOBALS['egw_setup']->oProc->DropTable('egw_cat2entry');
|
||||
|
||||
return $GLOBALS['setup_info']['phpgwapi']['currentver'] = '14.3.909';
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ $bgcolor = array('#DDDDDD','#EEEEEE');
|
||||
function parsedep($depends,$main=True)
|
||||
{
|
||||
$depstring = '(';
|
||||
foreach($depends as $a => $b)
|
||||
foreach($depends as $b)
|
||||
{
|
||||
foreach($b as $c => $d)
|
||||
{
|
||||
@ -98,14 +98,11 @@ function parsedep($depends,$main=True)
|
||||
$GLOBALS['egw_setup']->loaddb();
|
||||
$GLOBALS['egw_info']['setup']['stage']['db'] = $GLOBALS['egw_setup']->detection->check_db();
|
||||
|
||||
$setup_info = $GLOBALS['egw_setup']->detection->get_versions();
|
||||
//var_dump($setup_info);exit;
|
||||
$setup_info = $GLOBALS['egw_setup']->detection->get_db_versions($setup_info);
|
||||
//var_dump($setup_info);exit;
|
||||
$setup_info = $GLOBALS['egw_setup']->detection->compare_versions($setup_info);
|
||||
//var_dump($setup_info);exit;
|
||||
$setup_info = $GLOBALS['egw_setup']->detection->check_depends($setup_info);
|
||||
//var_dump($setup_info);exit;
|
||||
$setup_info = $GLOBALS['egw_setup']->detection->check_depends(
|
||||
$GLOBALS['egw_setup']->detection->compare_versions(
|
||||
$GLOBALS['egw_setup']->detection->get_db_versions(
|
||||
$GLOBALS['egw_setup']->detection->get_versions())));
|
||||
|
||||
@ksort($setup_info);
|
||||
|
||||
if(@get_var('cancel',Array('POST')))
|
||||
@ -172,8 +169,8 @@ if(@get_var('submit',Array('POST')))
|
||||
|
||||
if ($setup_info[$appname]['tables'])
|
||||
{
|
||||
$terror = $GLOBALS['egw_setup']->process->current($terror,$DEBUG);
|
||||
$terror = $GLOBALS['egw_setup']->process->default_records($terror,$DEBUG);
|
||||
$terror_c = $GLOBALS['egw_setup']->process->current($terror, $DEBUG);
|
||||
$terror = $GLOBALS['egw_setup']->process->default_records($terror_c, $DEBUG);
|
||||
echo '<br />' . $app_title . ' '
|
||||
. lang('tables installed, unless there are errors printed above') . '.';
|
||||
}
|
||||
@ -193,7 +190,7 @@ if(@get_var('submit',Array('POST')))
|
||||
|
||||
if ($setup_info[$appname]['hooks'])
|
||||
{
|
||||
$GLOBALS['egw_setup']->register_hooks($setup_info[$appname]['name']);
|
||||
Api\Hooks::read(true);
|
||||
echo '<br />' . $app_title . ' ' . lang('hooks registered') . '.';
|
||||
}
|
||||
}
|
||||
@ -233,14 +230,9 @@ else
|
||||
|
||||
if(@get_var('hooks', Array('GET')))
|
||||
{
|
||||
egw_cache::flush(egw_cache::INSTANCE);
|
||||
Api\Cache::flush(Api\Cache::INSTANCE);
|
||||
|
||||
// Find & register all application hooks
|
||||
foreach($setup_info as $appname => $info)
|
||||
{
|
||||
if ($info['currentver']) $GLOBALS['egw_setup']->register_hooks($appname);
|
||||
}
|
||||
echo lang('All hooks registered') . '<br />';
|
||||
echo lang('Cached cleared') . '<br />';
|
||||
}
|
||||
$detail = get_var('detail',Array('GET'));
|
||||
$resolve = get_var('resolve',Array('GET'));
|
||||
@ -256,29 +248,44 @@ if(@$detail)
|
||||
|
||||
foreach($setup_info[$detail] as $key => $val)
|
||||
{
|
||||
if($key != 'title')
|
||||
{
|
||||
$i = ($i ? 0 : 1);
|
||||
|
||||
if ($key == 'tables')
|
||||
switch($key)
|
||||
{
|
||||
case 'title':
|
||||
continue 2;
|
||||
case 'tables':
|
||||
$tblcnt = count($setup_info[$detail][$key]);
|
||||
if(is_array($val))
|
||||
{
|
||||
$key = '<a href="sqltoarray.php?appname=' . $detail . '&submit=True&apps=True">' . $key . '(' . $tblcnt . ')</a>' . "\n";
|
||||
$val = implode(',' . "\n",$val);
|
||||
}
|
||||
break;
|
||||
case 'hooks':
|
||||
foreach($val as &$hooks)
|
||||
{
|
||||
$hooks = (array)$hooks;
|
||||
}
|
||||
if ($key == 'hooks') { $val = implode(',',$val); }
|
||||
if ($key == 'depends') { $val = parsedep($val); }
|
||||
if (is_array($val)) { $val = implode(',',$val); }
|
||||
|
||||
$setup_tpl->set_var('bg_color',$bgcolor[$i]);
|
||||
$val = str_replace('EGroupware\\', '', implode(', ', call_user_func_array('array_merge', $val)));
|
||||
break;
|
||||
case 'depends':
|
||||
foreach($val as &$dep)
|
||||
{
|
||||
$dep = $dep['appname'].': '.implode(', ', $dep['versions']);
|
||||
}
|
||||
$val = implode('; ', $val);
|
||||
break;
|
||||
case 'check_install':
|
||||
$val = array2string($val);
|
||||
break;
|
||||
default:
|
||||
if (is_array($val)) $val = implode(', ', $val);
|
||||
break;
|
||||
}
|
||||
$setup_tpl->set_var('bg_color', $bgcolor[++$i & 1]);
|
||||
$setup_tpl->set_var('name',$key);
|
||||
$setup_tpl->set_var('details',$val);
|
||||
$setup_tpl->pparse('out','detail');
|
||||
}
|
||||
}
|
||||
|
||||
echo '<br /><a href="applications.php?debug='.$DEBUG.'">' . lang('Go back') . '</a>';
|
||||
$setup_tpl->pparse('out','footer');
|
||||
@ -345,8 +352,7 @@ elseif (@$resolve)
|
||||
{
|
||||
$list .= $y . ', ';
|
||||
}
|
||||
$list = substr($list,0,-2);
|
||||
echo "$list\n";
|
||||
echo substr($list,0,-2)."\n";
|
||||
}
|
||||
echo '<br /><br />' . lang('The table definition was correct, and the tables were installed') . '.';
|
||||
}
|
||||
@ -423,7 +429,7 @@ else
|
||||
switch($value['status'])
|
||||
{
|
||||
case 'C':
|
||||
$setup_tpl->set_var('remove',$key == 'phpgwapi' ? ' ' : '<input type="checkbox" name="remove[' . $value['name'] . ']" />');
|
||||
$setup_tpl->set_var('remove', in_array($key, array('api', 'phpgwapi')) ? ' ' : '<input type="checkbox" name="remove[' . $value['name'] . ']" />');
|
||||
$setup_tpl->set_var('upgrade',' ');
|
||||
if (!$GLOBALS['egw_setup']->detection->check_app_tables($value['name']))
|
||||
{
|
||||
|
@ -103,10 +103,9 @@ if($GLOBALS['error'] && is_array($newsettings))
|
||||
}
|
||||
else
|
||||
{
|
||||
$GLOBALS['egw_setup']->db->select($GLOBALS['egw_setup']->config_table,'*',false,__LINES__,__FILES__);
|
||||
while($GLOBALS['egw_setup']->db->next_record())
|
||||
foreach($GLOBALS['egw_setup']->db->select($GLOBALS['egw_setup']->config_table,'*',false,__LINES__,__FILES__) as $row)
|
||||
{
|
||||
$GLOBALS['current_config'][$GLOBALS['egw_setup']->db->f('config_name')] = $GLOBALS['egw_setup']->db->f('config_value');
|
||||
$GLOBALS['current_config'][$row['config_name']] = $row['config_value'];
|
||||
}
|
||||
}
|
||||
$setup_tpl->pparse('out','T_config_pre_script');
|
||||
|
@ -114,13 +114,14 @@ class setup
|
||||
}
|
||||
|
||||
try {
|
||||
$GLOBALS['egw']->db = $this->db = new egw_db($GLOBALS['egw_domain'][$this->ConfigDomain]);
|
||||
$GLOBALS['egw']->db = $this->db = new Api\Db\Deprecated($GLOBALS['egw_domain'][$this->ConfigDomain]);
|
||||
$this->db->connect();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
unset($e);
|
||||
return;
|
||||
}
|
||||
$this->db->set_app('phpgwapi');
|
||||
$this->db->set_app(Api\Db::API_APPNAME);
|
||||
|
||||
if ($connect_and_setcharset)
|
||||
{
|
||||
@ -128,22 +129,19 @@ class setup
|
||||
$this->set_table_names(); // sets/checks config- and applications-table-name
|
||||
|
||||
// Set the DB's client charset if a system-charset is set
|
||||
$this->db->select($this->config_table,'config_value',array(
|
||||
if (($this->system_charset = $this->db->select($this->config_table,'config_value',array(
|
||||
'config_app' => 'phpgwapi',
|
||||
'config_name' => 'system_charset',
|
||||
),__LINE__,__FILE__);
|
||||
if ($this->db->next_record() && $this->db->f(0))
|
||||
),__LINE__,__FILE__)->fetchColumn()))
|
||||
{
|
||||
$this->system_charset = $this->db->f(0);
|
||||
$this->db_charset_was = $this->db->Link_ID->GetCharSet(); // needed for the update
|
||||
|
||||
// we can NOT set the DB charset for mysql, if the api version < 1.0.1.019, as it would mess up the DB content!!!
|
||||
if (substr($this->db->Type,0,5) == 'mysql') // we need to check the api version
|
||||
{
|
||||
$this->db->select($this->applications_table,'app_version',array(
|
||||
$api_version = $this->db->select($this->applications_table,'app_version',array(
|
||||
'app_name' => 'phpgwapi',
|
||||
),__LINE__,__FILE__);
|
||||
$api_version = $this->db->next_record() ? $this->db->f(0) : false;
|
||||
),__LINE__,__FILE__)->fetchColumn();
|
||||
}
|
||||
if (!$api_version || !$this->alessthanb($api_version,'1.0.1.019'))
|
||||
{
|
||||
@ -454,12 +452,13 @@ class setup
|
||||
/**
|
||||
* Add an application to the phpgw_applications table
|
||||
*
|
||||
* @param $appname Application 'name' with a matching $setup_info[$appname] array slice
|
||||
* @param string $appname Application 'name' with a matching $setup_info[$appname] array slice
|
||||
* @param $_enable =99 set to True/False to override setup.inc.php setting
|
||||
* @param array $setup_info =null default use $GLOBALS['setup_info']
|
||||
*/
|
||||
function register_app($appname, $_enable=99)
|
||||
function register_app($appname, $_enable=99, array $setup_info=null)
|
||||
{
|
||||
$setup_info = $GLOBALS['setup_info'];
|
||||
if (!isset($setup_info)) $setup_info = $GLOBALS['setup_info'];
|
||||
|
||||
if(!$appname)
|
||||
{
|
||||
@ -530,8 +529,7 @@ class setup
|
||||
// _debug_array($setup_info[$appname]);
|
||||
}
|
||||
|
||||
$this->db->select($this->applications_table,'COUNT(*)',array('app_name' => $appname),__LINE__,__FILE__);
|
||||
if($this->db->next_record() && $this->db->f(0))
|
||||
if ($this->db->select($this->applications_table,'COUNT(*)',array('app_name' => $appname),__LINE__,__FILE__)->fetchColumn())
|
||||
{
|
||||
if(@$GLOBALS['DEBUG'])
|
||||
{
|
||||
@ -549,12 +547,12 @@ class setup
|
||||
/**
|
||||
* Update application info in the db
|
||||
*
|
||||
* @param $appname Application 'name' with a matching $setup_info[$appname] array slice
|
||||
* @param $enabled optional, set to False to not enable this app
|
||||
* @param string $appname Application 'name' with a matching $setup_info[$appname] array slice
|
||||
* @param array $setup_info =null default use $GLOBALS['setup_info']
|
||||
*/
|
||||
function update_app($appname)
|
||||
function update_app($appname, array $setup_info=null)
|
||||
{
|
||||
$setup_info = $GLOBALS['setup_info'];
|
||||
if (!isset($setup_info)) $setup_info = $GLOBALS['setup_info'];
|
||||
|
||||
if(!$appname)
|
||||
{
|
||||
@ -631,16 +629,16 @@ class setup
|
||||
}
|
||||
|
||||
// Remove categories
|
||||
$this->db->delete(categories::TABLE, array('cat_appname'=>$appname),__LINE__,__FILE__);
|
||||
categories::invalidate_cache($appname);
|
||||
$this->db->delete(Api\Categories::TABLE, array('cat_appname'=>$appname),__LINE__,__FILE__);
|
||||
Api\Categories::invalidate_cache($appname);
|
||||
|
||||
// Remove config
|
||||
$this->db->delete(config::TABLE, array('config_app'=>$appname),__LINE__,__FILE__);
|
||||
$this->db->delete(Api\Config::TABLE, array('config_app'=>$appname),__LINE__,__FILE__);
|
||||
//echo 'DELETING application: ' . $appname;
|
||||
$this->db->delete($this->applications_table,array('app_name'=>$appname),__LINE__,__FILE__);
|
||||
|
||||
// Remove links to the app
|
||||
egw_link::unlink(0, $appname);
|
||||
Api\Link::unlink(0, $appname);
|
||||
|
||||
$this->clear_session_cache();
|
||||
}
|
||||
@ -731,32 +729,6 @@ class setup
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an application's hooks
|
||||
*
|
||||
* @param $appname Application 'name' with a matching $setup_info[$appname] array slice
|
||||
*/
|
||||
function update_hooks($appname)
|
||||
{
|
||||
$this->register_hooks($appname);
|
||||
}
|
||||
|
||||
/**
|
||||
* de-Register an application's hooks
|
||||
*
|
||||
* @param $appname Application 'name' with a matching $setup_info[$appname] array slice
|
||||
* @return boolean|int false on error or number of removed hooks
|
||||
*/
|
||||
function deregister_hooks($appname)
|
||||
{
|
||||
if(!$appname)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
Api\Hooks::read(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* call the hooks for a single application
|
||||
*
|
||||
@ -961,7 +933,7 @@ class setup
|
||||
}
|
||||
}
|
||||
try {
|
||||
$this->accounts = new accounts($config);
|
||||
$this->accounts = new Api\Accounts($config);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
echo "<p><b>".$e->getMessage()."</b></p>\n";
|
||||
|
@ -62,20 +62,19 @@ class setup_detection
|
||||
/* one of these tables exists. checking for post/pre beta version */
|
||||
if($GLOBALS['egw_setup']->applications_table != 'applications')
|
||||
{
|
||||
$GLOBALS['egw_setup']->db->select($GLOBALS['egw_setup']->applications_table,'*',false,__LINE__,__FILE__);
|
||||
while(@$GLOBALS['egw_setup']->db->next_record())
|
||||
foreach($GLOBALS['egw_setup']->db->select($GLOBALS['egw_setup']->applications_table,'*',false,__LINE__,__FILE__) as $row)
|
||||
{
|
||||
$app = $GLOBALS['egw_setup']->db->f('app_name');
|
||||
$app = $row['app_name'];
|
||||
if (!isset($setup_info[$app])) // app source no longer there
|
||||
{
|
||||
$setup_info[$app] = array(
|
||||
'name' => $app,
|
||||
'tables' => $GLOBALS['egw_setup']->db->f('app_tables'),
|
||||
'tables' => $row['app_tables'],
|
||||
'version' => 'deleted',
|
||||
);
|
||||
}
|
||||
$setup_info[$app]['currentver'] = $GLOBALS['egw_setup']->db->f('app_version');
|
||||
$setup_info[$app]['enabled'] = $GLOBALS['egw_setup']->db->f('app_enabled');
|
||||
$setup_info[$app]['currentver'] = $row['app_version'];
|
||||
$setup_info[$app]['enabled'] = $row['app_enabled'];
|
||||
}
|
||||
/* This is to catch old setup installs that did not have phpgwapi listed as an app */
|
||||
$tmp = @$setup_info['phpgwapi']['version']; /* save the file version */
|
||||
@ -98,14 +97,13 @@ class setup_detection
|
||||
}
|
||||
else
|
||||
{
|
||||
$GLOBALS['egw_setup']->db->query('select * from applications');
|
||||
while(@$GLOBALS['egw_setup']->db->next_record())
|
||||
foreach($GLOBALS['egw_setup']->db->query('select * from applications') as $row)
|
||||
{
|
||||
if($GLOBALS['egw_setup']->db->f('app_name') == 'admin')
|
||||
if($row['app_name'] == 'admin')
|
||||
{
|
||||
$setup_info['phpgwapi']['currentver'] = $GLOBALS['egw_setup']->db->f('app_version');
|
||||
$setup_info['phpgwapi']['currentver'] = $row['app_version'];
|
||||
}
|
||||
$setup_info[$GLOBALS['egw_setup']->db->f('app_name')]['currentver'] = $GLOBALS['egw_setup']->db->f('app_version');
|
||||
$setup_info[$row['app_name']]['currentver'] = $row['app_version'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -316,10 +314,24 @@ class setup_detection
|
||||
{
|
||||
$setup_info = $this->get_db_versions($setup_info);
|
||||
}
|
||||
//_debug_array($setup_info);
|
||||
if (isset($setup_info['phpgwapi']['currentver']))
|
||||
// first check new api installed and up to date
|
||||
if (isset($setup_info['api']['currentver']))
|
||||
{
|
||||
if(@$setup_info['phpgwapi']['currentver'] == @$setup_info['phpgwapi']['version'])
|
||||
if($setup_info['api']['currentver'] == $setup_info['api']['version'])
|
||||
{
|
||||
$GLOBALS['egw_info']['setup']['header_msg'] = 'Stage 1 (Tables Complete)';
|
||||
return 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
$GLOBALS['egw_info']['setup']['header_msg'] = 'Stage 1 (Tables need upgrading)';
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
// then check old phpgwapi
|
||||
elseif (isset($setup_info['phpgwapi']['currentver']))
|
||||
{
|
||||
if($setup_info['phpgwapi']['currentver'] == $setup_info['phpgwapi']['version'])
|
||||
{
|
||||
$GLOBALS['egw_info']['setup']['header_msg'] = 'Stage 1 (Tables Complete)';
|
||||
return 10;
|
||||
@ -340,6 +352,7 @@ class setup_detection
|
||||
return 3;
|
||||
}
|
||||
catch (Api\Db\Exception $e) {
|
||||
unset($e);
|
||||
$GLOBALS['egw_info']['setup']['header_msg'] = 'Stage 1 (Create Database)';
|
||||
return 1;
|
||||
}
|
||||
@ -359,10 +372,10 @@ class setup_detection
|
||||
}
|
||||
|
||||
try { // catch db errors
|
||||
$GLOBALS['egw_setup']->db->select($GLOBALS['egw_setup']->config_table,'config_name,config_value',array('config_app' => 'phpgwapi'),__LINE__,__FILE__);
|
||||
while($GLOBALS['egw_setup']->db->next_record())
|
||||
foreach($GLOBALS['egw_setup']->db->select($GLOBALS['egw_setup']->config_table,
|
||||
'config_name,config_value',array('config_app' => 'phpgwapi'),__LINE__,__FILE__) as $row)
|
||||
{
|
||||
$config[$GLOBALS['egw_setup']->db->f(0)] = $GLOBALS['egw_setup']->db->f(1);
|
||||
$config[$row['config_name']] = $row['config_value'];
|
||||
}
|
||||
}
|
||||
catch (Api\Db\Exception $e) {
|
||||
@ -432,46 +445,9 @@ class setup_detection
|
||||
return 10;
|
||||
}
|
||||
|
||||
function check_lang($check = True)
|
||||
{
|
||||
if($check && $GLOBALS['egw_info']['setup']['stage']['db'] != 10)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
if (!$check)
|
||||
{
|
||||
$GLOBALS['setup_info'] = $GLOBALS['egw_setup']->detection->get_db_versions($GLOBALS['setup_info']);
|
||||
}
|
||||
try {
|
||||
$GLOBALS['egw_setup']->db->query($q = "SELECT DISTINCT lang FROM {$GLOBALS['egw_setup']->lang_table}",__LINE__,__FILE__);
|
||||
}
|
||||
catch (Api\Db\Exception $e) {
|
||||
// ignore db error
|
||||
}
|
||||
if($e || $GLOBALS['egw_setup']->db->num_rows() == 0)
|
||||
{
|
||||
$GLOBALS['egw_info']['setup']['header_msg'] = 'Stage 3 (No languages installed)';
|
||||
return 1;
|
||||
}
|
||||
while(@$GLOBALS['egw_setup']->db->next_record())
|
||||
{
|
||||
$GLOBALS['egw_info']['setup']['installed_langs'][$GLOBALS['egw_setup']->db->f('lang')] = $GLOBALS['egw_setup']->db->f('lang');
|
||||
}
|
||||
foreach($GLOBALS['egw_info']['setup']['installed_langs'] as $value)
|
||||
{
|
||||
$sql = "SELECT lang_name FROM {$GLOBALS['egw_setup']->languages_table} WHERE lang_id = '".$value."'";
|
||||
$GLOBALS['egw_setup']->db->query($sql);
|
||||
if ($GLOBALS['egw_setup']->db->next_record())
|
||||
{
|
||||
$GLOBALS['egw_info']['setup']['installed_langs'][$value] = $GLOBALS['egw_setup']->db->f('lang_name');
|
||||
}
|
||||
}
|
||||
$GLOBALS['egw_info']['setup']['header_msg'] = 'Stage 3 (Completed)';
|
||||
return 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that all of an app's tables exist in the db
|
||||
*
|
||||
* @param $appname
|
||||
* @param $any optional, set to True to see if any of the apps tables are installed
|
||||
*/
|
||||
|
@ -55,27 +55,45 @@ class setup_process
|
||||
* @param array $setup_info array of application info from setup.inc.php files
|
||||
* @param string $type='new' defaults to new(install), could also be 'upgrade'
|
||||
* @param boolean $DEBUG=false print debugging info
|
||||
* @param boolean $force_en=false install english language files
|
||||
* @param boolean $force_en=false install english language files, not used anymore
|
||||
* @param string $system_charset=null charset to use
|
||||
* @param array $preset_config=array()
|
||||
*/
|
||||
function pass(array $setup_info,$method='new',$DEBUG=False,$force_en=False,$preset_config=array())
|
||||
{
|
||||
unset($force_en); // no longer used
|
||||
|
||||
if(!$method)
|
||||
{
|
||||
return False;
|
||||
}
|
||||
// Place api first
|
||||
|
||||
// update to 16.x with no api installed yet
|
||||
if ($method == 'upgrade' && !isset($setup_info['api']['currentver']))
|
||||
{
|
||||
// remove api dependency
|
||||
unset($setup_info['phpgwapi']['depends']['api']);
|
||||
|
||||
$pass['phpgwapi'] = $setup_info['phpgwapi'];
|
||||
$pass['emailadmin'] = $setup_info['emailadmin'];
|
||||
$pass['api'] = $setup_info['api'];
|
||||
|
||||
// mark api as already installed in version 14.3.907
|
||||
$setup_info['api']['version'] = $setup_info['api']['currentversion'] = '14.3.907';
|
||||
$GLOBALS['egw_setup']->register_app('api', 99, $setup_info);
|
||||
$setup_info['api']['version'] = $pass['api']['version'];
|
||||
}
|
||||
// new install or upgrade after 16.x api is installed
|
||||
else
|
||||
{
|
||||
$pass['api'] = $setup_info['api'];
|
||||
$pass['phpgwapi'] = $setup_info['phpgwapi'];
|
||||
}
|
||||
$pass['admin'] = $setup_info['admin'];
|
||||
$pass['preferences'] = $setup_info['preferences'];
|
||||
$pass['etemplate'] = $setup_info['etemplate']; // helps to minimize passes, as many apps depend on it
|
||||
@reset($setup_info);
|
||||
$setup_info = $GLOBALS['egw_setup']->detection->get_versions($setup_info);
|
||||
@reset($setup_info);
|
||||
|
||||
// setting api-target-version for general use
|
||||
$this->api_version_target = $setup_info['phpgwapi']['version'];
|
||||
$this->api_version_target = $setup_info['api']['version'];
|
||||
|
||||
$i = 1;
|
||||
$passed = array();
|
||||
@ -86,14 +104,13 @@ class setup_process
|
||||
{
|
||||
$passing = array();
|
||||
if($DEBUG) { echo '<br>process->pass(): #' . $i . ' for ' . $method . ' processing' . "\n"; }
|
||||
/* Check current versions and dependencies */
|
||||
$setup_info = $GLOBALS['egw_setup']->detection->get_db_versions($setup_info);
|
||||
$setup_info = $GLOBALS['egw_setup']->detection->compare_versions($setup_info,true);
|
||||
//_debug_array($setup_info);exit;
|
||||
$setup_info = $GLOBALS['egw_setup']->detection->check_depends($setup_info);
|
||||
//if($i==2) { _debug_array($passed);exit; }
|
||||
|
||||
/* stuff the rest of the apps, but only those with available upgrades */
|
||||
// Check current versions and dependencies
|
||||
$setup_info = $GLOBALS['egw_setup']->detection->check_depends(
|
||||
$GLOBALS['egw_setup']->detection->compare_versions(
|
||||
$GLOBALS['egw_setup']->detection->get_db_versions($setup_info), true));
|
||||
|
||||
// stuff the rest of the apps, but only those with available upgrades
|
||||
foreach($setup_info as $key => $value)
|
||||
{
|
||||
// check if app is either installed or supports the used database
|
||||
@ -103,7 +120,7 @@ class setup_process
|
||||
{
|
||||
continue; // app does not support this db-type, dont try installing it
|
||||
}
|
||||
if($value['name'] != 'phpgwapi' && $value['status'] == 'U')
|
||||
if(/*$value['name'] != 'phpgwapi' &&*/ $value['status'] == 'U')
|
||||
{
|
||||
if($passed[$value['name']]['status'] != 'F' && $passed[$value['name']]['status'] != 'C')
|
||||
{
|
||||
@ -116,9 +133,9 @@ class setup_process
|
||||
{
|
||||
case 'new':
|
||||
/* Create tables and insert new records for each app in this list */
|
||||
$passing = $this->current($pass,$DEBUG);
|
||||
$passing_c = $this->current($pass,$DEBUG);
|
||||
if (isset($pass['phpgwapi'])) $this->save_minimal_config($preset_config);
|
||||
$passing = $this->default_records($passing,$DEBUG);
|
||||
$passing = $this->default_records($passing_c,$DEBUG);
|
||||
break;
|
||||
case 'upgrade':
|
||||
/* Run upgrade scripts on each app in the list */
|
||||
@ -128,7 +145,6 @@ class setup_process
|
||||
default:
|
||||
/* What the heck are you doing? */
|
||||
return False;
|
||||
break;
|
||||
}
|
||||
|
||||
$pass = array();
|
||||
@ -170,17 +186,15 @@ class setup_process
|
||||
$passing_string = implode (':', $passing);
|
||||
}
|
||||
try {
|
||||
// flush instance cache
|
||||
egw_cache::flush(egw_cache::INSTANCE);
|
||||
// delete image-map, in case new apps get installed, or existing ones updated
|
||||
common::delete_image_map();
|
||||
// flush instance cache: also registers hooks and flushes image cache
|
||||
Api\Cache::flush(Api\Cache::INSTANCE);
|
||||
}
|
||||
catch(Exception $e) {
|
||||
unset($e);
|
||||
// ignore exception, as during a new install, there's no cache configured and therefore no need to unset
|
||||
}
|
||||
/* now return the list */
|
||||
return $setup_info = array_merge($setup_info,$passed);
|
||||
return array_merge($setup_info,$passed);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -272,6 +286,7 @@ class setup_process
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
unset($e);
|
||||
// do nothing if new DateTimeZone fails (eg. 'System/Localtime' returned), specially do NOT store it!
|
||||
error_log(__METHOD__."() NO valid 'date.timezone' set in your php.ini!");
|
||||
}
|
||||
@ -281,6 +296,7 @@ class setup_process
|
||||
|
||||
// use securest password hash by default
|
||||
require_once EGW_SERVER_ROOT.'/setup/inc/hook_config.inc.php'; // for sql_passwdhashes, to get securest available password hash
|
||||
$securest = null;
|
||||
sql_passwdhashes(array(), true, $securest);
|
||||
$current_config['sql_encryption_type'] = $current_config['ldap_encryption_type'] = $securest;
|
||||
|
||||
@ -310,8 +326,8 @@ class setup_process
|
||||
|
||||
// so the default_records use the current data
|
||||
$GLOBALS['egw_info']['server'] = array_merge((array)$GLOBALS['egw_info']['server'], $current_config);
|
||||
egw_cache::flush(); // flush whole instance cache
|
||||
config::init_static(); // flush internal cache of config class
|
||||
Api\Cache::flush(); // flush whole instance cache
|
||||
Api\Config::init_static(); // flush internal cache of config class
|
||||
$GLOBALS['egw_setup']->setup_account_object($current_config);
|
||||
}
|
||||
|
||||
@ -390,6 +406,7 @@ class setup_process
|
||||
if($appdata['tables'] && file_exists($appdir.'tables_current.inc.php'))
|
||||
{
|
||||
if($DEBUG) { echo '<br>process->current(): Including: ' . $appdir.'tables_current.inc.php'; }
|
||||
$phpgw_baseline = null;
|
||||
include ($appdir.'tables_current.inc.php');
|
||||
$ret = $this->post_process($phpgw_baseline,$DEBUG);
|
||||
if($ret)
|
||||
@ -397,12 +414,10 @@ class setup_process
|
||||
if($GLOBALS['egw_setup']->app_registered($appname))
|
||||
{
|
||||
$GLOBALS['egw_setup']->update_app($appname);
|
||||
$GLOBALS['egw_setup']->update_hooks($appname);
|
||||
}
|
||||
else
|
||||
{
|
||||
$GLOBALS['egw_setup']->register_app($appname);
|
||||
$GLOBALS['egw_setup']->register_hooks($appname);
|
||||
$GLOBALS['egw_setup']->set_default_preferences($appname);
|
||||
}
|
||||
// Update the array values for return below
|
||||
@ -430,12 +445,10 @@ class setup_process
|
||||
if($GLOBALS['egw_setup']->app_registered($appname))
|
||||
{
|
||||
$GLOBALS['egw_setup']->update_app($appname);
|
||||
$GLOBALS['egw_setup']->update_hooks($appname);
|
||||
}
|
||||
else
|
||||
{
|
||||
$GLOBALS['egw_setup']->register_app($appname,$enabled);
|
||||
$GLOBALS['egw_setup']->register_hooks($appname);
|
||||
$GLOBALS['egw_setup']->set_default_preferences($appname);
|
||||
}
|
||||
$appdata['status'] = 'C';
|
||||
@ -443,6 +456,9 @@ class setup_process
|
||||
if($DEBUG) { echo '<br>process->current(): Outgoing status: ' . $appname . ',status: '. $appdata['status']; }
|
||||
}
|
||||
|
||||
// update hooks
|
||||
Api\Hooks::read(true);
|
||||
|
||||
/* Done, return current status */
|
||||
return $setup_info;
|
||||
}
|
||||
@ -478,6 +494,8 @@ class setup_process
|
||||
}
|
||||
/* $appdata['status'] = 'C'; */
|
||||
}
|
||||
unset($appdata, $oProc);
|
||||
|
||||
// Clear categories cache in case app adds categories
|
||||
categories::invalidate_cache();
|
||||
|
||||
@ -515,6 +533,7 @@ class setup_process
|
||||
$GLOBALS['egw_setup']->oProc->m_odb->transaction_commit();
|
||||
}
|
||||
}
|
||||
unset($appdata);
|
||||
|
||||
/* Done, return current status */
|
||||
return ($setup_info);
|
||||
@ -543,6 +562,7 @@ class setup_process
|
||||
{
|
||||
echo '<br>process->baseline(): Including baseline tables for ' . $appname . "\n";
|
||||
}
|
||||
$phpgw_baseline = null;
|
||||
include ($appdir.'tables_baseline.inc.php');
|
||||
$GLOBALS['egw_setup']->oProc->GenerateScripts($phpgw_baseline, $DEBUG);
|
||||
$this->post_process($phpgw_baseline,$DEBUG);
|
||||
@ -559,6 +579,7 @@ class setup_process
|
||||
//$setup_info[$key]['status'] = 'C';
|
||||
}
|
||||
}
|
||||
unset($appdata);
|
||||
|
||||
/* Done, return current status */
|
||||
return ($setup_info);
|
||||
@ -589,8 +610,8 @@ class setup_process
|
||||
if (isset($appdata['autoinstall']) && ($appdata['autoinstall'] === true ||
|
||||
$appdata['autoinstall'] === $this->api_version_target))
|
||||
{
|
||||
$info = $this->current(array($appname => $appdata),$DEBUG);
|
||||
$info = $this->default_records($info,$DEBUG);
|
||||
$info_c = $this->current(array($appname => $appdata), $DEBUG);
|
||||
$info = $this->default_records($info_c, $DEBUG);
|
||||
$appdata = $info[$appname];
|
||||
continue;
|
||||
}
|
||||
@ -677,12 +698,10 @@ class setup_process
|
||||
if($GLOBALS['egw_setup']->app_registered($appname))
|
||||
{
|
||||
$GLOBALS['egw_setup']->update_app($appname);
|
||||
$GLOBALS['egw_setup']->update_hooks($appname);
|
||||
}
|
||||
else
|
||||
{
|
||||
$GLOBALS['egw_setup']->register_app($appname);
|
||||
$GLOBALS['egw_setup']->register_hooks($appname);
|
||||
}
|
||||
}
|
||||
|
||||
@ -703,6 +722,9 @@ class setup_process
|
||||
$appdate['status'] = $appstatus;
|
||||
}
|
||||
|
||||
// update hooks
|
||||
Api\Hooks::read(true);
|
||||
|
||||
/* Done, return current status */
|
||||
return $setup_info;
|
||||
}
|
||||
@ -737,7 +759,8 @@ class setup_process
|
||||
$this->init_process();
|
||||
}
|
||||
|
||||
$GLOBALS['egw_setup']->oProc->m_oTranslator->_GetColumns($GLOBALS['egw_setup']->oProc, $tablename, $sColumns, $sColumnName);
|
||||
$sColumns = null;
|
||||
$GLOBALS['egw_setup']->oProc->m_oTranslator->_GetColumns($GLOBALS['egw_setup']->oProc, $tablename, $sColumns);
|
||||
|
||||
while(list($key,$tbldata) = each($GLOBALS['egw_setup']->oProc->m_oTranslator->sCol))
|
||||
{
|
||||
|
@ -86,8 +86,9 @@ $setup_info = $GLOBALS['egw_setup']->detection->get_versions();
|
||||
$GLOBALS['egw_info']['setup']['stage']['db'] = $GLOBALS['egw_setup']->detection->check_db($setup_info);
|
||||
if ($GLOBALS['egw_info']['setup']['stage']['db'] != 1)
|
||||
{
|
||||
$setup_info = $GLOBALS['egw_setup']->detection->get_versions();
|
||||
$setup_info = $GLOBALS['egw_setup']->detection->get_db_versions($setup_info);
|
||||
$setup_info = $GLOBALS['egw_setup']->detection->get_db_versions(
|
||||
$GLOBALS['egw_setup']->detection->get_versions());
|
||||
|
||||
$GLOBALS['egw_info']['setup']['stage']['db'] = $GLOBALS['egw_setup']->detection->check_db($setup_info);
|
||||
if($GLOBALS['DEBUG'])
|
||||
{
|
||||
@ -101,7 +102,7 @@ if ($GLOBALS['DEBUG']) { echo 'Stage: ' . $GLOBALS['egw_info']['setup']['stage']
|
||||
//$action = 'Upgrade';
|
||||
// end DEBUG code
|
||||
|
||||
switch(@get_var('action',Array('POST')))
|
||||
switch($_POST['action'])
|
||||
{
|
||||
case 'Uninstall all applications':
|
||||
$subtitle = lang('Deleting Tables');
|
||||
@ -254,8 +255,9 @@ switch($GLOBALS['egw_info']['setup']['stage']['db'])
|
||||
break;
|
||||
case 4:
|
||||
$setup_tpl->set_var('hidden_vars', html::input_hidden('csrf_token', Api\Csrf::token(__FILE__)));
|
||||
$setup_tpl->set_var('oldver',lang('You appear to be running version %1 of eGroupWare',$setup_info['phpgwapi']['currentver']));
|
||||
$setup_tpl->set_var('automatic',lang('We will automatically update your tables/records to %1',$setup_info['phpgwapi']['version']));
|
||||
$setup_tpl->set_var('oldver',lang('You appear to be running version %1 of eGroupWare',
|
||||
isset($setup_info['api']['currentver']) ? $setup_info['api']['currentver'] : $setup_info['phpgwapi']['currentver']));
|
||||
$setup_tpl->set_var('automatic',lang('We will automatically update your tables/records to %1',$setup_info['api']['version']));
|
||||
$setup_tpl->set_var('backupwarn',lang('but we <u>highly recommend backing up</u> your tables in case the script causes damage to your data.<br /><strong>These automated scripts can easily destroy your data.</strong>'));
|
||||
$setup_tpl->set_var('lang_backup',lang('create a backup before upgrading the DB'));
|
||||
$setup_tpl->set_var('lang_debug',lang('enable for extra debug-messages'));
|
||||
@ -301,14 +303,14 @@ switch($GLOBALS['egw_info']['setup']['stage']['db'])
|
||||
break;
|
||||
case 'drop':
|
||||
Api\Csrf::validate($_POST['csrf_token'], __FILE__);
|
||||
$setup_info = $GLOBALS['egw_setup']->detection->get_versions($setup_info);
|
||||
$setup_info = $GLOBALS['egw_setup']->process->droptables($setup_info);
|
||||
$setup_info = $GLOBALS['egw_setup']->process->droptables(
|
||||
$GLOBALS['egw_setup']->detection->get_versions($setup_info));
|
||||
break;
|
||||
case 'new':
|
||||
// use uploaded backup, instead installing from scratch
|
||||
if ($_POST['upload'])
|
||||
{
|
||||
$db_backup = new db_backup();
|
||||
$db_backup = new Api\Db\Backup();
|
||||
if (is_array($_FILES['uploaded']) && !$_FILES['uploaded']['error'] &&
|
||||
is_uploaded_file($_FILES['uploaded']['tmp_name']))
|
||||
{
|
||||
@ -336,14 +338,14 @@ switch($GLOBALS['egw_info']['setup']['stage']['db'])
|
||||
}
|
||||
else
|
||||
{
|
||||
$setup_info = $GLOBALS['egw_setup']->detection->upgrade_exclude($setup_info);
|
||||
$s_info = $GLOBALS['egw_setup']->detection->upgrade_exclude($setup_info);
|
||||
// Set the DB's client charset if a system-charset is set
|
||||
if (preg_match('/^[a-z0-9-]+$/i', $_REQUEST['system_charset']))
|
||||
{
|
||||
$GLOBALS['egw_setup']->system_charset = $_REQUEST['system_charset'];
|
||||
$GLOBALS['egw_setup']->db->Link_ID->SetCharSet($_REQUEST['system_charset']);
|
||||
}
|
||||
$setup_info = $GLOBALS['egw_setup']->process->pass($setup_info,'new',$_REQUEST['debug'],True);
|
||||
$setup_info = $GLOBALS['egw_setup']->process->pass($s_info,'new',$_REQUEST['debug'],True);
|
||||
$GLOBALS['egw_info']['setup']['currentver']['phpgwapi'] = 'oldversion';
|
||||
}
|
||||
break;
|
||||
@ -468,54 +470,7 @@ switch($GLOBALS['egw_info']['setup']['stage']['config'])
|
||||
$setup_tpl->set_var('admin_table_data',lang('Not ready for this stage yet'));
|
||||
break;
|
||||
}
|
||||
/*
|
||||
// Lang Section
|
||||
$setup_tpl->set_var('lang_step_text',lang('Step %1 - Language Management', ++$num));
|
||||
$GLOBALS['egw_info']['setup']['stage']['lang'] = $GLOBALS['egw_setup']->detection->check_lang();
|
||||
|
||||
// begin DEBUG code
|
||||
//$GLOBALS['egw_info']['setup']['stage']['lang'] = 0;
|
||||
// end DEBUG code
|
||||
|
||||
switch($GLOBALS['egw_info']['setup']['stage']['lang'])
|
||||
{
|
||||
case 1:
|
||||
$setup_tpl->set_var('lang_status_img',$incomplete);
|
||||
$setup_tpl->set_var('lang_status_alt','not completed');
|
||||
$btn_install_lang = $GLOBALS['egw_setup']->html->make_frm_btn_simple(
|
||||
lang('You do not have any languages installed. Please install one now <br />'),
|
||||
'post','lang.php',
|
||||
'submit',lang('Install Language'),
|
||||
'');
|
||||
$setup_tpl->set_var('lang_table_data',$btn_install_lang);
|
||||
break;
|
||||
case 10:
|
||||
$langs_list = array();
|
||||
$languages = setup_translation::get_supported_langs();
|
||||
foreach ($GLOBALS['egw_info']['setup']['installed_langs'] as $key => $value)
|
||||
{
|
||||
$langs_list[] = isset($languages[$key]) ? $languages[$key]['descr'] : $value;
|
||||
}
|
||||
$setup_tpl->set_var('lang_status_img',$completed);
|
||||
$setup_tpl->set_var('lang_status_alt','completed');
|
||||
$btn_manage_lang = $GLOBALS['egw_setup']->html->make_frm_btn_simple(
|
||||
lang('This stage is completed<br />') . lang('Currently installed languages: %1 <br />',implode(', ',$langs_list)),
|
||||
'post','lang.php',
|
||||
'submit',lang('Manage Languages'),
|
||||
'');
|
||||
// show system-charset and offer conversation
|
||||
$btn_manage_lang .= lang('Current system-charset is %1.',$GLOBALS['egw_setup']->system_charset ?
|
||||
"'<b>".$GLOBALS['egw_setup']->system_charset."</b>'" : lang('not set'))."\n";
|
||||
$btn_manage_lang .= lang('To change the charset: back up your database, deinstall all applications and re-install the backup with "convert backup to charset selected" checked.');
|
||||
$setup_tpl->set_var('lang_table_data',$btn_manage_lang);
|
||||
break;
|
||||
default:
|
||||
$setup_tpl->set_var('lang_status_img',$incomplete);
|
||||
$setup_tpl->set_var('lang_status_alt',lang('not completed'));
|
||||
$setup_tpl->set_var('lang_table_data',lang('Not ready for this stage yet'));
|
||||
break;
|
||||
}
|
||||
*/
|
||||
$setup_tpl->set_var('apps_step_text',lang('Step %1 - Advanced Application Management', ++$num));
|
||||
// $GLOBALS['egw_info']['setup']['stage']['apps'] = $GLOBALS['egw_setup']->check_apps();
|
||||
switch($GLOBALS['egw_info']['setup']['stage']['db'])
|
||||
@ -534,7 +489,7 @@ switch($GLOBALS['egw_info']['setup']['stage']['db'])
|
||||
}
|
||||
}
|
||||
// warn if essential apps are not installed
|
||||
foreach(array('phpgwapi','etemplate','home','admin','preferences','emailadmin') as $app)
|
||||
foreach(array('api','phpgwapi','etemplate','home','admin','preferences') as $app)
|
||||
{
|
||||
if (!isset($setup_info[$app]) || empty($setup_info[$app]['currentver']))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user