Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2528332
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/config/config.ini.sample b/config/config.ini.sample
index 5eb6607..3dfe7cf 100644
--- a/config/config.ini.sample
+++ b/config/config.ini.sample
@@ -1,53 +1,53 @@
;; 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
;; 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/%u.ifb
+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=%u)(mail=%u)(alias=%u)))"
+filter = "(&(objectClass=kolabInetOrgPerson)(|(uid=%s)(mail=%s)(alias=%s)))"
attributes[] = mail
fbsource = file:/www/kolab-freebusy/data/%mail.ifb
loglevel = 100 ; Debug
diff --git a/lib/Kolab/FreeBusy/DirectoryLDAP.php b/lib/Kolab/FreeBusy/DirectoryLDAP.php
index 54709f2..55a59df 100644
--- a/lib/Kolab/FreeBusy/DirectoryLDAP.php
+++ b/lib/Kolab/FreeBusy/DirectoryLDAP.php
@@ -1,111 +1,111 @@
<?php
namespace Kolab\FreeBusy;
// PEAR modules operate in global namespace
use \Net_LDAP3;
use \Monolog\Logger as Monolog;
/**
*
*/
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'],
'sizelimit' => 0,
'timelimit' => 0,
) + $config;
// instantiate Net_LDAP3 and connect with logger
$this->logger = Logger::get('ldap', intval($config['loglevel']));
$this->ldap = new Net_LDAP3($ldap_config);
$this->ldap->config_set('log_hook', array($this, 'log'));
$this->ldap->config_set('return_attributes', (array)$config['attributes']);
// 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('u' => $user);
+ $result = array('s' => $user);
if ($this->ready) {
// search with configured filter
- $filter = preg_replace('/%u/i', $user, $this->config['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/lib/Kolab/FreeBusy/DirectoryStatic.php b/lib/Kolab/FreeBusy/DirectoryStatic.php
index ff55e0e..8424332 100644
--- a/lib/Kolab/FreeBusy/DirectoryStatic.php
+++ b/lib/Kolab/FreeBusy/DirectoryStatic.php
@@ -1,38 +1,38 @@
<?php
namespace Kolab\FreeBusy;
/**
* Implementation of a static address directory for Free/Busy user lookups.
*
* This directory basically pipes the username through with an optional check
* whether it matches the configured filter rule
*/
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('u' => $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
index 2d12ebc..96bb547 100644
--- a/lib/Kolab/FreeBusy/Source.php
+++ b/lib/Kolab/FreeBusy/Source.php
@@ -1,66 +1,67 @@
<?php
namespace Kolab\FreeBusy;
/**
* Abstract class to fetch free/busy data from a specific source
*/
abstract class Source
{
protected $config = array();
/**
* Factory method creating an instace of Source according to config
*
* @param array Hash array with config
*/
public static function factory($url)
{
$config = parse_url($url);
$config['url'] = $url;
switch ($config['scheme']) {
case 'file': return new SourceFile($config);
- case 'imap': return new SourceIMAP($config);
+ case 'imap':
+ case 'imaps': return new SourceIMAP($config);
case 'http':
case 'https': return new SourceURL($config);
}
Logger::get('source')->addError("Invalid source configuration: " . $url);
return null;
}
/**
* Default constructor
*/
public function __construct($config)
{
$this->config = $config;
}
/**
* Retrieve free/busy data for the given user
*
* @param array Hash array with user attributes
*/
abstract public function getFreeBusyData($user, $extended);
/**
* Replace all %varname strings in config with values from $user
*/
protected function getUserConfig($user)
{
$config = array();
foreach ($this->config as $k => $val) {
if (is_string($val) && strpos($val, '%') !== false) {
$val = preg_replace_callback(
'/%\{?([a-z0-9]+)\}?/',
function($m) use ($user) { return $user[$m[1]]; },
$val);
}
$config[$k] = $val;
}
return $config;
}
}
\ No newline at end of file
diff --git a/web/index.php b/web/index.php
index 93115f2..9d7cc37 100644
--- a/web/index.php
+++ b/web/index.php
@@ -1,128 +1,128 @@
<?php
/**
* Kolab Server Free/Busy Service Endpoint
*
* This is the public API to provide Free/Busy information for Kolab users.
*
* @version 0.1.0
* @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\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()) {
// check for trusted IP first
$remote_ip = Utils::remoteIP();
$trusted_ip = $config->trustednetworks ? Utils::checkIPRange($remote_ip, $config->trustednetworks['allow']) : false;
$log = Logger::get('web');
$log->addDebug('Request: ' . $_SERVER['REDIRECT_URL'], 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', true);
+ header('Content-type: text/plain; charset=utf-8', true);
// analyse request
$url = array_filter(explode('/', $_SERVER['REDIRECT_URL']));
$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) {
$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
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Feb 1, 7:51 AM (1 d, 15 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
426633
Default Alt Text
(12 KB)
Attached To
Mode
R28 freebusy
Attached
Detach File
Event Timeline
Log In to Comment