Page MenuHomePhorge

No OneTemporary

Size
18 KB
Referenced Files
None
Subscribers
None
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

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)

Event Timeline