summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>2013-09-18 13:17:47 (GMT)
committerJeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>2013-09-18 13:17:47 (GMT)
commita4bbb85b2e377d0fe1bb76f127dc7d5f58d964a3 (patch)
tree612d13b095504f69080330c82f86c73f3b49d80d
parent1dad011fd3005577481b359426cebe5fb41743fa (diff)
parent5f76c88df172452a1947819b1a1ad872543649b6 (diff)
downloadpykolab-a4bbb85b2e377d0fe1bb76f127dc7d5f58d964a3.tar.gz
Merge branch 'master' of ssh://git.kolabsys.com/git/pykolab
-rw-r--r--.gitignore3
-rwxr-xr-xbin/kolab_parse_telemetry.py2
-rwxr-xr-xbin/kolab_smtp_access_policy.py57
-rw-r--r--bin/rebuild.sh.in6
-rwxr-xr-xconf.py2
-rw-r--r--conf/kolab.conf22
-rw-r--r--configure.ac4
-rw-r--r--cyruslib.py157
-rwxr-xr-xkolab.py2
-rwxr-xr-xkolabd.py2
-rw-r--r--kolabd/__init__.py2
-rw-r--r--kolabd/process.py12
-rw-r--r--pykolab.spec.in11
-rw-r--r--pykolab/Makefile.am6
-rw-r--r--pykolab/__init__.py2
-rw-r--r--pykolab/auth/__init__.py25
-rw-r--r--pykolab/auth/ldap/__init__.py304
-rw-r--r--pykolab/auth/ldap/auth_cache.py138
-rw-r--r--pykolab/auth/ldap/cache.py26
-rw-r--r--pykolab/auth/ldap/syncrepl.py27
-rw-r--r--pykolab/base.py7
-rw-r--r--pykolab/cli/__init__.py2
-rw-r--r--pykolab/cli/cmd_acl_cleanup.py2
-rw-r--r--pykolab/cli/cmd_add_domain.py35
-rw-r--r--pykolab/cli/cmd_add_user.py38
-rw-r--r--pykolab/cli/cmd_add_user_subscription.py2
-rw-r--r--pykolab/cli/cmd_count_domain_mailboxes.py68
-rw-r--r--pykolab/cli/cmd_create_mailbox.py6
-rw-r--r--pykolab/cli/cmd_delete_domain.py58
-rw-r--r--pykolab/cli/cmd_delete_mailbox.py6
-rw-r--r--pykolab/cli/cmd_delete_mailbox_acl.py8
-rw-r--r--pykolab/cli/cmd_delete_message.py2
-rw-r--r--pykolab/cli/cmd_export_mailbox.py2
-rw-r--r--pykolab/cli/cmd_find_domain.py58
-rw-r--r--pykolab/cli/cmd_list_deleted_mailboxes.py44
-rw-r--r--pykolab/cli/cmd_list_domain_mailboxes.py83
-rw-r--r--pykolab/cli/cmd_list_domains.py2
-rw-r--r--pykolab/cli/cmd_list_mailbox_acls.py4
-rw-r--r--pykolab/cli/cmd_list_mailbox_metadata.py4
-rw-r--r--pykolab/cli/cmd_list_mailboxes.py23
-rw-r--r--pykolab/cli/cmd_list_messages.py9
-rw-r--r--pykolab/cli/cmd_list_quota.py29
-rw-r--r--pykolab/cli/cmd_list_user_subscriptions.py19
-rw-r--r--pykolab/cli/cmd_mailbox_cleanup.py2
-rw-r--r--pykolab/cli/cmd_remove_mailaddress.py2
-rw-r--r--pykolab/cli/cmd_remove_user_subscription.py2
-rw-r--r--pykolab/cli/cmd_rename_mailbox.py2
-rw-r--r--pykolab/cli/cmd_server_info.py58
-rw-r--r--pykolab/cli/cmd_set_language.py2
-rw-r--r--pykolab/cli/cmd_set_mail.py2
-rw-r--r--pykolab/cli/cmd_set_mailbox_acl.py4
-rw-r--r--pykolab/cli/cmd_set_mailbox_metadata.py2
-rw-r--r--pykolab/cli/cmd_sync.py2
-rw-r--r--pykolab/cli/cmd_sync_mailhost_attrs.py133
-rw-r--r--pykolab/cli/cmd_transfer_mailbox.py24
-rw-r--r--pykolab/cli/cmd_undelete_mailbox.py4
-rw-r--r--pykolab/cli/cmd_user_info.py48
-rw-r--r--pykolab/cli/commands.py5
-rw-r--r--pykolab/cli/sieve/cmd_list.py2
-rw-r--r--pykolab/cli/sieve/cmd_put.py2
-rw-r--r--pykolab/cli/sieve/cmd_refresh.py2
-rw-r--r--pykolab/cli/sieve/cmd_test.py2
-rw-r--r--pykolab/cli/telemetry/cmd_examine_command_issue.py2
-rw-r--r--pykolab/cli/telemetry/cmd_examine_session.py2
-rw-r--r--pykolab/cli/telemetry/cmd_expire_sessions.py2
-rw-r--r--pykolab/cli/telemetry/cmd_list_sessions.py2
-rw-r--r--pykolab/cli/wap/__init__.py0
-rw-r--r--pykolab/cli/wap/cmd_system_capabilities.py50
-rw-r--r--pykolab/cli/wap/cmd_user_types_list.py40
-rw-r--r--pykolab/conf/__init__.py12
-rw-r--r--pykolab/conf/defaults.py2
-rw-r--r--pykolab/conf/entitlement.py2
-rw-r--r--pykolab/errors.py2
-rw-r--r--pykolab/imap/__init__.py77
-rw-r--r--pykolab/imap/cyrus.py12
-rw-r--r--pykolab/imap_utf7.py91
-rw-r--r--pykolab/logger.py8
-rw-r--r--pykolab/plugins/__init__.py2
-rw-r--r--pykolab/plugins/defaultfolders/__init__.py2
-rw-r--r--pykolab/plugins/dynamicquota/__init__.py2
-rw-r--r--pykolab/plugins/recipientpolicy/__init__.py26
-rw-r--r--pykolab/plugins/sievemgmt/__init__.py2
-rw-r--r--pykolab/setup/__init__.py2
-rw-r--r--pykolab/setup/components.py2
-rw-r--r--pykolab/setup/setup_freebusy.py101
-rw-r--r--pykolab/setup/setup_imap.py2
-rw-r--r--pykolab/setup/setup_kolabd.py2
-rw-r--r--pykolab/setup/setup_ldap.py109
-rw-r--r--pykolab/setup/setup_mta.py67
-rw-r--r--pykolab/setup/setup_mysql.py2
-rw-r--r--pykolab/setup/setup_php.py2
-rw-r--r--pykolab/setup/setup_roundcube.py6
-rw-r--r--pykolab/setup/setup_syncroton.py2
-rw-r--r--pykolab/setup/setup_zpush.py109
-rw-r--r--pykolab/telemetry.py2
-rw-r--r--pykolab/translate.py2
-rw-r--r--pykolab/translit.py2
-rw-r--r--pykolab/utils.py69
-rw-r--r--pykolab/wap_client/__init__.py184
-rw-r--r--pykolab/xml/event.py77
-rwxr-xr-xsaslauthd.py2
-rw-r--r--saslauthd/__init__.py12
-rwxr-xr-xsetup-kolab.py2
-rw-r--r--share/Makefile.am25
-rw-r--r--share/templates/cyrus.conf.tpl8
-rw-r--r--share/templates/freebusy/config.php.tpl212
-rw-r--r--share/templates/header_checks.inbound6
-rw-r--r--share/templates/header_checks.internal1
-rw-r--r--share/templates/header_checks.submission5
-rw-r--r--share/templates/imapd.conf.tpl3
-rw-r--r--share/templates/master.cf.tpl202
-rw-r--r--share/templates/roundcubemail/acl.inc.php.tpl12
-rw-r--r--share/templates/roundcubemail/calendar.inc.php.tpl20
-rw-r--r--share/templates/roundcubemail/config.inc.php.tpl208
-rw-r--r--share/templates/roundcubemail/db.inc.php.tpl29
-rw-r--r--share/templates/roundcubemail/kolab.inc.php.tpl12
-rw-r--r--share/templates/roundcubemail/kolab_auth.inc.php.tpl28
-rw-r--r--share/templates/roundcubemail/kolab_files.inc.php.tpl15
-rw-r--r--share/templates/roundcubemail/kolab_folders.inc.php.tpl28
-rw-r--r--share/templates/roundcubemail/main.inc.php.tpl265
-rw-r--r--share/templates/roundcubemail/managesieve.inc.php.tpl26
-rw-r--r--share/templates/roundcubemail/owncloud.inc.php.tpl6
-rw-r--r--share/templates/roundcubemail/password.inc.php.tpl52
-rw-r--r--share/templates/roundcubemail/recipient_to_contact.inc.php.tpl4
-rw-r--r--share/templates/roundcubemail/terms.inc.php.tpl12
-rw-r--r--share/templates/zpush/config.php.tpl106
-rwxr-xr-xtest-wallace.py2
-rw-r--r--tests/functional/purge_users.py2
-rw-r--r--tests/functional/test_wallace/test_001_user_add.py2
-rw-r--r--tests/functional/test_wap_client/test_001_connect.py6
-rw-r--r--tests/functional/test_wap_client/test_006_form_value_select_options.py31
-rw-r--r--tests/functional/test_wap_client/test_007_policy_uid.py176
-rw-r--r--tests/functional/user_add.py7
-rwxr-xr-xucs/kolab_sieve.py2
-rwxr-xr-xucs/listener.py51
-rwxr-xr-xwallace.py2
-rw-r--r--wallace/__init__.py17
-rw-r--r--wallace/module_footer.py2
-rw-r--r--wallace/module_optout.py2
-rw-r--r--wallace/module_resources.py11
-rw-r--r--wallace/modules.py21
141 files changed, 2862 insertions, 1474 deletions
diff --git a/.gitignore b/.gitignore
index 7c1de8b..e8d60b3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,11 +9,13 @@ Makefile.in
*.rej
*.spec
*.tar.gz
+*.tar.gz.gpg
aclocal.m4
autom4te.cache/
bin/rebuild.sh
bin/test*
ChangeLog
+conf/*-*.conf
config.log
config.status
configure
@@ -23,3 +25,4 @@ po/POTFILES
pykolab/constants.py
pykolab-[0-9]*.*/
src/
+test-*
diff --git a/bin/kolab_parse_telemetry.py b/bin/kolab_parse_telemetry.py
index ea4da25..b4fb6d0 100755
--- a/bin/kolab_parse_telemetry.py
+++ b/bin/kolab_parse_telemetry.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/bin/kolab_smtp_access_policy.py b/bin/kolab_smtp_access_policy.py
index 0320973..c13bfaf 100755
--- a/bin/kolab_smtp_access_policy.py
+++ b/bin/kolab_smtp_access_policy.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -62,7 +62,7 @@ log = pykolab.getLogger('pykolab.smtp_access_policy')
# TODO: Removing the stdout handler would mean one can no longer test by
# means of manual execution in debug mode.
-log.remove_stdout_handler()
+#log.remove_stdout_handler()
conf = pykolab.getConf()
@@ -410,23 +410,53 @@ class PolicyRequest(object):
John.Doe@example.org (mail) for example could be sending with
envelope sender jdoe@example.org (mailAlternateAddress, alias).
"""
- search_attrs = conf.get_list(self.sasl_domain, 'mail_attributes')
+
+ search_attrs = conf.get_list(self.sasl_domain, 'address_search_attrs')
+
+ if search_attrs == None or \
+ (isinstance(search_attrs, list) and len(search_attrs) == 0):
+
+ search_attrs = conf.get_list(self.sasl_domain, 'mail_attributes')
if search_attrs == None or \
(isinstance(search_attrs, list) and len(search_attrs) == 0):
search_attrs = conf.get_list(
+ 'kolab_smtp_access_policy',
+ 'address_search_attrs'
+ )
+
+ if search_attrs == None or \
+ (isinstance(search_attrs, list) and len(search_attrs) == 0):
+
+
+ search_attrs = conf.get_list(
conf.get('kolab', 'auth_mechanism'),
'mail_attributes'
)
+ want_attrs = []
+
+ for search_attr in search_attrs:
+ if not self.sasl_user.has_key(search_attr):
+ want_attrs.append(search_attr)
+
+ if len(want_attrs) > 0:
+ self.sasl_user.update(
+ self.auth.get_user_attributes(
+ self.sasl_domain,
+ self.sasl_user,
+ want_attrs
+ )
+ )
+
# Catch a user using one of its own alias addresses.
for search_attr in search_attrs:
if self.sasl_user.has_key(search_attr):
if isinstance(self.sasl_user[search_attr], list):
- if self.sender in self.sasl_user[search_attr]:
+ if self.sender.lower() in [x.lower() for x in self.sasl_user[search_attr]]:
return True
- elif self.sasl_user[search_attr] == self.sender:
+ elif self.sasl_user[search_attr].lower() == self.sender.lower():
return True
return False
@@ -491,7 +521,7 @@ class PolicyRequest(object):
)
reject(
- _("Could not find envelope sender user %s") % (
+ _("Could not find envelope sender user %s (511)") % (
self.sasl_username
)
)
@@ -953,7 +983,9 @@ class PolicyRequest(object):
self.verify_authenticity()
self.sasl_user_uses_alias = self.verify_alias()
+
if not self.sasl_user_uses_alias:
+ log.debug(_("Sender is not using an alias"), level=8)
self.sasl_user_is_delegate = self.verify_delegate()
# If the authenticated user is using delegate functionality, apply the
@@ -1230,7 +1262,10 @@ def hold(message, policy_request=None):
def permit(message, policy_request=None):
log.info(_("Returning action PERMIT: %s") % (message))
- print "action=PERMIT\n\n"
+ if hasattr(policy_request, 'sasl_username'):
+ print "action=PREPEND Sender: %s\naction=PERMIT\n\n" % (policy_request.sasl_username)
+ else:
+ print "action=PERMIT\n\n"
sys.exit(0)
def reject(message, policy_request=None):
@@ -1267,13 +1302,13 @@ def normalize_address(email_address):
# Take the first part split by recipient delimiter and the last part
# split by '@'.
return "%s@%s" % (
- email_address.split("+")[0],
+ email_address.split("+")[0].lower(),
# TODO: Under some conditions, the recipient may not be fully
# qualified. We'll cross that bridge when we get there, though.
- email_address.split('@')[1]
+ email_address.split('@')[1].lower()
)
else:
- return email_address
+ return email_address.lower()
def read_request_input():
"""
@@ -1421,4 +1456,4 @@ if __name__ == "__main__":
elif not recipient_allowed:
reject(_("Recipient access denied"))
else:
- permit(_("No objections"))
+ permit(_("No objections"), policy_requests[instance])
diff --git a/bin/rebuild.sh.in b/bin/rebuild.sh.in
index 4e2510d..2fda4c0 100644
--- a/bin/rebuild.sh.in
+++ b/bin/rebuild.sh.in
@@ -13,9 +13,13 @@ declare -a product_series
declare -a answers
declare -a tasks
-dists[${#dists[@]}]='f16'; dist_tags[${#dist_tags[@]}]='fc16'; product_series[${#product_series[@]}]="3.0"
+#dists[${#dists[@]}]='f16'; dist_tags[${#dist_tags[@]}]='fc16'; product_series[${#product_series[@]}]="3.0"
dists[${#dists[@]}]='f17'; dist_tags[${#dist_tags[@]}]='fc17'; product_series[${#product_series[@]}]="3.0"
+dists[${#dists[@]}]='f17'; dist_tags[${#dist_tags[@]}]='fc17'; product_series[${#product_series[@]}]="3.1"
+dists[${#dists[@]}]='f18'; dist_tags[${#dist_tags[@]}]='fc18'; product_series[${#product_series[@]}]="3.0"
+dists[${#dists[@]}]='f18'; dist_tags[${#dist_tags[@]}]='fc18'; product_series[${#product_series[@]}]="3.1"
dists[${#dists[@]}]='el6'; dist_tags[${#dist_tags[@]}]='el6'; product_series[${#product_series[@]}]="3.0"
+dists[${#dists[@]}]='el6'; dist_tags[${#dist_tags[@]}]='el6'; product_series[${#product_series[@]}]="3.1"
autoreconf -v && ./configure && make dist || exit 1
diff --git a/conf.py b/conf.py
index c0804d8..c19db63 100755
--- a/conf.py
+++ b/conf.py
@@ -1,7 +1,7 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/conf/kolab.conf b/conf/kolab.conf
index e0f64c3..f98dca9 100644
--- a/conf/kolab.conf
+++ b/conf/kolab.conf
@@ -17,6 +17,11 @@ imap_backend = cyrus-imap
; The default locale for this Kolab Groupware installation
default_locale = en_US
+; Synchronization interval - describes the number of seconds to wait in
+; between non-persistent synchronization attempts. Relevant only for
+; deployments that lack persistent search and syncrepl ldap controls.
+sync_interval = 300
+
[ldap]
; The URI to LDAP
ldap_uri = ldap://localhost:389
@@ -117,6 +122,8 @@ quota_attribute = mailquota
;
; For OpenLDAP, use 'entrydn' - the 'entryUUID' can regrettably not be searched
; with.
+;
+; For Active Directory, use 'objectsid'.
unique_attribute = nsuniqueid
; Attribute names that hold valid, internal recipient addresses. Note the use
@@ -247,11 +254,6 @@ autocreate_folders = {
'/shared/vendor/kolab/folder-type': "configuration.default",
},
},
- 'Drafts': {
- 'annotations': {
- '/private/vendor/kolab/folder-type': "mail.drafts",
- },
- },
'Contacts': {
'annotations': {
'/private/vendor/kolab/folder-type': "contact.default",
@@ -263,6 +265,16 @@ autocreate_folders = {
'/shared/vendor/kolab/folder-type': "contact",
},
},
+ 'Drafts': {
+ 'annotations': {
+ '/private/vendor/kolab/folder-type': "mail.drafts",
+ },
+ },
+ 'Files': {
+ 'annotations': {
+ '/private/vendor/kolab/folder-type': "file.default",
+ },
+ },
'Journal': {
'annotations': {
'/private/vendor/kolab/folder-type': "journal.default",
diff --git a/configure.ac b/configure.ac
index abf6bbd..79800f8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
-AC_INIT([pykolab], 0.6)
-AC_SUBST([RELEASE], 0.1)
+AC_INIT([pykolab], 0.6.5)
+AC_SUBST([RELEASE], 1)
AC_CONFIG_SRCDIR(pykolab/constants.py.in)
diff --git a/cyruslib.py b/cyruslib.py
index 75b636f..85d7e63 100644
--- a/cyruslib.py
+++ b/cyruslib.py
@@ -642,49 +642,128 @@ class CYRUS:
"""Get Annotation"""
self.__prepare('GETANNOTATION')
res, data = self.__docommand('getannotation', self.decode(mailbox), pattern)
+
if (len(data) == 1) and data[0] is None:
self.__verbose( '[GETANNOTATION %s] No results' % (mailbox) )
return {}
+
ann = {}
- for annotation in data:
- if isinstance(annotation, tuple):
- annotation = annotation[0]
- self.__verbose( '[GETANNOTATION] RAW %r (length %d)' % (annotation,len(annotation)))
- annotation = annotation.split('"')
- self.__verbose( '[GETANNOTATION] SPLIT %r (length %d)' % (annotation,len(annotation)))
- if not len(annotation) in [ 9, 17, 21, 37 ]:
- self.__verbose( '[GETANNOTATION] Invalid annotation entry' )
- continue
- mbx = self.encode(annotation[1])
- _key = annotation[3]
-
- if annotation[5] == "value.shared":
- key = "/shared%s" % (_key)
- elif annotation[5] == "value.priv":
- key = "/private%s" % (_key)
-
- value = annotation[7]
-
- self.__verbose( '[GETANNOTATION %s] %s: %s' % (mbx, key, value) )
- if not ann.has_key(mbx):
- ann[mbx] = {}
- if not ann[mbx].has_key(key):
- ann[mbx][key] = value
-
- if len(annotation) > 21:
- # There's another one hidden in here.
- if annotation[21] == "value.shared":
- key = "/shared%s" % (_key)
- elif annotation[21] == "value.priv":
- key = "/private%s" % (_key)
-
- value = annotation[23]
-
- self.__verbose( '[GETANNOTATION %s] %s: %s' % (mbx, key, value) )
- if not ann.has_key(mbx):
- ann[mbx] = {}
- if not ann[mbx].has_key(key):
- ann[mbx][key] = value
+ annotations = []
+ empty_values = [ "NIL", '" "', None, '', ' ' ]
+
+ concat_items = []
+ for item in data:
+ if isinstance(item, tuple):
+ item = ' '.join([str(x) for x in item])
+
+ if len(concat_items) > 0:
+ concat_items.append(item)
+
+ if ''.join(concat_items).count('(') == ''.join(concat_items).count(')'):
+ annotations.append(''.join(concat_items))
+ concat_items = []
+ continue
+ else:
+
+ if item.count('(') == item.count(')'):
+ annotations.append(item)
+ continue
+ else:
+ concat_items.append(item)
+ continue
+
+ for annotation in annotations:
+ annotation = annotation.strip()
+
+ if not annotation[0] == '"':
+ folder = annotation.split('"')[0].replace('"','').strip()
+ key = annotation.split('"')[1].replace('"','').replace("'","").strip()
+ _annot = annotation.split('(')[1].split(')')[0].strip()
+ else:
+ folder = annotation.split('"')[1].replace('"','').strip()
+ key = annotation.split('"')[3].replace('"','').replace("'","").strip()
+ _annot = annotation.split('(')[1].split(')')[0].strip()
+
+ if not ann.has_key(folder):
+ ann[folder] = {}
+
+ try:
+ value_priv = _annot[(_annot.index('"value.priv"')+len('"value.priv"')):_annot.index('"size.priv"')].strip()
+ except ValueError, errmsg:
+ value_priv = None
+
+ try:
+ size_priv = _annot[(_annot.index('"size.priv"')+len('"size.priv"')):].strip().split('"')[1].strip()
+ try:
+ value_priv = value_priv[value_priv.index('{%s}' % (size_priv))+len('{%s}' % (size_priv)):].strip()
+ except Exception, errmsg:
+ pass
+ except Exception, errmsg:
+ pass
+
+ if value_priv in empty_values:
+ value_priv = None
+ else:
+ try:
+ value_priv = value_priv[:value_priv.index('"content-type.priv"')].strip()
+ except:
+ pass
+
+ try:
+ value_priv = value_priv[:value_priv.index('"modifiedsince.priv"')].strip()
+ except:
+ pass
+
+ if value_priv.startswith('"'):
+ value_priv = value_priv[1:]
+
+ if value_priv.endswith('"'):
+ value_priv = value_priv[:-1]
+
+ if value_priv in empty_values:
+ value_priv = None
+
+ try:
+ value_shared = _annot[(_annot.index('"value.shared"')+len('"value.shared"')):_annot.index('"size.shared"')].strip()
+ except ValueError, errmsg:
+ value_shared = None
+
+ try:
+ size_shared = _annot[(_annot.index('"size.shared"')+len('"size.shared"')):].strip().split('"')[1].strip()
+ try:
+ value_shared = value_shared[value_shared.index('{%s}' % (size_shared))+len('{%s}' % (size_shared)):].strip()
+ except Exception, errmsg:
+ pass
+ except Exception, errmsg:
+ pass
+
+ if value_shared in empty_values:
+ value_shared = None
+ else:
+ try:
+ value_shared = value_shared[:value_shared.index('"content-type.shared"')].strip()
+ except:
+ pass
+
+ try:
+ value_shared = value_shared[:value_shared.index('"modifiedsince.shared"')].strip()
+ except:
+ pass
+
+ if value_shared.startswith('"'):
+ value_shared = value_shared[1:]
+
+ if value_shared.endswith('"'):
+ value_shared = value_shared[:-1]
+
+ if value_shared in empty_values:
+ value_shared = None
+
+ if not value_priv == None:
+ ann[folder]['/private' + key] = value_priv
+
+ if not value_shared == None:
+ ann[folder]['/shared' + key] = value_shared
return ann
diff --git a/kolab.py b/kolab.py
index fd2c84d..5b4d771 100755
--- a/kolab.py
+++ b/kolab.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/kolabd.py b/kolabd.py
index a4acb4a..ca10654 100755
--- a/kolabd.py
+++ b/kolabd.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/kolabd/__init__.py b/kolabd/__init__.py
index b345b8d..5624280 100644
--- a/kolabd/__init__.py
+++ b/kolabd/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/kolabd/process.py b/kolabd/process.py
index 70b535a..ffe33f5 100644
--- a/kolabd/process.py
+++ b/kolabd/process.py
@@ -1,4 +1,4 @@
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -30,6 +30,7 @@ conf = pykolab.getConf()
class KolabdProcess(multiprocessing.Process):
def __init__(self, domain):
self.domain = domain
+ log.debug(_("Process created for domain %s") % (domain), level=8)
multiprocessing.Process.__init__(
self,
target=self.synchronize,
@@ -38,11 +39,20 @@ class KolabdProcess(multiprocessing.Process):
)
def synchronize(self, domain):
+ log.debug(_("Synchronizing for domain %s") % (domain), level=8)
+ sync_interval = conf.get('kolab', 'sync_interval')
+
+ if sync_interval == None or sync_interval == 0:
+ sync_interval = 300
+ else:
+ sync_interval = (int)(sync_interval)
+
while True:
try:
auth = Auth(domain)
auth.connect(domain)
auth.synchronize()
+ time.sleep(sync_interval)
except KeyboardInterrupt:
break
except Exception, errmsg:
diff --git a/pykolab.spec.in b/pykolab.spec.in
index f2a8a3c..8a43f44 100644
--- a/pykolab.spec.in
+++ b/pykolab.spec.in
@@ -41,6 +41,7 @@ Requires: kolab-cli = %{version}-%{release}
Requires: python-ldap >= 2.4
Requires: python-pyasn1
Requires: python-pyasn1-modules
+Requires: python-sqlalchemy
Requires(pre): /usr/sbin/useradd
Requires(pre): /usr/sbin/usermod
Requires(pre): /usr/sbin/groupadd
@@ -301,6 +302,9 @@ rm -rf %{buildroot}
%{python_sitelib}/pykolab/plugins/defaultfolders
%{python_sitelib}/pykolab/plugins/dynamicquota
%{python_sitelib}/pykolab/plugins/recipientpolicy
+# No sieve script management without our modified version of
+# python-sievelib
+%exclude %{python_sitelib}/pykolab/plugins/sievemgmt
%{python_sitelib}/kolab/
%{python_sitelib}/cyruslib.py*
%attr(0775,kolab,kolab-n) %dir %{_localstatedir}/lib/kolab/
@@ -331,6 +335,10 @@ rm -rf %{buildroot}
%{python_sitelib}/pykolab/cli/*.py
%{python_sitelib}/pykolab/cli/*.pyc
%{python_sitelib}/pykolab/cli/*.pyo
+%dir %{python_sitelib}/pykolab/cli/wap
+%{python_sitelib}/pykolab/cli/wap/*.py
+%{python_sitelib}/pykolab/cli/wap/*.pyc
+%{python_sitelib}/pykolab/cli/wap/*.pyo
%dir %{python_sitelib}/pykolab/setup/
%{python_sitelib}/pykolab/setup/*.py
%{python_sitelib}/pykolab/setup/*.pyc
@@ -339,6 +347,9 @@ rm -rf %{buildroot}
%{python_sitelib}/pykolab/wap_client/*.py
%{python_sitelib}/pykolab/wap_client/*.pyc
%{python_sitelib}/pykolab/wap_client/*.pyo
+# No sieve script management without our modified version of
+# python-sievelib
+%exclude %{python_sitelib}/pykolab/cli/sieve
%files -n kolab-saslauthd
%defattr(-,root,root,-)
diff --git a/pykolab/Makefile.am b/pykolab/Makefile.am
index a3488c1..a23aa6e 100644
--- a/pykolab/Makefile.am
+++ b/pykolab/Makefile.am
@@ -8,6 +8,7 @@ pykolab_auth_PYTHON = \
pykolab_auth_ldapdir = $(pythondir)/$(PACKAGE)/auth/ldap
pykolab_auth_ldap_PYTHON = \
auth/ldap/__init__.py \
+ auth/ldap/auth_cache.py \
auth/ldap/cache.py \
auth/ldap/syncrepl.py
@@ -23,6 +24,10 @@ pykolab_clitelemetrydir = $(pythondir)/$(PACKAGE)/cli/telemetry
pykolab_clitelemetry_PYTHON = \
$(wildcard cli/telemetry/*.py)
+pykolab_cliwapdir = $(pythondir)/$(PACKAGE)/cli/wap
+pykolab_cliwap_PYTHON = \
+ $(wildcard cli/wap/*.py)
+
pykolab_confdir = $(pythondir)/$(PACKAGE)/conf
pykolab_conf_PYTHON = \
conf/defaults.py \
@@ -69,7 +74,6 @@ pykolab_setup_PYTHON = \
setup/setup_php.py \
setup/setup_roundcube.py \
setup/setup_syncroton.py \
- setup/setup_zpush.py \
setup/__init__.py
pykolab_wapclientdir = $(pythondir)/$(PACKAGE)/wap_client
diff --git a/pykolab/__init__.py b/pykolab/__init__.py
index 3f0b520..0666cd3 100644
--- a/pykolab/__init__.py
+++ b/pykolab/__init__.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/auth/__init__.py b/pykolab/auth/__init__.py
index 6b07549..fd02083 100644
--- a/pykolab/auth/__init__.py
+++ b/pykolab/auth/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -37,15 +37,10 @@ class Auth(pykolab.base.Base):
"""
Initialize the authentication class.
"""
- pykolab.base.Base.__init__(self)
+ pykolab.base.Base.__init__(self, domain=domain)
self._auth = None
- if not domain == None:
- self.domain = domain
- else:
- self.domain = conf.get('kolab', 'primary_domain')
-
def authenticate(self, login):
"""
Verify login credentials supplied in login against the appropriate
@@ -97,8 +92,12 @@ class Auth(pykolab.base.Base):
return
if domain == None:
- section = 'kolab'
- domain = conf.get('kolab', 'primary_domain')
+ if not self.domain == None:
+ section = self.domain
+ domain = self.domain
+ else:
+ section = 'kolab'
+ domain = conf.get('kolab', 'primary_domain')
else:
self.list_domains()
section = domain
@@ -160,7 +159,7 @@ class Auth(pykolab.base.Base):
self._auth.connect()
- def disconnect(self):
+ def disconnect(self, domain=None):
"""
Connect to the domain authentication backend using domain, or fall
back to the primary domain specified by the configuration.
@@ -228,6 +227,8 @@ class Auth(pykolab.base.Base):
except:
if not self.domain == kolab_primary_domain:
return [(self.domain, [])]
+ else:
+ domains = []
# If no domains are found, the primary domain is used.
if len(domains) < 1:
@@ -263,8 +264,8 @@ class Auth(pykolab.base.Base):
def search_mail_address(self, domain, mail_address):
return self._auth._search_mail_address(domain, mail_address)
- def set_entry_attribute(self, domain, entry, attribute):
- return self._auth.set_entry_attribute(entry, attribute)
+ def set_entry_attribute(self, domain, entry, attribute, value):
+ return self._auth.set_entry_attribute(entry, attribute, value)
def set_entry_attributes(self, domain, entry, attributes):
return self._auth.set_entry_attributes(entry, attributes)
diff --git a/pykolab/auth/ldap/__init__.py b/pykolab/auth/ldap/__init__.py
index e3ca936..cdb9ade 100644
--- a/pykolab/auth/ldap/__init__.py
+++ b/pykolab/auth/ldap/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -35,6 +35,7 @@ from pykolab.translate import _
log = pykolab.getLogger('pykolab.auth')
conf = pykolab.getConf()
+import auth_cache
import cache
# Catch python-ldap-2.4 changes
@@ -110,7 +111,7 @@ class LDAP(pykolab.base.Base):
Initialize the LDAP object for domain. If no domain is specified,
domain name space configured as 'kolab'.'primary_domain' is used.
"""
- pykolab.base.Base.__init__(self)
+ pykolab.base.Base.__init__(self, domain=domain)
self.ldap = None
self.bind = False
@@ -151,7 +152,26 @@ class LDAP(pykolab.base.Base):
self.connect()
self._bind()
- user_filter = self.config_get('user_filter')
+ # See if we know a base_dn for the domain
+ base_dn = None
+
+ try:
+ base_dn = auth_cache.get_entry(self.domain)
+ except:
+ pass
+
+ if base_dn == None:
+ config_base_dn = self.config_get('base_dn')
+ ldap_base_dn = self._kolab_domain_root_dn(self.domain)
+
+ if not ldap_base_dn == None and not ldap_base_dn == config_base_dn:
+ base_dn = ldap_base_dn
+ else:
+ base_dn = config_base_dn
+
+ auth_cache.set_entry(self.domain, base_dn)
+
+ user_filter = self.config_get_raw('user_filter') % ({'base_dn':base_dn})
_filter = '(&(|'
@@ -163,41 +183,69 @@ class LDAP(pykolab.base.Base):
_filter += ')%s)' % (user_filter)
- _search = self.ldap.search_ext(
- self.config_get('base_dn'),
- ldap.SCOPE_SUBTREE,
- _filter,
- ['entrydn']
- )
+ entry_dn = None
- (
- _result_type,
- _result_data,
- _result_msgid,
- _result_controls
- ) = self.ldap.result3(_search)
+ try:
+ entry_dn = auth_cache.get_entry(_filter)
+ except:
+ pass
- if len(_result_data) >= 1:
- (entry_dn, entry_attrs) = _result_data[0]
+ if entry_dn == None:
+ _search = self.ldap.search_ext(
+ base_dn,
+ ldap.SCOPE_SUBTREE,
+ _filter,
+ ['entrydn']
+ )
- try:
- log.debug(_("Binding with user_dn %s and password %s")
- % (entry_dn, login[1]))
+ (
+ _result_type,
+ _result_data,
+ _result_msgid,
+ _result_controls
+ ) = self.ldap.result3(_search)
+
+ if len(_result_data) >= 1:
+ (entry_dn, entry_attrs) = _result_data[0]
- # Needs to be synchronous or succeeds and continues setting retval
- # to True!!
- self.ldap.simple_bind_s(entry_dn, login[1])
- retval = True
- except:
try:
- log.debug(
- _("Failed to authenticate as user %s") % (login[0]),
- level=8
- )
+ log.debug(_("Binding with user_dn %s and password %s")
+ % (entry_dn, login[1]))
+
+ # Needs to be synchronous or succeeds and continues setting retval
+ # to True!!
+ self.ldap.simple_bind_s(entry_dn, login[1])
+ retval = True
+ auth_cache.set_entry(_filter, entry_dn)
except:
- pass
+ try:
+ log.debug(
+ _("Failed to authenticate as user %s") % (login[0]),
+ level=8
+ )
+ except:
+ pass
+
+ retval = False
+ else:
+ try:
+ log.debug(_("Binding with user_dn %s and password %s")
+ % (entry_dn, login[1]))
+
+ # Needs to be synchronous or succeeds and continues setting retval
+ # to True!!
+ self.ldap.simple_bind_s(entry_dn, login[1])
+ retval = True
+ except:
+ try:
+ log.debug(
+ _("Failed to authenticate as user %s") % (login[0]),
+ level=8
+ )
+ except:
+ pass
- retval = False
+ retval = False
return retval
@@ -361,14 +409,21 @@ class LDAP(pykolab.base.Base):
_filter = "%s%s%s" % (__filter_prefix,_filter,__filter_suffix)
-
log.debug(_("Finding recipient with filter %r") % (_filter), level=8)
if len(_filter) <= 6:
return None
+ config_base_dn = self.config_get('base_dn')
+ ldap_base_dn = self._kolab_domain_root_dn(self.domain)
+
+ if not ldap_base_dn == None and not ldap_base_dn == config_base_dn:
+ base_dn = ldap_base_dn
+ else:
+ base_dn = config_base_dn
+
_results = self.ldap.search_s(
- self.config_get('base_dn'),
+ base_dn,
scope=ldap.SCOPE_SUBTREE,
filterstr=_filter,
attrlist=result_attributes,
@@ -379,7 +434,10 @@ class LDAP(pykolab.base.Base):
for _result in _results:
(_entry_id, _entry_attrs) = _result
- _entry_dns.append(_entry_id)
+
+ # Prevent Active Directory referrals
+ if not _entry_id == None:
+ _entry_dns.append(_entry_id)
return _entry_dns
@@ -409,8 +467,6 @@ class LDAP(pykolab.base.Base):
__filter_prefix = "(&%s" % resource_filter
__filter_suffix = ")"
- resource_base_dn = self.config_get('resource_base_dn')
-
recipient_address_attrs = self.config_get_list("mail_attributes")
result_attributes = recipient_address_attrs
@@ -434,6 +490,14 @@ class LDAP(pykolab.base.Base):
if len(_filter) <= 6:
return None
+ config_base_dn = self.config_get('resource_base_dn')
+ ldap_base_dn = self._kolab_domain_root_dn(self.domain)
+
+ if not ldap_base_dn == None and not ldap_base_dn == config_base_dn:
+ resource_base_dn = ldap_base_dn
+ else:
+ resource_base_dn = config_base_dn
+
_results = self.ldap.search_s(
resource_base_dn,
scope=ldap.SCOPE_SUBTREE,
@@ -564,6 +628,9 @@ class LDAP(pykolab.base.Base):
}
)
+ if primary_mail_address == None:
+ return entry_modifications
+
i = 1
_primary_mail = primary_mail_address
@@ -796,8 +863,16 @@ class LDAP(pykolab.base.Base):
_filter = "(%s=%s)" % (attr, value)
+ config_base_dn = self.config_get('base_dn')
+ ldap_base_dn = self._kolab_domain_root_dn(self.domain)
+
+ if not ldap_base_dn == None and not ldap_base_dn == config_base_dn:
+ base_dn = ldap_base_dn
+ else:
+ base_dn = config_base_dn
+
return self._search(
- self.config_get('base_dn'),
+ base_dn,
filterstr=_filter,
attrlist=[
'*',
@@ -863,18 +938,34 @@ class LDAP(pykolab.base.Base):
else:
override_search = False
- self._search(
- self.config_get('base_dn'),
- filterstr=_filter,
- attrlist=[
- '*',
- self.config_get('unique_attribute'),
- conf.get('cyrus-sasl', 'result_attribute'),
- 'modifytimestamp'
- ],
- override_search=override_search,
- callback=self._synchronize_callback,
- )
+ config_base_dn = self.config_get('base_dn')
+ ldap_base_dn = self._kolab_domain_root_dn(self.domain)
+
+ if not ldap_base_dn == None and not ldap_base_dn == config_base_dn:
+ base_dn = ldap_base_dn
+ else:
+ base_dn = config_base_dn
+
+ log.debug(_("Synchronization is searching against base DN: %s") % (base_dn), level=8)
+
+ try:
+ self._search(
+ base_dn,
+ filterstr=_filter,
+ attrlist=[
+ '*',
+ self.config_get('unique_attribute'),
+ conf.get('cyrus-sasl', 'result_attribute'),
+ 'modifytimestamp'
+ ],
+ override_search=override_search,
+ callback=self._synchronize_callback,
+ )
+ except Exception, errmsg:
+ log.error("Exception occurred: %r" % (errmsg))
+ if conf.debuglevel > 8:
+ import traceback
+ traceback.print_exc()
def user_quota(self, entry_id, folder):
default_quota = self.config_get('default_quota')
@@ -883,8 +974,9 @@ class LDAP(pykolab.base.Base):
if quota_attribute == None:
return
+ # The default quota may be None, but LDAP quota could still be set
if default_quota == None:
- return
+ default_quota = 0
self._bind()
@@ -919,6 +1011,11 @@ class LDAP(pykolab.base.Base):
}
)
+ try:
+ current_ldap_quota = (int)(current_ldap_quota)
+ except:
+ current_ldap_quota = None
+
if not current_ldap_quota == None:
if not new_quota == (int)(current_ldap_quota):
self.set_entry_attribute(
@@ -1180,6 +1277,9 @@ class LDAP(pykolab.base.Base):
if entry[result_attribute] == None:
return
+ if entry[result_attribute] == '':
+ return
+
cache.get_entry(self.domain, entry)
self.imap.connect(domain=self.domain)
@@ -1311,6 +1411,15 @@ class LDAP(pykolab.base.Base):
for key in entry_changes.keys():
entry[key] = entry_changes[key]
+ if not entry.has_key(result_attribute):
+ return
+
+ if entry[result_attribute] == None:
+ return
+
+ if entry[result_attribute] == '':
+ return
+
# Now look at entry_changes and old_canon_attr, and see if they're
# the same value.
if entry_changes.has_key(result_attribute):
@@ -1475,12 +1584,17 @@ class LDAP(pykolab.base.Base):
Expects the new entry.
"""
+ # Initialize old_canon_attr (#1701)
+ old_canon_attr = None
+
result_attribute = conf.get('cyrus-sasl','result_attribute')
_entry = cache.get_entry(self.domain, entry, update=False)
- if _entry.__dict__.has_key('result_attribute') and not _entry.result_attribute == '':
- old_canon_attr = _entry.result_attribute
+ # We do not necessarily have a synchronisation cache entry (#1701)
+ if not _entry == None:
+ if _entry.__dict__.has_key('result_attribute') and not _entry.result_attribute == '':
+ old_canon_attr = _entry.result_attribute
entry_changes = self.recipient_policy(entry)
@@ -1550,7 +1664,7 @@ class LDAP(pykolab.base.Base):
mailserver_attribute = self.config_get('mailserver_attribute')
if entry.has_key(mailserver_attribute):
- server = entry['mailserver_attribute']
+ server = entry[mailserver_attribute]
if not entry.has_key('kolabtargetfolder'):
entry['kolabtargetfolder'] = self.get_entry_attribute(
@@ -1725,7 +1839,13 @@ class LDAP(pykolab.base.Base):
entry_dn = self.entry_dn(entry_id)
- base_dn = self.config_get('base_dn')
+ config_base_dn = self.config_get('base_dn')
+ ldap_base_dn = self._kolab_domain_root_dn(self.domain)
+
+ if not ldap_base_dn == None and not ldap_base_dn == config_base_dn:
+ base_dn = ldap_base_dn
+ else:
+ base_dn = config_base_dn
for _type in ['user', 'group', 'sharedfolder']:
__filter = self.config_get('kolab_%s_filter' % (_type))
@@ -1844,6 +1964,9 @@ class LDAP(pykolab.base.Base):
_domain_attrs = utils.normalize(_domain_attrs)
if _domain_attrs.has_key(domain_rootdn_attribute):
return _domain_attrs[domain_rootdn_attribute]
+ else:
+ if isinstance(_domain_attrs[domain_name_attribute], list):
+ domain = _domain_attrs[domain_name_attribute][0]
else:
if conf.has_option('ldap', 'base_dn'):
@@ -1999,6 +2122,15 @@ class LDAP(pykolab.base.Base):
else:
change = change_dict['change_type']
+ # See if we can find the cache entry - this way we can get to
+ # the value of a (former, on a deleted entry) result_attribute
+ result_attribute = conf.get('cyrus-sasl', 'result_attribute')
+ if not entry.has_key(result_attribute):
+ cache_entry = cache.get_entry(self.domain, entry, update=False)
+
+ if hasattr(cache_entry, 'result_attribute') and change == 'delete':
+ entry[result_attribute] = cache_entry.result_attribute
+
eval(
"self._change_%s_%s(entry, change_dict)" % (
change,
@@ -2009,6 +2141,10 @@ class LDAP(pykolab.base.Base):
# Typical for Paged Results Control
elif kw.has_key('entry') and isinstance(kw['entry'], list):
for entry_dn,entry_attrs in kw['entry']:
+ # This is a referral
+ if entry_dn == None:
+ continue
+
entry = { 'dn': entry_dn }
entry_attrs = utils.normalize(entry_attrs)
for attr in entry_attrs.keys():
@@ -2046,6 +2182,14 @@ class LDAP(pykolab.base.Base):
#
# server = self.imap.user_mailbox_server(folder)
+ log.debug(
+ _("Done with _synchronize_callback() for entry %r") % (
+ entry['id']
+ ),
+ level=9
+ )
+
+
def _unbind(self):
"""
Discard the current set of bind credentials.
@@ -2389,27 +2533,37 @@ class LDAP(pykolab.base.Base):
_use_ldap_controls = self.ldap.supported_controls
for supported_control in _use_ldap_controls:
- exec("""_results = self.%s(
- %r,
- scope=%r,
- filterstr=%r,
- attrlist=%r,
- attrsonly=%r,
- timeout=%r,
- callback=callback,
- primary_domain=%r,
- secondary_domains=%r
- )""" % (
- supported_control,
- base_dn,
- scope,
- filterstr,
- attrlist,
- attrsonly,
- timeout,
- primary_domain,
- secondary_domains
+ try:
+ exec("""_results = self.%s(
+ %r,
+ scope=%r,
+ filterstr=%r,
+ attrlist=%r,
+ attrsonly=%r,
+ timeout=%r,
+ callback=callback,
+ primary_domain=%r,
+ secondary_domains=%r
+ )""" % (
+ supported_control,
+ base_dn,
+ scope,
+ filterstr,
+ attrlist,
+ attrsonly,
+ timeout,
+ primary_domain,
+ secondary_domains
+ )
)
- )
+
+ break
+
+ except Exception, errmsg:
+ log.error(_("An error occured using %s: %r") % (supported_control, errmsg))
+ if conf.debuglevel > 8:
+ import traceback
+ traceback.print_exc()
+ continue
return _results
diff --git a/pykolab/auth/ldap/auth_cache.py b/pykolab/auth/ldap/auth_cache.py
new file mode 100644
index 0000000..12f362c
--- /dev/null
+++ b/pykolab/auth/ldap/auth_cache.py
@@ -0,0 +1,138 @@
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
+#
+# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
+#
+# 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; version 3 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 Library 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.
+#
+
+import datetime
+
+import sqlalchemy
+
+from sqlalchemy import Column
+from sqlalchemy import DateTime
+from sqlalchemy import Integer
+from sqlalchemy import MetaData
+from sqlalchemy import String
+from sqlalchemy import Table
+
+from sqlalchemy import desc
+from sqlalchemy import create_engine
+from sqlalchemy.orm import mapper
+
+try:
+ from sqlalchemy.orm import relationship
+except:
+ from sqlalchemy.orm import relation as relationship
+
+try:
+ from sqlalchemy.orm import sessionmaker
+except:
+ from sqlalchemy.orm import create_session
+
+import pykolab
+
+from pykolab import utils
+from pykolab.constants import KOLAB_LIB_PATH
+from pykolab.translate import _
+
+conf = pykolab.getConf()
+log = pykolab.getLogger('pykolab.auth_cache')
+
+metadata = MetaData()
+
+db = None
+
+##
+## Classes
+##
+
+class Entry(object):
+ def __init__(self, key, value):
+ self.key = key
+ self.value = value
+
+##
+## Tables
+##
+
+entry_table = Table(
+ 'entries', metadata,
+ Column('id', Integer, primary_key=True),
+ Column('domain', String(128), index=True, nullable=True),
+ Column('key', String(128), index=True, nullable=False),
+ Column('value', String(128), nullable=False),
+ Column('last_change', DateTime, nullable=False, default=datetime.datetime.now())
+ )
+
+##
+## Table <-> Class Mappers
+##
+
+mapper(Entry, entry_table)
+
+##
+## Functions
+##
+
+def get_entry(key):
+ db = init_db()
+ _entries = db.query(Entry).filter_by(key=key).all()
+
+ if len(_entries) == 0:
+ return None
+ if len(_entries) > 1:
+ return None
+
+ log.debug("Entry found: %r" % (_entries[0].__dict__))
+ log.debug("Returning: %r" % (_entries[0].value))
+
+ return _entries[0].value
+
+def set_entry(key, value):
+ db = init_db()
+ _entries = db.query(Entry).filter_by(key=key).all()
+
+ if len(_entries) == 0:
+ db.add(
+ Entry(
+ key,
+ value
+ )
+ )
+
+ db.commit()
+
+#def purge_entries():
+ #db = init_db()
+ #db.query(Entry).filter(Entry.last_change <= datetime.datetime.now()).delete()
+
+def init_db():
+ """
+ Returns a SQLAlchemy Session() instance.
+ """
+ global db
+
+ if not db == None:
+ return db
+
+ db_uri = 'sqlite:///%s/auth_cache.db' % (KOLAB_LIB_PATH)
+ echo = conf.debuglevel > 8
+ engine = create_engine(db_uri, echo=echo)
+ metadata.create_all(engine)
+
+ Session = sessionmaker(bind=engine)
+ db = Session()
+
+ return db
diff --git a/pykolab/auth/ldap/cache.py b/pykolab/auth/ldap/cache.py
index 6688bf7..55a47c3 100644
--- a/pykolab/auth/ldap/cache.py
+++ b/pykolab/auth/ldap/cache.py
@@ -1,4 +1,4 @@
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -62,9 +62,14 @@ class Entry(object):
def __init__(self, uniqueid, result_attr, last_change):
self.uniqueid = uniqueid
self.result_attribute = result_attr
+
+ modifytimestamp_format = conf.get('ldap', 'modifytimestamp_format')
+ if modifytimestamp_format == None:
+ modifytimestamp_format = "%Y%m%d%H%M%SZ"
+
self.last_change = datetime.datetime.strptime(
last_change,
- "%Y%m%d%H%M%SZ"
+ modifytimestamp_format
)
##
@@ -125,9 +130,13 @@ def get_entry(domain, entry, update=True):
db.commit()
_entry = db.query(Entry).filter_by(uniqueid=entry['id']).first()
else:
- if not _entry.last_change.strftime("%Y%m%d%H%M%SZ") == entry['modifytimestamp']:
+ modifytimestamp_format = conf.get('ldap', 'modifytimestamp_format')
+ if modifytimestamp_format == None:
+ modifytimestamp_format = "%Y%m%d%H%M%SZ"
+
+ if not _entry.last_change.strftime(modifytimestamp_format) == entry['modifytimestamp']:
log.debug(_("Updating timestamp for cache entry %r") % (entry['id']), level=8)
- last_change = datetime.datetime.strptime(entry['modifytimestamp'], "%Y%m%d%H%M%SZ")
+ last_change = datetime.datetime.strptime(entry['modifytimestamp'], modifytimestamp_format)
_entry.last_change = last_change
db.commit()
_entry = db.query(Entry).filter_by(uniqueid=entry['id']).first()
@@ -163,7 +172,12 @@ def init_db(domain):
def last_modify_timestamp(domain):
db = init_db(domain)
last_change = db.query(Entry).order_by(desc(Entry.last_change)).first()
+
+ modifytimestamp_format = conf.get('ldap', 'modifytimestamp_format')
+ if modifytimestamp_format == None:
+ modifytimestamp_format = "%Y%m%d%H%M%SZ"
+
if not last_change == None:
- return last_change.last_change.strftime("%Y%m%d%H%M%SZ")
+ return last_change.last_change.strftime(modifytimestamp_format)
- return datetime.datetime(1900, 01, 01, 00, 00, 00).strftime("%Y%m%d%H%M%SZ")
+ return datetime.datetime(1900, 01, 01, 00, 00, 00).strftime(modifytimestamp_format)
diff --git a/pykolab/auth/ldap/syncrepl.py b/pykolab/auth/ldap/syncrepl.py
index e02e086..03ab5ae 100644
--- a/pykolab/auth/ldap/syncrepl.py
+++ b/pykolab/auth/ldap/syncrepl.py
@@ -5,8 +5,13 @@ import ldap
import ldap.syncrepl
import ldapurl
+import pykolab
+
from pykolab import utils
+log = pykolab.getLogger('pykolab.syncrepl')
+conf = pykolab.getConf()
+
class DNSync(ldap.ldapobject.LDAPObject,ldap.syncrepl.SyncreplConsumer):
callback = None
@@ -28,16 +33,36 @@ class DNSync(ldap.ldapobject.LDAPObject,ldap.syncrepl.SyncreplConsumer):
return self.__db['cookie']
def syncrepl_delete(self, uuids):
+ log.debug("syncrepl_delete uuids: %r" % (uuids), level=8)
+
+ # Get the unique_attribute name to issue along with our
+ # callback (if any)
+ unique_attr = conf.get('ldap', 'unique_attribute')
+ if unique_attr == None:
+ unique_attr = 'entryuuid'
+
+ if unique_attr == 'nsuniqueid':
+ log.warning(
+ _("The name of the persistent, unique attribute " + \
+ "is very probably not compatible with the use of " + \
+ "syncrepl.")
+ )
+
+
for uuid in uuids:
dn = self.__db[uuid]
+ log.debug("syncrepl_delete dn: %r" % (dn), level=8)
+
if not self.callback == None:
self.callback(
change_type='delete',
previous_dn=None,
change_number=None,
dn=dn,
- entry={}
+ entry={
+ unique_attr: uuid
+ }
)
del self.__db[uuid]
diff --git a/pykolab/base.py b/pykolab/base.py
index ebc1a59..207783c 100644
--- a/pykolab/base.py
+++ b/pykolab/base.py
@@ -1,4 +1,4 @@
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -26,7 +26,10 @@ class Base(object):
Abstraction class for functions commonly shared between auth, imap, etc.
"""
def __init__(self, *args, **kw):
- self.domain = conf.get('kolab', 'primary_domain')
+ if kw.has_key('domain') and not kw['domain'] == None:
+ self.domain = kw['domain']
+ else:
+ self.domain = conf.get('kolab', 'primary_domain')
# Placeholder primary_domain => [secondary_domains]. Should be updated
# on auth backend _connect().
diff --git a/pykolab/cli/__init__.py b/pykolab/cli/__init__.py
index aa054c0..a2cf250 100644
--- a/pykolab/cli/__init__.py
+++ b/pykolab/cli/__init__.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/cmd_acl_cleanup.py b/pykolab/cli/cmd_acl_cleanup.py
index 80d5396..3880d68 100644
--- a/pykolab/cli/cmd_acl_cleanup.py
+++ b/pykolab/cli/cmd_acl_cleanup.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/cmd_add_domain.py b/pykolab/cli/cmd_add_domain.py
index f3d5d97..92aab7c 100644
--- a/pykolab/cli/cmd_add_domain.py
+++ b/pykolab/cli/cmd_add_domain.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -35,16 +35,16 @@ def __init__():
def cli_options():
my_option_group = conf.add_cli_parser_option_group(_("CLI Options"))
my_option_group.add_option(
- '--alias-for',
- dest = "parent_domain",
- action = "store",
- default = None,
- help = _("Add domain as alias for DOMAIN"),
+ '--alias',
+ dest = "domains",
+ action = "append",
+ default = [],
+ help = _("Add alias domain."),
metavar = "DOMAIN",
)
def description():
- return _("Add a new domain or domain alias.")
+ return _("Add a new domain.")
def execute(*args, **kw):
from pykolab import wap_client
@@ -58,31 +58,12 @@ def execute(*args, **kw):
sys.exit(1)
wap_client.authenticate(username=username)
- domains = wap_client.domains_list()
dna = conf.get('ldap', 'domain_name_attribute')
- if not conf.parent_domain == None:
- parent_found = False
- if isinstance(domains['list'], dict):
- for _domain in domains['list'].keys():
- if parent_found:
- continue
-
- if isinstance(domains['list'][_domain][dna], basestring):
- if conf.parent_domain == domains['list'][_domain][dna]:
- parent_found = True
- elif isinstance(domains['list'][_domain], list):
- if conf.parent_domain in domains['list'][_domain][dna]:
- parent_found = True
-
- if not parent_found:
- log.error(_("Invalid parent domain"))
- sys.exit(1)
-
try:
domain = conf.cli_args.pop(0)
except IndexError, errmsg:
domain = utils.ask_question(_("Domain name"))
- wap_client.domain_add(domain, conf.parent_domain)
+ wap_client.domain_add(domain, conf.domains)
diff --git a/pykolab/cli/cmd_add_user.py b/pykolab/cli/cmd_add_user.py
new file mode 100644
index 0000000..873e1d8
--- /dev/null
+++ b/pykolab/cli/cmd_add_user.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
+#
+# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
+#
+# 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; version 3 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 Library 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.
+#
+
+import commands
+
+import pykolab
+
+from pykolab.translate import _
+
+log = pykolab.getLogger('pykolab.cli')
+conf = pykolab.getConf()
+
+def __init__():
+ commands.register('add_user', execute, description="Add a user.")
+
+def execute(*args, **kw):
+ from pykolab import wap_client
+ # Create the authentication object.
+ # TODO: Binds with superuser credentials!
+ wap_client.authenticate()
+ wap_client.user_add()
+
diff --git a/pykolab/cli/cmd_add_user_subscription.py b/pykolab/cli/cmd_add_user_subscription.py
index 4b3393a..666ef7e 100644
--- a/pykolab/cli/cmd_add_user_subscription.py
+++ b/pykolab/cli/cmd_add_user_subscription.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/cmd_count_domain_mailboxes.py b/pykolab/cli/cmd_count_domain_mailboxes.py
new file mode 100644
index 0000000..6cc71ef
--- /dev/null
+++ b/pykolab/cli/cmd_count_domain_mailboxes.py
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
+#
+# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
+#
+# 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; version 3 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 Library 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.
+#
+
+import datetime
+
+import commands
+
+import pykolab
+
+from pykolab import imap_utf7
+from pykolab.auth import Auth
+from pykolab.imap import IMAP
+from pykolab.translate import _
+
+log = pykolab.getLogger('pykolab.cli')
+conf = pykolab.getConf()
+
+def __init__():
+ commands.register('count_domain_mailboxes', execute)
+
+def cli_options():
+ my_option_group = conf.add_cli_parser_option_group(_("CLI Options"))
+ my_option_group.add_option( '--server',
+ dest = "connect_server",
+ action = "store",
+ default = None,
+ metavar = "SERVER",
+ help = _("List mailboxes on server SERVER only."))
+
+def execute(*args, **kw):
+ """
+ List deleted mailboxes
+ """
+ imap = IMAP()
+ imap.connect()
+
+ auth = Auth()
+ auth.connect()
+
+ domains = auth.list_domains()
+
+ folders = []
+ for primary,secondaries in domains:
+ print "%s: %d" % (primary,len(imap.lm("user/%%@%s" % (primary))))
+ for secondary in secondaries:
+ print "%s: %d" % (secondary,len(imap.lm("user/%%@%s" % (secondary))))
+
+ null_realm = len(imap.lm("user/%%"))
+
+ if null_realm > 0:
+ print "null: %d" % (null_realm)
+
diff --git a/pykolab/cli/cmd_create_mailbox.py b/pykolab/cli/cmd_create_mailbox.py
index 5510e56..63ae0ad 100644
--- a/pykolab/cli/cmd_create_mailbox.py
+++ b/pykolab/cli/cmd_create_mailbox.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -63,9 +63,7 @@ def execute(*args, **kw):
imap = IMAP()
imap.connect()
- admin_login = conf.get('cyrus-imap', 'admin_login')
-
- imap.cm(mailbox)
+ imap.create_folder(mailbox)
if not conf.metadata == None:
imap.set_metadata(mailbox, conf.metadata.split('=')[0], conf.metadata.split('=')[1])
diff --git a/pykolab/cli/cmd_delete_domain.py b/pykolab/cli/cmd_delete_domain.py
new file mode 100644
index 0000000..6856aec
--- /dev/null
+++ b/pykolab/cli/cmd_delete_domain.py
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
+#
+# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
+#
+# 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; version 3 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 Library 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.
+#
+
+import sys
+
+import commands
+
+import pykolab
+
+from pykolab import utils
+from pykolab.translate import _
+
+log = pykolab.getLogger('pykolab.cli')
+conf = pykolab.getConf()
+
+def __init__():
+ commands.register('delete_domain', execute, description=description())
+
+def description():
+ return _("Delete a domain.")
+
+def execute(*args, **kw):
+ from pykolab import wap_client
+
+ # Use uber-administrative privileges
+ username = conf.get('ldap', 'bind_dn')
+ if username == None:
+ log.error(_("Could not find credentials with sufficient permissions" + \
+ "to add a domain name space."))
+
+ sys.exit(1)
+
+ wap_client.authenticate(username=username)
+
+ dna = conf.get('ldap', 'domain_name_attribute')
+
+ try:
+ domain = conf.cli_args.pop(0)
+ except IndexError, errmsg:
+ domain = utils.ask_question(_("Domain name"))
+
+ wap_client.domain_delete(domain)
diff --git a/pykolab/cli/cmd_delete_mailbox.py b/pykolab/cli/cmd_delete_mailbox.py
index 0978b7e..61bc278 100644
--- a/pykolab/cli/cmd_delete_mailbox.py
+++ b/pykolab/cli/cmd_delete_mailbox.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -49,7 +49,9 @@ def execute(*args, **kw):
imap = IMAP()
imap.connect()
- delete_folders = imap.lm(delete_folder)
+
+ delete_folders = imap.list_folders(delete_folder)
+
for delete_folder in delete_folders:
imap.delete_mailfolder(delete_folder)
diff --git a/pykolab/cli/cmd_delete_mailbox_acl.py b/pykolab/cli/cmd_delete_mailbox_acl.py
index 1bf2ad6..727b00d 100644
--- a/pykolab/cli/cmd_delete_mailbox_acl.py
+++ b/pykolab/cli/cmd_delete_mailbox_acl.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -62,4 +62,8 @@ def execute(*args, **kw):
else:
folders = imap.lm(folder)
for folder in folders:
- imap.set_acl(folder, identifier, '') \ No newline at end of file
+ try:
+ imap.set_acl(folder, identifier, '')
+ except:
+ # Mailbox no longer exists?
+ pass \ No newline at end of file
diff --git a/pykolab/cli/cmd_delete_message.py b/pykolab/cli/cmd_delete_message.py
index 105cfd9..f90fdc0 100644
--- a/pykolab/cli/cmd_delete_message.py
+++ b/pykolab/cli/cmd_delete_message.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/cmd_export_mailbox.py b/pykolab/cli/cmd_export_mailbox.py
index 72ea139..fde3fac 100644
--- a/pykolab/cli/cmd_export_mailbox.py
+++ b/pykolab/cli/cmd_export_mailbox.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/cmd_find_domain.py b/pykolab/cli/cmd_find_domain.py
new file mode 100644
index 0000000..0486fee
--- /dev/null
+++ b/pykolab/cli/cmd_find_domain.py
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
+#
+# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
+#
+# 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; version 3 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 Library 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.
+#
+
+import sys
+
+import commands
+
+import pykolab
+
+from pykolab import utils
+from pykolab.translate import _
+
+log = pykolab.getLogger('pykolab.cli')
+conf = pykolab.getConf()
+
+def __init__():
+ commands.register('find_domain', execute, description=description())
+
+def description():
+ return _("Find a domain.")
+
+def execute(*args, **kw):
+ from pykolab import wap_client
+
+ # Use uber-administrative privileges
+ username = conf.get('ldap', 'bind_dn')
+ if username == None:
+ log.error(_("Could not find credentials with sufficient permissions" + \
+ "to add a domain name space."))
+
+ sys.exit(1)
+
+ wap_client.authenticate(username=username)
+
+ dna = conf.get('ldap', 'domain_name_attribute')
+
+ try:
+ domain = conf.cli_args.pop(0)
+ except IndexError, errmsg:
+ domain = utils.ask_question(_("Domain name"))
+
+ wap_client.domain_find(domain)
diff --git a/pykolab/cli/cmd_list_deleted_mailboxes.py b/pykolab/cli/cmd_list_deleted_mailboxes.py
index 90bcddd..305a129 100644
--- a/pykolab/cli/cmd_list_deleted_mailboxes.py
+++ b/pykolab/cli/cmd_list_deleted_mailboxes.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -17,10 +17,14 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
+import datetime
+
import commands
import pykolab
+from pykolab import imap_utf7
+from pykolab.auth import Auth
from pykolab.imap import IMAP
from pykolab.translate import _
@@ -30,14 +34,48 @@ conf = pykolab.getConf()
def __init__():
commands.register('list_deleted_mailboxes', execute)
+def cli_options():
+ my_option_group = conf.add_cli_parser_option_group(_("CLI Options"))
+ my_option_group.add_option( '--raw',
+ dest = "raw",
+ action = "store_true",
+ default = False,
+ help = _("Display raw IMAP UTF-7 folder names"))
+
+ my_option_group.add_option( '--server',
+ dest = "connect_server",
+ action = "store",
+ default = None,
+ metavar = "SERVER",
+ help = _("List mailboxes on server SERVER only."))
+
def execute(*args, **kw):
"""
List deleted mailboxes
"""
imap = IMAP()
imap.connect()
- folders = imap.lm("DELETED/*")
+
+ auth = Auth()
+ auth.connect()
+
+ domains = auth.list_domains()
+
+ folders = []
+ for primary,secondaries in domains:
+ folders.extend(imap.lm("DELETED/*@%s" % (primary)))
+ for secondary in secondaries:
+ folders.extend(imap.lm("DELETED/*@%s" % (secondary)))
+
+ folders.extend(imap.lm("DELETED/*"))
+
print "Deleted folders:"
+
for folder in folders:
- print folder
+ mbox_parts = imap.parse_mailfolder(folder)
+
+ if not conf.raw:
+ print "%s (Deleted at %s)" % (imap_utf7.decode(folder), datetime.datetime.fromtimestamp(int(mbox_parts['hex_timestamp'], 16)))
+ else:
+ print "%s (Deleted at %s)" % (folder, datetime.datetime.fromtimestamp(int(mbox_parts['hex_timestamp'], 16)))
diff --git a/pykolab/cli/cmd_list_domain_mailboxes.py b/pykolab/cli/cmd_list_domain_mailboxes.py
new file mode 100644
index 0000000..684f1c8
--- /dev/null
+++ b/pykolab/cli/cmd_list_domain_mailboxes.py
@@ -0,0 +1,83 @@
+# -*- coding: utf-8 -*-
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
+#
+# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
+#
+# 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; version 3 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 Library 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.
+#
+
+import commands
+
+import pykolab
+
+from pykolab import imap_utf7
+from pykolab.auth import Auth
+from pykolab.imap import IMAP
+from pykolab.translate import _
+
+log = pykolab.getLogger('pykolab.cli')
+conf = pykolab.getConf()
+
+def __init__():
+ commands.register('list_domain_mailboxes', execute)
+
+def cli_options():
+ my_option_group = conf.add_cli_parser_option_group(_("CLI Options"))
+ my_option_group.add_option( '--raw',
+ dest = "raw",
+ action = "store_true",
+ default = False,
+ help = _("Display raw IMAP UTF-7 folder names"))
+
+ my_option_group.add_option( '--server',
+ dest = "connect_server",
+ action = "store",
+ default = None,
+ metavar = "SERVER",
+ help = _("List mailboxes on server SERVER only."))
+
+def execute(*args, **kw):
+ """
+ List deleted mailboxes
+ """
+
+ try:
+ domain = conf.cli_args.pop(0)
+ except:
+ domain = utils.ask_question(_("Domain"))
+
+ imap = IMAP()
+ imap.connect()
+
+ auth = Auth()
+ auth.connect()
+
+ domains = auth.list_domains()
+
+ folders = []
+ for primary,secondaries in domains:
+ if not domain == primary and not domain in secondaries:
+ continue
+
+ folders.extend(imap.lm("user/%%@%s" % (primary)))
+ for secondary in secondaries:
+ folders.extend(imap.lm("user/%%@%s" % (secondary)))
+
+ print "Deleted folders:"
+
+ for folder in folders:
+ if not conf.raw:
+ print imap_utf7.decode(folder)
+ else:
+ print folder
diff --git a/pykolab/cli/cmd_list_domains.py b/pykolab/cli/cmd_list_domains.py
index fd2c7da..c1b58d7 100644
--- a/pykolab/cli/cmd_list_domains.py
+++ b/pykolab/cli/cmd_list_domains.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/cmd_list_mailbox_acls.py b/pykolab/cli/cmd_list_mailbox_acls.py
index 62bac4f..f69c09d 100644
--- a/pykolab/cli/cmd_list_mailbox_acls.py
+++ b/pykolab/cli/cmd_list_mailbox_acls.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -55,7 +55,7 @@ def execute(*args, **kw):
else:
acls = []
- folders = imap.lm(folder)
+ folders = imap.list_folders(folder)
for folder in folders:
print "Folder", folder
acls = imap.list_acls(folder)
diff --git a/pykolab/cli/cmd_list_mailbox_metadata.py b/pykolab/cli/cmd_list_mailbox_metadata.py
index b430896..a07420d 100644
--- a/pykolab/cli/cmd_list_mailbox_metadata.py
+++ b/pykolab/cli/cmd_list_mailbox_metadata.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -81,7 +81,7 @@ def execute(*args, **kw):
else:
metadata = []
- folders = imap.lm(folder)
+ folders = imap.list_folders(folder)
for folder in folders:
print "Folder", folder
diff --git a/pykolab/cli/cmd_list_mailboxes.py b/pykolab/cli/cmd_list_mailboxes.py
index 3451e7c..f9391eb 100644
--- a/pykolab/cli/cmd_list_mailboxes.py
+++ b/pykolab/cli/cmd_list_mailboxes.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -21,6 +21,7 @@ import commands
import pykolab
+from pykolab import imap_utf7
from pykolab.imap import IMAP
from pykolab.translate import _
@@ -43,6 +44,13 @@ def cli_options():
default = False,
help = _("Display raw IMAP UTF-7 folder names"))
+ my_option_group.add_option( '--server',
+ dest = "connect_server",
+ action = "store",
+ default = None,
+ metavar = "SERVER",
+ help = _("List mailboxes on server SERVER only."))
+
def execute(*args, **kw):
"""
List mailboxes
@@ -67,13 +75,20 @@ def execute(*args, **kw):
searches = [ '' ]
imap = IMAP()
- imap.connect()
+
+ if not conf.connect_server == None:
+ imap.connect(server=conf.connect_server)
+ else:
+ imap.connect()
folders = []
for search in searches:
log.debug(_("Appending folder search for %r") % (search), level=8)
- folders.extend(imap.lm(search))
+ folders.extend(imap.lm(imap_utf7.encode(search)))
for folder in folders:
- print folder
+ if not conf.raw:
+ print imap_utf7.decode(folder)
+ else:
+ print folder
diff --git a/pykolab/cli/cmd_list_messages.py b/pykolab/cli/cmd_list_messages.py
index 586e2ae..716cdd3 100644
--- a/pykolab/cli/cmd_list_messages.py
+++ b/pykolab/cli/cmd_list_messages.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -23,6 +23,7 @@ import commands
import pykolab
+from pykolab import imap_utf7
from pykolab.imap import IMAP
from pykolab.translate import _
@@ -60,7 +61,7 @@ def execute(*args, **kw):
imap = IMAP()
imap.connect()
- _folder = imap.lm(folder)
+ _folder = imap.lm(imap_utf7.encode(folder))
if _folder == None or _folder == []:
log.error(_("No such folder"))
@@ -68,7 +69,7 @@ def execute(*args, **kw):
imap.set_acl(folder, 'cyrus-admin', 'lrs')
- imap.select(folder)
+ imap.select(imap_utf7.encode(folder))
if conf.list_deleted:
typ, data = imap.search(None, 'ALL')
@@ -94,3 +95,5 @@ def execute(*args, **kw):
print num
else:
print num
+
+ imap.set_acl(folder, 'cyrus-admin', '')
diff --git a/pykolab/cli/cmd_list_quota.py b/pykolab/cli/cmd_list_quota.py
index 6aba95b..9980ea3 100644
--- a/pykolab/cli/cmd_list_quota.py
+++ b/pykolab/cli/cmd_list_quota.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -32,6 +32,15 @@ conf = pykolab.getConf()
def __init__():
commands.register('list_quota', execute, description=description(), aliases=['lq'])
+def cli_options():
+ my_option_group = conf.add_cli_parser_option_group(_("CLI Options"))
+ my_option_group.add_option( '--server',
+ dest = "connect_server",
+ action = "store",
+ default = None,
+ metavar = "SERVER",
+ help = _("List mailboxes on server SERVER only."))
+
def description():
return """List quota for a folder."""
@@ -46,11 +55,15 @@ def execute(*args, **kw):
quota_folder = '*'
imap = IMAP()
- imap.connect()
+
+ if not conf.connect_server == None:
+ imap.connect(server=conf.connect_server)
+ else:
+ imap.connect()
folders = []
- quota_folders = imap.lm(quota_folder)
+ quota_folders = imap.list_folders(quota_folder)
for quota_folder in quota_folders:
try:
(used, quota) = imap.get_quota(quota_folder)
@@ -63,7 +76,10 @@ def execute(*args, **kw):
percentage = round(((float)(used)/(float)(quota)) * 100.0, 1)
print "%d (Used: %d, Percentage: %d)" % (quota, used, percentage)
else:
- print "No quota"
+ if used == None:
+ print "%d (Used: %d, Percentage: %d)" % (quota, 0, 0)
+ else:
+ print "No quota"
except:
try:
(quota_root, used, quota) = imap.get_quota_root(quota_folder)
@@ -76,7 +92,10 @@ def execute(*args, **kw):
percentage = round(((float)(used)/(float)(quota)) * 100.0, 1)
print "%d (Root: %s, Used: %d, Percentage: %d)" % (quota, quota_root, used, percentage)
else:
- print "No quota"
+ if used == None and not quota_root == None:
+ print "%d (Root: %s, Used: %d, Percentage: %d)" % (quota, quota_root, 0, 0)
+ else:
+ print "No quota"
except:
print "Folder: %s" % (quota_folder)
print "No quota root"
diff --git a/pykolab/cli/cmd_list_user_subscriptions.py b/pykolab/cli/cmd_list_user_subscriptions.py
index a25e8d6..3360613 100644
--- a/pykolab/cli/cmd_list_user_subscriptions.py
+++ b/pykolab/cli/cmd_list_user_subscriptions.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -21,6 +21,7 @@ import commands
import pykolab
+from pykolab import imap_utf7
from pykolab.imap import IMAP
from pykolab.translate import _
from pykolab import utils
@@ -33,6 +34,12 @@ def __init__():
def cli_options(*args, **kw):
my_option_group = conf.add_cli_parser_option_group(_("CLI Options"))
+ my_option_group.add_option( '--raw',
+ dest = "raw",
+ action = "store_true",
+ default = False,
+ help = _("Display raw IMAP UTF-7 folder names"))
+
my_option_group.add_option( '--unsubscribed',
dest = "unsubscribed",
action = "store_true",
@@ -83,9 +90,15 @@ def execute(*args, **kw):
unsubscribed_folders.append(folder)
if len(unsubscribed_folders) > 0:
- print "\n".join(unsubscribed_folders)
+ if not conf.raw:
+ print "\n".join([imap_utf7.decode(x) for x in unsubscribed_folders])
+ else:
+ print "\n".join(unsubscribed_folders)
else:
print _("No unsubscribed folders for user %s") % (user)
else:
- print "\n".join(subscribed_folders)
+ if not conf.raw:
+ print "\n".join([imap_utf7.decode(x) for x in subscribed_folders])
+ else:
+ print "\n".join(subscribed_folders)
diff --git a/pykolab/cli/cmd_mailbox_cleanup.py b/pykolab/cli/cmd_mailbox_cleanup.py
index c3af740..a214556 100644
--- a/pykolab/cli/cmd_mailbox_cleanup.py
+++ b/pykolab/cli/cmd_mailbox_cleanup.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/cmd_remove_mailaddress.py b/pykolab/cli/cmd_remove_mailaddress.py
index 19c4756..fbb571a 100644
--- a/pykolab/cli/cmd_remove_mailaddress.py
+++ b/pykolab/cli/cmd_remove_mailaddress.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/cmd_remove_user_subscription.py b/pykolab/cli/cmd_remove_user_subscription.py
index 79e9d09..17ff818 100644
--- a/pykolab/cli/cmd_remove_user_subscription.py
+++ b/pykolab/cli/cmd_remove_user_subscription.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/cmd_rename_mailbox.py b/pykolab/cli/cmd_rename_mailbox.py
index 9917f6b..e596401 100644
--- a/pykolab/cli/cmd_rename_mailbox.py
+++ b/pykolab/cli/cmd_rename_mailbox.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/cmd_server_info.py b/pykolab/cli/cmd_server_info.py
new file mode 100644
index 0000000..51ec40d
--- /dev/null
+++ b/pykolab/cli/cmd_server_info.py
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
+#
+# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
+#
+# 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; version 3 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 Library 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.
+#
+
+import commands
+
+import pykolab
+
+from pykolab.imap import IMAP
+from pykolab.translate import _
+
+log = pykolab.getLogger('pykolab.cli')
+conf = pykolab.getConf()
+
+def __init__():
+ commands.register('server_info', execute, description=description())
+
+def cli_options():
+ my_option_group = conf.add_cli_parser_option_group(_("CLI Options"))
+ my_option_group.add_option( '--server',
+ dest = "connect_server",
+ action = "store",
+ default = None,
+ metavar = "SERVER",
+ help = _("List mailboxes on server SERVER only."))
+
+
+def description():
+ return "Display server info.\n"
+
+def execute(*args, **kw):
+ """
+ List mailboxes
+ """
+
+ imap = IMAP()
+
+ if not conf.connect_server == None:
+ imap.connect(server=conf.connect_server)
+ else:
+ imap.connect()
+
+ print imap.get_metadata("")
diff --git a/pykolab/cli/cmd_set_language.py b/pykolab/cli/cmd_set_language.py
index 316d95a..4785fe3 100644
--- a/pykolab/cli/cmd_set_language.py
+++ b/pykolab/cli/cmd_set_language.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/cmd_set_mail.py b/pykolab/cli/cmd_set_mail.py
index d32952f..1a54f46 100644
--- a/pykolab/cli/cmd_set_mail.py
+++ b/pykolab/cli/cmd_set_mail.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/cmd_set_mailbox_acl.py b/pykolab/cli/cmd_set_mailbox_acl.py
index 8ba4567..e86c62d 100644
--- a/pykolab/cli/cmd_set_mailbox_acl.py
+++ b/pykolab/cli/cmd_set_mailbox_acl.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -67,6 +67,6 @@ def execute(*args, **kw):
print >> sys.stderr, _("No such folder %r") % (folder)
else:
- folders = imap.lm(folder)
+ folders = imap.list_folders(folder)
for folder in folders:
imap.set_acl(folder, identifier, acl)
diff --git a/pykolab/cli/cmd_set_mailbox_metadata.py b/pykolab/cli/cmd_set_mailbox_metadata.py
index 2cade85..acff7c5 100644
--- a/pykolab/cli/cmd_set_mailbox_metadata.py
+++ b/pykolab/cli/cmd_set_mailbox_metadata.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/cmd_sync.py b/pykolab/cli/cmd_sync.py
index 8beef3d..da75a71 100644
--- a/pykolab/cli/cmd_sync.py
+++ b/pykolab/cli/cmd_sync.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/cmd_sync_mailhost_attrs.py b/pykolab/cli/cmd_sync_mailhost_attrs.py
new file mode 100644
index 0000000..0f2e4d9
--- /dev/null
+++ b/pykolab/cli/cmd_sync_mailhost_attrs.py
@@ -0,0 +1,133 @@
+# -*- coding: utf-8 -*-
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
+#
+# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
+#
+# 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; version 3 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 Library 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.
+#
+
+import commands
+
+import pykolab
+
+from pykolab import imap_utf7
+from pykolab.auth import Auth
+from pykolab.imap import IMAP
+from pykolab.translate import _
+
+log = pykolab.getLogger('pykolab.cli')
+conf = pykolab.getConf()
+
+def __init__():
+ commands.register('sync_mailhost_attrs', execute, description=description())
+
+def description():
+ return "Synchronize mailHost attribute values with the actual mailserver in a Cyrus IMAP Murder.\n"
+
+def cli_options():
+ my_option_group = conf.add_cli_parser_option_group(_("CLI Options"))
+ my_option_group.add_option( '--delete',
+ dest = "delete",
+ action = "store_true",
+ default = False,
+ help = _("Delete mailboxes for recipients that do not appear to exist in LDAP."))
+
+ my_option_group.add_option( '--dry-run',
+ dest = "dry_run",
+ action = "store_true",
+ default = False,
+ help = _("Display changes, do not apply them."))
+
+ my_option_group.add_option( '--server',
+ dest = "connect_server",
+ action = "store",
+ default = None,
+ metavar = "SERVER",
+ help = _("List mailboxes on server SERVER only."))
+
+def execute(*args, **kw):
+ """
+ Synchronize or display changes
+ """
+
+ imap = IMAP()
+
+ if not conf.connect_server == None:
+ imap.connect(server=conf.connect_server)
+ else:
+ imap.connect()
+
+ auth = Auth()
+ auth.connect()
+
+ domains = auth.list_domains()
+
+ for primary,secondaries in domains:
+ folders = []
+
+ folders.extend(imap.lm('shared/%%@%s' % (primary)))
+ folders.extend(imap.lm('user/%%@%s' % (primary)))
+
+ for secondary in secondaries:
+ folders.extend(imap.lm('shared/%%@%s' % (secondary)))
+ folders.extend(imap.lm('user/%%@%s' % (secondary)))
+
+ auth = Auth(domain=primary)
+ auth.connect()
+
+ for folder in folders:
+ server = imap.user_mailbox_server(folder)
+ recipient = auth.find_recipient('/'.join(folder.split('/')[1:]))
+ if (isinstance(recipient, list)):
+ if len(recipient) > 1:
+ log.warning(_("Multiple recipients for '%s'!") % ('/'.join(folder.split('/')[1:])))
+ continue
+ elif len(recipient) == 0:
+ if conf.delete:
+ if conf.dry_run:
+ if not folder.split('/')[0] == 'shared':
+ log.warning(_("No recipients for '%s' (would have deleted the mailbox if not for --dry-run)!") % ('/'.join(folder.split('/')[1:])))
+ else:
+ continue
+ else:
+ if not '/'.join(folder.split('/')[0]) == 'shared':
+ log.info(_("Deleting mailbox '%s' because it has no recipients") % (folder))
+ imap.dm(folder)
+ else:
+ log.info(_("Not automatically deleting shared folder '%s'") % (folder))
+ else:
+ log.warning(_("No recipients for '%s' (use --delete to delete)!") % ('/'.join(folder.split('/')[1:])))
+
+ continue
+ else:
+ mailhost = auth.get_entry_attribute(primary, recipient, 'mailhost')
+
+ if not server == mailhost:
+ if conf.dry_run:
+ print folder, server, mailhost
+ else:
+ auth.set_entry_attribute(primary, recipient, 'mailhost', server)
+
+ folders = []
+ folders.extend(imap.lm("shared/%%"))
+ folders.extend(imap.lm("user/%%"))
+
+ auth = Auth()
+ auth.connect()
+
+ for folder in folders:
+ server = imap.user_mailbox_server(folder)
+ recipient = auth.find_recipient('/'.join(folder.split('/')[1:]))
+
+ print folder, server, recipient
diff --git a/pykolab/cli/cmd_transfer_mailbox.py b/pykolab/cli/cmd_transfer_mailbox.py
index 65843a9..56aab24 100644
--- a/pykolab/cli/cmd_transfer_mailbox.py
+++ b/pykolab/cli/cmd_transfer_mailbox.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -21,6 +21,8 @@ import commands
import pykolab
+from pykolab.auth import Auth
+from pykolab.imap import IMAP
from pykolab.translate import _
log = pykolab.getLogger('pykolab.cli')
@@ -41,22 +43,26 @@ def execute(*args, **kw):
if len(conf.cli_args) > 0:
target_partition = conf.cli_args.pop(0)
- mbox_parts = imap.parse_mailfolder(mailfolder)
+ imap = IMAP()
+ imap.connect()
- print "Mailbox parts:", mbox_parts
+ mbox_parts = imap.parse_mailfolder(mailfolder)
if mbox_parts['domain'] == None:
+ domain = conf.get('kolab', 'primary_domain')
user_identifier = mbox_parts['path_parts'][1]
else:
+ domain = mbox_parts['domain']
user_identifier = "%s@%s" % (mbox_parts['path_parts'][1], mbox_parts['domain'])
- print "User Identifier:", user_identifier
+ auth = Auth(domain=domain)
+ auth.connect()
- user = auth.find_user("mail", user_identifier)
+ user = auth.find_recipient(user_identifier)
- print "User:", user
-
- imap.connect()
+ source_server = imap.user_mailbox_server(mailfolder)
+ imap.connect(server=source_server)
imap.imap.xfer(mailfolder, target_server)
- auth.set_user_attribute(mbox_parts['domain'], user, "mailHost", target_server)
+ if not user == None and not len(user) < 1:
+ auth.set_entry_attributes(domain, user, {'mailhost': target_server})
diff --git a/pykolab/cli/cmd_undelete_mailbox.py b/pykolab/cli/cmd_undelete_mailbox.py
index 5b7719c..46eec85 100644
--- a/pykolab/cli/cmd_undelete_mailbox.py
+++ b/pykolab/cli/cmd_undelete_mailbox.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -21,6 +21,7 @@ import commands
import pykolab
+from pykolab.imap import IMAP
from pykolab.translate import _
log = pykolab.getLogger('pykolab.cli')
@@ -43,6 +44,7 @@ def execute(*args, **kw):
if len(conf.cli_args) > 0:
target_folder = conf.cli_args.pop(0)
+ imap = IMAP()
imap.connect()
imap.undelete_mailfolder(undelete_folder, target_folder)
diff --git a/pykolab/cli/cmd_user_info.py b/pykolab/cli/cmd_user_info.py
new file mode 100644
index 0000000..23fceb8
--- /dev/null
+++ b/pykolab/cli/cmd_user_info.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+#
+# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
+#
+# 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; version 3 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 Library 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.
+#
+
+import commands
+
+import pykolab
+
+from pykolab import utils
+from pykolab.translate import _
+
+log = pykolab.getLogger('pykolab.cli')
+conf = pykolab.getConf()
+
+def __init__():
+ commands.register('user_info', execute, description="Display user information.")
+
+def execute(*args, **kw):
+ from pykolab import wap_client
+
+ try:
+ user = conf.cli_args.pop(0)
+ except IndexError, errmsg:
+ user = utils.ask_question(_("Email address"))
+
+ wap_client.authenticate(username=conf.get("ldap", "bind_dn"), password=conf.get("ldap", "bind_pw"))
+ if len(user.split('@')) > 1:
+ wap_client.system_select_domain(user.split('@')[1])
+
+ user_info = wap_client.user_find({'mail':user})
+
+ for (k,v) in user_info.iteritems():
+ print "%s: %r" % (k,v)
diff --git a/pykolab/cli/commands.py b/pykolab/cli/commands.py
index c559ac0..cb57160 100644
--- a/pykolab/cli/commands.py
+++ b/pykolab/cli/commands.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -56,15 +56,12 @@ def __init__():
register('help', list_commands)
register('list_users', not_yet_implemented, description="Not yet implemented")
- register('add_user', not_yet_implemented, description="Not yet implemented")
register('delete_user', not_yet_implemented, description="Not yet implemented")
register('list_groups', not_yet_implemented, description="Not yet implemented")
register('add_group', not_yet_implemented, description="Not yet implemented")
register('delete_group', not_yet_implemented, description="Not yet implemented")
- register('delete_domain', not_yet_implemented, description="Not yet implemented")
-
def list_commands(*args, **kw):
"""
List commands
diff --git a/pykolab/cli/sieve/cmd_list.py b/pykolab/cli/sieve/cmd_list.py
index e89a42e..2c2cb54 100644
--- a/pykolab/cli/sieve/cmd_list.py
+++ b/pykolab/cli/sieve/cmd_list.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/sieve/cmd_put.py b/pykolab/cli/sieve/cmd_put.py
index b514653..1b9514c 100644
--- a/pykolab/cli/sieve/cmd_put.py
+++ b/pykolab/cli/sieve/cmd_put.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/sieve/cmd_refresh.py b/pykolab/cli/sieve/cmd_refresh.py
index 87af982..496f31f 100644
--- a/pykolab/cli/sieve/cmd_refresh.py
+++ b/pykolab/cli/sieve/cmd_refresh.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/sieve/cmd_test.py b/pykolab/cli/sieve/cmd_test.py
index d396aa2..3fa0b8e 100644
--- a/pykolab/cli/sieve/cmd_test.py
+++ b/pykolab/cli/sieve/cmd_test.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/telemetry/cmd_examine_command_issue.py b/pykolab/cli/telemetry/cmd_examine_command_issue.py
index ec827a0..3e30d19 100644
--- a/pykolab/cli/telemetry/cmd_examine_command_issue.py
+++ b/pykolab/cli/telemetry/cmd_examine_command_issue.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/telemetry/cmd_examine_session.py b/pykolab/cli/telemetry/cmd_examine_session.py
index b9bbcad..f933dcb 100644
--- a/pykolab/cli/telemetry/cmd_examine_session.py
+++ b/pykolab/cli/telemetry/cmd_examine_session.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/telemetry/cmd_expire_sessions.py b/pykolab/cli/telemetry/cmd_expire_sessions.py
index a2c693a..92a1ab7 100644
--- a/pykolab/cli/telemetry/cmd_expire_sessions.py
+++ b/pykolab/cli/telemetry/cmd_expire_sessions.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/telemetry/cmd_list_sessions.py b/pykolab/cli/telemetry/cmd_list_sessions.py
index 4579ec5..f7b8c6e 100644
--- a/pykolab/cli/telemetry/cmd_list_sessions.py
+++ b/pykolab/cli/telemetry/cmd_list_sessions.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/cli/wap/__init__.py b/pykolab/cli/wap/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pykolab/cli/wap/__init__.py
diff --git a/pykolab/cli/wap/cmd_system_capabilities.py b/pykolab/cli/wap/cmd_system_capabilities.py
new file mode 100644
index 0000000..f56c55d
--- /dev/null
+++ b/pykolab/cli/wap/cmd_system_capabilities.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
+#
+# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
+#
+# 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; version 3 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 Library 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.
+#
+
+import sys
+
+import pykolab
+from pykolab.cli import commands
+
+from pykolab.translate import _
+
+log = pykolab.getLogger('pykolab.cli')
+conf = pykolab.getConf()
+
+def __init__():
+ commands.register('system_capabilities', execute, group='wap', description="Display the system capabilities.")
+
+def execute(*args, **kw):
+ from pykolab import wap_client
+ # Create the authentication object.
+ # TODO: Binds with superuser credentials!
+ wap_client.authenticate()
+ system_capabilities = wap_client.system_capabilities()
+
+ if system_capabilities['count'] < 1:
+ print "No system capabilities"
+ sys.exit(1)
+
+ for domain in system_capabilities['list'].keys():
+ print "Domain capabilities for %s" % (domain)
+
+ domain_capabilities = system_capabilities['list'][domain]
+
+ for service in domain_capabilities['actions'].keys():
+ print " %-15s - %r" % (service, domain_capabilities['actions'][service]['type'])
diff --git a/pykolab/cli/wap/cmd_user_types_list.py b/pykolab/cli/wap/cmd_user_types_list.py
new file mode 100644
index 0000000..eb8e2c4
--- /dev/null
+++ b/pykolab/cli/wap/cmd_user_types_list.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
+#
+# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
+#
+# 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; version 3 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 Library 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.
+#
+
+import pykolab
+from pykolab.cli import commands
+
+from pykolab.translate import _
+
+log = pykolab.getLogger('pykolab.cli')
+conf = pykolab.getConf()
+
+def __init__():
+ commands.register('list_user_types', execute, group='wap', description="List WAP user types.")
+
+def execute(*args, **kw):
+ from pykolab import wap_client
+ # Create the authentication object.
+ # TODO: Binds with superuser credentials!
+ wap_client.authenticate()
+ user_types = wap_client.user_types_list()
+
+ for user_type in user_types['list']:
+ type = user_types['list'][user_type]
+ print "%-15s - %s" % (type['key'], type['description'])
diff --git a/pykolab/conf/__init__.py b/pykolab/conf/__init__.py
index 29675ae..239c0dd 100644
--- a/pykolab/conf/__init__.py
+++ b/pykolab/conf/__init__.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -123,7 +123,7 @@ class Conf(object):
continue
for key in self.defaults.__dict__[section].keys():
- retval = False
+ retval = False
if not config.has_option(section, key):
continue
@@ -182,7 +182,7 @@ class Conf(object):
return
for key in config.options('testing'):
- retval = False
+ retval = False
if isinstance(self.defaults.__dict__['testing'][key], int):
value = config.getint('testing',key)
@@ -596,7 +596,7 @@ class Conf(object):
if value:
try:
from smtplib import SMTP
- self.use_mail = value
+ self.use_mail = value
return True
except ImportError:
log.error(_("No SMTP class found in the smtplib library."))
@@ -606,8 +606,8 @@ class Conf(object):
# Attempt to load the suite,
# Get the suite's options,
# Set them here.
- if not hasattr(self,'test_suites'):
- self.test_suites = []
+ if not hasattr(self,'test_suites'):
+ self.test_suites = []
if "zpush" in value:
selectively = False
diff --git a/pykolab/conf/defaults.py b/pykolab/conf/defaults.py
index e1e34ab..f85b594 100644
--- a/pykolab/conf/defaults.py
+++ b/pykolab/conf/defaults.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/conf/entitlement.py b/pykolab/conf/entitlement.py
index c726c1e..778781d 100644
--- a/pykolab/conf/entitlement.py
+++ b/pykolab/conf/entitlement.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/errors.py b/pykolab/errors.py
index d6547df..94efe0e 100644
--- a/pykolab/errors.py
+++ b/pykolab/errors.py
@@ -1,4 +1,4 @@
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/imap/__init__.py b/pykolab/imap/__init__.py
index adf0006..52dfdc1 100644
--- a/pykolab/imap/__init__.py
+++ b/pykolab/imap/__init__.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -111,6 +111,7 @@ class IMAP(object):
if conf.has_section(domain) and conf.has_option(domain, 'imap_uri'):
uri = conf.get(domain, 'imap_uri')
+ scheme = None
hostname = None
port = None
@@ -131,6 +132,11 @@ class IMAP(object):
if port == None:
port = 993
+ if scheme == None or scheme == "":
+ scheme = 'imaps'
+
+ uri = '%s://%s:%s' % (scheme, hostname, port)
+
# Get the credentials
admin_login = conf.get(backend, 'admin_login')
admin_password = conf.get(backend, 'admin_password')
@@ -167,7 +173,7 @@ class IMAP(object):
self._imap[hostname].logged_in = True
else:
- if not login and self._imap[hostname].logged_in == True:
+ if not login:
self.disconnect(hostname)
self.connect(uri=uri,login=False)
elif login and not hasattr(self._imap[hostname],'logged_in'):
@@ -193,7 +199,8 @@ class IMAP(object):
def disconnect(self, server=None):
if server == None:
# No server specified, but make sure self.imap is None anyways
- del self.imap
+ if hasattr(self, 'imap'):
+ del self.imap
else:
if self._imap.has_key(server):
del self._imap[server]
@@ -201,6 +208,8 @@ class IMAP(object):
log.warning(_("Called imap.disconnect() on a server that we had no connection to."))
def create_folder(self, folder_path, server=None):
+ folder_path = self.folder_utf7(folder_path)
+
if not server == None:
if not self._imap.has_key(server):
self.connect(server=server)
@@ -236,12 +245,26 @@ class IMAP(object):
else:
raise AttributeError, _("%r has no attribute %s") % (self,name)
+ def folder_utf7(self, folder):
+ from pykolab import imap_utf7
+ return imap_utf7.encode(folder)
+
+ def folder_utf8(self, folder):
+ from pykolab import imap_utf7
+ return imap_utf7.decode(folder)
+
def get_metadata(self, folder):
"""
Obtain all metadata entries on a folder
"""
+ metadata = {}
+
+ _metadata = self.imap.getannotation(self.folder_utf7(folder), '*')
- return self.imap.getannotation(folder, '*')
+ for (k,v) in _metadata.items():
+ metadata[self.folder_utf8(k)] = v
+
+ return metadata
def get_separator(self):
if not hasattr(self, 'imap') or self.imap == None:
@@ -305,7 +328,7 @@ class IMAP(object):
if short_rights.has_key(acl):
acl = short_rights[acl]
- self.imap.sam(folder, identifier, acl)
+ self.imap.sam(self.folder_utf7(folder), identifier, acl)
def set_metadata(self, folder, metadata_path, metadata_value, shared=True):
"""
@@ -321,7 +344,7 @@ class IMAP(object):
shared = False
metadata_path = metadata_path.replace('/private/', '/')
- self.imap._setannotation(folder, metadata_path, metadata_value, shared)
+ self.imap._setannotation(self.folder_utf7(folder), metadata_path, metadata_value, shared)
def shared_folder_create(self, folder_path, server=None):
"""
@@ -445,11 +468,21 @@ class IMAP(object):
admin_login = conf.get(backend, 'admin_login')
admin_password = conf.get(backend, 'admin_password')
- self.connect(login=False)
-
- self.login_plain(admin_login, admin_password, folder)
+ success = False
+ while not success:
+ try:
- (personal, other, shared) = self.namespaces()
+ self.disconnect()
+ self.connect(login=False)
+ self.login_plain(admin_login, admin_password, folder)
+ (personal, other, shared) = self.namespaces()
+ success = True
+ except Exception, errmsg:
+ log.debug(_("Waiting for the Cyrus murder to settle... %r") % (errmsg))
+ if conf.debuglevel > 8:
+ import traceback
+ traceback.print_exc()
+ time.sleep(0.5)
for additional_folder in additional_folders.keys():
_add_folder = {}
@@ -461,9 +494,12 @@ class IMAP(object):
folder_name = "%s%s" % (personal, folder_name)
try:
- self.imap.cm(folder_name)
+ self.create_folder(folder_name)
except:
log.warning(_("Mailbox already exists: %s") % (folder_name))
+ if conf.debuglevel > 8:
+ import traceback
+ traceback.print_exc()
continue
if additional_folders[additional_folder].has_key("annotations"):
@@ -608,8 +644,8 @@ class IMAP(object):
"""
Check if the environment has a folder named folder.
"""
- folders = self.imap.lm(folder)
- log.debug(_("Looking for folder '%s', we found folders: %r") % (folder,folders), level=8)
+ folders = self.imap.lm(self.folder_utf7(folder))
+ log.debug(_("Looking for folder '%s', we found folders: %r") % (folder,[self.folder_utf8(x) for x in folders]), level=8)
# Greater then one, this folder may have subfolders.
if len(folders) > 0:
return True
@@ -636,7 +672,7 @@ class IMAP(object):
"%s") % (rights,subject,folder), level=8)
self.set_acl(
- folder,
+ self.folder_utf7(folder),
"%s" % (subject),
"%s" % (rights)
)
@@ -647,7 +683,7 @@ class IMAP(object):
"%s") % (rights,subject,folder), level=8)
self.set_acl(
- folder,
+ self.folder_utf7(folder),
"%s" % (subject),
""
)
@@ -872,22 +908,25 @@ class IMAP(object):
log.info(_("Deleting folder %s") % (mailfolder_path))
- self.imap.dm(mailfolder_path)
+ self.imap.dm(self.folder_utf7(mailfolder_path))
def get_quota(self, mailfolder_path):
try:
- return self.lq(mailfolder_path)
+ return self.lq(self.folder_utf7(mailfolder_path))
except:
return
def get_quota_root(self, mailfolder_path):
- return self.lqr(mailfolder_path)
+ return self.lqr(self.folder_utf7(mailfolder_path))
def list_acls(self, folder):
"""
List the ACL entries on a folder
"""
- return self.imap.lam(folder)
+ return self.imap.lam(self.folder_utf7(folder))
+
+ def list_folders(self, pattern):
+ return [self.folder_utf8(x) for x in self.lm(self.folder_utf7(pattern))]
def list_user_folders(self, primary_domain=None, secondary_domains=[]):
"""
diff --git a/pykolab/imap/cyrus.py b/pykolab/imap/cyrus.py
index 079c4dc..6881740 100644
--- a/pykolab/imap/cyrus.py
+++ b/pykolab/imap/cyrus.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -193,6 +193,14 @@ class Cyrus(cyruslib.CYRUS):
return server
+ def folder_utf7(self, folder):
+ from pykolab import imap_utf7
+ return imap_utf7.encode(folder)
+
+ def folder_utf8(self, folder):
+ from pykolab import imap_utf7
+ return imap_utf7.decode(folder)
+
def _setquota(self, mailfolder, quota):
"""
Login to the actual backend server.
@@ -367,7 +375,7 @@ class Cyrus(cyruslib.CYRUS):
# but it still would not cover all cases.
#
- # If no folders where found... well... then there you go.
+ # If no folders were found... well... then there you go.
if len(folders) < 1:
return None
diff --git a/pykolab/imap_utf7.py b/pykolab/imap_utf7.py
new file mode 100644
index 0000000..038623b
--- /dev/null
+++ b/pykolab/imap_utf7.py
@@ -0,0 +1,91 @@
+# The contents of this file has been derived code from the Twisted project
+# (http://twistedmatrix.com/). The original author is Jp Calderone.
+
+# Twisted project license follows:
+
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+class FolderNameError(ValueError):
+ pass
+
+
+def encode(s):
+ if isinstance(s, str) and sum(n for n in (ord(c) for c in s) if n > 127):
+ try:
+ s = unicode(s, "UTF-8")
+ except Exception, errmsg:
+ raise FolderNameError("%r contains characters not valid in a str folder name. "
+ "Convert to unicode first?" % s)
+
+ r = []
+ _in = []
+ for c in s:
+ if ord(c) in (range(0x20, 0x26) + range(0x27, 0x7f)):
+ if _in:
+ r.extend(['&', modified_base64(''.join(_in)), '-'])
+ del _in[:]
+ r.append(str(c))
+ elif c == '&':
+ if _in:
+ r.extend(['&', modified_base64(''.join(_in)), '-'])
+ del _in[:]
+ r.append('&-')
+ else:
+ _in.append(c)
+ if _in:
+ r.extend(['&', modified_base64(''.join(_in)), '-'])
+
+ return ''.join(r)
+
+
+def decode(s):
+ r = []
+ decode = []
+ for c in s:
+ if c == '&' and not decode:
+ decode.append('&')
+ elif c == '-' and decode:
+ if len(decode) == 1:
+ r.append('&')
+ else:
+ r.append(modified_unbase64(''.join(decode[1:])))
+ decode = []
+ elif decode:
+ decode.append(c)
+ else:
+ r.append(c)
+ if decode:
+ r.append(modified_unbase64(''.join(decode[1:])))
+ out = ''.join(r)
+
+ if not isinstance(out, unicode):
+ out = unicode(out, 'latin-1')
+ return out
+
+
+def modified_base64(s):
+ s_utf7 = s.encode('utf-7')
+ return s_utf7[1:-1].replace('/', ',')
+
+
+def modified_unbase64(s):
+ s_utf7 = '+' + s.replace(',', '/') + '-'
+ return s_utf7.decode('utf-7')
diff --git a/pykolab/logger.py b/pykolab/logger.py
index c812261..6f82d5d 100644
--- a/pykolab/logger.py
+++ b/pykolab/logger.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -41,7 +41,11 @@ class Logger(logging.Logger):
if hasattr(sys, 'argv'):
for arg in sys.argv:
if debuglevel == -1:
- debuglevel = int(arg)
+ try:
+ debuglevel = int(arg)
+ except ValueError, errmsg:
+ continue
+
loglevel = logging.DEBUG
break
diff --git a/pykolab/plugins/__init__.py b/pykolab/plugins/__init__.py
index d0ba88e..c85ab0e 100644
--- a/pykolab/plugins/__init__.py
+++ b/pykolab/plugins/__init__.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/plugins/defaultfolders/__init__.py b/pykolab/plugins/defaultfolders/__init__.py
index cee1b02..45c63e8 100644
--- a/pykolab/plugins/defaultfolders/__init__.py
+++ b/pykolab/plugins/defaultfolders/__init__.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/plugins/dynamicquota/__init__.py b/pykolab/plugins/dynamicquota/__init__.py
index 62823ff..af67421 100644
--- a/pykolab/plugins/dynamicquota/__init__.py
+++ b/pykolab/plugins/dynamicquota/__init__.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/plugins/recipientpolicy/__init__.py b/pykolab/plugins/recipientpolicy/__init__.py
index e3d6b65..6ca70ef 100644
--- a/pykolab/plugins/recipientpolicy/__init__.py
+++ b/pykolab/plugins/recipientpolicy/__init__.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -77,9 +77,10 @@ class KolabRecipientpolicy(object):
return mail
except KeyError, e:
log.warning(_("Attribute substitution for 'mail' failed in Recipient Policy"))
- mail = utils.translate(user_attrs['mail'], user_attrs['preferredlanguage'])
- mail = mail.lower()
- return mail
+ if user_attrs.has_key('mail'):
+ return user_attrs['mail']
+ else:
+ return None
def set_secondary_mail(self, *args, **kw):
"""
@@ -120,7 +121,14 @@ class KolabRecipientpolicy(object):
_domains = [ kw['primary_domain'] ] + kw['secondary_domains']
for attr in [ 'givenname', 'sn', 'surname' ]:
- user_attrs[attr] = utils.translate(user_attrs[attr], user_attrs['preferredlanguage'])
+ try:
+ user_attrs[attr] = utils.translate(user_attrs[attr], user_attrs['preferredlanguage'])
+ except Exception, errmsg:
+ log.error(_("An error occurred in composing the secondary mail attribute for entry %r") % (user_attrs['id']))
+ if conf.debuglevel > 8:
+ import traceback
+ traceback.print_exc()
+ return []
for number in alternative_mail_routines.keys():
for routine in alternative_mail_routines[number].keys():
@@ -130,8 +138,12 @@ class KolabRecipientpolicy(object):
log.debug(_("Appending additional mail address: %s") % (retval), level=8)
alternative_mail.append(retval)
- except KeyError, e:
- log.warning(_("Attribute substitution for 'alternative_mail' failed in Recipient Policy"))
+ except Exception, errmsg:
+ log.error(_("Policy for secondary email address failed: %r") % (errmsg))
+ if conf.debuglevel > 8:
+ import traceback
+ traceback.print_exc()
+ return []
for _domain in kw['secondary_domains']:
user_attrs['domain'] = _domain
diff --git a/pykolab/plugins/sievemgmt/__init__.py b/pykolab/plugins/sievemgmt/__init__.py
index 6395f2f..32dbdf5 100644
--- a/pykolab/plugins/sievemgmt/__init__.py
+++ b/pykolab/plugins/sievemgmt/__init__.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/setup/__init__.py b/pykolab/setup/__init__.py
index 2d9fafe..c238177 100644
--- a/pykolab/setup/__init__.py
+++ b/pykolab/setup/__init__.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/setup/components.py b/pykolab/setup/components.py
index a51c416..b22a79a 100644
--- a/pykolab/setup/components.py
+++ b/pykolab/setup/components.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/setup/setup_freebusy.py b/pykolab/setup/setup_freebusy.py
index 9d99ca9..7c0df1d 100644
--- a/pykolab/setup/setup_freebusy.py
+++ b/pykolab/setup/setup_freebusy.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -17,9 +17,8 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
-from Cheetah.Template import Template
+from ConfigParser import RawConfigParser
import os
-import subprocess
import sys
import time
@@ -39,92 +38,44 @@ def __init__():
'freebusy',
execute,
description=description(),
- after=['mysql','ldap', 'roundcube']
+ after=['ldap']
)
def description():
return _("Setup Free/Busy.")
def execute(*args, **kw):
- if not os.path.isfile('/etc/kolab/freebusy/config.php'):
+ if not os.path.isfile('/etc/kolab-freebusy/config.ini') and not os.path.isfile('/etc/kolab-freebusy/config.ini.sample'):
log.error(_("Free/Busy is not installed on this system"))
return
- if not hasattr(conf, 'mysql_roundcube_password'):
- print >> sys.sdterr, utils.multiline_message(
- _("""
- Please supply the MySQL password for the 'roundcube'
- user. You have supplied this password earlier, and it is
- available from the database URI setting in
- /etc/roundcubemail/db.inc.php.
- """)
- )
-
- conf.mysql_roundcube_password = utils.ask_question(
- _("MySQL roundcube password"),
- password=True,
- confirm=True
- )
+ if not os.path.isfile('/etc/kolab-freebusy/config.ini'):
+ os.rename('/etc/kolab-freebusy/config.ini.sample', '/etc/kolab-freebusy/config.ini')
freebusy_settings = {
- 'ldap_base_dn': conf.get('ldap', 'base_dn'),
- 'ldap_ldap_uri': conf.get('ldap', 'ldap_uri'),
- 'ldap_service_bind_dn': conf.get('ldap', 'service_bind_dn'),
- 'ldap_service_bind_pw': conf.get('ldap', 'service_bind_pw'),
- 'primary_domain': conf.get('kolab', 'primary_domain'),
- 'mysql_roundcube_password': conf.mysql_roundcube_password
+ 'directory "kolab-ldap"': {
+ 'host': conf.get('ldap', 'ldap_uri'),
+ 'base_dn': conf.get('ldap', 'base_dn'),
+ 'bind_dn': conf.get('ldap', 'service_bind_dn'),
+ 'bind_pw': conf.get('ldap', 'service_bind_pw'),
+ 'fbsource': 'file:/var/lib/kolab-freebusy/%mail.ifb',
+ },
+ 'httpauth': {
+ }
}
- want_files = [
- 'config.php',
- ]
-
- for want_file in want_files:
- template_file = None
- if os.path.isfile('/etc/kolab/templates/freebusy/%s.tpl' % (want_file)):
- template_file = '/etc/kolab/templates/freebusy/%s.tpl' % (want_file)
- elif os.path.isfile('/usr/share/kolab/templates/freebusy/%s.tpl' % (want_file)):
- template_file = '/usr/share/kolab/templates/freebusy/%s.tpl' % (want_file)
- elif os.path.isfile(os.path.abspath(os.path.join(__file__, '..', '..', '..', 'share', 'templates', 'freebusy', '%s.tpl' % (want_file)))):
- template_file = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'share', 'templates', 'freebusy', '%s.tpl' % (want_file)))
-
- if not template_file == None:
- log.debug(_("Using template file %r") % (template_file), level=8)
- fp = open(template_file, 'r')
- template_definition = fp.read()
- fp.close()
-
- t = Template(template_definition, searchList=[freebusy_settings])
- log.debug(
- _("Successfully compiled template %r, writing out to %r") % (
- template_file,
- '/etc/kolab/freebusy/%s' % (want_file)
- ),
- level=8
- )
-
- fp = open('/etc/kolab/freebusy/%s' % (want_file), 'w')
- fp.write(t.__str__())
- fp.close()
+ cfg_parser = RawConfigParser()
+ cfg_parser.read('/etc/kolab-freebusy/config.ini')
- time.sleep(2)
+ for section in freebusy_settings.keys():
+ if len(freebusy_settings[section].keys()) < 1:
+ cfg_parser.remove_section(section)
+ continue
- if os.path.isfile('/bin/systemctl'):
- subprocess.call(['/bin/systemctl', 'restart', 'httpd.service'])
- elif os.path.isfile('/sbin/service'):
- subprocess.call(['/sbin/service', 'httpd', 'restart'])
- elif os.path.isfile('/usr/sbin/service'):
- subprocess.call(['/usr/sbin/service','apache2','restart'])
- else:
- log.error(_("Could not start the webserver server service."))
+ for key in freebusy_settings[section].keys():
+ cfg_parser.set(section, key, freebusy_settings[section][key])
- if os.path.isfile('/bin/systemctl'):
- subprocess.call(['/bin/systemctl', 'enable', 'httpd.service'])
- elif os.path.isfile('/sbin/chkconfig'):
- subprocess.call(['/sbin/chkconfig', 'httpd', 'on'])
- elif os.path.isfile('/usr/sbin/update-rc.d'):
- subprocess.call(['/usr/sbin/update-rc.d', 'apache2', 'defaults'])
- else:
- log.error(_("Could not configure to start on boot, the " + \
- "webserver server service."))
+ fp = open('/etc/kolab-freebusy/config.ini', "w+")
+ cfg_parser.write(fp)
+ fp.close()
diff --git a/pykolab/setup/setup_imap.py b/pykolab/setup/setup_imap.py
index 4b7564f..292c891 100644
--- a/pykolab/setup/setup_imap.py
+++ b/pykolab/setup/setup_imap.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/setup/setup_kolabd.py b/pykolab/setup/setup_kolabd.py
index 47d1cae..4534502 100644
--- a/pykolab/setup/setup_kolabd.py
+++ b/pykolab/setup/setup_kolabd.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/setup/setup_ldap.py b/pykolab/setup/setup_ldap.py
index a7cedba..f6576f1 100644
--- a/pykolab/setup/setup_ldap.py
+++ b/pykolab/setup/setup_ldap.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -60,6 +60,30 @@ def cli_options():
help = _("Allow anonymous binds (default: no).")
)
+ ldap_group.add_option(
+ "--without-ldap",
+ dest = "without_ldap",
+ action = "store_true",
+ default = False,
+ help = _("Skip setting up the LDAP server.")
+ )
+
+ ldap_group.add_option(
+ "--with-openldap",
+ dest = "with_openldap",
+ action = "store_true",
+ default = False,
+ help = _("Setup configuration for OpenLDAP compatibility.")
+ )
+
+ ldap_group.add_option(
+ "--with-ad",
+ dest = "with_ad",
+ action = "store_true",
+ default = False,
+ help = _("Setup configuration for Active Directory compatibility.")
+ )
+
def description():
return _("Setup LDAP.")
@@ -69,6 +93,60 @@ def execute(*args, **kw):
if not conf.config_file == conf.defaults.config_file:
ask_questions = False
+ if conf.without_ldap:
+ print >> sys.stderr, _("Skipping setup of LDAP, as specified")
+ return
+
+ _input = {}
+
+ if conf.with_openldap and not conf.with_ad:
+
+ conf.command_set('ldap', 'unique_attribute', 'entryuuid')
+
+ fp = open(conf.defaults.config_file, "w+")
+ conf.cfg_parser.write(fp)
+ fp.close()
+
+ return
+
+ elif conf.with_ad and not conf.with_openldap:
+ conf.command_set('ldap', 'auth_attributes', 'samaccountname')
+ conf.command_set('ldap', 'modifytimestamp_format', '%%Y%%m%%d%%H%%M%%S.0Z')
+ conf.command_set('ldap', 'unique_attribute', 'userprincipalname')
+
+ # TODO: These attributes need to be checked
+ conf.command_set('ldap', 'mail_attributes', 'mail')
+ conf.command_set('ldap', 'mailserver_attributes', 'mailhost')
+ conf.command_set('ldap', 'quota_attribute', 'mailquota')
+
+ return
+
+ elif conf.with_ad and conf.with_openldap:
+ print >> sys.stderr, utils.multiline_message(
+ _("""
+ You can not configure Kolab to run against OpenLDAP
+ and Active Directory simultaneously.
+ """)
+ )
+
+ sys.exit(1)
+
+ # Pre-execution checks
+ for path, directories, files in os.walk('/etc/dirsrv/'):
+ for direct in directories:
+ if direct.startswith('slapd-'):
+ print >> sys.stderr, utils.multiline_message(
+ _("""
+ It seems 389 Directory Server has an existing
+ instance configured. This setup script does not
+ intend to destroy or overwrite your data. Please
+ make sure /etc/dirsrv/ and /var/lib/dirsrv/ are
+ clean so that this setup does not have to worry.
+ """)
+ )
+
+ sys.exit(1)
+
_input = {}
if ask_questions:
@@ -147,7 +225,6 @@ def execute(*args, **kw):
_input['fqdn'] = fqdn
_input['hostname'] = hostname.split('.')[0]
_input['domain'] = domainname
-
_input['nodotdomain'] = _input['domain'].replace('.','_')
_input['rootdn'] = utils.standard_root_dn(_input['domain'])
@@ -272,7 +349,24 @@ ServerAdminPwd = %(admin_pass)s
(stdoutdata, stderrdata) = setup_389.communicate()
- # TODO: Get the return code and display output if not successful.
+ if not setup_389.returncode == 0:
+ print >> sys.stderr, utils.multiline_message(
+ _("""
+ An error was detected in the setup procedure for 389
+ Directory Server. This setup will write out stderr and
+ stdout to /var/log/kolab/setup.error.log and
+ /var/log/kolab/setup.out.log respectively, before it
+ exits.
+ """)
+ )
+
+ fp = open('/var/log/kolab/setup.error.log', 'w')
+ fp.write(stderrdata)
+ fp.close()
+
+ fp = open('/var/log/kolab/setup.out.log', 'w')
+ fp.write(stderrdata)
+ fp.close()
log.debug(_("Setup DS stdout:"), level=8)
log.debug(stdoutdata, level=8)
@@ -280,9 +374,8 @@ ServerAdminPwd = %(admin_pass)s
log.debug(_("Setup DS stderr:"), level=8)
log.debug(stderrdata, level=8)
- # TODO: Fails when ran a second time.
-
- # TODO: When fail, fail gracefully.
+ if not setup_389.returncode == 0:
+ sys.exit(1)
# Find the kolab schema. It's installed as %doc in the kolab-schema package.
# TODO: Chown nobody, nobody, chmod 440
@@ -301,6 +394,7 @@ ServerAdminPwd = %(admin_pass)s
os.path.basename(schema_file)
)
)
+
schema_error = False
except:
log.error(_("Could not copy the LDAP extensions for Kolab"))
@@ -561,7 +655,7 @@ ServerAdminPwd = %(admin_pass)s
aci.append('(targetattr="*")(version 3.0; acl "Configuration Administrators Group"; allow (all) groupdn="ldap:///cn=Configuration Administrators,ou=Groups,ou=TopologyManagement,o=NetscapeRoot";)')
aci.append('(targetattr="*")(version 3.0; acl "Configuration Administrator"; allow (all) userdn="ldap:///uid=admin,ou=Administrators,ou=TopologyManagement,o=NetscapeRoot";)')
aci.append('(targetattr = "*")(version 3.0; acl "SIE Group"; allow (all) groupdn = "ldap:///cn=slapd-%(hostname)s,cn=389 Directory Server,cn=Server Group,cn=%(fqdn)s,ou=%(domain)s,o=NetscapeRoot";)' %(_input))
- aci.append('(targetattr = "*") (version 3.0;acl "Search Access";allow (read,compare,search)(userdn = "ldap:///all");)')
+ aci.append('(targetattr != "userPassword") (version 3.0;acl "Search Access";allow (read,compare,search)(userdn = "ldap:///all");)')
modlist = []
modlist.append((ldap.MOD_REPLACE, "aci", aci))
auth._auth.ldap.modify_s(dn, modlist)
@@ -575,3 +669,4 @@ ServerAdminPwd = %(admin_pass)s
else:
log.error(_("Could not start and configure to start on boot, the " + \
"directory server admin service."))
+
diff --git a/pykolab/setup/setup_mta.py b/pykolab/setup/setup_mta.py
index 35df4fb..9280d18 100644
--- a/pykolab/setup/setup_mta.py
+++ b/pykolab/setup/setup_mta.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -52,6 +52,8 @@ def execute(*args, **kw):
resource_filter = conf.get('ldap', 'resource_filter')
+ sharedfolder_filter = conf.get('ldap', 'sharedfolder_filter')
+
server_host = utils.parse_ldap_uri(conf.get('ldap', 'ldap_uri'))[1]
files = {
@@ -67,7 +69,7 @@ domain = ldap:/etc/postfix/ldap/mydestination.cf
bind_dn = %(service_bind_dn)s
bind_pw = %(service_bind_pw)s
-query_filter = (&(|(mail=%%s)(alias=%%s))(|%(kolab_user_filter)s%(kolab_group_filter)s%(resource_filter)s))
+query_filter = (&(|(mail=%%s)(alias=%%s))(|%(kolab_user_filter)s%(kolab_group_filter)s%(resource_filter)s%(sharedfolder_filter)s))
result_attribute = mail
""" % {
"base_dn": conf.get('ldap', 'base_dn'),
@@ -77,6 +79,7 @@ result_attribute = mail
"kolab_user_filter": user_filter,
"kolab_group_filter": group_filter,
"resource_filter": resource_filter,
+ "sharedfolder_filter": sharedfolder_filter,
},
"/etc/postfix/ldap/mydestination.cf": """
server_host = %(server_host)s
@@ -111,7 +114,7 @@ bind_dn = %(service_bind_dn)s
bind_pw = %(service_bind_pw)s
# This finds the mail enabled distribution group LDAP entry
-query_filter = (&(mail=%%s)(objectClass=kolabgroupofuniquenames)(objectclass=groupofuniquenames))
+query_filter = (&(|(mail=%%s)(alias=%%s))(objectClass=kolabgroupofuniquenames)(objectclass=groupofuniquenames)(!(objectclass=groupofurls)))
# From this type of group, get all uniqueMember DNs
special_result_attribute = uniqueMember
# Only from those DNs, get the mail
@@ -136,7 +139,7 @@ bind_dn = %(service_bind_dn)s
bind_pw = %(service_bind_pw)s
# This finds the mail enabled dynamic distribution group LDAP entry
-query_filter = (&(mail=%%s)(objectClass=kolabgroupofuniquenames)(objectClass=groupOfURLs))
+query_filter = (&(|(mail=%%s)(alias=%%s))(objectClass=kolabgroupofuniquenames)(objectClass=groupOfURLs))
# From this type of group, get all memberURL searches/references
special_result_attribute = memberURL
# Only from those DNs, get the mail
@@ -189,6 +192,27 @@ result_attribute = mail
"service_bind_dn": conf.get('ldap', 'service_bind_dn'),
"service_bind_pw": conf.get('ldap', 'service_bind_pw'),
},
+ "/etc/postfix/ldap/virtual_alias_maps_sharedfolders.cf": """
+server_host = %(server_host)s
+server_port = 389
+version = 3
+search_base = %(base_dn)s
+scope = sub
+
+domain = ldap:/etc/postfix/ldap/mydestination.cf
+
+bind_dn = %(service_bind_dn)s
+bind_pw = %(service_bind_pw)s
+
+query_filter = (&(|(mail=%%s)(alias=%%s))(objectclass=kolabsharedfolder))
+result_attribute = kolabtargetfolder
+result_format = shared+%%s
+""" % {
+ "base_dn": conf.get('ldap', 'base_dn'),
+ "server_host": server_host,
+ "service_bind_dn": conf.get('ldap', 'service_bind_dn'),
+ "service_bind_pw": conf.get('ldap', 'service_bind_pw'),
+ },
}
if not os.path.isdir('/etc/postfix/ldap'):
@@ -199,13 +223,22 @@ result_attribute = mail
fp.write(files[filename])
fp.close()
+ fp = open('/etc/postfix/transport', 'a')
+ fp.write("\n# Shared Folder Delivery for %(domain)s:\nshared@%(domain)s\t\tlmtp:unix:/var/lib/imap/socket/lmtp\n" % {'domain': conf.get('kolab', 'primary_domain')})
+ fp.close()
+
+ subprocess.call(["postmap", "/etc/postfix/transport"])
+
postfix_main_settings = {
"inet_interfaces": "all",
+ "recipient_delimiter": "+",
"local_recipient_maps": "ldap:/etc/postfix/ldap/local_recipient_maps.cf",
"mydestination": "ldap:/etc/postfix/ldap/mydestination.cf",
- "transport_maps": "ldap:/etc/postfix/ldap/transport_maps.cf",
- "virtual_alias_maps": "$alias_maps, ldap:/etc/postfix/ldap/virtual_alias_maps.cf, ldap:/etc/postfix/ldap/mailenabled_distgroups.cf, ldap:/etc/postfix/ldap/mailenabled_dynamic_distgroups.cf",
+ "transport_maps": "ldap:/etc/postfix/ldap/transport_maps.cf, hash:/etc/postfix/transport",
+ "virtual_alias_maps": "$alias_maps, ldap:/etc/postfix/ldap/virtual_alias_maps.cf, ldap:/etc/postfix/ldap/virtual_alias_maps_sharedfolders.cf, ldap:/etc/postfix/ldap/mailenabled_distgroups.cf, ldap:/etc/postfix/ldap/mailenabled_dynamic_distgroups.cf",
"smtpd_tls_auth_only": "yes",
+ "smtpd_tls_security_level": "may",
+ "smtp_tls_security_level": "may",
"smtpd_sasl_auth_enable": "yes",
"smtpd_sender_login_maps": "$relay_recipient_maps",
"smtpd_sender_restrictions": "permit_mynetworks, reject_sender_login_mismatch",
@@ -232,6 +265,19 @@ result_attribute = mail
'/etc/postfix/main.cf'
)
+ # Copy header checks files
+ for hc_file in [ 'inbound', 'internal', 'submission' ]:
+ if not os.path.isfile("/etc/postfix/header_checks.%s" % (hc_file)):
+ if os.path.isfile('/etc/kolab/templates/header_checks.%s' % (hc_file)):
+ input_file = '/etc/kolab/templates/header_checks.%s' % (hc_file)
+ elif os.path.isfile('/usr/share/kolab/templates/header_checks.%s' % (hc_file)):
+ input_file = '/usr/share/kolab/templates/header_checks.%s' % (hc_file)
+ elif os.path.isfile(os.path.abspath(os.path.join(__file__, '..', '..', '..', 'share', 'templates', 'header_checks.%s' % (hc_file)))):
+ input_file = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'share', 'templates', 'header_checks.%s' % (hc_file)))
+
+ shutil.copy(input_file, "/etc/postfix/header_checks.%s" % (hc_file))
+ subprocess.call(["postmap", "/etc/postfix/header_checks.%s" % (hc_file)])
+
myaugeas = Augeas()
setting_base = '/files/etc/postfix/main.cf/'
@@ -241,9 +287,12 @@ result_attribute = mail
current_value = myaugeas.get(setting)
if current_value == None:
- insert_paths = myaugeas.match('/files/etc/postfix/main.cf/*')
- insert_path = insert_paths[(len(insert_paths)-1)]
- myaugeas.insert(insert_path, setting_key, False)
+ try:
+ myaugeas.set(setting, postfix_main_settings[setting_key])
+ except:
+ insert_paths = myaugeas.match('/files/etc/postfix/main.cf/*')
+ insert_path = insert_paths[(len(insert_paths)-1)]
+ myaugeas.insert(insert_path, setting_key, False)
log.debug(_("Setting key %r to %r") % (setting_key, postfix_main_settings[setting_key]), level=8)
myaugeas.set(setting, postfix_main_settings[setting_key])
diff --git a/pykolab/setup/setup_mysql.py b/pykolab/setup/setup_mysql.py
index 1c5fd0c..4b2e8c2 100644
--- a/pykolab/setup/setup_mysql.py
+++ b/pykolab/setup/setup_mysql.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/setup/setup_php.py b/pykolab/setup/setup_php.py
index 54915a5..34246f9 100644
--- a/pykolab/setup/setup_php.py
+++ b/pykolab/setup/setup_php.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/setup/setup_roundcube.py b/pykolab/setup/setup_roundcube.py
index 1c1c60c..7536ce2 100644
--- a/pykolab/setup/setup_roundcube.py
+++ b/pykolab/setup/setup_roundcube.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -90,11 +90,11 @@ def execute(*args, **kw):
want_files = [
'acl.inc.php',
'calendar.inc.php',
- 'db.inc.php',
+ 'config.inc.php',
'kolab_auth.inc.php',
+ 'kolab_files.inc.php',
'kolab_folders.inc.php',
'kolab.inc.php',
- 'main.inc.php',
'managesieve.inc.php',
'owncloud.inc.php',
'password.inc.php',
diff --git a/pykolab/setup/setup_syncroton.py b/pykolab/setup/setup_syncroton.py
index c14682e..f902f57 100644
--- a/pykolab/setup/setup_syncroton.py
+++ b/pykolab/setup/setup_syncroton.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/setup/setup_zpush.py b/pykolab/setup/setup_zpush.py
deleted file mode 100644
index 809d243..0000000
--- a/pykolab/setup/setup_zpush.py
+++ /dev/null
@@ -1,109 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
-#
-# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
-#
-# 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; version 3 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 Library 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.
-#
-
-from Cheetah.Template import Template
-import os
-import subprocess
-import sys
-import time
-
-import components
-
-import pykolab
-
-from pykolab import utils
-from pykolab.constants import *
-from pykolab.translate import _
-
-log = pykolab.getLogger('pykolab.setup')
-conf = pykolab.getConf()
-
-def __init__():
- components.register('zpush', execute, description=description(), after=['mysql','ldap'])
-
-def description():
- return _("Setup zpush.")
-
-def execute(*args, **kw):
- if not os.path.isfile('/etc/z-push/config.php'):
- log.error(_("Z-Push is not installed on this system"))
- return
-
- zpush_settings = {
- 'ldap_base_dn': conf.get('ldap', 'base_dn'),
- 'ldap_ldap_uri': conf.get('ldap', 'ldap_uri'),
- 'ldap_service_bind_dn': conf.get('ldap', 'service_bind_dn'),
- 'ldap_service_bind_pw': conf.get('ldap', 'service_bind_pw'),
- 'imap_server': "localhost"
- }
-
-
- want_files = [
- 'config.php',
- ]
-
- for want_file in want_files:
- template_file = None
- if os.path.isfile('/etc/kolab/templates/zpush/%s.tpl' % (want_file)):
- template_file = '/etc/kolab/templates/zpush/%s.tpl' % (want_file)
- elif os.path.isfile('/usr/share/kolab/templates/zpush/%s.tpl' % (want_file)):
- template_file = '/usr/share/kolab/templates/zpush/%s.tpl' % (want_file)
- elif os.path.isfile(os.path.abspath(os.path.join(__file__, '..', '..', '..', 'share', 'templates', 'zpush', '%s.tpl' % (want_file)))):
- template_file = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'share', 'templates', 'zpush', '%s.tpl' % (want_file)))
-
- if not template_file == None:
- log.debug(_("Using template file %r") % (template_file), level=8)
- fp = open(template_file, 'r')
- template_definition = fp.read()
- fp.close()
-
- t = Template(template_definition, searchList=[zpush_settings])
- log.debug(
- _("Successfully compiled template %r, writing out to %r") % (
- template_file,
- '/etc/z-push/%s' % (want_file)
- ),
- level=8
- )
-
- fp = open('/etc/z-push/%s' % (want_file), 'w')
- fp.write(t.__str__())
- fp.close()
-
- time.sleep(2)
-
- if os.path.isfile('/bin/systemctl'):
- subprocess.call(['/bin/systemctl', 'restart', 'httpd.service'])
- elif os.path.isfile('/sbin/service'):
- subprocess.call(['/sbin/service', 'httpd', 'restart'])
- elif os.path.isfile('/usr/sbin/service'):
- subprocess.call(['/usr/sbin/service','apache2','restart'])
- else:
- log.error(_("Could not start the webserver server service."))
-
- if os.path.isfile('/bin/systemctl'):
- subprocess.call(['/bin/systemctl', 'enable', 'httpd.service'])
- elif os.path.isfile('/sbin/chkconfig'):
- subprocess.call(['/sbin/chkconfig', 'httpd', 'on'])
- elif os.path.isfile('/usr/sbin/update-rc.d'):
- subprocess.call(['/usr/sbin/update-rc.d', 'apache2', 'defaults'])
- else:
- log.error(_("Could not configure to start on boot, the " + \
- "webserver server service."))
-
diff --git a/pykolab/telemetry.py b/pykolab/telemetry.py
index 66bd1ae..1a8eea4 100644
--- a/pykolab/telemetry.py
+++ b/pykolab/telemetry.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/translate.py b/pykolab/translate.py
index 76f50b3..0a4bef2 100644
--- a/pykolab/translate.py
+++ b/pykolab/translate.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/translit.py b/pykolab/translit.py
index 119675f..855e249 100644
--- a/pykolab/translit.py
+++ b/pykolab/translit.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/pykolab/utils.py b/pykolab/utils.py
index c10bbb2..5cba8f9 100644
--- a/pykolab/utils.py
+++ b/pykolab/utils.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -21,6 +21,7 @@ import getpass
import grp
import os
import pwd
+import struct
import sys
import pykolab
@@ -126,11 +127,21 @@ def ask_confirmation(question, default="y", all_inclusive_no=True):
else:
return True
-def ask_menu(question, options={}):
- print question
+def ask_menu(question, options={}, default=''):
+ if not default == '':
+ print question + " [" + default + "]:"
+ else:
+ print question
+
answer_correct = False
max_key_length = 0
+ if isinstance(options, list):
+ _options = options
+ options = {}
+ for key in _options:
+ options[key] = key
+
keys = options.keys()
keys.sort()
@@ -142,10 +153,29 @@ def ask_menu(question, options={}):
str_format = "%%%ds" % max_key_length
- for key in keys:
- print " - " + eval("str_format % key") + ": " + options[key]
+ if default == '' or not default in options.keys():
+ for key in keys:
+ if options[key] == key:
+ print " - " + key
+ else:
+ print " - " + eval("str_format % key") + ": " + options[key]
+
+ answer = raw_input(_("Choice") + ": ")
- answer = raw_input(_("Choice") + ": ")
+ else:
+ answer = raw_input(_("Choice (type '?' for options)") + ": ")
+
+ if answer == '?':
+ for key in keys:
+ if options[key] == key:
+ print " - " + key
+ else:
+ print " - " + eval("str_format % key") + ": " + options[key]
+
+ continue
+
+ if answer == '' and default in options.keys():
+ answer = default
if answer in [str(x) for x in options.keys()]:
answer_correct = True
@@ -271,20 +301,29 @@ def normalize(_object):
if type(_object[key]) == list:
if _object[key] == None:
continue
+
if len(_object[key]) == 1:
result[key.lower()] = ''.join(_object[key])
else:
result[key.lower()] = _object[key]
+
else:
if _object[key] == None:
continue
+
# What the heck?
result[key.lower()] = _object[key]
+ if result.has_key('objectsid') and not result['objectsid'][0] == "S":
+ result['objectsid'] = sid_to_string(result['objectsid'])
+
if result.has_key('sn'):
result['surname'] = result['sn'].replace(' ', '')
if result.has_key('mail'):
+ if isinstance(result['mail'], list):
+ result['mail'] = result['mail'][0]
+
if len(result['mail']) > 0:
if len(result['mail'].split('@')) > 1:
result['domain'] = result['mail'].split('@')[1]
@@ -385,6 +424,24 @@ def pop_empty_from_list(_input_list):
if not item == '':
_output_list.append(item)
+def sid_to_string(sid):
+ srl = ord(sid[0])
+ number_sub_id = ord(sid[1])
+ iav = struct.unpack('!Q', '\x00\x00' + sid[2:8])[0]
+
+ sub_ids = []
+
+ for i in range(number_sub_id):
+ sub_ids.append(struct.unpack('<I',sid[8+4*i:12+4*i])[0])
+
+ result = 'S-%d-%d-%s' % (
+ srl,
+ iav,
+ '-'.join([str(s) for s in sub_ids]),
+ )
+
+ return result
+
def standard_root_dn(domain):
return 'dc=%s' % (',dc='.join(domain.split('.')))
diff --git a/pykolab/wap_client/__init__.py b/pykolab/wap_client/__init__.py
index a38953a..1dd6aab 100644
--- a/pykolab/wap_client/__init__.py
+++ b/pykolab/wap_client/__init__.py
@@ -76,40 +76,36 @@ def connect():
return conn
-def domain_add(domain, parent=None):
- params = {
- 'domain': domain,
- }
-
+def domain_add(domain, aliases=[]):
dna = conf.get('ldap', 'domain_name_attribute')
- if not parent == None:
- domains = domains_list()
- parent_found = False
- if isinstance(domains['list'], dict):
- for _domain in domains['list'].keys():
- if parent_found:
- continue
-
- if isinstance(domains['list'][_domain][dna], basestring):
- if parent == domains['list'][_domain][dna]:
- parent_found = True
- elif isinstance(domains['list'][_domain][dna], list):
- if parent in domains['list'][_domain][dna]:
- parent_found = True
-
- if parent_found:
- params['parent'] = parent
- else:
- log.error(_("Invalid parent domain"))
- return
-
- post = json.dumps(params)
+ post = json.dumps({
+ dna: [ domain ] + aliases
+ })
return request('POST', 'domain.add', post=post)
+def domain_delete(domain):
+ domain_id, domain_attrs = domain_find(domain).popitem()
+
+ post = json.dumps({
+ 'id': domain_id
+ })
+
+ return request('POST', 'domain.delete', post=post)
+
+def domain_find(domain):
+ dna = conf.get('ldap', 'domain_name_attribute')
+
+ get = { dna: domain }
+
+ return request('GET', 'domain.find', get=get)
+
def domain_info(domain):
- get = { 'domain': domain }
+ domain_id, domain_attrs = domain_find(domain)
+
+ get = { 'id': domain_id }
+
return request('GET', 'domain.info', get=get)
def domains_capabilities():
@@ -164,10 +160,12 @@ def get_user_input():
user_types = user_types_list()
if user_types['count'] > 1:
+ print ""
for key in user_types['list'].keys():
if not key == "status":
print "%s) %s" % (key,user_types['list'][key]['name'])
+ print ""
user_type_id = utils.ask_question("Please select the user type")
elif user_types['count'] > 0:
@@ -185,15 +183,62 @@ def get_user_input():
sys.exit(1)
params = {
- 'user_type_id': user_type_id
+ 'object_type': 'user',
+ 'type_id': user_type_id
}
+ must_attrs = []
+ may_attrs = []
+
for attribute in user_type_info['form_fields'].keys():
- params[attribute] = utils.ask_question(attribute)
+ if isinstance(user_type_info['form_fields'][attribute], dict):
+ if user_type_info['form_fields'][attribute].has_key('optional') and user_type_info['form_fields'][attribute]['optional']:
+ may_attrs.append(attribute)
+ else:
+ must_attrs.append(attribute)
+ else:
+ must_attrs.append(attribute)
- for attribute in user_type_info['auto_form_fields'].keys():
- exec("retval = form_value_generate_%s(params)" % (attribute))
- params[attribute] = retval[attribute]
+ for attribute in must_attrs:
+ if isinstance(user_type_info['form_fields'][attribute], dict) and \
+ user_type_info['form_fields'][attribute].has_key('type'):
+
+ if user_type_info['form_fields'][attribute]['type'] == 'select':
+ if not user_type_info['form_fields'][attribute].has_key('values'):
+ attribute_values = form_value_select_options('user', user_type_id, attribute)
+
+ default = ''
+ if attribute_values[attribute].has_key('default'):
+ default = attribute_values[attribute]['default']
+
+ params[attribute] = utils.ask_menu(
+ "Choose the %s value" % (attribute),
+ attribute_values[attribute]['list'],
+ default=default
+ )
+
+ else:
+ default = ''
+ if user_type_info['form_fields'][attribute].has_key('default'):
+ default = user_type_info['form_fields'][attribute]['default']
+
+ params[attribute] = utils.ask_menu(
+ "Choose the %s value" % (attribute),
+ user_type_info['form_fields'][attribute]['values'],
+ default=default
+ )
+
+ else:
+ params[attribute] = utils.ask_question(attribute)
+
+ else:
+ params[attribute] = utils.ask_question(attribute)
+
+ for attribute in user_type_info['fields'].keys():
+ params[attribute] = user_type_info['fields'][attribute]
+
+ exec("retval = user_form_value_generate(params)")
+ print retval
return params
@@ -201,9 +246,19 @@ def group_add(params=None):
if params == None:
params = get_group_input()
- params = json.dumps(params)
+ post = json.dumps(params)
+
+ return request('POST', 'group.add', post=post)
+
+def group_delete(params=None):
+ if params == None:
+ params = {
+ 'id': utils.ask_question("Name of group to delete", "group")
+ }
- return request('POST', 'group.add', params)
+ post = json.dumps(params)
+
+ return request('POST', 'group.delete', post=post)
def group_form_value_generate_mail(params=None):
if params == None:
@@ -237,7 +292,8 @@ def request(method, api_uri, get=None, post=None, headers={}):
del response_data['status']
return response_data['result']
else:
- return response_data['result']
+ print "ERROR: %r" % (response_data['reason'])
+ return False
def request_raw(method, api_uri, get=None, post=None, headers={}):
global session_id
@@ -328,40 +384,60 @@ def user_edit(user = None, attributes={}):
return user_edit
-def user_form_value_generate_cn(params=None):
- if params == None:
- params = get_user_input()
-
- post = json.dumps(params)
+def user_find(attribs=None):
+ if attribs == None:
+ post = {
+ 'search': {
+ 'params': {
+ utils.ask_question("Attribute") : {
+ 'value': utils.ask_question("value"),
+ 'type': 'exact'
+ }
+ }
+ }
+ }
+ else:
+ post = { 'search': { 'params': {} } }
- return request('POST', 'user_form_value.generate_cn', post=post)
+ for (k,v) in attribs.iteritems():
+ post['search']['params'][k] = { 'value': v, 'type': 'exact' }
-def user_form_value_generate_displayname(params=None):
- if params == None:
- params = get_user_input()
+ post = json.dumps(post)
- post = json.dumps(params)
+ user = request('POST', 'user.find', post=post)
- return request('POST', 'user_form_value.generate_displayname', post=post)
+ return user
-def user_form_value_generate_mail(params=None):
+def user_form_value_generate(params=None):
if params == None:
params = get_user_input()
post = json.dumps(params)
- return request('POST', 'user_form_value.generate_mail', post=post)
+ return request('POST', 'form_value.generate', post=post)
def form_value_generate_password(*args, **kw):
return request('GET', 'form_value.generate_password')
-def form_value_list_options(attribute_name, *args, **kw):
- post = json.dumps({'attribute': attribute_name})
+def form_value_list_options(object_type, object_type_id, attribute):
+ post = json.dumps(
+ {
+ 'object_type': object_type,
+ 'type_id': object_type_id,
+ 'attribute': attribute
+ }
+ )
return request('POST', 'form_value.list_options', post=post)
-def form_value_select_options(attribute_name, *args, **kw):
- post = json.dumps({'attributes': [attribute_name]})
+def form_value_select_options(object_type, object_type_id, attribute):
+ post = json.dumps(
+ {
+ 'object_type': object_type,
+ 'type_id': object_type_id,
+ 'attributes': [ attribute ]
+ }
+ )
return request('POST', 'form_value.select_options', post=post)
@@ -423,7 +499,7 @@ def user_form_value_generate_uid(params=None):
params = json.dumps(params)
- return request('POST', 'user_form_value.generate_uid', params)
+ return request('POST', 'form_value.generate_uid', params)
def user_form_value_generate_userpassword(*args, **kw):
result = form_value_generate_password()
diff --git a/pykolab/xml/event.py b/pykolab/xml/event.py
index 18eea3e..686039b 100644
--- a/pykolab/xml/event.py
+++ b/pykolab/xml/event.py
@@ -32,6 +32,7 @@ class Event(object):
def __init__(self, from_ical="", from_string=""):
self._attendees = []
+ self._categories = []
if from_ical == "":
if from_string == "":
@@ -48,6 +49,53 @@ class Event(object):
self._attendees.append(attendee)
self.event.setAttendees(self._attendees)
+ def add_category(self, category):
+ self._categories.append(category)
+ self.event.setCategories(self._categories)
+
+ def add_exception_date(self, _datetime):
+ valid_datetime = False
+ if isinstance(_datetime, datetime.date):
+ valid_datetime = True
+
+ if isinstance(_datetime, datetime.datetime):
+ # If no timezone information is passed on, make it UTC
+ if _datetime.tzinfo == None:
+ _datetime = _datetime.replace(tzinfo=pytz.utc)
+
+ valid_datetime = True
+
+ if not valid_datetime:
+ raise InvalidEventDateError, _("Event start needs datetime.date or datetime.datetime instance")
+
+ (
+ year,
+ month,
+ day,
+ ) = (
+ _datetime.year,
+ _datetime.month,
+ _datetime.day,
+ )
+ if hasattr(_datetime, 'hour'):
+ (
+ hour,
+ minute,
+ second
+ ) = (
+ _datetime.hour,
+ _datetime.minute,
+ _datetime.second
+ )
+ _cdatetime = kolabformat.cDateTime(year, month, day, hour, minute, second)
+ else:
+ _cdatetime = kolabformat.cDateTime(year, month, day)
+
+ if hasattr(_datetime, "tzinfo"):
+ _cdatetime.setTimezone(_datetime.tzinfo.__str__())
+
+ self.event.addExceptionDate(_cdatetime)
+
def as_string_itip(self, method="REQUEST"):
cal = icalendar.Calendar()
cal.add(
@@ -194,6 +242,12 @@ class Event(object):
def get_attendees(self):
return self._attendees
+ def get_categories(self):
+ return self.event.categories()
+
+ def get_classification(self):
+ return self.classification()
+
def get_created(self):
_datetime = self.event.created()
@@ -218,6 +272,9 @@ class Event(object):
except ValueError:
result = datetime.datetime.now()
+ def get_description(self):
+ return self.event.description()
+
def get_end(self):
_datetime = self.event.end()
@@ -256,6 +313,9 @@ class Event(object):
else:
return datetime.datetime(year, month, day, hour, minute, second, tzinfo=_timezone)
+ def get_exception_dates(self):
+ return self.event.exceptionDates()
+
def get_ical_attendee(self):
# TODO: Formatting, aye? See also the example snippet:
#
@@ -477,6 +537,9 @@ class Event(object):
attendee.set_participant_status(status)
self.event.setAttendees(self._attendees)
+ def set_classification(self, classification):
+ self.event.setClassification(classification)
+
def set_created(self, _datetime=None):
if _datetime == None:
_datetime = datetime.datetime.now()
@@ -501,6 +564,9 @@ class Event(object):
kolabformat.cDateTime(year, month, day, hour, minute, second)
)
+ def set_description(self, description):
+ self.event.setDescription(description)
+
def set_dtstamp(self, _datetime):
(
year,
@@ -565,6 +631,10 @@ class Event(object):
self.event.setEnd(_cdatetime)
+ def set_exception_dates(self, _datetimes):
+ for _datetime in _datetimes:
+ self.add_exception_date(_datetime)
+
def set_from_ical(self, attr, value):
if attr == "dtend":
self.set_ical_dtend(value.dt)
@@ -698,6 +768,9 @@ class Event(object):
self.event.setLastModified(kolabformat.cDateTime(year, month, day, hour, minute, second))
+ def set_location(self, location):
+ self.event.setLocation(location)
+
def set_organizer(self, email, name=None):
contactreference = ContactReference(email)
if not name == None:
@@ -708,6 +781,9 @@ class Event(object):
def set_priority(self, priority):
self.event.setPriority(priority)
+ def set_recurrence(self, recurrence):
+ self.event.setRecurrenceRule(recurrence)
+
def set_start(self, _datetime):
valid_datetime = False
@@ -796,6 +872,7 @@ class Event(object):
msg['To'] = ', '.join([x.__str__() for x in self.get_attendees()])
msg['Date'] = formatdate(localtime=True)
+ msg.add_header('X-Kolab-MIME-Version', '3.0')
msg.add_header('X-Kolab-Type', 'application/x-vnd.kolab.event')
text = utils.multiline_message("""
diff --git a/saslauthd.py b/saslauthd.py
index b24e0e3..26677bc 100755
--- a/saslauthd.py
+++ b/saslauthd.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/saslauthd/__init__.py b/saslauthd/__init__.py
index edbca94..4eaba67 100644
--- a/saslauthd/__init__.py
+++ b/saslauthd/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -194,7 +194,14 @@ class SASLAuthDaemon(object):
auth = Auth(domain=realm)
auth.connect()
- if auth.authenticate(login):
+ success = False
+
+ try:
+ success = auth.authenticate(login)
+ except:
+ success = False
+
+ if success:
# #1170: Catch broken pipe error (incomplete authentication request)
try:
clientsocket.send(struct.pack("!H2s", 2, "OK"))
@@ -208,6 +215,7 @@ class SASLAuthDaemon(object):
pass
clientsocket.close()
+ auth.disconnect()
def reload_config(self, *args, **kw):
pass
diff --git a/setup-kolab.py b/setup-kolab.py
index 7794e99..e70358d 100755
--- a/setup-kolab.py
+++ b/setup-kolab.py
@@ -1,7 +1,7 @@
#!/usr/bin/python -u
# -*- coding: utf-8 -*-
#
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/share/Makefile.am b/share/Makefile.am
index 4bfff10..fc80b0a 100644
--- a/share/Makefile.am
+++ b/share/Makefile.am
@@ -1,35 +1,18 @@
templatedir = $(datadir)/kolab/templates
template_DATA = \
- $(wildcard templates/*.tpl)
-
-fbtemplatedir = $(datadir)/kolab/templates/freebusy
-fbtemplate_DATA = \
- $(wildcard templates/freebusy/*.tpl)
-
-hordetemplatedir = $(datadir)/kolab/templates/horde/conf.d/
-hordetemplate_DATA = \
- $(wildcard templates/horde/conf.d/*.tpl)
+ $(wildcard templates/*.tpl) \
+ $(wildcard templates/header_checks.*)
rctemplatedir = $(datadir)/kolab/templates/roundcubemail
rctemplate_DATA = \
$(wildcard templates/roundcubemail/*.tpl)
-zpushtemplatedir = $(datadir)/kolab/templates/zpush
-zpushtemplate_DATA = \
- $(wildcard templates/zpush/*.tpl)
-
EXTRA_DIST = \
$(template_DATA) \
- $(fbtemplate_DATA) \
- $(hordetemplate_DATA) \
- $(rctemplate_DATA) \
- $(zpushtemplate_DATA)
+ $(rctemplate_DATA)
install-exec-local:
mkdir -p \
$(DESTDIR)/$(sysconfdir)/kolab/templates \
- $(DESTDIR)/$(sysconfdir)/kolab/templates/freebusy \
- $(DESTDIR)/$(sysconfdir)/kolab/templates/horde/conf.d \
- $(DESTDIR)/$(sysconfdir)/kolab/templates/roundcubemail \
- $(DESTDIR)/$(sysconfdir)/kolab/templates/zpush
+ $(DESTDIR)/$(sysconfdir)/kolab/templates/roundcubemail
diff --git a/share/templates/cyrus.conf.tpl b/share/templates/cyrus.conf.tpl
index 056c210..9a4a17a 100644
--- a/share/templates/cyrus.conf.tpl
+++ b/share/templates/cyrus.conf.tpl
@@ -37,18 +37,18 @@ EVENTS {
# this is only necessary if using duplicate delivery suppression,
# Sieve or NNTP
- duplicate_prune cmd="cyr_expire -E 3" at=0400
+ duplicateprune cmd="cyr_expire -E 3" at=0400
# Expire data older then 69 days. Two full months of 31 days
# each includes two full backup cycles, plus 1 week margin
# because we run our full backups on the first sat/sun night
# of each month.
- delete_prune cmd="cyr_expire -E 4 -D 69" at=0430
- expunge_prune cmd="cyr_expire -E 4 -X 69" at=0445
+ deleteprune cmd="cyr_expire -E 4 -D 69" at=0430
+ expungeprune cmd="cyr_expire -E 4 -X 69" at=0445
# this is only necessary if caching TLS sessions
tlsprune cmd="tls_prune" at=0400
# Create search indexes regularly
- squatter cmd="squatter -s -i" at=0530
+ #squatter cmd="squatter -s -i" at=0530
}
diff --git a/share/templates/freebusy/config.php.tpl b/share/templates/freebusy/config.php.tpl
deleted file mode 100644
index f41195a..0000000
--- a/share/templates/freebusy/config.php.tpl
+++ /dev/null
@@ -1,212 +0,0 @@
-<?php
-/**
- * This file provides configuration settings for both the freebusy.php
- * and the pfb.php scripts.
- *
- * \$Horde: framework/Kolab_FreeBusy/www/Horde/Kolab/FreeBusy/config.php,v 1.4.2.2 2010/07/22 13:55:30 wrobel Exp \$
- *
- * Copyright 2008-2009 The Horde Project (http://www.horde.org/)
- *
- * @author Steffen Hansen <steffen@klaralvdalens-datakonsult.se>
- * @author Gunnar Wrobel <p@rdus.de>
- * @author Thomas Arendsen Hein <thomas@intevation.de>
- * @package Kolab_FreeBusy
- */
-
-\$conf = array();
-
-/* Horde::Log configuration */
-\$conf['log']['enabled'] = true;
-\$conf['log']['priority'] = PEAR_LOG_DEBUG;
-\$conf['log']['type'] = 'file';
-\$conf['log']['name'] = '/var/log/kolab/freebusy/freebusy.log';
-\$conf['log']['ident'] = 'Kolab Free/Busy';
-\$conf['log']['params']['append'] = true;
-
-/* PHP error logging */
-ini_set('error_log', '/var/log/kolab/freebusy/php.log');
-
-/* Horde::Kolab::LDAP configuration */
-\$conf['kolab']['ldap']['server'] = 'localhost';
-\$conf['kolab']['ldap']['basedn'] = '$ldap_base_dn';
-\$conf['kolab']['ldap']['phpdn'] = '$ldap_service_bind_dn';
-\$conf['kolab']['ldap']['phppw'] = '$ldap_service_bind_pw';
-
-/* Horde::Kolab::IMAP configuration */
-\$conf['kolab']['imap']['server'] = 'localhost';
-\$conf['kolab']['imap']['port'] = 143;
-\$conf['kolab']['imap']['protocol'] = 'imap/tls/novalidate-cert/readonly';
-\$conf['kolab']['imap']['namespaces'] = array(
- array('type' => 'personal', 'name' => '', 'delimiter' => '/'),
- array('type' => 'other', 'name' => 'Other Users', 'delimiter' => '/'),
- array('type' => 'shared', 'name' => 'Shared Folders', 'delimiter' => '/'),
-);
-
-/* Horde::Auth configuration */
-\$conf['auth']['params']['login_block'] = 0;
-\$conf['auth']['checkbrowser'] = false;
-\$conf['auth']['checkip'] = false;
-\$conf['umask'] = false;
-
-\$conf['auth']['driver'] = 'imap';
-\$conf['auth']['params']['hostspec'] = 'localhost';
-\$conf['auth']['params']['protocol'] = 'imap/tls/novalidate-cert';
-
-/* Allow special users to log into the system */
-\$conf['kolab']['imap']['allow_special_users'] = true;
-
-/* Do not record login attempts */
-\$conf['auth']['params']['login_block'] = false;
-
-/* Kolab::Freebusy configuration */
-
-/* Should we redirect using a Location header, if the user is not local? If this
- * is false we silently download the file ourselves and output it so that it
- * looks as though the free/busy information is coming from us.
- */
-\$conf['fb']['redirect'] = false;
-
-/* What is the address of the current server where the calendar data is stored?
- * This is also used as the LDAP server address where user objects reside.
- */
-\$conf['kolab']['freebusy']['server'] = 'http://' . \$_SERVER["HTTP_HOST"] . '/freebusy';
-
-/* What is our default mail domain? This is used if any users do not have
- * '@domain' specified after their username as part of their email address.
- */
-\$conf['fb']['email_domain'] = '$primary_domain';
-
-/* Location of the cache files */
-\$conf['fb']['cache_dir'] = '/tmp';
-\$conf['fb']['cache']['driver'] = 'sql';
-\$conf['fb']['cache']['params']['phptype'] = 'mysql';
-\$conf['fb']['cache']['params']['username'] = 'roundcube';
-\$conf['fb']['cache']['params']['password'] = '$mysql_roundcube_password';
-\$conf['fb']['cache']['params']['hostspec'] = 'localhost';
-\$conf['fb']['cache']['params']['database'] = 'roundcube';
-\$conf['fb']['cache']['params']['charset'] = 'utf-8';
-
-/* What db type to use for the freebusy caches */
-\$conf['fb']['dbformat'] = 'db4';
-
-/* Should we send a Content-Type header, indicating what the mime type of the
- * resulting VFB file is?
- */
-\$conf['fb']['send_content_type'] = false;
-
-/* Should we send a Content-Length header, indicating how large the resulting
- * VFB file is?
- */
-\$conf['fb']['send_content_length'] = false;
-
-/* Should we send a Content-Disposition header, indicating what the name of the
- * resulting VFB file should be?
- */
-\$conf['fb']['send_content_disposition'] = false;
-
-/* Should we use ACLs or does everybody get full rights? DO NOT set
- * this to false if you don't know what you are doing. Your free/busy
- * service should not be visible to any outside networks when
- * disabling the use of ACL settings.
- */
-\$conf['fb']['use_acls'] = true;
-
-/* How many days in advance should the free/busy information be calculated? This
- * is the default value that can be overwritten by the kolabFreeBusyFuture
- * attribute of the users LDAP account.
- */
-\$conf['fb']['future_days'] = 180;
-
-/* The resulting vCalendar file is being cached. The following setting
- * determines how many seconds it will be delivered without checking if
- * the contents of the file might have changed. A negative setting disables
- * caching (which is currently required for the resource management to work).
- */
-\$conf['fb']['vcal_cache']['min_age'] = -1;
-
-/* The resulting vCalendar file is being cached. The following setting
- * determines after how many seconds it will be considered too old for
- * delivery and a refresh of its contents will be enforced.
- */
-\$conf['fb']['vcal_cache']['max_age'] = 259200;
-
-/* The IMAP namespaces on the server. @TODO: Should obviously be
- * auto-detected.
- */
-\$conf['fb']['namespace']['personal'] = '';
-\$conf['fb']['namespace']['other'] = 'Other Users';
-
-/* In most cases you can rely on the standard event status to free/busy status
- * mapping. For the default kolab server this will mean that only the event
- * status "free" will be mapped to the free/busy status "FREE". All other event
- * status ("tentative", "busy", "outofoffice") will be mapped to "BUSY".
- *
- * If this mapping should be modified you can define it like this:
- *
- * \$conf['fb']['status_map'] = array(
- * Horde_Kolab_FreeBusy_Object_Event::STATUS_TENTATIVE =>
- * Horde_Kolab_FreeBusy_Helper_Freebusy_StatusMap::STATUS_BUSY_TENTATIVE,
- * Horde_Kolab_FreeBusy_Object_Event::STATUS_OUTOFOFFICE =>
- * 'X-OUT-OF-OFFICE',
- * );
- */
-require_once 'Horde/Kolab/FreeBusy/Object/Event.php';
-require_once 'Horde/Kolab/FreeBusy/Helper/Freebusy/StatusMap.php';
-\$conf['fb']['status_map'] = array(
- Horde_Kolab_FreeBusy_Object_Event::STATUS_TENTATIVE =>
- Horde_Kolab_FreeBusy_Helper_Freebusy_StatusMap::STATUS_BUSY_TENTATIVE,
- Horde_Kolab_FreeBusy_Object_Event::STATUS_OUTOFOFFICE =>
- 'X-OUT-OF-OFFICE',
-);
-
-/* Are there remote servers on which users have additional (shared)
- * folders? In that case free/busy information should also be fetched
- * from these servers.
- *
- * Add them like this:
- *
- * array('remote1.example.com', 'remote2.example.com')
- */
-\$conf['fb']['remote_servers'] = array();
-
-/* Is there an exchange server that you want to relay through this free/busy
- * application?
- *
- * Configure it like this:
- *
- * \$conf['fb']['exchange_server'] = array(
- * 'url' => 'https://example.com',
- * 'interval' => 30,
- * );
- */
-#\$conf['fb']['exchange_server'] = array(
-# 'url' => 'http://test90-9.test90.kolabsys.com',
-# 'interval' => 30,
-# 'username' => 'kolabservice',
-# 'password' => 'SomePass',
-#);
-
-/**
- * Ensure we use the Kolab group driver when handling groups.
- */
-\$conf['group']['driver'] = 'kolab';
-\$conf['group']['cache'] = false;
-
-//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-//
-// If you modify this file, please do not forget to also modify the
-// template in kolabd!
-//
-//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-// DEBUGGING
-// =========
-//
-// Activate this to see the log messages on the screen
-// \$conf['log']['type'] = 'display';
-//
-// Activate this to see the php messages on the screen
-// ini_set('display_errors', 1);
-//
-// Both settings will disrupt header delivery (which should not cause a
-// problem).
diff --git a/share/templates/header_checks.inbound b/share/templates/header_checks.inbound
new file mode 100644
index 0000000..a824f84
--- /dev/null
+++ b/share/templates/header_checks.inbound
@@ -0,0 +1,6 @@
+/^X-Spam-Flag:.*YES/ REJECT
+/^X-Virus-Scanned:/ IGNORE
+/^X-Spam-Flag:.*NO/ IGNORE
+/^X-Spam-Score:/ IGNORE
+/^X-Spam-Level:/ IGNORE
+/^X-Spam-Status:/ IGNORE
diff --git a/share/templates/header_checks.internal b/share/templates/header_checks.internal
new file mode 100644
index 0000000..2976141
--- /dev/null
+++ b/share/templates/header_checks.internal
@@ -0,0 +1 @@
+/^Received:.*127\.0\.0\.1/ IGNORE
diff --git a/share/templates/header_checks.submission b/share/templates/header_checks.submission
new file mode 100644
index 0000000..4866ef8
--- /dev/null
+++ b/share/templates/header_checks.submission
@@ -0,0 +1,5 @@
+/^Received:.*with ESMTPSA/ IGNORE
+/^Received:.*127\.0\.0\.1/ IGNORE
+/^User-Agent:/ IGNORE
+/^X-Mailer:/ IGNORE
+/^Mime-Version:/ IGNORE
diff --git a/share/templates/imapd.conf.tpl b/share/templates/imapd.conf.tpl
index 8d4e30b..874e55a 100644
--- a/share/templates/imapd.conf.tpl
+++ b/share/templates/imapd.conf.tpl
@@ -8,7 +8,7 @@ sasl_mech_list: PLAIN LOGIN
allowplaintext: no
tls_cert_file: /etc/pki/cyrus-imapd/cyrus-imapd.pem
tls_key_file: /etc/pki/cyrus-imapd/cyrus-imapd.pem
-tls_ca_file: /etc/pki/tls/certs/ca-bundle.crt
+tls_ca_file: /etc/pki/cyrus-imapd/cyrus-imapd.pem
# uncomment this if you're operating in a DSCP environment (RFC-4594)
# qosmarking: af13
auth_mech: pts
@@ -48,3 +48,4 @@ deletedprefix: DELETED
delete_mode: delayed
expunge_mode: delayed
flushseenstate: 1
+postuser: shared
diff --git a/share/templates/master.cf.tpl b/share/templates/master.cf.tpl
index 161d053..44c983a 100644
--- a/share/templates/master.cf.tpl
+++ b/share/templates/master.cf.tpl
@@ -1,19 +1,17 @@
-#
# Postfix master process configuration file. For details on the format
# of the file, see the master(5) manual page (command: "man 5 master").
-#
# Do not forget to execute "postfix reload" after editing this file.
-#
-# ==========================================================================
-# service type private unpriv chroot wakeup maxproc command + args
-# (yes) (yes) (yes) (never) (100)
-# ==========================================================================
-smtp inet n - n - - smtpd
-#smtp inet n - n - 1 postscreen
-#smtpd pass - - n - - smtpd
-#dnsblog unix - - n - 0 dnsblog
-#tlsproxy unix - - n - 0 tlsproxy
-submission inet n - n - - smtpd
+# ==============================================================================
+# service type private unpriv chroot wakeup maxproc command
+# (yes) (yes) (yes) (never) (100) + args
+# ==============================================================================
+smtp inet n - n - - smtpd
+#smtp inet n - n - 1 postscreen
+#smtpd pass - - n - - smtpd
+#dnsblog unix - - n - 0 dnsblog
+#tlsproxy unix - - n - 0 tlsproxy
+submission inet n - n - - smtpd
+ -o cleanup_service_name=cleanup_submission
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
@@ -23,119 +21,58 @@ submission inet n - n - - smtpd
-o smtpd_recipient_restrictions=\$submission_recipient_restrictions
-o smtpd_sender_restrictions=\$submission_sender_restrictions
-#smtps inet n - n - - smtpd
-# -o syslog_name=postfix/smtps
-# -o smtpd_tls_wrappermode=yes
-# -o smtpd_sasl_auth_enable=yes
-# -o smtpd_client_restrictions=permit_sasl_authenticated,reject
-# -o milter_macro_daemon_name=ORIGINATING
-#628 inet n - n - - qmqpd
-pickup fifo n - n 60 1 pickup
-cleanup unix n - n - 0 cleanup
-qmgr fifo n - n 300 1 qmgr
-#qmgr fifo n - n 300 1 oqmgr
-tlsmgr unix - - n 1000? 1 tlsmgr
-rewrite unix - - n - - trivial-rewrite
-bounce unix - - n - 0 bounce
-defer unix - - n - 0 bounce
-trace unix - - n - 0 bounce
-verify unix - - n - 1 verify
-flush unix n - n 1000? 0 flush
-proxymap unix - - n - - proxymap
-proxywrite unix - - n - 1 proxymap
-smtp unix - - n - - smtp
-relay unix - - n - - smtp
-# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
-showq unix n - n - - showq
-error unix - - n - - error
-retry unix - - n - - error
-discard unix - - n - - discard
-local unix - n n - - local
-virtual unix - n n - - virtual
-lmtp unix - - n - - lmtp
-anvil unix - - n - 1 anvil
-scache unix - - n - 1 scache
-#
-# ====================================================================
-# Interfaces to non-Postfix software. Be sure to examine the manual
-# pages of the non-Postfix software to find out what options it wants.
-#
-# Many of the following services use the Postfix pipe(8) delivery
-# agent. See the pipe(8) man page for information about \${recipient}
-# and other message envelope options.
-# ====================================================================
-#
-# maildrop. See the Postfix MAILDROP_README file for details.
-# Also specify in main.cf: maildrop_destination_recipient_limit=1
-#
-#maildrop unix - n n - - pipe
-# flags=DRhu user=vmail argv=/usr/local/bin/maildrop -d \${recipient}
-#
-# ====================================================================
-#
-# Recent Cyrus versions can use the existing "lmtp" master.cf entry.
-#
-# Specify in cyrus.conf:
-# lmtp cmd="lmtpd -a" listen="localhost:lmtp" proto=tcp4
-#
-# Specify in main.cf one or more of the following:
-# mailbox_transport = lmtp:inet:localhost
-# virtual_transport = lmtp:inet:localhost
-#
-# ====================================================================
-#
-# Cyrus 2.1.5 (Amos Gouaux)
-# Also specify in main.cf: cyrus_destination_recipient_limit=1
-#
-#cyrus unix - n n - - pipe
-# user=cyrus argv=/usr/lib/cyrus-imapd/deliver -e -r \${sender} -m \${extension} \${user}
-#
-# ====================================================================
-#
-# Old example of delivery via Cyrus.
-#
-#old-cyrus unix - n n - - pipe
-# flags=R user=cyrus argv=/usr/lib/cyrus-imapd/deliver -e -m \${extension} \${user}
-#
-# ====================================================================
-#
-# See the Postfix UUCP_README file for configuration details.
-#
-#uucp unix - n n - - pipe
-# flags=Fqhu user=uucp argv=uux -r -n -z -a\$sender - \$nexthop!rmail (\$recipient)
-#
-# ====================================================================
-#
-# Other external delivery methods.
-#
-#ifmail unix - n n - - pipe
-# flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r \$nexthop (\$recipient)
-#
-#bsmtp unix - n n - - pipe
-# flags=Fq. user=bsmtp argv=/usr/local/sbin/bsmtp -f \$sender \$nexthop \$recipient
-#
-#scalemail-backend unix - n n - 2 pipe
-# flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store
-# \${nexthop} \${user} \${extension}
-#
-#mailman unix - n n - - pipe
-# flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
-# \${nexthop} \${user}
+#smtps inet n - n - - smtpd
+# -o syslog_name=postfix/smtps
+# -o smtpd_tls_wrappermode=yes
+# -o smtpd_sasl_auth_enable=yes
+# -o smtpd_client_restrictions=permit_sasl_authenticated,reject
+# -o milter_macro_daemon_name=ORIGINATING
+#628 inet n - n - - qmqpd
+pickup fifo n - n 60 1 pickup
+cleanup unix n - n - 0 cleanup
+ -o header_checks=regexp:/etc/postfix/header_checks.inbound
+ -o mime_header_checks=regexp:/etc/postfix/header_checks.inbound
+cleanup_internal unix n - n - 0 cleanup
+ -o header_checks=regexp:/etc/postfix/header_checks.internal
+ -o mime_header_checks=regexp:/etc/postfix/header_checks.internal
+cleanup_submission unix n - n - 0 cleanup
+ -o header_checks=regexp:/etc/postfix/header_checks.submission
+ -o mime_header_checks=regexp:/etc/postfix/header_checks.submission
+qmgr fifo n - n 300 1 qmgr
+#qmgr fifo n - n 300 1 oqmgr
+tlsmgr unix - - n 1000? 1 tlsmgr
+rewrite unix - - n - - trivial-rewrite
+bounce unix - - n - 0 bounce
+defer unix - - n - 0 bounce
+trace unix - - n - 0 bounce
+verify unix - - n - 1 verify
+flush unix n - n 1000? 0 flush
+proxymap unix - - n - - proxymap
+proxywrite unix - - n - 1 proxymap
+smtp unix - - n - - smtp
+relay unix - - n - - smtp
+showq unix n - n - - showq
+error unix - - n - - error
+retry unix - - n - - error
+discard unix - - n - - discard
+local unix - n n - - local
+virtual unix - n n - - virtual
+lmtp unix - - n - - lmtp
+anvil unix - - n - 1 anvil
+scache unix - - n - 1 scache
-#
# Filter email through Amavisd
-#
-smtp-amavis unix - - n - 3 smtp
+smtp-amavis unix - - n - 3 smtp
-o smtp_data_done_timeout=1800
-o disable_dns_lookups=yes
-o smtp_send_xforward_command=yes
-o max_use=20
+ -o smtp_bind_address=127.0.0.1
-#
# Listener to re-inject email from Amavisd into Postfix
-#
-127.0.0.1:10025 inet n - n - 100 smtpd
- -o content_filter=smtp-wallace:[127.0.0.1]:10026
+127.0.0.1:10025 inet n - n - 100 smtpd
+ -o cleanup_service_name=cleanup_internal
+ -o content_filter=
-o local_recipient_maps=
-o relay_recipient_maps=
-o smtpd_restriction_classes=
@@ -146,19 +83,16 @@ smtp-amavis unix - - n - 3 smtp
-o mynetworks=127.0.0.0/8
-o smtpd_authorized_xforward_hosts=127.0.0.0/8
-#
# Filter email through Wallace
-#
-smtp-wallace unix - - n - 3 smtp
+smtp-wallace unix - - n - 3 smtp
-o smtp_data_done_timeout=1800
-o disable_dns_lookups=yes
-o smtp_send_xforward_command=yes
-o max_use=20
-#
# Listener to re-inject email from Wallace into Postfix
-#
-127.0.0.1:10027 inet n - n - 100 smtpd
+127.0.0.1:10027 inet n - n - 100 smtpd
+ -o cleanup_service_name=cleanup_internal
-o content_filter=
-o local_recipient_maps=
-o relay_recipient_maps=
@@ -170,18 +104,18 @@ smtp-wallace unix - - n - 3 smtp
-o mynetworks=127.0.0.0/8
-o smtpd_authorized_xforward_hosts=127.0.0.0/8
-recipient_policy unix - n n - - spawn
- user=kolab-n argv=${kolab_sap_executable_path} --verify-recipient
+recipient_policy unix - n n - - spawn
+ user=kolab-n argv=/usr/libexec/postfix/kolab_smtp_access_policy --verify-recipient
-recipient_policy_incoming unix - n n - - spawn
- user=kolab-n argv=${kolab_sap_executable_path} --verify-recipient --allow-unauthenticated
+recipient_policy_incoming unix - n n - - spawn
+ user=kolab-n argv=/usr/libexec/postfix/kolab_smtp_access_policy --verify-recipient --allow-unauthenticated
-sender_policy unix - n n - - spawn
- user=kolab-n argv=${kolab_sap_executable_path} --verify-sender
+sender_policy unix - n n - - spawn
+ user=kolab-n argv=/usr/libexec/postfix/kolab_smtp_access_policy --verify-sender
-sender_policy_incoming unix - n n - - spawn
- user=kolab-n argv=${kolab_sap_executable_path} --verify-sender --allow-unauthenticated
+sender_policy_incoming unix - n n - - spawn
+ user=kolab-n argv=/usr/libexec/postfix/kolab_smtp_access_policy --verify-sender --allow-unauthenticated
-submission_policy unix - n n - - spawn
- user=kolab-n argv=${kolab_sap_executable_path} --verify-sender --verify-recipient
+submission_policy unix - n n - - spawn
+ user=kolab-n argv=/usr/libexec/postfix/kolab_smtp_access_policy --verify-sender --verify-recipient
diff --git a/share/templates/roundcubemail/acl.inc.php.tpl b/share/templates/roundcubemail/acl.inc.php.tpl
index f4b651c..ca1bae5 100644
--- a/share/templates/roundcubemail/acl.inc.php.tpl
+++ b/share/templates/roundcubemail/acl.inc.php.tpl
@@ -1,11 +1,11 @@
<?php
- \$rcmail_config['acl_advanced_mode'] = false;
- \$rcmail_config['acl_users_source'] = 'kolab_addressbook';
- \$rcmail_config['acl_users_field'] = 'mail';
- \$rcmail_config['acl_users_filter'] = 'objectClass=kolabInetOrgPerson';
+ \$config['acl_advanced_mode'] = false;
+ \$config['acl_users_source'] = 'kolab_addressbook';
+ \$config['acl_users_field'] = 'mail';
+ \$config['acl_users_filter'] = 'objectClass=kolabInetOrgPerson';
- if (file_exists(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
- include_once(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
+ if (file_exists(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
+ include_once(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
}
?>
diff --git a/share/templates/roundcubemail/calendar.inc.php.tpl b/share/templates/roundcubemail/calendar.inc.php.tpl
index a7cf6d2..b119f7b 100644
--- a/share/templates/roundcubemail/calendar.inc.php.tpl
+++ b/share/templates/roundcubemail/calendar.inc.php.tpl
@@ -1,15 +1,15 @@
<?php
- \$rcmail_config['calendar_driver'] = "kolab";
- \$rcmail_config['calendar_default_view'] = "agendaWeek";
- \$rcmail_config['calendar_timeslots'] = 2;
- \$rcmail_config['calendar_first_day'] = 1;
- \$rcmail_config['calendar_first_hour'] = 6;
- \$rcmail_config['calendar_work_start'] = 6;
- \$rcmail_config['calendar_work_end'] = 18;
- \$rcmail_config['calendar_event_coloring'] = 0;
+ \$config['calendar_driver'] = "kolab";
+ \$config['calendar_default_view'] = "agendaWeek";
+ \$config['calendar_timeslots'] = 2;
+ \$config['calendar_first_day'] = 1;
+ \$config['calendar_first_hour'] = 6;
+ \$config['calendar_work_start'] = 6;
+ \$config['calendar_work_end'] = 18;
+ \$config['calendar_event_coloring'] = 0;
- if (file_exists(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
- include_once(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
+ if (file_exists(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
+ include_once(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
}
?>
diff --git a/share/templates/roundcubemail/config.inc.php.tpl b/share/templates/roundcubemail/config.inc.php.tpl
new file mode 100644
index 0000000..4ec3469
--- /dev/null
+++ b/share/templates/roundcubemail/config.inc.php.tpl
@@ -0,0 +1,208 @@
+<?php
+ \$config = array();
+
+ \$config['db_dsnw'] = '$mysql_uri';
+
+ \$config['session_domain'] = '';
+ \$config['des_key'] = "$des_key";
+ \$config['username_domain'] = '$primary_domain';
+
+ \$config['mail_domain'] = '';
+
+ // IMAP Server Settings
+ \$config['default_host'] = 'tls://localhost';
+ \$config['default_port'] = 143;
+ \$config['imap_delimiter'] = '/';
+ \$config['imap_force_lsub'] = true;
+
+ // Caching and storage settings
+ \$config['imap_cache'] = 'db';
+ \$config['imap_cache_ttl'] = '10d';
+ \$config['messages_cache'] = 'db';
+ \$config['message_cache_ttl'] = '10d';
+ \$config['session_storage'] = 'db';
+
+ // SMTP Server Settings
+ \$config['smtp_server'] = 'tls://localhost';
+ \$config['smtp_port'] = 587;
+ \$config['smtp_user'] = '%u';
+ \$config['smtp_pass'] = '%p';
+ \$config['smtp_helo_host'] = \$_SERVER["HTTP_HOST"];
+
+ // LDAP Settings
+ \$config['ldap_cache'] = 'db';
+ \$config['ldap_cache_ttl'] = '1h';
+
+ // Kolab specific defaults
+ \$config['product_name'] = 'Kolab Groupware';
+ \$config['skin_logo'] = 'skins/kolab/images/kolab_logo.png';
+ \$config['quota_zero_as_unlimited'] = false;
+ \$config['login_lc'] = 2;
+ \$config['auto_create_user'] = true;
+ \$config['enable_installer'] = false;
+ // The SMTP server does not allow empty identities
+ \$config['mdn_use_from'] = true;
+
+ // Plugins
+ \$config['plugins'] = array(
+ 'acl',
+ 'archive',
+ 'calendar',
+ 'jqueryui',
+ 'kolab_activesync',
+ 'kolab_addressbook',
+ 'kolab_auth',
+ 'kolab_config',
+ 'kolab_folders',
+ 'libkolab',
+ 'libcalendaring',
+ 'managesieve',
+ 'newmail_notifier',
+ 'odfviewer',
+ 'password',
+ 'redundant_attachments',
+ 'tasklist',
+ 'threading_as_default',
+ // contextmenu must be after kolab_addressbook (#444)
+ 'contextmenu',
+ );
+
+
+ // Do not show deleted messages, mark deleted messages as read,
+ // and flag them as deleted instead of moving them to the Trash
+ // folder.
+ \$config['skip_deleted'] = true;
+ \$config['read_when_deleted'] = true;
+ \$config['flag_for_deletion'] = true;
+ \$config['delete_always'] = true;
+
+ \$config['session_lifetime'] = 180;
+ \$config['password_charset'] = 'UTF-8';
+ \$config['useragent'] = 'Kolab 3.1/Roundcube ' . RCUBE_VERSION;
+ \$config['dont_override'] = Array('skin');
+
+ \$config['message_sort_col'] = 'date';
+
+ \$config['spellcheck_dictionary'] = true;
+ \$config['spellcheck_ignore_caps'] = true;
+ \$config['spellcheck_ignore_nums'] = true;
+ \$config['spellcheck_ignore_syms'] = true;
+
+ \$config['undo_timeout'] = 10;
+ \$config['upload_progress'] = 2;
+ \$config['address_template'] = '{street}<br/>{locality} {zipcode}<br/>{country} {region}';
+ \$config['preview_pane'] = true;
+ \$config['preview_pane_mark_read'] = 0;
+
+ \$config['autoexpand_threads'] = 2;
+ \$config['top_posting'] = 0;
+ \$config['sig_above'] = false;
+ \$config['mdn_requests'] = 0;
+ \$config['mdn_default'] = false;
+ \$config['dsn_default'] = false;
+ \$config['reply_same_folder'] = false;
+
+ if (file_exists(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
+ include_once(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
+ }
+
+ // Re-apply mandatory settings here.
+
+ \$config['debug_level'] = 0;
+ \$config['devel_mode'] = false;
+ \$config['log_driver'] = 'file';
+ \$config['log_date_format'] = 'd-M-Y H:i:s,u O';
+ \$config['syslog_id'] = 'roundcube';
+ \$config['syslog_facility'] = LOG_USER;
+ \$config['smtp_log'] = true;
+ \$config['log_logins'] = true;
+ \$config['log_session'] = true;
+ \$config['sql_debug'] = true;
+ \$config['memcache_debug'] = true;
+ \$config['imap_debug'] = true;
+ \$config['ldap_debug'] = true;
+ \$config['smtp_debug'] = true;
+
+ \$config['skin'] = 'larry';
+ \$config['skin_include_php'] = false;
+ \$config['mime_magic'] = null;
+ \$config['im_identify_path'] = '/usr/bin/identify';
+ \$config['im_convert_path'] = '/usr/bin/convert';
+ \$config['log_dir'] = 'logs/';
+ \$config['temp_dir'] = '/var/lib/roundcubemail/';
+
+ // Some additional default folders (archive plugin)
+ \$config['archive_mbox'] = 'Archive';
+ // The Kolab daemon by default creates 'Spam'
+ \$config['junk_mbox'] = 'Spam';
+ \$config['default_folders'] = array('INBOX', 'Drafts', 'Sent', 'Spam', 'Trash', 'Archive');
+
+ \$config['address_book_type'] = 'ldap';
+ \$config['autocomplete_min_length'] = 3;
+ \$config['autocomplete_threads'] = 0;
+ \$config['autocomplete_max'] = 15;
+ \$config['ldap_public'] = array(
+ 'kolab_addressbook' => array(
+ 'name' => 'Global Address Book',
+ 'hosts' => Array('localhost'),
+ 'port' => 389,
+ 'use_tls' => false,
+ 'base_dn' => '$ldap_user_base_dn',
+ 'user_specific' => true,
+ 'bind_dn' => '%dn',
+ 'bind_pass' => '',
+ 'search_base_dn' => '$ldap_user_base_dn',
+ 'search_bind_dn' => '$ldap_service_bind_dn',
+ 'search_bind_pw' => '$ldap_service_bind_pw',
+ 'search_filter' => '(&(objectClass=inetOrgPerson)(mail=%fu))',
+ 'writable' => false,
+ 'LDAP_Object_Classes' => array("top", "inetOrgPerson"),
+ 'required_fields' => array("cn", "sn", "mail"),
+ 'LDAP_rdn' => 'uid',
+ 'ldap_version' => 3, // using LDAPv3
+ 'search_fields' => array('displayname', 'mail'),
+ 'sort' => array('displayname', 'sn', 'givenname', 'cn'),
+ 'scope' => 'sub',
+ 'filter' => '(objectClass=inetOrgPerson)',
+ 'vlv' => false,
+ 'vlv_search' => false,
+ 'fuzzy_search' => true,
+ 'sizelimit' => '0',
+ 'timelimit' => '0',
+ 'fieldmap' => Array(
+ // Roundcube => LDAP
+ 'name' => 'displayName',
+ 'surname' => 'sn',
+ 'firstname' => 'givenName',
+ 'middlename' => 'initials',
+ 'prefix' => 'title',
+ 'email:primary' => 'mail',
+ 'email:alias' => 'alias',
+ 'email:personal' => 'mailalternateaddress',
+ 'phone:main' => 'telephoneNumber',
+ 'phone:work' => 'alternateTelephoneNumber',
+ 'phone:mobile' => 'mobile',
+ 'phone:work2' => 'blackberry',
+ 'jobtitle' => 'title',
+ 'manager' => 'manager',
+ 'assistant' => 'secretary',
+ 'photo' => 'jpegphoto'
+ ),
+ 'groups' => Array(
+ 'base_dn' => '$ldap_group_base_dn',
+ 'filter' => '(&' . '$ldap_group_filter' . '(mail=*))',
+ 'object_classes' => Array("top", "groupOfUniqueNames"),
+ 'member_attr' => 'uniqueMember',
+ ),
+ ),
+ );
+
+ \$config['autocomplete_addressbooks'] = Array(
+ 'kolab_addressbook'
+ );
+
+ \$config['autocomplete_single'] = true;
+
+ \$config['htmleditor'] = 0;
+
+?>
diff --git a/share/templates/roundcubemail/db.inc.php.tpl b/share/templates/roundcubemail/db.inc.php.tpl
deleted file mode 100644
index 1257f18..0000000
--- a/share/templates/roundcubemail/db.inc.php.tpl
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-
- \$rcmail_config = array();
-
- \$rcmail_config['db_dsnw'] = '$mysql_uri';
-
- if (file_exists(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
- include_once(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
- }
-
- \$rcmail_config['db_max_length'] = 512000;
- \$rcmail_config['db_persistent'] = TRUE;
- \$rcmail_config['db_table_users'] = 'users';
- \$rcmail_config['db_table_identities'] = 'identities';
- \$rcmail_config['db_table_contacts'] = 'contacts';
- \$rcmail_config['db_table_contactgroups'] = 'contactgroups';
- \$rcmail_config['db_table_contactgroupmembers'] = 'contactgroupmembers';
- \$rcmail_config['db_table_session'] = 'session';
- \$rcmail_config['db_table_cache'] = 'cache';
- \$rcmail_config['db_table_messages'] = 'messages';
- \$rcmail_config['db_sequence_users'] = 'user_ids';
- \$rcmail_config['db_sequence_identities'] = 'identity_ids';
- \$rcmail_config['db_sequence_contacts'] = 'contact_ids';
- \$rcmail_config['db_sequence_contactgroups'] = 'contactgroups_ids';
- \$rcmail_config['db_sequence_cache'] = 'cache_ids';
- \$rcmail_config['db_sequence_messages'] = 'message_ids';
-
-
-?>
diff --git a/share/templates/roundcubemail/kolab.inc.php.tpl b/share/templates/roundcubemail/kolab.inc.php.tpl
index aa9fd0b..05711ef 100644
--- a/share/templates/roundcubemail/kolab.inc.php.tpl
+++ b/share/templates/roundcubemail/kolab.inc.php.tpl
@@ -1,15 +1,15 @@
<?php
- \$rcmail_config['kolab_freebusy_server'] = 'http://' . \$_SERVER["HTTP_HOST"] . '/freebusy';
+ \$config['kolab_freebusy_server'] = 'http://' . \$_SERVER["HTTP_HOST"] . '/freebusy';
- if (file_exists(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
- include_once(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
+ if (file_exists(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
+ include_once(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
}
- \$rcmail_config['kolab_cache'] = true;
+ \$config['kolab_cache'] = true;
- \$rcmail_config['kolab_ssl_verify_peer'] = false;
+ \$config['kolab_ssl_verify_peer'] = false;
- \$rcmail_config['kolab_use_subscriptions'] = true;
+ \$config['kolab_use_subscriptions'] = true;
?>
diff --git a/share/templates/roundcubemail/kolab_auth.inc.php.tpl b/share/templates/roundcubemail/kolab_auth.inc.php.tpl
index 6044232..8fad27a 100644
--- a/share/templates/roundcubemail/kolab_auth.inc.php.tpl
+++ b/share/templates/roundcubemail/kolab_auth.inc.php.tpl
@@ -2,7 +2,7 @@
// The id of the LDAP address book (which refers to the rcmail_config['ldap_public'])
// or complete addressbook definition array.
- \$rcmail_config['kolab_auth_addressbook'] = Array(
+ \$config['kolab_auth_addressbook'] = Array(
'name' => 'Kolab Auth',
'hosts' => Array('localhost'),
'port' => 389,
@@ -35,36 +35,36 @@
// This will overwrite defined filter
- \$rcmail_config['kolab_auth_filter'] = '(&' . '$ldap_user_filter' . '(|(uid=%u)(mail=%fu)(alias=%fu)))';
+ \$config['kolab_auth_filter'] = '(&' . '$ldap_user_filter' . '(|(uid=%u)(mail=%fu)(alias=%fu)))';
// Use this fields (from fieldmap configuration) to get authentication ID
- \$rcmail_config['kolab_auth_login'] = 'email';
+ \$config['kolab_auth_login'] = 'email';
// Use this fields (from fieldmap configuration) for default identity
- \$rcmail_config['kolab_auth_name'] = 'name';
- \$rcmail_config['kolab_auth_alias'] = 'alias';
- \$rcmail_config['kolab_auth_email'] = 'email';
+ \$config['kolab_auth_name'] = 'name';
+ \$config['kolab_auth_alias'] = 'alias';
+ \$config['kolab_auth_email'] = 'email';
if (preg_match('/\/helpdesk-login\//', \$_SERVER["REQUEST_URI"]) ) {
// Login and password of the admin user. Enables "Login As" feature.
- \$rcmail_config['kolab_auth_admin_login'] = '$imap_admin_login';
- \$rcmail_config['kolab_auth_admin_password'] = '$imap_admin_password';
+ \$config['kolab_auth_admin_login'] = '$imap_admin_login';
+ \$config['kolab_auth_admin_password'] = '$imap_admin_password';
- \$rcmail_config['kolab_auth_auditlog'] = true;
+ \$config['kolab_auth_auditlog'] = true;
}
// Administrative role field (from fieldmap configuration) which must be filled with
// specified value which adds privilege to login as another user.
- \$rcmail_config['kolab_auth_role'] = 'role';
- \$rcmail_config['kolab_auth_role_value'] = 'cn=kolab-admin,$ldap_base_dn';
+ \$config['kolab_auth_role'] = 'role';
+ \$config['kolab_auth_role_value'] = 'cn=kolab-admin,$ldap_base_dn';
// Administrative group name to which user must be assigned to
// which adds privilege to login as another user.
- \$rcmail_config['kolab_auth_group'] = 'Kolab Helpdesk';
+ \$config['kolab_auth_group'] = 'Kolab Helpdesk';
- if (file_exists(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
- include_once(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
+ if (file_exists(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
+ include_once(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
}
?>
diff --git a/share/templates/roundcubemail/kolab_files.inc.php.tpl b/share/templates/roundcubemail/kolab_files.inc.php.tpl
new file mode 100644
index 0000000..1c5fced
--- /dev/null
+++ b/share/templates/roundcubemail/kolab_files.inc.php.tpl
@@ -0,0 +1,15 @@
+<?php
+
+// URL of kolab-chwala installation
+\$config['kolab_files_url'] = 'http://' . \$_SERVER['HTTP_HOST'] . '/chwala/';
+
+// List of files list columns. Available are: name, size, mtime, type
+\$config['kolab_files_list_cols'] = array('name', 'mtime', 'size');
+
+// Name of the column to sort files list by
+\$config['kolab_files_sort_col'] = 'name';
+
+// Order of the files list sort
+\$config['kolab_files_sort_order'] = 'asc';
+
+?>
diff --git a/share/templates/roundcubemail/kolab_folders.inc.php.tpl b/share/templates/roundcubemail/kolab_folders.inc.php.tpl
index 107ccec..93f6eec 100644
--- a/share/templates/roundcubemail/kolab_folders.inc.php.tpl
+++ b/share/templates/roundcubemail/kolab_folders.inc.php.tpl
@@ -1,19 +1,19 @@
<?php
- \$rcmail_config['kolab_folders_configuration_default'] = 'Configuration';
- \$rcmail_config['kolab_folders_event_default'] = 'Calendar';
- \$rcmail_config['kolab_folders_contact_default'] = 'Contacts';
- \$rcmail_config['kolab_folders_task_default'] = '';
- \$rcmail_config['kolab_folders_note_default'] = '';
- \$rcmail_config['kolab_folders_journal_default'] = '';
- \$rcmail_config['kolab_folders_mail_inbox'] = 'INBOX';
- \$rcmail_config['kolab_folders_mail_drafts'] = 'Drafts';
- \$rcmail_config['kolab_folders_mail_sentitems'] = 'Sent';
- \$rcmail_config['kolab_folders_mail_junkemail'] = 'Spam';
- \$rcmail_config['kolab_folders_mail_outbox'] = '';
- \$rcmail_config['kolab_folders_mail_wastebasket'] = 'Trash';
+ \$config['kolab_folders_configuration_default'] = 'Configuration';
+ \$config['kolab_folders_event_default'] = 'Calendar';
+ \$config['kolab_folders_contact_default'] = 'Contacts';
+ \$config['kolab_folders_task_default'] = '';
+ \$config['kolab_folders_note_default'] = '';
+ \$config['kolab_folders_journal_default'] = '';
+ \$config['kolab_folders_mail_inbox'] = 'INBOX';
+ \$config['kolab_folders_mail_drafts'] = 'Drafts';
+ \$config['kolab_folders_mail_sentitems'] = 'Sent';
+ \$config['kolab_folders_mail_junkemail'] = 'Spam';
+ \$config['kolab_folders_mail_outbox'] = '';
+ \$config['kolab_folders_mail_wastebasket'] = 'Trash';
- if (file_exists(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
- include_once(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
+ if (file_exists(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
+ include_once(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
}
?>
diff --git a/share/templates/roundcubemail/main.inc.php.tpl b/share/templates/roundcubemail/main.inc.php.tpl
deleted file mode 100644
index 9e4d14f..0000000
--- a/share/templates/roundcubemail/main.inc.php.tpl
+++ /dev/null
@@ -1,265 +0,0 @@
-<?php
- \$rcmail_config = array();
-
- \$rcmail_config['imap_cache'] = 'db';
- \$rcmail_config['messages_cache'] = 'db';
- \$rcmail_config['force_https'] = false;
- \$rcmail_config['use_https'] = false;
- \$rcmail_config['login_autocomplete'] = 0;
- \$rcmail_config['session_lifetime'] = 180;
- \$rcmail_config['ip_check'] = false;
- \$rcmail_config['referer_check'] = false;
- \$rcmail_config['password_charset'] = 'ISO-8859-1';
- \$rcmail_config['sendmail_delay'] = 0;
- \$rcmail_config['max_recipients'] = 0;
- \$rcmail_config['max_group_members'] = 0;
- \$rcmail_config['useragent'] = 'Roundcube Webmail/'.RCMAIL_VERSION;
- \$rcmail_config['include_host_config'] = false;
- \$rcmail_config['generic_message_footer'] = '';
- \$rcmail_config['generic_message_footer_html'] = '';
- \$rcmail_config['http_received_header'] = true;
- \$rcmail_config['http_received_header_encrypt'] = true;
- \$rcmail_config['mail_header_delimiter'] = NULL;
- \$rcmail_config['line_length'] = 72;
- \$rcmail_config['send_format_flowed'] = true;
- \$rcmail_config['dont_override'] = Array('skin');
- \$rcmail_config['identities_level'] = 0;
- \$rcmail_config['contact_photo_size'] = 160;
- \$rcmail_config['email_dns_check'] = false;
-
- \$rcmail_config['message_sort_col'] = '';
- \$rcmail_config['message_sort_order'] = 'DESC';
- \$rcmail_config['list_cols'] = array('subject', 'status', 'from', 'date', 'size', 'flag', 'attachment');
- \$rcmail_config['language'] = null;
- \$rcmail_config['date_short'] = 'D H:i';
- \$rcmail_config['date_long'] = 'd.m.Y H:i';
- \$rcmail_config['date_today'] = 'H:i';
- \$rcmail_config['date_format'] = 'Y-m-d';
- \$rcmail_config['quota_zero_as_unlimited'] = false;
- \$rcmail_config['enable_spellcheck'] = true;
- \$rcmail_config['spellcheck_dictionary'] = true;
- \$rcmail_config['spellcheck_engine'] = 'googie';
- \$rcmail_config['spellcheck_uri'] = '';
- \$rcmail_config['spellcheck_languages'] = NULL;
- \$rcmail_config['spellcheck_ignore_caps'] = true;
- \$rcmail_config['spellcheck_ignore_nums'] = true;
- \$rcmail_config['spellcheck_ignore_syms'] = true;
- \$rcmail_config['max_pagesize'] = 200;
- \$rcmail_config['min_keep_alive'] = 60;
- \$rcmail_config['undo_timeout'] = 10;
- \$rcmail_config['upload_progress'] = 2;
- \$rcmail_config['address_book_type'] = 'ldap';
- \$rcmail_config['autocomplete_min_length'] = 3;
- \$rcmail_config['autocomplete_threads'] = 0;
- \$rcmail_config['autocomplete_max'] = 15;
- \$rcmail_config['address_template'] = '{street}<br/>{locality} {zipcode}<br/>{country} {region}';
- \$rcmail_config['default_charset'] = 'ISO-8859-1';
- \$rcmail_config['pagesize'] = 40;
- \$rcmail_config['timezone'] = 'auto';
- \$rcmail_config['dst_active'] = (bool)date('I');
- \$rcmail_config['prefer_html'] = true;
- \$rcmail_config['show_images'] = 0;
- \$rcmail_config['prettydate'] = true;
- \$rcmail_config['draft_autosave'] = 300;
- \$rcmail_config['preview_pane'] = true;
- \$rcmail_config['preview_pane_mark_read'] = 0;
- \$rcmail_config['logout_purge'] = false;
- \$rcmail_config['logout_expunge'] = false;
- \$rcmail_config['inline_images'] = true;
- \$rcmail_config['mime_param_folding'] = 1;
- \$rcmail_config['skip_deleted'] = true;
- \$rcmail_config['read_when_deleted'] = true;
- \$rcmail_config['flag_for_deletion'] = true;
- \$rcmail_config['keep_alive'] = 300;
- \$rcmail_config['check_all_folders'] = false;
- \$rcmail_config['display_next'] = true;
- \$rcmail_config['autoexpand_threads'] = 2;
- \$rcmail_config['top_posting'] = false;
- \$rcmail_config['strip_existing_sig'] = true;
- \$rcmail_config['show_sig'] = 1;
- \$rcmail_config['sig_above'] = false;
- \$rcmail_config['force_7bit'] = false;
- \$rcmail_config['search_mods'] = null;
- \$rcmail_config['delete_always'] = true;
- \$rcmail_config['mdn_requests'] = 0;
- \$rcmail_config['mdn_default'] = false;
- \$rcmail_config['dsn_default'] = false;
- \$rcmail_config['reply_same_folder'] = false;
-
- \$rcmail_config['plugins'] = array(
- 'acl',
- 'archive',
- 'calendar',
- 'http_authentication',
- 'jqueryui',
- 'kolab_activesync',
- 'kolab_addressbook',
- 'kolab_auth',
- 'kolab_config',
- 'kolab_folders',
- 'libkolab',
- 'libcalendaring',
- 'listcommands',
- 'managesieve',
- 'newmail_notifier',
- 'odfviewer',
- 'password',
- 'redundant_attachments',
- 'tasklist',
- 'threading_as_default',
- // contextmenu must be after kolab_addressbook (#444)
- 'contextmenu',
- );
-
- if (file_exists(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
- include_once(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
- }
-
- // Re-apply mandatory settings here.
-
- \$rcmail_config['debug_level'] = 0;
- \$rcmail_config['devel_mode'] = false;
- \$rcmail_config['log_driver'] = 'file';
- \$rcmail_config['log_date_format'] = 'd-M-Y H:i:s,u O';
- \$rcmail_config['syslog_id'] = 'roundcube';
- \$rcmail_config['syslog_facility'] = LOG_USER;
- \$rcmail_config['smtp_log'] = true;
- \$rcmail_config['log_logins'] = true;
- \$rcmail_config['log_session'] = true;
- \$rcmail_config['sql_debug'] = true;
- \$rcmail_config['memcache_debug'] = true;
- \$rcmail_config['imap_debug'] = true;
- \$rcmail_config['ldap_debug'] = true;
- \$rcmail_config['smtp_debug'] = true;
-
- \$rcmail_config['product_name'] = 'Kolab Groupware';
- \$rcmail_config['skin'] = 'larry';
- \$rcmail_config['skin_logo'] = 'skins/kolab/images/kolab_logo.png';
- \$rcmail_config['skin_include_php'] = false;
- \$rcmail_config['mime_magic'] = '/usr/share/misc/magic';
- \$rcmail_config['im_identify_path'] = '/usr/bin/identify';
- \$rcmail_config['im_convert_path'] = '/usr/bin/convert';
- \$rcmail_config['login_lc'] = true;
- \$rcmail_config['auto_create_user'] = true;
- \$rcmail_config['enable_installer'] = false;
- \$rcmail_config['session_storage'] = 'db';
- \$rcmail_config['default_port'] = 143;
- \$rcmail_config['imap_auth_type'] = '';
- \$rcmail_config['imap_delimiter'] = '/';
- \$rcmail_config['imap_ns_personal'] = null;
- \$rcmail_config['imap_ns_other'] = null;
- \$rcmail_config['imap_ns_shared'] = null;
- \$rcmail_config['imap_force_caps'] = false;
- \$rcmail_config['imap_force_lsub'] = true;
- \$rcmail_config['imap_timeout'] = 0;
- \$rcmail_config['imap_auth_cid'] = null;
- \$rcmail_config['imap_auth_pw'] = null;
- \$rcmail_config['smtp_port'] = 587;
- \$rcmail_config['smtp_user'] = '%u';
- \$rcmail_config['smtp_pass'] = '%p';
- \$rcmail_config['smtp_auth_type'] = '';
- \$rcmail_config['smtp_auth_cid'] = null;
- \$rcmail_config['smtp_auth_pw'] = null;
- \$rcmail_config['smtp_helo_host'] = \$_SERVER["HTTP_HOST"];
- \$rcmail_config['smtp_timeout'] = 0;
- \$rcmail_config['log_dir'] = '/var/log/roundcubemail/';
- \$rcmail_config['temp_dir'] = '\${_tmppath}';
- \$rcmail_config['message_cache_lifetime'] = '10d';
-
- \$rcmail_config['archive_mbox'] = 'Archive';
- \$rcmail_config['drafts_mbox'] = 'Drafts';
- \$rcmail_config['junk_mbox'] = 'Spam';
- \$rcmail_config['sent_mbox'] = 'Sent';
- \$rcmail_config['trash_mbox'] = 'Trash';
- \$rcmail_config['default_imap_folders'] = array('INBOX', 'Drafts', 'Sent', 'Spam', 'Trash');
- \$rcmail_config['create_default_folders'] = true;
- \$rcmail_config['protect_default_folders'] = true;
-
- \$mandatory_plugins = Array(
- 'calendar',
- 'kolab_addressbook',
- 'kolab_auth',
- 'kolab_config',
- 'kolab_folders',
- 'libkolab',
- 'password',
- );
-
- foreach ( \$mandatory_plugins as \$num => \$plugin ) {
- if (!in_array(\$plugin, \$rcmail_config['plugins'])) {
- \$rcmail_config['plugins'][] = \$plugin;
- }
- }
-
- \$rcmail_config['default_host'] = 'tls://localhost';
- \$rcmail_config['smtp_server'] = 'tls://localhost';
- \$rcmail_config['session_domain'] = '';
- \$rcmail_config['des_key'] = "$des_key";
- \$rcmail_config['username_domain'] = '$primary_domain';
-
- \$rcmail_config['mail_domain'] = '';
-
- \$rcmail_config['ldap_public'] = array(
- 'kolab_addressbook' => array(
- 'name' => 'Global Address Book',
- 'hosts' => Array('localhost'),
- 'port' => 389,
- 'use_tls' => false,
- 'base_dn' => '$ldap_user_base_dn',
- 'user_specific' => true,
- 'bind_dn' => '%dn',
- 'bind_pass' => '',
- 'search_base_dn' => '$ldap_user_base_dn',
- 'search_bind_dn' => '$ldap_service_bind_dn',
- 'search_bind_pw' => '$ldap_service_bind_pw',
- 'search_filter' => '(&(objectClass=inetOrgPerson)(mail=%fu))',
- 'writable' => false,
- 'LDAP_Object_Classes' => array("top", "inetOrgPerson"),
- 'required_fields' => array("cn", "sn", "mail"),
- 'LDAP_rdn' => 'uid',
- 'ldap_version' => 3, // using LDAPv3
- 'search_fields' => array('displayname', 'mail'),
- 'sort' => array('displayname', 'sn', 'givenname', 'cn'),
- 'scope' => 'sub',
- 'filter' => '(objectClass=inetOrgPerson)',
- 'vlv' => false,
- 'vlv_search' => false,
- 'fuzzy_search' => true,
- 'sizelimit' => '0',
- 'timelimit' => '0',
- 'fieldmap' => Array(
- // Roundcube => LDAP
- 'name' => 'displayName',
- 'surname' => 'sn',
- 'firstname' => 'givenName',
- 'middlename' => 'initials',
- 'prefix' => 'title',
- 'email:primary' => 'mail',
- 'email:alias' => 'alias',
- 'email:personal' => 'mailalternateaddress',
- 'phone:main' => 'telephoneNumber',
- 'phone:work' => 'alternateTelephoneNumber',
- 'phone:mobile' => 'mobile',
- 'phone:work2' => 'blackberry',
- 'jobtitle' => 'title',
- 'manager' => 'manager',
- 'assistant' => 'secretary',
- 'photo' => 'jpegphoto'
- ),
- 'groups' => Array(
- 'base_dn' => '$ldap_group_base_dn',
- 'filter' => '(&' . '$ldap_group_filter' . '(mail=*))',
- 'object_classes' => Array("top", "groupOfUniqueNames"),
- 'member_attr' => 'uniqueMember',
- ),
- ),
- );
-
- \$rcmail_config['autocomplete_addressbooks'] = Array(
- 'kolab_addressbook'
- );
-
- \$rcmail_config['autocomplete_single'] = true;
-
- \$rcmail_config['htmleditor'] = 0;
-?>
diff --git a/share/templates/roundcubemail/managesieve.inc.php.tpl b/share/templates/roundcubemail/managesieve.inc.php.tpl
index 8ab9998..c05a096 100644
--- a/share/templates/roundcubemail/managesieve.inc.php.tpl
+++ b/share/templates/roundcubemail/managesieve.inc.php.tpl
@@ -1,18 +1,18 @@
<?php
- \$rcmail_config['managesieve_port'] = 4190;
- \$rcmail_config['managesieve_host'] = '%h';
- \$rcmail_config['managesieve_auth_type'] = 'PLAIN';
- \$rcmail_config['managesieve_auth_cid'] = null;
- \$rcmail_config['managesieve_auth_pw'] = null;
- \$rcmail_config['managesieve_usetls'] = true;
- \$rcmail_config['managesieve_default'] = '/etc/dovecot/sieve/global';
- \$rcmail_config['managesieve_mbox_encoding'] = 'UTF-8';
- \$rcmail_config['managesieve_replace_delimiter'] = '';
- \$rcmail_config['managesieve_disabled_extensions'] = array();
- \$rcmail_config['managesieve_debug'] = true;
+ \$config['managesieve_port'] = 4190;
+ \$config['managesieve_host'] = '%h';
+ \$config['managesieve_auth_type'] = 'PLAIN';
+ \$config['managesieve_auth_cid'] = null;
+ \$config['managesieve_auth_pw'] = null;
+ \$config['managesieve_usetls'] = true;
+ \$config['managesieve_default'] = '/etc/dovecot/sieve/global';
+ \$config['managesieve_mbox_encoding'] = 'UTF-8';
+ \$config['managesieve_replace_delimiter'] = '';
+ \$config['managesieve_disabled_extensions'] = array();
+ \$config['managesieve_debug'] = true;
- if (file_exists(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
- include_once(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
+ if (file_exists(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
+ include_once(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
}
?>
diff --git a/share/templates/roundcubemail/owncloud.inc.php.tpl b/share/templates/roundcubemail/owncloud.inc.php.tpl
index 089849a..513a482 100644
--- a/share/templates/roundcubemail/owncloud.inc.php.tpl
+++ b/share/templates/roundcubemail/owncloud.inc.php.tpl
@@ -1,9 +1,9 @@
<?php
// ownCloud URL
- \$rcmail_config['owncloud_url'] = 'http://' . \$_SERVER["HTTP_HOST"] . '/owncloud';
+ \$config['owncloud_url'] = 'http://' . \$_SERVER["HTTP_HOST"] . '/owncloud';
- if (file_exists(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
- include_once(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
+ if (file_exists(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
+ include_once(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
}
?>
diff --git a/share/templates/roundcubemail/password.inc.php.tpl b/share/templates/roundcubemail/password.inc.php.tpl
index 7aa45db..ca3f815 100644
--- a/share/templates/roundcubemail/password.inc.php.tpl
+++ b/share/templates/roundcubemail/password.inc.php.tpl
@@ -4,22 +4,22 @@
// -----------------------
// A driver to use for password change. Default: "sql".
// See README file for list of supported driver names.
- \$rcmail_config['password_driver'] = 'ldap';
+ \$config['password_driver'] = 'ldap';
// Determine whether current password is required to change password.
// Default: false.
- \$rcmail_config['password_confirm_current'] = true;
+ \$config['password_confirm_current'] = true;
// Require the new password to be a certain length.
// set to blank to allow passwords of any length
- \$rcmail_config['password_minimum_length'] = 6;
+ \$config['password_minimum_length'] = 6;
// Require the new password to contain a letter and punctuation character
// Change to false to remove this check.
- \$rcmail_config['password_require_nonalpha'] = false;
+ \$config['password_require_nonalpha'] = false;
// Enables logging of password changes into logs/password
- \$rcmail_config['password_log'] = true;
+ \$config['password_log'] = true;
// LDAP and LDAP_SIMPLE Driver options
@@ -28,41 +28,41 @@
// You can provide one or several hosts in an array in which case the hosts are tried from left to right.
// Exemple: array('ldap1.exemple.com', 'ldap2.exemple.com');
// Default: 'localhost'
- \$rcmail_config['password_ldap_host'] = 'localhost';
+ \$config['password_ldap_host'] = 'localhost';
// LDAP server port to connect to
// Default: '389'
- \$rcmail_config['password_ldap_port'] = '389';
+ \$config['password_ldap_port'] = '389';
// TLS is started after connecting
// Using TLS for password modification is recommended.
// Default: false
- \$rcmail_config['password_ldap_starttls'] = false;
+ \$config['password_ldap_starttls'] = false;
// LDAP version
// Default: '3'
- \$rcmail_config['password_ldap_version'] = '3';
+ \$config['password_ldap_version'] = '3';
// LDAP base name (root directory)
// Exemple: 'dc=exemple,dc=com'
- \$rcmail_config['password_ldap_basedn'] = '$ldap_user_base_dn';
+ \$config['password_ldap_basedn'] = '$ldap_user_base_dn';
// LDAP connection method
// There is two connection method for changing a user's LDAP password.
// 'user': use user credential (recommanded, require password_confirm_current=true)
// 'admin': use admin credential (this mode require password_ldap_adminDN and password_ldap_adminPW)
// Default: 'user'
- \$rcmail_config['password_ldap_method'] = 'user';
+ \$config['password_ldap_method'] = 'user';
// LDAP Admin DN
// Used only in admin connection mode
// Default: null
- \$rcmail_config['password_ldap_adminDN'] = null;
+ \$config['password_ldap_adminDN'] = null;
// LDAP Admin Password
// Used only in admin connection mode
// Default: null
- \$rcmail_config['password_ldap_adminPW'] = null;
+ \$config['password_ldap_adminPW'] = null;
// LDAP user DN mask
// The user's DN is mandatory and as we only have his login,
@@ -72,7 +72,7 @@
// '%domain' will be replaced by the current roundcube user's domain part
// '%dc' will be replaced by domain name hierarchal string e.g. "dc=test,dc=domain,dc=com"
// Exemple: 'uid=%login,ou=people,dc=exemple,dc=com'
- // \$rcmail_config['password_ldap_userDN_mask'] = 'uid=%login,ou=people,dc=exemple,dc=com';
+ // \$config['password_ldap_userDN_mask'] = 'uid=%login,ou=people,dc=exemple,dc=com';
// LDAP search DN
// The DN roundcube should bind with to find out user's DN
@@ -83,7 +83,7 @@
// users login to find his DN instead. A common reason might be that
// your users are placed under different ou's like engineering or
// sales which cannot be derived from their login only.
- \$rcmail_config['password_ldap_searchDN'] = '$ldap_service_bind_dn';
+ \$config['password_ldap_searchDN'] = '$ldap_service_bind_dn';
// LDAP search password
// If password_ldap_searchDN is set, the password to use for
@@ -93,13 +93,13 @@
// is only accesible to roundcube and don't forget to restrict roundcube's access to
// your directory as much as possible using ACLs. Should this password be compromised
// you want to minimize the damage.
- \$rcmail_config['password_ldap_searchPW'] = '$ldap_service_bind_pw';
+ \$config['password_ldap_searchPW'] = '$ldap_service_bind_pw';
// LDAP search base
// If password_ldap_searchDN is set, the base to search in using the filter below.
// Note that you should comment out the default password_ldap_userDN_mask setting
// for this to take effect.
- \$rcmail_config['password_ldap_search_base'] = '$ldap_user_base_dn';
+ \$config['password_ldap_search_base'] = '$ldap_user_base_dn';
// LDAP search filter
// If password_ldap_searchDN is set, the filter to use when
@@ -111,7 +111,7 @@
// '%dc' will be replaced by domain name hierarchal string e.g. "dc=test,dc=domain,dc=com"
// Example: '(uid=%login)'
// Example: '(&(objectClass=posixAccount)(uid=%login))'
- \$rcmail_config['password_ldap_search_filter'] = '(&(|(uid=%login)(mail=%login)(mailAlternateAddress=%login)(alias=%login))(objectclass=kolabinetorgperson))';
+ \$config['password_ldap_search_filter'] = '(&(|(uid=%login)(mail=%login)(mailAlternateAddress=%login)(alias=%login))(objectclass=kolabinetorgperson))';
// LDAP password hash type
// Standard LDAP encryption type which must be one of: crypt,
@@ -119,37 +119,37 @@
// Please note that most encodage types require external libraries
// to be included in your PHP installation, see function hashPassword in drivers/ldap.php for more info.
// Default: 'crypt'
- \$rcmail_config['password_ldap_encodage'] = 'clear';
+ \$config['password_ldap_encodage'] = 'clear';
// LDAP password attribute
// Name of the ldap's attribute used for storing user password
// Default: 'userPassword'
- \$rcmail_config['password_ldap_pwattr'] = 'userPassword';
+ \$config['password_ldap_pwattr'] = 'userPassword';
// LDAP password force replace
// Force LDAP replace in cases where ACL allows only replace not read
// See http://pear.php.net/package/Net_LDAP2/docs/latest/Net_LDAP2/Net_LDAP2_Entry.html#methodreplace
// Default: true
- \$rcmail_config['password_ldap_force_replace'] = true;
+ \$config['password_ldap_force_replace'] = true;
// LDAP Password Last Change Date
// Some places use an attribute to store the date of the last password change
// The date is meassured in "days since epoch" (an integer value)
// Whenever the password is changed, the attribute will be updated if set (e.g. shadowLastChange)
- \$rcmail_config['password_ldap_lchattr'] = '';
+ \$config['password_ldap_lchattr'] = '';
// LDAP Samba password attribute, e.g. sambaNTPassword
// Name of the LDAP's Samba attribute used for storing user password
- \$rcmail_config['password_ldap_samba_pwattr'] = '';
+ \$config['password_ldap_samba_pwattr'] = '';
// LDAP Samba Password Last Change Date attribute, e.g. sambaPwdLastSet
// Some places use an attribute to store the date of the last password change
// The date is meassured in "seconds since epoch" (an integer value)
// Whenever the password is changed, the attribute will be updated if set
- \$rcmail_config['password_ldap_samba_lchattr'] = '';
+ \$config['password_ldap_samba_lchattr'] = '';
- if (file_exists(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
- include_once(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
+ if (file_exists(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
+ include_once(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
}
?>
diff --git a/share/templates/roundcubemail/recipient_to_contact.inc.php.tpl b/share/templates/roundcubemail/recipient_to_contact.inc.php.tpl
index f3b8d2f..b41ad79 100644
--- a/share/templates/roundcubemail/recipient_to_contact.inc.php.tpl
+++ b/share/templates/roundcubemail/recipient_to_contact.inc.php.tpl
@@ -1,4 +1,4 @@
<?php
- \$rcmail_config['recipient_to_contact_addressbooks'] = array();
- \$rcmail_config['recipient_to_contact_enabled_by_default'] = true;
+ \$config['recipient_to_contact_addressbooks'] = array();
+ \$config['recipient_to_contact_enabled_by_default'] = true;
?> \ No newline at end of file
diff --git a/share/templates/roundcubemail/terms.inc.php.tpl b/share/templates/roundcubemail/terms.inc.php.tpl
index 05e9f36..646197d 100644
--- a/share/templates/roundcubemail/terms.inc.php.tpl
+++ b/share/templates/roundcubemail/terms.inc.php.tpl
@@ -3,20 +3,20 @@
/* terms plugin */
// log accepted terms
- \$rcmail_config['terms_log'] = true;
+ \$config['terms_log'] = true;
// renew agreement if older than YYYY-MM-DD HH:MM:SS
// NOTICE: Must be in past and set accordingly to server Timezone!!!
- \$rcmail_config['terms_date'] = '2011-02-24 00:00:00';
+ \$config['terms_date'] = '2011-02-24 00:00:00';
// renew agreement automatically afer x days
- \$rcmail_config['terms_renew'] = 28; // 0 = never
+ \$config['terms_renew'] = 28; // 0 = never
// always request terms agreement after login
- \$rcmail_config['terms_always'] = false;
+ \$config['terms_always'] = false;
- if (file_exists(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
- include_once(RCMAIL_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
+ if (file_exists(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__))) {
+ include_once(RCUBE_CONFIG_DIR . '/' . \$_SERVER["HTTP_HOST"] . '/' . basename(__FILE__));
}
?>
diff --git a/share/templates/zpush/config.php.tpl b/share/templates/zpush/config.php.tpl
deleted file mode 100644
index 9480ae4..0000000
--- a/share/templates/zpush/config.php.tpl
+++ /dev/null
@@ -1,106 +0,0 @@
-<?php
- /***********************************************
- * File : config.php
- * Project : Z-Push
- * Descr : Main configuration file
- *
- */
-
- define('KOLAB_SERVER', "$ldap_ldap_uri");
- define('KOLAB_LDAP_BASE',"$ldap_base_dn");
- define('KOLAB_BIND_DN',"$ldap_service_bind_dn");
- define('KOLAB_BIND_PW',"$ldap_service_bind_pw");
- define("KOLAB_LDAP_ACL","");
- define('KOLAB_IMAP_SERVER', "$imap_server");
-
- // Defines the default time zone
- if (function_exists("date_default_timezone_set")){
- date_default_timezone_set(date_default_timezone_get());
- }
-
- // Defines the base path on the server, terminated by a slash
- define('BASE_PATH', dirname(\$_SERVER['SCRIPT_FILENAME']) . "/");
-
- // Define the include paths
- ini_set(
- 'include_path',
- BASE_PATH . "include/" . PATH_SEPARATOR .
- BASE_PATH . PATH_SEPARATOR .
- ini_get('include_path') . PATH_SEPARATOR .
- "/usr/share/php/" . PATH_SEPARATOR .
- "/usr/share/php5/" . PATH_SEPARATOR .
- "/usr/share/pear/"
- );
-
- define('STATE_DIR', 'state');
-
- // Try to set unlimited timeout
- define('SCRIPT_TIMEOUT', 0);
-
- //Max size of attachments to display inline. Default is 1MB
- define('MAX_EMBEDDED_SIZE', 1048576);
-
- // Device Provisioning
- define('PROVISIONING', true);
-
- // This option allows the 'loose enforcement' of the provisioning policies for older
- // devices which don't support provisioning (like WM 5 and HTC Android Mail) - dw2412 contribution
- // false (default) - Enforce provisioning for all devices
- // true - allow older devices, but enforce policies on devices which support it
- define('LOOSE_PROVISIONING', false);
- // Default conflict preference
- // Some devices allow to set if the server or PIM (mobile)
- // should win in case of a synchronization conflict
- // SYNC_CONFLICT_OVERWRITE_SERVER - Server is overwritten, PIM wins
- // SYNC_CONFLICT_OVERWRITE_PIM - PIM is overwritten, Server wins (default)
- define('SYNC_CONFLICT_DEFAULT', SYNC_CONFLICT_OVERWRITE_PIM);
-
- // The data providers that we are using (see configuration below
- \$BACKEND_PROVIDER = "BackendKolab";
-
- define("KOLAB_LDAP_ACL","");
- define('KOLAB_IMAP_NAMESPACES', Array(
- 'personal' => "",
- 'shared' => "Shared Folders",
- 'users' => "Other Users"
- )
- );
-
- define('KOLAB_IMAP_PORT', 143);
- define('KOLAB_IMAP_OPTIONS', "/tls/novalidate-cert");
-
- define('KOLAB_INDEX',"/var/cache/kolab/z-push/kolabindex");
-
- //KolabMode
- // 0 = FlatMode
- // 1 = FolderMode
- // 2 = try to determine the mode
- define("KOLAB_MODE",2);
- // define which mobile support foldermode
- // this list is checked if KOLAB_MODE is set to 2
- define("KOLAB_MOBILES_FOLDERMODE","iphone:ipod:ipad");
- // folders by default if annotation is not found
- // possiblename1:possiblename2: ......
- // if no folders found the last found will be the default
- define('KOLAB_DEFAULTFOLDER_DIARY',"calendar:kalender:calendrier:agenda");
- define('KOLAB_DEFAULTFOLDER_CONTACT',"contacts:kontact");
- define('KOLAB_DEFAULTFOLDER_TASK',"task:taske");
- // If 1: shared folders will be read-only, even if the user have rights on it
- define('KOLAB_SHAREDFOLDERS_RO',"1");
-
- // Logfile
- define('KOLAB_LOGFILE',"/var/log/z-push/access.log");
- //For Gal
- define('SYNC_GAL_DISPLAYNAME','cn');
- define('SYNC_GAL_PHONE','telephonenumber');
- define('SYNC_GAL_OFFICE', '');
- define('SYNC_GAL_TITLE','title');
- define('SYNC_GAL_COMPANY','o');
- define('SYNC_GAL_ALIAS','uid');
- define('SYNC_GAL_FIRSTNAME','givenname');
- define('SYNC_GAL_LASTNAME','sn');
- define('SYNC_GAL_HOMEPHONE','homephone');
- define('SYNC_GAL_MOBILEPHONE','mobile');
- define('SYNC_GAL_EMAILADDRESS','mail');
-
-?>
diff --git a/test-wallace.py b/test-wallace.py
index 8da3475..c49c486 100755
--- a/test-wallace.py
+++ b/test-wallace.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/tests/functional/purge_users.py b/tests/functional/purge_users.py
index 5bc1b82..17db9d7 100644
--- a/tests/functional/purge_users.py
+++ b/tests/functional/purge_users.py
@@ -11,7 +11,7 @@ def purge_users():
users = wap_client.users_list()
for user in users['list']:
- wap_client.user_delete({'user': user})
+ wap_client.user_delete({'id': user})
from tests.functional.purge_imap import purge_imap
purge_imap()
diff --git a/tests/functional/test_wallace/test_001_user_add.py b/tests/functional/test_wallace/test_001_user_add.py
index 9a2c587..d4e620a 100644
--- a/tests/functional/test_wallace/test_001_user_add.py
+++ b/tests/functional/test_wallace/test_001_user_add.py
@@ -24,7 +24,7 @@ class TestUserAdd(unittest.TestCase):
}
self.jane = {
- 'local': 'john.doe',
+ 'local': 'jane.doe',
'domain': 'example.org'
}
diff --git a/tests/functional/test_wap_client/test_001_connect.py b/tests/functional/test_wap_client/test_001_connect.py
index 42b8aa3..aa0c069 100644
--- a/tests/functional/test_wap_client/test_001_connect.py
+++ b/tests/functional/test_wap_client/test_001_connect.py
@@ -31,8 +31,12 @@ class TestConnect(unittest.TestCase):
self.assertEqual(result['reason'], "Unknown service")
self.assertEqual(result['code'], 400)
- def test_003_domains_list(self):
+ def test_004_domains_list(self):
result = wap_client.domains_list()
self.assertTrue(result.has_key('count'))
self.assertTrue(result.has_key('list'))
self.assertEqual(result['count'], len(result['list']))
+
+ def test_005_get_domain(self):
+ result = wap_client.request_raw('GET', 'system.get_domain')
+ self.assertEqual(result, {u'status': u'OK', u'result': {u'domain': u'example.org'}})
diff --git a/tests/functional/test_wap_client/test_006_form_value_select_options.py b/tests/functional/test_wap_client/test_006_form_value_select_options.py
new file mode 100644
index 0000000..92b4992
--- /dev/null
+++ b/tests/functional/test_wap_client/test_006_form_value_select_options.py
@@ -0,0 +1,31 @@
+import time
+import unittest
+
+import pykolab
+from pykolab import wap_client
+
+conf = pykolab.getConf()
+
+class TestFormValueListOptions(unittest.TestCase):
+
+ def test_001_list_options_user_preferredlanguage(self):
+ conf = pykolab.getConf()
+ conf.finalize_conf(fatal=False)
+
+ self.login = conf.get('ldap', 'bind_dn')
+ self.password = conf.get('ldap', 'bind_pw')
+ self.domain = conf.get('kolab', 'primary_domain')
+
+ result = wap_client.authenticate(self.login, self.password, self.domain)
+
+ attribute_values = wap_client.form_value_select_options(
+ 'user',
+ 1,
+ 'preferredlanguage'
+ )
+
+ self.assertTrue(attribute_values['preferredlanguage'].has_key('default'))
+ self.assertTrue(attribute_values['preferredlanguage'].has_key('list'))
+ self.assertTrue(len(attribute_values['preferredlanguage']['list']) > 1)
+ self.assertTrue(attribute_values['preferredlanguage']['default'] in attribute_values['preferredlanguage']['list'])
+
diff --git a/tests/functional/test_wap_client/test_007_policy_uid.py b/tests/functional/test_wap_client/test_007_policy_uid.py
new file mode 100644
index 0000000..534ebda
--- /dev/null
+++ b/tests/functional/test_wap_client/test_007_policy_uid.py
@@ -0,0 +1,176 @@
+from ConfigParser import RawConfigParser
+import time
+import unittest
+
+import pykolab
+from pykolab import wap_client
+from pykolab.auth import Auth
+from pykolab.imap import IMAP
+
+conf = pykolab.getConf()
+
+class TestPolicyUid(unittest.TestCase):
+
+ def remove_option(self, section, option):
+ self.config.remove_option(section, option)
+
+ fp = open(conf.config_file, "w")
+ self.config.write(fp)
+ fp.close()
+
+ def set(self, section, option, value):
+ self.config.set(section, option, value)
+
+ fp = open(conf.config_file, "w")
+ self.config.write(fp)
+ fp.close()
+
+ @classmethod
+ def setup_class(self, *args, **kw):
+ self.config = RawConfigParser()
+ self.config.read(conf.config_file)
+
+ from tests.functional.purge_users import purge_users
+ purge_users()
+
+ self.user = {
+ 'local': 'john.doe',
+ 'domain': 'example.org'
+ }
+
+ self.login = conf.get('ldap', 'bind_dn')
+ self.password = conf.get('ldap', 'bind_pw')
+ self.domain = conf.get('kolab', 'primary_domain')
+
+ result = wap_client.authenticate(self.login, self.password, self.domain)
+
+ @classmethod
+ def teardown_class(self, *args, **kw):
+ self.config.remove_option('example.org', 'policy_uid')
+
+ fp = open(conf.config_file, "w")
+ self.config.write(fp)
+ fp.close()
+
+ from tests.functional.purge_users import purge_users
+ purge_users()
+
+ def test_001_default(self):
+ from tests.functional.user_add import user_add
+ user_add("John", "Doe")
+ from tests.functional.synchronize import synchronize_once
+ synchronize_once()
+
+ auth = Auth()
+ auth.connect()
+
+ user = auth.find_recipient('john.doe@example.org')
+
+ user_info = wap_client.user_info(user)
+
+ self.assertEqual(user_info['uid'], "doe")
+
+ from tests.functional.purge_users import purge_users
+ purge_users()
+
+ def test_002_givenname_dot_surname(self):
+ self.set('example.org', 'policy_uid', '%(givenname)s.%(surname)s')
+
+ from tests.functional.user_add import user_add
+ user_add("John", "Doe")
+ from tests.functional.synchronize import synchronize_once
+ synchronize_once()
+
+ auth = Auth()
+ auth.connect()
+
+ user = auth.find_recipient('john.doe@example.org')
+
+ user_info = wap_client.user_info(user)
+
+ self.assertEqual(user_info['uid'], "John.Doe")
+
+ from tests.functional.purge_users import purge_users
+ purge_users()
+
+ def test_003_givenname_fc_dot_surname(self):
+ self.set('example.org', 'policy_uid', "'%(givenname)s'[0:1].%(surname)s")
+
+ from tests.functional.user_add import user_add
+ user_add("John", "Doe")
+ from tests.functional.synchronize import synchronize_once
+ synchronize_once()
+
+ auth = Auth()
+ auth.connect()
+
+ user = auth.find_recipient('john.doe@example.org')
+
+ user_info = wap_client.user_info(user)
+
+ self.assertEqual(user_info['uid'], "J.Doe")
+
+ from tests.functional.purge_users import purge_users
+ purge_users()
+
+ def test_004_givenname(self):
+ self.set('example.org', 'policy_uid', '%(givenname)s')
+
+ from tests.functional.user_add import user_add
+ user_add("John", "Doe")
+ from tests.functional.synchronize import synchronize_once
+ synchronize_once()
+
+ auth = Auth()
+ auth.connect()
+
+ user = auth.find_recipient('john.doe@example.org')
+
+ user_info = wap_client.user_info(user)
+
+ self.assertEqual(user_info['uid'], "John")
+
+ from tests.functional.purge_users import purge_users
+ purge_users()
+
+ def test_005_lowercase_givenname(self):
+ self.set('example.org', 'policy_uid', '%(givenname)s.lower()')
+
+ from tests.functional.user_add import user_add
+ user_add("John", "Doe")
+ from tests.functional.synchronize import synchronize_once
+ synchronize_once()
+
+ auth = Auth()
+ auth.connect()
+
+ user = auth.find_recipient('john.doe@example.org')
+
+ user_info = wap_client.user_info(user)
+
+ self.assertEqual(user_info['uid'], "john")
+
+ from tests.functional.purge_users import purge_users
+ purge_users()
+
+ def test_006_lowercase_givenname_surname(self):
+ self.set('example.org', 'policy_uid', "%(givenname)s.lower().%(surname)s.lower()")
+
+ from tests.functional.user_add import user_add
+ user_add("John", "Doe")
+ from tests.functional.synchronize import synchronize_once
+ synchronize_once()
+
+ auth = Auth()
+ auth.connect()
+
+ user = auth.find_recipient('john.doe@example.org')
+
+ user_info = wap_client.user_info(user)
+
+ self.assertEqual(user_info['uid'], "john.doe")
+
+ from tests.functional.purge_users import purge_users
+ purge_users()
+
+
diff --git a/tests/functional/user_add.py b/tests/functional/user_add.py
index 2fc44cf..6af0419 100644
--- a/tests/functional/user_add.py
+++ b/tests/functional/user_add.py
@@ -59,12 +59,5 @@ def user_add(givenname, sn, preferredlanguage='en_US'):
fvg_params['type_id'] = user_type_id
fvg_params['attributes'] = [attr for attr in user_type_info['auto_form_fields'].keys() if not attr in params.keys()]
- exec("retval = wap_client.form_value_generate(%r)" % (params))
-
- for attribute in user_type_info['auto_form_fields'].keys():
- params[attribute] = retval[attribute]
-
- params['userpassword'] = user_details['userpassword']
-
result = wap_client.user_add(params)
diff --git a/ucs/kolab_sieve.py b/ucs/kolab_sieve.py
index f2b8df0..bf593f3 100755
--- a/ucs/kolab_sieve.py
+++ b/ucs/kolab_sieve.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/ucs/listener.py b/ucs/listener.py
index ea19d02..232675e 100755
--- a/ucs/listener.py
+++ b/ucs/listener.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -91,6 +91,32 @@ def handler(*args, **kw):
if isinstance(new, dict) and len(new.keys()) > 0:
log.info("Modify entry %r" % (dn))
+ mailserver_attribute = conf.get('ldap', 'mailserver_attribute').lower()
+
+ if mailserver_attribute == None:
+ log.error("Mail server attribute is not set")
+ return
+
+ if old.has_key(mailserver_attribute):
+ log.info("Modified entry %r has mail server attribute %s: %r" % (dn, mailserver_attribute, new[mailserver_attribute]))
+
+ if not old[mailserver_attribute] == constants.fqdn:
+ # Even though the new mailserver can be us, it is the
+ # *current* mail server that needs to push for the XFER.
+ log.info("The mail server for user %r is set, and it is not me (%r)" % (dn, old[mailserver_attribute]))
+ return
+
+ else:
+ # If old has no mailserver attribute, but new does, we need to create
+ # the user locally.
+ if new.has_key(mailserver_attribute):
+ if not new[mailserver_attribute] == constants.fqdn:
+ log.info("The mail server for user %r is set (in new, not old), but it is not me (%r)" % (dn, new[mailserver_attribute]))
+ return
+ else:
+ log.info("Entry %r does not have a mail server attribute." % (dn))
+ return
+
auth._auth._synchronize_callback(
change_type = 'modify',
previous_dn = None,
@@ -102,6 +128,25 @@ def handler(*args, **kw):
else:
log.info("Delete entry %r" % (dn))
+ # See if the mailserver_attribute exists
+ mailserver_attribute = conf.get('ldap', 'mailserver_attribute').lower()
+
+ if mailserver_attribute == None:
+ log.error("Mail server attribute is not set")
+ # TODO: Perhaps, query for IMAP servers. If there is only one,
+ # we know what to do.
+ return
+
+ if old.has_key(mailserver_attribute):
+ log.info("Deleted entry %r has mail server attribute %s: %r" % (dn, mailserver_attribute, old[mailserver_attribute]))
+
+ if not old[mailserver_attribute] == constants.fqdn:
+ log.info("The mail server for user %r is set, and it is not me (%r)" % (dn, old[mailserver_attribute]))
+ return
+
+ else:
+ log.info("Entry deletion notification for %r does not have a mail server attribute specified." % (dn))
+
auth._auth._synchronize_callback(
change_type = 'delete',
previous_dn = None,
@@ -130,6 +175,10 @@ def handler(*args, **kw):
log.info("The mail server for user %r is set, and it is not me (%r)" % (dn, new[mailserver_attribute]))
return
+ else:
+ log.info("Added entry %r does not have a mail server attribute set." % (dn))
+ return
+
auth._auth._synchronize_callback(
change_type = 'add',
previous_dn = None,
diff --git a/wallace.py b/wallace.py
index 3a5bd01..c1d4567 100755
--- a/wallace.py
+++ b/wallace.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/wallace/__init__.py b/wallace/__init__.py
index 56d7173..2db963e 100644
--- a/wallace/__init__.py
+++ b/wallace/__init__.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -63,6 +63,9 @@ def worker_process(*args, **kw):
class WallaceDaemon(object):
def __init__(self):
+ self.current_connections = 0
+ self.max_connections = 24
+
daemon_group = conf.add_cli_parser_option_group(_("Daemon Options"))
daemon_group.add_option(
@@ -215,21 +218,29 @@ class WallaceDaemon(object):
if stage.lower() == "defer":
continue
+ self.current_connections += 1
self.pool.apply_async(pickup_message, (filepath, (self.modules), {'module': module, 'stage': stage}))
+ self.current_connections -= 1
continue
+ self.current_connections += 1
self.pool.apply_async(pickup_message, (filepath, (self.modules)))
+ self.current_connections -= 1
try:
while 1:
+ while self.current_connections >= self.max_connections:
+ time.sleep(0.5)
+
pair = s.accept()
log.info(_("Accepted connection"))
if not pair == None:
+ self.current_connections += 1
connection, address = pair
- #print "Accepted connection from %r" % (address)
channel = SMTPChannel(self, connection, address)
asyncore.loop()
+
except Exception, errmsg:
traceback.print_exc()
s.shutdown(1)
@@ -258,6 +269,8 @@ class WallaceDaemon(object):
self.pool.apply_async(pickup_message, (filename, (self.modules)))
+ self.current_connections -= 1
+
return
def reload_config(self, *args, **kw):
diff --git a/wallace/module_footer.py b/wallace/module_footer.py
index 550e58f..2779461 100644
--- a/wallace/module_footer.py
+++ b/wallace/module_footer.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/wallace/module_optout.py b/wallace/module_optout.py
index 5540d80..7fdeb6f 100644
--- a/wallace/module_optout.py
+++ b/wallace/module_optout.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
diff --git a/wallace/module_resources.py b/wallace/module_resources.py
index 5a66dda..b2924fa 100644
--- a/wallace/module_resources.py
+++ b/wallace/module_resources.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -127,7 +127,7 @@ def execute(*args, **kw):
_message = json.load(open(filepath, 'r'))
log.debug("Loaded message %r" % (_message), level=9)
- message = message_from_string(_message['data'])
+ message = message_from_string(str(_message['data']))
recipients = _message['to']
any_itips = False
@@ -436,6 +436,9 @@ def execute(*args, **kw):
send_response(original_resource['mail'], itip_event)
+ auth.disconnect()
+ del auth
+
# Disconnect IMAP or we lock the mailbox almost constantly
imap.disconnect()
del imap
@@ -589,6 +592,8 @@ def resource_record_from_email_address(email_address):
resource_records = [ resource_records ]
+ auth.disconnect()
+
return resource_records
def resource_records_from_itip_events(itip_events):
@@ -722,6 +727,8 @@ def resource_records_from_itip_events(itip_events):
level=8
)
+ auth.disconnect()
+
return resource_records
def send_response(from_address, itip_events):
diff --git a/wallace/modules.py b/wallace/modules.py
index 040fe62..d256bdb 100644
--- a/wallace/modules.py
+++ b/wallace/modules.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com)
#
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
#
@@ -251,8 +251,20 @@ X-Wallace-Result: REJECT
def cb_action_ACCEPT(module, filepath):
log.info(_("Accepting message in %s (by module %s)") % (filepath, module))
- _message = json.load(open(filepath, 'r'))
- message = message_from_string(_message['data'])
+ try:
+ _message = json.load(open(filepath, 'r'))
+ log.debug(_(u"Message JSON loaded: %r") % (_message), level=9)
+ except Exception, errmsg:
+ log.error(_("Error loading message: %r") % (errmsg))
+ return
+
+ try:
+ message = message_from_string(str(_message['data']).replace('\x00',''))
+ except Exception, errmsg:
+ log.error(_("Error parsing message: %r") % (errmsg))
+ return
+
+ log.debug(_("Accepting message in: %r") %(filepath), level=8)
sender = _message['from']
recipients = _message['to']
@@ -271,8 +283,7 @@ def cb_action_ACCEPT(module, filepath):
# come from (TODO)
# - Third, a character return is inserted somewhere. It
# divides the body from the headers - and we don't like (TODO)
- #unicode(message.as_string()).replace('\0', '').lstrip()
- message.as_string().encode('utf-8').replace('\0','').lstrip()
+ message.as_string()
)
except smtplib.SMTPDataError, errmsg: