Viewing File: /usr/local/cpanel/base/3rdparty/roundcube/plugins/kolab_delegation/kolab_delegation.php

<?php

/**
 * Delegation configuration utility for Kolab accounts
 *
 * @version @package_version@
 * @author Aleksander Machniak <machniak@kolabsys.com>
 * @author Thomas Bruederli <bruederli@kolabsys.com>
 *
 * Copyright (C) 2011-2012, 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/>.
 */

class kolab_delegation extends rcube_plugin
{
    public $task = 'login|mail|settings|calendar|tasks';

    private $rc;
    private $engine;


    /**
     * Plugin initialization.
     */
    public function init()
    {
        $this->rc = rcube::get_instance();

        $this->require_plugin('libkolab');
        $this->require_plugin('kolab_auth');

        // on-login delegation initialization
        $this->add_hook('login_after', array($this, 'login_hook'));
        // on-check-recent delegation support
        $this->add_hook('check_recent', array($this, 'check_recent_hook'));

        // on-message-send delegation support
        $this->add_hook('message_before_send', array($this, 'message_before_send'));

        // delegation support in Calendar and Tasklist plugins
        $this->add_hook('message_load', array($this, 'message_load'));
        $this->add_hook('calendar_user_emails', array($this, 'calendar_user_emails'));
        $this->add_hook('calendar_list_filter', array($this, 'calendar_list_filter'));
        $this->add_hook('calendar_load_itip', array($this, 'calendar_load_itip'));
        $this->add_hook('tasklist_list_filter', array($this, 'tasklist_list_filter'));

        // delegation support in kolab_auth plugin
        $this->add_hook('kolab_auth_emails', array($this, 'kolab_auth_emails'));

        // delegation support in Enigma plugin
        $this->add_hook('enigma_user_identities', array($this, 'user_identities'));

        if ($this->rc->task == 'settings') {
            // delegation management interface
            $this->register_action('plugin.delegation',              array($this, 'controller_ui'));
            $this->register_action('plugin.delegation-delete',       array($this, 'controller_action'));
            $this->register_action('plugin.delegation-save',         array($this, 'controller_action'));
            $this->register_action('plugin.delegation-autocomplete', array($this, 'controller_action'));

            $this->add_hook('settings_actions', array($this, 'settings_actions'));

            if ($this->rc->output->type == 'html'
                && ($this->rc->action == 'plugin.delegation' || empty($_REQUEST['_framed']))
            ) {
                $this->add_texts('localization/', array('deleteconfirm', 'savingdata', 'yes', 'no'));

                if ($this->rc->action == 'plugin.delegation') {
                    $this->include_script('kolab_delegation.js');
                }

                $this->skin_path = $this->local_skin_path();
                $this->include_stylesheet($this->skin_path . '/style.css');
            }
        }
        // Calendar/Tasklist plugin UI bindings
        else if (($this->rc->task == 'calendar' || $this->rc->task == 'tasks')
            && empty($_REQUEST['_framed'])
        ) {
            if ($this->rc->output->type == 'html') {
                $this->calendar_ui();
            }
        }
    }

    /**
     * Adds Delegation section in Settings
     */
    function settings_actions($args)
    {
        $args['actions'][] = array(
            'action' => 'plugin.delegation',
            'class'  => 'delegation',
            'label'  => 'tabtitle',
            'domain' => 'kolab_delegation',
            'title'  => 'delegationtitle',
        );

        return $args;
    }

    /**
     * Engine object getter
     */
    private function engine()
    {
        if (!$this->engine) {
            require_once $this->home . '/kolab_delegation_engine.php';

            $this->load_config();
            $this->engine = new kolab_delegation_engine();
        }

        return $this->engine;
    }

    /**
     * On-login action
     */
    public function login_hook($args)
    {
        // Manage (create) identities for delegator's email addresses
        // and subscribe to delegator's folders. Also remove identities
        // after delegation is removed

        $engine = $this->engine();
        $engine->delegation_init();

        return $args;
    }

    /**
     * Check-recent action
     */
    public function check_recent_hook($args)
    {
        // Checking for new messages shall be extended to Inbox folders of all
        // delegators if 'check_all_folders' is set to false.

        if ($this->rc->task != 'mail') {
            return $args;
        }

        if (!empty($args['all'])) {
            return $args;
        }

        if (empty($_SESSION['delegators'])) {
            return $args;
        }

        $storage  = $this->rc->get_storage();
        $other_ns = $storage->get_namespace('other');
        $folders  = $storage->list_folders_subscribed('', '*', 'mail');

        foreach (array_keys($_SESSION['delegators']) as $uid) {
            foreach ($other_ns as $ns) {
                $folder = $ns[0] . $uid;
                if (in_array($folder, $folders) && !in_array($folder, $args['folders'])) {
                    $args['folders'][] = $folder;
                }
            }
        }

        return $args;
    }

    /**
     * Mail send action
     */
    public function message_before_send($args)
    {
        // Checking headers of email being send, we'll add
        // Sender: header if mail is send on behalf of someone else

        if (!empty($_SESSION['delegators'])) {
            $engine = $this->engine();
            $engine->delegator_delivery_filter($args);
        }

        return $args;
    }

    /**
     * E-mail message loading action
     */
    public function message_load($args)
    {
        // This is a place where we detect delegate context
        // So we can handle event invitations on behalf of delegator
        // @TODO: should we do this only in delegators' folders?

        // skip invalid messages or Kolab objects (for better performance)
        if (empty($args['object']->headers) || $args['object']->headers->get('x-kolab-type', false)) {
            return $args;
        }

        $engine  = $this->engine();
        $context = $engine->delegator_context_from_message($args['object']);

        if ($context) {
            $this->rc->output->set_env('delegator_context', $context);
            $this->include_script('kolab_delegation.js');
        }

        return $args;
    }

    /**
     * calendar::get_user_emails() handler
     */
    public function calendar_user_emails($args)
    {
        // In delegator context we'll use delegator's addresses
        // instead of current user addresses

        if (!empty($_SESSION['delegators'])) {
            $engine = $this->engine();
            $engine->delegator_emails_filter($args);
        }

        return $args;
    }

    /**
     * calendar_driver::list_calendars() handler
     */
    public function calendar_list_filter($args)
    {
        // In delegator context we'll use delegator's folders
        // instead of current user folders

        if (!empty($_SESSION['delegators'])) {
            $engine = $this->engine();
            $engine->delegator_folder_filter($args, 'calendars');
        }

        return $args;
    }

    /**
     * tasklist_driver::get_lists() handler
     */
    public function tasklist_list_filter($args)
    {
        // In delegator context we'll use delegator's folders
        // instead of current user folders

        if (!empty($_SESSION['delegators'])) {
            $engine = $this->engine();
            $engine->delegator_folder_filter($args, 'tasklists');
        }

        return $args;
    }

    /**
     * calendar::load_itip() handler
     */
    public function calendar_load_itip($args)
    {
        // In delegator context we'll use delegator's address/name
        // for invitation responses

        if (!empty($_SESSION['delegators'])) {
            $engine = $this->engine();
            $engine->delegator_identity_filter($args);
        }

        return $args;
    }

    /**
     * Delegation support in Calendar/Tasks plugin UI
     */
    public function calendar_ui()
    {
        // Initialize handling of delegators' identities in event form

        if (!empty($_SESSION['delegators'])) {
            $engine = $this->engine();
            $this->rc->output->set_env('namespace', $engine->namespace_js());
            $this->rc->output->set_env('delegators', $engine->list_delegators_js());
            $this->include_script('kolab_delegation.js');
        }
    }

    /**
     * Delegation support in kolab_auth plugin
     */
    public function kolab_auth_emails($args)
    {
        // Add delegators addresses to address selector in user identity form

        if (!empty($_SESSION['delegators'])) {
            // @TODO: Consider not adding all delegator addresses to the list.
            // Instead add only address of currently edited identity
            foreach ($_SESSION['delegators'] as $emails) {
                $args['emails'] = array_merge($args['emails'], $emails);
            }

            $args['emails'] = array_unique($args['emails']);
            sort($args['emails']);
        }

        return $args;
    }

    /**
     * Delegation support in Enigma plugin
     */
    public function user_identities($args)
    {
        // Remove delegators' identities from the key generation form

        if (!empty($_SESSION['delegators'])) {
            $args['identities'] = array_filter($args['identities'], function($ident) {
                foreach ($_SESSION['delegators'] as $emails) {
                    if (in_array($ident['email'], $emails)) {
                        return false;
                    }
                }

                return true;
            });
        }

        return $args;
    }

    /**
     * Delegation UI handler
     */
    public function controller_ui()
    {
        // main interface (delegates list)
        if (empty($_REQUEST['_framed'])) {
            $this->register_handler('plugin.delegatelist', array($this, 'delegate_list'));

            $this->rc->output->include_script('list.js');
            $this->rc->output->send('kolab_delegation.settings');
        }
        // delegate frame
        else {
            $this->register_handler('plugin.delegateform', array($this, 'delegate_form'));
            $this->register_handler('plugin.delegatefolders', array($this, 'delegate_folders'));

            $this->rc->output->set_env('autocomplete_max', (int)$this->rc->config->get('autocomplete_max', 15));
            $this->rc->output->set_env('autocomplete_min_length', $this->rc->config->get('autocomplete_min_length'));
            $this->rc->output->add_label('autocompletechars', 'autocompletemore');

            $this->rc->output->send('kolab_delegation.editform');
        }
    }

    /**
     * Delegation action handler
     */
    public function controller_action()
    {
        $this->add_texts('localization/');

        $engine = $this->engine();

        // Delegate delete
        if ($this->rc->action == 'plugin.delegation-delete') {
            $id    = rcube_utils::get_input_value('id', rcube_utils::INPUT_GPC);
            $error = $engine->delegate_delete($id, (bool) rcube_utils::get_input_value('acl', rcube_utils::INPUT_GPC));

            if (!$error) {
                $this->rc->output->show_message($this->gettext('deletesuccess'), 'confirmation');
                $this->rc->output->command('plugin.delegate_save_complete', array('deleted' => $id));
            }
            else {
                $this->rc->output->show_message($this->gettext($error), 'error');
            }
        }
        // Delegate add/update
        else if ($this->rc->action == 'plugin.delegation-save') {
            $id  = rcube_utils::get_input_value('id', rcube_utils::INPUT_GPC);
            $acl = rcube_utils::get_input_value('folders', rcube_utils::INPUT_GPC);

            // update
            if ($id) {
                $delegate = $engine->delegate_get($id);
                $error    = $engine->delegate_acl_update($delegate['uid'], $acl);

                if (!$error) {
                    $this->rc->output->show_message($this->gettext('updatesuccess'), 'confirmation');
                    $this->rc->output->command('plugin.delegate_save_complete', array('updated' => $id));
                }
                else {
                    $this->rc->output->show_message($this->gettext($error), 'error');
                }
            }
            // new
            else {
                $login    = rcube_utils::get_input_value('newid', rcube_utils::INPUT_GPC);
                $delegate = $engine->delegate_get_by_name($login);
                $error    = $engine->delegate_add($delegate, $acl);

                if (!$error) {
                    $this->rc->output->show_message($this->gettext('createsuccess'), 'confirmation');
                    $this->rc->output->command('plugin.delegate_save_complete', array(
                        'created' => $delegate['ID'],
                        'name'    => $delegate['name'],
                    ));
                }
                else {
                    $this->rc->output->show_message($this->gettext($error), 'error');
                }
            }
        }
        // Delegate autocompletion
        else if ($this->rc->action == 'plugin.delegation-autocomplete') {
            $search = rcube_utils::get_input_value('_search', rcube_utils::INPUT_GPC, true);
            $reqid  = rcube_utils::get_input_value('_reqid', rcube_utils::INPUT_GPC);
            $users  = $engine->list_users($search);

            $this->rc->output->command('ksearch_query_results', $users, $search, $reqid);
        }

        $this->rc->output->send();
    }

    /**
     * Template object of delegates list
     */
    public function delegate_list($attrib = array())
    {
        $attrib += array('id' => 'delegate-list');

        $engine = $this->engine();
        $list   = $engine->list_delegates();
        $table  = new html_table();

        // sort delegates list
        asort($list, SORT_LOCALE_STRING);

        foreach ($list as $id => $delegate) {
            $table->add_row(array('id' => 'rcmrow' . $id));
            $table->add(null, rcube::Q($delegate));
        }

        $this->rc->output->add_gui_object('delegatelist', $attrib['id']);
        $this->rc->output->set_env('delegatecount', count($list));

        return $table->show($attrib);
    }

    /**
     * Template object of delegate form
     */
    public function delegate_form($attrib = array())
    {
        $engine   = $this->engine();
        $table    = new html_table(array('cols' => 2));
        $id       = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GPC);
        $field_id = 'delegate';

        if ($id) {
            $delegate = $engine->delegate_get($id);
        }

        if (!empty($delegate)) {
            $input = new html_hiddenfield(array('name' => $field_id, 'id' => $field_id, 'size' => 40));
            $input = rcube::Q($delegate['name']) . $input->show($id);

            $this->rc->output->set_env('active_delegate', $id);
            $this->rc->output->command('parent.enable_command','delegate-delete', true);
        }
        else {
            $input = new html_inputfield(array('name' => $field_id, 'id' => $field_id, 'size' => 40));
            $input = $input->show();
        }

        $table->add('title', html::label($field_id, $this->gettext('delegate')));
        $table->add(null, $input);

        if ($attrib['form']) {
            $this->rc->output->add_gui_object('editform', $attrib['form']);
        }

        return $table->show($attrib);
    }

    /**
     * Template object of folders list
     */
    public function delegate_folders($attrib = array())
    {
        if (!$attrib['id']) {
            $attrib['id'] = 'delegatefolders';
        }

        $engine = $this->engine();
        $id     = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GPC);

        if ($id) {
            $delegate = $engine->delegate_get($id);
        }

        $folder_data   = $engine->list_folders(!empty($delegate) ? $delegate['uid'] : null);
        $use_fieldsets = rcube_utils::get_boolean($attrib['use-fieldsets']);
        $rights        = array();
        $folder_groups = array();

        foreach ($folder_data as $folder_name => $folder) {
            $folder_groups[$folder['type']][] = $folder_name;
            $rights[$folder_name] = $folder['rights'];
        }

        $html = '';

        // build block for every folder type
        foreach ($folder_groups as $type => $group) {
            if (empty($group)) {
                continue;
            }

            $attrib['type'] = $type;
            $table = $this->delegate_folders_block($group, $attrib, $rights);
            $label = $this->gettext($type);

            if ($use_fieldsets) {
                $html .= html::tag('fieldset', 'foldersblock', html::tag('legend', $type, $label) . $table);
            }
            else {
                $html .= html::div('foldersblock', html::tag('h3', $type, $label) . $table);
            }
        }

        $this->rc->output->add_gui_object('folderslist', $attrib['id']);

        return html::div($attrib, $html);
    }

    /**
     * List of folders in specified group
     */
    private function delegate_folders_block($a_folders, $attrib, $rights)
    {
        $path      = 'plugins/kolab_delegation/' . $this->skin_path . '/';
        $read_ico  = !empty($attrib['readicon']) ? html::img(array('src' =>  $path . $attrib['readicon'], 'title' => $this->gettext('read'))) : '';
        $write_ico = !empty($attrib['writeicon']) ? html::img(array('src' => $path . $attrib['writeicon'], 'title' => $this->gettext('write'))) : '';

        $table = new html_table(array('cellspacing' => 0, 'class' => 'table-striped'));
        $table->add_header(array('class' => 'read checkbox-cell', 'title' => $this->gettext('read'), 'tabindex' => 0), $read_ico);
        $table->add_header(array('class' => 'write checkbox-cell', 'title' => $this->gettext('write'), 'tabindex' => 0), $write_ico);
        $table->add_header('foldername', $this->rc->gettext('folder'));

        $checkbox_read  = new html_checkbox(array('name' => 'read[]', 'class' => 'read'));
        $checkbox_write = new html_checkbox(array('name' => 'write[]', 'class' => 'write'));

        $names = array();
        foreach ($a_folders as $folder) {
            $foldername = $origname = kolab_storage::object_prettyname($folder);

            // find folder prefix to truncate (the same code as in kolab_addressbook plugin)
            for ($i = count($names)-1; $i >= 0; $i--) {
                if (strpos($foldername, $names[$i].' &raquo; ') === 0) {
                    $length = strlen($names[$i].' &raquo; ');
                    $prefix = substr($foldername, 0, $length);
                    $count  = count(explode(' &raquo; ', $prefix));
                    $foldername = str_repeat('&nbsp;&nbsp;', $count-1) . '&raquo; ' . substr($foldername, $length);
                    break;
                }
            }

            $folder_id = 'rcmf' . rcube_utils::html_identifier($folder);
            $names[] = $origname;
            $classes = array('mailbox');

            if ($folder_class = $this->rc->folder_classname($folder)) {
                if ($this->rc->text_exists($folder_class)) {
                    $foldername = html::quote($this->rc->gettext($folder_class));
                }
                $classes[] = $folder_class;
            }

            $table->add_row();
            $table->add('read checkbox-cell', $checkbox_read->show(
                $rights[$folder] >= kolab_delegation_engine::ACL_READ ? $folder : null,
                array('value' => $folder)));
            $table->add('write checkbox-cell', $checkbox_write->show(
                $rights[$folder] >= kolab_delegation_engine::ACL_WRITE ? $folder : null,
                array('value' => $folder, 'id' => $folder_id)));

            $table->add(join(' ', $classes), html::label($folder_id, $foldername));
        }

        return $table->show();
    }
}
Back to Directory File Manager