X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=classes%2Fpref%2Fprefs.php;h=b2e7edf03d8797ec403a653ed20624ed7a0ff922;hb=1ffe3391f902c4baa984982f19e61a0e45de21ff;hp=ff8a17cdb9614e0cc30a58fcc90332e78add49b8;hpb=369dbc19d6ae35c97a2306ae4821c7812e2f24b2;p=tt-rss.git diff --git a/classes/pref/prefs.php b/classes/pref/prefs.php index ff8a17cd..b2e7edf0 100644 --- a/classes/pref/prefs.php +++ b/classes/pref/prefs.php @@ -1,12 +1,63 @@ pref_sections = array( + 1 => __('General'), + 2 => __('Interface'), + 3 => __('Advanced'), + 4 => __('Digest') + ); + + $this->pref_help = array( + "ALLOW_DUPLICATE_POSTS" => array(__("Allow duplicate articles"), ""), + "AUTO_ASSIGN_LABELS" => array(__("Assign articles to labels automatically"), ""), + "BLACKLISTED_TAGS" => array(__("Blacklisted tags"), __("When auto-detecting tags in articles these tags will not be applied (comma-separated list).")), + "CDM_AUTO_CATCHUP" => array(__("Automatically mark articles as read"), __("This option enables marking articles as read automatically while you scroll article list.")), + "CDM_EXPANDED" => array(__("Automatically expand articles in combined mode"), ""), + "COMBINED_DISPLAY_MODE" => array(__("Combined feed display"), __("Display expanded list of feed articles, instead of separate displays for headlines and article content")), + "CONFIRM_FEED_CATCHUP" => array(__("Confirm marking feed as read"), ""), + "DEFAULT_ARTICLE_LIMIT" => array(__("Amount of articles to display at once"), ""), + "DEFAULT_UPDATE_INTERVAL" => array(__("Default feed update interval"), __("Shortest interval at which a feed will be checked for updates regardless of update method")), + "DIGEST_CATCHUP" => array(__("Mark articles in e-mail digest as read"), ""), + "DIGEST_ENABLE" => array(__("Enable e-mail digest"), __("This option enables sending daily digest of new (and unread) headlines on your configured e-mail address")), + "DIGEST_PREFERRED_TIME" => array(__("Try to send digests around specified time"), __("Uses UTC timezone")), + "ENABLE_API_ACCESS" => array(__("Enable API access"), __("Allows external clients to access this account through the API")), + "ENABLE_FEED_CATS" => array(__("Enable feed categories"), ""), + "FEEDS_SORT_BY_UNREAD" => array(__("Sort feeds by unread articles count"), ""), + "FRESH_ARTICLE_MAX_AGE" => array(__("Maximum age of fresh articles (in hours)"), ""), + "HIDE_READ_FEEDS" => array(__("Hide feeds with no unread articles"), ""), + "HIDE_READ_SHOWS_SPECIAL" => array(__("Show special feeds when hiding read feeds"), ""), + "LONG_DATE_FORMAT" => array(__("Long date format"), ""), + "ON_CATCHUP_SHOW_NEXT_FEED" => array(__("On catchup show next feed"), __("Automatically open next feed with unread articles after marking one as read")), + "PURGE_OLD_DAYS" => array(__("Purge articles after this number of days (0 - disables)"), ""), + "PURGE_UNREAD_ARTICLES" => array(__("Purge unread articles"), ""), + "REVERSE_HEADLINES" => array(__("Reverse headline order (oldest first)"), ""), + "SHORT_DATE_FORMAT" => array(__("Short date format"), ""), + "SHOW_CONTENT_PREVIEW" => array(__("Show content preview in headlines list"), ""), + "SORT_HEADLINES_BY_FEED_DATE" => array(__("Sort headlines by feed date"), __("Use feed-specified date to sort headlines instead of local import date.")), + "SSL_CERT_SERIAL" => array(__("Login with an SSL certificate"), __("Click to register your SSL client certificate with tt-rss")), + "STRIP_IMAGES" => array(__("Do not embed images in articles"), ""), + "STRIP_UNSAFE_TAGS" => array(__("Strip unsafe tags from articles"), __("Strip all but most common HTML tags when reading articles.")), + "USER_STYLESHEET" => array(__("Customize stylesheet"), __("Customize CSS stylesheet to your liking")), + "USER_TIMEZONE" => array(__("User timezone"), ""), + "VFEED_GROUP_BY_FEED" => array(__("Group headlines in virtual feeds"), __("Special feeds, labels, and categories are grouped by originating feeds")), + "USER_CSS_THEME" => array(__("Select theme"), __("Select one of the available CSS themes")) + ); + } + function changepassword() { $old_pw = $_POST["old_password"]; @@ -28,8 +79,7 @@ class Pref_Prefs extends Handler_Protected { return; } - $module_class = "auth_" . $_SESSION["auth_module"]; - $authenticator = new $module_class($this->link); + $authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]); if (method_exists($authenticator, "change_password")) { print $authenticator->change_password($_SESSION["uid"], $old_pw, $new_pw); @@ -39,31 +89,44 @@ class Pref_Prefs extends Handler_Protected { } function saveconfig() { + $boolean_prefs = explode(",", $_POST["boolean_prefs"]); - $_SESSION["prefs_cache"] = false; + foreach ($boolean_prefs as $pref) { + if (!isset($_POST[$pref])) $_POST[$pref] = 'false'; + } - $orig_theme = get_pref($this->link, "_THEME_ID"); + $need_reload = false; foreach (array_keys($_POST) as $pref_name) { - $pref_name = db_escape_string($pref_name); - $value = db_escape_string($_POST[$pref_name]); + $pref_name = $this->dbh->escape_string($pref_name); + $value = $this->dbh->escape_string($_POST[$pref_name]); if ($pref_name == 'DIGEST_PREFERRED_TIME') { - if (get_pref($this->link, 'DIGEST_PREFERRED_TIME') != $value) { + if (get_pref('DIGEST_PREFERRED_TIME') != $value) { - db_query($this->link, "UPDATE ttrss_users SET + $this->dbh->query("UPDATE ttrss_users SET last_digest_sent = NULL WHERE id = " . $_SESSION['uid']); } } - set_pref($this->link, $pref_name, $value); + if ($pref_name == "language") { + if ($_SESSION["language"] != $value) { + setcookie("ttrss_lang", $value, + time() + SESSION_COOKIE_LIFETIME); + $_SESSION["language"] = $value; + + $need_reload = true; + } + } else { + set_pref($pref_name, $value); + } } - if ($orig_theme != get_pref($this->link, "_THEME_ID")) { - print "PREFS_THEME_CHANGED"; + if ($need_reload) { + print "PREFS_NEED_RELOAD"; } else { print __("The configuration was saved."); } @@ -71,13 +134,13 @@ class Pref_Prefs extends Handler_Protected { function getHelp() { - $pref_name = db_escape_string($_REQUEST["pn"]); + $pref_name = $this->dbh->escape_string($_REQUEST["pn"]); - $result = db_query($this->link, "SELECT help_text FROM ttrss_prefs + $result = $this->dbh->query("SELECT help_text FROM ttrss_prefs WHERE pref_name = '$pref_name'"); - if (db_num_rows($result) > 0) { - $help_text = db_fetch_result($result, 0, "help_text"); + if ($this->dbh->num_rows($result) > 0) { + $help_text = $this->dbh->fetch_result($result, 0, "help_text"); print $help_text; } else { printf(__("Unknown option: %s"), $pref_name); @@ -86,12 +149,12 @@ class Pref_Prefs extends Handler_Protected { function changeemail() { - $email = db_escape_string($_POST["email"]); - $full_name = db_escape_string($_POST["full_name"]); + $email = $this->dbh->escape_string($_POST["email"]); + $full_name = $this->dbh->escape_string($_POST["full_name"]); $active_uid = $_SESSION["uid"]; - db_query($this->link, "UPDATE ttrss_users SET email = '$email', + $this->dbh->query("UPDATE ttrss_users SET email = '$email', full_name = '$full_name' WHERE id = '$active_uid'"); print __("Your personal data has been saved."); @@ -109,20 +172,22 @@ class Pref_Prefs extends Handler_Protected { $profile_qpart = "profile IS NULL"; } - db_query($this->link, "DELETE FROM ttrss_user_prefs + $this->dbh->query("DELETE FROM ttrss_user_prefs WHERE $profile_qpart AND owner_uid = ".$_SESSION["uid"]); - initialize_user_prefs($this->link, $_SESSION["uid"], $_SESSION["profile"]); + initialize_user_prefs($_SESSION["uid"], $_SESSION["profile"]); - print "PREFS_THEME_CHANGED"; + echo __("Your preferences are now set to default values."); } function index() { global $access_level_names; - $prefs_blacklist = array("HIDE_READ_FEEDS", "FEEDS_SORT_BY_UNREAD", - "STRIP_UNSAFE_TAGS"); + $prefs_blacklist = array("STRIP_UNSAFE_TAGS", "REVERSE_HEADLINES", + "SORT_HEADLINES_BY_FEED_DATE", "DEFAULT_ARTICLE_LIMIT"); + + /* "FEEDS_SORT_BY_UNREAD", "HIDE_READ_FEEDS", "REVERSE_HEADLINES" */ $profile_blacklist = array("ALLOW_DUPLICATE_POSTS", "PURGE_OLD_DAYS", "PURGE_UNREAD_ARTICLES", "DIGEST_ENABLE", "DIGEST_CATCHUP", @@ -154,12 +219,15 @@ class Pref_Prefs extends Handler_Protected { print ""; - $result = db_query($this->link, "SELECT email,full_name, + print "

" . __("Personal data") . "

"; + + $result = $this->dbh->query("SELECT email,full_name,otp_enabled, access_level FROM ttrss_users WHERE id = ".$_SESSION["uid"]); - $email = htmlspecialchars(db_fetch_result($result, 0, "email")); - $full_name = htmlspecialchars(db_fetch_result($result, 0, "full_name")); + $email = htmlspecialchars($this->dbh->fetch_result($result, 0, "email")); + $full_name = htmlspecialchars($this->dbh->fetch_result($result, 0, "full_name")); + $otp_enabled = sql_bool_to_bool($this->dbh->fetch_result($result, 0, "otp_enabled")); print ""; print ""; print ""; } @@ -185,20 +253,21 @@ class Pref_Prefs extends Handler_Protected { print ""; - if ($_SESSION["auth_module"]) { - $module_class = "auth_" . $_SESSION["auth_module"]; - $authenticator = new $module_class($this->link); + if ($_SESSION["auth_module"]) { + $authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]); } else { $authenticator = false; } if ($authenticator && method_exists($authenticator, "change_password")) { - $result = db_query($this->link, "SELECT id FROM ttrss_users + print "

" . __("Password") . "

"; + + $result = $this->dbh->query("SELECT id FROM ttrss_users WHERE id = ".$_SESSION["uid"]." AND pwd_hash = 'SHA1:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8'"); - if (db_num_rows($result) != 0) { + if ($this->dbh->num_rows($result) != 0) { print format_warning(__("Your password is at default value, please change it."), "default_pass_warning"); } @@ -225,6 +294,10 @@ class Pref_Prefs extends Handler_Protected { } "; + if ($otp_enabled) { + print_notice(__("Changing your current password will disable OTP.")); + } + print "
".__('Full name')."dbh->fetch_result($result, 0, "access_level"); print "
".__('Access level')."" . $access_level_names[$access_level] . "
"; print ""; @@ -249,16 +322,127 @@ class Pref_Prefs extends Handler_Protected { print ""; + if ($_SESSION["auth_module"] == "auth_internal") { + + print "

" . __("One time passwords / Authenticator") . "

"; + + if ($otp_enabled) { + + print_notice(__("One time passwords are currently enabled. Enter your current password below to disable.")); + + print ""; + + print ""; + + print "
".__("Old password")."
"; + + print ""; + + print ""; + + print "
".__("Enter your password")."
"; + + print ""; + print ""; + + print "

"; + + print ""; + + } else { + + print "

".__("You will need a compatible Authenticator to use this. Changing your password would automatically disable OTP.") . "

"; + + print "

".__("Scan the following code by the Authenticator application:")."

"; + + $csrf_token = $_SESSION["csrf_token"]; + + print ""; + + print "
"; + + print ""; + print ""; + + print ""; + + print ""; + + print ""; + + print ""; + + print ""; + + print ""; + + print ""; + print "
".__("Enter your password")."
".__("Enter the generated one time password")."
"; + + print "
"; + + print "
"; + + print "

"; + + print "

"; + + } + + } } + PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION, + "hook_prefs_tab_section", "prefPrefsAuth"); + print ""; #pane print "
"; print "
"; - print ""; + + print ""; + print ""; + + print ""; + + print ""; + + print " + + + + + "; + + $system_enabled = array_map("trim", explode(",", PLUGINS)); + $user_enabled = array_map("trim", explode(",", get_pref("_ENABLED_PLUGINS"))); + + $tmppluginhost = new PluginHost(Db::get()); + $tmppluginhost->load_all($tmppluginhost::KIND_ALL, $_SESSION["uid"]); + $tmppluginhost->load_data(true); + + foreach ($tmppluginhost->get_plugins() as $name => $plugin) { + $about = $plugin->about(); + + if ($about[3] && strpos($name, "example") === FALSE) { + if (in_array($name, $system_enabled)) { + $checked = "checked='1'"; + } else { + $checked = ""; + } + + print ""; + + print ""; + + print ""; + print ""; + print ""; + print ""; + + if (count($tmppluginhost->get_all($plugin)) > 0) { + if (in_array($name, $system_enabled)) { + print ""; + } + } + + print ""; + + } + } + + print ""; + + print " + + + + + "; + + + foreach ($tmppluginhost->get_plugins() as $name => $plugin) { + $about = $plugin->about(); + + if (!$about[3] && strpos($name, "example") === FALSE) { + + if (in_array($name, $system_enabled)) { + $checked = "checked='1'"; + $disabled = "disabled='1'"; + $rowclass = ''; + } else if (in_array($name, $user_enabled)) { + $checked = "checked='1'"; + $disabled = ""; + $rowclass = "Selected"; + } else { + $checked = ""; + $disabled = ""; + $rowclass = ''; + } + + print ""; + + print ""; + + print ""; + print ""; + + print ""; + print ""; + + if (count($tmppluginhost->get_all($plugin)) > 0) { + if (in_array($name, $system_enabled) || in_array($name, $user_enabled)) { + print ""; + } + } + + print ""; + + + + } + + } + + print "

".__("System plugins")."

 ".__('Plugin')."".__('Description')."".__('Version')."".__('Author')."
$name" . htmlspecialchars($about[1]); + if (@$about[4]) { + print " — ".__("more info").""; + } + print "" . htmlspecialchars(sprintf("%.2f", $about[0])) . "" . htmlspecialchars($about[2]) . "".__("Clear data")."

".__("User plugins")."

 ".__('Plugin')."".__('Description')."".__('Version')."".__('Author')."
"; + if (@$about[4]) { + print " — ".__("more info").""; + } + print "" . htmlspecialchars(sprintf("%.2f", $about[0])) . "" . htmlspecialchars($about[2]) . "".__("Clear data")."
"; + + print "

"; + print "
"; print "
"; #pane + + PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB, + "hook_prefs_tab", "prefPrefs"); + print ""; #container } + + function toggleAdvanced() { + $_SESSION["prefs_show_advanced"] = !$_SESSION["prefs_show_advanced"]; + } + + function otpqrcode() { + require_once "lib/otphp/vendor/base32.php"; + require_once "lib/otphp/lib/otp.php"; + require_once "lib/otphp/lib/totp.php"; + require_once "lib/phpqrcode/phpqrcode.php"; + + $result = $this->dbh->query("SELECT login,salt,otp_enabled + FROM ttrss_users + WHERE id = ".$_SESSION["uid"]); + + $base32 = new Base32(); + + $login = $this->dbh->fetch_result($result, 0, "login"); + $otp_enabled = sql_bool_to_bool($this->dbh->fetch_result($result, 0, "otp_enabled")); + + if (!$otp_enabled) { + $secret = $base32->encode(sha1($this->dbh->fetch_result($result, 0, "salt"))); + $topt = new \OTPHP\TOTP($secret); + print QRcode::png($topt->provisioning_uri($login)); + } + } + + function otpenable() { + require_once "lib/otphp/vendor/base32.php"; + require_once "lib/otphp/lib/otp.php"; + require_once "lib/otphp/lib/totp.php"; + + $password = $_REQUEST["password"]; + $otp = $_REQUEST["otp"]; + + $authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]); + + if ($authenticator->check_password($_SESSION["uid"], $password)) { + + $result = $this->dbh->query("SELECT salt + FROM ttrss_users + WHERE id = ".$_SESSION["uid"]); + + $base32 = new Base32(); + + $secret = $base32->encode(sha1($this->dbh->fetch_result($result, 0, "salt"))); + $topt = new \OTPHP\TOTP($secret); + + $otp_check = $topt->now(); + + if ($otp == $otp_check) { + $this->dbh->query("UPDATE ttrss_users SET otp_enabled = true WHERE + id = " . $_SESSION["uid"]); + + print "OK"; + } else { + print "ERROR:".__("Incorrect one time password"); + } + } else { + print "ERROR:".__("Incorrect password"); + } + + } + + function otpdisable() { + $password = $this->dbh->escape_string($_REQUEST["password"]); + + $authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]); + + if ($authenticator->check_password($_SESSION["uid"], $password)) { + + $this->dbh->query("UPDATE ttrss_users SET otp_enabled = false WHERE + id = " . $_SESSION["uid"]); + + print "OK"; + } else { + print "ERROR: ".__("Incorrect password"); + } + + } + + function setplugins() { + if (is_array($_REQUEST["plugins"])) + $plugins = join(",", $_REQUEST["plugins"]); + else + $plugins = ""; + + set_pref("_ENABLED_PLUGINS", $plugins); + } + + function clearplugindata() { + $name = $this->dbh->escape_string($_REQUEST["name"]); + + PluginHost::getInstance()->clear_data(PluginHost::getInstance()->get_plugin($name)); + } + + function customizeCSS() { + $value = get_pref("USER_STYLESHEET"); + + $value = str_replace("
", "\n", $value); + + print_notice(T_sprintf("You can override colors, fonts and layout of your currently selected theme with custom CSS declarations here. This file can be used as a baseline.", "tt-rss.css")); + + print ""; + print ""; + print ""; + + print "
"; + print ""; + print "
"; + + print "
"; + print " "; + print ""; + print "
"; + + } + + function editPrefProfiles() { + print "
"; + + print "
". + "" . __('Select').""; + print "
"; + print "
".__('All')."
"; + print "
".__('None')."
"; + print "
"; + + print "
"; + + print " +
"; + + print "
"; + + $result = $this->dbh->query("SELECT title,id FROM ttrss_settings_profiles + WHERE owner_uid = ".$_SESSION["uid"]." ORDER BY title"); + + print "
"; + + print "
"; + + print ""; + + print ""; #odd + + print ""; + + if (!$_SESSION["profile"]) { + $is_active = __("(active)"); + } else { + $is_active = ""; + } + + print ""; + + print ""; + + $lnum = 1; + + while ($line = $this->dbh->fetch_assoc($result)) { + + $class = ($lnum % 2) ? "even" : "odd"; + + $profile_id = $line["id"]; + $this_row_id = "id=\"FCATR-$profile_id\""; + + print ""; + + $edit_title = htmlspecialchars($line["title"]); + + print ""; + + if ($_SESSION["profile"] == $line["id"]) { + $is_active = __("(active)"); + } else { + $is_active = ""; + } + + print ""; + + print ""; + + ++$lnum; + } + + print "
" . + __("Default profile") . " $is_active
" . $edit_title . + " + $is_active
"; + print "
"; + print "
"; + + print "
+
+ + +
"; + + print ""; + print "
"; + + } + + private function getShortDesc($pref_name) { + if (isset($this->pref_help[$pref_name])) { + return $this->pref_help[$pref_name][0]; + } + return ""; + } + + private function getHelpText($pref_name) { + if (isset($this->pref_help[$pref_name])) { + return $this->pref_help[$pref_name][1]; + } + return ""; + } + + private function getSectionName($id) { + if (isset($this->pref_sections[$id])) { + return $this->pref_sections[$id]; + } + + return ""; + } } ?>