diff --git a/plugins/enigma/enigma.js b/plugins/enigma/enigma.js index 0d3e2390b8..da87e6cee0 100644 --- a/plugins/enigma/enigma.js +++ b/plugins/enigma/enigma.js @@ -63,6 +63,12 @@ window.rcmail && rcmail.addEventListener('init', function(evt) { }); } } + + if ($('.enigma-bg-preview').length) { + rcmail.enigma_bg_post(); + $('#rcmfd_enigma_bg_icon, #rcmfd_enigma_bg_scale, #rcmfd_enigma_bg_angle') + .on('change', function() { rcmail.enigma_bg_post(); }); + } } else if (rcmail.env.task == 'mail') { if (rcmail.env.action == 'compose') { @@ -720,3 +726,20 @@ rcube_webmail.prototype.enigma_find_publickey = function(email) } ); }; + +rcube_webmail.prototype.enigma_bg_post = function() +{ + var post = {}; + + $.each(['bg_icon', 'bg_scale', 'bg_angle'], function() { + post['_enigma_' + this] = $('#rcmfd_enigma_' + this).val(); + }); + + rcmail.http_post('plugin.enigmabg', post); +}; + +rcube_webmail.prototype.enigma_bg_update = function(style) +{ + if (rcmail.env.task == 'settings') + $('.enigma-bg-preview').children().attr('style', style); +}; diff --git a/plugins/enigma/enigma.php b/plugins/enigma/enigma.php index fda9338ba3..8cbf6316e0 100644 --- a/plugins/enigma/enigma.php +++ b/plugins/enigma/enigma.php @@ -23,8 +23,9 @@ class enigma extends rcube_plugin public $task = 'mail|settings|cli'; public $rc; public $engine; - public $ui; + private $ui; + private $settings_ui; private $env_loaded = false; @@ -42,7 +43,7 @@ function init() $this->add_hook('message_body_prefix', array($this, 'status_message')); $this->register_action('plugin.enigmaimport', array($this, 'import_file')); - $this->register_action('plugin.enigmakeys', array($this, 'preferences_ui')); + $this->register_action('plugin.enigmakeys', array($this, 'keys_ui')); // load the Enigma plugin configuration $this->load_config(); @@ -76,16 +77,25 @@ function init() $this->add_hook('preferences_save', array($this, 'preferences_save')); $this->add_hook('identity_form', array($this, 'identity_form')); + // register handler for secure background style update + $this->register_action('plugin.enigmabg', array($this, 'background_style')); + // register handler for keys/certs management - $this->register_action('plugin.enigmakeys', array($this, 'preferences_ui')); -// $this->register_action('plugin.enigmacerts', array($this, 'preferences_ui')); + $this->register_action('plugin.enigmakeys', array($this, 'keys_ui')); +// $this->register_action('plugin.enigmacerts', array($this, 'keys_ui')); $this->load_ui(); - if (empty($_REQUEST['_framed']) || strpos($this->rc->action, 'plugin.enigma') === 0) { + if (empty($_REQUEST['_framed']) || strpos($this->rc->action, 'plugin.enigma') === 0 + || $this->rc->action == 'edit-prefs' || $this->rc->action == 'save-prefs' + ) { $this->ui->add_css(); } + if ($this->rc->action == 'edit-prefs' || $this->rc->action == 'save-prefs') { + $this->ui->add_js(); + } + $this->password_handler(); } else if ($this->rc->task == 'cli') { @@ -137,6 +147,17 @@ function load_ui($all = false) } } + /** + * Plugin Settings UI initialization. + */ + function load_settings_ui() + { + if (!$this->settings_ui) { + $this->load_ui(); + $this->settings_ui = new enigma_settings($this); + } + } + /** * Plugin engine initialization. */ @@ -182,6 +203,120 @@ function part_body($p) return $this->engine->part_body($p); } + /** + * Handler for keys/certs management UI template. + */ + function keys_ui() + { + $this->load_ui(); + + $this->ui->init(); + } + + /** + * Handler for message_body_prefix hook. + * Called for every displayed (content) part of the message. + * Adds infobox about signature verification and/or decryption + * status above the body. + * + * @param array Original parameters + * + * @return array Modified parameters + */ + function status_message($p) + { + $this->load_ui(); + + return $this->ui->status_message($p); + } + + /** + * Handler for message_load hook. + * Check message bodies and attachments for keys/certs. + */ + function message_load($p) + { + $this->load_ui(); + + return $this->ui->message_load($p); + } + + /** + * Handler for template_object_messagebody hook. + * This callback function adds a box below the message content + * if there is a key/cert attachment available + */ + function message_output($p) + { + $this->load_ui(); + + return $this->ui->message_output($p); + } + + /** + * Handler for attached keys/certs import + */ + function import_file() + { + $this->load_ui(); + + $this->ui->import_file(); + } + + /** + * Handle password submissions + */ + function password_handler() + { + $this->load_engine(); + + $this->engine->password_handler(); + } + + /** + * Handle message_ready hook (encryption/signing) + */ + function message_ready($p) + { + $this->load_ui(); + + return $this->ui->message_ready($p); + } + + /** + * Handle message_compose_body hook + */ + function message_compose($p) + { + $this->load_ui(); + + return $this->ui->message_compose($p); + } + + /** + * Handler for refresh hook. + */ + function refresh($p) + { + // calling enigma_engine constructor to remove passwords + // stored in session after expiration time + $this->load_engine(); + + return $p; + } + + /** + * Handle delete_user_commit hook + */ + function user_delete($p) + { + $this->load_engine(); + + $p['abort'] = $p['abort'] || !$this->engine->delete_user_data($p['username']); + + return $p; + } + /** * Handler for settings_actions hook. * Adds Enigma settings section into preferences. @@ -242,150 +377,11 @@ function preferences_sections_list($p) */ function preferences_list($p) { - if ($p['section'] != 'enigma') { - return $p; - } - - $no_override = array_flip((array)$this->rc->config->get('dont_override')); - - $p['blocks']['main']['name'] = $this->gettext('mainoptions'); - - if (!isset($no_override['enigma_encryption'])) { - if (!$p['current']) { - $p['blocks']['main']['content'] = true; - return $p; - } - - $field_id = 'rcmfd_enigma_encryption'; - $input = new html_checkbox(array( - 'name' => '_enigma_encryption', - 'id' => $field_id, - 'value' => 1, - )); - - $p['blocks']['main']['options']['enigma_encryption'] = array( - 'title' => html::label($field_id, $this->gettext('supportencryption')), - 'content' => $input->show(intval($this->rc->config->get('enigma_encryption'))), - ); - } - - if (!isset($no_override['enigma_signatures'])) { - if (!$p['current']) { - $p['blocks']['main']['content'] = true; - return $p; - } - - $field_id = 'rcmfd_enigma_signatures'; - $input = new html_checkbox(array( - 'name' => '_enigma_signatures', - 'id' => $field_id, - 'value' => 1, - )); - - $p['blocks']['main']['options']['enigma_signatures'] = array( - 'title' => html::label($field_id, $this->gettext('supportsignatures')), - 'content' => $input->show(intval($this->rc->config->get('enigma_signatures'))), - ); - } - - if (!isset($no_override['enigma_decryption'])) { - if (!$p['current']) { - $p['blocks']['main']['content'] = true; - return $p; - } - - $field_id = 'rcmfd_enigma_decryption'; - $input = new html_checkbox(array( - 'name' => '_enigma_decryption', - 'id' => $field_id, - 'value' => 1, - )); - - $p['blocks']['main']['options']['enigma_decryption'] = array( - 'title' => html::label($field_id, $this->gettext('supportdecryption')), - 'content' => $input->show(intval($this->rc->config->get('enigma_decryption'))), - ); - } - - if (!isset($no_override['enigma_sign_all'])) { - if (!$p['current']) { - $p['blocks']['main']['content'] = true; - return $p; - } - - $field_id = 'rcmfd_enigma_sign_all'; - $input = new html_checkbox(array( - 'name' => '_enigma_sign_all', - 'id' => $field_id, - 'value' => 1, - )); - - $p['blocks']['main']['options']['enigma_sign_all'] = array( - 'title' => html::label($field_id, $this->gettext('signdefault')), - 'content' => $input->show($this->rc->config->get('enigma_sign_all') ? 1 : 0), - ); - } - - if (!isset($no_override['enigma_encrypt_all'])) { - if (!$p['current']) { - $p['blocks']['main']['content'] = true; - return $p; - } - - $field_id = 'rcmfd_enigma_encrypt_all'; - $input = new html_checkbox(array( - 'name' => '_enigma_encrypt_all', - 'id' => $field_id, - 'value' => 1, - )); - - $p['blocks']['main']['options']['enigma_encrypt_all'] = array( - 'title' => html::label($field_id, $this->gettext('encryptdefault')), - 'content' => $input->show($this->rc->config->get('enigma_encrypt_all') ? 1 : 0), - ); - } - - if (!isset($no_override['enigma_attach_pubkey'])) { - if (!$p['current']) { - $p['blocks']['main']['content'] = true; - return $p; - } - - $field_id = 'rcmfd_enigma_attach_pubkey'; - $input = new html_checkbox(array( - 'name' => '_enigma_attach_pubkey', - 'id' => $field_id, - 'value' => 1, - )); - - $p['blocks']['main']['options']['enigma_attach_pubkey'] = array( - 'title' => html::label($field_id, $this->gettext('attachpubkeydefault')), - 'content' => $input->show($this->rc->config->get('enigma_attach_pubkey') ? 1 : 0), - ); - } - - if (!isset($no_override['enigma_password_time'])) { - if (!$p['current']) { - $p['blocks']['main']['content'] = true; - return $p; - } - - $field_id = 'rcmfd_enigma_password_time'; - $select = new html_select(array('name' => '_enigma_password_time', 'id' => $field_id)); - - foreach (array(1, 5, 10, 15, 30) as $m) { - $label = $this->gettext(array('name' => 'nminutes', 'vars' => array('m' => $m))); - $select->add($label, $m); - } - $select->add($this->gettext('wholesession'), 0); + if ($p['section'] == 'enigma') { + $this->load_settings_ui(); - $p['blocks']['main']['options']['enigma_password_time'] = array( - 'title' => html::label($field_id, $this->gettext('passwordtime')), - 'content' => $select->show(intval($this->rc->config->get('enigma_password_time'))), - ); + return $this->settings_ui->preferences_list($p); } - - return $p; } /** @@ -399,28 +395,21 @@ function preferences_list($p) function preferences_save($p) { if ($p['section'] == 'enigma') { - $p['prefs'] = array( - 'enigma_signatures' => (bool) rcube_utils::get_input_value('_enigma_signatures', rcube_utils::INPUT_POST), - 'enigma_decryption' => (bool) rcube_utils::get_input_value('_enigma_decryption', rcube_utils::INPUT_POST), - 'enigma_encryption' => (bool) rcube_utils::get_input_value('_enigma_encryption', rcube_utils::INPUT_POST), - 'enigma_sign_all' => (bool) rcube_utils::get_input_value('_enigma_sign_all', rcube_utils::INPUT_POST), - 'enigma_encrypt_all' => (bool) rcube_utils::get_input_value('_enigma_encrypt_all', rcube_utils::INPUT_POST), - 'enigma_attach_pubkey' => (bool) rcube_utils::get_input_value('_enigma_attach_pubkey', rcube_utils::INPUT_POST), - 'enigma_password_time' => intval(rcube_utils::get_input_value('_enigma_password_time', rcube_utils::INPUT_POST)), - ); - } + $this->load_settings_ui(); - return $p; + return $this->settings_ui->preferences_save($p); + } } /** - * Handler for keys/certs management UI template. + * Handler for background testing action */ - function preferences_ui() + function background_style() { - $this->load_ui(); + $this->load_env(); - $this->ui->init(); + $this->rc->output->command('enigma_bg_update', enigma_settings::security_bg_style(true)); + $this->rc->output->send(); } /** @@ -442,7 +431,7 @@ function identity_form($p) if ($p['record']['email']) { $listing = array(); $engine = $this->load_engine(); - $keys = (array)$engine->list_keys($p['record']['email']); + $keys = (array) $engine->list_keys($p['record']['email']); foreach ($keys as $key) { if ($key->get_type() === enigma_key::TYPE_KEYPAIR) { @@ -456,7 +445,8 @@ function identity_form($p) if (count($listing)) { $content .= html::p(null, $this->gettext(array('name' => 'identitymatchingprivkeys', 'vars' => array('nr' => count($listing))))); $content .= html::tag('ul', 'keylist', join('\n', $listing)); - } else { + } + else { $content .= html::p(null, $this->gettext('identitynoprivkeys')); } } @@ -477,108 +467,4 @@ function identity_form($p) return $p; } - - /** - * Handler for message_body_prefix hook. - * Called for every displayed (content) part of the message. - * Adds infobox about signature verification and/or decryption - * status above the body. - * - * @param array Original parameters - * - * @return array Modified parameters - */ - function status_message($p) - { - $this->load_ui(); - - return $this->ui->status_message($p); - } - - /** - * Handler for message_load hook. - * Check message bodies and attachments for keys/certs. - */ - function message_load($p) - { - $this->load_ui(); - - return $this->ui->message_load($p); - } - - /** - * Handler for template_object_messagebody hook. - * This callback function adds a box below the message content - * if there is a key/cert attachment available - */ - function message_output($p) - { - $this->load_ui(); - - return $this->ui->message_output($p); - } - - /** - * Handler for attached keys/certs import - */ - function import_file() - { - $this->load_ui(); - - $this->ui->import_file(); - } - - /** - * Handle password submissions - */ - function password_handler() - { - $this->load_engine(); - - $this->engine->password_handler(); - } - - /** - * Handle message_ready hook (encryption/signing) - */ - function message_ready($p) - { - $this->load_ui(); - - return $this->ui->message_ready($p); - } - - /** - * Handle message_compose_body hook - */ - function message_compose($p) - { - $this->load_ui(); - - return $this->ui->message_compose($p); - } - - /** - * Handler for refresh hook. - */ - function refresh($p) - { - // calling enigma_engine constructor to remove passwords - // stored in session after expiration time - $this->load_engine(); - - return $p; - } - - /** - * Handle delete_user_commit hook - */ - function user_delete($p) - { - $this->load_engine(); - - $p['abort'] = $p['abort'] || !$this->engine->delete_user_data($p['username']); - - return $p; - } } diff --git a/plugins/enigma/lib/enigma_settings.php b/plugins/enigma/lib/enigma_settings.php new file mode 100644 index 0000000000..51aa9f9ed6 --- /dev/null +++ b/plugins/enigma/lib/enigma_settings.php @@ -0,0 +1,345 @@ + | + +-------------------------------------------------------------------------+ +*/ + +class enigma_settings +{ + protected $plugin; + protected $rc; + + // List of images (security background) - from FontAwesome + protected static $images = array( + 'lock' => '', + 'key' => '', + 'shield' => '', + 'envelope' => '', + 'user' => '', + ); + + // List of image scale options (security background) + protected static $scale_options = array( + 10, 15, 20, 25, 30, 35, 40 + ); + + // List of image angle (rotation) options (security background) + protected static $angle_options = array( + 0, 45, 90, 135, 180, 225, 270, 315 + ); + + + public function __construct($plugin) + { + $this->plugin = $plugin; + $this->rc = rcube::get_instance(); + } + + /** + * Handler for preferences_list hook. + * Adds options blocks into Enigma settings sections in Preferences. + * + * @param array Original parameters + * + * @return array Modified parameters + */ + public function preferences_list($p) + { + $no_override = array_flip((array)$this->rc->config->get('dont_override')); + + $p['blocks']['main']['name'] = $this->plugin->gettext('mainoptions'); + $p['blocks']['secbg']['name'] = $this->plugin->gettext('securitybg'); + + if (!isset($no_override['enigma_encryption'])) { + if (!$p['current']) { + $p['blocks']['main']['content'] = true; + return $p; + } + + $field_id = 'rcmfd_enigma_encryption'; + $input = new html_checkbox(array( + 'name' => '_enigma_encryption', + 'id' => $field_id, + 'value' => 1, + )); + + $p['blocks']['main']['options']['enigma_encryption'] = array( + 'title' => html::label($field_id, $this->plugin->gettext('supportencryption')), + 'content' => $input->show(intval($this->rc->config->get('enigma_encryption'))), + ); + } + + if (!isset($no_override['enigma_signatures'])) { + if (!$p['current']) { + $p['blocks']['main']['content'] = true; + return $p; + } + + $field_id = 'rcmfd_enigma_signatures'; + $input = new html_checkbox(array( + 'name' => '_enigma_signatures', + 'id' => $field_id, + 'value' => 1, + )); + + $p['blocks']['main']['options']['enigma_signatures'] = array( + 'title' => html::label($field_id, $this->plugin->gettext('supportsignatures')), + 'content' => $input->show(intval($this->rc->config->get('enigma_signatures'))), + ); + } + + if (!isset($no_override['enigma_decryption'])) { + if (!$p['current']) { + $p['blocks']['main']['content'] = true; + return $p; + } + + $field_id = 'rcmfd_enigma_decryption'; + $input = new html_checkbox(array( + 'name' => '_enigma_decryption', + 'id' => $field_id, + 'value' => 1, + )); + + $p['blocks']['main']['options']['enigma_decryption'] = array( + 'title' => html::label($field_id, $this->plugin->gettext('supportdecryption')), + 'content' => $input->show(intval($this->rc->config->get('enigma_decryption'))), + ); + } + + if (!isset($no_override['enigma_sign_all'])) { + if (!$p['current']) { + $p['blocks']['main']['content'] = true; + return $p; + } + + $field_id = 'rcmfd_enigma_sign_all'; + $input = new html_checkbox(array( + 'name' => '_enigma_sign_all', + 'id' => $field_id, + 'value' => 1, + )); + + $p['blocks']['main']['options']['enigma_sign_all'] = array( + 'title' => html::label($field_id, $this->plugin->gettext('signdefault')), + 'content' => $input->show($this->rc->config->get('enigma_sign_all') ? 1 : 0), + ); + } + + if (!isset($no_override['enigma_encrypt_all'])) { + if (!$p['current']) { + $p['blocks']['main']['content'] = true; + return $p; + } + + $field_id = 'rcmfd_enigma_encrypt_all'; + $input = new html_checkbox(array( + 'name' => '_enigma_encrypt_all', + 'id' => $field_id, + 'value' => 1, + )); + + $p['blocks']['main']['options']['enigma_encrypt_all'] = array( + 'title' => html::label($field_id, $this->plugin->gettext('encryptdefault')), + 'content' => $input->show($this->rc->config->get('enigma_encrypt_all') ? 1 : 0), + ); + } + + if (!isset($no_override['enigma_attach_pubkey'])) { + if (!$p['current']) { + $p['blocks']['main']['content'] = true; + return $p; + } + + $field_id = 'rcmfd_enigma_attach_pubkey'; + $input = new html_checkbox(array( + 'name' => '_enigma_attach_pubkey', + 'id' => $field_id, + 'value' => 1, + )); + + $p['blocks']['main']['options']['enigma_attach_pubkey'] = array( + 'title' => html::label($field_id, $this->plugin->gettext('attachpubkeydefault')), + 'content' => $input->show($this->rc->config->get('enigma_attach_pubkey') ? 1 : 0), + ); + } + + if (!isset($no_override['enigma_password_time'])) { + if (!$p['current']) { + $p['blocks']['main']['content'] = true; + return $p; + } + + $field_id = 'rcmfd_enigma_password_time'; + $select = new html_select(array('name' => '_enigma_password_time', 'id' => $field_id)); + + foreach (array(1, 5, 10, 15, 30) as $m) { + $label = $this->plugin->gettext(array('name' => 'nminutes', 'vars' => array('m' => $m))); + $select->add($label, $m); + } + $select->add($this->plugin->gettext('wholesession'), 0); + + $p['blocks']['main']['options']['enigma_password_time'] = array( + 'title' => html::label($field_id, $this->plugin->gettext('passwordtime')), + 'content' => $select->show(intval($this->rc->config->get('enigma_password_time'))), + ); + } + + if (!$p['current']) { + $p['blocks']['secbg']['content'] = true; + return $p; + } + + $prefs = self::security_bg_settings(); + + $field_id = 'rcmfd_enigma_bg_icon'; + $select = new html_select(array('name' => '_enigma_bg_icon', 'id' => $field_id)); + + foreach (array_keys(self::$images) as $icon) { + $select->add($icon, $icon); + } + + $p['blocks']['secbg']['options']['enigma_bg_icon'] = array( + 'title' => html::label($field_id, $this->plugin->gettext('bgicon')), + 'content' => $select->show($prefs['enigma_bg_icon']), + ); + + foreach (array('bg_scale' => self::$scale_options, 'bg_angle' => self::$angle_options) as $item => $list) { + $opt_name = "enigma_$item"; + $field_id = "rcmfd_$opt_name"; + $range = new html_inputfield(array('type' => 'range', 'name' => "_$opt_name", 'id' => $field_id, + 'min' => 0, 'max' => count($list)-1, 'step' => 1)); + + $p['blocks']['secbg']['options'][$opt_name] = array( + 'title' => html::label($field_id, $this->plugin->gettext(str_replace('_', '', $item))), + 'content' => $range->show((int) $prefs[$opt_name]), + ); + } + + $p['blocks']['secbg']['options']['enigma_bg_preview'] = array( + 'class' => 'enigma-bg-preview', + 'title' => html::label(null, $this->plugin->gettext('bgpreview')), + 'content' => html::div(array('id' => 'enigma-message', 'class' => 'boxconfirmation enigmanotice encrypted'), $this->plugin->gettext('samplebox')), + ); + + return $p; + } + + /** + * Handler for preferences_save hook. + * Executed on Enigma settings form submit. + * + * @param array Original parameters + * + * @return array Modified parameters + */ + public function preferences_save($p) + { + if ($p['section'] == 'enigma') { + $p['prefs'] = array( + 'enigma_signatures' => (bool) rcube_utils::get_input_value('_enigma_signatures', rcube_utils::INPUT_POST), + 'enigma_decryption' => (bool) rcube_utils::get_input_value('_enigma_decryption', rcube_utils::INPUT_POST), + 'enigma_encryption' => (bool) rcube_utils::get_input_value('_enigma_encryption', rcube_utils::INPUT_POST), + 'enigma_sign_all' => (bool) rcube_utils::get_input_value('_enigma_sign_all', rcube_utils::INPUT_POST), + 'enigma_encrypt_all' => (bool) rcube_utils::get_input_value('_enigma_encrypt_all', rcube_utils::INPUT_POST), + 'enigma_attach_pubkey' => (bool) rcube_utils::get_input_value('_enigma_attach_pubkey', rcube_utils::INPUT_POST), + 'enigma_password_time' => (int) rcube_utils::get_input_value('_enigma_password_time', rcube_utils::INPUT_POST), + 'enigma_bg_icon' => rcube_utils::get_input_value('_enigma_bg_icon', rcube_utils::INPUT_POST), + 'enigma_bg_scale' => (int) rcube_utils::get_input_value('_enigma_bg_scale', rcube_utils::INPUT_POST), + 'enigma_bg_angle' => (int) rcube_utils::get_input_value('_enigma_bg_angle', rcube_utils::INPUT_POST), + ); + + if (!preg_match('/^[a-z]+$/', $p['prefs']['enigma_bg_icon'])) { + unset($p['prefs']['enigma_bg_icon']); + } + } + + return $p; + } + + /** + * Get the security background configuration. If there's no configuration + * we'll generate random values and save them as user preferences. + * + * @return array Configuration options + */ + protected static function security_bg_settings() + { + $rcube = rcube::get_instance(); + + $prefs = array( + 'enigma_bg_icon' => $rcube->config->get('enigma_bg_icon'), + 'enigma_bg_scale' => $rcube->config->get('enigma_bg_scale'), + 'enigma_bg_angle' => $rcube->config->get('enigma_bg_angle'), + ); + + if (empty($prefs['enigma_bg_icon'])) { + $images = array_keys(self::$images); + + $prefs['enigma_bg_icon'] = $images[mt_rand(0, count($images)-1)]; + $prefs['enigma_bg_scale'] = mt_rand(0, count(self::$scale_options)-1); + $prefs['enigma_bg_angle'] = mt_rand(0, count(self::$angle_options)-1); + + $rcube->user->save_prefs($prefs); + } + + return $prefs; + } + + /** + * Generate css rule with security background + * + * @param bool $post Replace user preferences with POST arguments + * + * @return string CSS rule + */ + public static function security_bg_style($post = false) + { + // get user preferences + $prefs = self::security_bg_settings(); + + // use POSTed values (testing background in Preferences > Encryption) + if ($post) { + if (isset($_POST['_enigma_bg_icon'])) { + $prefs['enigma_bg_icon'] = rcube_utils::get_input_value('_enigma_bg_icon', rcube_utils::INPUT_POST); + } + if (isset($_POST['_enigma_bg_scale'])) { + $prefs['enigma_bg_scale'] = (int) rcube_utils::get_input_value('_enigma_bg_scale', rcube_utils::INPUT_POST); + } + if (isset($_POST['_enigma_bg_angle'])) { + $prefs['enigma_bg_angle'] = (int) rcube_utils::get_input_value('_enigma_bg_angle', rcube_utils::INPUT_POST); + } + } + + $angle = self::$angle_options[$prefs['enigma_bg_angle']]; + $scale = self::$scale_options[$prefs['enigma_bg_scale']] ?: 10; + $icon = self::$images[$prefs['enigma_bg_icon']] ?: self::$images['lock']; + + // Get image viewport size for rotation arguments + $width = $height = 256; + if (preg_match('/viewbox="[0-9]+ [0-9]+ ([0-9]+) ([0-9]+)"/i', $icon, $m)) { + $width = intval($m[1] / 2); + $height = intval($m[2] / 2); + } + + // Modify the background image: + // - apply angle (rotation) + // - scale the image to get a nice margin around it + // - apply semi-transparent color + $icon = str_replace('add('title', $option['title']); - $table->add(null, $option['content']); + $table->add($option['class'], $option['content']); } else { $table->add(array('colspan' => 2), $option['content']); diff --git a/skins/elastic/ui.js b/skins/elastic/ui.js index a13903b00a..b536b52afb 100644 --- a/skins/elastic/ui.js +++ b/skins/elastic/ui.js @@ -796,9 +796,10 @@ function rcube_elastic_ui() } // Forms - var supported_controls = 'input:not(.button,.no-bs,[type=button],[type=radio],[type=checkbox]),textarea'; + var supported_controls = 'input:not(.button,.no-bs,[type=button],[type=radio],[type=range],[type=checkbox]),textarea'; $(supported_controls, $('.propform', context)).addClass('form-control'); $('[type=checkbox]', $('.propform', context)).addClass('form-check-input'); + $('[type=range]', $('.propform', context)).addClass('custom-range'); // Note: On selects we add form-control to get consistent focus // and to not have to create separate rules for selects and inputs