roundcubemail-plugins-kolab/plugins/wap_client/wap_client.php
2024-01-25 13:47:41 +01:00

342 lines
9.5 KiB
PHP

<?php
/**
* WAP Client plugin.
*
* @version @package_version@
* @author Aleksander Machniak <machniak@kolabsys.com>
*
* Copyright (C) 2016, 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 wap_client extends rcube_plugin
{
public $task = 'settings';
public $noajax = true;
protected $rc;
protected $uri;
protected $wap;
protected $userinfo;
protected $token;
/**
* Initializes the plugin
*/
public function init()
{
$this->rc = rcube::get_instance();
$this->add_hook('preferences_list', [$this, 'prefs_table']);
$this->add_hook('preferences_save', [$this, 'save_prefs']);
}
/**
* Hook to inject plugin-specific user settings
*/
public function prefs_table($args)
{
global $CURR_SECTION;
if ($args['section'] != 'server') {
return;
}
$this->load_config();
$accounts = (array) $this->rc->config->get('wap_client_accounts');
if (empty($accounts)) {
return;
}
$account_type = null;
$this->add_texts('localization');
if ($CURR_SECTION) {
$account_type = $this->get_account_type();
$_SESSION['wap_client_account_type'] = $account_type;
}
$input = new html_radiobutton(['name' => '_account_type', 'style' => 'display:block; float:left']);
$content = '';
foreach ($accounts as $idx => $def) {
$id = 'account_type_' . strtolower(asciiwords($idx, true));
$name = $idx;
$name = $this->rc->text_exists('wap_client.account.' . $name) ? $this->gettext('account.' . $name) : $name;
$desc = $this->rc->text_exists('wap_client.accountdesc.' . $name) ? $this->gettext('accountdesc.' . $name) : $def['description'];
$name = html::span(['style' => 'font-weight: bold'], rcube::Q($name));
if ($desc) {
$name .= html::br() . html::span(null, rcube::Q($desc));
}
$label_style = 'display:block; margin: 5px 0; padding-left: 30px';
$content .= $input->show($account_type, ['value' => $idx, 'id' => $id])
. html::label(['for' => $id, 'style' => $label_style], $name);
}
$conf = [
'account' => [
'name' => rcube::Q($this->gettext('accountoptions')),
'options' => [
'account_type' => [
'title' => $this->gettext('accounttype'),
'content' => $content,
],
],
],
];
$args['blocks'] = array_merge($conf, $args['blocks']);
return $args;
}
/**
* Hook to save plugin-specific user settings
*/
public function save_prefs($args)
{
if ($args['section'] != 'server') {
return;
}
$account_type = rcube_utils::get_input_value('_account_type', rcube_utils::INPUT_POST);
if (!$account_type || $account_type == $_SESSION['wap_client_account_type']) {
return;
}
$this->add_texts('localization');
$this->set_account_type($account_type);
}
/**
* Get current account type (from WAP)
*/
protected function get_account_type()
{
$this->init_wap();
if (empty($this->userinfo)) {
$this->rc->output->show_message($this->gettext('failedtypedetection'), 'warning');
return;
}
$roles = (array) $this->userinfo['nsroledn'];
$accounts = (array) $this->rc->config->get('wap_client_accounts');
$root_dn = $this->rc->config->get('wap_client_root_dn');
$base_dn = $this->rc->config->get('wap_client_base_dn');
foreach ($accounts as $name => $account) {
foreach ((array) $account['nsroledn'] as $role) {
$role = str_replace('$base_dn', $base_dn, $role);
$role = str_replace('$root_dn', $root_dn, $role);
if (!in_array($role, $roles)) {
continue 2;
}
}
return $name;
}
}
/**
* Set account type (in WAP)
*/
protected function set_account_type($type)
{
if (!$this->init_wap()) {
return false;
}
$query = $this->userinfo;
$accounts = (array) $this->rc->config->get('wap_client_accounts');
$root_dn = $this->rc->config->get('wap_client_root_dn');
$base_dn = $this->rc->config->get('wap_client_base_dn');
$account = $accounts[$type];
if (empty($account)) {
$this->rc->output->show_message($this->gettext('failedtypeupdate'), 'warning');
return;
}
unset($account['description']);
foreach ($account as $attr => $value) {
switch ($attr) {
case 'nsroledn':
$value = [];
foreach ((array) $account['nsroledn'] as $role) {
$role = str_replace('$base_dn', $base_dn, $role);
$role = str_replace('$root_dn', $root_dn, $role);
$value[] = $role;
}
// no break
default:
$query[$attr] = $value;
}
}
$response = $this->post('user.edit', $query);
if (!$response || $response['status'] != 'OK') {
$this->rc->output->show_message($this->gettext('failedtypeupdate'), 'warning');
return;
}
$this->userinfo = $query;
}
/**
* Initialize WAP connection and user session
*/
protected function init_wap()
{
if ($this->wap) {
return $this->wap;
}
$this->load_config();
$this->require_plugin('libkolab');
$uri = $this->rc->config->get('wap_client_uri');
$user = $this->rc->get_user_name();
$pass = $this->rc->decrypt($_SESSION['password']);
if (!$uri) {
rcube::raise_error("wap_client_uri is not set", true, false);
return;
}
// get HTTP_Request2 object
$this->uri = rcube_utils::resolve_url($uri);
$this->wap = libkolab::http_request($this->uri);
$query = [
'username' => $user,
'password' => $pass,
// 'domain' => $domain,
'info' => true,
];
// authenticate the user
$response = $this->post('system.authenticate', $query);
if ($response) {
$this->userinfo = $response['result']['info'];
$this->token = $response['result']['session_token'];
}
return $this->wap;
}
/**
* API's POST request.
*
* @param string $action Action name
* @param array $post POST arguments
*
* @return array|null Response
*/
protected function post($action, $post = [])
{
$url = $this->build_url($action);
if ($this->rc->config->get('wap_client_debug')) {
$this->rc->write_log('wap', "Calling API POST: $url\n" . @json_encode($post));
}
if ($this->token) {
$this->wap->setHeader('X-Session-Token', $this->token);
}
$this->wap->setMethod(HTTP_Request2::METHOD_POST);
$this->wap->setBody(@json_encode($post));
return $this->get_response($url);
}
/**
* Build Net_URL2 object for the request
*
* @param string $action Action GET parameter
* @param array $args GET parameters (hash array: name => value)
*
* @return Net_URL2 URL object
*/
private function build_url($action, $args = [])
{
$url = rtrim($this->uri, '/');
if ($action) {
$url .= '/' . urlencode($action);
}
$url = new Net_URL2($url);
if (!empty($args)) {
$url->setQueryVariables($args);
}
return $url;
}
/**
* HTTP Response handler.
*
* @param Net_URL2 $url URL object
*
* @return array|null Response data
*/
protected function get_response($url)
{
try {
$this->wap->setUrl($url);
$response = $this->wap->send();
} catch (Exception $e) {
rcube::raise_error($e, true, false);
return null;
}
try {
$body = $response->getBody();
} catch (Exception $e) {
rcube::raise_error($e, true, false);
return null;
}
if ($this->rc->config->get('wap_client_debug')) {
$this->rc->write_log('wap', "Response:\n$body");
}
$body = @json_decode($body, true);
if (!is_array($body)) {
rcube::raise_error("Failed to decode WAP response", true, false);
return null;
}
return $body;
}
}