--- php-kolab/Kolab_Freebusy/Freebusy/Cache.php 2008-03-03 15:48:25.000000000 +0100 +++ php-kolab.noacls/Kolab_Freebusy/Freebusy/Cache.php 2008-03-06 10:05:31.000000000 +0100 @@ -1,5 +1,5 @@ _cache_dir = $cache_dir; } - function store($access) + function store($access) { + global $conf; + /* Now we really need the free/busy library */ require_once('Horde/Kolab/Freebusy.php'); @@ -64,14 +66,16 @@ } $fbfilename = $this->_getFilename($access->folder, $access->owner); - $c_pvcal = &new FreeBusyCacheFile_pvcal($this->_cache_dir, $fbfilename); - $c_acl = &new FreeBusyCacheFile_acl($this->_cache_dir, $fbfilename); - $c_xacl = &new FreeBusyCacheFile_xacl($this->_cache_dir, $fbfilename); - + + if ($conf['fb']['use_acls'] == true) { + $c_acl = &new FreeBusyCacheFile_acl($this->_cache_dir, $fbfilename); + $c_xacl = &new FreeBusyCacheFile_xacl($this->_cache_dir, $fbfilename); + } + /* missing data means delete the cache files */ if (empty($vCal)) { - Horde::logMessage(sprintf(_("No events. Purging cache %s."), + Horde::logMessage(sprintf(_("No events. Purging cache %s."), $fbfilename), __FILE__, __LINE__, PEAR_LOG_DEBUG); @@ -79,17 +83,18 @@ if (is_a($result, 'PEAR_Error')) { return $result; } - $result = $c_acl->purge(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - $result = $c_xacl->purge(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + if ($conf['fb']['use_acls'] == true) { + $result = $c_acl->purge(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + $result = $c_xacl->purge(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } } else { - $result = $c_pvcal->storePVcal($vCal); if (is_a($result, 'PEAR_Error')) { return $result; @@ -99,54 +104,59 @@ if (is_a($relevance, 'PEAR_Error')) { $relevance; } - $acl = $fb->getACL(); - if (is_a($acl, 'PEAR_Error')) { - $acl; - } - $result = $c_acl->storeACL($acl, $relevance); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - - $xacl = $fb->getExtendedACL(); - if (is_a($xacl, 'PEAR_Error')) { - $xacl; - } - /* The owner may always look at the extended attributes */ - $xacl .= ' ' . $access->owner; - $result = $c_xacl->storeXACL($xacl); - if (is_a($result, 'PEAR_Error')) { - return $result; + if ($conf['fb']['use_acls'] == true) { + $acl = $fb->getACL(); + if (is_a($acl, 'PEAR_Error')) { + $acl; + } + + $result = $c_acl->storeACL($acl, $relevance); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + $xacl = $fb->getExtendedACL(); + if (is_a($xacl, 'PEAR_Error')) { + $xacl; + } + /* The owner may always look at the extended attributes */ + $xacl .= ' ' . $access->owner; + $result = $c_xacl->storeXACL($xacl); + if (is_a($result, 'PEAR_Error')) { + return $result; + } } - - Horde::logMessage(sprintf(_("FreeBusyCache::store(file=%s, relevance=%s, acl=%s, xacl=%s)"), - $fbfilename, $relevance, $acl, $xacl), + Horde::logMessage(sprintf(_("FreeBusyCache::store(file=%s, relevance=%s, acl=%s, xacl=%s)"), + $fbfilename, $relevance, $acl, $xacl), __FILE__, __LINE__, PEAR_LOG_DEBUG); } } function &loadPartial(&$access, $extended) { + global $conf; + $file = $this->_getFilename($access->folder, $access->owner); - $aclcache = &FreeBusyCacheDB_acl::singleton('acl', $this->_cache_dir); + if ($conf['fb']['use_acls'] == true) { + $aclcache = &FreeBusyCacheDB_acl::singleton('acl', $this->_cache_dir); - $relevant = false; - foreach ($access->groups as $id) { - if ($aclcache->has($file, $id)) { - $relevant = true; - break; - } - } + $relevant = false; + foreach ($access->groups as $id) { + if ($aclcache->has($file, $id)) { + $relevant = true; + break; + } + } - if (!$relevant) { - return PEAR::raiseError(sprintf(_("Folder %s is irrelevant for user %s."), - $access->imap_folder, $access->user)); - } + if (!$relevant) { + return PEAR::raiseError(sprintf(_("Folder %s is irrelevant for user %s."), + $access->imap_folder, $access->user)); + } - if ($extended) { - $extended = $this->_allowExtended($file, $access); + if ($extended) { + $extended = $this->_allowExtended($file, $access); + } } $c_pvcal = &new FreeBusyCacheFile_pvcal($this->_cache_dir, $file); @@ -162,12 +172,17 @@ global $conf; /* Which files will we access? */ - $aclcache = &FreeBusyCacheDB_acl::singleton('acl', $this->_cache_dir); - $files = $aclcache->get($access->owner); - if (is_a($files, 'PEAR_Error')) { - return $files; + if ($conf['fb']['use_acls'] == true) { + $aclcache = &FreeBusyCacheDB_acl::singleton('acl', $this->_cache_dir); + $files = $aclcache->get($access->owner); + if (is_a($files, 'PEAR_Error')) { + return $files; + } + } else { + $file_uid = str_replace("\0", '', str_replace(".", "^", $access->owner)); + $files = array(); + $this->findAll_readdir($file_uid, $conf['fb']['cache_dir'].'/'.$file_uid, $files); } - $filesnames = array(); $owner = $access->owner; if (ereg('(.*)@(.*)', $owner, $regs)) { @@ -185,12 +200,12 @@ if (!$c_vcal->expired($files)) { return $c_vcal->loadVcal(); } - + // Create the new iCalendar. $vCal = &new Horde_iCalendar(); $vCal->setAttribute('PRODID', '-//proko2//freebusy 1.0//EN'); $vCal->setAttribute('METHOD', 'PUBLISH'); - + // Create new vFreebusy. $vFb = &Horde_iCalendar::newComponent('vfreebusy', $vCal); $params = array(); @@ -198,33 +213,33 @@ $params['cn'] = $access->cn; } $vFb->setAttribute('ORGANIZER', 'MAILTO:' . $access->owner, $params); - + $vFb->setAttribute('DTSTAMP', time()); $vFb->setAttribute('URL', 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']); $mtimes = array(); foreach ($files as $file) { - if ($extended) { + if ($extended && $conf['fb']['use_acls'] == true) { $extended = $this->_allowExtended($file, $access); } $c_pvcal = &new FreeBusyCacheFile_pvcal($this->_cache_dir, $file); $pvCal = $c_pvcal->loadPVcal($extended); if (is_a($pvCal, 'PEAR_Error')) { - Horde::logMessage(sprintf(_("Ignoring partial free/busy file %s: %s)"), + Horde::logMessage(sprintf(_("Ignoring partial free/busy file %s: %s)"), $file, $pvCal->getMessage()), __FILE__, __LINE__, PEAR_LOG_INFO); continue; } $pvFb = &$pvCal->findComponent('vfreebusy'); if( !$pvFb ) { - Horde::logMessage(sprintf(_("Could not find free/busy info in file %s.)"), + Horde::logMessage(sprintf(_("Could not find free/busy info in file %s.)"), $file), __FILE__, __LINE__, PEAR_LOG_INFO); continue; } if ($ets = $pvFb->getAttributeDefault('DTEND', false) !== false) { // PENDING(steffen): Make value configurable if ($ets < time()) { - Horde::logMessage(sprintf(_("Free/busy info in file %s is too old.)"), + Horde::logMessage(sprintf(_("Free/busy info in file %s is too old.)"), $file), __FILE__, __LINE__, PEAR_LOG_INFO); $c_pvcal->purge(); continue; @@ -240,7 +255,7 @@ $remote_vfb = $this->_fetchRemote($conf['fb']['remote_servers'], $access); if (is_a($remote_vfb, 'PEAR_Error')) { - Horde::logMessage(sprintf(_("Ignoring remote free/busy files: %s)"), + Horde::logMessage(sprintf(_("Ignoring remote free/busy files: %s)"), $remote_vfb->getMessage()), __FILE__, __LINE__, PEAR_LOG_INFO); } else { @@ -263,10 +278,10 @@ return $vCal; } - function _allowExtended($file, &$access) + function _allowExtended($file, &$access) { $xaclcache = &FreeBusyCacheDB_xacl::singleton('xacl', $this->_cache_dir); - + foreach ($access->groups as $id) { if ($xaclcache->has($file, $id)) { return true; @@ -283,21 +298,21 @@ if (ereg('(.*)@(.*)', $owner, $regs)) { $owner = $regs[2] . '/' . $regs[1]; } - + return str_replace("\0", '', str_replace('.', '^', $owner . '/' . $folder)); } - function &_fetchRemote($servers, $access) + function &_fetchRemote($servers, $access) { $vFb = null; - + foreach ($servers as $server) { - + $url = 'https://' . urlencode($access->user) . ':' . urlencode($access->pass) . '@' . $server . $_SERVER['REQUEST_URI']; $remote = @file_get_contents($url); if (!$remote) { - $message = sprintf(_("Unable to read free/busy information from %s"), + $message = sprintf(_("Unable to read free/busy information from %s"), 'https://' . urlencode($access->user) . ':XXX' . '@' . $server . $_SERVER['REQUEST_URI']); Horde::logMessage($message, __FILE__, __LINE__, PEAR_LOG_INFO); @@ -305,18 +320,18 @@ $rvCal = &new Horde_iCalendar(); $result = $rvCal->parsevCalendar($remote); - + if (is_a($result, 'PEAR_Error')) { - $message = sprintf(_("Unable to parse free/busy information from %s: %s"), + $message = sprintf(_("Unable to parse free/busy information from %s: %s"), 'https://' . urlencode($access->user) . ':XXX' . '@' . $server . $_SERVER['REQUEST_URI'], $result->getMessage()); Horde::logMessage($message, __FILE__, __LINE__, PEAR_LOG_INFO); } - + $rvFb = &$rvCal->findComponent('vfreebusy'); if (!$pvFb) { - $message = sprintf(_("Unable to find free/busy information in data from %s."), + $message = sprintf(_("Unable to find free/busy information in data from %s."), 'https://' . urlencode($access->user) . ':XXX' . '@' . $server . $_SERVER['REQUEST_URI']); Horde::logMessage($message, __FILE__, __LINE__, PEAR_LOG_INFO); @@ -324,7 +339,7 @@ if ($ets = $rvFb->getAttributeDefault('DTEND', false) !== false) { // PENDING(steffen): Make value configurable if ($ets < time()) { - $message = sprintf(_("free/busy information from %s is too old."), + $message = sprintf(_("free/busy information from %s is too old."), 'https://' . urlencode($access->user) . ':XXX' . '@' . $server . $_SERVER['REQUEST_URI']); Horde::logMessage($message, __FILE__, __LINE__, PEAR_LOG_INFO); @@ -338,6 +353,23 @@ } return $vFb; } + + function findAll_readdir($uid, $dirname, &$lst) { + if ($dir = @opendir($dirname)) { + while (($file = readdir($dir)) !== false) { + if ($file == "." || $file == "..") + continue; + + $full_path = $dirname."/".$file; + + if (is_file($full_path) && preg_match("/(.*)\.x?pvc$/", $file, $matches)) + $lst[] = $uid."/".$matches[1]; + else if(is_dir($full_path)) + $this->findAll_readdir($uid."/".$file, $full_path, $lst); + } + closedir($dir); + } + } }; class FreeBusyCacheDB { @@ -351,7 +383,7 @@ global $conf; $this->_cache_dir = $cache_dir; - + if (!empty($conf['fb']['dbformat'])) { $this->_dbformat = $conf['fb']['dbformat']; } else { @@ -369,7 +401,7 @@ } - function _open() + function _open() { if ($this->_db) { return; @@ -381,7 +413,7 @@ return PEAR::raiseError(sprintf(_("Unable to open freebusy cache db %s"), $dbfile)); } } - + function _close() { @dba_close($this->_db); @@ -444,7 +476,7 @@ } return false; } - + function get($uid) { $result = $this->_open(); @@ -458,7 +490,7 @@ } return array(); } - + /** * Attempts to return a reference to a concrete FreeBusyACLCache * instance. It will only create a new instance if no @@ -604,7 +636,7 @@ /* Store the cache data */ $fh = fopen($this->_file, 'w'); if (!$fh) { - return PEAR::raiseError(sprintf(_("Failed creating cache file %s!"), + return PEAR::raiseError(sprintf(_("Failed creating cache file %s!"), $this->_file)); } fwrite($fh, serialize(array('version' => $this->_version, @@ -616,30 +648,30 @@ { $file = @file_get_contents($this->_file); if ($file === false) { - return PEAR::raiseError(sprintf(_("%s failed reading cache file %s!"), + return PEAR::raiseError(sprintf(_("%s failed reading cache file %s!"), get_class($this), $this->_file)); } $cache = @unserialize($file); if ($cache === false) { - return PEAR::raiseError(sprintf(_("%s failed to unserialize cache data from file %s!"), + return PEAR::raiseError(sprintf(_("%s failed to unserialize cache data from file %s!"), get_class($this), $this->_file)); } if (!isset($cache['version'])) { - return PEAR::raiseError(sprintf(_("Cache file %s lacks version data!"), + return PEAR::raiseError(sprintf(_("Cache file %s lacks version data!"), $this->_file)); } $this->_version = $cache['version']; if (!isset($cache['data'])) { - return PEAR::raiseError(sprintf(_("Cache file %s lacks data!"), + return PEAR::raiseError(sprintf(_("Cache file %s lacks data!"), $this->_file)); } if ($cache['version'] != $this->_version) { - return PEAR::raiseError(sprintf(_("Cache file %s has version %s while %s is required!"), + return PEAR::raiseError(sprintf(_("Cache file %s has version %s while %s is required!"), $this->_file, $cache['version'], $this->_version)); } return $cache['data']; } - + function _maketree($dirname) { $base = substr($dirname, 0, strrpos($dirname, '/')); @@ -685,7 +717,7 @@ return $pvcal; } - function getMtime() + function getMtime() { return filemtime($this->_file); } @@ -705,13 +737,13 @@ 'mtimes' => $mtimes); return $this->store($data); } - + function &loadVcal() { if ($this->_data) { return $this->_data; } - + $result = $this->load(); if (is_a($result, 'PEAR_Error')) { return $result; @@ -738,7 +770,7 @@ /* Files changed? */ $keys = array_keys($result['mtimes']); - $changes = array_diff($keys, $files); + $changes = array_diff($keys, $files); if (count($keys) != count($files) || !empty($changes)) { return true; } @@ -774,8 +806,8 @@ var $_suffix = 'acl'; var $_acls; - - function FreeBusyCacheFile_acl($cache_dir, $filename) + + function FreeBusyCacheFile_acl($cache_dir, $filename) { $this->_acls = &FreeBusyCacheDB::singleton('acl', $cache_dir); parent::FreeBusyCacheFile($cache_dir, $filename, 'acl'); @@ -787,7 +819,7 @@ if (is_a($oldacl, 'PEAR_Error')) { $oldacl = array(); } - + $result = $this->_acls->store($this->_filename, array(), $oldacl, false); if (is_a($result, 'PEAR_Error')) { return $result; @@ -795,8 +827,8 @@ return parent::purge(); } - - function storeACL(&$acl, $relevance) + + function storeACL(&$acl, $relevance) { $oldacl = $this->load(); if (is_a($oldacl, 'PEAR_Error')) { @@ -811,7 +843,7 @@ case 'nobody': $perm = false; break; - case 'admins': + case 'admins': default: $perm = 'a'; } @@ -833,8 +865,8 @@ var $_suffix = 'xacl'; var $_xacls; - - function FreeBusyCacheFile_xacl($cache_dir, $filename) + + function FreeBusyCacheFile_xacl($cache_dir, $filename) { $this->_xacls = &FreeBusyCacheDB::singleton('xacl', $cache_dir); parent::FreeBusyCacheFile($cache_dir, $filename, 'xacl'); @@ -846,7 +878,7 @@ if (is_a($oldxacl, 'PEAR_Error')) { $oldxacl = ''; } - + $result = $this->_xacls->store($this->_filename, '', $oldxacl); if (is_a($result, 'PEAR_Error')) { return $result; @@ -854,8 +886,8 @@ return parent::purge(); } - - function storeXACL(&$xacl) + + function storeXACL(&$xacl) { $oldxacl = $this->load(); if (is_a($oldxacl, 'PEAR_Error')) { diff -u -r -p kolab-freebusy/freebusy/config.php kolab-freebusy.noacls/freebusy/config.php --- kolab-freebusy/freebusy/config.php 2007-11-23 14:39:32.000000000 +0100 +++ kolab-freebusy.noacls/freebusy/config.php 2008-03-06 10:16:59.000000000 +0100 @@ -102,6 +102,10 @@ $conf['fb']['send_content_length'] = fal */ $conf['fb']['send_content_disposition'] = false; +/* Should we use ACLs or does everybody get full rights? + */ +$conf['fb']['use_acls'] = true; + /* Are there remote servers on which users have additional (shared) * folders? In that case free/busy information should also be fetched * from these servers.