pax_global_header00006660000000000000000000000064131633612060014513gustar00rootroot0000000000000052 comment=e6ebf6ba0d5c5813824b0673c0989911c22777c3 roundcube-sauserprefs-1.17.1/000077500000000000000000000000001316336120600161305ustar00rootroot00000000000000roundcube-sauserprefs-1.17.1/.gitignore000066400000000000000000000000171316336120600201160ustar00rootroot00000000000000config.inc.php roundcube-sauserprefs-1.17.1/CHANGELOG000066400000000000000000000117221316336120600173450ustar00rootroot00000000000000Roundcube Webmail SAUserPrefs ============================= Version 1.17.1 (2017-09-29, rc-1.3) ================================================= * Fix bug saving locales/langs options * Correct error message text from storage class (#39) Version 1.17 (2017-06-14, rc-1.3) ================================================= * "Flattened" the larry theme: fresher look by removing shadows and gradients Version 1.16 (2017-01-02, rc-1.1) ================================================= * More fixes for bayes learn thresholds * Correct PHP warning when no address rules defined Version 1.15 (2015-04-02, rc-1.1) ================================================= * Add plugin hook sauserprefs_sections_list * Add plugin hook sauserprefs_section_name * Add plugin hook sauserprefs_list * Remove unnecessary config option sauserprefs_bayes_delete * Depreciate config option sauserprefs_whitelist_sync * Depreciate config option sauserprefs_whitelist_abook_id * Split address book sync and import options * Allow for syncing and importing of multiple address books * Improve extensibility of storage class (again) * Fix setting default score for bayes learn thresholds Version 1.14 (2015-01-06, rc-1.1) ================================================= * Fix setting requried_score to default * Improve extensibility of storage class, add override options * Update after dev-accessibility merged to RC master * Drop IE6 support Version 1.13 (2014-03-30, rc-1.0) ================================================= * Support the address format *.exmaple.com for black/white listing * Make address and langs tables user sortable Version 1.12.1 (2014-01-30, rc-1.0) ================================================= * Fix default setting for fold headers option (typo) * Correct skin folder structure for Roundcube packaging Version 1.12 (2013-12-01, rc-1.0) ================================================= * Use new settings_actions hook to create settings tab (c49c35c) * Update config file var names to match core Version 1.11 (2013-05-19, rc-1.0) ================================================= * Change file structure to match core and use include_path **** code branching/tagging no longer sync'd to roundcube versions **** Version 1.10 (2013-03-03, rc-0.9) ================================================= * merge PDO branch (de56ea1909) * rename default skin to classic (c40419bdfe) * rcube_ui > rcube_utils (r6091) * Update for Roundcube framework Version 1.9 (2012-07-07, rc-0.8) ================================================= * Versoin ready for rc-0.8 Version 1.8 (2012-04-08, rc-0.8) ================================================= * Make storage class to handle SQL work * Add new config option sauserprefs_bayes_delete to seperate function from SQL * Remove sauserprefs_deprecated_prefs config option * Make username configurable Version 1.7 (2012-01-22, rc-0.8) ================================================= * Add inital support for Larry Version 1.6 (2011-12-04, rc-0.7) ================================================= * Use core function to sanitize input * Add plugin hook sauserprefs_save * Fix double request when clicking on tab using Firefox (from r4472) * Seperate ok_locales and ok_langs Version 1.5 (2011-01-14, rc-0.5) ================================================= * Update hooks (r3883) Version 1.4 (2010-08-16, rc-0.4) ================================================= * Update hooks (r3840) Version 1.3 (2010-08-01, rc-0.4) ================================================= * Skin update after r3757 * Use core config function (WARNING: Complete re-write of config file!) Version 1.2 (2009-11-04, rc-0.4) ================================================= * Bug fix: remove error message when saving without changes * Allow disabling of entire sections via dont_override * Allow whitelist to synchronise with any address book * Make GLOBAL users configable * Allow overriding of prefs name in db (deprecated_prefs) * Fix localisation of scores Version 1.0 (2009-09-23, rc-0.3) ================================================= * Added panel for Bayes settings * Replace general_settings config option with dont_override * Added contextual help * Re-designed interface to match User Preferences * Added 'Default Score' option to spam score dropdown * Added 'Other' option to spam score dropdown (if value is not in the available options) * Added ability to restore spam settings to default * Remove deprecated pref requred_hits and replace with requred_score * Swap split() for explode(), PHP 5.3 compatibility * Added invert message language selection * Added delete icon * Added support for plugin template system * Removed display_order config var, this is now controlled from the template * Added new contact add/save/delete hooks * Removed need for contact_id field in prefs table * Added import and delete all functions for address rules * Small changes to init functions for when labels are added to UI * Translated from sauserprefs patchroundcube-sauserprefs-1.17.1/README.md000066400000000000000000000113611316336120600174110ustar00rootroot00000000000000Roundcube Webmail SAUserPrefs ============================= This plugin adds the ability for users to edit they SpamAssassin user prefs from within Roundcube. It interacts with preferences storied in a database via SQL. For more information on setting up SpamAssassin to work with a database please see the [SpamAssassin Wiki][usingsql]. Tested with SpamAssassin Version 3.3 Inspiration for this plugin was taken from: [WebUserPrefs][webuserprefs] License ------- This plugin is released under the [GNU General Public License Version 3+][gpl]. Even if skins might contain some programming work, they are not considered as a linked part of the plugin and therefore skins DO NOT fall under the provisions of the GPL license. See the README file located in the core skins folder for details on the skin license. Install ------- * Place this plugin folder into plugins directory of Roundcube * Add sauserprefs to $config['plugins'] in your Roundcube config **NB:** When downloading the plugin from GitHub you will need to create a directory called sauserprefs and place the files in there, ignoring the root directory in the downloaded archive. Config ------ The default config file is plugins/sauserprefs/config.inc.php.dist Rename this to plugins/sauserprefs/config.inc.php * You must set the database connection string * Enter the table name, name of the username field, preference field, and value field Changing the order of the sections ---------------------------------- To change the order of the sections add a sections attribute with the sections listed in the desired order to the sasectionslist object in skins/[skin]/templates/sauserprefs.html. For example: ```html ``` Delete user bayesian data stored in database -------------------------------------------- If the bayesian data is stored in the same database as the user prefs then it is possible for users to delete their data from the UI. See config file for example SQL "SERVICE CURRENTLY NOT AVAILABLE! Error No. [500]" Error Message ---------------------------------------------------------------- On some setups users might see "SERVICE CURRENTLY NOT AVAILABLE! Error No. [500]" shows up at the top of the sauserprefs screen. In this case there could be a problem with the database connection. Try adding ?new_link=true to the end of the sauserprefs DSN in the config file. For example: ```php $config['sauserprefs_db_dsnw'] = 'mysql://username:password@localhost/database?new_link=true'; ``` sauserprefs_save hook --------------------- Before prefs are saved to the database the plugin hook sauserprefs_save is executed, this allows you to perform any custom actions like extra validation or setting specific values. Arguments: * section: (string) current prefs section * cur_prefs: (array) the current user preferences * new_prefs: (array) the new preferences * global_prefs: (array) the global preferences Return: * new_prefs: (array) the new preferences * abort: (boolean) if true the prefs will not be saved * message: (string) optional reason why the prefs were not saved which will be shown to the user sauserprefs_sections_list hook ------------------------------ This allows you to modify the sections list. Arguments: * list: (array) the current setions array * cols: (array) column names to display Return: * list: (array) the new setions array * cols: (array) column names to display sauserprefs_section_name hook ----------------------------- This allows you to modify the title displayed at top of the preferences screen. Arguments: * section: (string) selected section of the prefs * title: (string) the title for the current section Return: * title: (string) the title for the current section sauserprefs_list hook --------------------- This allows you to modify the elements of the preferences screen before they are displayed. Arguments: * section: (string) selected section of the prefs * block: (array) array containing preferences blocks/options Return: * block: (array) array containing preferences blocks/options Replacing the storage class --------------------------- To replace the default sql storage class with your own you need to set a special config options: * sauserprefs_storage: (string) the suffix of the storage class e.g. 'sql' for the default sql storage class The Roundcube config object is passed to the constructor of the class [usingsql]: http://wiki.apache.org/spamassassin/UsingSQL [webuserprefs]: http://sourceforge.net/projects/webuserprefs/ [rcplugrepo]: http://plugins.roundcube.net/packages/johndoh/sauserprefs [releases]: http://github.com/JohnDoh/Roundcube-Plugin-SpamAssassin-User-Prefs-SQL/releases [gpl]: http://www.gnu.org/licenses/gpl.htmlroundcube-sauserprefs-1.17.1/composer.json000066400000000000000000000013131316336120600206500ustar00rootroot00000000000000{ "name": "johndoh/sauserprefs", "description": "Control SpamAssassin settings from within Roundcube", "keywords": ["spamassassin","preferences"], "homepage": "http://github.com/JohnDoh/Roundcube-Plugin-SpamAssassin-User-Prefs-SQL/", "license": "GPL-3.0", "type": "roundcube-plugin", "version": "1.17.1", "authors": [ { "name": "Philip Weir", "email": "roundcube@tehinterweb.co.uk", "role": "Developer" } ], "repositories": [ { "type": "composer", "url": "http://plugins.roundcube.net" } ], "require": { "php": ">=5.2.1", "roundcube/plugin-installer": ">=0.1.2" }, "extra": { "roundcube": { "min-version": "1.3" } } }roundcube-sauserprefs-1.17.1/config.inc.php.dist000066400000000000000000000140731316336120600216250ustar00rootroot00000000000000 "5", "rewrite_header Subject" => "*****SPAM*****", "ok_languages" => "all", "ok_locales" => "all", "fold_headers" => "1", "add_header all Level" => "_STARS(*)_", "use_razor1" => "0", "use_razor2" => "1", "use_pyzor" => "1", "use_dcc" => "1", "use_bayes" => "1", "skip_rbl_checks" => "0", "report_safe" => "1", "bayes_auto_learn" => "1", "bayes_auto_learn_threshold_nonspam" => "0.1", "bayes_auto_learn_threshold_spam" => "12.0", "use_bayes_rules" => "1" ); // spam score increment - increment values in the the score threshold drop down by this, from 0 to 10 $config['sauserprefs_score_inc'] = 1; // delete user bayesian data stored in database // the query can contain the following macros that will be expanded as follows: // %u is replaced with the username from the sauserprefs_userid setting above // use an array to run multiple queries // set to null to disable this option // eg. $config['sauserprefs_bayes_delete_query'] = array( // 'DELETE FROM bayes_seen WHERE id IN (SELECT id FROM bayes_vars WHERE username = %u);', // 'DELETE FROM bayes_token WHERE id IN (SELECT id FROM bayes_vars WHERE username = %u);', // 'DELETE FROM bayes_vars WHERE username = %u;', // ); $config['sauserprefs_bayes_delete_query'] = null; // define languages $config['sauserprefs_languages'] = array( "af" => "Afrikaans", "sq" => "Albanian", "am" => "Amharic", "ar" => "Arabic", "hy" => "Armenian", "eu" => "Basque", "bs" => "Bosnian", "bg" => "Bulgarian", "be" => "Byelorussian", "ca" => "Catalan", "zh" => "Chinese", "hr" => "Croatian", "cs" => "Czech", "da" => "Danish", "nl" => "Dutch", "en" => "English", "eo" => "Esperanto", "et" => "Estonian", "fi" => "Finnish", "fr" => "French", "fy" => "Frisian", "ka" => "Georgian", "de" => "German", "el" => "Greek", "he" => "Hebrew", "hi" => "Hindi", "hu" => "Hungarian", "is" => "Icelandic", "id" => "Indonesian", "ga" => "Irish Gaelic", "it" => "Italian", "ja" => "Japanese", "ko" => "Korean", "la" => "Latin", "lv" => "Latvian", "lt" => "Lithuanian", "ms" => "Malay", "mr" => "Marathi", "ne" => "Nepali", "no" => "Norwegian", "fa" => "Persian", "pl" => "Polish", "pt" => "Portuguese", "qu" => "Quechua", "rm" => "Rhaeto-Romance", "ro" => "Romanian", "ru" => "Russian", "sa" => "Sanskrit", "sco" => "Scots", "gd" => "Scottish Gaelic", "sr" => "Serbian", "sk" => "Slovak", "sl" => "Slovenian", "es" => "Spanish", "sw" => "Swahili", "sv" => "Swedish", "tl" => "Tagalog", "ta" => "Tamil", "th" => "Thai", "tr" => "Turkish", "uk" => "Ukrainian", "vi" => "Vietnamese", "cy" => "Welsh", "yi" => "Yiddish" ); roundcube-sauserprefs-1.17.1/lib/000077500000000000000000000000001316336120600166765ustar00rootroot00000000000000roundcube-sauserprefs-1.17.1/lib/Roundcube/000077500000000000000000000000001316336120600206245ustar00rootroot00000000000000roundcube-sauserprefs-1.17.1/lib/Roundcube/rcube_sauserprefs_storage_sql.php000066400000000000000000000173051316336120600274700ustar00rootroot00000000000000db_dsnw = $config->get('sauserprefs_db_dsnw'); $this->db_dsnr = $config->get('sauserprefs_db_dsnr'); $this->db_persistent = $config->get('sauserprefs_db_persistent'); $this->table_name = $config->get('sauserprefs_sql_table_name'); $this->username_field = $config->get('sauserprefs_sql_username_field'); $this->preference_field = $config->get('sauserprefs_sql_preference_field'); $this->value_field = $config->get('sauserprefs_sql_value_field'); $this->bayes_delete_query = $config->get('sauserprefs_bayes_delete_query'); } function load_prefs($user) { $this->_db_connect('r'); $prefs = array(); $sql_result = $this->db->query( "SELECT `{$this->preference_field}`, `{$this->value_field}` FROM `{$this->table_name}` WHERE `{$this->username_field}` = ?;", $user); while ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) { $pref_name = $sql_arr[$this->preference_field]; $pref_name = sauserprefs::map_pref_name($pref_name); $pref_value = $sql_arr[$this->value_field]; if ($pref_name == 'whitelist_from' || $pref_name == 'blacklist_from' || $pref_name == 'whitelist_to') $prefs['addresses'][] = array('field' => $pref_name, 'value' => $pref_value); else $prefs[$pref_name] = $pref_value; // update deprecated prefs in db if ($sql_arr[$this->preference_field] != $pref_name) { $this->_db_connect('w'); $this->db->query( "UPDATE `{$this->table_name}` SET `{$this->preference_field}` = ? WHERE `{$this->username_field}` = ? AND `{$this->preference_field}` = ?;", sauserprefs::map_pref_name($pref_name), $user, $sql_arr[$this->preference_field]); } } return $prefs; } function save_prefs($user_id, $new_prefs, $cur_prefs, $global_prefs) { $result = true; // process prefs $actions = array(); foreach ($new_prefs as $preference => $value) { if ($preference == 'addresses') { foreach ($value as $address) { $actions[$address['action']][] = $address; } } elseif (array_key_exists($preference, $cur_prefs) && ($value == "" || $value == $global_prefs[$preference])) { $actions['DELETE'][] = array('field' => $preference, 'value' => null); } elseif (array_key_exists($preference, $cur_prefs) && $value != $cur_prefs[$preference]) { $actions['UPDATE'][] = array('field' => $preference, 'value' => $value); } elseif (!array_key_exists($preference, $cur_prefs) && $value != $global_prefs[$preference]) { $actions['INSERT'][] = array('field' => $preference, 'value' => $value); } } if (count($actions) > 0) { $this->_db_connect('w'); $result = false; foreach ($actions as $type => $prefs) { foreach ($prefs as $pref) { if ($type == 'INSERT') { $this->db->query( "INSERT INTO `{$this->table_name}` (`{$this->username_field}`, `{$this->preference_field}`, `{$this->value_field}`) VALUES (?, ?, ?);", $user_id, $pref['field'], $pref['value']); $result = $this->db->affected_rows(); if (!$result) { rcube::write_log('errors', 'sauserprefs error: cannot insert "' . $pref['field'] . '" = "' . $pref['value'] . '" for ' . $user_id); break; } } elseif ($type == 'UPDATE') { $this->db->query( "UPDATE `{$this->table_name}` SET `{$this->value_field}` = ? WHERE `{$this->username_field}` = ? AND `{$this->preference_field}` = ?;", $pref['value'], $user_id, $pref['field']); $result = $this->db->affected_rows(); if (!$result) { rcube::write_log('errors', 'sauserprefs error: cannot update "' . $pref['field'] . '" = "' . $pref['value'] . '" for ' . $user_id); break; } } elseif ($type == 'DELETE') { if ($pref['value']) { $this->db->query( "DELETE FROM `{$this->table_name}` WHERE `{$this->username_field}` = ? AND `{$this->preference_field}` = ? AND `{$this->value_field}` = ?;", $user_id, $pref['field'], $pref['value']); $result = $this->db->affected_rows(); if (!$result) { rcube::write_log('errors', 'sauserprefs error: cannot delete "' . $pref['field'] . '" = "' . $pref['value'] . '" for ' . $user_id); break; } } else { $this->db->query( "DELETE FROM `{$this->table_name}` WHERE `{$this->username_field}` = ? AND `{$this->preference_field}` = ?;", $user_id, $pref['field']); $result = $this->db->affected_rows(); if (!$result) { rcube::write_log('errors', 'sauserprefs error: cannot delete "' . $pref['field'] . '" for ' . $user_id); break; } } } } } } return $result; } function whitelist_add($user_id, $emails) { $this->_db_connect('w'); foreach ($emails as $email) { // check address is not already whitelisted $sql_result = $this->db->query( "SELECT `{$this->value_field}` FROM `{$this->table_name}` WHERE `{$this->username_field}` = ? AND `{$this->preference_field}` = ? AND `{$this->value_field}` = ?;", $user_id, sauserprefs::map_pref_name('whitelist_from'), $email); if (!$this->db->fetch_array($sql_result)) $this->db->query( "INSERT INTO `{$this->table_name}` (`{$this->username_field}`, `{$this->preference_field}`, `{$this->value_field}`) VALUES (?, ?, ?);", $user_id, sauserprefs::map_pref_name('whitelist_from'), $email); } } function whitelist_delete($user_id, $emails) { $this->_db_connect('w'); foreach ($emails as $email) { $this->db->query( "DELETE FROM `{$this->table_name}` WHERE `{$this->username_field}` = ? AND `{$this->preference_field}` = ? AND `{$this->value_field}` = ?;", $user_id, sauserprefs::map_pref_name('whitelist_from'), $email); } } function purge_bayes($user_id) { $result = false; $this->_db_connect('w'); $queries = !is_array($this->bayes_delete_query) ? array($this->bayes_delete_query) : $this->bayes_delete_query; foreach ($queries as $sql) { $sql = str_replace('%u', $this->db->quote($user_id, 'text'), $sql); $this->db->query($sql); if ($this->db->is_error()) break; } if (!$this->db->is_error()) $result = true; return $result; } private function _db_connect($mode) { if (!$this->db) $this->db = rcube_db::factory($this->db_dsnw, $this->db_dsnr, $this->db_persistent); $this->db->set_debug((bool)rcube::get_instance()->config->get('sql_debug')); $this->db->db_connect($mode); // check DB connections and exit on failure if ($err_str = $this->db->is_error()) { rcube::raise_error(array( 'code' => 603, 'type' => 'db', 'message' => $err_str), false, true); } } } ?>roundcube-sauserprefs-1.17.1/localization/000077500000000000000000000000001316336120600206205ustar00rootroot00000000000000roundcube-sauserprefs-1.17.1/localization/cs_CZ.inc000066400000000000000000000172641316336120600223260ustar00rootroot00000000000000 -1 || rcmail.env.ok_languages == "all") { langlist[i].checked = true; obj = rcube_find_object('spam_lang_' + i); obj.title = rcmail.get_label('enabled','sauserprefs'); obj.className = 'enabled'; } } // Tests if (rcube_find_object('rcmfd_spamuserazor1')) { if (rcmail.env.use_razor1 == '1') rcube_find_object('rcmfd_spamuserazor1').checked = true; else rcube_find_object('rcmfd_spamuserazor1').checked = false; } if (rcube_find_object('rcmfd_spamuserazor2')) { if (rcmail.env.use_razor2 == '1') rcube_find_object('rcmfd_spamuserazor2').checked = true; else rcube_find_object('rcmfd_spamuserazor2').checked = false; } if (rcube_find_object('rcmfd_spamusepyzor')) { if (rcmail.env.use_pyzor == '1') rcube_find_object('rcmfd_spamusepyzor').checked = true; else rcube_find_object('rcmfd_spamusepyzor').checked = false; } if (rcube_find_object('rcmfd_spamusedcc')) { if (rcmail.env.use_dcc == '1') rcube_find_object('rcmfd_spamusedcc').checked = true; else rcube_find_object('rcmfd_spamusedcc').checked = false; } if (rcube_find_object('rcmfd_spamskiprblchecks')) { if (rcmail.env.skip_rbl_checks == '0') rcube_find_object('rcmfd_spamskiprblchecks').checked = true; else rcube_find_object('rcmfd_spamskiprblchecks').checked = false; } // Bayes if (rcube_find_object('rcmfd_spamusebayes')) { if (rcmail.env.use_bayes == '1') rcube_find_object('rcmfd_spamusebayes').checked = true; else rcube_find_object('rcmfd_spamusebayes').checked = false; } if (rcube_find_object('rcmfd_spambayesautolearn')) { if (rcmail.env.bayes_auto_learn == '1') rcube_find_object('rcmfd_spambayesautolearn').checked = true; else rcube_find_object('rcmfd_spambayesautolearn').checked = false; } if (rcube_find_object('rcmfd_bayesnonspam')) rcube_find_object('rcmfd_bayesnonspam').selectedIndex = 0; if (rcube_find_object('rcmfd_bayesspam')) rcube_find_object('rcmfd_bayesspam').selectedIndex = 0; if (rcube_find_object('rcmfd_spambayesrules')) { if (rcmail.env.use_bayes_rules == '1') rcube_find_object('rcmfd_spambayesrules').checked = true; else rcube_find_object('rcmfd_spambayesrules').checked = false; } // Headers if (rcube_find_object('rcmfd_spamfoldheaders')) { if (rcmail.env.fold_headers == '1') rcube_find_object('rcmfd_spamfoldheaders').checked = true; else rcube_find_object('rcmfd_spamfoldheaders').checked = false; } if (rcube_find_object('rcmfd_spamlevelstars')) { if (rcmail.env.add_header_all_Level != '') { rcube_find_object('rcmfd_spamlevelstars').checked = true; rcube_find_object('rcmfd_spamlevelchar').value = rcmail.env.add_header_all_Level.substr(7, 1); } else { rcube_find_object('rcmfd_spamlevelstars').checked = false; rcube_find_object('rcmfd_spamlevelchar').value = "*"; } } // Report if (rcube_find_object('rcmfd_spamreport_0')) { if (rcmail.env.report_safe == '0') rcube_find_object('rcmfd_spamreport_0').checked = true; else rcube_find_object('rcmfd_spamreport_0').checked = false; } if (rcube_find_object('rcmfd_spamreport_1')) { if (rcmail.env.report_safe == '1') rcube_find_object('rcmfd_spamreport_1').checked = true; else rcube_find_object('rcmfd_spamreport_1').checked = false; } if (rcube_find_object('rcmfd_spamreport_2')) { if (rcmail.env.report_safe == '2') rcube_find_object('rcmfd_spamreport_2').checked = true; else rcube_find_object('rcmfd_spamreport_2').checked = false; } // Delete whitelist if (rcube_find_object('address-rules-table')) { $.each($('#address-rules-table tbody tr:visible'), function() { var actField = $(this).find('input[name="_address_rule_act[]"]'); if (actField.val() == "INSERT") { $(this).remove(); } else { actField.val('DELETE'); $(this).hide().appendTo('#address-rules-table tbody'); } rcmail.env.address_rule_count--; }); if ($('#address-rules-table tbody tr:visible').length == 0) $('#address-rules-table tbody tr.noaddressrules').show(); } } }, true); rcmail.register_command('plugin.sauserprefs.table_sort', function(props, obj) { var id = props; var idx = $(obj).parent('th').index(); var asc = !$(obj).parent('th').hasClass('sortedASC'); rcmail.sauserprefs_table_sort(id, idx, asc); $(obj).parents('thead:first').find('th').removeClass('sortedASC').removeClass('sortedDESC'); if (asc) { $(obj).parent('th').addClass('sortedASC'); $(obj).parent('th').removeClass('sortedDESC'); } else { $(obj).parent('th').removeClass('sortedASC'); $(obj).parent('th').addClass('sortedDESC'); } rcmail.env.sauserprefs_sort[id] = [idx, asc]; rcmail.save_pref({name: 'sauserprefs_sort', value: rcmail.env.sauserprefs_sort, env: true}); return false; }, true); rcmail.enable_command('plugin.sauserprefs.save','plugin.sauserprefs.default', true); } }); if (rcmail.env.action == 'plugin.sauserprefs') { rcmail.section_select = function(list) { var id = list.get_single_selection() if (id) { var add_url = ''; var target = window; this.set_busy(true); if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) { add_url = '&_framed=1'; target = window.frames[this.env.contentframe]; } target.location.href = this.env.comm_path + '&_action=plugin.sauserprefs.edit&_section=' + id + add_url; } return true; } } } });roundcube-sauserprefs-1.17.1/sauserprefs.php000066400000000000000000001363731316336120600212200ustar00rootroot00000000000000 'required_score'); // old => new function init() { $rcmail = rcube::get_instance(); $this->load_config(); $this->sa_user = $rcmail->config->get('sauserprefs_userid', "%u"); $identity_arr = $rcmail->user->get_identity(); $identity = $identity_arr['email']; $this->sa_user = str_replace('%u', $_SESSION['username'], $this->sa_user); $this->sa_user = str_replace('%l', $rcmail->user->get_username('local'), $this->sa_user); $this->sa_user = str_replace('%d', $rcmail->user->get_username('domain'), $this->sa_user); $this->sa_user = str_replace('%i', $identity, $this->sa_user); // backwards compatibility sauserprefs_whitelist_abook_id and sauserprefs_whitelist_sync removed 20150117 if ($rcmail->config->get('sauserprefs_whitelist_sync', false)) { $this->addressbook_sync = array($rcmail->config->get('sauserprefs_whitelist_abook_id'), 0); $this->addressbook_import = array($rcmail->config->get('sauserprefs_whitelist_abook_id'), 0); } $abook_sync = $rcmail->config->get('sauserprefs_abook_sync'); if ($abook_sync === true) { $this->addressbook_sync = array(0); } elseif ($abook_sync !== false) { $this->addressbook_sync = !is_array($abook_sync) ? array($abook_sync) : $abook_sync; } $abook_import = $rcmail->config->get('sauserprefs_abook_import'); if ($abook_import === true) { $this->addressbook_import = array(0); } elseif ($abook_import !== false) { $this->addressbook_import = !is_array($abook_import) ? array($abook_import) : $abook_import; } $this->bayes_query = $rcmail->config->get('sauserprefs_bayes_delete_query'); // backwards compatibility sauserprefs_bayes_delete removed 20150117 if ($rcmail->config->get('sauserprefs_bayes_delete') === false) $this->bayes_query = null; if ($rcmail->task == 'settings') { $this->add_texts('localization/'); $this->include_stylesheet($this->local_skin_path() . '/tabstyles.css'); $this->sections = array( 'general' => array('id' => 'general', 'class' => 'general', 'section' => $this->gettext('spamgeneralsettings')), 'tests' => array('id' => 'tests', 'class' => 'tests', 'section' => $this->gettext('spamtests')), 'bayes' => array('id' => 'bayes', 'class' => 'bayes', 'section' => $this->gettext('bayes')), 'headers' => array('id' => 'headers', 'class' => 'headers','section' => $this->gettext('headers')), 'report' => array('id' => 'report', 'class' => 'report','section' => $this->gettext('spamreportsettings')), 'addresses' => array('id' => 'addresses', 'class' => 'addresses', 'section' => $this->gettext('spamaddressrules')), ); $this->cur_section = rcube_utils::get_input_value('_section', rcube_utils::INPUT_GPC); $this->add_hook('settings_actions', array($this, 'settings_tab')); $this->register_action('plugin.sauserprefs', array($this, 'init_html')); $this->register_action('plugin.sauserprefs.edit', array($this, 'init_html')); $this->register_action('plugin.sauserprefs.save', array($this, 'save')); $this->register_action('plugin.sauserprefs.whitelist_import', array($this, 'whitelist_import')); $this->register_action('plugin.sauserprefs.purge_bayes', array($this, 'purge_bayes')); if (strpos($rcmail->action, 'plugin.sauserprefs') === 0) { $this->include_script('sauserprefs.js'); } } elseif (count($this->addressbook_sync) > 0) { $this->add_hook('contact_create', array($this, 'contact_add')); $this->add_hook('contact_update', array($this, 'contact_save')); $this->add_hook('contact_delete', array($this, 'contact_delete')); } } function settings_tab($p) { // add sauserprefs tab $p['actions'][] = array('action' => 'plugin.sauserprefs', 'class' => 'sauserprefs', 'label' => 'sauserprefs.sauserprefs', 'title' => 'sauserprefs.managespam', 'role' => 'button', 'aria-disabled' => 'false', 'tabindex' => '0'); return $p; } function init_html() { $this->_init_storage(); $this->_load_global_prefs(); $this->_load_user_prefs(); $this->api->output->set_pagetitle($this->gettext('sauserprefssettings')); if (rcube::get_instance()->action == 'plugin.sauserprefs.edit') { $this->api->output->include_script('list.js'); $this->user_prefs = array_merge($this->global_prefs, $this->user_prefs); $this->api->output->add_handler('userprefs', array($this, 'gen_form')); $this->api->output->add_handler('sectionname', array($this, 'prefs_section_name')); $this->api->output->send('sauserprefs.settingsedit'); } else { $this->api->output->add_handler('sasectionslist', array($this, 'section_list')); $this->api->output->add_handler('saprefsframe', array($this, 'preference_frame')); $this->api->output->send('sauserprefs.sauserprefs'); } } function section_list($attrib) { $rcmail = rcube::get_instance(); $no_override = array_flip(rcube::get_instance()->config->get('sauserprefs_dont_override')); // add id to message list table if not specified if (!strlen($attrib['id'])) $attrib['id'] = 'rcmsectionslist'; $sections = array(); // if template overrides default array then rebuild the array in the new order if (isset($attrib['sections'])) { $new_sections = array(); $keys = preg_split('/[\s,;]+/', str_replace(array("'", '"'), '', $attrib['sections'])); foreach ($keys as $key) { $new_sections[] = $this->sections[$key]; } $this->sections = $new_sections; } $data = rcube::get_instance()->plugins->exec_hook('sauserprefs_sections_list', array('list' => $this->sections, 'cols' => array('section'))); foreach ($data['list'] as $id => $block) { if (!isset($no_override['{' . $id . '}'])) $sections[$id] = $block; } // create XHTML table $out = $rcmail->table_output($attrib, $sections, $data['cols'], 'id'); // set client env $this->api->output->add_gui_object('sectionslist', $attrib['id']); $this->api->output->include_script('list.js'); return $out; } function preference_frame($attrib) { if (!$attrib['id']) $attrib['id'] = 'rcmprefsframe'; return $this->api->output->frame($attrib, true); } function gen_form($attrib) { $this->api->output->add_label( 'sauserprefs.spamaddressexists', 'sauserprefs.spamenteraddress', 'sauserprefs.spamaddresserror', 'sauserprefs.spamaddressdelete', 'sauserprefs.spamaddressdeleteall', 'sauserprefs.enabled', 'sauserprefs.disabled', 'sauserprefs.importingaddresses', 'sauserprefs.usedefaultconfirm', 'sauserprefs.purgebayesconfirm', 'sauserprefs.whitelist_from'); // output table sorting prefs $sorts = rcube::get_instance()->config->get('sauserprefs_sort', array()); if (!array_key_exists('#spam-langs-table', $sorts)) $sorts['#spam-langs-table'] = array(0, 'true'); if (!array_key_exists('#address-rules-table', $sorts)) $sorts['#address-rules-table'] = array(1, 'true'); $this->api->output->set_env('sauserprefs_sort', $sorts); // output global prefs as default in env foreach ($this->global_prefs as $key => $val) $this->api->output->set_env(str_replace(" ", "_", $key), $val); unset($attrib['form']); list($form_start, $form_end) = get_form_tags($attrib, 'plugin.sauserprefs.save', null, array('name' => '_section', 'value' => $this->cur_section)); $out = $form_start; $out .= $this->_prefs_block($this->cur_section, $attrib); return $out . $form_end; } function prefs_section_name() { $data = rcube::get_instance()->plugins->exec_hook('sauserprefs_section_name', array('section' => $this->cur_section, 'title' => $this->sections[$this->cur_section]['section'])); return $data['title']; } function save() { $rcmail = rcube::get_instance(); $this->_init_storage(); $this->_load_global_prefs(); $this->_load_user_prefs(); $no_override = array_flip($rcmail->config->get('sauserprefs_dont_override')); $new_prefs = array(); $result = true; switch ($this->cur_section) { case 'general': if (!isset($no_override['required_score'])) $new_prefs['required_score'] = rcube_utils::get_input_value('_spamthres', rcube_utils::INPUT_POST) ?: $this->global_prefs['required_score']; if (!isset($no_override['rewrite_header Subject'])) $new_prefs['rewrite_header Subject'] = rcube_utils::get_input_value('_spamsubject', rcube_utils::INPUT_POST); if (!isset($no_override['ok_locales'])) { $new_prefs['ok_locales'] = ''; if (is_array(rcube_utils::get_input_value('_spamlang', rcube_utils::INPUT_POST))) { $input_locals = rcube_utils::get_input_value('_spamlang', rcube_utils::INPUT_POST); $locales = array_intersect($input_locals, $this->sa_locales); $new_prefs['ok_locales'] = implode(" ", $locales); } } if (!isset($no_override['ok_languages'])) $new_prefs['ok_languages'] = is_array(rcube_utils::get_input_value('_spamlang', rcube_utils::INPUT_POST)) ? implode(" ", rcube_utils::get_input_value('_spamlang', rcube_utils::INPUT_POST)) : ''; break; case 'headers': if (!isset($no_override['fold_headers'])) $new_prefs['fold_headers'] = empty($_POST['_spamfoldheaders']) ? "0" : "1"; if (!isset($no_override['add_header all Level'])) { $spamchar = empty($_POST['_spamlevelchar']) ? "*" : rcube_utils::get_input_value('_spamlevelchar', rcube_utils::INPUT_POST); if (rcube_utils::get_input_value('_spamlevelstars', rcube_utils::INPUT_POST) == "1") { $new_prefs['add_header all Level'] = "_STARS(". $spamchar .")_"; $new_prefs['remove_header all'] = "0"; } else { $new_prefs['add_header all Level'] = ""; $new_prefs['remove_header all'] = "Level"; } } break; case 'tests': if (!isset($no_override['use_razor1'])) $new_prefs['use_razor1'] = empty($_POST['_spamuserazor1']) ? "0" : "1"; if (!isset($no_override['use_razor2'])) $new_prefs['use_razor2'] = empty($_POST['_spamuserazor2']) ? "0" : "1"; if (!isset($no_override['use_pyzor'])) $new_prefs['use_pyzor'] = empty($_POST['_spamusepyzor']) ? "0" : "1"; if (!isset($no_override['use_dcc'])) $new_prefs['use_dcc'] = empty($_POST['_spamusedcc']) ? "0" : "1"; if (!isset($no_override['skip_rbl_checks'])) $new_prefs['skip_rbl_checks'] = empty($_POST['_spamskiprblchecks']) ? "1" : "0"; break; case 'bayes': if (!isset($no_override['use_bayes'])) $new_prefs['use_bayes'] = empty($_POST['_spamusebayes']) ? "0" : "1"; if (!isset($no_override['bayes_auto_learn'])) $new_prefs['bayes_auto_learn'] = empty($_POST['_spambayesautolearn']) ? "0" : "1"; if (!isset($no_override['bayes_auto_learn_threshold_nonspam'])) $new_prefs['bayes_auto_learn_threshold_nonspam'] = rcube_utils::get_input_value('_bayesnonspam', rcube_utils::INPUT_POST) ?: $this->global_prefs['bayes_auto_learn_threshold_nonspam']; if (!isset($no_override['bayes_auto_learn_threshold_spam'])) $new_prefs['bayes_auto_learn_threshold_spam'] = rcube_utils::get_input_value('_bayesspam', rcube_utils::INPUT_POST) ?: $this->global_prefs['bayes_auto_learn_threshold_spam']; if (!isset($no_override['use_bayes_rules'])) $new_prefs['use_bayes_rules'] = empty($_POST['_spambayesrules']) ? "0" : "1"; break; case 'report': if (!isset($no_override['report_safe'])) $new_prefs['report_safe'] = rcube_utils::get_input_value('_spamreport', rcube_utils::INPUT_POST); break; case 'addresses': $acts = rcube_utils::get_input_value('_address_rule_act', rcube_utils::INPUT_POST); $prefs = rcube_utils::get_input_value('_address_rule_field', rcube_utils::INPUT_POST); $vals = rcube_utils::get_input_value('_address_rule_value', rcube_utils::INPUT_POST); foreach ($acts as $idx => $act) $new_prefs['addresses'][] = array('field' => $prefs[$idx], 'value' => $vals[$idx], 'action' => $act); break; } // allow additional actions before prefs are saved $data = $rcmail->plugins->exec_hook('sauserprefs_save', array( 'section' => $this->cur_section, 'cur_prefs' => $this->user_prefs, 'new_prefs' => $new_prefs, 'global_prefs' => $this->global_prefs)); if (!$data['abort']) { // save prefs if ($this->storage->save_prefs($this->sa_user, $data['new_prefs'], $this->user_prefs, $this->global_prefs)) $this->api->output->command('display_message', $this->gettext('sauserprefchanged'), 'confirmation'); else $this->api->output->command('display_message', $this->gettext('sauserpreffailed'), 'error'); } else { $this->api->output->command('display_message', $data['message'] ? $data['message'] : $this->gettext('sauserpreffailed'), 'error'); } // go to next step $rcmail->overwrite_action('plugin.sauserprefs.edit'); $this->_load_user_prefs(); $this->init_html(); } function whitelist_import() { foreach ($this->addressbook_import as $aid) { $contacts = rcube::get_instance()->get_address_book($aid); $contacts->set_page(1); $contacts->set_pagesize(99999); $result = $contacts->list_records(null, 0, true); if (empty($result) || $result->count == 0) return; $records = $result->records; foreach ($records as $row_data) { foreach ($this->_gen_email_arr($row_data) as $email) $this->api->output->command('sauserprefs_addressrule_import', $email, '', ''); } $contacts->close(); } } function purge_bayes() { $rcmail = rcube::get_instance(); $this->_init_storage(); if (empty($this->bayes_query)) { $this->api->output->command('display_message', $this->gettext('servererror'), 'error'); return; } if ($this->storage->purge_bayes($this->sa_user)) $this->api->output->command('display_message', $this->gettext('done'), 'confirmation'); else $this->api->output->command('display_message', $this->gettext('servererror'), 'error'); } function contact_add($args) { if (in_array($args['source'], $this->addressbook_sync)) { $rcmail = rcube::get_instance(); $this->_init_storage(); $emails = $this->_gen_email_arr($args['record']); $this->storage->whitelist_add($this->sa_user, $emails); } } function contact_save($args) { $this->contact_delete($args); $this->contact_add($args); } function contact_delete($args) { if (in_array($args['source'], $this->addressbook_sync)) { $rcmail = rcube::get_instance(); $this->_init_storage(); if (!is_array($args['id'])) $args['id'] = array($args['id']); $contacts = $rcmail->get_address_book($args['source']); foreach ($args['id'] as $id) { $emails = $this->_gen_email_arr($contacts->get_record($id, true)); $this->storage->whitelist_delete($this->sa_user, $emails); } $contacts->close(); } } private function _init_storage() { if (!$this->storage) { $rcmail = rcube::get_instance(); // Add include path for internal classes $include_path = $this->home . '/lib' . PATH_SEPARATOR; $include_path .= ini_get('include_path'); set_include_path($include_path); $class = $rcmail->config->get('sauserprefs_storage', 'sql'); $class = "rcube_sauserprefs_storage_" . $class; // try to instantiate class if(class_exists($class)) { $this->storage = new $class($rcmail->config); } else { // no storage found, raise error rcube::raise_error(array('code' => 604, 'type' => 'sauserprefs', 'line' => __LINE__, 'file' => __FILE__, 'message' => "Failed to find storage driver. Check sauserprefs_storage config option"), true, true); } } } private function _load_global_prefs() { $rcmail = rcube::get_instance(); $this->global_prefs = $this->_load_prefs($rcmail->config->get('sauserprefs_global_userid')); $this->global_prefs = array_merge($rcmail->config->get('sauserprefs_default_prefs'), $this->global_prefs); } private function _load_user_prefs() { $this->user_prefs = $this->_load_prefs($this->sa_user); } private function _load_prefs($user) { $rcmail = rcube::get_instance(); $prefs = $this->storage->load_prefs($user); // sort address rules if (is_array($prefs['addresses'])) usort($prefs['addresses'], array($this, 'sort_addresses')); return $prefs; } private function _prefs_block($part, $attrib) { $rcmail = rcube::get_instance(); $no_override = array_flip($rcmail->config->get('sauserprefs_dont_override')); $locale_info = localeconv(); $blocks = array(); switch ($part) { // General tests case 'general': $blocks = array( 'main' => array('name' => rcmail::Q($this->gettext('mainoptions')), 'class' => 'generalprefstable', 'cols' => 2), 'langs' => array('name' => rcmail::Q($this->gettext('langoptions')), 'class' => 'langprefstable', 'cols' => 1) ); $blocks['langs']['intro'] = html::p(null, rcmail::Q($this->gettext('spamlangexp'))); if (!isset($no_override['required_score'])) { $field_id = 'rcmfd_spamthres'; $input_spamthres = new html_select(array('name' => '_spamthres', 'id' => $field_id)); $input_spamthres->add($this->gettext('defaultscore'), ''); $decPlaces = 0; if ($rcmail->config->get('sauserprefs_score_inc') - (int)$rcmail->config->get('sauserprefs_score_inc') > 0) $decPlaces = strlen($rcmail->config->get('sauserprefs_score_inc') - (int)$rcmail->config->get('sauserprefs_score_inc')) - 2; $score_found = false; for ($i = 1; $i <= 10; $i = $i + $rcmail->config->get('sauserprefs_score_inc')) { $input_spamthres->add(number_format($i, $decPlaces, $locale_info['decimal_point'], ''), number_format($i, $decPlaces, '.', '')); if (!$score_found && $this->user_prefs['required_score'] && (float)$this->user_prefs['required_score'] == (float)$i) $score_found = true; } if (!$score_found && $this->user_prefs['required_score']) $input_spamthres->add(str_replace('%s', $this->user_prefs['required_score'], $this->gettext('otherscore')), (float)$this->user_prefs['required_score']); $blocks['main']['options']['spamthres'] = array( 'title' => html::label($field_id, rcmail::Q($this->gettext('spamthres'))), 'content' => $input_spamthres->show(number_format($this->user_prefs['required_score'], $decPlaces, '.', '')) ); $blocks['main']['options']['spamthres_help'] = array( 'row_attribs' => array('class' => 'sauphelp saupthres'), 'content_attribs' => array('colspan' => 2), 'content' => rcmail::Q($this->gettext('spamthresexp')) ); } if (!isset($no_override['rewrite_header Subject'])) { $field_id = 'rcmfd_spamsubject'; $input_spamsubject = new html_inputfield(array('name' => '_spamsubject', 'id' => $field_id, 'value' => $this->user_prefs['rewrite_header Subject'])); $blocks['main']['options']['spamsubject'] = array( 'title' => html::label($field_id, rcmail::Q($this->gettext('spamsubject'))), 'content' => $input_spamsubject->show() ); $blocks['main']['options']['spamsubject_help'] = array( 'row_attribs' => array('class' => 'sauphelp saupsubject'), 'title' => ' ', 'content' => rcmail::Q($this->gettext('spamsubjectblank')) ); } if (!isset($no_override['ok_languages']) || !isset($no_override['ok_locales'])) { $select_all = $this->api->output->button(array('command' => 'plugin.sauserprefs.select_all_langs', 'type' => 'link', 'label' => 'all')); $select_none = $this->api->output->button(array('command' => 'plugin.sauserprefs.select_no_langs', 'type' => 'link', 'label' => 'none')); $select_invert = $this->api->output->button(array('command' => 'plugin.sauserprefs.select_invert_langs', 'type' => 'link', 'label' => 'invert')); $blocks['langs']['options']['header'] = array( 'content_attribs' => array('id' => 'listcontrols'), 'content' => $this->gettext('select') .":  ". $select_all ."  ". $select_invert ."  ". $select_none ); $lang_table = new html_table(array('id' => 'spam-langs-table', 'class' => 'records-table sortable-table spam-langs-table fixedheader', 'cellspacing' => '0', 'cols' => 2)); $lang_table->add_header('lang', $this->api->output->button(array('command' => 'plugin.sauserprefs.table_sort', 'prop' => '#spam-langs-table', 'type' => 'link', 'label' => 'language', 'title' => 'sortby'))); $lang_table->add_header('tick', $this->api->output->button(array('command' => 'plugin.sauserprefs.table_sort', 'prop' => '#spam-langs-table', 'type' => 'link', 'label' => 'sauserprefs.enabled', 'title' => 'sortby'))); if (!isset($no_override['ok_locales'])) { if ($this->user_prefs['ok_locales'] == "all") $ok_locales = $this->sa_locales; else $ok_locales = explode(" ", $this->user_prefs['ok_locales']); } else { $ok_locales = array(); } if (!isset($no_override['ok_languages'])) { if ($this->user_prefs['ok_languages'] == "all") $ok_languages = array_keys($rcmail->config->get('sauserprefs_languages')); else $ok_languages = explode(" ", $this->user_prefs['ok_languages']); } else { $tmp_array = $rcmail->config->get('sauserprefs_languages'); $rcmail->config->set('sauserprefs_languages', array_intersect_key($tmp_array, array_flip($this->sa_locales))); $ok_languages = array(); } $i = 0; $locales_langs = array_merge($ok_locales, $ok_languages); foreach ($rcmail->config->get('sauserprefs_languages') as $lang_code => $name) { if (in_array($lang_code, $locales_langs)) $button = $this->api->output->button(array('command' => 'plugin.sauserprefs.message_lang', 'prop' => $lang_code, 'type' => 'link', 'class' => 'enabled', 'id' => 'spam_lang_' . $i, 'title' => 'sauserprefs.enabled', 'content' => ' ')); else $button = $this->api->output->button(array('command' => 'plugin.sauserprefs.message_lang', 'prop' => $lang_code, 'type' => 'link', 'class' => 'disabled', 'id' => 'spam_lang_' . $i, 'title' => 'sauserprefs.disabled', 'content' => ' ')); $input_spamlang = new html_checkbox(array('style' => 'display: none;', 'name' => '_spamlang[]', 'value' => $lang_code)); $lang_table->add('lang', $name); $lang_table->add('tick', $button . $input_spamlang->show(in_array($lang_code, $locales_langs) ? $lang_code : '')); $i++; } $blocks['langs']['options']['langtable'] = array( 'content_attribs' => array('class' => 'scroller'), 'content' => html::div(array('id' => 'spam-langs-cont'), $lang_table->show()) ); } break; // Header settings case 'headers': $blocks = array( 'main' => array('name' => rcmail::Q($this->gettext('mainoptions')), 'class' => 'headersprefstable', 'cols' => 3) ); $blocks['main']['intro'] = html::p(null, rcmail::Q($this->gettext('headersexp'))); if (!isset($no_override['fold_headers'])) { $help_button = html::span(array('class' => 'helpicon', 'title' => $this->gettext('moreinfo')), ''); $help_button = html::a(array('name' => '_headerhlp', 'href' => "#", 'onclick' => 'return '. rcmail_output::JS_OBJECT_NAME .'.sauserprefs_help("fold_help");', 'title' => $this->gettext('help')), $help_button); $field_id = 'rcmfd_spamfoldheaders'; $input_spamreport = new html_checkbox(array('name' => '_spamfoldheaders', 'id' => $field_id, 'value' => '1')); $blocks['main']['options']['spamfoldheaders'] = array( 'title' => html::label($field_id, rcmail::Q($this->gettext('foldheaders'))), 'content' => $input_spamreport->show($this->user_prefs['fold_headers']), 'help' => $help_button ); $blocks['main']['options']['spamfoldheaders_help'] = array( 'row_attribs' => array('id' => 'fold_help', 'style' => 'display: none;', 'class' => 'sauphelp'), 'content_attribs' => array('colspan' => 3), 'content' => rcmail::Q($this->gettext('foldhelp')) ); } if (!isset($no_override['add_header all Level'])) { $help_button = html::span(array('class' => 'helpicon', 'title' => $this->gettext('moreinfo')), ''); $help_button = html::a(array('name' => '_headerhlp', 'href' => "#", 'onclick' => 'return '. rcmail_output::JS_OBJECT_NAME .'.sauserprefs_help("level_help");', 'title' => $this->gettext('help')), $help_button); if ($this->user_prefs['remove_header all'] != 'Level') { $enabled = "1"; $char = $this->user_prefs['add_header all Level']; $char = substr($char, 7, 1); } else { $enabled = "0"; $char = "*"; } $field_id = 'rcmfd_spamlevelstars'; $input_spamreport = new html_checkbox(array('name' => '_spamlevelstars', 'id' => $field_id, 'value' => '1', 'onchange' => rcmail_output::JS_OBJECT_NAME . '.sauserprefs_toggle_level_char(this)')); $blocks['main']['options']['spamlevelstars'] = array( 'title' => html::label($field_id, rcmail::Q($this->gettext('spamlevelstars'))), 'content' => $input_spamreport->show($enabled), 'help' => $help_button ); $blocks['main']['options']['spamlevelstars_help'] = array( 'row_attribs' => array('id' => 'level_help', 'style' => 'display: none;', 'class' => 'sauphelp'), 'content_attribs' => array('colspan' => 3), 'content' => rcmail::Q($this->gettext('levelhelp')) ); $field_id = 'rcmfd_spamlevelchar'; $input_spamsubject = new html_inputfield(array('name' => '_spamlevelchar', 'id' => $field_id, 'value' => $char, 'maxlength' => '1', 'disabled' => $enabled?0:1)); $blocks['main']['options']['spamlevelchar'] = array( 'title' => html::label($field_id, rcmail::Q($this->gettext('spamlevelchar'))), 'content' => $input_spamsubject->show(), 'help' => ' ' ); } break; // Test settings case 'tests': $blocks = array( 'main' => array('name' => rcmail::Q($this->gettext('mainoptions')), 'class' => 'testsprefstable', 'cols' => 3) ); $blocks['main']['intro'] = html::p(null, rcmail::Q($this->gettext('spamtestssexp'))); if (!isset($no_override['use_razor1'])) { $help_button = html::span(array('class' => 'helpicon', 'title' => $this->gettext('moreinfo')), ''); $help_button = html::a(array('name' => '_headerhlp', 'href' => "#", 'onclick' => 'return '. rcmail_output::JS_OBJECT_NAME .'.sauserprefs_help("raz1_help");', 'title' => $this->gettext('help')), $help_button); $field_id = 'rcmfd_spamuserazor1'; $input_spamtest = new html_checkbox(array('name' => '_spamuserazor1', 'id' => $field_id, 'value' => '1')); $blocks['main']['options']['spamuserazor1'] = array( 'title' => html::label($field_id, rcmail::Q($this->gettext('userazor1'))), 'content' => $input_spamtest->show($this->user_prefs['use_razor1']), 'help' => $help_button ); $blocks['main']['options']['spamuserazor1_help'] = array( 'row_attribs' => array('id' => 'raz1_help', 'style' => 'display: none;', 'class' => 'sauphelp'), 'content_attribs' => array('colspan' => 3), 'content' => rcmail::Q($this->gettext('raz1help')) ); } if (!isset($no_override['use_razor2'])) { $help_button = html::span(array('class' => 'helpicon', 'title' => $this->gettext('moreinfo')), ''); $help_button = html::a(array('name' => '_headerhlp', 'href' => "#", 'onclick' => 'return '. rcmail_output::JS_OBJECT_NAME .'.sauserprefs_help("raz2_help");', 'title' => $this->gettext('help')), $help_button); $field_id = 'rcmfd_spamuserazor2'; $input_spamtest = new html_checkbox(array('name' => '_spamuserazor2', 'id' => $field_id, 'value' => '1')); $blocks['main']['options']['spamuserazor2'] = array( 'title' => html::label($field_id, rcmail::Q($this->gettext('userazor2'))), 'content' => $input_spamtest->show($this->user_prefs['use_razor2']), 'help' => $help_button ); $blocks['main']['options']['spamuserazor2_help'] = array( 'row_attribs' => array('id' => 'raz2_help', 'style' => 'display: none;', 'class' => 'sauphelp'), 'content_attribs' => array('colspan' => 3), 'content' => rcmail::Q($this->gettext('raz2help')) ); } if (!isset($no_override['use_pyzor'])) { $help_button = html::span(array('class' => 'helpicon', 'title' => $this->gettext('moreinfo')), ''); $help_button = html::a(array('name' => '_headerhlp', 'href' => "#", 'onclick' => 'return '. rcmail_output::JS_OBJECT_NAME .'.sauserprefs_help("pyz_help");', 'title' => $this->gettext('help')), $help_button); $field_id = 'rcmfd_spamusepyzor'; $input_spamtest = new html_checkbox(array('name' => '_spamusepyzor', 'id' => $field_id, 'value' => '1')); $blocks['main']['options']['spamusepyzor'] = array( 'title' => html::label($field_id, rcmail::Q($this->gettext('usepyzor'))), 'content' => $input_spamtest->show($this->user_prefs['use_pyzor']), 'help' => $help_button ); $blocks['main']['options']['spamusepyzor_help'] = array( 'row_attribs' => array('id' => 'pyz_help', 'style' => 'display: none;', 'class' => 'sauphelp'), 'content_attribs' => array('colspan' => 3), 'content' => rcmail::Q($this->gettext('pyzhelp')) ); } if (!isset($no_override['use_dcc'])) { $help_button = html::span(array('class' => 'helpicon', 'title' => $this->gettext('moreinfo')), ''); $help_button = html::a(array('name' => '_headerhlp', 'href' => "#", 'onclick' => 'return '. rcmail_output::JS_OBJECT_NAME .'.sauserprefs_help("dcc_help");', 'title' => $this->gettext('help')), $help_button); $field_id = 'rcmfd_spamusedcc'; $input_spamtest = new html_checkbox(array('name' => '_spamusedcc', 'id' => $field_id, 'value' => '1')); $blocks['main']['options']['spamusedcc'] = array( 'title' => html::label($field_id, rcmail::Q($this->gettext('usedcc'))), 'content' => $input_spamtest->show($this->user_prefs['use_dcc']), 'help' => $help_button ); $blocks['main']['options']['spamusedcc_help'] = array( 'row_attribs' => array('id' => 'dcc_help', 'style' => 'display: none;', 'class' => 'sauphelp'), 'content_attribs' => array('colspan' => 3), 'content' => rcmail::Q($this->gettext('dcchelp')) ); } if (!isset($no_override['skip_rbl_checks'])) { $help_button = html::span(array('class' => 'helpicon', 'title' => $this->gettext('moreinfo')), ''); $help_button = html::a(array('name' => '_headerhlp', 'href' => "#", 'onclick' => 'return '. rcmail_output::JS_OBJECT_NAME .'.sauserprefs_help("rbl_help");', 'title' => $this->gettext('help')), $help_button); $field_id = 'rcmfd_spamskiprblchecks'; $enabled = $this->user_prefs['skip_rbl_checks'] == "1" ? "0" : "1"; $input_spamtest = new html_checkbox(array('name' => '_spamskiprblchecks', 'id' => $field_id, 'value' => '1')); $blocks['main']['options']['spamskiprblchecks'] = array( 'title' => html::label($field_id, rcmail::Q($this->gettext('skiprblchecks'))), 'content' => $input_spamtest->show($enabled), 'help' => $help_button ); $blocks['main']['options']['spamskiprblchecks_help'] = array( 'row_attribs' => array('id' => 'rbl_help', 'style' => 'display: none;', 'class' => 'sauphelp'), 'content_attribs' => array('colspan' => 3), 'content' => rcmail::Q($this->gettext('rblhelp')) ); } break; // Bayes settings case 'bayes': $blocks = array( 'main' => array('name' => rcmail::Q($this->gettext('mainoptions')), 'class' => 'bayesprefstable', 'cols' => 3), 'autolearn' => array('name' => rcmail::Q($this->gettext('bayesautooptions')), 'class' => 'bayesprefstable', 'cols' => 2) ); if (!isset($no_override['use_bayes'])) { $help_button = html::span(array('class' => 'helpicon', 'title' => $this->gettext('moreinfo')), ''); $help_button = html::a(array('name' => '_headerhlp', 'href' => "#", 'onclick' => 'return '. rcmail_output::JS_OBJECT_NAME .'.sauserprefs_help("bayes_help");', 'title' => $this->gettext('help')), $help_button); $field_id = 'rcmfd_spamusebayes'; $input_spamtest = new html_checkbox(array('name' => '_spamusebayes', 'id' => $field_id, 'value' => '1', 'onchange' => rcmail_output::JS_OBJECT_NAME . '.sauserprefs_toggle_bayes(this)')); if (!empty($this->bayes_query)) $delete_link = "   " . html::span(array('id' => 'listcontrols'), $this->api->output->button(array('command' => 'plugin.sauserprefs.purge_bayes', 'type' => 'link', 'label' => 'sauserprefs.purgebayes', 'title' => 'sauserprefs.purgebayesexp'))); $blocks['main']['options']['spamusebayes'] = array( 'title' => html::label($field_id, rcmail::Q($this->gettext('usebayes'))), 'content_attribs' => array('colspan' => 2), 'content' => $input_spamtest->show($this->user_prefs['use_bayes']) . $delete_link, ); } if (!isset($no_override['use_bayes_rules'])) { $help_button = html::span(array('class' => 'helpicon', 'title' => $this->gettext('moreinfo')), ''); $help_button = html::a(array('name' => '_headerhlp', 'href' => "#", 'onclick' => 'return '. rcmail_output::JS_OBJECT_NAME .'.sauserprefs_help("bayesrules_help");', 'title' => $this->gettext('help')), $help_button); $field_id = 'rcmfd_spambayesrules'; $input_spamtest = new html_checkbox(array('name' => '_spambayesrules', 'id' => $field_id, 'value' => '1', 'disabled' => $this->user_prefs['use_bayes']?0:1)); $blocks['main']['options']['spambayesrules'] = array( 'title' => html::label($field_id, rcmail::Q($this->gettext('bayesrules'))), 'content' => $input_spamtest->show($this->user_prefs['use_bayes_rules']), 'help' => $help_button ); $blocks['main']['options']['spambayesrules_help'] = array( 'row_attribs' => array('id' => 'bayesrules_help', 'style' => 'display: none;', 'class' => 'sauphelp'), 'content_attribs' => array('colspan' => 3), 'content' => rcmail::Q($this->gettext('bayesruleshlp')) ); } if (!isset($no_override['bayes_auto_learn'])) { $help_button = html::span(array('class' => 'helpicon', 'title' => $this->gettext('moreinfo')), ''); $help_button = html::a(array('name' => '_headerhlp', 'href' => "#", 'onclick' => 'return '. rcmail_output::JS_OBJECT_NAME .'.sauserprefs_help("bayesauto_help");', 'title' => $this->gettext('help')), $help_button); $field_id = 'rcmfd_spambayesautolearn'; $input_spamtest = new html_checkbox(array('name' => '_spambayesautolearn', 'id' => $field_id, 'value' => '1', 'onchange' => rcmail_output::JS_OBJECT_NAME . '.sauserprefs_toggle_bayes_auto(this)', 'disabled' => $this->user_prefs['use_bayes']?0:1)); $blocks['main']['options']['spambayesautolearn'] = array( 'title' => html::label($field_id, rcmail::Q($this->gettext('bayesautolearn'))), 'content' => $input_spamtest->show($this->user_prefs['bayes_auto_learn']), 'help' => $help_button ); $blocks['main']['options']['spambayesautolearn_help'] = array( 'row_attribs' => array('id' => 'bayesauto_help', 'style' => 'display: none;', 'class' => 'sauphelp'), 'content_attribs' => array('colspan' => 3), 'content' => rcmail::Q($this->gettext('bayesautohelp')) ); } if (!isset($no_override['bayes_auto_learn_threshold_nonspam'])) { $field_id = 'rcmfd_bayesnonspam'; $input_bayesnthres = new html_select(array('name' => '_bayesnonspam', 'id' => $field_id, 'disabled' => (!$this->user_prefs['bayes_auto_learn'] || !$this->user_prefs['use_bayes'])?1:0)); $input_bayesnthres->add($this->gettext('defaultscore'), ''); $decPlaces = 1; //if ($rcmail->config->get('sauserprefs_score_inc') - (int)$rcmail->config->get('sauserprefs_score_inc') > 0) // $decPlaces = strlen($rcmail->config->get('sauserprefs_score_inc') - (int)$rcmail->config->get('sauserprefs_score_inc')) - 2; $score_found = false; for ($i = -1; $i <= 1; $i = $i + 0.1) { $input_bayesnthres->add(number_format($i, $decPlaces, $locale_info['decimal_point'], ''), number_format($i, $decPlaces, '.', '')); if (!$score_found && $this->user_prefs['bayes_auto_learn_threshold_nonspam'] && (float)$this->user_prefs['bayes_auto_learn_threshold_nonspam'] == (float)$i) $score_found = true; } if (!$score_found && $this->user_prefs['bayes_auto_learn_threshold_nonspam']) $input_bayesnthres->add(str_replace('%s', $this->user_prefs['bayes_auto_learn_threshold_nonspam'], $this->gettext('otherscore')), (float)$this->user_prefs['bayes_auto_learn_threshold_nonspam']); $blocks['autolearn']['options']['bayesnonspam'] = array( 'title' => html::label($field_id, rcmail::Q($this->gettext('bayesnonspam'))), 'content' => $input_bayesnthres->show(number_format($this->user_prefs['bayes_auto_learn_threshold_nonspam'], $decPlaces, '.', '')) ); $blocks['autolearn']['options']['bayesnonspam_help'] = array( 'row_attribs' => array('class' => 'sauphelp saupbayesnonspam'), 'content_attribs' => array('colspan' => 2), 'content' => rcmail::Q($this->gettext('bayesnonspamexp')) ); } if (!isset($no_override['bayes_auto_learn_threshold_spam'])) { $field_id = 'rcmfd_bayesspam'; $input_bayesthres = new html_select(array('name' => '_bayesspam', 'id' => $field_id, 'disabled' => (!$this->user_prefs['bayes_auto_learn'] || !$this->user_prefs['use_bayes'])?1:0)); $input_bayesthres->add($this->gettext('defaultscore'), ''); $decPlaces = 0; if ($rcmail->config->get('sauserprefs_score_inc') - (int)$rcmail->config->get('sauserprefs_score_inc') > 0) $decPlaces = strlen($rcmail->config->get('sauserprefs_score_inc') - (int)$rcmail->config->get('sauserprefs_score_inc')) - 2; $score_found = false; for ($i = 1; $i <= 20; $i = $i + $rcmail->config->get('sauserprefs_score_inc')) { $input_bayesthres->add(number_format($i, $decPlaces, $locale_info['decimal_point'], ''), number_format($i, $decPlaces, '.', '')); if (!$score_found && $this->user_prefs['bayes_auto_learn_threshold_spam'] && (float)$this->user_prefs['bayes_auto_learn_threshold_spam'] == (float)$i) $score_found = true; } if (!$score_found && $this->user_prefs['required_score']) $input_bayesthres->add(str_replace('%s', $this->user_prefs['bayes_auto_learn_threshold_spam'], $this->gettext('otherscore')), (float)$this->user_prefs['bayes_auto_learn_threshold_spam']); $blocks['autolearn']['options']['bayesspam'] = array( 'title' => html::label($field_id, rcmail::Q($this->gettext('bayesspam'))), 'content' => $input_bayesthres->show(number_format($this->user_prefs['bayes_auto_learn_threshold_spam'], $decPlaces, '.', '')) ); $blocks['autolearn']['options']['bayesspam_help'] = array( 'row_attribs' => array('class' => 'sauphelp saupbayesspam'), 'content_attribs' => array('colspan' => 2), 'content' => rcmail::Q($this->gettext('bayesspamexp')) ); } break; // Report settings case 'report': $blocks = array( 'main' => array('name' => rcmail::Q($this->gettext('mainoptions')), 'class' => 'reportprefstable', 'cols' => 2) ); if (!isset($no_override['report_safe'])) { $field_id = 'rcmfd_spamreport'; $input_spamreport0 = new html_radiobutton(array('name' => '_spamreport', 'id' => $field_id.'_0', 'value' => '0')); $blocks['main']['options']['bayesspam0'] = array( 'title' => html::label($field_id.'_0', rcmail::Q($this->gettext('spamreport0'))), 'content' => $input_spamreport0->show($this->user_prefs['report_safe']) ); $input_spamreport1 = new html_radiobutton(array('name' => '_spamreport', 'id' => $field_id.'_1', 'value' => '1')); $blocks['main']['options']['bayesspam1'] = array( 'title' => html::label($field_id.'_1', rcmail::Q($this->gettext('spamreport1'))), 'content' => $input_spamreport1->show($this->user_prefs['report_safe']) ); $input_spamreport2 = new html_radiobutton(array('name' => '_spamreport', 'id' => $field_id.'_2', 'value' => '2')); $blocks['main']['options']['bayesspam2'] = array( 'title' => html::label($field_id.'_2', rcmail::Q($this->gettext('spamreport2'))), 'content' => $input_spamreport2->show($this->user_prefs['report_safe']) ); } break; // Address settings case 'addresses': $blocks = array( 'main' => array('name' => rcmail::Q($this->gettext('mainoptions'))) ); $data = html::p(null, rcmail::Q($this->gettext('whitelistexp'))); if (count($this->addressbook_sync) > 0) $data .= rcmail::Q($this->gettext('autowhitelist')) . "

"; $blocks['main']['intro'] = $data; $table = new html_table(array('class' => 'addressprefstable propform', 'cols' => 4)); $field_id = 'rcmfd_spamaddressrule'; $input_spamaddressrule = new html_select(array('name' => '_spamaddressrule', 'id' => $field_id)); $input_spamaddressrule->add($this->gettext('whitelist_from'),'whitelist_from'); $input_spamaddressrule->add($this->gettext('blacklist_from'), 'blacklist_from'); $input_spamaddressrule->add($this->gettext('whitelist_to'), 'whitelist_to'); $field_id = 'rcmfd_spamaddress'; $input_spamaddress = new html_inputfield(array('name' => '_spamaddress', 'id' => $field_id)); $field_id = 'rcmbtn_add_address'; $button_addaddress = $this->api->output->button(array('id' => $field_id, 'command' => 'plugin.sauserprefs.addressrule_add', 'type' => 'input', 'class' => 'button', 'label' => 'sauserprefs.addrule')); $table->add('ruletype', $input_spamaddressrule->show()); $table->add('address', $input_spamaddress->show()); $table->add('action', $button_addaddress); $table->add(null, " "); $import = count($this->addressbook_import) > 0 ? $this->api->output->button(array('command' => 'plugin.sauserprefs.import_whitelist', 'type' => 'link', 'label' => 'sauserprefs.importaddresses', 'title' => 'sauserprefs.importfromaddressbook')) : ''; $delete_all = $this->api->output->button(array('command' => 'plugin.sauserprefs.whitelist_delete_all', 'type' => 'link', 'label' => 'sauserprefs.deleteall')); $table->add(array('colspan' => 4, 'id' => 'listcontrols'), $import ."  ". $delete_all); $address_table = new html_table(array('id' => 'address-rules-table', 'class' => 'records-table sortable-table address-rules-table fixedheader', 'cellspacing' => '0', 'cols' => 3)); $address_table->add_header('rule', $this->api->output->button(array('command' => 'plugin.sauserprefs.table_sort', 'prop' => '#address-rules-table', 'type' => 'link', 'label' => 'sauserprefs.rule', 'title' => 'sortby'))); $address_table->add_header('email', $this->api->output->button(array('command' => 'plugin.sauserprefs.table_sort', 'prop' => '#address-rules-table', 'type' => 'link', 'label' => 'email', 'title' => 'sortby'))); $address_table->add_header('control', ' '); $this->api->output->set_env('address_rule_count', count($this->user_prefs['addresses'])); foreach ((array)$this->user_prefs['addresses'] as $address) $this->_address_row($address_table, $address['field'], $address['value'], $attrib); // add no address and new address rows at the end if (count($this->user_prefs['addresses']) > 0) $norules = 'display: none;'; $address_table->set_row_attribs(array('class' => 'noaddressrules', 'style' => $norules)); $address_table->add(array('colspan' => '3'), rcube_utils::rep_specialchars_output($this->gettext('noaddressrules'))); $this->_address_row($address_table, null, null, $attrib, array('class' => 'newaddressrule')); $table->add(array('colspan' => 4, 'class' => 'scroller'), html::div(array('id' => 'address-rules-cont'), $address_table->show())); $blocks['main']['content'] = $table->show(); break; } $data = $rcmail->plugins->exec_hook('sauserprefs_list', array('section' => $part, 'blocks' => $blocks)); $out = ''; foreach ($data['blocks'] as $block) { if (isset($block['content']) || count($block['options']) > 0 ) { $content = $block['content']; if (count($block['options']) > 0) { $table = new html_table(array('class' => 'propform ' . $block['class'], 'cols' => $block['cols'])); foreach ($block['options'] as $row) { if (isset($row['row_attribs'])) $table->set_row_attribs($row['row_attribs']); if (isset($row['title'])) $table->add('title', $row['title']); $table->add($row['content_attribs'], $row['content']); if (isset($row['help'])) $table->add('help', $row['help']); } $content .= $table->show(); } $out .= html::tag('fieldset', null, html::tag('legend', null, $block['name']) . $block['intro'] . $content); } } return $out; } private function _address_row(&$address_table, $field, $value, $attrib, $row_attrib = array()) { if (!isset($field)) $address_table->set_row_attribs(array('style' => 'display: none;') + $row_attrib); $hidden_action = new html_hiddenfield(array('name' => '_address_rule_act[]', 'value' => '')); $hidden_field = new html_hiddenfield(array('name' => '_address_rule_field[]', 'value' => $field)); $hidden_text = new html_hiddenfield(array('name' => '_address_rule_value[]', 'value' => $value)); switch ($field) { case "whitelist_from": $fieldtxt = rcube_utils::rep_specialchars_output($this->gettext('whitelist_from')); break; case "blacklist_from": $fieldtxt = rcube_utils::rep_specialchars_output($this->gettext('blacklist_from')); break; case "whitelist_to": $fieldtxt = rcube_utils::rep_specialchars_output($this->gettext('whitelist_to')); break; } $address_table->add(array('class' => $field), $fieldtxt); $address_table->add(array('class' => 'email'), $value); $del_button = $this->api->output->button(array('command' => 'plugin.sauserprefs.addressrule_del', 'type' => 'link', 'class' => 'delete', 'label' => 'delete', 'content' => ' ', 'title' => 'delete')); $address_table->add('control', $del_button . $hidden_action->show() . $hidden_field->show() . $hidden_text->show()); } static function map_pref_name($pref, $reverse = false) { if (!$reverse) { if (array_key_exists($pref, self::$deprecated_prefs)) $pref = self::$deprecated_prefs[$pref]; } else { if (($orig_pref = array_search($pref, self::$deprecated_prefs)) != FALSE) $pref = $orig_pref; } return $pref; } static function sort_addresses($a, $b) { return strnatcasecmp($a["value"], $b["value"]); } private function _gen_email_arr($contact) { $emails = array(); if (!is_array($contact)) return $emails; foreach ($contact as $key => $value) { if (preg_match('/^email(:(.+))?$/i', $key, $matches)) { foreach ((array)$value as $subkey => $subval) { if ($matches[2]) $emails[$matches[2] . $subkey] = $subval; else $emails['email' . $subkey] = $subval; } } } return $emails; } } ?>roundcube-sauserprefs-1.17.1/skins/000077500000000000000000000000001316336120600172575ustar00rootroot00000000000000roundcube-sauserprefs-1.17.1/skins/classic/000077500000000000000000000000001316336120600207005ustar00rootroot00000000000000roundcube-sauserprefs-1.17.1/skins/classic/images/000077500000000000000000000000001316336120600221455ustar00rootroot00000000000000roundcube-sauserprefs-1.17.1/skins/classic/images/icons.png000066400000000000000000000044711316336120600237740ustar00rootroot00000000000000PNG  IHDRK}OhtEXtSoftwareAdobe ImageReadyqe<IDATxX lS?߱۱$kBEJa@) ]L+*j'beeE&”NZhRBH$rl'>g=cg4qQixҧw~<|Cu;FCDb1JDxpE'"_ٳg_6mӦ' (8֬Y g ^/ xFG:[2bPFxcǎp=:`(TѴ?-L$p!)ٜ3gn%T-XF D2{b:XX5FF K@4465Ȉ/H$\J|"8NjIS#<J EP#FA5$দkP.--r@摱@tꂅ󠳳Z@&6 MJ%#ryy(X VZ2!NΕve(@F6dx"X;ڑ+̹fBxF4Ї+Wp̮.\˥M\t:aŊܹ,v r@ #B4K< f,`ۮ]?HVVWWH'CnwODс{.ĺm۶$I.f%rB8AÇ< $p(qȅ`qq$ \N _@O?~pЦS5sufiϚ~_x;i|+Mx?cMZ㎢09X}/hS_[-[ 7A wt֕W%'mn)bYcu x9:A bAn~S{k2B*zWˤS)Ɩ3p]=p/n|%9h,l=XL@&04: brM&]iY^ 2D[~C4tD氼n7<2T~Fr`L5tcLÖNOW/zyFYk2STC+`&R9Aޖ)=(Y#$-n~[el#vS"Ϩ$aEI;E!EsHkhjP1T( ]( 6N63Z7 G m%rX m|s$ߍZpg5 9>_/IqzLvU,>ts #Z='8&Ʋ>kDi y*ֵJ*9Y"QDzCh)rna'O_", yYO&XRѐtB*W Bs>;0[jv4;L3HPRBddˤҵNuPD񼞥Ų<ȞeY\^b9ݾVf:IIx^nމICͼb4DQc`ݗL^u{@:p\q8Y< o,| g+5wi?NCC$@qŲ"`| 6d"ᤓeyRU$˂`ӓA5Z\ N[G Sk:GVe4:Z<4Cp3ʌ`5Bv>^zk$'(8: T9@A-G+ #xQ9s42Amx2E*D .Ӟ0B8FB'Z&e J }(0`V)A4?,Ac :%4`~iy7wP Ld45ͲDU-:ұ+w62K;>? *%Ӑfp"H y|=պEpdˁ[ yHpG dtW=|z "]pۓQw?b86!_Z{VՎABrf , _ `Fo76d,'v'd f9 I:zp/#XB/|S w٫~n1-,f/-eO棛^? ƔaHIENDB`roundcube-sauserprefs-1.17.1/skins/classic/images/sort.gif000066400000000000000000000002201316336120600236150ustar00rootroot00000000000000GIF89auuuhhhwww~~~nnofff!,@=Ii ZM iʂf'SШ4댚6I*;roundcube-sauserprefs-1.17.1/skins/classic/sauserprefs.css000066400000000000000000000074361316336120600237660ustar00rootroot00000000000000/** * SAUserPrefs plugin styles */ #address-rules-cont, #spam-langs-cont { border: 1px solid #999999; background-color: #F9F9F9; height: 200px; overflow: auto; width: 510px; } body.address-rules-table, body.spam-langs-table { margin: 0px; background-color: #F9F9F9; } table.address-rules-table, table.spam-langs-table { width: 100%; display: table; table-layout: fixed; border-collapse: collapse; border-spacing: 0px; } table.address-rules-table thead th.rule { width: 180px; } table.address-rules-table thead th.control { width: 40px; } table.address-rules-table thead th a, table.spam-langs-table thead th a { display: block; text-decoration: none; } table.address-rules-table thead th.sortedASC, table.address-rules-table thead th.sortedDESC, table.spam-langs-table thead th.sortedASC, table.spam-langs-table thead th.sortedDESC { background-position: 0px -26px; } table.spam-langs-table tr > .lang { width: 80%; } table.spam-langs-table tr > .tick { width: 20%; } table.spam-langs-table thead th.tick a { padding-right: 24px; } table.address-rules-table thead tr th.sortedASC a, table.spam-langs-table thead tr th.sortedASC a { background: url(images/sort.gif) no-repeat right -14px; } table.address-rules-table thead tr th.sortedDESC a, table.spam-langs-table thead tr th.sortedDESC a { background: url(images/sort.gif) no-repeat right 0; } table.spam-langs-table tr > .lang, table.address-rules-table tr > .rule, table.address-rules-table tr > .email { text-align: left; vertical-align: middle; } table.spam-langs-table tr > .tick, table.address-rules-table tr > .control { text-align: right; vertical-align: middle; } table.spam-langs-table tbody td.tick a, table.address-rules-table tr > .control a { display: block; float: right; width: 16px; height: 16px; background-image: url(images/icons.png); } table.address-rules-table tr > .control a.delete { background-position: 0 0; } table.spam-langs-table tr > .tick a.enabled { background-position: 0 -18px; } table.spam-langs-table tr > .tick a.disabled { background-position: 0 -36px; } .whitelist_from, .whitelist_to { color: #008800; text-align: left; vertical-align: middle; } .blacklist_from { color: #BB0000; text-align: left; vertical-align: middle; } #listcontrols { font-size: 11px; text-align: right; } #listcontrols a, #listcontrols a:active, #listcontrols a:visited { color: #CC0000; font-size: 11px; text-decoration: none; } #listcontrols a:hover { text-decoration: underline; } table.generalprefstable, table.headersprefstable, table.testsprefstable, table.bayesprefstable, table.reportprefstable { width: 100%; } table.generalprefstable tr > .title { width: 115px; } table.headersprefstable tr > .title { width: 220px; } table.testsprefstable tr > .title { width: 175px; } table.bayesprefstable tr > .title { width: 220px; } table.reportprefstable tr > .title { width: 320px; } table.generalprefstable tr > .help, table.langprefstable tr > .help, table.headersprefstable tr > .help, table.testsprefstable tr > .help, table.bayesprefstable tr > .help, table.reportprefstable tr > .help, table.addressprefstable tr > .help { text-align: right; } table.addressprefstable tr > .ruletype { width: 180px; padding-bottom: 10px; } table.addressprefstable tr > .address { width: 220px; padding-bottom: 10px; } table.addressprefstable tr > .action { width: 100px; text-align: right; padding-bottom: 10px; } table.langprefstable tr > .scroller, table.addressprefstable tr > .scroller { padding: 0; } span.helpicon { display: inline-block; width: 16px; height: 16px; background-image: url(images/icons.png); background-position: 0 -57px; } #rcmfd_spamlevelchar { width: 20px; } #rcmfd_spamsubject, #rcmfd_spamaddress { width: 200px; }roundcube-sauserprefs-1.17.1/skins/classic/tabstyles.css000066400000000000000000000000621316336120600234220ustar00rootroot00000000000000/** * SAUserPrefs plugin styles (tab styles) */ roundcube-sauserprefs-1.17.1/skins/classic/templates/000077500000000000000000000000001316336120600226765ustar00rootroot00000000000000roundcube-sauserprefs-1.17.1/skins/classic/templates/sauserprefs.html000066400000000000000000000027671316336120600261420ustar00rootroot00000000000000 <roundcube:object name="pagetitle" />
roundcube-sauserprefs-1.17.1/skins/classic/templates/settingsedit.html000066400000000000000000000016721316336120600263000ustar00rootroot00000000000000 <roundcube:object name="pagetitle" />
roundcube-sauserprefs-1.17.1/skins/larry/000077500000000000000000000000001316336120600204105ustar00rootroot00000000000000roundcube-sauserprefs-1.17.1/skins/larry/images/000077500000000000000000000000001316336120600216555ustar00rootroot00000000000000roundcube-sauserprefs-1.17.1/skins/larry/images/icons.png000066400000000000000000000016241316336120600235010ustar00rootroot00000000000000PNG  IHDRK}OhtEXtSoftwareAdobe ImageReadyqe<6IDATx]HTAwͶU++!A\ׂ_(P !- *X "z^ z rv+ݙq (5 O! XFY˅lnlD+F"F^  ;3)K@:JtW]GICƍоɏ" h)t2 "S乀Dpb 25~Е؛ɱ&5,b#6&]T)Ohv~4m@t*,|H a-Tt?0n JWѼlp*֨Ҁ'_,#yF،.T];ف}rބd86 QthUQM޹fTxBJKt? yRIENDB`roundcube-sauserprefs-1.17.1/skins/larry/images/listicons.png000066400000000000000000000114171316336120600243760ustar00rootroot00000000000000PNG  IHDR0^ËtEXtSoftwareAdobe ImageReadyqe<IDATx] xUd,@qX % Da0 DQtQ3 0Eqds`M!"$,@HLd9Vwj_[]_s9f3&^8NuVC4LtPxpM$O$/(m(XTKmXnPf^ X x+/0P$7̀Kz ƱwNjw]؊7CjD|8"7Q.1Z.Ӻu-x&v~G @J]g1(g*ի"4j?2"VI͂ hP$*!5t{;kbA(X zMu D'@ײeR+>\L{V*X R 0.mv?C]g '3&c@XNUzzzAuFNiGqZTͷ0rRg|qjFKE+[u1s8o ,S!At\8<?@hІJą/PCvxO򘘥B0̢vDR)VKΖ\%s A\ I &s*g]׈Qd 7JA޶ZMD k\RTJ8T942 cL0[cQ6$Ll> x`lhh-hk {!8_✋\+UÙdEF"FHrb TQwFen6ohN}|=W?psZmlFd~Wb׋D²^?  gF Y <xprԇI[j=rО+`=Rb`{ ,[f9,A_EP L/΢r&z nPa։|OiĚ+Ctz*'5հ 맨Y uiϰOltLφq,ft XP}b4´a"4`t3`{ghnXvR*>DXeLlnĖ 88&m gexW+VfIh/K*~' pL8KW݈XZXlzB|r 858~+Ng$ t'ޞ>wr/\tL֭U<j&H}1,pPP$Or%P>3-8l$^¿X. !=BB,c)Ĥ(*|mVQݫ;Y_LZ؟sWnt_}}zy7J?Sп:wԣQE: ilM@m^٬co;E;{8=/dy~b@^:)`_;C z7ۢ*z J&g-e&`lԞD ]/=>Fu V=D=Dƒ cB&P!|? : 1`4K;׭sKIH.c9L/3?72 ǚd1MT`@a!A9qz/}}ZwT~݁#/}4."u Ù'{бNo0g"at'F[5{'<gB`OfNk[nH;RE' p' (@ TM`h~,9sacC`$m\&; adoZo1]Z بPZM%~/y˜ @CǼq@6HW1!.رKrt/Cᡉǯx\, g_RXn.6 ]m*,_U038_\57n\Nڇю`ï]R^ 544Xx{Ȕ9K=Ga Xx?x7Ù6S&جQ`hܔkV=D w\rl=0Ad8ZR爆FQxQ uТVn^6y!g0df c'զ|;vqO `g;@t~ܱVq@Ė+;Y/l6ih4 J-ڰ/UN' p' 43Mn=1cFxnwھU 7ۍmJ$+h4j:yvl7q_X{@ht `2 q_8'@;̮BxI!u]]@E|iڒ1h®cgKj2fHLg;w ~$Ar(e-J]Ex !z,[4~1rR:׺}^aabFF̔PYuMn"=`{S%Oâ"ZrP!E¤zf7豊Ȱd;U`@@Voԓ Or' y llw CYNd1ԣ+jt{~R{/dG_3{?~/*("ݩ>}n cA[\ mEo*/OxD3.v䆐bTHLM\&n51\wUPLi'sqFQ q' 4oM&9j4~|~8f3PF__-N *$|T5]F%LU>|f[B:}n^ ̇`Q*n*Cpzc=bdENb6z*$5NnYBBX_s+ܭEwu`Q P֥w+c9x1 00Ub'vBu]an  [%[!Rr' p 5.3WeeԹcxfNTg7ܭ]f,J%ԹcxfNTgjV.3une9nxH p'l"KLZ'N]4Nc# ͂X{b}r>t yڤ'YExp CK4|/( XP*2]I]o 7|~SEbmcM 0E_GG{y*\Z|g3Ҟ|+bv%~oo4$a"PKWJBGrO[ = "`mK/>EN9WE^؛QR g6QUO9T0 ,jiOBcdEL0G]C-ׄqJ@p1b-_DRnȜ4pJިg=]ǞB"etVLy!NF tlbri)יko֛(&o[vۿ22n.&ӕl8x,MO=M'uuD {!*-MC6}ލK䝵_[z d?k5rKr\FW|N &AH]=d2}QJ2U֑o 9`)=f2E $2/[℥kd6|^L@opeF13MRی7:F欶@$zxi4Ap{M4zVN4ja߯C5 'xW6 L%ѨUaz1G(ѕA{2²HG5 >*45iTJPIbћ`xZ>CLL7z5`^4xM`)`Z8NhJH莯\Yɓ'N*EnX,OnEBBB IBf!J=LHWj@ańW KW&E s+$OiN8N8N8N0{2j9fO"xTQ\fnժU*PI^*""1d .lang { width: 90%; } table.spam-langs-table tr > .tick { width: 10%; } table.spam-langs-table thead th.tick a { padding-right: 24px; } table.address-rules-table thead th.sortedASC a, table.spam-langs-table thead th.sortedASC a { text-decoration: underline; background: url(images/listicons.png) no-repeat right -298px; } table.address-rules-table thead th.sortedDESC a, table.spam-langs-table thead th.sortedDESC a { text-decoration: underline; background: url(images/listicons.png) no-repeat right -330px; } table.address-rules-table thead th.rule { width: 180px; } table.address-rules-table thead th.control { width: 40px; } table.spam-langs-table tr > .lang, table.address-rules-table tr > .rule, table.address-rules-table tr > .email { text-align: left; vertical-align: middle; border-left: 0; border-right: 0; } table.spam-langs-table tr > .tick, table.address-rules-table tr > .control { text-align: right; vertical-align: middle; border-left: 0; border-right: 0; } table.spam-langs-table tbody td.tick a, table.address-rules-table tbody td.control a { display: block; float: right; width: 16px; height: 16px; background-image: url(images/icons.png); cursor: pointer; } table.address-rules-table tr > .control a.delete { background-position: 0 -1px; } table.spam-langs-table tr > .tick a.enabled { background-position: 0 -18px; } table.spam-langs-table tr > .tick a.disabled { background-position: 0 -36px; } .whitelist_from, .whitelist_to { color: #008800; text-align: left; vertical-align: middle; } .blacklist_from { color: #BB0000; text-align: left; vertical-align: middle; } #listcontrols { font-size: 11px; text-align: right; } #listcontrols a, #listcontrols a:active, #listcontrols a:visited { color: #2D5986; font-size: 11px; text-decoration: none; } #listcontrols a:hover { text-decoration: underline; } table.generalprefstable, table.langprefstable, table.headersprefstable, table.testsprefstable, table.bayesprefstable, table.reportprefstable, table.addressprefstable { width: 100%; border-spacing: 0; border-collapse: collapse; } table.generalprefstable td, table.langprefstable td, table.headersprefstable td, table.testsprefstable td, table.bayesprefstable td, table.reportprefstable td, table.addressprefstable td { width: 80%; padding: 4px 10px; background: #eee; border-bottom: 2px solid #fff; } table.addressprefstable td { width: auto; } table.generalprefstable tr > .title, table.langprefstable tr > .title, table.headersprefstable tr > .title, table.testsprefstable tr > .title, table.bayesprefstable tr > .title, table.reportprefstable tr > .title, table.addressprefstable tr > .title { width: 20%; color: #333; padding-right: 20px; white-space: nowrap; } table.addressprefstable tr > .ruletype { width: 180px; } table.addressprefstable tr > .address { width: 220px; } table.addressprefstable tr > .action { width: 100px; text-align: right; } table.langprefstable tr > .scroller, table.addressprefstable tr > .scroller { padding: 0; } span.helpicon { display: inline-block; width: 16px; height: 16px; background-image: url(images/icons.png); background-position: 0 -55px; } #sections-table #rcmrowtests td.section { background-image: url(images/listicons.png); background-position: 3px -199px; } #sections-table #rcmrowtests.selected td.section { background-image: url(images/listicons.png); background-position: 3px -225px; } #sections-table #rcmrowbayes td.section { background-image: url(images/listicons.png); background-position: 3px -248px; } #sections-table #rcmrowbayes.selected td.section { background-image: url(images/listicons.png); background-position: 3px -270px; } #sections-table #rcmrowheaders td.section { background-image: url(images/listicons.png); background-position: 3px -99px; } #sections-table #rcmrowheaders.selected td.section { background-image: url(images/listicons.png); background-position: 3px -124px; } #sections-table #rcmrowreport td.section { background-image: url(images/listicons.png); background-position: 3px -150px; } #sections-table #rcmrowreport.selected td.section { background-image: url(images/listicons.png); background-position: 3px -174px; } #sections-table #rcmrowaddresses td.section { background-image: url(images/listicons.png); background-position: 2px -50px; } #sections-table #rcmrowaddresses.selected td.section { background-image: url(images/listicons.png); background-position: 2px -74px; } #rcmfd_spamlevelchar { width: 20px; } #rcmfd_spamsubject, #rcmfd_spamaddress { width: 200px; }roundcube-sauserprefs-1.17.1/skins/larry/tabstyles.css000066400000000000000000000005131316336120600231330ustar00rootroot00000000000000/** * SAUserPrefs plugin styles (tab styles) */ #settings-sections #settingstabpluginsauserprefs a { background-image: url(images/listicons.png); background-position: 3px -3px; } #settings-sections #settingstabpluginsauserprefs.selected a { background-image: url(images/listicons.png); background-position: 3px -27px; }roundcube-sauserprefs-1.17.1/skins/larry/templates/000077500000000000000000000000001316336120600224065ustar00rootroot00000000000000roundcube-sauserprefs-1.17.1/skins/larry/templates/sauserprefs.html000066400000000000000000000031301316336120600256330ustar00rootroot00000000000000 <roundcube:object name="pagetitle" />

:

roundcube-sauserprefs-1.17.1/skins/larry/templates/settingsedit.html000066400000000000000000000014701316336120600260040ustar00rootroot00000000000000 <roundcube:object name="pagetitle" />