Page MenuHomePhorge

No OneTemporary

Size
13 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/Kolab/FreeBusy/Config.php b/lib/Kolab/FreeBusy/Config.php
index d80ef7f..205a438 100644
--- a/lib/Kolab/FreeBusy/Config.php
+++ b/lib/Kolab/FreeBusy/Config.php
@@ -1,122 +1,125 @@
<?php
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'])){
- $config['directories'][] = $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;
}
}
$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 = '')
{
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;
}
}
}
/**
* 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 a68e5bb..67e6d8d 100644
--- a/lib/Kolab/FreeBusy/Directory.php
+++ b/lib/Kolab/FreeBusy/Directory.php
@@ -1,63 +1,63 @@
<?php
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:
- trigger_error("Invalid directory type '" . $config['type'] . "'!", E_USER_ERROR);
+ 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)) {
// foward request to Source instance
return $source->getFreeBusyData($user, $extended);
}
}
return false;
}
}
\ No newline at end of file
diff --git a/lib/Kolab/FreeBusy/DirectoryLDAP.php b/lib/Kolab/FreeBusy/DirectoryLDAP.php
index 1c675f9..54709f2 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', $config['loglevel']);
+ $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);
if ($this->ready) {
// search with configured filter
$filter = preg_replace('/%u/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/Logger.php b/lib/Kolab/FreeBusy/Logger.php
index 552c7e0..8af607c 100644
--- a/lib/Kolab/FreeBusy/Logger.php
+++ b/lib/Kolab/FreeBusy/Logger.php
@@ -1,55 +1,52 @@
<?php
namespace Kolab\FreeBusy;
use Monolog\Logger as Monologger;
use Monolog\Handler\StreamHandler;
+use Monolog\Handler\SyslogHandler;
use Monolog\Handler\NullHandler;
/**
* Helper class for creating up Monolog instanced with local configration
*/
class Logger
{
private static $instances = array();
/**
* Static getter for a Monolog\Logger instance
*/
public static function get($name, $level = 0)
{
- if (!isset(self::$instances[$name])) {
+ if (!isset(self::$instances[$name]) || ($level && !self::$instances[$name]->isHandling($level))) {
$logger = new Monologger($name);
- // TODO: support more log drivers
+ // read log config
$config = Config::getInstance();
+ $identity = $config->get('log.name', 'freebusy');
+ $loglevel = $level ?: $config->get('log.level', Monologger::INFO);
+
switch ($config->get('log.driver')) {
case 'file':
- $logdir = self::realpath($config->get('log.path'));
- $loglevel = $level ?: $config->get("log.level", Monologger::INFO);
- $logger->pushHandler(new StreamHandler($logdir . $name. '.log', $loglevel));
+ $logdir = Utils::abspath($config->get('log.path'), '/');
+ $logger->pushHandler(new StreamHandler($logdir . $identity . '.log', $loglevel));
+ break;
+
+ case 'syslog':
+ $logger->pushHahdler(new SyslogHandler($identity, $config->get('log.facility', 'user'), $loglevel));
break;
default:
// null handler if logging is disabled
$logger->pushHandler(new NullHandler);
}
self::$instances[$name] = $logger;
}
return self::$instances[$name];
}
- /**
- * Resolve the given directory to a real path ending with a /
- */
- private static function realpath($dirname)
- {
- if ($dirname[0] != '/')
- $dirname = realpath(KOLAB_FREEBUSY_ROOT . '/' . $dirname);
-
- return rtrim($dirname, '/') . '/';
- }
}
diff --git a/lib/Kolab/FreeBusy/Source.php b/lib/Kolab/FreeBusy/Source.php
index 53c4d0f..2d12ebc 100644
--- a/lib/Kolab/FreeBusy/Source.php
+++ b/lib/Kolab/FreeBusy/Source.php
@@ -1,66 +1,66 @@
<?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 'http':
case 'https': return new SourceURL($config);
}
- trigger_error("Invalid source configuration: " . $url, E_USER_ERROR);
+ 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/lib/Kolab/FreeBusy/SourceURL.php b/lib/Kolab/FreeBusy/SourceURL.php
index d165bd5..e838640 100644
--- a/lib/Kolab/FreeBusy/SourceURL.php
+++ b/lib/Kolab/FreeBusy/SourceURL.php
@@ -1,52 +1,55 @@
<?php
namespace Kolab\FreeBusy;
/**
* Implementation of a Free/Busy data source reading from remote URLs through HTTP
*/
class SourceURL extends Source
{
/**
* @see Source::getFreeBusyData()
*/
public function getFreeBusyData($user, $extended)
{
$config = $this->getUserConfig($user);
// prepare HTTP stream context
$context = stream_context_create(array(
'http' => array(
'user_agent' => "Kolab Free-Busy Service/0.1.0",
'timeout' => 10,
),
));
// set HTTP auth credentials
if (!empty($config['user'])) {
stream_context_set_option($context, array(
'http' => array(
'header' => "Authorization: Basic " . base64_encode($config['user'] . ':' . $config['pass']) . "\r\n",
),
));
- $config['url'] = self::getUrl($config); // re-compose url without user:pass
+ $config['url'] = self::composeUrl($config); // re-compose url without user:pass
}
- // TODO: so some logging
+ $data = file_get_contents($config['url'], false, $context);
- return file_get_contents($config['url'], false, $context);
+ // log this...
+ Logger::get('url')->addInfo("Fetching data from " . $config['url'] . ": " . ($data ? 'OK' : 'FAILED'));
+
+ return $data;
}
/**
* Compose a full url from the given config (previously extracted with parse_url())
*/
- private static function getUrl($config)
+ private static function composeUrl($config)
{
$scheme = isset($config['scheme']) ? $config['scheme'] . '://' : '';
$host = isset($config['host']) ? $config['host'] : '';
$port = isset($config['port']) ? ':' . $config['port'] : '';
$path = isset($config['path']) ? $config['path'] : '';
$query = isset($config['query']) ? '?' . $config['query'] : '';
return $scheme . $host . $port . $path . $query;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Feb 1, 3:02 PM (1 d, 20 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
426684
Default Alt Text
(13 KB)

Event Timeline