* @copyright 2008-2010 Phergie Development Team (http://phergie.org)
* @license http://phergie.org/license New BSD License
* @link http://pear.phergie.org/package/Phergie_Plugin_Acl
*/
/**
* Provides an access control system to limit reponses to events based on
* the users who originate them.
*
* Configuration settings:
* acl.whitelist - mapping of user hostmask patterns (optionally by host) to
* plugins and methods where those plugins and methods will
* only be accessible to those users (i.e. and inaccessible
* to other users)
* acl.blacklist - mapping of user hostmasks (optionally by host) to plugins
* and methods where where those plugins and methods will be
* inaccessible to those users but accessible to other users
* acl.ops - TRUE to automatically give access to whitelisted plugins
* and methods to users with ops for events they initiate in
* channels where they have ops
*
* The whitelist and blacklist settings are formatted like so:
*
* 'acl.whitelist' => array(
* 'hostname1' => array(
* 'pattern1' => array(
* 'plugins' => array(
* 'ShortPluginName'
* ),
* 'methods' => array(
* 'methodName'
* )
* ),
* )
* ),
*
*
* The hostname array dimension is optional; if not used, rules will be
* applied across all connections. The pattern is a user hostmask pattern
* where asterisks (*) are used for wildcards. Plugins and methods do not
* need to be set to empty arrays if they are not used; simply exclude them.
*
* @category Phergie
* @package Phergie_Plugin_Acl
* @author Phergie Development Team
* @license http://phergie.org/license New BSD License
* @link http://pear.phergie.org/package/Phergie_Plugin_Acl
* @uses Phergie_Plugin_UserInfo pear.phergie.org
*/
class Phergie_Plugin_Acl extends Phergie_Plugin_Abstract
{
/**
* Checks for permission settings and removes the plugin if none are set.
*
* @return void
*/
public function onLoad()
{
$this->plugins->getPlugin('UserInfo');
if (!$this->getConfig('acl.blacklist')
&& !$this->getConfig('acl.whitelist')
) {
$this->plugins->removePlugin($this);
}
}
/**
* Applies a set of rules to a plugin handler iterator.
*
* @param Phergie_Plugin_Iterator $iterator Iterator to receive rules
* @param array $rules Associate array containing
* either a 'plugins' key pointing to an array containing plugin
* short names to filter, a 'methods' key pointing to an array
* containing method names to filter, or both
*
* @return void
*/
protected function applyRules(Phergie_Plugin_Iterator $iterator, array $rules)
{
if (!empty($rules['plugins'])) {
$iterator->addPluginFilter($rules['plugins']);
}
if (!empty($rules['methods'])) {
$iterator->addMethodFilter($rules['methods']);
}
}
/**
* Checks permission settings and short-circuits event processing for
* blacklisted users.
*
* @return void
*/
public function preEvent()
{
// Ignore server responses
if ($this->event instanceof Phergie_Event_Response) {
return;
}
// Ignore server-initiated events
if (!$this->event->isFromUser()) {
return;
}
// Get the iterator used to filter plugins when processing events
$iterator = $this->plugins->getIterator();
// Get configuration setting values
$whitelist = $this->getConfig('acl.whitelist', array());
$blacklist = $this->getConfig('acl.blacklist', array());
$ops = $this->getConfig('acl.ops', false);
// Support host-specific lists
$host = $this->connection->getHost();
foreach (array('whitelist', 'blacklist') as $var) {
foreach ($$var as $pattern => $rules) {
$regex = '/^' . str_replace('*', '.*', $pattern) . '$/i';
if (preg_match($regex, $host)) {
${$var} = ${$var}[$pattern];
break;
}
}
}
// Get information on the user initiating the current event
$hostmask = $this->event->getHostmask();
$isOp = $ops
&& $this->event->isInChannel()
&& $this->plugins->userInfo->isOp(
$this->event->getNick(),
$this->event->getSource()
);
// Filter whitelisted commands if the user is not on the whitelist
if (!$isOp) {
$whitelisted = false;
foreach ($whitelist as $pattern => $rules) {
if ($hostmask->matches($pattern)) {
$whitelisted = true;
}
}
if (!$whitelisted) {
foreach ($whitelist as $pattern => $rules) {
$this->applyRules($iterator, $rules);
}
}
}
// Filter blacklisted commands if the user is on the blacklist
$blacklisted = false;
foreach ($blacklist as $pattern => $rules) {
if ($hostmask->matches($pattern)) {
$this->applyRules($iterator, $rules);
break;
}
}
}
/**
* Clears filters on the plugin handler iterator.
*
* @return void
*/
public function postDispatch()
{
$this->plugins->getIterator()->clearFilters();
}
}