Page MenuHomePhorge

No OneTemporary

Size
28 KB
Referenced Files
None
Subscribers
None
diff --git a/composer.json b/composer.json
index 910564b..74048b4 100644
--- a/composer.json
+++ b/composer.json
@@ -1,27 +1,27 @@
{
"name": "kolab/free-busy",
"description": "Kolab Free/Busy Service",
"license": "AGPL-3.0",
- "version": "0.1.1",
+ "version": "0.1.2",
"repositories": [
{
"type": "pear",
"url": "http://pear.php.net/"
},
{
"type": "vcs",
"url": "git://git.kolab.org/git/pear/Net_LDAP3"
}
],
"autoload": {
"psr-0": { "": "lib/" }
},
"require": {
"php": ">=5.3.3",
"monolog/monolog": "1.2.*",
"kolab/Net_LDAP3": "dev-master",
"desarrolla2/cache": "dev-master",
"sabre/vobject" : "2.0.*"
},
"minimum-stability": "dev"
}
\ No newline at end of file
diff --git a/config/config.ini.sample b/config/config.ini.sample
index 62437d3..778f15a 100644
--- a/config/config.ini.sample
+++ b/config/config.ini.sample
@@ -1,61 +1,61 @@
;; Kolab Free/Busy Service configuration
;; Require HTTP authentication to access this service
[httpauth]
;; Example for static auth credentials
; type = static
; username = "<user>"
; password = "<pass>"
;; Example for LDAP-based authentication
; type = ldap
; host = ldap://localhost:389
; bind_dn = "uid=kolab-service,ou=Special Users,dc=yourdomain,dc=com"
; bind_pw = "<service-bind-pw>"
; base_dn = "dc=yourdomain,dc=com"
; filter = "(&(|(mail=%s)(alias=%s)(uid=%s))(objectclass=inetorgperson))" ; optional, %s is replaced by the username
;; Allow privileged access from these IPs
[trustednetworks]
-allow[] = 127.0.0.1
-allow[] = 192.168.0.0/16
-allow[] = 10.10.*
-allow[] = ::1
+allow = 127.0.0.1,
+ 192.168.0.0/16,
+ 10.10.*,
+ ::1
;; Logging configuration
[log]
driver = file ; supported drivers: file, syslog
path = ./log
name = freebusy
level = 300 ; (100 = Debug, 200 = Info, 300 = Warn, 400 = Error, 500 = Critical)
;; Directories to resolve email addresses and their f/b source locations
;; try local filesystem first
[directory "local"]
type = static
filter = "@yourdomain"
fbsource = file:/var/lib/kolab-freebusy/%s.ifb
;; local Kolab directory server
[directory "kolab-ldap"]
type = ldap
host = ldap://localhost:389
bind_dn = "uid=kolab-service,ou=Special Users,dc=yourdomain,dc=com"
bind_pw = "<service-bind-pw>"
base_dn = "dc=yourdomain,dc=com"
filter = "(&(objectClass=kolabInetOrgPerson)(|(uid=%s)(mail=%s)(alias=%s)))"
-attributes[] = mail
-lc_attributes[] = mail
+attributes = mail, sn
+lc_attributes = sn
fbsource = file:/www/kolab-freebusy/data/%mail.ifb
loglevel = 100 ; Debug
;; external MS Exchange 2010 server
[directory "exchange"]
type = static
filter = "@microsoft.com$"
fbsource = https://externalhost/free-busy/%s.ics
format = Exchange2010
diff --git a/lib/Kolab/Config.php b/lib/Kolab/Config.php
new file mode 100644
index 0000000..30cebbf
--- /dev/null
+++ b/lib/Kolab/Config.php
@@ -0,0 +1,284 @@
+<?php
+
+/**
+ * Model class to give access to service configuration
+ *
+ * This file is part of the Kolab PHP Utilities library
+ *
+ * @author Thomas Bruederli <bruederli@kolabsys.com>
+ *
+ * Copyright (C) 2013, Kolab Systems AG <contact@kolabsys.com>
+ *
+ * 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;
+
+/**
+ * Wrapper class for service configuration
+ */
+class Config
+{
+ const STRING = 0;
+ const BOOL = 1;
+ const INT = 2;
+ const FLOAT = 3;
+ const ARR = 4;
+
+ protected static $instance;
+
+ protected $env = '';
+ protected $basedir = '../config';
+ protected $data = array();
+ protected $valid = false;
+
+ /**
+ * Singelton getter
+ *
+ * @param string Path to load config from
+ */
+ public static function get_instance($env = '', $dir = null)
+ {
+ if (!isset(self::$instance)) {
+ self::$instance = new Config($env);
+ if ($dir) self::$instance->basedir = $dif;
+ }
+
+ if (!self::$instance->valid) {
+ self::$instance->load('config.ini');
+ }
+
+ return self::$instance;
+ }
+
+ /**
+ * Default constructor
+ */
+ function __construct($env = '')
+ {
+ $this->env = $env;
+ $this->load($this->basedir . '/config.ini');
+ }
+
+ /**
+ * Load config from the given .ini file
+ */
+ private function load($file, $use_env = true)
+ {
+ // check for relative path
+ if (!is_readable($inifile) && is_readable($this->basedir . '/' . $inifile)) {
+ $inifile = $this->basedir . '/' . $inifile;
+ }
+
+ $inifile = $this->resolve_path($file, $use_env);
+ if ($raw = self::parse_ini_file($inifile, true)) {
+ foreach ($raw as $section => $values) {
+ $sub = null;
+ if (preg_match('/^(\w+)\s+"?(.+)"?$/Ui', $section, $m)) {
+ $section = $m[1];
+ $sub = trim($m[2], '"');
+ }
+ if (!empty($sub) && !empty($values)) {
+ $config[$section][$sub] = $values;
+ }
+ else if (!empty($values) && is_array($values)) {
+ $config[$section] = $values;
+ }
+ }
+
+ $this->register($config);
+ $this->valid = !empty($this->data);
+ }
+ else {
+ trigger_error("Failed to parse configuration from $inifile", E_USER_ERROR);
+ }
+ }
+
+ /**
+ * Helper method to resolve the absolute path to the given config file.
+ * This also takes the 'env' property into account.
+ */
+ private function resolve_path($file, $use_env)
+ {
+ if ($file[0] != '/') {
+ $file = realpath($this->basedir . '/' . $file);
+ }
+
+ // check if <file>-env.ini exists
+ if ($file && $use_env && !empty($this->env)) {
+ $envfile = preg_replace('/\.(ini|conf)$/', '-' . $this->env . '.\\1', $file);
+ if (is_file($envfile))
+ return $envfile;
+ }
+
+ return $file;
+ }
+
+ /**
+ * Replacement for PHP's parse_ini_file()
+ */
+ private static function parse_ini_file($filename)
+ {
+ $raw = array();
+ foreach (file($filename) as $_line) {
+ if ($_line[0] == ';') // skip comments
+ continue;
+
+ if (preg_match('/^\[([a-z0-9-_\.]+[^\]]*)\]/', $_line, $matches)) {
+ $_cur_section = $matches[1];
+ $raw[$_cur_section] = array();
+ unset($_cur_key);
+ }
+
+ if (preg_match('/^([a-z0-9\.-_]+)\s*=\s*(.*)/', $_line, $matches)) {
+ if (isset($_cur_section) && !empty($_cur_section)) {
+ $_cur_key = $matches[1];
+ $raw[$_cur_section][$matches[1]] = isset($matches[2]) ? trim($matches[2], ' "') : '';
+ }
+ }
+ else if (preg_match('/^\s+(.*)$/', $_line, $matches)) {
+ if (isset($_cur_key) && !empty($_cur_key)) {
+ $raw[$_cur_section][$_cur_key] .= $matches[1];
+ }
+ }
+ }
+
+ return $raw;
+ }
+
+ /**
+ * Dump the hierarchical structure of config options into a flat list with keys delimited by dots
+ */
+ private function register($config, $prefix = '')
+ {
+ // merge the new config values over existing data
+ if (empty($prefix)) {
+ $this->data = array_replace_recursive($this->data, $config);
+ }
+ 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;
+ }
+
+ foreach ((array)$config as $key => $val) {
+ if (is_array($val)) {
+ $this->register($val, "$prefix$key.");
+ }
+ else {
+ $this->data[$prefix.$key] = $val;
+ }
+ }
+
+ // resolve references in config options (e.g. %(foo.bar))
+ if (empty($prefix)) {
+ array_walk_recursive($this->data, array($this, 'resolve_reference'));
+ }
+ }
+
+ /**
+ * Callback to resolve references in the given config option value
+ */
+ private function resolve_reference(&$value, $key)
+ {
+ if (is_string($value)) {
+ $value = preg_replace_callback('/%[({]([\w.]+)[})]/i', array($this, 'replace_reference'), $value);
+ }
+ }
+
+ /**
+ * Callback function to replace the given reference with the read config value
+ */
+ private function replace_reference($m)
+ {
+ return $this->data[$m[1]];
+ }
+
+ /**
+ * Magic getter for direct read-only access to config options
+ */
+ public function __get($name)
+ {
+ return $this->data[$name];
+ }
+
+ /**
+ * Magic isset check
+ */
+ public function __isset($name)
+ {
+ return array_key_exists($name, $this->data);
+ }
+
+ /**
+ * Common getter for config options with fallback to default values
+ *
+ * @param string Config option name
+ * @param mixed Default value if option isn't set in config
+ * @param integer Expected variable type
+ * @return mixed Config option value
+ */
+ public function get($name, $default = null, $type = null)
+ {
+ switch ($name) {
+ case 'output.tempdir':
+ case 'session.savepath':
+ // return an absolute path for relative directory properties
+ if (isset($this->data[$name]) && $this->data[$name][0] != '/') {
+ $value = realpath(INSTALL_PATH . '/' . $this->data[$name]);
+ break;
+ }
+
+ default:
+ $value = array_key_exists($name, $this->data) ? $this->data[$name] : $default;
+ }
+
+ // convert value to the requested type
+ return $type ? self::convert($value, $type) : value;
+ }
+
+ /**
+ * Determines whether we have a valid configuration loaded
+ *
+ * @return boolean True if valid, False otherwise
+ */
+ public function valid()
+ {
+ return !empty($this->data);
+ }
+
+ /**
+ * Convert the given (string) value to the requested type
+ *
+ * @param string Config value
+ * @param int Output type (one of this class constants)
+ * @return mixed The converted value
+ */
+ public static function convert($value, $type)
+ {
+ // convert value to the requested type
+ switch ($type) {
+ case self::INT:
+ return intval($value);
+ case self::FLOAT:
+ return floatval($value);
+ case self::BOOL:
+ return (bool)preg_match('/^(true|1|on|enabled|yes)$/i', $value);
+ case self::ARR:
+ return preg_split('/,\s*/', strval($value));
+ }
+
+ return $value;
+ }
+}
+
diff --git a/lib/Kolab/FreeBusy/Config.php b/lib/Kolab/FreeBusy/Config.php
deleted file mode 100644
index ab82a1a..0000000
--- a/lib/Kolab/FreeBusy/Config.php
+++ /dev/null
@@ -1,173 +0,0 @@
-<?php
-
-/**
- * This file is part of the Kolab Server Free/Busy Service
- *
- * @author Thomas Bruederli <bruederli@kolabsys.com>
- *
- * Copyright (C) 2013, Kolab Systems AG <contact@kolabsys.com>
- *
- * 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;
-
-/**
- * Wrapper class for service configuration
- */
-class Config
-{
- private static $instance;
-
- private $basedir = '.';
- private $data = array();
- private $valid = false;
-
- /**
- * Singelton getter
- *
- * @param string Path to load config from
- */
- public static function getInstance($dir = null)
- {
- if (!isset(self::$instance)) {
- self::$instance = new Config($dir);
- }
-
- if ($dir && !self::$instance->valid) {
- self::$instance->load($configdir . '/config.ini');
- }
-
- return self::$instance;
- }
-
- /**
- * Default constructor
- */
- function __construct($configdir = null)
- {
- if ($configdir) {
- $this->basedir = $configdir;
- $this->load($configdir . '/config.ini');
- }
- }
-
- /**
- * Load config from the given .ini file
- */
- private function load($inifile)
- {
- if ($raw = parse_ini_file($inifile, true)) {
- $config['directories'] = array();
- foreach ($raw as $section => $values) {
- // check for known sections
- if (in_array($section, array('httpauth','trustednetworks','log'))) {
- $config[$section] = $values;
- }
- else if (strpos($section, 'directory') === 0 || isset($values['fbsource'])) {
- $sect = preg_replace('/^directory\s*/', '', $section);
- $key = strlen($sect) ? $sect : count($config['directories']);
- $config['directories'][$key] = $values;
- }
- else if (!empty($values) && is_array($values)) {
- $config[$section] = $values;
- }
- }
-
- $this->register($config);
- $this->valid = !empty($this->data['directories']);
- }
- else {
- trigger_error("Failed to parse configuration from $inifile", E_USER_ERROR);
- }
- }
-
- /**
- * Dump the hierarchical structure of config options into a flat list with keys delimited by dots
- */
- private function register($config, $prefix = '')
- {
- // merge the new config values over existing data
- if (empty($prefix)) {
- $this->data = array_replace_recursive($this->data, $config);
- }
- 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;
- }
-
- foreach ((array)$config as $key => $val) {
- if (is_array($val)) {
- $this->register($val, "$prefix$key.");
- }
- else {
- $this->data[$prefix.$key] = $val;
- }
- }
-
- // resolve references in config options (e.g. %(foo.bar))
- if (empty($prefix)) {
- array_walk_recursive($this->data, array($this, 'resolve_reference'));
- }
- }
-
- /**
- * Callback to resolve references in the given config option value
- */
- private function resolve_reference(&$value, $key)
- {
- if (is_string($value)) {
- $value = preg_replace_callback('/%[({]([\w.]+)[})]/i', array($this, 'replace_reference'), $value);
- }
- }
-
- /**
- * Callback function to replace the given reference with the read config value
- */
- private function replace_reference($m)
- {
- return $this->data[$m[1]];
- }
-
- /**
- * Magic getter for direct read-only access to config options
- */
- public function __get($name)
- {
- return $this->data[$name];
- }
-
- /**
- * Common getter for config options with fallback in default values
- *
- * @param string Config option name
- * @param mixed Default value if option isn't set in config
- * @return mixed Config option value
- */
- public function get($name, $default = null)
- {
- return array_key_exists($name, $this->data) ? $this->data[$name] : $default;
- }
-
- /**
- * Determines whether we have a valid configuration loaded
- *
- * @return boolean True if valid, False otherwise
- */
- public function isValid()
- {
- return !empty($this->data);
- }
-}
-
diff --git a/lib/Kolab/FreeBusy/Directory.php b/lib/Kolab/FreeBusy/Directory.php
index 1c70f75..6478e85 100644
--- a/lib/Kolab/FreeBusy/Directory.php
+++ b/lib/Kolab/FreeBusy/Directory.php
@@ -1,105 +1,105 @@
<?php
/**
* This file is part of the Kolab Server Free/Busy Service
*
* @author Thomas Bruederli <bruederli@kolabsys.com>
*
* Copyright (C) 2013, Kolab Systems AG <contact@kolabsys.com>
*
* 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;
/**
* Abstract class representing an address directory for free/busy data lookups
*/
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)) {
// 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);
}
return $data;
}
}
return false;
}
/**
* Modify attribute values according to config
*/
protected function postprocessAttrib($attrib)
{
if (!empty($this->config['lc_attributes'])) {
- foreach ((array)$this->config['lc_attributes'] as $key) {
+ 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
diff --git a/lib/Kolab/FreeBusy/DirectoryLDAP.php b/lib/Kolab/FreeBusy/DirectoryLDAP.php
index 5e31e24..f462f79 100644
--- a/lib/Kolab/FreeBusy/DirectoryLDAP.php
+++ b/lib/Kolab/FreeBusy/DirectoryLDAP.php
@@ -1,129 +1,129 @@
<?php
/**
* This file is part of the Kolab Server Free/Busy Service
*
* @author Thomas Bruederli <bruederli@kolabsys.com>
*
* Copyright (C) 2013, Kolab Systems AG <contact@kolabsys.com>
*
* 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;
// PEAR modules operate in global namespace
use \Net_LDAP3;
use \Monolog\Logger as Monolog;
/**
* Implementation of an address lookup using an LDAP directory
*/
class DirectoryLDAP extends Directory
{
private $ldap;
private $logger;
private $ready = false;
/**
* Default constructor loading directory configuration
*/
public function __construct($config)
{
$this->config = $config;
$host = parse_url($config['host']);
$ldap_config = array(
'hosts' => array($host['host']),
'port' => $host['port'] ?: 389,
'use_tls' => $host['scheme'] == 'tls' || $host['scheme'] == 'ldaps',
'root_dn' => $config['base_dn'],
- 'return_attributes' => (array)$config['attributes'],
+ 'return_attributes' => Config::convert($config['attributes'], Config::ARR),
'log_hook' => array($this, 'log'),
) + $config;
// instantiate Net_LDAP3 and connect with logger
$this->logger = Logger::get('ldap', intval($config['loglevel']));
$this->ldap = new Net_LDAP3($ldap_config);
// connect + bind to LDAP server
if ($this->ldap->connect()) {
$this->ready = $this->ldap->bind($config['bind_dn'], $config['bind_pw']);
}
if ($this->ready) {
$this->logger->addInfo("Connected to $config[host] with '$config[bind_dn]'");
}
else {
$this->logger->addWarning("Connectiion to $config[host] with '$config[bind_dn]' failed!");
}
}
/**
* Callback for Net_LDAP3 logging
*/
public function log($level, $msg)
{
// map PHP log levels to Monolog levels
static $loglevels = array(
LOG_DEBUG => Monolog::DEBUG,
LOG_NOTICE => Monolog::NOTICE,
LOG_INFO => Monolog::INFO,
LOG_WARNING => Monolog::WARNING,
LOG_ERR => Monolog::ERROR,
LOG_CRIT => Monolog::CRITICAL,
LOG_ALERT => Monolog::ALERT,
LOG_EMERG => Monolog::EMERGENCY,
);
$msg = is_array($msg) ? join('; ', $msg) : strval($msg);
$this->logger->addRecord($loglevels[$level], $msg);
}
/**
* @see Directory::resolve()
*/
public function resolve($user)
{
$result = array('s' => $user);
if ($this->ready) {
// search with configured filter
$filter = preg_replace('/%s/i', $user, $this->config['filter']);
$ldapresult = $this->ldap->search($this->config['base_dn'], $filter, 'sub');
// got a valid result
if ($ldapresult && $ldapresult->count()) {
$ldapresult->rewind();
$entry = Net_LDAP3::normalize_entry($ldapresult->current()); // get the first entry
$this->logger->addInfo("Found " . $ldapresult->count() . " entries for $filter", $entry);
// convert entry attributes to strings and add them to the final result hash array
foreach ($entry as $k => $v) {
if (!empty($v)) {
$result[$k] = strval(is_array($v) ? $v[0] : $v);
}
}
return $result;
}
$this->logger->addInfo("No entry found for $filter");
}
return false;
}
}
diff --git a/web/index.php b/web/index.php
index 93a998a..fcbce69 100644
--- a/web/index.php
+++ b/web/index.php
@@ -1,137 +1,137 @@
<?php
/**
* Kolab Server Free/Busy Service Endpoint
*
* This is the public API to provide Free/Busy information for Kolab users.
*
- * @version 0.1.1
+ * @version 0.1.2
* @author Thomas Bruederli <bruederli@kolabsys.com>
*
* Copyright (C) 2013, Kolab Systems AG <contact@kolabsys.com>
*
* 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/>.
*/
define('KOLAB_FREEBUSY_ROOT', realpath('../'));
// suppress error notices
ini_set('error_reporting', E_ALL &~ E_NOTICE);
// use composer's autoloader for both dependencies and local lib
require_once KOLAB_FREEBUSY_ROOT . '/vendor/autoload.php';
+use Kolab\Config;
use Kolab\FreeBusy\Utils;
-use Kolab\FreeBusy\Config;
use Kolab\FreeBusy\Logger;
use Kolab\FreeBusy\Directory;
use Kolab\FreeBusy\HTTPAuth;
// load config
-$config = Config::getInstance(KOLAB_FREEBUSY_ROOT . '/config');
-if ($config->isValid()) {
+$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->trustednetworks['allow']) : false;
+ $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));
}
// check HTTP authentication
if (!$trusted_ip && $config->httpauth) {
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
$url = array_filter(explode('/', $uri));
$user = strtolower(array_pop($url));
$action = strtolower(array_pop($url));
$extended = false;
// remove file extension
if (preg_match('/^(.+)\.([ipx]fb)$/i', $user, $m)) {
$user = $m[1];
$extended = $m[2] == 'xfb';
}
// iterate over directories
- foreach ($config->directories as $key => $dirconfig) {
+ 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");
$now = time();
$dtformat = 'Ymd\THis\Z';
// NOTE: The following settings should probably correspond with
// whatever period of time kolab-freebusyd thinks it should use.
// Should probably be a setting. For now, do 8 weeks in the past
$start = $now - (60 * 60 * 24 * 7 * 8);
// Should probably be a setting. For now, do 16 weeks into the future
$end = $now + (60 * 60 * 24 * 7 * 16);
// Return an apparent empty Free/Busy list.
print "BEGIN:VCALENDAR\n";
print "VERSION:2.0\n";
print "PRODID:-//kolab.org//NONSGML Kolab Server 3//EN\n";
print "METHOD:PUBLISH\n";
print "BEGIN:VFREEBUSY\n";
print "ORGANIZER:MAILTO:" . $user . ".ifb\n";
print "DTSTAMP:" . gmdate($dtformat) . "\n";
print "DTSTART:" . gmdate($dtformat, $start) . "\n";
print "DTEND:" . gmdate($dtformat, $end) . "\n";
print "COMMENT:This is a dummy vfreebusy that indicates an empty calendar\n";
print "FREEBUSY:19700101T000000Z/19700101T000000Z\n";
print "END:VFREEBUSY\n";
print "END:VCALENDAR\n";
}
}
// exit with error
# header($_SERVER['SERVER_PROTOCOL'] . " 500 Internal Server Error", true);

File Metadata

Mime Type
text/x-diff
Expires
Sat, Jan 31, 2:13 PM (21 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
426327
Default Alt Text
(28 KB)

Event Timeline