Projects
Kolab:3.4
pykolab
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 117
View file
pykolab.spec
Changed
@@ -28,8 +28,8 @@ Summary: Kolab Groupware Solution Name: pykolab -Version: 0.7.2 -Release: 2%{?dist} +Version: 0.7.3 +Release: 1%{?dist} License: GPLv3+ Group: Applications/System URL: http://kolab.org/ @@ -37,12 +37,6 @@ # From 792046ae463672f81f123482c13f474e88cfd832 Source0: http://files.kolab.org/releases/%{name}-%{version}.tar.gz -Patch0001: 0001-Fix-typo.patch -Patch0002: 0002-Fix-session-timeouts.patch -Patch0003: 0003-Actually-fix-the-socket-file.patch -Patch0004: 0004-setup-roundcube.patch -Patch0005: 0005-make-a-assets_path-a-relative-url.patch - BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root BuildArch: noarch %if 0%{?suse_version} @@ -534,6 +528,9 @@ %attr(0700,%{kolab_user},%{kolab_group}) %dir %{_var}/spool/pykolab/wallace %changelog +* Fri Oct 31 2014 Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> - 0.7.3-1 +- New upstream release + * Mon Sep 15 2014 Daniel Hoffend <dh@dotlan.net> - 0.7.2-2 - added patch to fix setup-kolab mysql.initial - added patch to fix assets_path
View file
0001-Fix-typo.patch
Deleted
@@ -1,33 +0,0 @@ -From 9979cacd96ee89cdff64705ffab2a681250d32be Mon Sep 17 00:00:00 2001 -From: "Jeroen van Meeuwen (Kolab Systems)" <vanmeeuwen@kolabsys.com> -Date: Thu, 11 Sep 2014 21:40:31 +0200 -Subject: [PATCH] Fix typo - ---- - pykolab/logger.py | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/pykolab/logger.py b/pykolab/logger.py -index 51f3e12..3ad16e9 100644 ---- a/pykolab/logger.py -+++ b/pykolab/logger.py -@@ -156,7 +156,7 @@ class Logger(logging.Logger): - - if os.path.isfile(self.logfile): - try: -- if not user_uid == 0 or group_gid = 0: -+ if not user_uid == 0 or group_gid == 0: - os.chown( - self.logfile, - user_uid, -@@ -214,6 +214,6 @@ class Logger(logging.Logger): - if level <= self.debuglevel: - # TODO: Not the way it's supposed to work! - self.log(logging.DEBUG, '[%d]: %s' % (os.getpid(),msg)) -- -+ - - logging.setLoggerClass(Logger) --- -1.9.3 -
View file
0002-Fix-session-timeouts.patch
Deleted
@@ -1,23 +0,0 @@ -From 3e4968e556c3593e2828c15f5b7eedb4cb5b2c7e Mon Sep 17 00:00:00 2001 -From: Daniel Hoffend <dh@dotlan.net> -Date: Wed, 3 Sep 2014 23:20:45 +0200 -Subject: [PATCH] commit transaction for cache_cleanup - ---- - bin/kolab_smtp_access_policy.py | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/bin/kolab_smtp_access_policy.py b/bin/kolab_smtp_access_policy.py -index 6e904eb..4b3d89b 100755 ---- a/bin/kolab_smtp_access_policy.py -+++ b/bin/kolab_smtp_access_policy.py -@@ -1158,6 +1158,7 @@ def cache_cleanup(): - ).filter( - PolicyResult.created < ((int)(time.time()) - cache_expire) - ).delete() -+ session.commit() - - def cache_init(): - global cache, cache_expire, session --- -1.7.10.4
View file
0003-Actually-fix-the-socket-file.patch
Deleted
@@ -1,42 +0,0 @@ -From 69a6edbf8cc7dd48225a9026ccd23ca16144b178 Mon Sep 17 00:00:00 2001 -From: "Jeroen van Meeuwen (Kolab Systems)" <vanmeeuwen@kolabsys.com> -Date: Fri, 12 Sep 2014 01:10:55 +0200 -Subject: [PATCH 3/3] Actually fix the socket file - ---- - saslauthd/__init__.py | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/saslauthd/__init__.py b/saslauthd/__init__.py -index 6590747..1ae09dd 100644 ---- a/saslauthd/__init__.py -+++ b/saslauthd/__init__.py -@@ -170,13 +170,13 @@ class SASLAuthDaemon(object): - - # TODO: The saslauthd socket path could be a setting. - try: -- os.remove(socketfile) -+ os.remove(conf.socketfile) - except: - # TODO: Do the "could not remove, could not start" dance - pass - -- s.bind(socketfile) -- os.chmod(socketfile, 0777) -+ s.bind(conf.socketfile) -+ os.chmod(conf.socketfile, 0777) - - s.listen(5) - -@@ -271,7 +271,7 @@ class SASLAuthDaemon(object): - - def _ensure_socket_dir(self): - utils.ensure_directory( -- os.path.dirname(socketfile), -+ os.path.dirname(conf.socketfile), - conf.process_username, - conf.process_groupname - ) --- -1.9.3 -
View file
0004-setup-roundcube.patch
Deleted
@@ -1,33 +0,0 @@ -From 8b2933d7bdc2d410691fbc5a39a74a02166610c6 Mon Sep 17 00:00:00 2001 -From: Daniel Hoffend <dh@dotlan.net> -Date: Sun, 14 Sep 2014 02:18:04 +0200 -Subject: [PATCH] fixed import of roundcube mysql.initial.sql - ---- - pykolab/setup/setup_roundcube.py | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/pykolab/setup/setup_roundcube.py b/pykolab/setup/setup_roundcube.py -index 259f676..ab73861 100644 ---- a/pykolab/setup/setup_roundcube.py -+++ b/pykolab/setup/setup_roundcube.py -@@ -140,12 +140,13 @@ def execute(*args, **kw): - - schema_files = [] - for root, directories, filenames in os.walk('/usr/share/doc/'): -+ directories.sort() - for directory in directories: - if directory.startswith("roundcubemail"): -- for root, directories, filenames in os.walk(os.path.join(root, directory)): -- for filename in filenames: -+ for nested_root, nested_directories, nested_filenames in os.walk(os.path.join(root, directory)): -+ for filename in nested_filenames: - if filename.startswith('mysql.initial') and filename.endswith('.sql'): -- schema_filepath = os.path.join(root,filename) -+ schema_filepath = os.path.join(nested_root,filename) - if not schema_filepath in schema_files: - schema_files.append(schema_filepath) - --- -1.7.10.4 -
View file
0005-make-a-assets_path-a-relative-url.patch
Deleted
@@ -1,25 +0,0 @@ -From bd6bae0355f124e2ddd6257c07d93771f7d59c80 Mon Sep 17 00:00:00 2001 -From: Daniel Hoffend <dh@dotlan.net> -Date: Mon, 15 Sep 2014 13:15:51 +0200 -Subject: [PATCH] make a assets_path a relative url - ---- - share/templates/roundcubemail/config.inc.php.tpl | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/share/templates/roundcubemail/config.inc.php.tpl b/share/templates/roundcubemail/config.inc.php.tpl -index 920423e..c80e553 100644 ---- a/share/templates/roundcubemail/config.inc.php.tpl -+++ b/share/templates/roundcubemail/config.inc.php.tpl -@@ -7,7 +7,7 @@ - \$config['des_key'] = "$des_key"; - \$config['username_domain'] = '$primary_domain'; - \$config['use_secure_urls'] = true; -- \$config['assets_path'] = '/roundcubemail/assets/'; -+ \$config['assets_path'] = 'assets/'; - - \$config['mail_domain'] = ''; - --- -1.7.10.4 -
View file
cyrus-imapd.conf-cert-paths.patch
Changed
@@ -1,15 +1,14 @@ ---- pykolab-0.6.5.orig/share/templates/imapd.conf.tpl 2013-08-22 15:26:51.000000000 +0100 -+++ pykolab-0.6.5/share/templates/imapd.conf.tpl 2013-09-15 14:54:18.834592778 +0100 -@@ -6,9 +6,9 @@ +diff -ur pykolab-0.7.3.orig/share/templates/imapd.conf.tpl pykolab-0.7.3/share/templates/imapd.conf.tpl +--- pykolab-0.7.3.orig/share/templates/imapd.conf.tpl 2014-10-31 13:54:25.000000000 +0100 ++++ pykolab-0.7.3/share/templates/imapd.conf.tpl 2014-10-31 13:59:22.604112952 +0100 +@@ -6,8 +6,8 @@ sasl_pwcheck_method: auxprop saslauthd 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/cyrus-imapd/cyrus-imapd.pem -+tls_cert_file: /etc/ssl/private/cyrus-imapd.pem -+tls_key_file: /etc/ssl/private/cyrus-imapd.pem -+tls_ca_file: /etc/ssl/private/cyrus-imapd.pem +-tls_server_cert: /etc/pki/cyrus-imapd/cyrus-imapd.pem +-tls_server_key: /etc/pki/cyrus-imapd/cyrus-imapd.pem ++tls_server_cert: /etc/ssl/private/cyrus-imapd.pem ++tls_server_key: /etc/ssl/private/cyrus-imapd.pem # uncomment this if you're operating in a DSCP environment (RFC-4594) # qosmarking: af13 auth_mech: pts
View file
debian.changelog
Changed
@@ -1,3 +1,9 @@ +pykolab (0.7.3-0~kolab1) unstable; urgency=low + + * New upstream version 0.7.3 + + -- Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> Fri, 31 Oct 2014 01:49:00 +0100 + pykolab (0.7.2-0~kolab5) unstable; urgency=low * added patch to fix setup-kolab mysql.initial
View file
debian.series
Changed
@@ -1,6 +1,1 @@ cyrus-imapd.conf-cert-paths.patch -p1 -0001-Fix-typo.patch -p1 -0002-Fix-session-timeouts.patch -p1 -0003-Actually-fix-the-socket-file.patch -p1 -0004-setup-roundcube.patch -p1 -0005-make-a-assets_path-a-relative-url.patch -p1
View file
pykolab-0.7.2.tar.gz/bin/kolab_smtp_access_policy.py -> pykolab-0.7.3.tar.gz/bin/kolab_smtp_access_policy.py
Changed
@@ -1158,6 +1158,7 @@ ).filter( PolicyResult.created < ((int)(time.time()) - cache_expire) ).delete() + session.commit() def cache_init(): global cache, cache_expire, session
View file
pykolab-0.7.2.tar.gz/conf/kolab.conf -> pykolab-0.7.3.tar.gz/conf/kolab.conf
Changed
@@ -382,6 +382,9 @@ ; default settings for kolabInvitationPolicy kolab_invitation_policy = ACT_ACCEPT_IF_NO_CONFLICT:example.org, ACT_MANUAL +; number of days past their end resource calendar events should be kept +resource_calendar_expire_days = 100 + ; This is a domain name space specific section, that enables us to override ; all settings, for example, the LDAP URI, base and bind DNs, scopes, filters, ; etc. Note that overriding the LDAP settings for the primary domain name space
View file
pykolab-0.7.2.tar.gz/configure.ac -> pykolab-0.7.3.tar.gz/configure.ac
Changed
@@ -1,4 +1,4 @@ -AC_INIT([pykolab], 0.7.2) +AC_INIT([pykolab], 0.7.3) AC_SUBST([RELEASE], 1) AC_CONFIG_SRCDIR(pykolab/constants.py.in)
View file
pykolab-0.7.2.tar.gz/pykolab/auth/__init__.py -> pykolab-0.7.3.tar.gz/pykolab/auth/__init__.py
Changed
@@ -176,6 +176,9 @@ self._auth._disconnect() + del self._auth + self._auth = None + def find_recipient(self, address, domain=None): """ Find one or more entries corresponding to the recipient address. @@ -197,6 +200,9 @@ """ Find one or more resources corresponding to the recipient address. """ + if not self._auth or self._auth == None: + self.connect() + result = self._auth.find_resource(address) if isinstance(result, list) and len(result) == 1:
View file
pykolab-0.7.2.tar.gz/pykolab/auth/ldap/__init__.py -> pykolab-0.7.3.tar.gz/pykolab/auth/ldap/__init__.py
Changed
@@ -984,7 +984,20 @@ _filter = self._kolab_filter() - modified_after = self.get_latest_sync_timestamp() + modified_after = None + + if hasattr(conf, 'resync'): + if not conf.resync: + modified_after = self.get_latest_sync_timestamp() + else: + modifytimestamp_format = conf.get_raw('ldap', 'modifytimestamp_format') + if modifytimestamp_format == None: + modifytimestamp_format = "%Y%m%d%H%M%SZ" + + modified_after = datetime.datetime(1900, 01, 01, 00, 00, 00).strftime(modifytimestamp_format) + else: + modified_after = self.get_latest_sync_timestamp() + _filter = "(&%s(modifytimestamp>=%s))" % (_filter,modified_after) log.debug(_("Using filter %r") % (_filter), level=8)
View file
pykolab-0.7.2.tar.gz/pykolab/cli/cmd_rename_mailbox.py -> pykolab-0.7.3.tar.gz/pykolab/cli/cmd_rename_mailbox.py
Changed
@@ -70,5 +70,5 @@ print >> sys.stderr, _("Target folder %r already exists") % (target_folder) sys.exit(1) - imap.user_mailbox_rename(source_folder.replace('user/',''), target_folder.replace('user/',''), partition=partition) + imap.imap.rename(source_folder, target_folder, partition)
View file
pykolab-0.7.2.tar.gz/pykolab/cli/cmd_sync.py -> pykolab-0.7.3.tar.gz/pykolab/cli/cmd_sync.py
Changed
@@ -31,6 +31,14 @@ def __init__(): commands.register('sync', execute, description="Synchronize Kolab Users with IMAP.") +def cli_options(): + my_option_group = conf.add_cli_parser_option_group(_("CLI Options")) + my_option_group.add_option( '--resync', + dest = "resync", + action = "store_true", + default = False, + help = _("Resync from the beginning")) + def execute(*args, **kw): auth = Auth() log.debug(_("Listing domains..."), level=5)
View file
pykolab-0.7.2.tar.gz/pykolab/itip/__init__.py -> pykolab-0.7.3.tar.gz/pykolab/itip/__init__.py
Changed
@@ -48,7 +48,7 @@ # Get the itip_payload itip_payload = part.get_payload(decode=True) - log.debug(_("Raw iTip payload: %s") % (itip_payload), level=9) + log.debug(_("Raw iTip payload (%r): %r") % (part.get_param('charset'), itip_payload), level=9) # Python iCalendar prior to 3.0 uses "from_string". if hasattr(icalendar.Calendar, 'from_ical'): @@ -89,7 +89,7 @@ if c.has_key('dtstart'): itip['start'] = c['dtstart'].dt - elif itip['type'] == 'VEVENT': + elif itip['type'] == 'event': log.error(_("iTip event without a start")) continue
View file
pykolab-0.7.2.tar.gz/pykolab/logger.py -> pykolab-0.7.3.tar.gz/pykolab/logger.py
Changed
@@ -156,7 +156,7 @@ if os.path.isfile(self.logfile): try: - if not user_uid == 0 or group_gid = 0: + if not user_uid == 0 or group_gid == 0: os.chown( self.logfile, user_uid, @@ -214,6 +214,6 @@ if level <= self.debuglevel: # TODO: Not the way it's supposed to work! self.log(logging.DEBUG, '[%d]: %s' % (os.getpid(),msg)) - + logging.setLoggerClass(Logger)
View file
pykolab-0.7.2.tar.gz/pykolab/setup/setup_mysql.py -> pykolab-0.7.3.tar.gz/pykolab/setup/setup_mysql.py
Changed
@@ -127,6 +127,10 @@ for root, directories, filenames in os.walk('/usr/share/doc/'): for filename in filenames: if filename.startswith('kolab_wap') and filename.endswith('.sql'): + # Skip the Oracle file + if filename.endswith('oracle.sql'): + continue + schema_file = os.path.join(root,filename) if not schema_file == None:
View file
pykolab-0.7.2.tar.gz/pykolab/xml/event.py -> pykolab-0.7.3.tar.gz/pykolab/xml/event.py
Changed
@@ -21,6 +21,20 @@ log = pykolab.getLogger('pykolab.xml_event') +def ustr(s): + if not isinstance(s, unicode): + for cs in ['utf-8','latin-1']: + try: + s = unicode(s, cs) + break + except: + pass + + if isinstance(s, unicode): + return s.encode('utf-8') + + return s + def event_from_ical(string): return Event(from_ical=string) @@ -130,7 +144,7 @@ self.event.setAttendees(self._attendees) def add_category(self, category): - self._categories.append(str(category)) + self._categories.append(ustr(category)) self.event.setCategories(self._categories) def add_exception_date(self, _datetime): @@ -534,6 +548,10 @@ return self._translate_value(status, self.status_map) if status else None + def get_ical_class(self): + class_ = self.event.classification() + return self._translate_value(class_, self.classification_map) if class_ else None + def get_ical_sequence(self): return str(self.event.sequence()) if self.event.sequence() else None @@ -624,11 +642,11 @@ self.event.setCreated(xmlutils.to_cdatetime(_datetime, False, True)) def set_description(self, description): - self.event.setDescription(str(description)) + self.event.setDescription(ustr(description)) def set_comment(self, comment): if hasattr(self.event, 'setComment'): - self.event.setComment(str(comment)) + self.event.setComment(ustr(comment)) def set_dtstamp(self, _datetime): self.event.setLastModified(xmlutils.to_cdatetime(_datetime, False, True)) @@ -693,7 +711,7 @@ params = {} if params.has_key('CN'): - name = str(params['CN']) + name = ustr(params['CN']) else: name = None @@ -752,7 +770,7 @@ params = {} if params.has_key('CN'): - cn = str(params['CN']) + cn = ustr(params['CN']) self.set_organizer(str(address), name=cn) @@ -763,7 +781,7 @@ self.set_sequence(sequence) def set_ical_summary(self, summary): - self.set_summary(str(summary)) + self.set_summary(ustr(summary)) def set_ical_uid(self, uid): self.set_uid(str(uid)) @@ -786,7 +804,7 @@ self.event.setLastModified(xmlutils.to_cdatetime(_datetime, False, True)) def set_location(self, location): - self.event.setLocation(str(location)) + self.event.setLocation(ustr(location)) def set_organizer(self, email, name=None): contactreference = ContactReference(email)
View file
pykolab-0.7.2.tar.gz/pykolab/xml/recurrence_rule.py -> pykolab-0.7.3.tar.gz/pykolab/xml/recurrence_rule.py
Changed
@@ -71,7 +71,7 @@ } properties_map = { - 'frequency': 'get_frequency', + 'freq': 'get_frequency', 'interval': 'interval', 'count': 'count', 'until': 'end',
View file
pykolab-0.7.2.tar.gz/pykolab/xml/utils.py -> pykolab-0.7.3.tar.gz/pykolab/xml/utils.py
Changed
@@ -57,11 +57,17 @@ _timezone = _cdatetime.timezone() if _timezone == '' or _timezone == None: - _timezone = pytz.utc + _dt = datetime.datetime(year, month, day, hour, minute, second, tzinfo=pytz.utc) else: - _timezone = pytz.timezone(_timezone) - - return datetime.datetime(year, month, day, hour, minute, second, tzinfo=_timezone) + try: + # use pytz.timezone.localize() to correctly set DST in tzinfo according to the given date + _tz = pytz.timezone(_timezone) + _dt = _tz.localize(datetime.datetime(year, month, day, hour, minute, second)) + except: + # fall back to local time + _dt = datetime.datetime(year, month, day, hour, minute, second) + + return _dt else: return datetime.datetime(year, month, day, hour, minute, second)
View file
pykolab-0.7.2.tar.gz/saslauthd/__init__.py -> pykolab-0.7.3.tar.gz/saslauthd/__init__.py
Changed
@@ -170,13 +170,13 @@ # TODO: The saslauthd socket path could be a setting. try: - os.remove(socketfile) + os.remove(conf.socketfile) except: # TODO: Do the "could not remove, could not start" dance pass - s.bind(socketfile) - os.chmod(socketfile, 0777) + s.bind(conf.socketfile) + os.chmod(conf.socketfile, 0777) s.listen(5) @@ -271,7 +271,7 @@ def _ensure_socket_dir(self): utils.ensure_directory( - os.path.dirname(socketfile), + os.path.dirname(conf.socketfile), conf.process_username, conf.process_groupname )
View file
pykolab-0.7.2.tar.gz/share/templates/imapd.conf.tpl -> pykolab-0.7.3.tar.gz/share/templates/imapd.conf.tpl
Changed
@@ -6,9 +6,8 @@ sasl_pwcheck_method: auxprop saslauthd 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/cyrus-imapd/cyrus-imapd.pem +tls_server_cert: /etc/pki/cyrus-imapd/cyrus-imapd.pem +tls_server_key: /etc/pki/cyrus-imapd/cyrus-imapd.pem # uncomment this if you're operating in a DSCP environment (RFC-4594) # qosmarking: af13 auth_mech: pts @@ -32,7 +31,7 @@ unixhierarchysep: 1 virtdomains: userid annotation_definitions: /etc/imapd.annotations.conf -sieve_extensions: fileinto reject envelope body vacation imapflags notify include regex subaddress relational copy +sieve_extensions: fileinto reject envelope body vacation imapflags notify include regex subaddress relational copy date index allowallsubscribe: 0 allowusermoves: 1 altnamespace: 1 @@ -47,5 +46,4 @@ deletedprefix: DELETED delete_mode: delayed expunge_mode: delayed -flushseenstate: 1 postuser: shared
View file
pykolab-0.7.2.tar.gz/tests/functional/test_wallace/test_007_invitationpolicy.py -> pykolab-0.7.3.tar.gz/tests/functional/test_wallace/test_007_invitationpolicy.py
Changed
@@ -261,6 +261,7 @@ 'mailbox': 'user/jane.manager@example.org', 'kolabcalendarfolder': 'user/jane.manager/Calendar@example.org', 'kolabtasksfolder': 'user/jane.manager/Tasks@example.org', + 'kolabconfidentialcalendar': 'user/jane.manager/Calendar/Confidential@example.org', 'kolabinvitationpolicy': ['ACT_ACCEPT_IF_NO_CONFLICT','ACT_REJECT_IF_CONFLICT','TASK_ACCEPT','ACT_UPDATE'] } @@ -301,6 +302,20 @@ from tests.functional.synchronize import synchronize_once synchronize_once() + # create confidential calendar folder for jane + imap = IMAP() + imap.connect(domain='example.org') # sets self.domain + imap.user_mailbox_create_additional_folders(self.jane['mail'], { + 'Calendar/Confidential': { + 'annotations': { + '/shared/vendor/kolab/folder-type': "event", + '/private/vendor/kolab/folder-type': "event.confidential" + } + } + }) + imap.disconnect() + + def send_message(self, itip_payload, to_addr, from_addr=None, method="REQUEST"): if from_addr is None: from_addr = self.john['mail'] @@ -657,7 +672,7 @@ self.purge_mailbox(self.john['mailbox']) # send update with new date and incremented sequence - new_start = datetime.datetime(2014,8,15, 15,0,0, tzinfo=pytz.timezone("Europe/Berlin")) + new_start = pytz.timezone("Europe/Berlin").localize(datetime.datetime(2014,8,15, 15,0,0)) self.send_itip_update(self.jane['mail'], uid, new_start, summary="test", sequence=1) response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }, self.jane['mail']) @@ -681,7 +696,7 @@ # send update with new but conflicting date and incremented sequence self.create_calendar_event(datetime.datetime(2014,8,10, 10,30,0, tzinfo=pytz.timezone("Europe/Berlin")), user=self.jack) - new_start = datetime.datetime(2014,8,10, 9,30,0, tzinfo=pytz.timezone("Europe/Berlin")) + new_start = pytz.timezone("Europe/Berlin").localize(datetime.datetime(2014,8,10, 9,30,0)) self.send_itip_update(self.jack['mail'], uid, new_start, summary="test (updated)", sequence=1) response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('DECLINED') }, self.jack['mail']) @@ -933,6 +948,16 @@ self.assertEqual(notification, None) + def test_012_confidential_invitation(self): + start = datetime.datetime(2014,9,21, 9,30,0) + uid = self.send_itip_invitation(self.jane['mail'], start, summary='confidential', template=itip_invitation.replace("DESCRIPTION:test", "CLASS:CONFIDENTIAL")) + + # check event being stored in the folder annotared with event.confidential + event = self.check_user_calendar_event(self.jane['kolabconfidentialcalendar'], uid) + self.assertIsInstance(event, pykolab.xml.Event) + self.assertEqual(event.get_summary(), "confidential") + + def test_020_task_assignment_accept(self): start = datetime.datetime(2014,9,10, 19,0,0) uid = self.send_itip_invitation(self.jane['mail'], start, summary='work', template=itip_todo)
View file
pykolab-0.7.2.tar.gz/tests/unit/test-003-event.py -> pykolab-0.7.3.tar.gz/tests/unit/test-003-event.py
Changed
@@ -434,6 +434,7 @@ self.event.set_start(datetime.datetime(2014, 05, 23, 11, 00, 00, tzinfo=pytz.timezone("Europe/London"))) self.event.set_end(datetime.datetime(2014, 05, 23, 12, 30, 00, tzinfo=pytz.timezone("Europe/London"))) self.event.set_sequence(3) + self.event.set_classification('CONFIDENTIAL') self.event.add_custom_property('X-Custom', 'check') ical = icalendar.Calendar.from_ical(self.event.as_string_itip()) @@ -444,6 +445,7 @@ self.assertEqual(event['sequence'], 3) self.assertEqual(event['X-CUSTOM'], "check") self.assertIsInstance(event['dtstamp'].dt, datetime.datetime) + self.assertEqual(event['class'], "CONFIDENTIAL") def test_019_to_message_itip(self): self.event = Event()
View file
pykolab-0.7.2.tar.gz/tests/unit/test-011-itip.py -> pykolab-0.7.3.tar.gz/tests/unit/test-011-itip.py
Changed
@@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + import pykolab import datetime import pytz @@ -253,6 +255,54 @@ END:VCALENDAR """ +itip_unicode = """MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="=_c8894dbdb8baeedacae836230e3436fd" +From: "Doe, John" <john.doe@example.org> +Date: Tue, 25 Feb 2014 13:54:14 +0100 +Message-ID: <240fe7ae7e139129e9eb95213c1016d7@example.org> +User-Agent: Roundcube Webmail/0.9-0.3.el6.kolab_3.0 +To: resource-car-audia4@example.org +Subject: "test" + +--=_c8894dbdb8baeedacae836230e3436fd +Content-Type: text/plain; charset=UTF-8; format=flowed +Content-Transfer-Encoding: quoted-printable + +*test* + +--=_c8894dbdb8baeedacae836230e3436fd +Content-Type: text/calendar; charset=UTF-8; method=REQUEST; name=event.ics +Content-Disposition: attachment; filename=event.ics +Content-Transfer-Encoding: quoted-printable + + +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Roundcube=20Webmail=200.9-0.3.el6.kolab_3.0//NONSGML=20Calendar//= +EN +CALSCALE:GREGORIAN +METHOD:REQUEST +BEGIN:VEVENT +UID:eea25142-fb1c-4831-a02d-ac9fb4c16b70 +DTSTAMP:20140213T125414Z +DTSTART;TZID=3DEurope/London:20140713T100000 +DTEND;TZID=3DEurope/London:20140713T140000 +SUMMARY:Testing =C3=9Cmlauts +DESCRIPTION:Testing =C3=9Cmlauts +LOCATION:Rue the Gen=C3=A8ve +ORGANIZER;CN=3D"D=C3=BE,=20John":mailto:john.doe@example.org +ATTENDEE;ROLE=3DREQ-PARTICIPANT;CUTYPE=3DRESOURCE;PARTSTAT=3DNEEDS-ACTION;R= +SVP=3DTRUE:mailto:resource-car-audia4@example.org +ATTENDEE;ROLE=3DREQ-PARTICIPANT;PARTSTAT=3DTENTATIVE;CN=3DSomebody=20Else:m= +ailto:somebody@else.com +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR + +--=_c8894dbdb8baeedacae836230e3436fd-- +""" + itip_empty = """MIME-Version: 1.0 Date: Fri, 17 Jan 2014 13:51:50 +0100 From: <john.doe@example.org> @@ -318,6 +368,13 @@ itips7 = itip.events_from_message(message_from_string(itip_non_multipart.replace("METHOD:REQUEST", "METHOD:PUBLISH").replace("method=REQUEST", "method=PUBLISH"))) self.assertEqual(len(itips7), 0, "Invalid METHOD") + # iTips with unicode data + itips8 = itip.events_from_message(message_from_string(itip_unicode)) + self.assertEqual(len(itips8), 1) + xml = itips8[0]['xml'] + self.assertEqual(xml.get_summary(), "Testing Ümlauts") + self.assertEqual(xml.get_location(), "Rue the Genève") + def test_002_check_date_conflict(self): astart = datetime.datetime(2014,7,13, 10,0,0)
View file
pykolab-0.7.2.tar.gz/wallace/__init__.py -> pykolab-0.7.3.tar.gz/wallace/__init__.py
Changed
@@ -40,6 +40,8 @@ log = pykolab.getLogger('pykolab.wallace') conf = pykolab.getConf() +from modules import cb_action_ACCEPT + #conf.finalize_conf() #if conf.debuglevel > 8: # max_threads = 1 @@ -62,6 +64,10 @@ else: modules.execute(kw['module'], filepath) + # After all modules are executed, continue with a call to + # accept the message and re-inject in to Postfix. + continue_with_accept = True + for module in wallace_modules: try: result_filepath = modules.execute(module, filepath) @@ -72,6 +78,30 @@ if not result_filepath == None and not result_filepath == False: filepath = result_filepath else: + # A module has returned False or None + continue_with_accept = False + # The message very likely has been consumed by the module that returned False + if not os.path.isfile(filepath): + break + + if continue_with_accept: + cb_action_ACCEPT('wallace', filepath) + +def modules_heartbeat(wallace_modules): + lastrun = 0 + + while True: + try: + for module in wallace_modules: + try: + modules.heartbeat(module, lastrun) + except: + log.error(_("Module %s.heartbeat() failed with error: %s" % (module, traceback.format_exc()))) + + lastrun = int(time.time()) + time.sleep(60) + except (SystemExit, KeyboardInterrupt), e: + log.info("Terminating heartbeat process") break def worker_process(*args, **kw): @@ -149,9 +179,7 @@ self.modules = conf.get_list('wallace', 'modules') if self.modules == None: - self.modules = ['resources'] - elif not 'resources' in self.modules: - self.modules.append('resources') + self.modules = [] def do_wallace(self): if version.StrictVersion(sys.version[:3]) >= version.StrictVersion("2.7"): @@ -244,6 +272,11 @@ self.pool.apply_async(pickup_message, (filepath, (self.modules))) self.current_connections -= 1 + # start background process to run periodic jobs in active modules + self.heartbeat = multiprocessing.Process(target=modules_heartbeat, args=[self.modules]) + self.heartbeat.daemon = True + self.heartbeat.start() + try: while 1: while self.current_connections >= self.max_connections: @@ -262,6 +295,9 @@ s.shutdown(1) s.close() + # shut down hearbeat process + self.heartbeat.terminate() + def data_header(self, mailfrom, rcpttos): COMMASPACE = ', ' return "X-Kolab-From: " + mailfrom + "\r\n" + \ @@ -294,6 +330,8 @@ pass def remove_pid(self, *args, **kw): + if hasattr(self, 'heartbeat'): + self.heartbeat.terminate() if os.access(conf.pidfile, os.R_OK): os.remove(conf.pidfile) raise SystemExit
View file
pykolab-0.7.2.tar.gz/wallace/module_invitationpolicy.py -> pykolab-0.7.3.tar.gz/wallace/module_invitationpolicy.py
Changed
@@ -728,9 +728,14 @@ or metadata[folder].has_key('/private' + FOLDER_TYPE_ANNOTATION) and metadata[folder]['/private' + FOLDER_TYPE_ANNOTATION].startswith(type)): result.append(folder) - # store default folder folder in user record - if metadata[folder].has_key('/private' + FOLDER_TYPE_ANNOTATION) and metadata[folder]['/private' + FOLDER_TYPE_ANNOTATION].endswith('.default'): - user_rec['_default_folder'] = folder + if metadata[folder].has_key('/private' + FOLDER_TYPE_ANNOTATION): + # store default folder in user record + if metadata[folder]['/private' + FOLDER_TYPE_ANNOTATION].endswith('.default'): + user_rec['_default_folder'] = folder + + # store confidential folder in user record + if metadata[folder]['/private' + FOLDER_TYPE_ANNOTATION].endswith('.confidential') and not user_rec.has_key('_confidential_folder'): + user_rec['_confidential_folder'] = folder # cache with user record user_rec['_imap_folders'] = result @@ -908,6 +913,9 @@ targetfolder = list_user_folders(user_rec, object.type)[0] if user_rec.has_key('_default_folder'): targetfolder = user_rec['_default_folder'] + # use *.confidential folder for invitations classified as confidential + if object.get_classification() == kolabformat.ClassConfidential and user_rec.has_key('_confidential_folder'): + targetfolder = user_rec['_confidential_folder'] if not targetfolder: log.error(_("Failed to save %s: no target folder found for user %r") % (object.type, user_rec['mail']))
View file
pykolab-0.7.2.tar.gz/wallace/module_resources.py -> pykolab-0.7.3.tar.gz/wallace/module_resources.py
Changed
@@ -25,6 +25,7 @@ import tempfile import time from urlparse import urlparse +from dateutil.tz import tzlocal import base64 import uuid import re @@ -70,7 +71,7 @@ imap = None def __init__(): - modules.register('resources', execute, description=description()) + modules.register('resources', execute, description=description(), heartbeat=heartbeat) def accept(filepath): new_filepath = os.path.join( @@ -112,7 +113,7 @@ if not os.path.isdir(os.path.join(mybasepath, stage)): os.makedirs(os.path.join(mybasepath, stage)) - log.debug(_("Resource Management called for %r, %r") % (args, kw), level=9) + log.debug(_("Resource Management called for %r, %r") % (args, kw), level=8) auth = Auth() imap = IMAP() @@ -169,7 +170,7 @@ any_itips = False any_resources = False - possibly_any_resources = True + possibly_any_resources = False reference_uid = None # An iTip message may contain multiple events. Later on, test if the message @@ -197,11 +198,9 @@ if any_itips: # See if any iTip actually allocates a resource. - if len([x['resources'] for x in itip_events if x.has_key('resources')]) == 0: - if len([x['attendees'] for x in itip_events if x.has_key('attendees')]) == 0: - possibly_any_resources = False - else: - possibly_any_resources = False + if len([x['resources'] for x in itip_events if x.has_key('resources')]) > 0 \ + or len([x['attendees'] for x in itip_events if x.has_key('attendees')]) > 0: + possibly_any_resources = True if possibly_any_resources: auth.connect() @@ -393,6 +392,106 @@ os.unlink(filepath) +def heartbeat(lastrun): + global imap + + # run archival job every hour only + now = int(time.time()) + if lastrun == 0 or now - heartbeat._lastrun < 3600: + return + + log.debug(_("module_resources.heartbeat(%d)") % (heartbeat._lastrun), level=8) + + # get a list of resource records from LDAP + auth = Auth() + auth.connect() + + resource_dns = auth.find_resource('*') + + # filter by resource_base_dn + resource_base_dn = conf.get('ldap', 'resource_base_dn', None) + if resource_base_dn is not None: + resource_dns = [dn for dn in resource_dns if resource_base_dn in dn] + + if len(resource_dns) > 0: + imap = IMAP() + imap.connect() + + for resource_dn in resource_dns: + resource_attrs = auth.get_entry_attributes(None, resource_dn, ['kolabtargetfolder']) + if resource_attrs.has_key('kolabtargetfolder'): + try: + expunge_resource_calendar(resource_attrs['kolabtargetfolder']) + except Exception, e: + log.error(_("Expunge resource calendar for %s (%s) failed: %r") % ( + resource_dn, resource_attrs['kolabtargetfolder'], e + )) + + imap.disconnect() + + auth.disconnect() + + heartbeat._lastrun = now + +heartbeat._lastrun = 0 + + +def expunge_resource_calendar(mailbox): + """ + Cleanup routine to remove events older than 100 days from the given resource calendar + """ + global imap + + days = int(conf.get('wallace', 'resource_calendar_expire_days', 100)) + now = datetime.datetime.now(tzlocal()) + expire_date = now - datetime.timedelta(days=days) + + log.debug( + _("Expunge events in resource folder %r older than %d days") % (mailbox, days), + level=8 + ) + + # might raise an exception, let that bubble + targetfolder = imap.folder_quote(mailbox) + imap.set_acl(targetfolder, conf.get(conf.get('kolab', 'imap_backend'), 'admin_login'), "lrswipkxtecda") + imap.imap.m.select(targetfolder) + + typ, data = imap.imap.m.search(None, 'UNDELETED') + + for num in data[0].split(): + log.debug( + _("Fetching message ID %r from folder %r") % (num, mailbox), + level=9 + ) + + typ, data = imap.imap.m.fetch(num, '(RFC822)') + + event_message = message_from_string(data[0][1]) + + try: + event = event_from_message(message_from_string(data[0][1])) + except Exception, e: + log.error(_("Failed to parse event from message %s/%s: %r") % (mailbox, num, e)) + continue + + if event: + dt_end = to_dt(event.get_end()) + + # consider recurring events and get real end date + if event.is_recurring(): + dt_end = event.get_last_occurrence() + if dt_end is None: + # skip if recurring forever + continue + + if dt_end and dt_end < expire_date: + age = now - dt_end + log.debug(_("Flag event %s from message %s/%s as deleted (age = %d days)") % (event.uid, mailbox, num, age.days), level=8) + imap.imap.m.store(num, '+FLAGS', '\\Deleted') + + imap.imap.m.expunge() + + def check_availability(itip_events, resource_dns, resources, receiving_attendee=None): """ For each resource, determine if any of the events in question are in conflict. @@ -542,7 +641,7 @@ # might raise an exception, let that bubble imap.imap.m.select(imap.folder_quote(mailbox)) - typ, data = imap.imap.m.search(None, 'ALL') + typ, data = imap.imap.m.search(None, 'UNDELETED') num_messages = len(data[0].split()) @@ -780,8 +879,6 @@ resource_records = [ resource_records ] log.debug(_("Resource record: %r") % (resource_records), level=8) - auth.disconnect() - return resource_records
View file
pykolab-0.7.2.tar.gz/wallace/modules.py -> pykolab-0.7.3.tar.gz/wallace/modules.py
Changed
@@ -115,6 +115,13 @@ return modules[name]['function'](*args, **kw) +def heartbeat(name, *args, **kw): + if not modules.has_key(name): + log.warning(_("No such module %r in modules %r (1).") % (name, modules)) + + if modules[name].has_key('heartbeat'): + return modules[name]['heartbeat'](*args, **kw) + def cb_action_HOLD(module, filepath): log.info(_("Holding message in queue for manual review (%s by %s)") % (filepath, module)) @@ -334,7 +341,7 @@ exec("%s_%s_register()" % (module,name)) -def register(name, func, group=None, description=None, aliases=[]): +def register(name, func, group=None, description=None, aliases=[], heartbeat=None): if not group == None: module = "%s_%s" % (group,name) else: @@ -369,3 +376,5 @@ 'description': _("Alias for %s") % (name) } + if callable(heartbeat): + modules[module]['heartbeat'] = heartbeat
View file
pykolab.dsc
Changed
@@ -2,7 +2,7 @@ Source: pykolab Binary: pykolab, kolab-cli, kolab-conf, kolab-saslauthd, kolab-server, kolab-telemetry, kolab-xml, wallace Architecture: all -Version: 0.7.2-0~kolab5 +Version: 0.7.3-0~kolab1 Maintainer: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> Uploaders: Paul Klos <kolab@klos2day.nl> Homepage: http://www.kolab.org @@ -40,5 +40,5 @@ pykolab deb python optional wallace deb python optional Files: - 00000000000000000000000000000000 0 pykolab-0.7.2.tar.gz + 00000000000000000000000000000000 0 pykolab-0.7.3.tar.gz 00000000000000000000000000000000 0 debian.tar.gz
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.