Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2527703
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
18 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/Kolab/Config.php b/lib/Kolab/Config.php
index 30cebbf..c84426f 100644
--- a/lib/Kolab/Config.php
+++ b/lib/Kolab/Config.php
@@ -1,284 +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 ($dir) self::$instance->basedir = $dir;
}
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;
+ 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/Directory.php b/lib/Kolab/FreeBusy/Directory.php
index 6478e85..8ac2c24 100644
--- a/lib/Kolab/FreeBusy/Directory.php
+++ b/lib/Kolab/FreeBusy/Directory.php
@@ -1,105 +1,107 @@
<?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;
+use Kolab\Config;
+
/**
* 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 (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 f462f79..42d72b1 100644
--- a/lib/Kolab/FreeBusy/DirectoryLDAP.php
+++ b/lib/Kolab/FreeBusy/DirectoryLDAP.php
@@ -1,129 +1,130 @@
<?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 \Kolab\Config;
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' => 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/lib/Kolab/FreeBusy/Logger.php b/lib/Kolab/FreeBusy/Logger.php
index 618003b..b593330 100644
--- a/lib/Kolab/FreeBusy/Logger.php
+++ b/lib/Kolab/FreeBusy/Logger.php
@@ -1,73 +1,74 @@
<?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;
+use Kolab\Config;
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]) || ($level && !self::$instances[$name]->isHandling($level))) {
$logger = new Monologger($name);
// read log config
- $config = Config::getInstance();
+ $config = Config::get_instance();
$identity = $config->get('log.name', 'freebusy');
$loglevel = $level ?: $config->get('log.level', Monologger::INFO);
switch ($config->get('log.driver')) {
case 'file':
$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];
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Jan 31, 9:48 AM (10 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
426230
Default Alt Text
(18 KB)
Attached To
Mode
R28 freebusy
Attached
Detach File
Event Timeline
Log In to Comment