Page MenuHomePhorge

D2954.1775188122.diff
No OneTemporary

Authored By
Unknown
Size
26 KB
Referenced Files
None
Subscribers
None

D2954.1775188122.diff

diff --git a/composer.json b/composer.json
--- a/composer.json
+++ b/composer.json
@@ -2,12 +2,7 @@
"name": "kolab/free-busy",
"description": "Kolab Free/Busy Service",
"license": "AGPL-3.0",
- "version": "1.1.0",
"repositories": [
- {
- "type": "pear",
- "url": "http://pear.php.net/"
- },
{
"type": "vcs",
"url": "https://git.kolab.org/diffusion/PNL/php-net_ldap.git"
@@ -15,13 +10,13 @@
],
"require": {
"php": ">=5.3.3",
- "monolog/monolog": "1.2.*",
- "desarrolla2/cache": "dev-master",
- "sabre/vobject": "~3.3.3"
+ "monolog/monolog": "~1.2",
+ "sabre/vobject": "~3.3.3",
+ "garethp/php-ews": "~0.10.1"
},
"require-dev": {
- "pear-pear.php.net/net_ldap2": ">=2.0.12",
- "kolab/Net_LDAP3": "dev-master"
+ "pear/net_ldap2": "~2.2.0",
+ "kolab/net_ldap3": "~1.1.3"
},
- "minimum-stability": "dev"
+ "minimum-stability": "stable"
}
diff --git a/composer.json-dist b/composer.json-dist
--- a/composer.json-dist
+++ b/composer.json-dist
@@ -2,7 +2,6 @@
"name": "kolab/free-busy",
"description": "Kolab Free/Busy Service",
"license": "AGPL-3.0",
- "version": "1.1.0",
"autoload": {
"psr-0": {
"": "/usr/share/pear/"
diff --git a/lib/Kolab/Config.php b/lib/Kolab/Config.php
--- a/lib/Kolab/Config.php
+++ b/lib/Kolab/Config.php
@@ -175,7 +175,9 @@
}
else if (is_array($config)) {
$pkey = rtrim($prefix, '.');
- $this->data[$pkey] = is_array($this->data[$pkey]) ? array_replace_recursive((array)$this->data[$pkey], $config) : $config;
+ $this->data[$pkey] = isset($this->data[$pkey]) && is_array($this->data[$pkey])
+ ? array_replace_recursive((array)$this->data[$pkey], $config)
+ : $config;
}
foreach ((array)$config as $key => $val) {
@@ -216,7 +218,7 @@
*/
public function __get($name)
{
- return $this->data[$name];
+ return isset($this->data[$name]) ? $this->data[$name] : null;
}
/**
diff --git a/lib/Kolab/FreeBusy/Directory.php b/lib/Kolab/FreeBusy/Directory.php
--- a/lib/Kolab/FreeBusy/Directory.php
+++ b/lib/Kolab/FreeBusy/Directory.php
@@ -30,91 +30,108 @@
*/
abstract class Directory
{
- protected $config;
-
- /**
- * Factory method creating an instace of Directory according to config
- *
- * @param array Hash array with config
- */
- public static function factory($config)
- {
- switch (strtolower($config['type'])) {
- case 'ldap':
- return new DirectoryLDAP($config);
-
- case 'static':
- case 'external':
- return new DirectoryStatic($config);
-
- default:
- Logger::get('directory')->addError("Invalid directory type '" . $config['type'] . "'!");
- }
-
- return null;
- }
-
- /**
- * Resolve the given username to a Entity object
- *
- * @param string Username/Email to resolve
- * @return object Entity if found, otherwise False
- */
- abstract public function resolve($user);
-
- /**
- * Retrieve free/busy data for the given user.
- *
- * @param string Username or email to resolve
- * @param boolean Get extemded free-busy if possible
- * @return string VCalendar container if found, False otherwise
- */
- public function getFreeBusyData($user, $extended = false)
- {
- // resolve user record first
- if ($user = $this->resolve($user)) {
- $fbsource = $this->config['fbsource'];
- if ($source = Source::Factory($fbsource, $this->config)) {
- // forward request to Source instance
- if ($data = $source->getFreeBusyData($this->postprocessAttrib($user), $extended)) {
- // send data through the according format converter
- $converter = Format::factory($this->config['format']);
- $data = $converter->toVCalendar($data);
-
- // cache the generated data
- if ($data && $this->config['cacheto'] && !$source->isCached()) {
- $path = preg_replace_callback(
- '/%\{?([a-z0-9]+)\}?/',
- function($m) use ($user) { return $user[$m[1]]; },
- $this->config['cacheto']
- );
-
- if (!@file_put_contents($path, $data, LOCK_EX)) {
- Logger::get('directory')->addError("Failed to write to cache file '" . $path . "'!");
- }
- }
- }
-
- return $data;
- }
- }
-
- return false;
- }
-
- /**
- * Modify attribute values according to config
- */
- protected function postprocessAttrib($attrib)
- {
- if (!empty($this->config['lc_attributes'])) {
- foreach (Config::convert($this->config['lc_attributes'], Config::ARR) as $key) {
- if (!empty($attrib[$key]))
- $attrib[$key] = strtolower($attrib[$key]);
- }
- }
-
- return $attrib;
- }
-
-}
\ No newline at end of file
+ protected $config;
+
+ /**
+ * Factory method creating an instace of Directory according to config
+ *
+ * @param array Hash array with config
+ */
+ public static function factory($config)
+ {
+ switch (strtolower($config['type'])) {
+ case 'ldap':
+ return new DirectoryLDAP($config);
+
+ case 'static':
+ case 'external':
+ return new DirectoryStatic($config);
+
+ default:
+ Logger::get('directory')->addError("Invalid directory type '" . $config['type'] . "'!");
+ }
+
+ return null;
+ }
+
+ /**
+ * Resolve the given username to a Entity object
+ *
+ * @param string Username/Email to resolve
+ * @return object Entity if found, otherwise False
+ */
+ abstract public function resolve($user);
+
+ /**
+ * Retrieve free/busy data for the given user.
+ *
+ * @param string Username or email to resolve
+ * @param boolean Get extemded free-busy if possible
+ * @return string VCalendar container if found, False otherwise
+ */
+ public function getFreeBusyData($user, $extended = false)
+ {
+ $logger = Logger::get('directory');
+
+ // resolve user record first
+ if ($user = $this->resolve($user)) {
+ $fbsource = $this->config['fbsource'];
+ if ($source = Source::Factory($fbsource, $this->config)) {
+ $user = $this->postprocessAttrib($user);
+
+ // Find the cached data
+ if (!empty($this->config['cacheto'])) {
+ $path = preg_replace_callback(
+ '/%\{?([a-z0-9]+)\}?/',
+ function($m) use ($user) { return $user[$m[1]]; },
+ $this->config['cacheto']
+ );
+
+ // check for cached data
+ if (file_exists($path)) {
+ if (empty($this->config['expires']) || filemtime($path) + Utils::getOffsetSec($this->config['expires']) >= time()) {
+ $logger->addInfo("Deliver cached data from {$path}");
+ return file_get_contents($path);
+ }
+ }
+ }
+
+ // forward request to Source instance
+ if ($data = $source->getFreeBusyData($user, $extended)) {
+ // send data through the according format converter
+ $converter = Format::factory($this->config['format']);
+ $data = $converter->toVCalendar($data);
+
+ // cache the generated data
+ if ($data && !empty($path)) {
+ if (!file_put_contents($path, $data, LOCK_EX)) {
+ $logger->addError("Failed to write to cache in {$path}");
+ } else {
+ $logger->addInfo("Cached data in {$path}");
+ }
+ }
+ }
+
+ return $data;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Modify attribute values according to config
+ */
+ protected function postprocessAttrib($attrib)
+ {
+ if (!empty($this->config['lc_attributes'])) {
+ foreach (Config::convert($this->config['lc_attributes'], Config::ARR) as $key) {
+ if (!empty($attrib[$key])) {
+ $attrib[$key] = strtolower($attrib[$key]);
+ }
+ }
+ }
+
+ return $attrib;
+ }
+}
diff --git a/lib/Kolab/FreeBusy/DirectoryStatic.php b/lib/Kolab/FreeBusy/DirectoryStatic.php
--- a/lib/Kolab/FreeBusy/DirectoryStatic.php
+++ b/lib/Kolab/FreeBusy/DirectoryStatic.php
@@ -31,29 +31,28 @@
*/
class DirectoryStatic extends Directory
{
- /**
- * Default constructor loading directory configuration
- */
- public function __construct($config)
- {
- $this->config = $config;
- }
-
- /**
- * @see Directory::resolve()
- */
- public function resolve($user)
- {
- $result = array('s' => $user);
-
- // check if user matches the filter property (if configured)
- if (!empty($this->config['filter'])) {
- if (!preg_match('!'.$this->config['filter'].'!i', $user))
- $result = false;
- }
-
- return $result;
- }
-
+ /**
+ * Default constructor loading directory configuration
+ */
+ public function __construct($config)
+ {
+ $this->config = $config;
+ }
+
+ /**
+ * @see Directory::resolve()
+ */
+ public function resolve($user)
+ {
+ $result = array('s' => $user);
+
+ // check if user matches the filter property (if configured)
+ if (!empty($this->config['filter'])) {
+ if (!preg_match('!'.$this->config['filter'].'!i', $user)) {
+ $result = false;
+ }
+ }
+
+ return $result;
+ }
}
-
diff --git a/lib/Kolab/FreeBusy/Source.php b/lib/Kolab/FreeBusy/Source.php
--- a/lib/Kolab/FreeBusy/Source.php
+++ b/lib/Kolab/FreeBusy/Source.php
@@ -29,7 +29,6 @@
abstract class Source
{
protected $config = array();
- protected $cached = false;
/**
* Factory method creating an instace of Source according to config
@@ -51,6 +50,7 @@
case 'fbd':
case 'fbdaemon': return new SourceFBDaemon($config + $conf);
case 'aggregate': return new SourceAggregator($config + $conf);
+ case 'ews': return new SourceEWS($config + $conf);
}
Logger::get('source')->addError("Invalid source configuration: " . $url);
@@ -68,7 +68,7 @@
/**
* Retrieve free/busy data for the given user
*
- * @param array Hash array with user attributes
+ * @param false|string vCalendar (ICS) file output, or False on error
*/
abstract public function getFreeBusyData($user, $extended);
@@ -81,7 +81,7 @@
foreach ($this->config as $k => $val) {
if (is_string($val) && strpos($val, '%') !== false) {
$val = preg_replace_callback(
- '/%\{?([a-z0-9]+)\}?/',
+ '/%\{?([a-z]{1}[a-z0-9]*)\}?/',
function($m) use ($k, $user) {
$enc = $k == 'url' || $k == 'query' || $k == 'fbsource';
return $enc ? urlencode($user[$m[1]]) : $user[$m[1]];
@@ -94,30 +94,4 @@
return $config;
}
-
- /**
- * Helper method to check if a cached file exists and is still valid
- *
- * @param array Hash array with (replaced) config properties
- * @return string Cached free-busy data or false if cache file doesn't exist or is expired
- */
- protected function getCached($config)
- {
- if ($config['cacheto'] && file_exists($config['cacheto'])) {
- if (empty($config['expires']) || filemtime($config['cacheto']) + Utils::getOffsetSec($config['expires']) >= time()) {
- $this->cached = true;
- return file_get_contents($config['cacheto']);
- }
- }
-
- return false;
- }
-
- /**
- * Return the value of the 'cached' flag
- */
- public function isCached()
- {
- return $this->cached;
- }
}
diff --git a/lib/Kolab/FreeBusy/SourceAggregator.php b/lib/Kolab/FreeBusy/SourceAggregator.php
--- a/lib/Kolab/FreeBusy/SourceAggregator.php
+++ b/lib/Kolab/FreeBusy/SourceAggregator.php
@@ -40,7 +40,7 @@
public function getFreeBusyData($user, $extended)
{
$log = Logger::get('aggregate', intval($this->config['loglevel']));
- # $config = $this->getUserConfig($user);
+ // $config = $this->getUserConfig($user);
$attr = str_replace('%', '', strval($this->config['path'] ?: $this->config['host']));
if (!empty($user[$attr])) {
diff --git a/lib/Kolab/FreeBusy/SourceEWS.php b/lib/Kolab/FreeBusy/SourceEWS.php
new file mode 100644
--- /dev/null
+++ b/lib/Kolab/FreeBusy/SourceEWS.php
@@ -0,0 +1,202 @@
+<?php
+
+/**
+ * This file is part of the Kolab Server Free/Busy Service
+ *
+ * @author Aleksander Machniak <machniak@kolabsys.com>
+ *
+ * Copyright (C) 2013-2021, Apheleia IT AG <contact@apheleia.ch>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace Kolab\FreeBusy;
+
+use garethp\ews\API;
+use garethp\ews\API\Exception;
+
+/**
+ * Implementation of a Free/Busy data source reading from an EWS server
+ */
+class SourceEWS extends Source
+{
+ /**
+ * @see Source::getFreeBusyData()
+ */
+ public function getFreeBusyData($user, $extended)
+ {
+ $config = $this->getUserConfig($user);
+ $user = is_array($user) ? $user['s'] : $user;
+
+ // Get start and end date for the request
+ list($start, $end) = $this->getPeriod();
+
+ // Fetch the availability info from the EWS server
+ $data = $this->fetchData($user, $start, $end, $config);
+
+ if ($data === false) {
+ return false;
+ }
+
+ // Process the data (convert to ics)
+ foreach ($data as $idx => $event) {
+ // Map the busy-type property
+ switch ($event->getBusyType()) {
+ case 'Free':
+ $fbtype = 'FREE';
+ break;
+
+ case 'Tentative':
+ $fbtype = 'BUSY-TENTATIVE';
+ break;
+
+ case 'Busy':
+ // case 'OOF':
+ // case 'NoData':
+ default:
+ $fbtype = 'BUSY';
+ break;
+ }
+
+ $startTime = new \DateTime($event->getStartTime(), new \DateTimeZone('UTC'));
+ $endTime = new \DateTime($event->getEndTime(), new \DateTimeZone('UTC'));
+
+ $data[$idx] = sprintf(
+ "FREEBUSY;FBTYPE=%s:%s/%s",
+ $fbtype,
+ $startTime->format('Ymd\THis\Z'),
+ $endTime->format('Ymd\THis\Z'),
+ );
+ }
+
+ return sprintf(
+ "BEGIN:VCALENDAR\n"
+ . "PRODID:%s\n"
+ . "VERSION:2.0\n"
+ . "METHOD:PUBLISH\n"
+ . "BEGIN:VFREEBUSY\n"
+ . "ORGANIZER:mailto:%s\n"
+ . "UID:%s\n"
+ . "DTSTAMP:%s\n"
+ . "DTSTART:%s\n"
+ . "DTEND:%s\n"
+ . "%s\n"
+ . "END:VFREEBUSY\n"
+ . "END:VCALENDAR\n",
+ Utils::PRODID,
+ $user,
+ \date('YmdHi') . '-' . \substr(\md5($user), 0, 16),
+ $start->format('Ymd\THis\Z'),
+ $start->format('Ymd\THis\Z'),
+ $end->format('Ymd\THis\Z'),
+ implode("\n", $data)
+ );
+ }
+
+ /**
+ * Fetches the user availability data from the EWS server
+ */
+ private function fetchData($user, $startdate, $enddate, $config)
+ {
+ $logger = Logger::get('ews');
+
+ $logger->addDebug(sprintf("Fetching data from %s for %s...", $config['host'], $user));
+
+ try {
+ // Create and build the client
+ $api = API::withUsernameAndPassword(
+ $config['host'],
+ urldecode($config['user']),
+ urldecode($config['pass']),
+ array(
+ // return date-time in UTC
+ 'timezone' => 'UTC',
+ // act as the requested user
+ 'impersonation' => $user
+ )
+ );
+
+ $calendar = $api->getCalendar();
+
+ // This is using the EWS's GetUserAvailability API
+ $options = array();
+/*
+ $options = array(
+ 'FreeBusyViewOptions' => array(
+ 'MergedFreeBusyIntervalInMinutes' => 15 // default: 30
+ )
+ );
+*/
+ $availability = $calendar->getAvailabilityFor($startdate, $enddate, array($user), $options);
+
+ // Check response status
+ $responseMessage = $availability->getFreeBusyResponseArray()->FreeBusyResponse->getResponseMessage();
+ if ($responseMessage->getResponseClass() === 'Error') {
+ throw new Exception\ExchangeException($responseMessage);
+ }
+
+ $items = $availability->getFreeBusyResponseArray()->FreeBusyResponse->getFreeBusyView()->getCalendarEventArray();
+
+ if ($items && $items->CalendarEvent) {
+ $logger->addDebug(sprintf("Found %d events", count($items->CalendarEvent)));
+ return $items->CalendarEvent;
+ }
+
+ $logger->addDebug("Found 0 events");
+ return array();
+ } catch (Exception\UnauthorizedException $e) {
+ $logger->addError("EWS access unauthorized");
+ } catch (Exception\ServiceUnavailableException $e) {
+ $logger->addError("EWS service unavailable");
+ } catch (Exception\NoResponseReturnedException $e) {
+ $logger->addError("EWS no response");
+ } catch (Exception\AutodiscoverFailed $e) {
+ $logger->addError("EWS autodiscovery failed");
+ } catch (\Exception $e) {
+ $logger->addError($e->getMessage() ?: "EWS unknown error");
+ }
+
+ return false;
+ }
+
+ /**
+ * Get request period start and end
+ */
+ private function getPeriod()
+ {
+ // use date from HTTP query
+ if (!empty($_GET['dtstart']) &&
+ ($dtstart = \filter_input(INPUT_GET, 'dtstart', FILTER_SANITIZE_STRING))
+ ) {
+ try {
+ $start = new \DateTime($dtstart, new \DateTimezone('UTC'));
+ } catch (Exception $e) {
+ // ignore
+ }
+ }
+
+ if (empty($start)) {
+ $start = new \DateTime('now', new \DateTimeZone('UTC'));
+ }
+
+ // Set the period to 7 days in the past and 42-7 days in the future
+ // Note: 42 days is max. supported period on EWS
+
+ $start->sub(new \DateInterval('P7D'));
+ $end = clone $start;
+ $end->add(new \DateInterval('P42D'));
+
+ return array($start, $end);
+ }
+}
diff --git a/lib/Kolab/FreeBusy/SourceFBDaemon.php b/lib/Kolab/FreeBusy/SourceFBDaemon.php
--- a/lib/Kolab/FreeBusy/SourceFBDaemon.php
+++ b/lib/Kolab/FreeBusy/SourceFBDaemon.php
@@ -42,23 +42,6 @@
// log this...
$log->addInfo("Fetching data for ", $config);
- // caching is enabled
- if (!empty($config['cacheto'])) {
- // check for cached data
- if ($cached = $this->getCached($config)) {
- $log->addInfo("Deliver cached data from " . $config['cacheto']);
- return $cached;
- }
- // touch cache file to avoid multiple requests generating the same data
- if (file_exists($config['cacheto'])) {
- touch($config['cacheto']);
- }
- else {
- file_put_contents($config['cacheto'], Utils::dummyVFreebusy($user['mail']));
- $tempfile = $config['cacheto'];
- }
- }
-
// compose command for freebusyd
if (!empty($config['folder'])) {
$cmd = 'FOLDER';
@@ -128,10 +111,6 @@
}
return $fbdata;
}
- // remove (temporary) cache file again
- else if ($tempfile) {
- unlink($tempfile);
- }
// not found
return false;
diff --git a/lib/Kolab/FreeBusy/SourceIMAP.php b/lib/Kolab/FreeBusy/SourceIMAP.php
--- a/lib/Kolab/FreeBusy/SourceIMAP.php
+++ b/lib/Kolab/FreeBusy/SourceIMAP.php
@@ -79,23 +79,6 @@
// log this...
$log->addInfo("Fetching data for ", $config);
- // caching is enabled
- if (!empty($config['cacheto'])) {
- // check for cached data
- if ($cached = $this->getCached($config)) {
- $log->addInfo("Deliver cached data from " . $config['cacheto']);
- return $cached;
- }
- // touch cache file to avoid multiple requests generating the same data
- if (file_exists($config['cacheto'])) {
- touch($config['cacheto']);
- }
- 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) {
@@ -258,10 +241,6 @@
// serialize to VCALENDAR format
return $freebusy->serialize();
}
- // remove (temporary) cache file again
- else if ($tempfile) {
- unlink($tempfile);
- }
return false;
}
diff --git a/lib/Kolab/FreeBusy/Utils.php b/lib/Kolab/FreeBusy/Utils.php
--- a/lib/Kolab/FreeBusy/Utils.php
+++ b/lib/Kolab/FreeBusy/Utils.php
@@ -249,7 +249,7 @@
}
}
- // Should probably be a setting. For now, do 8 weeks in the past
+ // Should probably be a setting. For now, do 16 weeks into the future
return new \DateTime('now + 16 weeks 00:00:00', new \DateTimezone('UTC'));
}
diff --git a/public_html/index.php b/public_html/index.php
--- a/public_html/index.php
+++ b/public_html/index.php
@@ -50,79 +50,77 @@
// load config
$config = Config::get_instance(KOLAB_FREEBUSY_ROOT . '/config');
if ($config->valid()) {
- // check for trusted IP first
- $remote_ip = Utils::remoteIP();
- $trusted_ip = $config->trustednetworks ? Utils::checkIPRange($remote_ip, $config->get('trustednetworks.allow', array(), Config::ARR)) : false;
-
- $log = Logger::get('web');
-
- $uri = $_SERVER['REDIRECT_URL'];
-
- // we're not always redirected here
- if (empty($uri)) {
- $uri = $_SERVER['REQUEST_URI'];
- $log->addDebug('Request (direct): ' . $uri, array('ip' => $remote_ip, 'trusted' => $trusted_ip));
- } else {
- $log->addDebug('Request (redirect): ' . $uri, array('ip' => $remote_ip, 'trusted' => $trusted_ip));
- }
-
- list($uri, $args) = explode('?', $uri);
-
- // check HTTP authentication
- if (!$trusted_ip && $config->httpauth) {
- $_SERVER['FREEBUSY_URI'] = urldecode(rtrim($uri, '/'));
-
- if (!HTTPAuth::check($config->httpauth)) {
- $log->addDebug("Abort with 401 Unauthorized");
- header('WWW-Authenticate: Basic realm="Kolab Free/Busy Service"');
- header($_SERVER['SERVER_PROTOCOL'] . " 401 Unauthorized", true);
- exit;
- }
- }
-
- #header('Content-type: text/calendar; charset=utf-8', true);
- header('Content-type: text/plain; charset=utf-8', true);
-
- // analyse request
- $user = $_SERVER['FREEBUSY_USER'];
- $extended = !empty($_SERVER['FREEBUSY_EXTENDED']);
-
- if (!$user) {
- $url = array_filter(explode('/', $uri));
- $user = strtolower(array_pop($url));
-
- // remove file extension
- if (preg_match('/^(.+)\.([ipx]fb)$/i', $user, $m)) {
- $user = urldecode($m[1]);
- $extended = $m[2] == 'xfb';
- }
- }
-
- // iterate over directories
- foreach ($config->directory as $key => $dirconfig) {
- $log->addDebug("Trying directory $key", $dirconfig);
-
- $directory = Directory::factory($dirconfig);
- if ($directory && ($fbdata = $directory->getFreeBusyData($user, $extended))) {
- $log->addInfo("Found valid data for user $user in directory $key");
- echo $fbdata;
- exit;
- }
- }
-
- // return 404 if request was sent from a trusted IP
- if ($trusted_ip) {
- $log->addDebug("Returning '404 Not Found' for user $user");
- header($_SERVER['SERVER_PROTOCOL'] . " 404 Not found", true);
- }
- else {
- $log->addInfo("Returning empty Free/Busy list for user $user");
-
- // Return an apparent empty Free/Busy list.
- print Utils::dummyVFreebusy($user);
- }
+ // check for trusted IP first
+ $remote_ip = Utils::remoteIP();
+ $trusted_ip = $config->trustednetworks ? Utils::checkIPRange($remote_ip, $config->get('trustednetworks.allow', array(), Config::ARR)) : false;
+
+ $log = Logger::get('web');
+
+ $uri = isset($_SERVER['REDIRECT_URL']) ? $_SERVER['REDIRECT_URL'] : '';
+
+ // we're not always redirected here
+ if (empty($uri)) {
+ $uri = $_SERVER['REQUEST_URI'];
+ $log->addDebug('Request (direct): ' . $uri, array('ip' => $remote_ip, 'trusted' => $trusted_ip));
+ } else {
+ $log->addDebug('Request (redirect): ' . $uri, array('ip' => $remote_ip, 'trusted' => $trusted_ip));
+ }
+
+ list($uri, ) = explode('?', $uri);
+
+ // check HTTP authentication
+ if (!$trusted_ip && $config->httpauth) {
+ $_SERVER['FREEBUSY_URI'] = urldecode(rtrim($uri, '/'));
+
+ if (!HTTPAuth::check($config->httpauth)) {
+ $log->addDebug("Abort with 401 Unauthorized");
+ header('WWW-Authenticate: Basic realm="Kolab Free/Busy Service"');
+ header($_SERVER['SERVER_PROTOCOL'] . " 401 Unauthorized", true);
+ exit;
+ }
+ }
+
+ //header('Content-type: text/calendar; charset=utf-8', true);
+ header('Content-type: text/plain; charset=utf-8', true);
+
+ // analyse request
+ $user = isset($_SERVER['FREEBUSY_USER']) ? $_SERVER['FREEBUSY_USER'] : null;
+ $extended = !empty($_SERVER['FREEBUSY_EXTENDED']);
+
+ if (!$user) {
+ $url = array_filter(explode('/', $uri));
+ $user = strtolower(array_pop($url));
+
+ // remove file extension
+ if (preg_match('/^(.+)\.([ipx]fb)$/i', $user, $m)) {
+ $user = urldecode($m[1]);
+ $extended = $m[2] == 'xfb';
+ }
+ }
+
+ // iterate over directories
+ foreach ($config->directory as $key => $dirconfig) {
+ $log->addDebug("Trying directory $key", $dirconfig);
+
+ $directory = Directory::factory($dirconfig);
+ if ($directory && ($fbdata = $directory->getFreeBusyData($user, $extended))) {
+ $log->addInfo("Found valid data for user $user in directory $key");
+ echo $fbdata;
+ exit;
+ }
+ }
+
+ // return 404 if request was sent from a trusted IP
+ if ($trusted_ip) {
+ $log->addDebug("Returning '404 Not Found' for user $user");
+ header($_SERVER['SERVER_PROTOCOL'] . " 404 Not found", true);
+ } else {
+ $log->addInfo("Returning empty Free/Busy list for user $user");
+
+ // Return an apparent empty Free/Busy list.
+ print Utils::dummyVFreebusy($user);
+ }
}
// exit with error
# header($_SERVER['SERVER_PROTOCOL'] . " 500 Internal Server Error", true);
-

File Metadata

Mime Type
text/plain
Expires
Fri, Apr 3, 3:48 AM (10 h, 27 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18822477
Default Alt Text
D2954.1775188122.diff (26 KB)

Event Timeline