From 31de4bc5ebf9556817554ae9630ca06e92fd7218 Mon Sep 17 00:00:00 2001 From: Hugues Hiegel Date: Thu, 12 Sep 2013 11:35:26 +0200 Subject: Updates / Plugins --- plugins/sauserprefs/config.inc.php.dist | 160 ++++ .../include/rcube_sauserprefs_storage.php | 268 ++++++ plugins/sauserprefs/localization/cs_CZ.inc | 86 ++ plugins/sauserprefs/localization/de_CH.inc | 86 ++ plugins/sauserprefs/localization/de_DE.inc | 86 ++ plugins/sauserprefs/localization/en_GB.inc | 86 ++ plugins/sauserprefs/localization/en_US.inc | 86 ++ plugins/sauserprefs/localization/es_ES.inc | 85 ++ plugins/sauserprefs/localization/fr_FR.inc | 86 ++ plugins/sauserprefs/localization/gl_ES.inc | 85 ++ plugins/sauserprefs/localization/hu_HU.inc | 61 ++ plugins/sauserprefs/localization/it_IT.inc | 86 ++ plugins/sauserprefs/localization/pl_PL.inc | 86 ++ plugins/sauserprefs/localization/pt_BR.inc | 85 ++ plugins/sauserprefs/localization/ro_RO.inc | 85 ++ plugins/sauserprefs/localization/ru_RU.inc | 87 ++ plugins/sauserprefs/localization/sk_SK.inc | 86 ++ plugins/sauserprefs/localization/sv_SE.inc | 84 ++ plugins/sauserprefs/package.xml | 91 +++ plugins/sauserprefs/sauserprefs.js | 459 +++++++++++ plugins/sauserprefs/sauserprefs.php | 909 +++++++++++++++++++++ plugins/sauserprefs/skins/classic/help.gif | Bin 0 -> 1024 bytes plugins/sauserprefs/skins/classic/icons.gif | Bin 0 -> 1345 bytes plugins/sauserprefs/skins/classic/icons.png | Bin 0 -> 2045 bytes plugins/sauserprefs/skins/classic/ie6hacks.css | 9 + plugins/sauserprefs/skins/classic/iehacks.css | 9 + plugins/sauserprefs/skins/classic/safari.css | 6 + plugins/sauserprefs/skins/classic/sauserprefs.css | 185 +++++ plugins/sauserprefs/skins/classic/tabstyles.css | 3 + .../skins/classic/templates/sauserprefs.html | 47 ++ .../skins/classic/templates/settingsedit.html | 33 + plugins/sauserprefs/skins/larry/help.png | Bin 0 -> 475 bytes plugins/sauserprefs/skins/larry/icons.png | Bin 0 -> 962 bytes plugins/sauserprefs/skins/larry/iehacks.css | 9 + plugins/sauserprefs/skins/larry/listicons.png | Bin 0 -> 4891 bytes plugins/sauserprefs/skins/larry/safari.css | 6 + plugins/sauserprefs/skins/larry/sauserprefs.css | 253 ++++++ plugins/sauserprefs/skins/larry/tabstyles.css | 15 + .../skins/larry/templates/sauserprefs.html | 54 ++ .../skins/larry/templates/settingsedit.html | 30 + 40 files changed, 3892 insertions(+) create mode 100644 plugins/sauserprefs/config.inc.php.dist create mode 100644 plugins/sauserprefs/include/rcube_sauserprefs_storage.php create mode 100644 plugins/sauserprefs/localization/cs_CZ.inc create mode 100644 plugins/sauserprefs/localization/de_CH.inc create mode 100644 plugins/sauserprefs/localization/de_DE.inc create mode 100644 plugins/sauserprefs/localization/en_GB.inc create mode 100644 plugins/sauserprefs/localization/en_US.inc create mode 100644 plugins/sauserprefs/localization/es_ES.inc create mode 100644 plugins/sauserprefs/localization/fr_FR.inc create mode 100644 plugins/sauserprefs/localization/gl_ES.inc create mode 100644 plugins/sauserprefs/localization/hu_HU.inc create mode 100644 plugins/sauserprefs/localization/it_IT.inc create mode 100644 plugins/sauserprefs/localization/pl_PL.inc create mode 100644 plugins/sauserprefs/localization/pt_BR.inc create mode 100644 plugins/sauserprefs/localization/ro_RO.inc create mode 100644 plugins/sauserprefs/localization/ru_RU.inc create mode 100644 plugins/sauserprefs/localization/sk_SK.inc create mode 100644 plugins/sauserprefs/localization/sv_SE.inc create mode 100644 plugins/sauserprefs/package.xml create mode 100644 plugins/sauserprefs/sauserprefs.js create mode 100644 plugins/sauserprefs/sauserprefs.php create mode 100644 plugins/sauserprefs/skins/classic/help.gif create mode 100644 plugins/sauserprefs/skins/classic/icons.gif create mode 100644 plugins/sauserprefs/skins/classic/icons.png create mode 100644 plugins/sauserprefs/skins/classic/ie6hacks.css create mode 100644 plugins/sauserprefs/skins/classic/iehacks.css create mode 100644 plugins/sauserprefs/skins/classic/safari.css create mode 100644 plugins/sauserprefs/skins/classic/sauserprefs.css create mode 100644 plugins/sauserprefs/skins/classic/tabstyles.css create mode 100644 plugins/sauserprefs/skins/classic/templates/sauserprefs.html create mode 100644 plugins/sauserprefs/skins/classic/templates/settingsedit.html create mode 100644 plugins/sauserprefs/skins/larry/help.png create mode 100644 plugins/sauserprefs/skins/larry/icons.png create mode 100644 plugins/sauserprefs/skins/larry/iehacks.css create mode 100644 plugins/sauserprefs/skins/larry/listicons.png create mode 100644 plugins/sauserprefs/skins/larry/safari.css create mode 100644 plugins/sauserprefs/skins/larry/sauserprefs.css create mode 100644 plugins/sauserprefs/skins/larry/tabstyles.css create mode 100644 plugins/sauserprefs/skins/larry/templates/sauserprefs.html create mode 100644 plugins/sauserprefs/skins/larry/templates/settingsedit.html (limited to 'plugins/sauserprefs') diff --git a/plugins/sauserprefs/config.inc.php.dist b/plugins/sauserprefs/config.inc.php.dist new file mode 100644 index 000000000..81b85507f --- /dev/null +++ b/plugins/sauserprefs/config.inc.php.dist @@ -0,0 +1,160 @@ + "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 +$rcmail_config['sauserprefs_score_inc'] = 1; + +// allow the user to delete bayesian data +// please also see sauserprefs_bayes_delete_query option +$rcmail_config['sauserprefs_bayes_delete'] = false; + +// 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 +// eg. $rcmail_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;', +// ); +$rcmail_config['sauserprefs_bayes_delete_query'] = ''; + +// define languages +$rcmail_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" + ); +?> \ No newline at end of file diff --git a/plugins/sauserprefs/include/rcube_sauserprefs_storage.php b/plugins/sauserprefs/include/rcube_sauserprefs_storage.php new file mode 100644 index 000000000..0819d5cf4 --- /dev/null +++ b/plugins/sauserprefs/include/rcube_sauserprefs_storage.php @@ -0,0 +1,268 @@ +db_dsnw = $db_dsnw; + $this->db_dsnr = $db_dsnr; + $this->db_persistent = $db_persistent; + $this->sa_user = $sa_user; + $this->table_name = $table_name; + $this->username_field = $username_field; + $this->preference_field = $preference_field; + $this->value_field = $value_field; + $this->bayes_delete_query = $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, true); + $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] != sauserprefs::map_pref_name($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($new_prefs, $cur_prefs, $global_prefs) + { + $this->_db_connect('w'); + $result = true; + + // save prefs + foreach ($new_prefs as $preference => $value) { + if ($preference == 'addresses') { + foreach ($value as $address) { + if ($address['action'] == "DELETE") { + $result = false; + + $this->db->query( + "DELETE FROM ". $this->table_name. + " WHERE ". $this->username_field ." = ?". + " AND ". $this->preference_field ." = ?". + " AND ". $this->value_field ." = ?;", + $this->sa_user, + sauserprefs::map_pref_name($address['field']), + $address['value']); + + $result = $this->db->affected_rows(); + + if (!$result) { + rcube::write_log('errors', 'sauserprefs error: cannot delete "' . sauserprefs::map_pref_name($prefs[$idx]) . '" = "' . $vals[$idx] . '" for ' . $this->sa_user); + break; + } + } + elseif ($address['action'] == "INSERT") { + $result = false; + + $this->db->query( + "INSERT INTO ". $this->table_name. + " (". $this->username_field. + ", ". $this->preference_field. + ", ". $this->value_field. + ") VALUES (?, ?, ?);", + $this->sa_user, + sauserprefs::map_pref_name($address['field']), + $address['value']); + + $result = $this->db->affected_rows(); + + if (!$result) { + rcube::write_log('errors', 'sauserprefs error: cannot insert "' . sauserprefs::map_pref_name($prefs[$idx]) . '" = "' . $vals[$idx] . '" for ' . $this->sa_user); + break; + } + } + } + } + elseif (array_key_exists($preference, $cur_prefs) && ($value == "" || $value == $global_prefs[$preference])) { + $result = false; + + $this->db->query( + "DELETE FROM ". $this->table_name. + " WHERE ". $this->username_field ." = ?". + " AND ". $this->preference_field ." = ?;", + $this->sa_user, + sauserprefs::map_pref_name($preference)); + + $result = $this->db->affected_rows(); + + if (!$result) { + rcube::write_log('errors', 'sauserprefs error: cannot delete "' . sauserprefs::map_pref_name($preference) . '" for "' . $this->sa_user); + break; + } + } + elseif (array_key_exists($preference, $cur_prefs) && $value != $cur_prefs[$preference]) { + $result = false; + + $this->db->query( + "UPDATE ". $this->table_name. + " SET ". $this->value_field ." = ?". + " WHERE ". $this->username_field ." = ?". + " AND ". $this->preference_field ." = ?;", + $value, + $this->sa_user, + sauserprefs::map_pref_name($preference)); + + $result = $this->db->affected_rows(); + + if (!$result) { + rcube::write_log('errors', 'sauserprefs error: cannot update "' . sauserprefs::map_pref_name($preference) . '" = "' . $value . '" for ' . $this->sa_user); + break; + } + } + elseif (!array_key_exists($preference, $cur_prefs) && $value != $global_prefs[$preference]) { + $result = false; + + $this->db->query( + "INSERT INTO ". $this->table_name. + " (". $this->username_field. + ", ". $this->preference_field. + ", ". $this->value_field. + ") VALUES (?, ?, ?);", + $this->sa_user, + sauserprefs::map_pref_name($preference), + $value); + + $result = $this->db->affected_rows(); + + if (!$result) { + rcube::write_log('errors', 'sauserprefs error: cannot insert "' . sauserprefs::map_pref_name($preference) . '" = "' . $value . '" for ' . $this->sa_user); + break; + } + } + } + + return $result; + } + + function whitelist_add($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 ." = ?;", + $this->sa_user, + 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 (?, ?, ?);", + $this->sa_user, + sauserprefs::map_pref_name('whitelist_from'), + $email); + } + } + + function whitelist_delete($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 ." = ?;", + $this->sa_user, + sauserprefs::map_pref_name('whitelist_from'), + $email); + + } + + function purge_bayes() + { + $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($this->sa_user, 'text'), $sql); + $this->db->query($sql); + + if ($this->db->is_error()) + break; + } + + if (!$this->db->is_error()) + return true; + else + return false; + } + + private function _db_connect($mode) + { + if (!$this->db) + $this->db = rcube_db::factory($this->db_dsnw, $this->db_dsnr, $this->db_persistent); + + $this->db->db_connect($mode); + + // check DB connections and exit on failure + if ($err_str = $this->db->is_error()) { + raise_error(array( + 'code' => 603, + 'type' => 'db', + 'message' => $err_str), false, true); + } + } +} + +?> \ No newline at end of file diff --git a/plugins/sauserprefs/localization/cs_CZ.inc b/plugins/sauserprefs/localization/cs_CZ.inc new file mode 100644 index 000000000..53be0e691 --- /dev/null +++ b/plugins/sauserprefs/localization/cs_CZ.inc @@ -0,0 +1,86 @@ + \ No newline at end of file diff --git a/plugins/sauserprefs/localization/de_CH.inc b/plugins/sauserprefs/localization/de_CH.inc new file mode 100644 index 000000000..00cd54ffb --- /dev/null +++ b/plugins/sauserprefs/localization/de_CH.inc @@ -0,0 +1,86 @@ + \ No newline at end of file diff --git a/plugins/sauserprefs/localization/de_DE.inc b/plugins/sauserprefs/localization/de_DE.inc new file mode 100644 index 000000000..00cd54ffb --- /dev/null +++ b/plugins/sauserprefs/localization/de_DE.inc @@ -0,0 +1,86 @@ + \ No newline at end of file diff --git a/plugins/sauserprefs/localization/en_GB.inc b/plugins/sauserprefs/localization/en_GB.inc new file mode 100644 index 000000000..6c500af9f --- /dev/null +++ b/plugins/sauserprefs/localization/en_GB.inc @@ -0,0 +1,86 @@ + \ No newline at end of file diff --git a/plugins/sauserprefs/localization/en_US.inc b/plugins/sauserprefs/localization/en_US.inc new file mode 100644 index 000000000..6c500af9f --- /dev/null +++ b/plugins/sauserprefs/localization/en_US.inc @@ -0,0 +1,86 @@ + \ No newline at end of file diff --git a/plugins/sauserprefs/localization/es_ES.inc b/plugins/sauserprefs/localization/es_ES.inc new file mode 100644 index 000000000..26dcb63d1 --- /dev/null +++ b/plugins/sauserprefs/localization/es_ES.inc @@ -0,0 +1,85 @@ + \ No newline at end of file diff --git a/plugins/sauserprefs/localization/fr_FR.inc b/plugins/sauserprefs/localization/fr_FR.inc new file mode 100644 index 000000000..c8ce746b1 --- /dev/null +++ b/plugins/sauserprefs/localization/fr_FR.inc @@ -0,0 +1,86 @@ + \ No newline at end of file diff --git a/plugins/sauserprefs/localization/gl_ES.inc b/plugins/sauserprefs/localization/gl_ES.inc new file mode 100644 index 000000000..e7dfe159a --- /dev/null +++ b/plugins/sauserprefs/localization/gl_ES.inc @@ -0,0 +1,85 @@ + \ No newline at end of file diff --git a/plugins/sauserprefs/localization/hu_HU.inc b/plugins/sauserprefs/localization/hu_HU.inc new file mode 100644 index 000000000..952f3f1cf --- /dev/null +++ b/plugins/sauserprefs/localization/hu_HU.inc @@ -0,0 +1,61 @@ + \ No newline at end of file diff --git a/plugins/sauserprefs/localization/it_IT.inc b/plugins/sauserprefs/localization/it_IT.inc new file mode 100644 index 000000000..67f4a99a0 --- /dev/null +++ b/plugins/sauserprefs/localization/it_IT.inc @@ -0,0 +1,86 @@ + \ No newline at end of file diff --git a/plugins/sauserprefs/localization/pl_PL.inc b/plugins/sauserprefs/localization/pl_PL.inc new file mode 100644 index 000000000..eaae55944 --- /dev/null +++ b/plugins/sauserprefs/localization/pl_PL.inc @@ -0,0 +1,86 @@ + \ No newline at end of file diff --git a/plugins/sauserprefs/localization/pt_BR.inc b/plugins/sauserprefs/localization/pt_BR.inc new file mode 100644 index 000000000..f5eb14327 --- /dev/null +++ b/plugins/sauserprefs/localization/pt_BR.inc @@ -0,0 +1,85 @@ + \ No newline at end of file diff --git a/plugins/sauserprefs/localization/ro_RO.inc b/plugins/sauserprefs/localization/ro_RO.inc new file mode 100644 index 000000000..dff15fd1f --- /dev/null +++ b/plugins/sauserprefs/localization/ro_RO.inc @@ -0,0 +1,85 @@ + \ No newline at end of file diff --git a/plugins/sauserprefs/localization/ru_RU.inc b/plugins/sauserprefs/localization/ru_RU.inc new file mode 100644 index 000000000..3681836bb --- /dev/null +++ b/plugins/sauserprefs/localization/ru_RU.inc @@ -0,0 +1,87 @@ + \ No newline at end of file diff --git a/plugins/sauserprefs/localization/sk_SK.inc b/plugins/sauserprefs/localization/sk_SK.inc new file mode 100644 index 000000000..4cefe9928 --- /dev/null +++ b/plugins/sauserprefs/localization/sk_SK.inc @@ -0,0 +1,86 @@ + \ No newline at end of file diff --git a/plugins/sauserprefs/localization/sv_SE.inc b/plugins/sauserprefs/localization/sv_SE.inc new file mode 100644 index 000000000..029ee86a5 --- /dev/null +++ b/plugins/sauserprefs/localization/sv_SE.inc @@ -0,0 +1,84 @@ + \ No newline at end of file diff --git a/plugins/sauserprefs/package.xml b/plugins/sauserprefs/package.xml new file mode 100644 index 000000000..e6845a1dc --- /dev/null +++ b/plugins/sauserprefs/package.xml @@ -0,0 +1,91 @@ + + + sauserprefs + http://github.com/JohnDoh/Roundcube-Plugin-SpamAssassin-User-Prefs-SQL/ + Control SpamAssassin settings from within Roundcube + Adds a 'Spam' tab to the 'Personal Settings' to allow the user to change their SpamAssassin preferences. Preferences must be stored in a SQL database. Default preferences are used when no user preference is found. + + Philip Weir + JohnDoh + roundcube@tehinterweb.co.uk + yes + + 2013-02-24 + + + 1.10 + 1.10 + + + stable + stable + + GNU GPLv3+ + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5.2.1 + + + 1.7.0 + + + + + diff --git a/plugins/sauserprefs/sauserprefs.js b/plugins/sauserprefs/sauserprefs.js new file mode 100644 index 000000000..3b965566f --- /dev/null +++ b/plugins/sauserprefs/sauserprefs.js @@ -0,0 +1,459 @@ +/** + * SAUserPrefs plugin script + */ + +rcube_webmail.prototype.sauserprefs_toggle_level_char = function(checkbox) { + var level_char; + + if (level_char = rcube_find_object('rcmfd_spamlevelchar')) + level_char.disabled = !checkbox.checked; +} + +rcube_webmail.prototype.sauserprefs_toggle_bayes = function(checkbox) { + var tickbox; + var dropdown; + + if (tickbox = rcube_find_object('rcmfd_spambayesrules')) + tickbox.disabled = !checkbox.checked; + + if (tickbox = rcube_find_object('rcmfd_spambayesautolearn')) + tickbox.disabled = !checkbox.checked; + + if ((dropdown = rcube_find_object('rcmfd_bayesnonspam')) && (tickbox.checked || !checkbox.checked)) + dropdown.disabled = !checkbox.checked; + + if ((dropdown = rcube_find_object('rcmfd_bayesspam')) && (tickbox.checked || !checkbox.checked)) + dropdown.disabled = !checkbox.checked; +} + +rcube_webmail.prototype.sauserprefs_toggle_bayes_auto = function(checkbox) { + var dropdown; + + if (dropdown = rcube_find_object('rcmfd_bayesnonspam')) + dropdown.disabled = !checkbox.checked; + + if (dropdown = rcube_find_object('rcmfd_bayesspam')) + dropdown.disabled = !checkbox.checked; +} + +rcube_webmail.prototype.sauserprefs_addressrule_import = function(address) { + parent.rcmail.set_busy(false, null, rcmail.env.sauserprefs_whitelist); + + var adrTable = rcube_find_object('address-rules-table').tBodies[0]; + + var actions = document.getElementsByName('_address_rule_act[]'); + var prefs = document.getElementsByName('_address_rule_field[]'); + var addresses = document.getElementsByName('_address_rule_value[]'); + var insHere; + + for (var i = 1; i < addresses.length; i++) { + if (addresses[i].value == address && actions[i].value != "DELETE") { + return false; + } + else if (addresses[i].value > address) { + insHere = adrTable.rows[i + 1]; + break; + } + } + + var newNode = adrTable.rows[0].cloneNode(true); + adrTable.rows[1].style.display = 'none'; + + if (insHere) + adrTable.insertBefore(newNode, insHere); + else + adrTable.appendChild(newNode); + + newNode.style.display = ""; + newNode.cells[0].className = "whitelist_from"; + newNode.cells[0].innerHTML = rcmail.gettext('whitelist_from','sauserprefs'); + newNode.cells[1].innerHTML = address; + actions[newNode.rowIndex - 2].value = "INSERT"; + prefs[newNode.rowIndex - 2].value = "whitelist_from"; + addresses[newNode.rowIndex - 2].value = address; + + rcmail.env.address_rule_count++; +} + +rcube_webmail.prototype.sauserprefs_help = function(sel) { + var help = rcube_find_object(sel); + help.style.display = (help.style.display == 'none' ? '' : 'none'); + return false; +} + +$(document).ready(function() { + if (window.rcmail) { + rcmail.addEventListener('init', function(evt) { + var tab = $('').attr('id', 'settingstabpluginsauserprefs').addClass('tablink'); + var button = $('').attr('href', rcmail.env.comm_path+'&_action=plugin.sauserprefs').attr('title', rcmail.gettext('managespam', 'sauserprefs')).html(rcmail.gettext('sauserprefs','sauserprefs')).appendTo(tab); + + // add button and register command + rcmail.add_element(tab, 'tabs'); + + if (rcmail.env.action == 'plugin.sauserprefs.edit') { + rcmail.register_command('plugin.sauserprefs.select_all_langs', function() { + var langlist = document.getElementsByName('_spamlang[]'); + var obj; + + for (var i = 0; i < langlist.length; i++) { + langlist[i].checked = true; + obj = rcube_find_object('spam_lang_'+ i); + obj.title = rcmail.gettext('enabled','sauserprefs'); + obj.className = 'enabled'; + } + + return false; + }, true); + + rcmail.register_command('plugin.sauserprefs.select_invert_langs', function() { + var langlist = document.getElementsByName('_spamlang[]'); + var obj; + + for (var i = 0; i < langlist.length; i++) { + if (langlist[i].checked) { + langlist[i].checked = false; + obj = rcube_find_object('spam_lang_'+ i); + obj.title = rcmail.gettext('disabled','sauserprefs'); + obj.className = 'disabled'; + } + else { + langlist[i].checked = true; + obj = rcube_find_object('spam_lang_'+ i); + obj.title = rcmail.gettext('enabled','sauserprefs'); + obj.className = 'enabled'; + } + } + + return false; + }, true); + + rcmail.register_command('plugin.sauserprefs.select_no_langs', function() { + var langlist = document.getElementsByName('_spamlang[]'); + var obj; + + for (var i = 0; i < langlist.length; i++) { + langlist[i].checked = false; + obj = rcube_find_object('spam_lang_'+ i); + obj.title = rcmail.gettext('disabled','sauserprefs'); + obj.className = 'disabled'; + } + + return false; + }, true); + + rcmail.register_command('plugin.sauserprefs.message_lang', function(lang_code, obj) { + var langlist = document.getElementsByName('_spamlang[]'); + var i = obj.parentNode.parentNode.rowIndex - 1; + + if (langlist[i].checked) { + langlist[i].checked = false; + obj.title = rcmail.gettext('disabled','sauserprefs'); + obj.className = 'disabled'; + } + else { + langlist[i].checked = true; + obj.title = rcmail.gettext('enabled','sauserprefs'); + obj.className = 'enabled'; + } + + return false; + }, true); + + rcmail.register_command('plugin.sauserprefs.addressrule_del', function(props, obj) { + var adrTable = rcube_find_object('address-rules-table').tBodies[0]; + var rowidx = obj.parentNode.parentNode.rowIndex - 1; + var fieldidx = rowidx - 1; + + if (!confirm(rcmail.gettext('spamaddressdelete','sauserprefs'))) + return false; + + if (document.getElementsByName('_address_rule_act[]')[fieldidx].value == "INSERT") { + adrTable.deleteRow(rowidx); + } + else { + adrTable.rows[rowidx].style.display = 'none'; + document.getElementsByName('_address_rule_act[]')[fieldidx].value = "DELETE"; + } + + rcmail.env.address_rule_count--; + if (rcmail.env.address_rule_count < 1) + adrTable.rows[1].style.display = ''; + + return false; + }, true); + + rcmail.register_command('plugin.sauserprefs.addressrule_add', function() { + var adrTable = rcube_find_object('address-rules-table').tBodies[0]; + var input_spamaddressrule = rcube_find_object('_spamaddressrule'); + var selrule = input_spamaddressrule.selectedIndex; + var input_spamaddress = rcube_find_object('_spamaddress'); + + if (input_spamaddress.value.replace(/^\s+|\s+$/g, '') == '') { + alert(rcmail.gettext('spamenteraddress','sauserprefs')); + input_spamaddress.focus(); + return false; + } + else if (!rcube_check_email(input_spamaddress.value.replace(/^\s+/, '').replace(/[\s,;]+$/, ''), true)) { + alert(rcmail.gettext('spamaddresserror','sauserprefs')); + input_spamaddress.focus(); + return false; + } + else { + var actions = document.getElementsByName('_address_rule_act[]'); + var prefs = document.getElementsByName('_address_rule_field[]'); + var addresses = document.getElementsByName('_address_rule_value[]'); + var insHere; + + for (var i = 1; i < addresses.length; i++) { + if (addresses[i].value == input_spamaddress.value && actions[i].value != "DELETE") { + alert(rcmail.gettext('spamaddressexists','sauserprefs')); + input_spamaddress.focus(); + return false; + } + else if (addresses[i].value > input_spamaddress.value) { + insHere = adrTable.rows[i + 1]; + break; + } + } + + var newNode = adrTable.rows[0].cloneNode(true); + adrTable.rows[1].style.display = 'none'; + + if (insHere) + adrTable.insertBefore(newNode, insHere); + else + adrTable.appendChild(newNode); + + newNode.style.display = ""; + newNode.cells[0].className = input_spamaddressrule.options[selrule].value; + newNode.cells[0].innerHTML = input_spamaddressrule.options[selrule].text; + newNode.cells[1].innerHTML = input_spamaddress.value; + actions[newNode.rowIndex - 2].value = "INSERT"; + prefs[newNode.rowIndex - 2].value = input_spamaddressrule.options[selrule].value; + addresses[newNode.rowIndex - 2].value = input_spamaddress.value; + + input_spamaddressrule.selectedIndex = 0; + input_spamaddress.value = ''; + + rcmail.env.address_rule_count++; + } + }, true); + + rcmail.register_command('plugin.sauserprefs.whitelist_delete_all', function(props, obj) { + var adrTable = rcube_find_object('address-rules-table').tBodies[0]; + + if (!confirm(rcmail.gettext('spamaddressdeleteall','sauserprefs'))) + return false; + + for (var i = adrTable.rows.length - 1; i > 1; i--) { + if (document.getElementsByName('_address_rule_act[]')[i-1].value == "INSERT") { + adrTable.deleteRow(i); + rcmail.env.address_rule_count--; + } + else if (document.getElementsByName('_address_rule_act[]')[i-1].value != "DELETE") { + adrTable.rows[i].style.display = 'none'; + document.getElementsByName('_address_rule_act[]')[i-1].value = "DELETE"; + rcmail.env.address_rule_count--; + } + } + + adrTable.rows[1].style.display = ''; + return false; + }, true); + + rcmail.register_command('plugin.sauserprefs.import_whitelist', function(props, obj) { + rcmail.env.sauserprefs_whitelist = rcmail.set_busy(true, 'sauserprefs.importingaddresses'); + rcmail.http_request('plugin.sauserprefs.whitelist_import', '', rcmail.env.sauserprefs_whitelist); + return false; + }, true); + + rcmail.register_command('plugin.sauserprefs.purge_bayes', function(props, obj) { + if (confirm(rcmail.gettext('purgebayesconfirm','sauserprefs'))) { + var lock = rcmail.set_busy(true, 'sauserprefs.purgingbayes'); + rcmail.http_request('plugin.sauserprefs.purge_bayes', '', lock); + } + + return false; + }, true); + + rcmail.register_command('plugin.sauserprefs.save', function() { rcmail.gui_objects.editform.submit(); }, true); + + rcmail.register_command('plugin.sauserprefs.default', function() { + if (confirm(rcmail.gettext('usedefaultconfirm','sauserprefs'))) { + // Score + if (rcube_find_object('rcmfd_spamthres')) + rcube_find_object('rcmfd_spamthres').selectedIndex = 0; + + // Subject tag + if (rcube_find_object('rcmfd_spamsubject')) + rcube_find_object('rcmfd_spamsubject').value = rcmail.env.rewrite_header_Subject + + // Languages + var langlist = document.getElementsByName('_spamlang[]'); + var obj; + var dlangs = " " + rcmail.env.ok_languages + " "; + + for (var i = 0; i < langlist.length; i++) { + langlist[i].checked = false; + obj = rcube_find_object('spam_lang_' + i); + obj.title = rcmail.gettext('disabled','sauserprefs'); + obj.className = 'disabled'; + + if (dlangs.indexOf(" " + langlist[i].value + " ") > -1) { + langlist[i].checked = true; + obj = rcube_find_object('spam_lang_' + i); + obj.title = rcmail.gettext('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 == '1') + 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.skip_rbl_checks == '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')) { + var adrTable = rcube_find_object('address-rules-table').tBodies[0]; + for (var i = adrTable.rows.length - 1; i > 1; i--) { + if (document.getElementsByName('_address_rule_act[]')[i-1].value == "INSERT") { + adrTable.deleteRow(i); + rcmail.env.address_rule_count--; + } + else if (document.getElementsByName('_address_rule_act[]')[i-1].value != "DELETE") { + adrTable.rows[i].style.display = 'none'; + document.getElementsByName('_address_rule_act[]')[i-1].value = "DELETE"; + rcmail.env.address_rule_count--; + } + } + adrTable.rows[1].style.display = ''; + } + } + }, 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; + } + } + } +}); \ No newline at end of file diff --git a/plugins/sauserprefs/sauserprefs.php b/plugins/sauserprefs/sauserprefs.php new file mode 100644 index 000000000..8cab496b7 --- /dev/null +++ b/plugins/sauserprefs/sauserprefs.php @@ -0,0 +1,909 @@ + 'required_score'); + + 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); + + // init storage + include('include/rcube_sauserprefs_storage.php'); + $this->storage = new rcube_sauserprefs_storage($rcmail->config->get('sauserprefs_db_dsnw'), $rcmail->config->get('sauserprefs_db_dsnr'), $rcmail->config->get('sauserprefs_db_persistent'), + $this->sa_user, $rcmail->config->get('sauserprefs_sql_table_name'), $rcmail->config->get('sauserprefs_sql_username_field'), $rcmail->config->get('sauserprefs_sql_preference_field'), + $rcmail->config->get('sauserprefs_sql_value_field'), $rcmail->config->get('sauserprefs_bayes_delete_query')); + + if ($rcmail->config->get('sauserprefs_whitelist_abook_id', false)) + $this->addressbook = $rcmail->config->get('sauserprefs_whitelist_abook_id'); + + if ($rcmail->task == 'settings') { + $this->add_texts('localization/', array('sauserprefs', 'managespam')); + $this->include_stylesheet($this->local_skin_path() . '/tabstyles.css'); + + $this->sections = array( + 'general' => array('id' => 'general', 'section' => $this->gettext('spamgeneralsettings')), + 'tests' => array('id' => 'tests', 'section' => $this->gettext('spamtests')), + 'bayes' => array('id' => 'bayes', 'section' => $this->gettext('bayes')), + 'headers' => array('id' => 'headers', 'section' => $this->gettext('headers')), + 'report' => array('id' => 'report','section' => $this->gettext('spamreportsettings')), + 'addresses' => array('id' => 'addresses', 'section' => $this->gettext('spamaddressrules')), + ); + $this->cur_section = rcube_utils::get_input_value('_section', rcube_utils::INPUT_GPC); + + $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')); + $this->include_script('sauserprefs.js'); + } + elseif ($rcmail->config->get('sauserprefs_whitelist_sync')) { + $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 init_html() + { + $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->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) + { + $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(); + $blocks = $attrib['sections'] ? preg_split('/[\s,;]+/', strip_quotes($attrib['sections'])) : array_keys($this->sections); + foreach ($blocks as $block) { + if (!isset($no_override['{' . $block . '}'])) + $sections[$block] = $this->sections[$block]; + } + + // create XHTML table + $out = rcube::get_instance()->table_output($attrib, $sections, array('section'), '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 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() + { + return $this->sections[$this->cur_section]['section']; + } + + function save() + { + $rcmail = rcube::get_instance(); + $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_hits'])) + $new_prefs['required_hits'] = rcube_utils::get_input_value('_spamthres', rcube_utils::INPUT_POST); + + 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))) { + $locales = array_intersect(rcube_utils::get_input_value('_spamlang', rcube_utils::INPUT_POST), $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']) && !empty($_POST['_bayesnonspam'])) + $new_prefs['bayes_auto_learn_threshold_nonspam'] = rcube_utils::get_input_value('_bayesnonspam', rcube_utils::INPUT_POST); + + if (!isset($no_override['bayes_auto_learn_threshold_spam']) && !empty($_POST['_bayesspam'])) + $new_prefs['bayes_auto_learn_threshold_spam'] = rcube_utils::get_input_value('_bayesspam', rcube_utils::INPUT_POST); + + 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($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() + { + $contacts = rcube::get_instance()->get_address_book($this->addressbook); + $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(); + + if (!$rcmail->config->get('sauserprefs_bayes_delete', false)) { + $this->api->output->command('display_message', $this->gettext('servererror'), 'error'); + return; + } + + if ($this->storage->purge_bayes()) + $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) + { + $rcmail = rcube::get_instance(); + + // only works with specified address book + if ($args['source'] != $this->addressbook && $args['source'] != null) + return; + + $emails = $this->_gen_email_arr($args['record']); + $this->storage->whitelist_add($emails); + } + + function contact_save($args) + { + $this->contact_delete($args); + $this->contact_add($args); + } + + function contact_delete($args) + { + $rcmail = rcube::get_instance(); + + // only works with specified address book + if ($args['source'] != $this->addressbook && $args['source'] != null) + return; + + if (!is_array($args['id'])) + $args['id'] = array($args['id']); + + $contacts = $rcmail->get_address_book($this->addressbook); + foreach ($args['id'] as $id) { + $emails = $this->_gen_email_arr($contacts->get_record($id, true)); + $this->storage->whitelist_delete($emails); + } + + $contacts->close(); + } + + 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 + $prefs['addresses'] = $this->_subval_sort($prefs['addresses'], 'value'); + + 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(); + + switch ($part) + { + // General tests + case 'general': + $out = ''; + $data = ''; + + $table = new html_table(array('class' => 'generalprefstable', 'cols' => 2)); + + if (!isset($no_override['required_hits'])) { + $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_hits'] && (float)$this->user_prefs['required_hits'] == (float)$i) + $score_found = true; + } + + if (!$score_found && $this->user_prefs['required_hits']) + $input_spamthres->add(str_replace('%s', $this->user_prefs['required_hits'], $this->gettext('otherscore')), (float)$this->user_prefs['required_hits']); + + $table->add('title', html::label($field_id, rcmail::Q($this->gettext('spamthres')))); + $table->add(null, $input_spamthres->show(number_format($this->user_prefs['required_hits'], $decPlaces, '.', ''))); + $table->add(array('colspan' => 2), 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'], 'style' => 'width:200px;')); + + $table->add('title', html::label($field_id, rcmail::Q($this->gettext('spamsubject')))); + $table->add(null, $input_spamsubject->show()); + + $table->add('title', " "); + $table->add(null, rcmail::Q($this->gettext('spamsubjectblank'))); + } + + if ($table->size() > 0) + $out .= html::tag('fieldset', null, html::tag('legend', null, rcmail::Q($this->gettext('mainoptions'))) . $table->show()); + + if (!isset($no_override['ok_languages']) || !isset($no_override['ok_locales'])) { + $data = html::p(null, rcmail::Q($this->gettext('spamlangexp'))); + + $table = new html_table(array('class' => 'langprefstable', 'cols' => 1)); + + $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')); + + $table->add(array('id' => 'listcontrols'), $this->gettext('select') .":  ". $select_all ."  ". $select_invert ."  ". $select_none); + + $lang_table = new html_table(array('id' => 'spam-langs-table', 'class' => 'records-table', 'cellspacing' => '0', 'cols' => 2)); + $lang_table->add_header(array('colspan' => 2), $this->gettext('language')); + + 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++; + } + + $table->add('scroller', html::div(array('id' => 'spam-langs-cont'), $lang_table->show())); + + $out .= html::tag('fieldset', null, html::tag('legend', null, rcmail::Q($this->gettext('langoptions'))) . $data . $table->show()); + } + + break; + + // Header settings + case 'headers': + $data = html::p(null, rcmail::Q($this->gettext('headersexp'))); + + $table = new html_table(array('class' => 'headersprefstable', 'cols' => 3)); + + if (!isset($no_override['fold_headers'])) { + $help_button = html::img(array('class' => $imgclass, 'src' => $attrib['helpicon'], 'alt' => $this->gettext('sieveruleheaders'), 'border' => 0, 'style' => 'margin-left: 4px;')); + $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')); + + $table->add('title', html::label($field_id, rcmail::Q($this->gettext('foldheaders')))); + $table->add(null, $input_spamreport->show($this->user_prefs['fold_headers'])); + $table->add('help', $help_button); + $table->set_row_attribs(array('id' => 'fold_help', 'style' => 'display: none;')); + $table->add(array('colspan' => '3'), rcmail::Q($this->gettext('foldhelp'))); + } + + if (!isset($no_override['add_header all Level'])) { + $help_button = html::img(array('class' => $imgclass, 'src' => $attrib['helpicon'], 'alt' => $this->gettext('sieveruleheaders'), 'border' => 0, 'style' => 'margin-left: 4px;')); + $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)')); + + $table->add('title', html::label($field_id, rcmail::Q($this->gettext('spamlevelstars')))); + $table->add(null, $input_spamreport->show($enabled)); + $table->add('help', $help_button); + $table->set_row_attribs(array('id' => 'level_help', 'style' => 'display: none;')); + $table->add(array('colspan' => '3'), rcmail::Q($this->gettext('levelhelp'))); + + $field_id = 'rcmfd_spamlevelchar'; + $input_spamsubject = new html_inputfield(array('name' => '_spamlevelchar', 'id' => $field_id, 'value' => $char, + 'style' => 'width:20px;', 'disabled' => $enabled?0:1)); + + $table->add('title', html::label($field_id, rcmail::Q($this->gettext('spamlevelchar')))); + $table->add(null, $input_spamsubject->show()); + $table->add('help', ' '); + } + + $out = html::tag('fieldset', null, html::tag('legend', null, rcmail::Q($this->gettext('mainoptions'))) . $data . $table->show()); + break; + + // Test settings + case 'tests': + $data = html::p(null, rcmail::Q($this->gettext('spamtestssexp'))); + + $table = new html_table(array('class' => 'testsprefstable', 'cols' => 3)); + + if (!isset($no_override['use_razor1'])) { + $help_button = html::img(array('class' => $imgclass, 'src' => $attrib['helpicon'], 'alt' => $this->gettext('sieveruleheaders'), 'border' => 0, 'style' => 'margin-left: 4px;')); + $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')); + + $table->add('title', html::label($field_id, rcmail::Q($this->gettext('userazor1')))); + $table->add(null, $input_spamtest->show($this->user_prefs['use_razor1'])); + $table->add('help', $help_button); + $table->set_row_attribs(array('id' => 'raz1_help', 'style' => 'display: none;')); + $table->add(array('colspan' => '3'), rcmail::Q($this->gettext('raz1help'))); + } + + if (!isset($no_override['use_razor2'])) { + $help_button = html::img(array('class' => $imgclass, 'src' => $attrib['helpicon'], 'alt' => $this->gettext('sieveruleheaders'), 'border' => 0, 'style' => 'margin-left: 4px;')); + $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')); + + $table->add('title', html::label($field_id, rcmail::Q($this->gettext('userazor2')))); + $table->add(null, $input_spamtest->show($this->user_prefs['use_razor2'])); + $table->add('help', $help_button); + $table->set_row_attribs(array('id' => 'raz2_help', 'style' => 'display: none;')); + $table->add(array('colspan' => '3'), rcmail::Q($this->gettext('raz2help'))); + } + + if (!isset($no_override['use_pyzor'])) { + $help_button = html::img(array('class' => $imgclass, 'src' => $attrib['helpicon'], 'alt' => $this->gettext('sieveruleheaders'), 'border' => 0, 'style' => 'margin-left: 4px;')); + $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')); + + $table->add('title', html::label($field_id, rcmail::Q($this->gettext('usepyzor')))); + $table->add(null, $input_spamtest->show($this->user_prefs['use_pyzor'])); + $table->add('help', $help_button); + $table->set_row_attribs(array('id' => 'pyz_help', 'style' => 'display: none;')); + $table->add(array('colspan' => '3'), rcmail::Q($this->gettext('pyzhelp'))); + } + + if (!isset($no_override['use_dcc'])) { + $help_button = html::img(array('class' => $imgclass, 'src' => $attrib['helpicon'], 'alt' => $this->gettext('sieveruleheaders'), 'border' => 0, 'style' => 'margin-left: 4px;')); + $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')); + + $table->add('title', html::label($field_id, rcmail::Q($this->gettext('usedcc')))); + $table->add(null, $input_spamtest->show($this->user_prefs['use_dcc'])); + $table->add('help', $help_button); + $table->set_row_attribs(array('id' => 'dcc_help', 'style' => 'display: none;')); + $table->add(array('colspan' => '3'), rcmail::Q($this->gettext('dcchelp'))); + } + + if (!isset($no_override['skip_rbl_checks'])) { + $help_button = html::img(array('class' => $imgclass, 'src' => $attrib['helpicon'], 'alt' => $this->gettext('sieveruleheaders'), 'border' => 0, 'style' => 'margin-left: 4px;')); + $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')); + + $table->add('title', html::label($field_id, rcmail::Q($this->gettext('skiprblchecks')))); + $table->add(null, $input_spamtest->show($enabled)); + $table->add('help', $help_button); + $table->set_row_attribs(array('id' => 'rbl_help', 'style' => 'display: none;')); + $table->add(array('colspan' => '3'), rcmail::Q($this->gettext('rblhelp'))); + } + + $out = html::tag('fieldset', null, html::tag('legend', null, rcmail::Q($this->gettext('mainoptions'))) . $data . $table->show()); + break; + + // Bayes settings + case 'bayes': + $data = html::p(null, rcmail::Q($this->gettext('bayeshelp'))); + + $table = new html_table(array('class' => 'bayesprefstable', 'cols' => 3)); + + if (!isset($no_override['use_bayes'])) { + $help_button = html::img(array('class' => $imgclass, 'src' => $attrib['helpicon'], 'alt' => $this->gettext('sieveruleheaders'), 'border' => 0, 'style' => 'margin-left: 4px;')); + $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 ($rcmail->config->get('sauserprefs_bayes_delete', false)) + $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'))); + + $table->add('title', html::label($field_id, rcmail::Q($this->gettext('usebayes')))); + $table->add(null, $input_spamtest->show($this->user_prefs['use_bayes']) . $delete_link); + $table->add('help', ' '); + $table->set_row_attribs(array('id' => 'bayes_help', 'style' => 'display: none;')); + $table->add(array('colspan' => '3'), rcmail::Q($this->gettext('bayeshelp'))); + } + + if (!isset($no_override['use_bayes_rules'])) { + $help_button = html::img(array('class' => $imgclass, 'src' => $attrib['helpicon'], 'alt' => $this->gettext('sieveruleheaders'), 'border' => 0, 'style' => 'margin-left: 4px;')); + $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)); + + $table->add('title', html::label($field_id, rcmail::Q($this->gettext('bayesrules')))); + $table->add(null, $input_spamtest->show($this->user_prefs['use_bayes_rules'])); + $table->add('help', $help_button); + $table->set_row_attribs(array('id' => 'bayesrules_help', 'style' => 'display: none;')); + $table->add(array('colspan' => '3'), rcmail::Q($this->gettext('bayesruleshlp'))); + } + + if (!isset($no_override['bayes_auto_learn'])) { + $help_button = html::img(array('class' => $imgclass, 'src' => $attrib['helpicon'], 'alt' => $this->gettext('sieveruleheaders'), 'border' => 0, 'style' => 'margin-left: 4px;')); + $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)); + + $table->add('title', html::label($field_id, rcmail::Q($this->gettext('bayesautolearn')))); + $table->add(null, $input_spamtest->show($this->user_prefs['bayes_auto_learn'])); + $table->add('help', $help_button); + $table->set_row_attribs(array('id' => 'bayesauto_help', 'style' => 'display: none;')); + $table->add(array('colspan' => '3'), rcmail::Q($this->gettext('bayesautohelp'))); + } + + if ($table->size() > 0) + $out = html::tag('fieldset', null, html::tag('legend', null, rcmail::Q($this->gettext('mainoptions'))) . $table->show()); + + $table = new html_table(array('class' => 'bayesprefstable', 'cols' => 2)); + + $data = ""; + 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']); + + $table->add('title', html::label($field_id, rcmail::Q($this->gettext('bayesnonspam')))); + $table->add(null, $input_bayesnthres->show(number_format($this->user_prefs['bayes_auto_learn_threshold_nonspam'], $decPlaces, '.', ''))); + $table->add(array('colspan' => '2'), 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_hits']) + $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']); + + $table->add('title', html::label($field_id, rcmail::Q($this->gettext('bayesspam')))); + $table->add(null, $input_bayesthres->show(number_format($this->user_prefs['bayes_auto_learn_threshold_spam'], $decPlaces, '.', ''))); + $table->add(array('colspan' => '2'), rcmail::Q($this->gettext('bayesspamexp'))); + } + + if ($table->size() > 0) + $out .= html::tag('fieldset', null, html::tag('legend', null, rcmail::Q($this->gettext('bayesautooptions'))) . $table->show()); + + break; + + // Report settings + case 'report': + $data = html::p(null, rcmail::Q($this->gettext('spamreport'))); + + $table = new html_table(array('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')); + $table->add('title', html::label($field_id.'_0', rcmail::Q($this->gettext('spamreport0')))); + $table->add(null, $input_spamreport0->show($this->user_prefs['report_safe'])); + + $input_spamreport1 = new html_radiobutton(array('name' => '_spamreport', 'id' => $field_id.'_1', 'value' => '1')); + $table->add('title', html::label($field_id.'_1', rcmail::Q($this->gettext('spamreport1')))); + $table->add(null, $input_spamreport1->show($this->user_prefs['report_safe'])); + $data .= $input_spamreport1->show($this->user_prefs['report_safe']) ." ". html::label($field_id .'_1', rcmail::Q($this->gettext('spamreport1'))) . "
"; + + $input_spamreport2 = new html_radiobutton(array('name' => '_spamreport', 'id' => $field_id.'_2', 'value' => '2')); + $table->add('title', html::label($field_id.'_2', rcmail::Q($this->gettext('spamreport2')))); + $table->add(null, $input_spamreport2->show($this->user_prefs['report_safe'])); + } + + $out = html::tag('fieldset', null, html::tag('legend', null, rcmail::Q($this->gettext('mainoptions'))) . $table->show()); + break; + + // Address settings + case 'addresses': + $data = html::p(null, rcmail::Q($this->gettext('whitelistexp'))); + + if ($rcmail->config->get('sauserprefs_whitelist_sync')) + $data .= rcmail::Q($this->gettext('autowhitelist')) . "

"; + + $table = new html_table(array('class' => 'addressprefstable', '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, 'style' => 'width:200px;')); + + $field_id = 'rcmbtn_add_address'; + $button_addaddress = $this->api->output->button(array('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 = $this->api->output->button(array('command' => 'plugin.sauserprefs.import_whitelist', 'type' => 'link', 'label' => 'import', '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', 'cellspacing' => '0', 'cols' => 3)); + $address_table->add_header('rule', $this->gettext('rule')); + $address_table->add_header('email', $this->gettext('email')); + $address_table->add_header('control', ' '); + + $this->_address_row($address_table, null, null, $attrib); + + if (sizeof($this->user_prefs['addresses']) > 0) + $norules = 'display: none;'; + + $address_table->set_row_attribs(array('style' => $norules)); + $address_table->add(array('colspan' => '3'), rcube_utils::rep_specialchars_output($this->gettext('noaddressrules'))); + + $this->api->output->set_env('address_rule_count', sizeof($this->user_prefs['addresses'])); + foreach ($this->user_prefs['addresses'] as $address) + $this->_address_row($address_table, $address['field'], $address['value'], $attrib); + + $table->add(array('colspan' => 4, 'class' => 'scroller'), html::div(array('id' => 'address-rules-cont'), $address_table->show())); + + if ($table->size()) + $out = html::tag('fieldset', null, html::tag('legend', null, rcmail::Q($this->gettext('mainoptions'))) . $data . $table->show()); + + break; + + default: + $out = ''; + } + + return $out; + } + + private function _address_row($address_table, $field, $value, $attrib) + { + if (!isset($field)) + $address_table->set_row_attribs(array('style' => 'display: none;')); + + $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' => ' ')); + $address_table->add('control', $del_button . $hidden_action->show() . $hidden_field->show() . $hidden_text->show()); + + return $address_table; + } + + 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; + } + + private function _subval_sort($a, $subkey) + { + if (sizeof($a) == 0) + return array(); + + foreach ($a as $k => $v) + $b[$k] = strtolower($v[$subkey]); + + asort($b); + + foreach ($b as $k => $v) + $c[] = $a[$k]; + + return $c; + } + + 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; + } +} + +?> \ No newline at end of file diff --git a/plugins/sauserprefs/skins/classic/help.gif b/plugins/sauserprefs/skins/classic/help.gif new file mode 100644 index 000000000..ea7bbb363 Binary files /dev/null and b/plugins/sauserprefs/skins/classic/help.gif differ diff --git a/plugins/sauserprefs/skins/classic/icons.gif b/plugins/sauserprefs/skins/classic/icons.gif new file mode 100644 index 000000000..e52c33e51 Binary files /dev/null and b/plugins/sauserprefs/skins/classic/icons.gif differ diff --git a/plugins/sauserprefs/skins/classic/icons.png b/plugins/sauserprefs/skins/classic/icons.png new file mode 100644 index 000000000..065d880bd Binary files /dev/null and b/plugins/sauserprefs/skins/classic/icons.png differ diff --git a/plugins/sauserprefs/skins/classic/ie6hacks.css b/plugins/sauserprefs/skins/classic/ie6hacks.css new file mode 100644 index 000000000..65c3e6af8 --- /dev/null +++ b/plugins/sauserprefs/skins/classic/ie6hacks.css @@ -0,0 +1,9 @@ +/** + * SAUserPrefs plugin styles (IE6 hacks) + */ + +#spam-langs-table td.tick a, +#address-rules-table td.control a +{ + background-image: url(icons.gif); +} \ No newline at end of file diff --git a/plugins/sauserprefs/skins/classic/iehacks.css b/plugins/sauserprefs/skins/classic/iehacks.css new file mode 100644 index 000000000..0577d936c --- /dev/null +++ b/plugins/sauserprefs/skins/classic/iehacks.css @@ -0,0 +1,9 @@ +/** + * SAUserPrefs plugin styles (IE hacks) + */ + +#address-rules-table, +#spam-langs-table +{ + width: expression('auto'); +} \ No newline at end of file diff --git a/plugins/sauserprefs/skins/classic/safari.css b/plugins/sauserprefs/skins/classic/safari.css new file mode 100644 index 000000000..0ff418083 --- /dev/null +++ b/plugins/sauserprefs/skins/classic/safari.css @@ -0,0 +1,6 @@ +/** + * SAUserPrefs plugin styles (safari hacks) + */ + +html>body*#address-rules-table[id$="address-rules-table"]:not([class="none"]) { table-layout: auto; } +html>body*#spam-langs-table[id$="spam-langs-table"]:not([class="none"]) { table-layout: auto; } \ No newline at end of file diff --git a/plugins/sauserprefs/skins/classic/sauserprefs.css b/plugins/sauserprefs/skins/classic/sauserprefs.css new file mode 100644 index 000000000..81ba60250 --- /dev/null +++ b/plugins/sauserprefs/skins/classic/sauserprefs.css @@ -0,0 +1,185 @@ +/** + * 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; +} + +#address-rules-table, +#spam-langs-table +{ + width: 100%; + display: table; + table-layout: fixed; +} + +#address-rules-table thead td.rule +{ + width: 180px; +} + +#address-rules-table thead td.control +{ + width: 40px; +} + +#spam-langs-table td.lang, +#address-rules-table td.rule, +#address-rules-table td.email, +#address-rules-table td.email +{ + text-align: left; + vertical-align: middle; +} + +#spam-langs-table td.tick, +#address-rules-table td.control +{ + text-align: right; + vertical-align: middle; +} + +#spam-langs-table td.tick a, +#address-rules-table td.control a +{ + display: block; + float: right; + width: 16px; + height: 16px; + background-image: url(icons.png); +} + +#address-rules-table td.control a.delete +{ + background-position: 0 0; +} + +#spam-langs-table td.tick a.enabled +{ + background-position: 0 -18px; +} + +#spam-langs-table td.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 td.title +{ + width: 115px; +} + +table.headersprefstable td.title +{ + width: 220px; +} + +table.testsprefstable td.title +{ + width: 175px; +} + +table.bayesprefstable td.title +{ + width: 220px; +} + +table.reportprefstable td.title +{ + width: 320px; +} + +table.generalprefstable td.help, +table.langprefstable td.help, +table.headersprefstable td.help, +table.testsprefstable td.help, +table.bayesprefstable td.help, +table.reportprefstable td.help, +table.addressprefstable td.help +{ + text-align: right; +} + +table.addressprefstable td.ruletype +{ + width: 180px; + padding-bottom: 10px; +} + +table.addressprefstable td.address +{ + width: 220px; + padding-bottom: 10px; +} + +table.addressprefstable td.action +{ + width: 100px; + text-align: right; + padding-bottom: 10px; +} + +table.langprefstable td.scroller, +table.addressprefstable td.scroller +{ + padding: 0; +} \ No newline at end of file diff --git a/plugins/sauserprefs/skins/classic/tabstyles.css b/plugins/sauserprefs/skins/classic/tabstyles.css new file mode 100644 index 000000000..c3cfaa4ac --- /dev/null +++ b/plugins/sauserprefs/skins/classic/tabstyles.css @@ -0,0 +1,3 @@ +/** + * SAUserPrefs plugin styles (tab styles) + */ diff --git a/plugins/sauserprefs/skins/classic/templates/sauserprefs.html b/plugins/sauserprefs/skins/classic/templates/sauserprefs.html new file mode 100644 index 000000000..dae567837 --- /dev/null +++ b/plugins/sauserprefs/skins/classic/templates/sauserprefs.html @@ -0,0 +1,47 @@ + + + +<roundcube:object name="pagetitle" /> + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + +
+ +
+ +
+ + + \ No newline at end of file diff --git a/plugins/sauserprefs/skins/classic/templates/settingsedit.html b/plugins/sauserprefs/skins/classic/templates/settingsedit.html new file mode 100644 index 000000000..73ba59880 --- /dev/null +++ b/plugins/sauserprefs/skins/classic/templates/settingsedit.html @@ -0,0 +1,33 @@ + + + +<roundcube:object name="pagetitle" /> + + + + + + + + + + + + + +
+ +
+ +
+
+ + +
+
+
+ +

 

+ + + \ No newline at end of file diff --git a/plugins/sauserprefs/skins/larry/help.png b/plugins/sauserprefs/skins/larry/help.png new file mode 100644 index 000000000..9f7a6ae44 Binary files /dev/null and b/plugins/sauserprefs/skins/larry/help.png differ diff --git a/plugins/sauserprefs/skins/larry/icons.png b/plugins/sauserprefs/skins/larry/icons.png new file mode 100644 index 000000000..6e070901e Binary files /dev/null and b/plugins/sauserprefs/skins/larry/icons.png differ diff --git a/plugins/sauserprefs/skins/larry/iehacks.css b/plugins/sauserprefs/skins/larry/iehacks.css new file mode 100644 index 000000000..0577d936c --- /dev/null +++ b/plugins/sauserprefs/skins/larry/iehacks.css @@ -0,0 +1,9 @@ +/** + * SAUserPrefs plugin styles (IE hacks) + */ + +#address-rules-table, +#spam-langs-table +{ + width: expression('auto'); +} \ No newline at end of file diff --git a/plugins/sauserprefs/skins/larry/listicons.png b/plugins/sauserprefs/skins/larry/listicons.png new file mode 100644 index 000000000..3571ac6c4 Binary files /dev/null and b/plugins/sauserprefs/skins/larry/listicons.png differ diff --git a/plugins/sauserprefs/skins/larry/safari.css b/plugins/sauserprefs/skins/larry/safari.css new file mode 100644 index 000000000..0ff418083 --- /dev/null +++ b/plugins/sauserprefs/skins/larry/safari.css @@ -0,0 +1,6 @@ +/** + * SAUserPrefs plugin styles (safari hacks) + */ + +html>body*#address-rules-table[id$="address-rules-table"]:not([class="none"]) { table-layout: auto; } +html>body*#spam-langs-table[id$="spam-langs-table"]:not([class="none"]) { table-layout: auto; } \ No newline at end of file diff --git a/plugins/sauserprefs/skins/larry/sauserprefs.css b/plugins/sauserprefs/skins/larry/sauserprefs.css new file mode 100644 index 000000000..41dfab2e2 --- /dev/null +++ b/plugins/sauserprefs/skins/larry/sauserprefs.css @@ -0,0 +1,253 @@ +/** + * SAUserPrefs plugin styles + */ + +#address-rules-cont, +#spam-langs-cont +{ + height: 200px; + overflow: auto; + width: 100%; +} + +body.address-rules-table, +body.spam-langs-table +{ + margin: 0px; +} + +#address-rules-table, +#spam-langs-table +{ + width: 100%; + display: table; + table-layout: fixed; + border: 0; +} + +#address-rules-table thead td, +#spam-langs-table thead td +{ + background-color: #CCC; + font-weight: bold; + color: #000; +} + +#address-rules-table thead td.rule +{ + width: 180px; +} + +#address-rules-table thead td.control +{ + width: 40px; +} + +#spam-langs-table td.lang, +#address-rules-table td.rule, +#address-rules-table td.email, +#address-rules-table td.email +{ + text-align: left; + vertical-align: middle; + border-left: 0; + border-right: 0; +} + +#spam-langs-table td.tick, +#address-rules-table td.control +{ + text-align: right; + vertical-align: middle; + border-left: 0; + border-right: 0; +} + +#spam-langs-table td.tick a, +#address-rules-table td.control a +{ + display: block; + float: right; + width: 16px; + height: 16px; + background-image: url(icons.png); + cursor: pointer; +} + +#address-rules-table td.control a.delete +{ + background-position: 0 -1px; +} + +#spam-langs-table td.tick a.enabled +{ + background-position: 0 -18px; +} + +#spam-langs-table td.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 td.title, +table.langprefstable td.title, +table.headersprefstable td.title, +table.testsprefstable td.title, +table.bayesprefstable td.title, +table.reportprefstable td.title, +table.addressprefstable td.title +{ + width: 20%; + color: #333; + padding-right: 20px; + white-space: nowrap; +} + +table.addressprefstable td.ruletype +{ + width: 180px; +} + +table.addressprefstable td.address +{ + width: 220px; +} + +table.addressprefstable td.action +{ + width: 100px; + text-align: right; +} + +table.langprefstable td.scroller, +table.addressprefstable td.scroller +{ + padding: 0; +} + +#sections-table #rcmrowtests td.section +{ + background-image: url(listicons.png); + background-position: 5px -199px; +} + +#sections-table #rcmrowtests.selected td.section +{ + background-image: url(listicons.png); + background-position: 5px -225px; +} + +#sections-table #rcmrowbayes td.section +{ + background-image: url(listicons.png); + background-position: 5px -248px; +} + +#sections-table #rcmrowbayes.selected td.section +{ + background-image: url(listicons.png); + background-position: 5px -270px; +} + +#sections-table #rcmrowheaders td.section +{ + background-image: url(listicons.png); + background-position: 5px -99px; +} + +#sections-table #rcmrowheaders.selected td.section +{ + background-image: url(listicons.png); + background-position: 5px -124px; +} + +#sections-table #rcmrowreport td.section +{ + background-image: url(listicons.png); + background-position: 5px -150px; +} + +#sections-table #rcmrowreport.selected td.section +{ + background-image: url(listicons.png); + background-position: 5px -174px; +} + +#sections-table #rcmrowaddresses td.section +{ + background-image: url(listicons.png); + background-position: 4px -50px; +} + +#sections-table #rcmrowaddresses.selected td.section +{ + background-image: url(listicons.png); + background-position: 4px -74px; +} \ No newline at end of file diff --git a/plugins/sauserprefs/skins/larry/tabstyles.css b/plugins/sauserprefs/skins/larry/tabstyles.css new file mode 100644 index 000000000..c22f8199a --- /dev/null +++ b/plugins/sauserprefs/skins/larry/tabstyles.css @@ -0,0 +1,15 @@ +/** + * SAUserPrefs plugin styles (tab styles) + */ + +#settings-sections #settingstabpluginsauserprefs a +{ + background-image: url(listicons.png); + background-position: 3px -3px; +} + +#settings-sections #settingstabpluginsauserprefs.selected a +{ + background-image: url(listicons.png); + background-position: 3px -27px; +} \ No newline at end of file diff --git a/plugins/sauserprefs/skins/larry/templates/sauserprefs.html b/plugins/sauserprefs/skins/larry/templates/sauserprefs.html new file mode 100644 index 000000000..6f734f092 --- /dev/null +++ b/plugins/sauserprefs/skins/larry/templates/sauserprefs.html @@ -0,0 +1,54 @@ + + + +<roundcube:object name="pagetitle" /> + + + + + + + + + + + + + +
+ + + +
+ +
+
+ +
+
+ +
+
+ +
+ +
+ +
+ +
+ + + + + + + \ No newline at end of file diff --git a/plugins/sauserprefs/skins/larry/templates/settingsedit.html b/plugins/sauserprefs/skins/larry/templates/settingsedit.html new file mode 100644 index 000000000..302288027 --- /dev/null +++ b/plugins/sauserprefs/skins/larry/templates/settingsedit.html @@ -0,0 +1,30 @@ + + + +<roundcube:object name="pagetitle" /> + + + + + + + + + + + +

+ +
+ +
+ +
+ + +
+ + + + + \ No newline at end of file -- cgit v1.2.3