Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2528425
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Feb 1, 9:14 AM (1 d, 16 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
426684
Default Alt Text
(13 KB)
Attached To
Mode
R28 freebusy
Attached
Detach File
Event Timeline
Log In to Comment