config/config.ini.sample lib/Kolab

Thomas Brüderli bruederli at kolabsys.com
Wed May 7 10:02:25 CEST 2014


 config/config.ini.sample             |    3 +
 lib/Kolab/FreeBusy/DirectoryLDAP.php |    5 ++
 lib/Kolab/FreeBusy/SourceIMAP.php    |   61 +++++++++++++++++++++++++++++------
 3 files changed, 58 insertions(+), 11 deletions(-)

New commits:
commit d8cf3d34722af8379cadbd828efb3c0b962162d4
Author: Thomas Bruederli <thomas at roundcube.net>
Date:   Wed May 7 09:38:12 2014 +0200

    Consider events from shared folders if user is a confirmed participant (or organizer)

diff --git a/config/config.ini.sample b/config/config.ini.sample
index eeb7347..c20a2de 100644
--- a/config/config.ini.sample
+++ b/config/config.ini.sample
@@ -53,8 +53,9 @@ bind_dn = "uid=kolab-service,ou=Special Users,dc=yourdomain,dc=com"
 bind_pw = "<service-bind-pw>"
 base_dn = "dc=yourdomain,dc=com"
 filter = "(&(objectClass=kolabInetOrgPerson)(|(uid=%s)(mail=%s)(alias=%s)))"
-attributes = mail, sn
+attributes = mail, sn, alias
 lc_attributes = sn
+mail_attributes = mail, alias
 fbsource = file:/var/lib/kolab-freebusy/%mail.ifb
 loglevel = 200  ; Info
 
diff --git a/lib/Kolab/FreeBusy/DirectoryLDAP.php b/lib/Kolab/FreeBusy/DirectoryLDAP.php
index 42d72b1..84248fa 100644
--- a/lib/Kolab/FreeBusy/DirectoryLDAP.php
+++ b/lib/Kolab/FreeBusy/DirectoryLDAP.php
@@ -112,7 +112,10 @@ class DirectoryLDAP extends Directory
 
 				// convert entry attributes to strings and add them to the final result hash array
 				foreach ($entry as $k => $v) {
-					if (!empty($v)) {
+					if (is_array($v) && count($v) > 1) {
+						$result[$k] = array_map('strval', $v);
+					}
+					else if (!empty($v)) {
 						$result[$k] = strval(is_array($v) ? $v[0] : $v);
 					}
 				}
diff --git a/lib/Kolab/FreeBusy/SourceIMAP.php b/lib/Kolab/FreeBusy/SourceIMAP.php
index 494a4d5..ee2092e 100644
--- a/lib/Kolab/FreeBusy/SourceIMAP.php
+++ b/lib/Kolab/FreeBusy/SourceIMAP.php
@@ -23,6 +23,7 @@
 
 namespace Kolab\FreeBusy;
 
+use Kolab\Config;
 use Sabre\VObject;
 use Sabre\VObject\Component\VCalendar;
 use Sabre\VObject\FreeBusyGenerator;
@@ -45,7 +46,7 @@ class SourceIMAP extends Source
 
 	public function __construct($config)
 	{
-		parent::__construct($config);
+		parent::__construct($config + array('mail_attributes' => 'mail'));
 
 		// load the Roundcube framework with its autoloader
 		require_once KOLAB_FREEBUSY_ROOT . '/lib/Roundcube/bootstrap.php';
@@ -84,6 +85,15 @@ class SourceIMAP extends Source
 			}
 			else {
 				file_put_contents($config['cacheto'], Utils::dummyVFreebusy($user['mail']));
+				$tempfile = $config['cacheto'];
+			}
+		}
+
+		// compose a list of user email addresses
+		$user_email = array();
+		foreach (Config::convert($this->config['mail_attributes'], Config::ARR) as $key) {
+			if (!empty($user[$key])) {
+				$user_email = array_merge($user_email, (array)$user[$key]);
 			}
 		}
 
@@ -106,8 +116,9 @@ class SourceIMAP extends Source
 			$dtstart  = new \DateTime('now - 8 weeks 00:00:00', $utc);
 			$dtend    = new \DateTime('now + 16 weeks 00:00:00', $utc);
 			$calendar = VObject\Component::create('VCALENDAR');
+			$seen     = array();
 
-			$query = array(array('dtstart','>',$dtstart), array('dtend','<',$dtend));
+			$query = array(array('dtstart','<=',$dtend), array('dtend','>=',$dtstart));
 			foreach ($folders as $folder) {
 				$log->debug('Reading Kolab folder: ' . $folder->name, $folder->get_folder_info());
 
@@ -123,14 +134,38 @@ class SourceIMAP extends Source
 				}
 
 				foreach ($folder->select($query) as $event) {
-					$log->debug('Found event', $event);
+					//$log->debug('Processing event', $event);
 
-					if ($event['cancelled'])
+					if ($event['cancelled']) {
 						continue;
+					}
 
-					// TODO: only consider shared namespace events if user is a confirmed participant
+					// only consider shared namespace events if user is a confirmed participant (or organizer)
 					if (!$read_all && $folder->get_namespace() == 'shared') {
-						continue;  // skip all for now
+						$participant = false;
+						if (is_array($event['organizer']) && !empty($event['organizer']['email'])) {
+							$participant = in_array($event['organizer']['email'], $user_email);
+						}
+						else if (is_array($event['attendees'])) {
+							foreach ($event['attendees'] as $attendee) {
+								if (in_array($attendee['email'], $user_email)) {
+									if ($attendee['status'] == 'ACCEPTED') {
+										$participant = true;
+										break;
+									}
+									else if ($attendee['status'] == 'TENTATIVE') {
+										$event['free_busy'] = 'tentative';
+										$participant = true;
+										break;
+									}
+								}
+							}
+						}
+
+						if (!$participant) {
+							$log->debug('Skip shared event', array($event['uid'], $event['title']));
+							continue;
+						}
 					}
 
 					// copied from libvcalendar::_to_ical()
@@ -142,6 +177,14 @@ class SourceIMAP extends Source
 						$event['end']->add(new \DateInterval('P1D'));
 						$event['end']->_dateonly = true;
 					}
+
+					// avoid duplicate entries
+					$key = $event['start']->format('c') . '/' . $event['end']->format('c');
+					if ($seen[$key]++) {
+						$log->debug('Skipping duplicate event at ' . $key, array($event['uid'], $event['title']));
+						continue;
+					}
+
 					if (!empty($event['start']))
 						$ve->add(\libvcalendar::datetime_prop('DTSTART', $event['start'], false, (bool)$event['allday']));
 					if (!empty($event['end']))
@@ -199,14 +242,14 @@ class SourceIMAP extends Source
 			$freebusy = $fbgen->getResult();
 			$freebusy->PRODID = Utils::PRODID;
 			$freebusy->METHOD = 'PUBLISH';
-			$freebusy->VFREEBUSY->ORGANIZER = 'mailto:' . $user['mail'];
+			$freebusy->VFREEBUSY->ORGANIZER = 'mailto:' . $user_email[0];
 
 			// serialize to VCALENDAR format
 			return $freebusy->serialize();
 		}
 		// remove (temporary) cache file again
-		else if (!empty($config['cacheto']) && file_exists($config['cacheto'])) {
-			unlink($config['cacheto']);
+		else if ($tempfile) {
+			unlink($tempfile);
 		}
 
 		return false;




More information about the commits mailing list