@ -4,6 +4,7 @@ class Pref_Prefs extends Handler_Protected {
private $pref_help = [];
private $pref_help = [];
private $pref_item_map = [];
private $pref_item_map = [];
private $pref_help_bottom = [];
private $pref_blacklist = [];
private $pref_blacklist = [];
private $profile_blacklist = [];
private $profile_blacklist = [];
@ -272,34 +273,7 @@ class Pref_Prefs extends Handler_Protected {
echo __("Your preferences are now set to default values.");
echo __("Your preferences are now set to default values.");
}
}
function index() {
private function index_auth_personal() {
global $access_level_names;
$_SESSION["prefs_op_result"] = "";
print "< div dojoType = 'dijit.layout.AccordionContainer' region = 'center' > ";
print "< div dojoType = 'dijit.layout.AccordionPane'
title=\"< i class = 'material-icons' > person< / i > ".__('Personal data / Authentication')."\">";
print "< div dojoType = 'dijit.layout.TabContainer' > ";
print "< div dojoType = 'dijit.layout.ContentPane' title = \"".__('Personal data ' ) . " \ " > ";
print "< form dojoType = 'dijit.form.Form' id = 'changeUserdataForm' > ";
print "< script type = 'dojo/method' event = 'onSubmit' args = 'evt' >
evt.preventDefault();
if (this.validate()) {
Notify.progress('Saving data...', true);
new Ajax.Request('backend.php', {
parameters: dojo.objectToQuery(this.getValues()),
onComplete: function(transport) {
notify_callback2(transport);
} });
}
< / script > ";
$sth = $this->pdo->prepare("SELECT email,full_name,otp_enabled,
$sth = $this->pdo->prepare("SELECT email,full_name,otp_enabled,
access_level FROM ttrss_users
access_level FROM ttrss_users
@ -311,52 +285,72 @@ class Pref_Prefs extends Handler_Protected {
$full_name = htmlspecialchars($row["full_name"]);
$full_name = htmlspecialchars($row["full_name"]);
$otp_enabled = sql_bool_to_bool($row["otp_enabled"]);
$otp_enabled = sql_bool_to_bool($row["otp_enabled"]);
print "< fieldset > ";
?>
print "< label > ".__('Full name:')."< / label > ";
< form dojoType = 'dijit.form.Form' >
print "< input dojoType = 'dijit.form.ValidationTextBox' name = 'full_name' required = '1' value = '$full_name' > ";
print "< / fieldset > ";
print "< fieldset > ";
<?php print_hidden ( "op" , "pref-prefs" ) ?>
print "< label > ".__('E-mail:')."< / label > ";
<?php print_hidden ( "method" , "changeemail" ) ?>
print "< input dojoType = 'dijit.form.ValidationTextBox' name = 'email' required = '1' value = '$email' > ";
print "< / fieldset > ";
if (!SINGLE_USER_MODE & & !empty($_SESSION["hide_hello"])) {
< script type = 'dojo/method' event = 'onSubmit' args = 'evt' >
evt.preventDefault();
if (this.validate()) {
Notify.progress('Saving data...', true);
$access_level = $row["access_level"];
new Ajax.Request('backend.php', {
print "< fieldset > ";
parameters: dojo.objectToQuery(this.getValues()),
print "< label > ".__('Access level:')."< / label > ";
onComplete: function(transport) {
print $access_level_names[$access_level];
Notify.info(transport.responseText);
print "< / fieldset > ";
}
});
}
}
< / script >
print_hidden("op", "pref-prefs");
< fieldset >
print_hidden("method", "changeemail");
< label > <? = __ ( 'Full name:' ) ?> </ label >
< input dojoType = 'dijit.form.ValidationTextBox' name = 'full_name' required = '1' value = " <? = $full_name ?> " >
< / fieldset >
print "< hr / > ";
< fieldset >
< label > <? = __ ( 'E-mail:' ) ?> </ label >
< input dojoType = 'dijit.form.ValidationTextBox' name = 'email' required = '1' value = " <? = $email ?> " >
< / fieldset >
print "< button dojoType = 'dijit.form.Button' type = 'submit' class = 'alt-primary' > ".
<?php if ( ! SINGLE_USER_MODE && ! empty ( $_SESSION [ "hide_hello" ])) { ?>
__("Save data")."< / button > ";
< fieldset >
< label > <? = __ ( 'Access level:' ) ?> </ label >
<? = $access_level_names [ $row [ "access_level" ]] ?>
< / fieldset >
<?php } ?>
print "< / form > ";
< hr / >
print "< / div > "; # content pane
< button dojoType = 'dijit.form.Button' type = 'submit' class = 'alt-primary' >
<? = __ ( "Save data" ) ?>
< / button >
< / form >
<?php
}
private function index_auth_password() {
if ($_SESSION["auth_module"]) {
if ($_SESSION["auth_module"]) {
$authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]);
$authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]);
} else {
} else {
$authenticator = false;
$authenticator = false;
}
}
print "< div dojoType = 'dijit.layout.ContentPane' title = \"" . __ ( ' Password ' ) . " \ " > " ;
$otp_enabled = $this->is_otp_enabled() ;
if ($authenticator & & method_exists($authenticator, "change_password")) {
if ($authenticator & & method_exists($authenticator, "change_password")) {
?>
< div style = 'display : none' id = 'pwd_change_infobox' > < / div >
print "< div style = 'display : none' id = 'pwd_change_infobox' > < / div > ";
< form dojoType = 'dijit.form.Form' >
print "< form dojoType = 'dijit.form.Form' > ";
<?php print_hidden ( "op" , "pref-prefs" ) ?>
<?php print_hidden ( "method" , "changepassword" ) ?>
print " < script type = 'dojo/method' event = 'onSubmit' args = 'evt' >
< script type = 'dojo/method' event = 'onSubmit' args = 'evt' >
evt.preventDefault();
evt.preventDefault();
if (this.validate()) {
if (this.validate()) {
Notify.progress('Changing password...', true);
Notify.progress('Changing password...', true);
@ -374,84 +368,98 @@ class Pref_Prefs extends Handler_Protected {
$('pwd_change_infobox').innerHTML =
$('pwd_change_infobox').innerHTML =
transport.responseText.replace('ERROR: ', '');
transport.responseText.replace('ERROR: ', '');
var warn = $('default_pass_warning');
const warn = $('default_pass_warning');
if (warn) Element.hide(warn);
if (warn) Element.hide(warn);
}
}
new Effect.Appear('pwd_change_infobox');
new Effect.Appear('pwd_change_infobox');
}
} });
});
this.reset();
this.reset();
}
}
< / script > ";
< / script >
if ($otp_enabled) {
<?php if ( $otp_enabled ) {
print_notice(__("Changing your current password will disable OTP."));
print_notice(__("Changing your current password will disable OTP."));
}
} ?>
print "< fieldset > ";
< fieldset >
print "< label > " . __("Old password:") . "< / label > ";
< label > <? = __ ( "Old password:" ) ?> </ label >
print " < input dojoType = 'dijit.form.ValidationTextBox' type = 'password' required = '1' name = 'old_password' > ";
< input dojoType = 'dijit.form.ValidationTextBox' type = 'password' required = '1' name = 'old_password' >
print "< / fieldset > ";
< / fieldset >
print "< fieldset > ";
< fieldset >
print "< label > " . __("New password:") . "< / label > ";
< label > <? = __ ( "New password:" ) ?> </ label >
print " < input dojoType = 'dijit.form.ValidationTextBox' type = 'password' regexp = '^[^<>]+' required = '1' name = 'new_password' > ";
< input dojoType = 'dijit.form.ValidationTextBox' type = 'password' regexp = '^[^<>]+' required = '1' name = 'new_password' >
print "< / fieldset > ";
< / fieldset >
print "< fieldset > ";
< fieldset >
print "< label > " . __("Confirm password:") . "< / label > ";
< label > <? = __ ( "Confirm password:" ) ?> </ label >
print " < input dojoType = 'dijit.form.ValidationTextBox' type = 'password' regexp = '^[^<>]+' required = '1' name = 'confirm_password' > ";
< input dojoType = 'dijit.form.ValidationTextBox' type = 'password' regexp = '^[^<>]+' required = '1' name = 'confirm_password' >
print "< / fieldset > ";
< / fieldset >
print_hidden("op", "pref-prefs");
< hr / >
print_hidden("method", "changepassword");
print "< hr / > ";
< button dojoType = 'dijit.form.Button' type = 'submit' class = 'alt-primary' >
<? = __ ( "Change password" ) ?>
< / button >
< / form >
print "< button dojoType = 'dijit.form.Button' type = 'submit' class = 'alt-primary' > " .
<?php
__("Change password") . "< / button > ";
print "< / form > ";
} else {
} else {
print_notice(T_sprintf("Authentication module used for this session (< b > %s< / b > ) does not provide an ability to set passwords.",
print_notice(T_sprintf("Authentication module used for this session (< b > %s< / b > ) does not provide an ability to set passwords.",
$_SESSION["auth_module"]));
$_SESSION["auth_module"]));
}
}
}
print "< / div > "; # content pane
private function index_auth_app_passwords() {
print_notice("You can create separate passwords for API clients. Using one is required if you enable OTP.");
?>
print "< div dojoType = 'dijit.layout.ContentPane' title = \"" . __ ( ' App passwords ' ) . " \ " > ";
< div id = 'app_passwords_holder' >
<?php $this -> appPasswordList () ?>
< / div >
print_notice("You can create separate passwords for API clients. Using one is required if you enable OTP.");
< hr >
print "< div id = 'app_passwords_holder' > ";
< button style = 'float : left' class = 'alt-primary' dojoType = 'dijit.form.Button' onclick = "Helpers.AppPasswords.generate()" >
$this->appPasswordList();
<? = __ ( 'Generate new password' ) ?>
print "< / div > ";
< / button >
< button style = 'float : left' class = 'alt-danger' dojoType = 'dijit.form.Button'
onclick="Helpers.AppPasswords.removeSelected()">
<? = __ ( 'Remove selected passwords' ) ?>
< / button >
print "< hr > ";
<?php
}
print "< button style = 'float : left' class = 'alt-primary' dojoType = 'dijit.form.Button'
private function is_otp_enabled() {
onclick=\"Helpers.AppPasswords.generate()\">" .
$sth = $this->pdo->prepare("SELECT otp_enabled FROM ttrss_users
__('Generate new password') . "< / button > ";
WHERE id = ?");
$sth->execute([$_SESSION["uid"]]);
print "< button style = 'float : left' class = 'alt-danger' dojoType = 'dijit.form.Button'
if ($row = $sth->fetch()) {
onclick=\"Helpers.AppPasswords.removeSelected()\">" .
return sql_bool_to_bool($row["otp_enabled"]);
__('Remove selected passwords') . "< / button > ";
}
print "< / div > "; # content pane
return false;
}
print "< div dojoType = 'dijit.layout.ContentPane' title = \"".__('One time passwords / Authenticator ' ) . " \ " > ";
private function index_auth_2fa() {
$otp_enabled = $this->is_otp_enabled();
if ($_SESSION["auth_module"] == "auth_internal") {
if ($_SESSION["auth_module"] == "auth_internal") {
if ($otp_enabled) {
if ($otp_enabled) {
print_warning("One time passwords are currently enabled. Enter your current password below to disable.");
print_warning("One time passwords are currently enabled. Enter your current password below to disable.");
?>
print "< form dojoType = 'dijit.form.Form' > ";
< form dojoType = 'dijit.form.Form' >
<?php print_hidden ( "op" , "pref-prefs" ) ?>
<?php print_hidden ( "method" , "otpdisable" ) ?>
print "< script type = 'dojo/method' event = 'onSubmit' args = 'evt' >
< script type = 'dojo/method' event = 'onSubmit' args = 'evt' >
evt.preventDefault();
evt.preventDefault();
if (this.validate()) {
if (this.validate()) {
Notify.progress('Disabling OTP', true);
Notify.progress('Disabling OTP', true);
@ -465,25 +473,26 @@ class Pref_Prefs extends Handler_Protected {
} else {
} else {
window.location.reload();
window.location.reload();
}
}
}});
}
});
this.reset();
this.reset();
}
}
< / script > ";
< / script >
print "< fieldset > ";
< fieldset >
print "< label > ".__("Your password:")."< / label > ";
< label > <? = __ ( "Your password:" ) ?> </ label >
print " < input dojoType = 'dijit.form.ValidationTextBox' type = 'password' required = '1' name = 'password' > ";
< input dojoType = 'dijit.form.ValidationTextBox' type = 'password' required = '1' name = 'password' >
print "< / fieldset > ";
< / fieldset >
print_hidden("op", "pref-prefs");
< hr / >
print_hidden("method", "otpdisable");
print "< hr / > ";
< button dojoType = 'dijit.form.Button' type = 'submit' class = 'alt-danger' >
<? = __ ( "Disable OTP" ) ?>
< / button >
print "< button dojoType = 'dijit.form.Button' type = 'submit' > ".
< / form >
__("Disable OTP")."< / button > ";
print "< / form > ";
<?php
} else {
} else {
@ -492,7 +501,6 @@ class Pref_Prefs extends Handler_Protected {
if (function_exists("imagecreatefromstring")) {
if (function_exists("imagecreatefromstring")) {
print "< h3 > " . __("Scan the following code by the Authenticator application or copy the key manually") . "< / h3 > ";
print "< h3 > " . __("Scan the following code by the Authenticator application or copy the key manually") . "< / h3 > ";
$csrf_token_hash = sha1($_SESSION["csrf_token"]);
$csrf_token_hash = sha1($_SESSION["csrf_token"]);
print "< img alt = 'otp qr-code' src = 'backend.php?op=pref-prefs&method=otpqrcode&csrf_token_hash=$csrf_token_hash' > ";
print "< img alt = 'otp qr-code' src = 'backend.php?op=pref-prefs&method=otpqrcode&csrf_token_hash=$csrf_token_hash' > ";
} else {
} else {
@ -500,19 +508,20 @@ class Pref_Prefs extends Handler_Protected {
print "< h3 > " . __("Use the following OTP key with a compatible Authenticator application") . "< / h3 > ";
print "< h3 > " . __("Use the following OTP key with a compatible Authenticator application") . "< / h3 > ";
}
}
print "< form dojoType = 'dijit.form.Form' id = 'changeOtpForm' > ";
$otp_secret = $this->otpsecret();
$otp_secret = $this->otpsecret();
?>
print "< fieldset > ";
< form dojoType = 'dijit.form.Form' id = 'changeOtpForm' >
print "< label > ".__("OTP Key:")."< / label > ";
print "< input dojoType = 'dijit.form.ValidationTextBox' disabled = 'disabled' value = '$otp_secret' size = '32' > ";
print "< / fieldset > ";
print_hidden("op", "pref-prefs");
<?php print_hidden ( "op" , "pref-prefs" ) ?>
print_hidden("method", "otpenable");
<?php print_hidden ( "method" , "otpenable" ) ?>
print "< script type = 'dojo/method' event = 'onSubmit' args = 'evt' >
< fieldset >
< label > <? = __ ( "OTP Key:" ) ?> </ label >
< input dojoType = 'dijit.form.ValidationTextBox' disabled = 'disabled' value = " <? = $otp_secret ?> " size = '32' >
< / fieldset >
< script type = 'dojo/method' event = 'onSubmit' args = 'evt' >
evt.preventDefault();
evt.preventDefault();
if (this.validate()) {
if (this.validate()) {
Notify.progress('Saving data...', true);
Notify.progress('Saving data...', true);
@ -526,79 +535,59 @@ class Pref_Prefs extends Handler_Protected {
} else {
} else {
window.location.reload();
window.location.reload();
}
}
} });
}
}
< / script > ";
});
}
< / script >
print "< fieldset > ";
< fieldset >
print "< label > ".__("Your password:")."< / label > ";
< label > <? = __ ( "Your password:" ) ?> </ label >
print "< input dojoType = 'dijit.form.ValidationTextBox' type = 'password' required = '1'
< input dojoType = 'dijit.form.ValidationTextBox' type = 'password' required = '1' name = 'password' >
name='password'>";
< / fieldset >
print "< / fieldset > ";
print "< fieldset > ";
< fieldset >
print "< label > ".__("One time password:")."< / label > ";
< label > <? = __ ( "One time password:" ) ?> </ label >
print "< input dojoType = 'dijit.form.ValidationTextBox' autocomplete = 'off'
< input dojoType = 'dijit.form.ValidationTextBox' autocomplete = 'off' required = '1' name = 'otp' >
required='1' name='otp'>";
< / fieldset >
print "< / fieldset > ";
print "< hr / > ";
< hr / >
print "< button dojoType = 'dijit.form.Button' type = 'submit' class = 'alt-primary' > ".
__("Enable OTP")."< / button > ";
print "< / form > ";
< button dojoType = 'dijit.form.Button' type = 'submit' class = 'alt-primary' >
<? = __ ( "Enable OTP" ) ?>
< / button >
< / form >
<?php
}
}
} else {
} else {
print_notice("OTP is only available when using < b > auth_internal< / b > authentication module.");
print_notice("OTP is only available when using < b > auth_internal< / b > authentication module.");
}
}
print "< / div > "; # content pane
print "< / div > "; # tab container
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION, "prefPrefsAuth");
print "< / div > "; #pane
print "< div dojoType = 'dijit.layout.AccordionPane' selected = 'true'
title=\"< i class = 'material-icons' > settings< / i > ".__('Preferences')."\">";
print "< form dojoType = 'dijit.form.Form' id = 'changeSettingsForm' > ";
print "< script type = 'dojo/method' event = 'onSubmit' args = 'evt, quit' >
if (evt) evt.preventDefault();
if (this.validate()) {
console.log(dojo.objectToQuery(this.getValues()));
new Ajax.Request('backend.php', {
parameters: dojo.objectToQuery(this.getValues()),
onComplete: function(transport) {
var msg = transport.responseText;
if (quit) {
document.location.href = 'index.php';
} else {
if (msg == 'PREFS_NEED_RELOAD') {
window.location.reload();
} else {
Notify.info(msg);
}
}
}
} });
}
< / script > ";
print '< div dojoType = "dijit.layout.BorderContainer" gutters = "false" > ';
print '< div dojoType = "dijit.layout.ContentPane" region = "center" style = "overflow-y : auto" > ';
private function index_auth() {
?>
< div dojoType = 'dijit.layout.TabContainer' >
< div dojoType = 'dijit.layout.ContentPane' title = " <? = __ ( 'Personal data' ) ?> " >
<?php $this -> index_auth_personal () ?>
< / div >
< div dojoType = 'dijit.layout.ContentPane' title = " <? = __ ( 'Password' ) ?> " >
<?php $this -> index_auth_password () ?>
< / div >
< div dojoType = 'dijit.layout.ContentPane' title = " <? = __ ( 'App passwords' ) ?> " >
<?php $this -> index_auth_app_passwords () ?>
< / div >
< div dojoType = 'dijit.layout.ContentPane' title = " <? = __ ( 'Authenticator (OTP)' ) ?> " >
<?php $this -> index_auth_2fa () ?>
< / div >
< / div >
<?php
}
private function index_prefs_list() {
$profile = $_SESSION["profile"] ?? null;
$profile = $_SESSION["profile"] ?? null;
if ($profile) {
if ($profile) {
print_notice(__("Some preferences are only available in default profile."));
print_notice(__("Some preferences are only available in default profile."));
$this->initialize_user_prefs($_SESSION["uid"], $profile);
$this->initialize_user_prefs($_SESSION["uid"], $profile);
} else {
} else {
$this->initialize_user_prefs($_SESSION["uid"]);
$this->initialize_user_prefs($_SESSION["uid"]);
@ -660,7 +649,9 @@ class Pref_Prefs extends Handler_Protected {
continue;
continue;
}
}
if (isset($prefs_available[$pref_name]) & & $item = $prefs_available[$pref_name]) {
if (isset($prefs_available[$pref_name])) {
$item = $prefs_available[$pref_name];
print "< fieldset class = 'prefs' > ";
print "< fieldset class = 'prefs' > ";
@ -735,16 +726,16 @@ class Pref_Prefs extends Handler_Protected {
array_push($listed_boolean_prefs, $pref_name);
array_push($listed_boolean_prefs, $pref_name);
$checked = ($value == "true") ? "checked=\"checked\"" : "";
$is_ checked = ($value == "true") ? "checked=\"checked\"" : "";
if ($pref_name == "PURGE_UNREAD_ARTICLES" & & FORCE_ARTICLE_PURGE != 0) {
if ($pref_name == "PURGE_UNREAD_ARTICLES" & & FORCE_ARTICLE_PURGE != 0) {
$disabled = "disabled=\"1\"";
$is_ disabled = "disabled=\"1\"";
$checked = "checked=\"checked\"";
$is_ checked = "checked=\"checked\"";
} else {
} else {
$disabled = "";
$is_ disabled = "";
}
}
print "< input type = 'checkbox' name = '$pref_name' $ checked $ disabled
print "< input type = 'checkbox' name = '$pref_name' $ is_ checked $ is_ disabled
dojoType='dijit.form.CheckBox' id='CB_$pref_name' value='1'>";
dojoType='dijit.form.CheckBox' id='CB_$pref_name' value='1'>";
} else if (in_array($pref_name, ['FRESH_ARTICLE_MAX_AGE',
} else if (in_array($pref_name, ['FRESH_ARTICLE_MAX_AGE',
@ -753,19 +744,19 @@ class Pref_Prefs extends Handler_Protected {
$regexp = ($type_name == 'integer') ? 'regexp="^\d*$"' : '';
$regexp = ($type_name == 'integer') ? 'regexp="^\d*$"' : '';
if ($pref_name == "PURGE_OLD_DAYS" & & FORCE_ARTICLE_PURGE != 0) {
if ($pref_name == "PURGE_OLD_DAYS" & & FORCE_ARTICLE_PURGE != 0) {
$disabled = "disabled='1'";
$is_ disabled = "disabled='1'";
$value = FORCE_ARTICLE_PURGE;
$value = FORCE_ARTICLE_PURGE;
} else {
} else {
$disabled = "";
$is_ disabled = "";
}
}
if ($type_name == 'integer')
if ($type_name == 'integer')
print "< input dojoType = \"dijit.form.NumberSpinner\"
print "< input dojoType = \"dijit.form.NumberSpinner\"
required='1' $disabled
required='1' $is_ disabled
name=\"$pref_name\" value=\"$value\">";
name=\"$pref_name\" value=\"$value\">";
else
else
print "< input dojoType = \"dijit.form.TextBox\"
print "< input dojoType = \"dijit.form.TextBox\"
required='1' $regexp $disabled
required='1' $regexp $is_ disabled
name=\"$pref_name\" value=\"$value\">";
name=\"$pref_name\" value=\"$value\">";
} else if ($pref_name == "SSL_CERT_SERIAL") {
} else if ($pref_name == "SSL_CERT_SERIAL") {
@ -808,204 +799,246 @@ class Pref_Prefs extends Handler_Protected {
}
}
}
}
}
}
print_hidden("boolean_prefs", htmlspecialchars(join(",", $listed_boolean_prefs)));
}
$listed_boolean_prefs = htmlspecialchars(join(",", $listed_boolean_prefs));
private function index_prefs() {
?>
print_hidden("boolean_prefs", "$listed_boolean_prefs");
< form dojoType = 'dijit.form.Form' id = 'changeSettingsForm' >
<?php print_hidden ( "op" , "pref-prefs" ) ?>
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION, "prefPrefsPrefsInside");
<?php print_hidden ( "method" , "saveconfig" ) ?>
< script type = 'dojo/method' event = 'onSubmit' args = 'evt, quit' >
print '< / div > '; # inside pane
if (evt) evt.preventDefault();
print '< div dojoType = "dijit.layout.ContentPane" region = "bottom" > ';
print_hidden("op", "pref-prefs");
print_hidden("method", "saveconfig");
print "< div dojoType = \"fox.form.ComboButton\" type = \"submit\" class = \"alt-primary\" >
< span > ".__('Save configuration')."< / span >
< div dojoType = \"dijit.DropDownMenu\" >
< div dojoType = \"dijit.MenuItem\"
onclick=\"dijit.byId('changeSettingsForm').onSubmit(null, true)\">".
__("Save and exit preferences")."< / div >
< / div >
< / div > ";
print "< button dojoType = \"dijit.form.Button\" onclick = \"return Helpers . Profiles . edit ( ) \ " > ".
__('Manage profiles')."< / button > ";
print "< button dojoType = \"dijit.form.Button\" class = \"alt-danger\" onclick = \"return Helpers . Prefs . confirmReset ( ) \ " > ".
__('Reset to defaults')."< / button > ";
print " ";
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION, "prefPrefsPrefsOutside");
print "< / form > ";
print '< / div > '; # inner pane
print '< / div > '; # border container
print "< / div > "; #pane
print "< div dojoType = \"dijit.layout.AccordionPane\"
title=\"< i class = 'material-icons' > extension< / i > ".__('Plugins')."\">";
print "< form dojoType = \"dijit.form.Form\" id = \"changePluginsForm\" > ";
print "< script type = \"dojo/method\" event = \"onSubmit\" args = \"evt\" >
evt.preventDefault();
if (this.validate()) {
if (this.validate()) {
Notify.progress('Saving data...', true );
console.log(dojo.objectToQuery(this.getValues()));
new Ajax.Request('backend.php', {
new Ajax.Request('backend.php', {
parameters: dojo.objectToQuery(this.getValues()),
parameters: dojo.objectToQuery(this.getValues()),
onComplete: function(transport) {
onComplete: function(transport) {
Notify.close();
var msg = transport.responseText;
if (confirm(__('Selected plugins have been enabled. Reload?'))) {
if (quit) {
document.location.href = 'index.php';
} else {
if (msg == 'PREFS_NEED_RELOAD') {
window.location.reload();
window.location.reload();
} else {
Notify.info(msg);
}
}
} });
}
}
< / script > ";
print_hidden("op", "pref-prefs");
print_hidden("method", "setplugins");
print '< div dojoType = "dijit.layout.BorderContainer" gutters = "false" > ';
print '< div dojoType = "dijit.layout.ContentPane" region = "center" style = "overflow-y : auto" > ';
if (ini_get("open_basedir") & & function_exists("curl_init") & & !defined("NO_CURL")) {
print_warning("Your PHP configuration has open_basedir restrictions enabled. Some plugins relying on CURL for functionality may not work correctly.");
}
}
});
if ($_SESSION["safe_mode"]) {
print_error("You have logged in using safe mode, no user plugins will be actually enabled until you login again.");
}
}
< / script >
$feed_handler_whitelist = [ "Af_Comics" ];
< div dojoType = "dijit.layout.BorderContainer" gutters = "false" >
< div dojoType = "dijit.layout.ContentPane" region = "center" style = "overflow-y : auto" >
<?php $this -> index_prefs_list () ?>
<?php PluginHost :: getInstance () -> run_hooks ( PluginHost :: HOOK_PREFS_TAB_SECTION , "prefPrefsPrefsInside" ) ?>
< / div >
< div dojoType = "dijit.layout.ContentPane" region = "bottom" >
$feed_handlers = array_merge(
< div dojoType = "fox.form.ComboButton" type = "submit" class = "alt-primary" >
PluginHost::getInstance()->get_hooks(PluginHost::HOOK_FEED_FETCHED),
< span > <? = __ ( 'Save configuration' ) ?> </ span >
PluginHost::getInstance()->get_hooks(PluginHost::HOOK_FEED_PARSED),
< div dojoType = "dijit.DropDownMenu" >
PluginHost::getInstance()->get_hooks(PluginHost::HOOK_FETCH_FEED));
< div dojoType = "dijit.MenuItem" onclick = "dijit.byId('changeSettingsForm').onSubmit(null, true)" >
<? = __ ( "Save and exit preferences" ) ?>
< / div >
< / div >
< / div >
$feed_handlers = array_filter($feed_handlers, function($plugin) use ($feed_handler_whitelist) {
< button dojoType = "dijit.form.Button" onclick = "return Helpers.Profiles.edit()" >
return in_array(get_class($plugin), $feed_handler_whitelist) === false; });
<? = __ ( 'Manage profiles' ) ?>
< / button >
if (count($feed_handlers) > 0) {
< button dojoType = "dijit.form.Button" class = "alt-danger" onclick = "return Helpers.Prefs.confirmReset()" >
print_error(
<? = __ ( 'Reset to defaults' ) ?>
T_sprintf("The following plugins use per-feed content hooks. This may cause excessive data usage and origin server load resulting in a ban of your instance: < b > %s< / b > " ,
< / button >
implode(", ", array_map(function($plugin) { return get_class($plugin); }, $feed_handlers))
) . " (< a href = 'https://tt-rss.org/wiki/FeedHandlerPlugins' target = '_blank' > ".__("More info...")."< / a > )"
<?php PluginHost :: getInstance () -> run_hooks ( PluginHost :: HOOK_PREFS_TAB_SECTION , "prefPrefsPrefsOutside" ) ?>
);
< / div >
< / div >
< / form >
<?php
}
}
print "< h2 > ".__("System plugins")."< / h2 > ";
private function index_plugins_system() {
print_notice("System plugins are enabled in < strong > config.php< / strong > for all users.");
print_notice("System plugins are enabled in < strong > config.php< / strong > for all users.");
$system_enabled = array_map("trim", explode(",", PLUGINS));
$system_enabled = array_map("trim", explode(",", (string)PLUGINS));
$user_enabled = array_map("trim", explode(",", get_pref("_ENABLED_PLUGINS")));
$tmppluginhost = new PluginHost();
$tmppluginhost = new PluginHost();
$tmppluginhost->load_all($tmppluginhost::KIND_ALL, $_SESSION["uid"], true);
$tmppluginhost->load_all($tmppluginhost::KIND_ALL, $_SESSION["uid"], true);
//$tmppluginhost->load_data(true);
foreach ($tmppluginhost->get_plugins() as $name => $plugin) {
foreach ($tmppluginhost->get_plugins() as $name => $plugin) {
$about = $plugin->about();
$about = $plugin->about();
if ($about[3] ?? false) {
if ($about[3] ?? false) {
if (in_array($name, $system_enabled)) {
$is_checked = in_array($name, $system_enabled) ? "checked" : "";
$checked = "checked='1'";
?>
} else {
< fieldset class = 'prefs plugin' >
$checked = "";
< label > <? = $name ?> :</ label >
}
< label class = 'checkbox description text-muted' id = "PLABEL- <? = htmlspecialchars ( $name ) ?> " >
< input disabled = '1' dojoType = 'dijit.form.CheckBox' <? = $is_checked ?> type = 'checkbox' > <? = htmlspecialchars ( $about [ 1 ]) ?>
print "< fieldset class = 'prefs plugin' >
< / label >
< label > $name:< / label >
< label class = 'checkbox description text-muted' id = 'PLABEL-$name' >
<?php if ( $about [ 4 ] ?? false ) { ?>
< input disabled = '1'
< button dojoType = 'dijit.form.Button' class = 'alt-info'
dojoType='dijit.form.CheckBox' $checked type='checkbox'>
onclick='window.open("<? = htmlspecialchars ( $about [ 4 ]) ?> ")'>
".htmlspecialchars($about[1]). "< / label > ";
< i class = 'material-icons' > open_in_new</ i > <? = __ ( "More info..." ) ?> </ button >
<?php } ?>
if ($about[4] ?? false) {
print "< button dojoType = 'dijit.form.Button' class = 'alt-info'
< div dojoType = 'dijit.Tooltip' connectId = 'PLABEL- <? = htmlspecialchars ( $name ) ?> ' position = 'after' >
onclick='window.open(\"".htmlspecialchars($about[4])."\")'>
<? = htmlspecialchars ( T_sprintf ( "v%.2f, by %s" , $about [ 0 ], $about [ 2 ])) ?>
< i class = 'material-icons' > open_in_new< / i > ".__("More info...")."< / button > ";
< / div >
< / fieldset >
<?php
}
}
print "< div dojoType = 'dijit.Tooltip' connectId = 'PLABEL-$name' position = 'after' > ".
htmlspecialchars(T_sprintf("v%.2f, by %s", $about[0], $about[2])).
"< / div > ";
print "< / fieldset > ";
}
}
}
}
print "< h2 > ".__("User plugins")."< / h2 > ";
private function index_plugins_user() {
$system_enabled = array_map("trim", explode(",", (string)PLUGINS));
$user_enabled = array_map("trim", explode(",", get_pref("_ENABLED_PLUGINS")));
$tmppluginhost = new PluginHost();
$tmppluginhost->load_all($tmppluginhost::KIND_ALL, $_SESSION["uid"], true);
foreach ($tmppluginhost->get_plugins() as $name => $plugin) {
foreach ($tmppluginhost->get_plugins() as $name => $plugin) {
$about = $plugin->about();
$about = $plugin->about();
if (empty($about[3]) || $about[3] == false) {
if (empty($about[3]) || $about[3] == false) {
$checked = "";
$is_ checked = "";
$disabled = "";
$is_ disabled = "";
if (in_array($name, $system_enabled)) {
if (in_array($name, $system_enabled)) {
$checked = "checked='1'";
$is_ checked = "checked='1'";
$disabled = "disabled='1'";
$is_ disabled = "disabled='1'";
} else if (in_array($name, $user_enabled)) {
} else if (in_array($name, $user_enabled)) {
$checked = "checked='1'";
$is_ checked = "checked='1'";
}
}
print "< fieldset class = 'prefs plugin' >
?>
< label > $name:< / label >
< label class = 'checkbox description text-muted' id = 'PLABEL-$name' >
< fieldset class = 'prefs plugin' >
< input name = 'plugins[]' value = '$name' dojoType = 'dijit.form.CheckBox' $ checked $ disabled type = 'checkbox' >
< label > <? = $name ?> :</ label >
".htmlspecialchars($about[1])."< / label > ";
< label class = 'checkbox description text-muted' id = "PLABEL- <? = htmlspecialchars ( $name ) ?> " >
< input name = 'plugins[]' value = " <? = htmlspecialchars ( $name ) ?> "
dojoType='dijit.form.CheckBox' <? = $is_checked ?> <? = $is_disabled ?> type='checkbox'>
<? = htmlspecialchars ( $about [ 1 ]) ?>
< / input >
< / label >
if (count($tmppluginhost->get_all($plugin)) > 0) {
<?php if ( count ( $tmppluginhost -> get_all ( $plugin )) > 0 ) {
if (in_array($name, $system_enabled) || in_array($name, $user_enabled)) {
if (in_array($name, $system_enabled) || in_array($name, $user_enabled)) { ?>
print " < button dojoType = 'dijit.form.Button'
< button dojoType = 'dijit.form.Button'
onclick=\"Helpers.Prefs.clearPluginData('$name')\">
onclick='Helpers.Prefs.clearPluginData("<? = htmlspecialchars ( $name ) ?> ")'>
< i class = 'material-icons' > clear< / i > ".__("Clear data")."< / button > ";
< i class = 'material-icons' > clear</ i > <? = __ ( "Clear data" ) ?> </ button >
<?php }
} ?>
<?php if ( $about [ 4 ] ?? false ) { ?>
< button dojoType = 'dijit.form.Button' class = 'alt-info'
onclick='window.open("<? = htmlspecialchars ( $about [ 4 ]) ?> ")'>
< i class = 'material-icons' > open_in_new</ i > <? = __ ( "More info..." ) ?> </ button >
<?php } ?>
< div dojoType = 'dijit.Tooltip' connectId = "PLABEL- <? = htmlspecialchars ( $name ) ?> " position = 'after' >
<? = htmlspecialchars ( T_sprintf ( "v%.2f, by %s" , $about [ 0 ], $about [ 2 ])) ?>
< / div >
< / fieldset >
<?php
}
}
}
}
if ($about[4] ?? false) {
print " < button dojoType = 'dijit.form.Button' class = 'alt-info'
onclick='window.open(\"".htmlspecialchars($about[4])."\")'>
< i class = 'material-icons' > open_in_new< / i > ".__("More info...")."< / button > ";
}
}
print "< div dojoType = 'dijit.Tooltip' connectId = 'PLABEL-$name' position = 'after' > ".
private function index_plugins() {
htmlspecialchars(T_sprintf("v%.2f, by %s", $about[0], $about[2])).
?>
"< / div > ";
< form dojoType = "dijit.form.Form" id = "changePluginsForm" >
< script type = "dojo/method" event = "onSubmit" args = "evt" >
evt.preventDefault();
if (this.validate()) {
Notify.progress('Saving data...', true);
print "< / fieldset > ";
new Ajax.Request('backend.php', {
parameters: dojo.objectToQuery(this.getValues()),
onComplete: function(transport) {
Notify.close();
if (confirm(__('Selected plugins have been enabled. Reload?'))) {
window.location.reload();
}
}
}
}
});
}
< / script >
print "< / div > "; #content-pane
<?php print_hidden ( "op" , "pref-prefs" ) ?>
print '< div dojoType = "dijit.layout.ContentPane" region = "bottom" > ';
<?php print_hidden ( "method" , "setplugins" ) ?>
print "< button dojoType = 'dijit.form.Button' style = 'float : left' class = 'alt-info' onclick = 'window.open(\"https://tt-rss.org/wiki/Plugins\")' >
< div dojoType = "dijit.layout.BorderContainer" gutters = "false" >
< i class = 'material-icons' > help< / i > ".__("More info...")."< / button > ";
< div dojoType = "dijit.layout.ContentPane" region = "center" style = "overflow-y : auto" >
<?php
if (!empty($_SESSION["safe_mode"])) {
print_error("You have logged in using safe mode, no user plugins will be actually enabled until you login again.");
}
print "< button dojoType = 'dijit.form.Button' class = 'alt-primary' type = 'submit' > ".
$feed_handler_whitelist = [ "Af_Comics" ];
__("Enable selected plugins")."< / button > ";
print "< / div > "; #pane
print "< / div > "; #pane
$feed_handlers = array_merge(
print "< / div > "; #border-container
PluginHost::getInstance()->get_hooks(PluginHost::HOOK_FEED_FETCHED),
PluginHost::getInstance()->get_hooks(PluginHost::HOOK_FEED_PARSED),
PluginHost::getInstance()->get_hooks(PluginHost::HOOK_FETCH_FEED));
print "< / form > ";
$feed_handlers = array_filter($feed_handlers, function($plugin) use ($feed_handler_whitelist) {
return in_array(get_class($plugin), $feed_handler_whitelist) === false; });
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB, "prefPrefs");
if (count($feed_handlers) > 0) {
print_error(
T_sprintf("The following plugins use per-feed content hooks. This may cause excessive data usage and origin server load resulting in a ban of your instance: < b > %s< / b > " ,
implode(", ", array_map(function($plugin) { return get_class($plugin); }, $feed_handlers))
) . " (< a href = 'https://tt-rss.org/wiki/FeedHandlerPlugins' target = '_blank' > ".__("More info...")."< / a > )"
);
}
?>
< h2 > <? = __ ( "System plugins" ) ?> </ h2 >
<?php $this -> index_plugins_system () ?>
< h2 > <? = __ ( "User plugins" ) ?> </ h2 >
print "< / div > "; #container
<?php $this -> index_plugins_user () ?>
< / div >
< div dojoType = "dijit.layout.ContentPane" region = "bottom" >
< button dojoType = 'dijit.form.Button' style = 'float : left' class = 'alt-info' onclick = 'window.open("https://tt-rss.org/wiki/Plugins")' >
< i class = 'material-icons' > help</ i > <? = __ ( "More info..." ) ?>
< / button >
< button dojoType = 'dijit.form.Button' class = 'alt-primary' type = 'submit' >
<? = __ ( "Enable selected plugins" ) ?>
< / button >
< / div >
< / div >
< / form >
<?php
}
function index() {
?>
< div dojoType = 'dijit.layout.AccordionContainer' region = 'center' >
< div dojoType = 'dijit.layout.AccordionPane' title = "<i class='material-icons'>person</i> <? = __ ( 'Personal data / Authentication' ) ?> " >
<?php $this -> index_auth () ?>
< / div >
< div dojoType = 'dijit.layout.AccordionPane' selected = 'true' title = "<i class='material-icons'>settings</i> <? = __ ( 'Preferences' ) ?> " >
<?php $this -> index_prefs () ?>
< / div >
< div dojoType = 'dijit.layout.AccordionPane' title = "<i class='material-icons'>extension</i> <? = __ ( 'Plugins' ) ?> " >
<?php $this -> index_plugins () ?>
< / div >
<?php PluginHost :: getInstance () -> run_hooks ( PluginHost :: HOOK_PREFS_TAB , "prefPrefs" ) ?>
< / div >
<?php
}
}
function toggleAdvanced() {
function toggleAdvanced() {