*/
/**
- * The Horde_Kolab_FreeBusy class serves as Registry aka ServiceLocator for the
+ * The Horde_Kolab_FreeBusy class holds the Registry aka ServiceLocator for the
* Free/Busy application. It also provides the entry point into the the Horde
* MVC system and allows to dispatch a request.
*
static protected $instance;
/**
- * The object representing the request.
+ * The provider for dependency injection
*
- * @var Horde_Controller_Request_Base
+ * @var Horde_Provider_Base
*/
- private $_request;
+ protected $provider;
/**
- * The object representing the request<->controller mapping.
+ * Constructor.
*
- * @var Horde_Routes_Mapper
+ * @param array $params The parameters required to initialize the
+ * application.
*/
- private $_mapper;
+ public function __construct($params = array())
+ {
+ $this->provider = new Horde_Provider_Base();
+ $this->provider->params = $params;
+ $this->provider->request = new Horde_Provider_Injection_Factory(array('Horde_Kolab_FreeBusy_Factory', 'getRequest'));
+ $this->provider->mapper = new Horde_Provider_Injection_Factory(array('Horde_Kolab_FreeBusy_Factory', 'getMapper'));
+ $this->provider->dispatcher = new Horde_Provider_Injection_Factory(array('Horde_Kolab_FreeBusy_Factory', 'getDispatcher'));
+ $this->provider->logger = new Horde_Provider_Injection_Factory(array('Horde_Kolab_FreeBusy_Factory', 'getLogger'));
+ $this->provider->driver = new Horde_Provider_Injection_Factory(array('Horde_Kolab_FreeBusy_Driver_Base', 'factory'));
+ }
/**
- * The request dispatcher.
+ * Get an element.
+ *
+ * @param string $key The key of the element to retrieve.
*
- * @var Horde_Controller_Dispatcher
+ * @return mixed The element.
*/
- private $_dispatcher;
+ public function __get($key)
+ {
+ return $this->provider->{$key};
+ }
/**
- * Constructor.
+ * Set an element to the given value.
*
- * @param array $params The parameters required to initialize the
- * application.
+ * @param string $key The key of the element to set.
+ * @param mixed $value The value to set the element to.
+ *
+ * @return NULL
*/
- public function __construct($params = array())
+ public function __set($key, $value)
{
- $this->_params = $params;
+ $this->provider->{$key} = $value;
}
/**
* 'controllerDir' - (string) The directory holding controllers.
* 'viewsDir' - (string) The directory holding views.
*
+ * 'logger' - (array) The keys of the array are log handler class names
+ * (e.g. Horde_Log_Handler_Stream) while the
+ * corresponding values are arrays. Each such array
+ * may contain a key 'params' that holds parameters
+ * passed to the constructor of the log handler. It
+ * may also hold a second key 'options' with options
+ * passed to the instantiated log handler. [optional]
+ *
* </pre>
*
* @return Horde_Kolab_FreeBusy The Horde_Registry instance.
}
/**
- * Inject the request object into the application context.
- *
- * @param Horde_Controller_Request_Base $request The object that should
- * represent the current
- * request.
- *
- * @return NULL
- */
- public function setRequest(Horde_Controller_Request_Base $request)
- {
- $this->_request = $request;
- }
-
- /**
- * Return the object representing the current request.
- *
- * @return Horde_Controller_Request_Base The current request.
- *
- * @throws Horde_Exception
- */
- public function getRequest()
- {
- if (!isset($this->_request)) {
- if (!empty($this->_params['request']['class'])) {
- $request_class = $this->_params['request']['class'];
- } else {
- $request_class = 'Horde_Controller_Request_Http';
- }
- if (!empty($this->_params['request']['params'])) {
- $params = $this->_params['request']['params'];
- } else {
- $params = array();
- }
- // Set up our request and routing objects
- $this->_request = new $request_class($params);
- /**
- * The HTTP request object would hide errors. Display them.
- */
- if (isset($this->request->_exception)) {
- throw $this->request->_exception;
- }
- }
-
- return $this->_request;
- }
-
- /**
- * Inject the mapper object into the application context.
- *
- * @param Horde_Route_Mapper $mapper The object that handles mapping.
- *
- * @return NULL
- */
- public function setMapper(Horde_Route_Mapper $mapper)
- {
- $this->_mapper = $mapper;
- }
-
- /**
- * Return the mapper.
- *
- * @return Horde_Route_Mapper The mapper.
- *
- * @throws Horde_Exception
- */
- public function getMapper()
- {
- if (!isset($this->_mapper)) {
- if (!empty($this->_params['mapper']['params'])) {
- $params = $this->_params['mapper']['params'];
- } else {
- $params = array();
- }
- $this->_mapper = new Horde_Routes_Mapper($params);
-
- /**
- * Application routes are relative only to the application. Let the
- * mapper know where they start.
- */
- if (!empty($this->_params['script'])) {
- $this->_mapper->prefix = dirname($this->_params['script']);
- } else {
- $this->_mapper->prefix = dirname($_SERVER['PHP_SELF']);
- }
-
- // Check for route definitions.
- if (!empty($this->_params['config']['dir'])) {
- $routeFile = $this->_params['config']['dir'] . '/routes.php';
- }
- if (empty($this->_params['config']['dir'])
- || !file_exists($routeFile)) {
- $this->_mapper->connect(':(mail).:(type)',
- array('controller' => 'freebusy',
- 'action' => 'fetch',
- 'requirements' => array('type' => '(i|x|v)fb',
- 'mail' => '[^/]+'),
- ));
-
- $this->_mapper->connect('trigger/*(folder).pfb',
- array('controller' => 'freebusy',
- 'action' => 'trigger'
- ));
-
- $this->_mapper->connect('*(folder).:(type)',
- array('controller' => 'freebusy',
- 'action' => 'trigger',
- 'requirements' => array('type' => '(p|px)fb'),
- ));
-
- $this->_mapper->connect('delete/:(mail)',
- array('controller' => 'freebusy',
- 'action' => 'delete',
- 'requirements' => array('mail' => '[^/]+'),
- ));
-
- $this->_mapper->connect('regenerate',
- array('controller' => 'freebusy',
- 'action' => 'regenerate',
- ));
- } else {
- // Load application routes.
- include $routeFile;
- }
- }
-
- return $this->_mapper;
- }
-
- /**
- * Inject the dispatcher object into the application context.
- *
- * @param Horde_Controller_Dispatcher $dispatcher The object that handles
- * dispatching.
- *
- * @return NULL
- */
- public function setDispatcher(Horde_Controller_Dispatcher $dispatcher)
- {
- $this->_dispatcher = $dispatcher;
- }
-
- /**
- * Return the dispatcher.
- *
- * @return Horde_Controller_Dispatcher The dispatcher.
- *
- * @throws Horde_Exception
- */
- public function getDispatcher()
- {
- if (!isset($this->_dispatcher)) {
- if (empty($this->_params['dispatch']['controllerDir'])) {
- $controllerDir = dirname(__FILE__) . '/FreeBusy/Controller';
- } else {
- $controllerDir = $this->_params['dispatch']['controllerDir'];
- }
-
- if (empty($this->_params['dispatch']['viewsDir'])) {
- $viewsDir = dirname(__FILE__) . '/FreeBusy/View';
- } else {
- $viewsDir = $this->_params['dispatch']['viewsDir'];
- }
-
- $context = array(
- 'mapper' => $this->getMapper(),
- 'controllerDir' => $controllerDir,
- 'viewsDir' => $viewsDir,
- // 'logger' => '',
- );
-
- $this->_dispatcher = Horde_Controller_Dispatcher::singleton($context);
- }
-
- return $this->_dispatcher;
- }
-
- /**
* Handle the current request.
*
* @return NULL
public function dispatch()
{
try {
- $this->getDispatcher()->dispatch($this->getRequest());
+ $this->provider->dispatcher->dispatch($this->provider->request);
} catch (Exception $e) {
//@todo: Error view
throw $e;
+++ /dev/null
-<?php
-/**
- * The Horde_Kolab_FreeBusy_Access:: class provides functionality to check
- * free/busy access rights for the specified folder.
- *
- * $Horde: framework/Kolab_FreeBusy/lib/Horde/Kolab/FreeBusy/Access.php,v 1.23 2009/07/08 18:39:07 slusarz Exp $
- *
- * Copyright 2004-2008 Klarälvdalens Datakonsult AB
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
- *
- * @author Gunnar Wrobel <p@rdus.de>
- * @author Steffen Hansen <steffen@klaralvdalens-datakonsult.se>
- * @package Kolab_FreeBusy
- */
-class Horde_Kolab_FreeBusy_Access {
-
- /**
- * The user calling the script.
- *
- * @var string
- */
- var $user;
-
- /**
- * Did the above combination authenticate?
- *
- * @var string
- */
- var $_authenticated = false;
-
- /**
- * The object representing the user calling the script.
- *
- * @var string
- */
- var $user_object;
-
- /**
- * The requested owner.
- *
- * @var string
- */
- var $owner;
-
- /**
- * The object representing the folder owner.
- *
- * @var string
- */
- var $owner_object;
-
- /**
- * The object representing the server configuration.
- *
- * @var string
- */
- var $server_object;
-
- /**
- * The folder we try to access.
- *
- * @var string
- */
- var $folder;
-
- /**
- * The IMAP path of folder we try to access.
- *
- * @var string
- */
- var $imap_folder;
-
- /**
- * The common name (CN) of the owner.
- *
- * @var string
- */
- var $cn = '';
-
- /**
- * The free/busy server for the folder owner.
- *
- * @var string
- */
- var $freebusyserver;
-
- /**
- * Constructor.
- *
- * @param array $params Any additional options
- */
- function Horde_Kolab_FreeBusy_Access()
- {
- $this->_parseUser();
- }
-
- /**
- * Parse the requested folder for the owner of that folder.
- *
- * @param string $req_folder The folder requested.
- *
- * @return boolean|PEAR_Error True if successful.
- */
- function parseFolder($req_folder = '')
- {
- /* Handle the owner/folder name and make sure the owner part is in lower case */
- $req_folder = Horde_String::convertCharset($req_folder, 'UTF-8', 'UTF7-IMAP');
- $folder = explode('/', $req_folder);
- if (count($folder) < 2) {
- return PEAR::raiseError(sprintf(_("No such folder %s"), $req_folder));
- }
-
- $folder[0] = strtolower($folder[0]);
- $req_folder = implode('/', $folder);
- $this->owner = $folder[0];
- unset($folder[0]);
- $this->folder = join('/', $folder);
-
- $result = $this->_process();
- if (is_a($result, 'PEAR_Error')) {
- return $result;
- }
- return true;
- }
-
- /**
- * Parse the owner value.
- *
- * @param string $owner The owner that should be processed.
- *
- * @return boolean|PEAR_Error True if successful.
- */
- function parseOwner($owner = '')
- {
- $this->owner = $owner;
-
- $result = $this->_process();
- if (is_a($result, 'PEAR_Error')) {
- return $result;
- }
- return true;
- }
-
- /**
- * Fetch remote free/busy user if the current user is not local or
- * redirect to the other server if configured this way.
- *
- * @param boolean $trigger Have we been called for triggering?
- * @param boolean $extended Should the extended information been delivered?
- */
- function fetchRemote($trigger = false, $extended = false)
- {
- global $conf;
-
- if (!empty($conf['kolab']['freebusy']['server'])) {
- $server = $conf['kolab']['freebusy']['server'];
- } else {
- $server = 'https://localhost/freebusy';
- }
- if (!empty($conf['fb']['redirect'])) {
- $do_redirect = $conf['fb']['redirect'];
- } else {
- $do_redirect = false;
- }
-
- if ($trigger) {
- $path = sprintf('/trigger/%s/%s.' . ($extended)?'pxfb':'pfb',
- urlencode($this->owner), urlencode($this->imap_folder));
- } else {
- $path = sprintf('/%s.' . ($extended)?'xfb':'ifb', urlencode($this->owner));
- }
-
- /* Check if we are on the right server and redirect if appropriate */
- if ($this->freebusyserver && $this->freebusyserver != $server) {
- $redirect = $this->freebusyserver . $path;
- Horde::logMessage(sprintf("URL %s indicates remote free/busy server since we only offer %s. Redirecting.",
- $this->freebusyserver, $server), __FILE__,
- __LINE__, PEAR_LOG_ERR);
- if ($do_redirect) {
- header("Location: $redirect");
- } else {
- header("X-Redirect-To: $redirect");
- $redirect = 'https://' . urlencode($this->user) . ':' . urlencode(Horde_Auth::getCredential('password'))
- . '@' . $this->freebusyserver . $path;
- if (!@readfile($redirect)) {
- $message = sprintf(_("Unable to read free/busy information from %s"),
- 'https://' . urlencode($this->user) . ':XXX'
- . '@' . $this->freebusyserver . $_SERVER['REQUEST_URI']);
- return PEAR::raiseError($message);
- }
- }
- exit;
- }
- }
-
- /**
- * Check if we are in an authenticated situation.
- *
- * @return boolean|PEAR_Error True if successful.
- */
- function authenticated()
- {
- global $conf;
-
- if (empty($this->user)) {
- header('WWW-Authenticate: Basic realm="Kolab Freebusy"');
- return PEAR::raiseError(_("Please authenticate!"));
- }
-
- if (!$this->_authenticated) {
- return PEAR::raiseError(sprintf(_("Invalid authentication for user %s!"),
- $this->user));
- }
- return true;
- }
-
- /**
- * Parse the current user accessing the page and try to
- * authenticate the user.
- */
- function _parseUser()
- {
- global $conf;
-
- $this->user = Horde_Auth::getAuth();
-
- if (empty($this->user)) {
- $this->user = isset($_SERVER['PHP_AUTH_USER'])?$_SERVER['PHP_AUTH_USER']:false;
- $pass = isset($_SERVER['PHP_AUTH_PW'])?$_SERVER['PHP_AUTH_PW']:false;
- } else {
- $this->_authenticated = true;
- return;
- }
-
- // This part allows you to use the PHP scripts with CGI rather than as
- // an apache module. This will of course slow down things but on the
- // other hand it allows you to reduce the memory footprint of the
- // apache server. The default is to use PHP as a module and the CGI
- // version requires specific Apache configuration.
- //
- // The line you need to add to your configuration of the /freebusy
- // location of your server looks like this:
- //
- // RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}]
- //
- // The complete section will probably look like this then:
- //
- // <IfModule mod_rewrite.c>
- // RewriteEngine On
- // # FreeBusy list handling
- // RewriteBase /freebusy
- // RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}]
- // RewriteRule ^([^/]+)\.ifb freebusy.php?uid=$1 [L]
- // RewriteRule ^([^/]+)\.vfb freebusy.php?uid=$1 [L]
- // RewriteRule ^([^/]+)\.xfb freebusy.php?uid=$1&extended=1 [L]
- // RewriteRule ^trigger/(.+)\.pfb pfb.php?folder=$1&cache=0 [L]
- // RewriteRule ^(.+)\.pfb pfb.php?folder=$1&cache=1 [L]
- // RewriteRule ^(.+)\.pxfb pfb.php?folder=$1&cache=1&extended=1 [L]
- // </IfModule>
- if (empty($this->user) && isset($_ENV['REDIRECT_REDIRECT_REMOTE_USER'])) {
- $a = base64_decode(substr($_ENV['REDIRECT_REDIRECT_REMOTE_USER'], 6)) ;
- if ((strlen($a) != 0) && (strcasecmp($a, ':') == 0)) {
- list($this->user, $pass) = explode(':', $a, 2);
- }
- }
-
- if (!empty($this->user)) {
- /* Load the authentication libraries */
- $auth = Horde_Auth::singleton(isset($conf['auth']['driver'])?$conf['auth']['driver']:'kolab');
- if (!$this->_authenticated) {
- $this->_authenticated = $auth->authenticate($this->user, array('password' => $pass), false);
- }
- if ($this->_authenticated) {
- @session_start();
- $_SESSION['__auth'] = array(
- 'authenticated' => true,
- 'userId' => $this->user,
- 'timestamp' => time(),
- 'remote_addr' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null,
- );
- Horde_Auth::setCredential('password', $pass);
- }
- }
- }
-
- /**
- * Process both the user accessing the page as well as the
- * owner of the requested free/busy information.
- *
- * @return boolean|PEAR_Error True if successful.
- */
- function _process()
- {
- global $conf;
-
- require_once 'Horde/Kolab/Server.php';
-
- if (isset($conf['kolab']['ldap']['phpdn'])) {
- $params = array(
- 'uid' => $conf['kolab']['ldap']['phpdn'],
- 'pass' => $conf['kolab']['ldap']['phppw'],
- );
- } else {
- $params = array(
- 'user' => Horde_Auth::getAuth(),
- 'pass' => Horde_Auth::getCredential('password'),
- );
- }
-
- /* Connect to the Kolab user database */
- $db = &Horde_Kolab_Server::singleton($params);
- // TODO: Remove once Kolab_Server has been fixed to always return the base dn
- $db->fetch();
-
- /* Retrieve the server configuration */
- try {
- $server = $db->fetch(sprintf('k=kolab,%s',
- $db->getBaseUid()),
- 'Horde_Kolab_Server_Object_Kolab_Server');
- $this->server_object = $server;
- } catch (Horde_Kolab_Server_Exception $e) {
- Horde::logMessage(sprintf("Failed fetching the k=kolab configuration object. Error was: %s",
- $e->getMessage()),
- __FILE__, __LINE__, PEAR_LOG_ERR);
- $this->server_object = null;
- }
-
- /* Fetch the user calling us */
- $udn = $db->uidForIdOrMail($this->user);
- if (is_a($udn, 'PEAR_Error')) {
- return $udn;
- }
- if ($udn) {
- $user = $db->fetch($udn, 'Horde_Kolab_Server_Object_Kolab_User');
- if (is_a($user, 'PEAR_Error')) {
- return $user;
- }
- $this->user_object = $user;
- }
-
- if ($this->user_object && $this->user_object->exists()) {
- $mail = $this->user_object->get(Horde_Kolab_Server_Object_Kolab_User::ATTRIBUTE_MAIL);
- if (is_a($mail, 'PEAR_Error')) {
- return $mail;
- }
- if ($mail) {
- $this->user = $mail;
- }
- }
-
- /* Fetch the owner of the free/busy data */
- $odn = $db->uidForIdOrMailOrAlias($this->owner);
- if (is_a($odn, 'PEAR_Error')) {
- return $odn;
- }
- if (!$odn) {
- $idx = strpos($this->user, '@');
- if($idx !== false) {
- $domain = substr($this->user, $idx+1);
- Horde::logMessage(sprintf("Trying to append %s to %s",
- $domain, $this->owner),
- __FILE__, __LINE__, PEAR_LOG_DEBUG);
- $odn = $odn = $db->uidForIdOrMail($this->owner . '@' . $domain);
- }
- }
-
- if ($odn) {
- $owner = $db->fetch($odn, 'Horde_Kolab_Server_Object_Kolab_User');
- if (is_a($owner, 'PEAR_Error')) {
- return $owner;
- }
- $this->owner_object = &$owner;
- }
-
- if (!empty($this->owner_object)) {
- if ($this->owner_object->exists()) {
- $this->owner = $this->owner_object->get(Horde_Kolab_Server_Object_Kolab_User::ATTRIBUTE_MAIL);
-
- $freebusyserver = $this->owner_object->getServer('freebusy');
- if (!is_a($freebusyserver, 'PEAR_Error')) {
- $this->freebusyserver = $freebusyserver;
- }
- }
- } else {
- return PEAR::raiseError(_("Unable to determine owner of the free/busy data!"));
- }
-
- /* Mangle the folder request into an IMAP folder name */
- $this->imap_folder = $this->_getImapFolder();
-
- return true;
- }
-
- /**
- * Calculate the correct IMAP folder name to access based on the
- * combination of user and owner.
- *
- * @return string The IMAP folder we should access.
- */
- function _getImapFolder()
- {
- $userdom = false;
- $ownerdom = false;
- if (ereg( '(.*)@(.*)', $this->user, $regs)) {
- // Regular user
- $user = $regs[1];
- $userdom = $regs[2];
- } else {
- $user = $this->user;
- }
-
- if(ereg( '(.*)@(.*)', $this->owner, $regs)) {
- // Regular owner
- $owner = $regs[1];
- $ownerdom = $regs[2];
- } else {
- $owner = $this->owner;
- }
-
- $fldrcomp = array();
- if ($user == $owner) {
- $fldrcomp[] = 'INBOX';
- } else {
- $fldrcomp[] = 'user';
- $fldrcomp[] = $owner;
- }
-
- if (!empty($this->folder)) {
- $fldrcomp[] = $this->folder;
- }
-
- $folder = join('/', $fldrcomp);
- if ($ownerdom && !$userdom) {
- $folder .= '@' . $ownerdom;
- }
- return $folder;
- }
-
-}
-
}
/**
- * Load the complete free/busy data of a user.
- *
- * @param Horde_Kolab_FreeBusy_Access $access The object holding the
- * relevant access
- * parameters.
- * @param boolean $extended Should the data hold the extended
- * free/busy information?
- *
- * @return Horde_iCalendar|PEAR_Error The free/busy data for a user.
- */
- function &load(&$access, $extended)
- {
- global $conf;
-
- /* Which files will we access? */
- if (!empty($conf['fb']['use_acls'])) {
- $aclcache = &Horde_Kolab_FreeBusy_Cache_DB_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);
- }
-
- $owner = $access->owner;
- if (ereg('(.*)@(.*)', $owner, $regs)) {
- $owner = $regs[2] . '/' . $regs[1];
- }
- $user = $access->user;
- if (ereg('(.*)@(.*)', $user, $regs)) {
- $user = $regs[2] . '/' . $regs[1];
- }
- $c_file = str_replace("\0", '', str_replace('.', '^', $user . '/' . $owner));
-
- $c_vcal = new Horde_Kolab_FreeBusy_Cache_File_vcal($this->_cache_dir,
- $c_file, $extended);
-
- /* If the current vCal cache did not expire, we can deliver it */
- if (!$c_vcal->expired($files)) {
- return $c_vcal->loadVcal();
- }
-
- // Create the new iCalendar.
- $vCal = new Horde_iCalendar();
- $vCal->setAttribute('PRODID', '-//kolab.org//NONSGML Kolab Server 2//EN');
- $vCal->setAttribute('METHOD', 'PUBLISH');
-
- // Create new vFreebusy.
- $vFb = &Horde_iCalendar::newComponent('vfreebusy', $vCal);
- $params = array();
-
- $cn = $access->owner_object->get(Horde_Kolab_Server_Object_Kolab_User::ATTRIBUTE_CN);
- if (!empty($cn) || is_a($cn, 'PEAR_Error')) {
- $params['cn'] = $access->owner_object->get(Horde_Kolab_Server_Object_Kolab_User::ATTRIBUTE_CN);
- }
- $vFb->setAttribute('ORGANIZER', 'MAILTO:' . $access->owner, $params);
-
- $vFb->setAttribute('DTSTAMP', time());
- if (isset($_SERVER['SERVER_NAME'])) {
- $host = $_SERVER['SERVER_NAME'];
- } else {
- $host = 'localhost';
- }
- if (isset($_SERVER['REQUEST_URI'])) {
- $uri = $_SERVER['REQUEST_URI'];
- } else {
- $uri = '/';
- }
- $vFb->setAttribute('URL', 'http://' . $host . $uri);
-
- $mtimes = array();
- foreach ($files as $file) {
- if ($extended && !empty($conf['fb']['use_acls'])) {
- $extended_pvc = $this->_allowExtended($file, $access);
- } else {
- $extended_pvc = $extended;
- }
- $c_pvcal = new Horde_Kolab_FreeBusy_Cache_File_pvcal($this->_cache_dir, $file);
- $pvCal = $c_pvcal->loadPVcal($extended_pvc);
- if (is_a($pvCal, 'PEAR_Error')) {
- 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.)",
- $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.)",
- $file), __FILE__, __LINE__, PEAR_LOG_INFO);
- $c_pvcal->purge();
- continue;
- }
- }
- $vFb->merge($pvFb);
-
- /* Store last modification time */
- $mtimes[$file] = array($c_pvcal->getFile(), $c_pvcal->getMtime());
- }
-
- if (!empty($conf['fb']['remote_servers'])) {
- $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)",
- $remote_vfb->getMessage()),
- __FILE__, __LINE__, PEAR_LOG_INFO);
- } else {
- $vFb->merge($remote_vfb);
- }
- }
-
- if (!(boolean)$vFb->getBusyPeriods()) {
- /* No busy periods in fb list. We have to add a
- * dummy one to be standards compliant
- */
- $vFb->setAttribute('COMMENT', 'This is a dummy vfreebusy that indicates an empty calendar');
- $vFb->addBusyPeriod('BUSY', 0,0, null);
- }
-
- $vCal->addComponent($vFb);
-
- $c_vcal->storeVcal($vCal, $mtimes);
-
- return $vCal;
- }
-
- /**
* Is extended access to the given file allowed?
*
* @param string $file Name of the cache file.
--- /dev/null
+<?php
+/**
+ * The Kolab implementation of the free/busy system.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package Kolab_FreeBusy
+ * @author Steffen Hansen <steffen@klaralvdalens-datakonsult.se>
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_FreeBusy
+ */
+
+/**
+ * The Horde_Kolab_FreeBusy class serves as Registry aka ServiceLocator for the
+ * Free/Busy application. It also provides the entry point into the the Horde
+ * MVC system and allows to dispatch a request.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you did not
+ * receive this file, see
+ * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ *
+ * @category Kolab
+ * @package Kolab_FreeBusy
+ * @author Steffen Hansen <steffen@klaralvdalens-datakonsult.se>
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_FreeBusy
+ * @since Horde 3.2
+ */
+class Horde_Kolab_FreeBusy_Cache_Base
+{
+
+ public function getParts($callee)
+ {
+ }
+
+ public function calleeExpired($callee, $parts)
+ {
+ }
+
+ public function getCallee($callee, $params = array())
+ {
+ }
+
+ public function setCallee($callee, $parts, $data, $params = array())
+ {
+ }
+
+ public function getCalleePart($callee, $part, $params = array())
+ {
+ }
+}
\ No newline at end of file
class FreeBusyController extends Horde_Controller_Base
{
/**
+ * A reference to the application class.
+ *
+ * @var Horde_Kolab_FreeBusy
+ */
+ protected $app;
+
+ /**
+ * A reference to the logger.
+ *
+ * @var Horde_Log_Logger
+ */
+ protected $logger;
+
+ /**
* Parameters provided to this class.
*
* @var array
var $_cache;
/**
- * Setup the cache.
+ * Constructor.
*/
- function _initCache()
+ public function __construct()
{
- global $conf;
-
- /* Load the cache class now */
- require_once 'Horde/Kolab/FreeBusy/Cache.php';
-
- /* Where is the cache data stored? */
- if (!empty($conf['fb']['cache_dir'])) {
- $cache_dir = $conf['fb']['cache_dir'];
- } else {
- if (class_exists('Horde')) {
- $cache_dir = Horde::getTempDir();
- } else {
- $cache_dir = '/tmp';
- }
- }
-
- $this->_cache = new Horde_Kolab_FreeBusy_Cache($cache_dir);
+ /**
+ * The dispatcher does not know how to construct this class so we are
+ * left to fetching our dependencies ourselves. The application class is
+ * used as a service locator here.
+ */
+ $this->app = Horde_Kolab_FreeBusy::singleton();
+ $this->logger = $this->app->logger;
}
/**
- * Trigger regeneration of free/busy data in a calender.
+ * Fetch the free/busy data for a user.
*
* @return NULL
*/
- function &trigger()
+ public function fetch()
{
- global $conf;
-
- /* Get the folder name */
- $req_folder = Horde_Util::getFormData('folder', '');
-
- Horde::logMessage(sprintf("Starting generation of partial free/busy data for folder %s",
- $req_folder), __FILE__, __LINE__, PEAR_LOG_DEBUG);
-
- /* Validate folder access */
- $access = new Horde_Kolab_FreeBusy_Access();
- $result = $access->parseFolder($req_folder);
- if (is_a($result, 'PEAR_Error')) {
- $error = array('type' => FREEBUSY_ERROR_NOTFOUND,
- 'error' => $result);
- $view = new Horde_Kolab_FreeBusy_View_error($error);
- return $view;
- }
-
- Horde::logMessage(sprintf("Partial free/busy data of owner %s on server %s requested by user %s.",
- $access->owner, $access->freebusyserver, $access->user),
- __FILE__, __LINE__, PEAR_LOG_DEBUG);
-
- /* Get the cache request variables */
- $req_cache = Horde_Util::getFormData('cache', false);
- $req_extended = Horde_Util::getFormData('extended', false);
-
- /* Try to fetch the data if it is stored on a remote server */
- $result = $access->fetchRemote(true, $req_extended);
- if (is_a($result, 'PEAR_Error')) {
- $error = array('type' => FREEBUSY_ERROR_UNAUTHORIZED,
- 'error' => $result);
- $view = new Horde_Kolab_FreeBusy_View_error($error);
- return $view;
- }
-
- $this->_initCache();
-
- if (!$req_cache) {
- /* User wants to regenerate the cache */
+ $this->logger->debug(sprintf("Starting generation of free/busy data for user %s",
+ $this->params->callee));
- /* Here we really need an authenticated IMAP user */
- $result = $access->authenticated();
- if (is_a($result, 'PEAR_Error')) {
- $error = array('type' => FREEBUSY_ERROR_UNAUTHORIZED,
- 'error' => $result);
- $view = new Horde_Kolab_FreeBusy_View_error($error);
- return $view;
- }
-
- if (empty($access->owner)) {
- $message = sprintf(_("No such account %s!"),
- htmlentities($access->req_owner));
- $error = array('type' => FREEBUSY_ERROR_NOTFOUND,
- 'error' => PEAR::raiseError($message));
- $view = new Horde_Kolab_FreeBusy_View_error($error);
- return $view;
- }
-
- /* Update the cache */
- $result = $this->_cache->store($access);
- if (is_a($result, 'PEAR_Error')) {
- $error = array('type' => FREEBUSY_ERROR_NOTFOUND,
- 'error' => $result);
- $view = new Horde_Kolab_FreeBusy_View_error($error);
- return $view;
- }
- }
-
- /* Load the cache data */
- $vfb = $this->_cache->loadPartial($access, $req_extended);
- if (is_a($vfb, 'PEAR_Error')) {
- $error = array('type' => FREEBUSY_ERROR_NOTFOUND,
- 'error' => $vfb);
- $view = new Horde_Kolab_FreeBusy_View_error($error);
- return $view;
- }
+ $params = array('extended' => $this->params->type == 'xfb');
- Horde::logMessage("Delivering partial free/busy data.", __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ // @todo: Reconsider this. We have been decoupled from the
+ // global context here but reinjecting this value seems
+ // extremely weird. Are there any other options?
+ $this->app->callee = $this->params->callee;
+ $this->data = $this->app->driver->fetch($this->params);
- /* Generate the renderer */
- $data = array('fb' => $vfb, 'name' => $access->owner . '.ifb');
- $view = new Horde_Kolab_FreeBusy_View_vfb($data);
+ $this->logger->debug('Delivering complete free/busy data.');
- /* Finish up */
- Horde::logMessage("Free/busy generation complete.", __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ /* Display the result to the user */
+ $this->render();
- return $view;
+ $this->logger->debug('Free/busy generation complete.');
}
/**
- * Fetch the free/busy data for a user.
+ * Trigger regeneration of free/busy data in a calender.
*
* @return NULL
*/
- function &fetch()
+ function &trigger()
{
- global $conf;
+ $this->logger->debug(sprintf("Starting generation of partial free/busy data for folder %s",
+ $this->params->part));
- /* Get the user requsted */
- $req_owner = Horde_Util::getFormData('uid');
+ $params = array('extended' => $this->params->type == 'pxfb',
+ 'cached' => $this->params->cache);
- Horde::logMessage(sprintf("Starting generation of free/busy data for user %s",
- $req_owner), __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ // @todo: Reconsider this. We have been decoupled from the
+ // global context here but reinjecting this value seems
+ // extremely weird. Are there any other options?
+ $this->app->callee_part = $this->params->part;
+ $this->data = $this->app->driver->trigger($this->params);
- /* Validate folder access */
- $access = new Horde_Kolab_FreeBusy_Access();
- $result = $access->parseOwner($req_owner);
- if (is_a($result, 'PEAR_Error')) {
- $error = array('type' => FREEBUSY_ERROR_NOTFOUND, 'error' => $result);
- $view = new Horde_Kolab_FreeBusy_View_error($error);
- return $view;
- }
-
- Horde::logMessage(sprintf("Free/busy data of owner %s on server %s requested by user %s.",
- $access->owner, $access->freebusyserver, $access->user),
- __FILE__, __LINE__, PEAR_LOG_DEBUG);
-
- $req_extended = Horde_Util::getFormData('extended', false);
+ $this->logger->debug("Delivering partial free/busy data.");
- /* Try to fetch the data if it is stored on a remote server */
- $result = $access->fetchRemote(false, $req_extended);
- if (is_a($result, 'PEAR_Error')) {
- $error = array('type' => FREEBUSY_ERROR_UNAUTHORIZED, 'error' => $result);
- $view = new Horde_Kolab_FreeBusy_View_error($error);
- return $view;
- }
-
- $this->_initCache();
+ /* Display the result to the user */
+ $this->render();
- $result = $this->_cache->load($access, $req_extended);
- if (is_a($result, 'PEAR_Error')) {
- $error = array('type' => FREEBUSY_ERROR_NOTFOUND, 'error' => $result);
- $view = new Horde_Kolab_FreeBusy_View_error($error);
- return $view;
- }
-
- Horde::logMessage("Delivering complete free/busy data.", __FILE__, __LINE__, PEAR_LOG_DEBUG);
-
- /* Generate the renderer */
- $data = array('fb' => $result, 'name' => $access->owner . '.vfb');
- $view = new Horde_Kolab_FreeBusy_View_vfb($data);
-
- /* Finish up */
- Horde::logMessage("Free/busy generation complete.", __FILE__, __LINE__, PEAR_LOG_DEBUG);
-
- return $view;
+ $this->logger->debug("Free/busy generation complete.");
}
+
/**
* Regenerate the free/busy cache data.
*
--- /dev/null
+<?php
+/**
+ * The Kolab implementation of the free/busy system.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package Kolab_FreeBusy
+ * @author Steffen Hansen <steffen@klaralvdalens-datakonsult.se>
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_FreeBusy
+ */
+
+/**
+ * The Horde_Kolab_FreeBusy class serves as Registry aka ServiceLocator for the
+ * Free/Busy application. It also provides the entry point into the the Horde
+ * MVC system and allows to dispatch a request.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you did not
+ * receive this file, see
+ * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ *
+ * @category Kolab
+ * @package Kolab_FreeBusy
+ * @author Steffen Hansen <steffen@klaralvdalens-datakonsult.se>
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_FreeBusy
+ * @since Horde 3.2
+ */
+class Horde_Kolab_FreeBusy_Driver_Base
+{
+ /**
+ * The user calling the script.
+ *
+ * @var string
+ */
+ protected $user;
+
+ /**
+ * The password of the user calling the script.
+ *
+ * @var string
+ */
+ protected $pass;
+
+ /**
+ * The logging handler.
+ *
+ * @var Horde_Log_Logger
+ */
+ protected $logger;
+
+ /**
+ * Constructor.
+ *
+ * @param array $params Any additional options
+ */
+ public function __construct($callee = null, $callee_part = null, $logger = null)
+ {
+ list($this->user, $this->pass) = $this->getCredentials();
+
+ if (!empty($this->user)) {
+ $this->authenticate();
+ }
+
+ if (!empty($callee)) {
+ list($this->callee, $this->remote) = $this->handleCallee($callee);
+ }
+ if (!empty($callee_part)) {
+ list($this->callee, $this->remote, $this->part) = $this->handleCallee($callee_part);
+ }
+
+ $this->logger = $logger;
+ }
+
+ /**
+ * Create a new driver.
+ *
+ * @param Horde_Provider $provider The instance providing required
+ * dependencies.
+ *
+ * @return Horde_Kolab_FreeBusy_Driver_Base The new driver.
+ */
+ static public function factory($provider)
+ {
+ $class = 'Horde_Kolab_FreeBusy_Driver_Freebusy_Kolab';
+ $callee = isset($provider->callee) ? $provider->callee : null;
+ $callee_part = isset($provider->callee_part) ? $provider->callee_part : null;
+ $driver = new $class($callee, $callee_part, $provider->logger);
+ return $driver;
+ }
+
+ /**
+ * Parse the current user accessing the page and try to
+ * authenticate the user.
+ */
+ protected function getCredentials()
+ {
+ $user = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : false;
+ $pass = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : false;
+
+ //@todo: Fix!
+ // This part allows you to use the PHP scripts with CGI rather than as
+ // an apache module. This will of course slow down things but on the
+ // other hand it allows you to reduce the memory footprint of the
+ // apache server. The default is to use PHP as a module and the CGI
+ // version requires specific Apache configuration.
+ //
+ // The line you need to add to your configuration of the /freebusy
+ // location of your server looks like this:
+ //
+ // RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}]
+ //
+ // The complete section will probably look like this then:
+ //
+ // <IfModule mod_rewrite.c>
+ // RewriteEngine On
+ // # FreeBusy list handling
+ // RewriteBase /freebusy
+ // RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}]
+ // RewriteRule ^([^/]+)\.ifb freebusy.php?uid=$1 [L]
+ // RewriteRule ^([^/]+)\.vfb freebusy.php?uid=$1 [L]
+ // RewriteRule ^([^/]+)\.xfb freebusy.php?uid=$1&extended=1 [L]
+ // RewriteRule ^trigger/(.+)\.pfb pfb.php?folder=$1&cache=0 [L]
+ // RewriteRule ^(.+)\.pfb pfb.php?folder=$1&cache=1 [L]
+ // RewriteRule ^(.+)\.pxfb pfb.php?folder=$1&cache=1&extended=1 [L]
+ // </IfModule>
+ if (empty($user) && isset($_ENV['REDIRECT_REDIRECT_REMOTE_USER'])) {
+ $a = base64_decode(substr($_ENV['REDIRECT_REDIRECT_REMOTE_USER'], 6)) ;
+ if ((strlen($a) != 0) && (strcasecmp($a, ':') == 0)) {
+ list($user, $pass) = explode(':', $a, 2);
+ }
+ }
+ return array($user, $pass);
+ }
+
+ /**
+ * Authenticate
+ *
+ * @return boolean|PEAR_Error True if successful.
+ */
+ public function authenticate()
+ {
+ /* Load the authentication libraries */
+ require_once 'Horde/Auth.php';
+ require_once 'Horde/Secret.php';
+
+ $auth = &Auth::singleton(isset($conf['auth']['driver'])?$conf['auth']['driver']:'kolab');
+ if (!$this->_authenticated) {
+ $this->_authenticated = $auth->authenticate($this->user, array('password' => $pass), false);
+ }
+ if ($this->_authenticated) {
+ @session_start();
+ $_SESSION['__auth'] = array(
+ 'authenticated' => true,
+ 'userId' => $this->user,
+ 'timestamp' => time(),
+ 'remote_addr' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null,
+ );
+ Auth::setCredential('password', $pass);
+ }
+ }
+
+ /**
+ * Check if we are in an authenticated situation.
+ *
+ * @return boolean|PEAR_Error True if successful.
+ */
+ public function authenticated()
+ {
+ global $conf;
+
+ if (empty($this->user)) {
+ header('WWW-Authenticate: Basic realm="Kolab Freebusy"');
+ return PEAR::raiseError(_("Please authenticate!"));
+ }
+
+ if (!$this->_authenticated) {
+ return PEAR::raiseError(sprintf(_("Invalid authentication for user %s!"),
+ $this->user));
+ }
+ return true;
+ }
+
+ /**
+ * Fetch the data.
+ *
+ * @params array $params Additional options.
+ *
+ * @return array The fetched data.
+ */
+ //abstract public function fetch($params = array());
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * The Kolab implementation of the free/busy system.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package Kolab_FreeBusy
+ * @author Steffen Hansen <steffen@klaralvdalens-datakonsult.se>
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_FreeBusy
+ */
+
+/**
+ * The Horde_Kolab_FreeBusy class serves as Registry aka ServiceLocator for the
+ * Free/Busy application. It also provides the entry point into the the Horde
+ * MVC system and allows to dispatch a request.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you did not
+ * receive this file, see
+ * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ *
+ * @category Kolab
+ * @package Kolab_FreeBusy
+ * @author Steffen Hansen <steffen@klaralvdalens-datakonsult.se>
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_FreeBusy
+ * @since Horde 3.2
+ */
+class Horde_Kolab_FreeBusy_Driver_Freebusy_Base extends Horde_Kolab_FreeBusy_Driver_Base
+{
+
+ /**
+ * Fetch the free/busy data.
+ *
+ * @params array $params Additional options.
+ *
+ * @return array The free/busy data.
+ */
+ public function fetch($params = array())
+ {
+ $this->logger->debug(sprintf("Free/busy data of owner %s requested by user %s (remote: %s).",
+ $this->callee, $this->user, $this->remote));
+
+ if (!empty($this->remote)) {
+ /* Try to fetch the data if it is stored on a remote server */
+ //@todo: How to determine which hook/processor to run?
+ return $this->fetchRemote($params);
+ // if (is_a($result, 'PEAR_Error')) {
+ // $error = array('type' => FREEBUSY_ERROR_UNAUTHORIZED, 'error' => $result);
+ }
+
+ global $conf;
+
+ /* Which files will we access? */
+ if (!empty($conf['fb']['use_acls'])) {
+ $aclcache = &Horde_Kolab_FreeBusy_Cache_DB_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);
+ }
+
+ $owner = $access->owner;
+ if (ereg('(.*)@(.*)', $owner, $regs)) {
+ $owner = $regs[2] . '/' . $regs[1];
+ }
+ $user = $access->user;
+ if (ereg('(.*)@(.*)', $user, $regs)) {
+ $user = $regs[2] . '/' . $regs[1];
+ }
+ $c_file = str_replace("\0", '', str_replace('.', '^', $user . '/' . $owner));
+
+ $c_vcal = new Horde_Kolab_FreeBusy_Cache_File_vcal($this->_cache_dir,
+ $c_file, $extended);
+
+ /* If the current vCal cache did not expire, we can deliver it */
+ if (!$this->cache->expired($files)) {
+ return $this->cache->loadVcal();
+ }
+
+ // Create the new iCalendar.
+ $vCal = new Horde_iCalendar();
+ $vCal->setAttribute('PRODID', '-//kolab.org//NONSGML Kolab Server 2//EN');
+ $vCal->setAttribute('METHOD', 'PUBLISH');
+
+ // Create new vFreebusy.
+ $vFb = &Horde_iCalendar::newComponent('vfreebusy', $vCal);
+ $params = array();
+
+ $cn = $access->owner_object->get(Horde_Kolab_Server_Object_Kolab_User::ATTRIBUTE_CN);
+ if (!empty($cn) || is_a($cn, 'PEAR_Error')) {
+ $params['cn'] = $access->owner_object->get(Horde_Kolab_Server_Object_Kolab_User::ATTRIBUTE_CN);
+ }
+ $vFb->setAttribute('ORGANIZER', 'MAILTO:' . $access->owner, $params);
+
+ $vFb->setAttribute('DTSTAMP', time());
+ if (isset($_SERVER['SERVER_NAME'])) {
+ $host = $_SERVER['SERVER_NAME'];
+ } else {
+ $host = 'localhost';
+ }
+ if (isset($_SERVER['REQUEST_URI'])) {
+ $uri = $_SERVER['REQUEST_URI'];
+ } else {
+ $uri = '/';
+ }
+ $vFb->setAttribute('URL', 'http://' . $host . $uri);
+
+ $mtimes = array();
+ foreach ($files as $file) {
+ if ($extended && !empty($conf['fb']['use_acls'])) {
+ $extended_pvc = $this->_allowExtended($file, $access);
+ } else {
+ $extended_pvc = $extended;
+ }
+ $c_pvcal = new Horde_Kolab_FreeBusy_Cache_File_pvcal($this->_cache_dir, $file);
+ $pvCal = $c_pvcal->loadPVcal($extended_pvc);
+ if (is_a($pvCal, 'PEAR_Error')) {
+ 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.)",
+ $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.)",
+ $file), __FILE__, __LINE__, PEAR_LOG_INFO);
+ $c_pvcal->purge();
+ continue;
+ }
+ }
+ $vFb->merge($pvFb);
+
+ /* Store last modification time */
+ $mtimes[$file] = array($c_pvcal->getFile(), $c_pvcal->getMtime());
+ }
+
+ if (!empty($conf['fb']['remote_servers'])) {
+ $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)",
+ $remote_vfb->getMessage()),
+ __FILE__, __LINE__, PEAR_LOG_INFO);
+ } else {
+ $vFb->merge($remote_vfb);
+ }
+ }
+
+ if (!(boolean)$vFb->getBusyPeriods()) {
+ /* No busy periods in fb list. We have to add a
+ * dummy one to be standards compliant
+ */
+ $vFb->setAttribute('COMMENT', 'This is a dummy vfreebusy that indicates an empty calendar');
+ $vFb->addBusyPeriod('BUSY', 0,0, null);
+ }
+
+ $vCal->addComponent($vFb);
+
+ $c_vcal->storeVcal($vCal, $mtimes);
+
+ return $vCal;
+
+ $result = $this->app->getCache->load($access, $extended);
+ // if (is_a($result, 'PEAR_Error')) {
+ // $error = array('type' => FREEBUSY_ERROR_NOTFOUND, 'error' => $result);
+
+ //$data = array('fb' => $result, 'name' => $access->owner . '.vfb');
+ //$view = &new Horde_Kolab_FreeBusy_View_vfb($data);
+ }
+
+ /**
+ * Trigger regeneration of free/busy data in a calender.
+ *
+ * @return NULL
+ */
+ function &trigger($params = array())
+ {
+ $this->logger->debug(sprintf("Partial free/busy data of owner %s on server %s requested by user %s.",
+ $this->callee, $this->freebusyserver, $this->user));
+
+ if (!empty($this->remote)) {
+ /* Try to fetch the data if it is stored on a remote server */
+ //@todo: How to determine which hook/processor to run?
+ return $this->triggerRemote($params);
+ // if (is_a($result, 'PEAR_Error')) {
+ // $error = array('type' => FREEBUSY_ERROR_UNAUTHORIZED, 'error' => $result);
+ }
+
+ if (!$req_cache) {
+ /* User wants to regenerate the cache */
+
+ /* Here we really need an authenticated IMAP user */
+ $result = $access->authenticated();
+ if (is_a($result, 'PEAR_Error')) {
+ $error = array('type' => FREEBUSY_ERROR_UNAUTHORIZED,
+ 'error' => $result);
+ $view = new Horde_Kolab_FreeBusy_View_error($error);
+ return $view;
+ }
+
+ if (empty($access->owner)) {
+ $message = sprintf(_("No such account %s!"),
+ htmlentities($access->req_owner));
+ $error = array('type' => FREEBUSY_ERROR_NOTFOUND,
+ 'error' => PEAR::raiseError($message));
+ $view = new Horde_Kolab_FreeBusy_View_error($error);
+ return $view;
+ }
+
+ /* Update the cache */
+ $result = $this->_cache->store($access);
+ if (is_a($result, 'PEAR_Error')) {
+ $error = array('type' => FREEBUSY_ERROR_NOTFOUND,
+ 'error' => $result);
+ $view = new Horde_Kolab_FreeBusy_View_error($error);
+ return $view;
+ }
+ }
+
+ /* Load the cache data */
+ $vfb = $this->_cache->loadPartial($access, $req_extended);
+ if (is_a($vfb, 'PEAR_Error')) {
+ $error = array('type' => FREEBUSY_ERROR_NOTFOUND,
+ 'error' => $vfb);
+ $view = new Horde_Kolab_FreeBusy_View_error($error);
+ return $view;
+ }
+
+ /* Generate the renderer */
+ //$data = array('fb' => $vfb, 'name' => $access->owner . '.ifb');
+ //$view = new Horde_Kolab_FreeBusy_View_vfb($data);
+
+ /* Finish up */
+ return $view;
+ }
+
+ /**
+ * Fetch remote free/busy user if the current user is not local or
+ * redirect to the other server if configured this way.
+ *
+ * @param boolean $trigger Have we been called for triggering?
+ * @param boolean $extended Should the extended information been delivered?
+ */
+ function fetchRemote($trigger = false, $extended = false)
+ {
+ global $conf;
+
+ if (!empty($conf['kolab']['freebusy']['server'])) {
+ $server = $conf['kolab']['freebusy']['server'];
+ } else {
+ $server = 'https://localhost/freebusy';
+ }
+ if (!empty($conf['fb']['redirect'])) {
+ $do_redirect = $conf['fb']['redirect'];
+ } else {
+ $do_redirect = false;
+ }
+
+ if ($trigger) {
+ $path = sprintf('/trigger/%s/%s.' . ($extended)?'pxfb':'pfb',
+ urlencode($this->owner), urlencode($this->imap_folder));
+ } else {
+ $path = sprintf('/%s.' . ($extended)?'xfb':'ifb', urlencode($this->owner));
+ }
+
+ /* Check if we are on the right server and redirect if appropriate */
+ if ($this->freebusyserver && $this->freebusyserver != $server) {
+ $redirect = $this->freebusyserver . $path;
+ Horde::logMessage(sprintf("URL %s indicates remote free/busy server since we only offer %s. Redirecting.",
+ $this->freebusyserver, $server), __FILE__,
+ __LINE__, PEAR_LOG_ERR);
+ if ($do_redirect) {
+ header("Location: $redirect");
+ } else {
+ header("X-Redirect-To: $redirect");
+ $redirect = 'https://' . urlencode($this->user) . ':' . urlencode(Horde_Auth::getCredential('password'))
+ . '@' . $this->freebusyserver . $path;
+ if (!@readfile($redirect)) {
+ $message = sprintf(_("Unable to read free/busy information from %s"),
+ 'https://' . urlencode($this->user) . ':XXX'
+ . '@' . $this->freebusyserver . $_SERVER['REQUEST_URI']);
+ return PEAR::raiseError($message);
+ }
+ }
+ exit;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * The Kolab implementation of the free/busy system.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package Kolab_FreeBusy
+ * @author Steffen Hansen <steffen@klaralvdalens-datakonsult.se>
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_FreeBusy
+ */
+
+/**
+ * The Horde_Kolab_FreeBusy class serves as Registry aka ServiceLocator for the
+ * Free/Busy application. It also provides the entry point into the the Horde
+ * MVC system and allows to dispatch a request.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you did not
+ * receive this file, see
+ * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ *
+ * @category Kolab
+ * @package Kolab_FreeBusy
+ * @author Steffen Hansen <steffen@klaralvdalens-datakonsult.se>
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_FreeBusy
+ * @since Horde 3.2
+ */
+class Horde_Kolab_FreeBusy_Driver_Freebusy_Kolab extends Horde_Kolab_FreeBusy_Driver_Freebusy_Base
+{
+ /**
+ * Fetch the free/busy data for a user.
+ *
+ * @params array $params Additional options.
+ * <pre>
+ * 'extended' - Whether to fetch extended free/busy information or not.
+ * </pre>
+ *
+ * @return array The free/busy data.
+ */
+ public function fetch($params = array())
+ {
+ $extended = !empty($params['extended']);
+
+ }
+
+ /**
+ * Parse the owner value.
+ *
+ * @param string $owner The owner that should be processed.
+ *
+ * @return boolean|PEAR_Error True if successful.
+ */
+ protected function handleCallee($callee)
+ {
+ $this->owner = $owner;
+
+ $result = $this->_process();
+ if (is_a($result, 'PEAR_Error')) {
+ return $result;
+ }
+ return true;
+ }
+
+ /**
+ * Parse the requested folder for the owner of that folder.
+ *
+ * @param string $req_folder The folder requested.
+ *
+ * @return boolean|PEAR_Error True if successful.
+ */
+ protected function handleCalleePart($callee_part)
+ {
+ /* Handle the owner/folder name and make sure the owner part is in lower case */
+ $req_folder = Horde_String::convertCharset($req_folder, 'UTF-8', 'UTF7-IMAP');
+ $folder = explode('/', $req_folder);
+ if (count($folder) < 2) {
+ return PEAR::raiseError(sprintf(_("No such folder %s"), $req_folder));
+ }
+
+ $folder[0] = strtolower($folder[0]);
+ $req_folder = implode('/', $folder);
+ $this->owner = $folder[0];
+ unset($folder[0]);
+ $this->folder = join('/', $folder);
+
+ $result = $this->_process();
+ if (is_a($result, 'PEAR_Error')) {
+ return $result;
+ }
+ return true;
+ }
+
+ /**
+ * Process both the user accessing the page as well as the
+ * owner of the requested free/busy information.
+ *
+ * @return boolean|PEAR_Error True if successful.
+ */
+ private function _process()
+ {
+ global $conf;
+
+ require_once 'Horde/Kolab/Server.php';
+
+ if (isset($conf['kolab']['ldap']['phpdn'])) {
+ $params = array(
+ 'uid' => $conf['kolab']['ldap']['phpdn'],
+ 'pass' => $conf['kolab']['ldap']['phppw'],
+ );
+ } else {
+ $params = array(
+ 'user' => Horde_Auth::getAuth(),
+ 'pass' => Horde_Auth::getCredential('password'),
+ );
+ }
+
+ /* Connect to the Kolab user database */
+ $db = &Horde_Kolab_Server::singleton($params);
+ // TODO: Remove once Kolab_Server has been fixed to always return the base dn
+ $db->fetch();
+
+ /* Retrieve the server configuration */
+ try {
+ $server = $db->fetch(sprintf('k=kolab,%s',
+ $db->getBaseUid()),
+ 'Horde_Kolab_Server_Object_Kolab_Server');
+ $this->server_object = $server;
+ } catch (Horde_Kolab_Server_Exception $e) {
+ Horde::logMessage(sprintf("Failed fetching the k=kolab configuration object. Error was: %s",
+ $e->getMessage()),
+ __FILE__, __LINE__, PEAR_LOG_ERR);
+ $this->server_object = null;
+ }
+
+ /* Fetch the user calling us */
+ $udn = $db->uidForIdOrMail($this->user);
+ if (is_a($udn, 'PEAR_Error')) {
+ return $udn;
+ }
+ if ($udn) {
+ $user = $db->fetch($udn, 'Horde_Kolab_Server_Object_Kolab_User');
+ if (is_a($user, 'PEAR_Error')) {
+ return $user;
+ }
+ $this->user_object = $user;
+ }
+
+ if ($this->user_object && $this->user_object->exists()) {
+ $mail = $this->user_object->get(Horde_Kolab_Server_Object_Kolab_User::ATTRIBUTE_MAIL);
+ if (is_a($mail, 'PEAR_Error')) {
+ return $mail;
+ }
+ if ($mail) {
+ $this->user = $mail;
+ }
+ }
+
+ /* Fetch the owner of the free/busy data */
+ $odn = $db->uidForIdOrMailOrAlias($this->owner);
+ if (is_a($odn, 'PEAR_Error')) {
+ return $odn;
+ }
+ if (!$odn) {
+ $idx = strpos($this->user, '@');
+ if($idx !== false) {
+ $domain = substr($this->user, $idx+1);
+ Horde::logMessage(sprintf("Trying to append %s to %s",
+ $domain, $this->owner),
+ __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ $odn = $odn = $db->uidForIdOrMail($this->owner . '@' . $domain);
+ }
+ }
+
+ if ($odn) {
+ $owner = $db->fetch($odn, 'Horde_Kolab_Server_Object_Kolab_User');
+ if (is_a($owner, 'PEAR_Error')) {
+ return $owner;
+ }
+ $this->owner_object = &$owner;
+ }
+
+ if (!empty($this->owner_object)) {
+ if ($this->owner_object->exists()) {
+ $this->owner = $this->owner_object->get(Horde_Kolab_Server_Object_Kolab_User::ATTRIBUTE_MAIL);
+
+ $freebusyserver = $this->owner_object->getServer('freebusy');
+ if (!is_a($freebusyserver, 'PEAR_Error')) {
+ $this->freebusyserver = $freebusyserver;
+ }
+ }
+ } else {
+ return PEAR::raiseError(_("Unable to determine owner of the free/busy data!"));
+ }
+
+ /* Mangle the folder request into an IMAP folder name */
+ $this->imap_folder = $this->_getImapFolder();
+
+ return true;
+ }
+
+ /**
+ * Calculate the correct IMAP folder name to access based on the
+ * combination of user and owner.
+ *
+ * @return string The IMAP folder we should access.
+ */
+ function _getImapFolder()
+ {
+ $userdom = false;
+ $ownerdom = false;
+ if (ereg( '(.*)@(.*)', $this->user, $regs)) {
+ // Regular user
+ $user = $regs[1];
+ $userdom = $regs[2];
+ } else {
+ $user = $this->user;
+ }
+
+ if(ereg( '(.*)@(.*)', $this->owner, $regs)) {
+ // Regular owner
+ $owner = $regs[1];
+ $ownerdom = $regs[2];
+ } else {
+ $owner = $this->owner;
+ }
+
+ $fldrcomp = array();
+ if ($user == $owner) {
+ $fldrcomp[] = 'INBOX';
+ } else {
+ $fldrcomp[] = 'user';
+ $fldrcomp[] = $owner;
+ }
+
+ if (!empty($this->folder)) {
+ $fldrcomp[] = $this->folder;
+ }
+
+ $folder = join('/', $fldrcomp);
+ if ($ownerdom && !$userdom) {
+ $folder .= '@' . $ownerdom;
+ }
+ return $folder;
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * The Kolab implementation of the free/busy system.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package Kolab_FreeBusy
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_FreeBusy
+ */
+
+/**
+ * Factory methods for objects required by the free/busy system.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you did not
+ * receive this file, see
+ * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ *
+ * @category Kolab
+ * @package Kolab_FreeBusy
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_FreeBusy
+ * @since Horde 3.2
+ */
+class Horde_Kolab_FreeBusy_Factory
+{
+
+ /**
+ * Create the object representing the current request.
+ *
+ * @param Horde_Provider $provider The instance providing required
+ * dependencies.
+ *
+ * @return Horde_Controller_Request_Base The current request.
+ *
+ * @throws Horde_Exception
+ */
+ static public function getRequest($provider)
+ {
+ $params = isset($provider->params['request']) ? $provider->params['request'] : array();
+ if (!empty($params['class'])) {
+ $request_class = $params['class'];
+ } else {
+ $request_class = 'Horde_Controller_Request_Http';
+ }
+
+ if (!empty($params['params'])) {
+ $request_params = $params['params'];
+ } else {
+ $request_params = array();
+ }
+
+ /** Set up our request and routing objects */
+ $request = new $request_class($request_params);
+
+ /** The HTTP request object would hide errors. Display them. */
+ if (isset($request->_exception)) {
+ throw $request->_exception;
+ }
+
+ return $request;
+ }
+
+ /**
+ * Create the mapper.
+ *
+ * @param Horde_Provider $provider The instance providing required
+ * dependencies.
+ *
+ * @return Horde_Route_Mapper The mapper.
+ *
+ * @throws Horde_Exception
+ */
+ static public function getMapper($provider)
+ {
+ $params = isset($provider->params['mapper']) ? $provider->params['mapper'] : array();
+ if (!empty($params['params'])) {
+ $mapper_params = $params['params'];
+ } else {
+ $mapper_params = array();
+ }
+ $mapper = new Horde_Routes_Mapper($mapper_params);
+
+ /**
+ * Application routes are relative only to the application. Let the
+ * mapper know where they start.
+ */
+ if (!empty($provider->params['script'])) {
+ $mapper->prefix = dirname($provider->params['script']);
+ } else {
+ $mapper->prefix = dirname($_SERVER['PHP_SELF']);
+ }
+
+ // Check for route definitions.
+ if (!empty($provider->params['config']['dir'])) {
+ $routeFile = $provider->params['config']['dir'] . '/routes.php';
+ }
+ if (empty($params['config']['dir'])
+ || !file_exists($routeFile)) {
+ $mapper->connect(':(callee).:(type)',
+ array('controller' => 'freebusy',
+ 'action' => 'fetch',
+ 'requirements' => array('type' => '(i|x|v)fb',
+ 'callee' => '[^/]+'),
+ ));
+
+ $mapper->connect('trigger/*(folder).pfb',
+ array('controller' => 'freebusy',
+ 'action' => 'trigger'
+ ));
+
+ $mapper->connect('*(folder).:(type)',
+ array('controller' => 'freebusy',
+ 'action' => 'trigger',
+ 'requirements' => array('type' => '(p|px)fb'),
+ ));
+
+ $mapper->connect('delete/:(callee)',
+ array('controller' => 'freebusy',
+ 'action' => 'delete',
+ 'requirements' => array('callee' => '[^/]+'),
+ ));
+
+ $mapper->connect('regenerate',
+ array('controller' => 'freebusy',
+ 'action' => 'regenerate',
+ ));
+ } else {
+ // Load application routes.
+ include $routeFile;
+ }
+ return $mapper;
+ }
+
+ /**
+ * Create the dispatcher.
+ *
+ * @param Horde_Provider $provider The instance providing required
+ * dependencies.
+ *
+ * @return Horde_Controller_Dispatcher The dispatcher.
+ */
+ static public function getDispatcher($provider)
+ {
+ $params = isset($provider->params['dispatch']) ? $provider->params['dispatch'] : array();
+ if (empty($params['controllerDir'])) {
+ $controllerDir = dirname(__FILE__) . '/Controller';
+ } else {
+ $controllerDir = $params['controllerDir'];
+ }
+
+ if (empty($params['viewsDir'])) {
+ $viewsDir = dirname(__FILE__) . '/View';
+ } else {
+ $viewsDir = $params['viewsDir'];
+ }
+
+ $context = array(
+ 'mapper' => $provider->mapper,
+ 'controllerDir' => $controllerDir,
+ 'viewsDir' => $viewsDir,
+ 'logger' => $provider->logger,
+ );
+
+ $dispatcher = Horde_Controller_Dispatcher::singleton($context);
+
+ return $dispatcher;
+ }
+
+ /**
+ * Return the logger.
+ *
+ * @param Horde_Provider $provider The instance providing required
+ * dependencies.
+ *
+ * @return Horde_Log_Logger The logger.
+ */
+ static public function getLogger($provider)
+ {
+ $logger = new Horde_Log_Logger();
+
+ $logger_params = isset($provider->params['logger']) ? $provider->params['logger'] : array();
+
+ if (empty($params)) {
+ $handlers = array('Horde_Log_Handler_Syslog' => array());
+ } else {
+ $handlers = $logger_params['logger'];
+ }
+
+ foreach ($handlers as $name => $params) {
+ if (!empty($params['params'])) {
+ /**
+ * We need to pass parameters to the constructor so use
+ * reflection.
+ */
+ $reflectionObj = new ReflectionClass($name);
+ $handler = $reflectionObj->newInstanceArgs($params['params']);
+ } else {
+ $handler = new $name();
+ }
+
+ if (!empty($params['options'])) {
+ foreach ($params['options'] as $key => $value) {
+ $handler->setOption($key, $value);
+ }
+ }
+
+ $logger->addHandler($handler);
+ }
+ return $logger;
+ }
+}
\ No newline at end of file
<dir name="Controller">
<file name="FreebusyController.php" role="php" />
</dir> <!-- /lib/Horde/Kolab/FreeBusy/Controller -->
+ <dir name="Driver">
+ <file name="Base.php" role="php" />
+ <dir name="Freebusy">
+ <file name="Base.php" role="php" />
+ <file name="Kolab.php" role="php" />
+ </dir> <!-- /lib/Horde/Kolab/FreeBusy/Driver/Freebusy -->
+ </dir> <!-- /lib/Horde/Kolab/FreeBusy/Driver -->
+ <file name="Factory.php" role="php" />
<file name="Imap.php" role="php" />
<file name="Report.php" role="php" />
<file name="View.php" role="php" />
<install name="lib/Horde/Kolab/FreeBusy/Access.php" as="Horde/Kolab/FreeBusy/Access.php" />
<install name="lib/Horde/Kolab/FreeBusy/Cache.php" as="Horde/Kolab/FreeBusy/Cache.php" />
<install name="lib/Horde/Kolab/FreeBusy/Controller/FreebusyController.php" as="Horde/Kolab/FreeBusy/Controller/FreebusyController.php" />
+ <install name="lib/Horde/Kolab/FreeBusy/Driver/Base.php" as="Horde/Kolab/FreeBusy/Driver/Base.php" />
+ <install name="lib/Horde/Kolab/FreeBusy/Driver/Freebusy/Base.php" as="Horde/Kolab/FreeBusy/Driver/Freebusy/Base.php" />
+ <install name="lib/Horde/Kolab/FreeBusy/Driver/Freebusy/Kolab.php" as="Horde/Kolab/FreeBusy/Driver/Freebusy/Kolab.php" />
+ <install name="lib/Horde/Kolab/FreeBusy/Factory.php" as="Horde/Kolab/FreeBusy/Factory.php" />
<install name="lib/Horde/Kolab/FreeBusy/Imap.php" as="Horde/Kolab/FreeBusy/Imap.php" />
<install name="lib/Horde/Kolab/FreeBusy/Report.php" as="Horde/Kolab/FreeBusy/Report.php" />
<install name="lib/Horde/Kolab/FreeBusy/View.php" as="Horde/Kolab/FreeBusy/View.php" />
/**
* Test setup.
+ *
+ * @return NULL
*/
public function setUp()
{
/**
* Test destruction.
+ *
+ * @return NULL
*/
public function tearDown()
{
),
'dispatch' => array(
'controllerDir' => dirname(__FILE__) . '/Mock/Controller',
+ ),
+ 'logger' => array(
+ 'Horde_Log_Handler_Null' => array(),
)
);
+
$application = Horde_Kolab_FreeBusy::singleton($params);
$output = '';
/**
* Test setup.
+ *
+ * @return NULL
*/
public function setUp()
{
*/
public function fetch()
{
- $this->renderText('fetched "' . $this->params->type . '" data for user "' . $this->params->mail . '"');
+ $this->renderText('fetched "' . $this->params->type . '" data for user "' . $this->params->callee . '"');
}
/**
*/
public function delete()
{
- $this->renderText('deleted data for user "' . $this->params->mail . '"');
+ $this->renderText('deleted data for user "' . $this->params->callee . '"');
}
}
\ No newline at end of file
--- /dev/null
+<?php
+/**
+ * Test triggering free/busy generation.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package Kolab_FreeBusy
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_FreeBusy
+ */
+
+/**
+ * The Autoloader allows us to omit "require/include" statements.
+ */
+require_once 'Horde/Autoloader.php';
+
+/**
+ * Test triggering the generation/caching of free/busy data.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Kolab
+ * @package Kolab_FreeBusy
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_FreeBusy
+ */
+class Horde_Kolab_FreeBusy_TriggerTest extends Horde_Kolab_Test_FreeBusy
+{
+
+ /**
+ * Test setup.
+ *
+ * @return NULL
+ */
+ public function setUp()
+ {
+ /**
+ * The controller automatically starts a session. But we don't want to
+ * send out cookie headers since we are running in PHPUnit.
+ */
+ ini_set('session.use_cookies', 0);
+ ini_set('session.use_only_cookies', 0);
+ session_cache_limiter(null);
+ }
+
+ /**
+ * Test destruction.
+ *
+ * @return NULL
+ */
+ public function tearDown()
+ {
+ Horde_Kolab_FreeBusy::destroy();
+ }
+
+ /**
+ * Test triggering a folder.
+ *
+ * @return NULL
+ */
+ public function testTriggering()
+ {
+ $params = array(
+ 'script' => '/freebusy/freebusy.php',
+ 'request' => array(
+ 'params' => array(
+ 'server' => array(
+ 'REQUEST_URI' => '/freebusy/test@example.com/Kalender.pxfb'
+ )
+ )
+ ),
+ 'logger' => array(
+ 'Horde_Log_Handler_Null' => array(),
+ )
+ );
+
+ $application = Horde_Kolab_FreeBusy::singleton($params);
+
+ $output = '';
+
+ if (empty($result)) {
+ try {
+ ob_start();
+ $application->dispatch();
+ $output = ob_get_contents();
+ ob_end_clean();
+ } catch (Horde_Controller_Exception $e) {
+ $this->assertEquals('No routes match the path: "' . trim($key, '/') . '"', $e->getMessage());
+ }
+ $this->assertEquals('', $output);
+ } else {
+ ob_start();
+ $application->dispatch();
+ $output = ob_get_contents();
+ ob_end_clean();
+ $this->assertEquals($result, $output);
+ }
+ Horde_Kolab_FreeBusy::destroy();
+ }
+}
\ No newline at end of file