2011-12-13 06:00:42 +00:00
< ? php
2013-04-02 12:20:06 +00:00
2012-08-17 10:20:55 +00:00
class Pref_Prefs extends Handler_Protected {
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
private $pref_help = [];
private $pref_item_map = [];
2021-02-14 08:29:38 +00:00
private $pref_help_bottom = [];
2019-02-21 19:08:21 +00:00
private $pref_blacklist = [];
private $profile_blacklist = [];
2013-04-02 12:20:06 +00:00
2011-12-26 08:02:52 +00:00
function csrf_ignore ( $method ) {
2021-02-12 12:22:10 +00:00
$csrf_ignored = array ( " index " , " updateself " , " otpqrcode " );
2011-12-26 08:02:52 +00:00
return array_search ( $method , $csrf_ignored ) !== false ;
}
2013-04-19 04:40:19 +00:00
function __construct ( $args ) {
parent :: __construct ( $args );
2013-04-02 12:20:06 +00:00
2019-02-21 19:08:21 +00:00
$this -> pref_item_map = [
__ ( 'General' ) => [
'USER_LANGUAGE' ,
'USER_TIMEZONE' ,
'BLOCK_SEPARATOR' ,
'USER_CSS_THEME' ,
'BLOCK_SEPARATOR' ,
'ENABLE_API_ACCESS' ,
],
__ ( 'Feeds' ) => [
'DEFAULT_UPDATE_INTERVAL' ,
'FRESH_ARTICLE_MAX_AGE' ,
2019-04-10 10:03:26 +00:00
'DEFAULT_SEARCH_LANGUAGE' ,
2019-02-21 19:08:21 +00:00
'BLOCK_SEPARATOR' ,
'ENABLE_FEED_CATS' ,
'BLOCK_SEPARATOR' ,
'CONFIRM_FEED_CATCHUP' ,
'ON_CATCHUP_SHOW_NEXT_FEED' ,
'BLOCK_SEPARATOR' ,
'HIDE_READ_FEEDS' ,
'HIDE_READ_SHOWS_SPECIAL' ,
],
__ ( 'Articles' ) => [
'PURGE_OLD_DAYS' ,
'PURGE_UNREAD_ARTICLES' ,
'BLOCK_SEPARATOR' ,
'COMBINED_DISPLAY_MODE' ,
'CDM_EXPANDED' ,
'BLOCK_SEPARATOR' ,
'CDM_AUTO_CATCHUP' ,
'VFEED_GROUP_BY_FEED' ,
'BLOCK_SEPARATOR' ,
'SHOW_CONTENT_PREVIEW' ,
'STRIP_IMAGES' ,
],
__ ( 'Digest' ) => [
'DIGEST_ENABLE' ,
'DIGEST_CATCHUP' ,
'DIGEST_PREFERRED_TIME' ,
],
__ ( 'Advanced' ) => [
'BLACKLISTED_TAGS' ,
'BLOCK_SEPARATOR' ,
'LONG_DATE_FORMAT' ,
'SHORT_DATE_FORMAT' ,
'BLOCK_SEPARATOR' ,
'SSL_CERT_SERIAL' ,
]
];
2020-12-21 05:50:34 +00:00
$this -> pref_help_bottom = [
" BLACKLISTED_TAGS " => __ ( " Never apply these tags automatically (comma-separated list). " ),
];
2019-02-21 19:08:21 +00:00
$this -> pref_help = [
2013-04-02 12:46:08 +00:00
" ALLOW_DUPLICATE_POSTS " => array ( __ ( " Allow duplicate articles " ), " " ),
2020-12-21 05:50:34 +00:00
" BLACKLISTED_TAGS " => array ( __ ( " Blacklisted tags " ), " " ),
2019-04-10 10:03:26 +00:00
" DEFAULT_SEARCH_LANGUAGE " => array ( __ ( " Default language " ), __ ( " Used for full-text search " )),
2019-02-21 19:08:21 +00:00
" CDM_AUTO_CATCHUP " => array ( __ ( " Mark read on scroll " ), __ ( " Mark articles as read as you scroll past them " )),
" CDM_EXPANDED " => array ( __ ( " Always expand articles " )),
" COMBINED_DISPLAY_MODE " => array ( __ ( " Combined mode " ), __ ( " Show flat list of articles instead of separate panels " )),
2019-02-22 03:58:06 +00:00
" CONFIRM_FEED_CATCHUP " => array ( __ ( " Confirm marking feeds as read " )),
2019-02-21 19:08:21 +00:00
" DEFAULT_ARTICLE_LIMIT " => array ( __ ( " Amount of articles to display at once " )),
" DEFAULT_UPDATE_INTERVAL " => array ( __ ( " Default update interval " )),
" DIGEST_CATCHUP " => array ( __ ( " Mark sent articles as read " )),
" DIGEST_ENABLE " => array ( __ ( " Enable digest " ), __ ( " Send daily digest of new (and unread) headlines to your e-mail address " )),
" DIGEST_PREFERRED_TIME " => array ( __ ( " Try to send around this time " ), __ ( " Time in UTC " )),
" ENABLE_API_ACCESS " => array ( __ ( " Enable API " ), __ ( " Allows accessing this account through the API " )),
" ENABLE_FEED_CATS " => array ( __ ( " Enable categories " )),
2013-04-02 12:38:12 +00:00
" FEEDS_SORT_BY_UNREAD " => array ( __ ( " Sort feeds by unread articles count " ), " " ),
2019-02-21 19:08:21 +00:00
" FRESH_ARTICLE_MAX_AGE " => array ( __ ( " Maximum age of fresh articles " ), " <strong> " . __ ( " hours " ) . " </strong> " ),
" HIDE_READ_FEEDS " => array ( __ ( " Hide read feeds " )),
" HIDE_READ_SHOWS_SPECIAL " => array ( __ ( " Always show special feeds " ), __ ( " While hiding read feeds " )),
2019-02-21 09:35:40 +00:00
" LONG_DATE_FORMAT " => array ( __ ( " Long date format " ), __ ( " Syntax is identical to PHP <a href='http://php.net/manual/function.date.php'>date()</a> function. " )),
2019-02-22 03:58:06 +00:00
" ON_CATCHUP_SHOW_NEXT_FEED " => array ( __ ( " Automatically show next feed " ), __ ( " After marking one as read " )),
2019-02-21 19:08:21 +00:00
" PURGE_OLD_DAYS " => array ( __ ( " Purge articles older than " ), __ ( " <strong>days</strong> (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 " )),
2013-04-02 12:20:06 +00:00
" SORT_HEADLINES_BY_FEED_DATE " => array ( __ ( " Sort headlines by feed date " ), __ ( " Use feed-specified date to sort headlines instead of local import date. " )),
2019-02-21 19:08:21 +00:00
" SSL_CERT_SERIAL " => array ( __ ( " SSL client certificate " )),
" STRIP_IMAGES " => array ( __ ( " Do not embed media " )),
2013-04-02 12:20:06 +00:00
" STRIP_UNSAFE_TAGS " => array ( __ ( " Strip unsafe tags from articles " ), __ ( " Strip all but most common HTML tags when reading articles. " )),
2019-02-21 09:35:40 +00:00
" USER_STYLESHEET " => array ( __ ( " Customize stylesheet " )),
2019-02-21 19:08:21 +00:00
" USER_TIMEZONE " => array ( __ ( " Time zone " )),
" VFEED_GROUP_BY_FEED " => array ( __ ( " Group by feed " ), __ ( " Group multiple-feed output by originating feed " )),
2013-04-29 11:54:23 +00:00
" USER_LANGUAGE " => array ( __ ( " Language " )),
2019-02-21 09:35:40 +00:00
" USER_CSS_THEME " => array ( __ ( " Theme " ))
2019-02-21 19:08:21 +00:00
];
$this -> pref_blacklist = [ " ALLOW_DUPLICATE_POSTS " , " STRIP_UNSAFE_TAGS " , " REVERSE_HEADLINES " ,
" SORT_HEADLINES_BY_FEED_DATE " , " DEFAULT_ARTICLE_LIMIT " ,
" FEEDS_SORT_BY_UNREAD " , " USER_STYLESHEET " ];
/* "FEEDS_SORT_BY_UNREAD", "HIDE_READ_FEEDS", "REVERSE_HEADLINES" */
$this -> profile_blacklist = [ " ALLOW_DUPLICATE_POSTS " , " PURGE_OLD_DAYS " ,
" PURGE_UNREAD_ARTICLES " , " DIGEST_ENABLE " , " DIGEST_CATCHUP " ,
" BLACKLISTED_TAGS " , " ENABLE_API_ACCESS " , " UPDATE_POST_ON_CHECKSUM_CHANGE " ,
" DEFAULT_UPDATE_INTERVAL " , " USER_TIMEZONE " , " SORT_HEADLINES_BY_FEED_DATE " ,
" SSL_CERT_SERIAL " , " DIGEST_PREFERRED_TIME " ];
2013-04-02 12:20:06 +00:00
}
2011-12-13 06:00:42 +00:00
function changepassword () {
2019-12-06 14:45:22 +00:00
if ( defined ( '_TTRSS_DEMO_INSTANCE' )) {
print " ERROR: " . format_error ( " Disabled in demo version. " );
return ;
}
2017-12-03 20:35:38 +00:00
$old_pw = clean ( $_POST [ " old_password " ]);
$new_pw = clean ( $_POST [ " new_password " ]);
2020-09-14 17:53:00 +00:00
$new_unclean_pw = $_POST [ " new_password " ];
2017-12-03 20:35:38 +00:00
$con_pw = clean ( $_POST [ " confirm_password " ]);
2011-12-13 06:00:42 +00:00
2020-09-14 17:53:00 +00:00
if ( $new_unclean_pw != $new_pw ) {
print " ERROR: " . format_error ( " New password contains disallowed characters. " );
return ;
}
2019-10-09 06:04:51 +00:00
if ( $old_pw == $new_pw ) {
print " ERROR: " . format_error ( " New password must be different from the old one. " );
return ;
}
2011-12-13 06:00:42 +00:00
if ( $old_pw == " " ) {
2015-07-06 09:10:15 +00:00
print " ERROR: " . format_error ( " Old password cannot be blank. " );
2011-12-13 06:00:42 +00:00
return ;
}
if ( $new_pw == " " ) {
2015-07-06 09:10:15 +00:00
print " ERROR: " . format_error ( " New password cannot be blank. " );
2011-12-13 06:00:42 +00:00
return ;
}
if ( $new_pw != $con_pw ) {
2015-07-06 09:10:15 +00:00
print " ERROR: " . format_error ( " Entered passwords do not match. " );
2011-12-13 06:00:42 +00:00
return ;
}
2013-04-18 08:27:34 +00:00
$authenticator = PluginHost :: getInstance () -> get_plugin ( $_SESSION [ " auth_module " ]);
2011-12-13 06:00:42 +00:00
2012-08-16 14:21:35 +00:00
if ( method_exists ( $authenticator , " change_password " )) {
2015-07-06 09:10:15 +00:00
print format_notice ( $authenticator -> change_password ( $_SESSION [ " uid " ], $old_pw , $new_pw ));
2012-01-23 08:20:09 +00:00
} else {
2015-07-06 09:10:15 +00:00
print " ERROR: " . format_error ( " Function not supported by authentication module. " );
2012-01-23 08:20:09 +00:00
}
2011-12-13 06:00:42 +00:00
}
function saveconfig () {
2017-12-03 20:35:38 +00:00
$boolean_prefs = explode ( " , " , clean ( $_POST [ " boolean_prefs " ]));
2013-03-19 19:14:23 +00:00
foreach ( $boolean_prefs as $pref ) {
if ( ! isset ( $_POST [ $pref ])) $_POST [ $pref ] = 'false' ;
}
2013-04-04 14:15:37 +00:00
$need_reload = false ;
2011-12-13 06:00:42 +00:00
foreach ( array_keys ( $_POST ) as $pref_name ) {
2017-12-02 09:01:56 +00:00
$value = $_POST [ $pref_name ];
2011-12-13 06:00:42 +00:00
2018-12-07 07:35:46 +00:00
switch ( $pref_name ) {
case 'DIGEST_PREFERRED_TIME' :
if ( get_pref ( 'DIGEST_PREFERRED_TIME' ) != $value ) {
2012-01-31 11:52:33 +00:00
2018-12-07 07:35:46 +00:00
$sth = $this -> pdo -> prepare ( " UPDATE ttrss_users SET
2017-12-02 09:01:56 +00:00
last_digest_sent = NULL WHERE id = ? " );
2018-12-07 07:35:46 +00:00
$sth -> execute ([ $_SESSION [ 'uid' ]]);
2012-01-31 11:52:33 +00:00
2018-12-07 07:35:46 +00:00
}
break ;
case 'USER_LANGUAGE' :
if ( ! $need_reload ) $need_reload = $_SESSION [ " language " ] != $value ;
break ;
2012-01-31 11:52:33 +00:00
2018-12-07 07:35:46 +00:00
case 'USER_CSS_THEME' :
if ( ! $need_reload ) $need_reload = get_pref ( $pref_name ) != $value ;
break ;
2020-12-21 05:50:34 +00:00
case 'BLACKLISTED_TAGS' :
$cats = FeedItem_Common :: normalize_categories ( explode ( " , " , $value ));
asort ( $cats );
$value = implode ( " , " , $cats );
break ;
2013-04-04 14:15:37 +00:00
}
2011-12-13 06:00:42 +00:00
2013-04-29 11:54:23 +00:00
set_pref ( $pref_name , $value );
2011-12-13 06:00:42 +00:00
}
2013-04-04 14:15:37 +00:00
if ( $need_reload ) {
print " PREFS_NEED_RELOAD " ;
} else {
print __ ( " The configuration was saved. " );
}
2011-12-13 06:00:42 +00:00
}
function changeemail () {
2017-12-03 20:35:38 +00:00
$email = clean ( $_POST [ " email " ]);
$full_name = clean ( $_POST [ " full_name " ]);
2011-12-13 06:00:42 +00:00
$active_uid = $_SESSION [ " uid " ];
2019-10-09 06:04:51 +00:00
$sth = $this -> pdo -> prepare ( " SELECT email, login, full_name FROM ttrss_users WHERE id = ? " );
$sth -> execute ([ $active_uid ]);
if ( $row = $sth -> fetch ()) {
$old_email = $row [ " email " ];
if ( $old_email != $email ) {
$mailer = new Mailer ();
2020-03-13 11:40:35 +00:00
$tpl = new Templator ();
2019-10-09 06:04:51 +00:00
2020-03-13 11:40:35 +00:00
$tpl -> readTemplateFromFile ( " mail_change_template.txt " );
2019-10-09 06:04:51 +00:00
$tpl -> setVariable ( 'LOGIN' , $row [ " login " ]);
$tpl -> setVariable ( 'NEWMAIL' , $email );
$tpl -> setVariable ( 'TTRSS_HOST' , SELF_URL_PATH );
$tpl -> addBlock ( 'message' );
$tpl -> generateOutputToString ( $message );
$mailer -> mail ([ " to_name " => $row [ " login " ],
" to_address " => $row [ " email " ],
" subject " => " [tt-rss] Mail address change notification " ,
" message " => $message ]);
}
}
2017-12-02 09:01:56 +00:00
$sth = $this -> pdo -> prepare ( " UPDATE ttrss_users SET email = ?,
full_name = ? WHERE id = ? " );
$sth -> execute ([ $email , $full_name , $active_uid ]);
2011-12-13 06:00:42 +00:00
print __ ( " Your personal data has been saved. " );
return ;
}
function resetconfig () {
$_SESSION [ " prefs_op_result " ] = " reset-to-defaults " ;
2018-03-15 16:26:50 +00:00
$sth = $this -> pdo -> prepare ( " DELETE FROM ttrss_user_prefs
2018-06-20 15:27:34 +00:00
WHERE ( profile = : profile OR ( : profile IS NULL AND profile IS NULL ))
2017-12-02 09:01:56 +00:00
AND owner_uid = : uid " );
$sth -> execute ([ " :profile " => $_SESSION [ 'profile' ], " :uid " => $_SESSION [ 'uid' ]]);
2011-12-13 06:00:42 +00:00
2021-02-15 13:07:22 +00:00
$this -> _init_user_prefs ( $_SESSION [ " uid " ], $_SESSION [ " profile " ]);
2013-04-05 03:52:50 +00:00
echo __ ( " Your preferences are now set to default values. " );
2011-12-13 06:00:42 +00:00
}
2021-02-14 08:29:38 +00:00
private function index_auth_personal () {
2011-12-13 06:00:42 +00:00
2017-12-02 09:01:56 +00:00
$sth = $this -> pdo -> prepare ( " SELECT email,full_name,otp_enabled,
2012-03-29 10:44:52 +00:00
access_level FROM ttrss_users
2017-12-02 09:01:56 +00:00
WHERE id = ? " );
$sth -> execute ([ $_SESSION [ " uid " ]]);
$row = $sth -> fetch ();
2011-12-13 06:00:42 +00:00
2017-12-02 09:01:56 +00:00
$email = htmlspecialchars ( $row [ " email " ]);
$full_name = htmlspecialchars ( $row [ " full_name " ]);
2017-12-03 17:46:27 +00:00
$otp_enabled = sql_bool_to_bool ( $row [ " otp_enabled " ]);
2011-12-13 06:00:42 +00:00
2021-02-14 08:29:38 +00:00
?>
< form dojoType = 'dijit.form.Form' >
2011-12-13 06:00:42 +00:00
2021-02-14 08:29:38 +00:00
< ? php print_hidden ( " op " , " pref-prefs " ) ?>
< ? php print_hidden ( " method " , " changeemail " ) ?>
2012-05-16 07:56:21 +00:00
2021-02-14 08:29:38 +00:00
< script type = 'dojo/method' event = 'onSubmit' args = 'evt' >
evt . preventDefault ();
if ( this . validate ()) {
Notify . progress ( 'Saving data...' , true );
2011-12-13 06:00:42 +00:00
2021-02-14 08:29:38 +00:00
new Ajax . Request ( 'backend.php' , {
parameters : dojo . objectToQuery ( this . getValues ()),
onComplete : function ( transport ) {
Notify . info ( transport . responseText );
}
});
}
</ script >
< fieldset >
< label >< ? = __ ( 'Full name:' ) ?> </label>
< input dojoType = 'dijit.form.ValidationTextBox' name = 'full_name' required = '1' value = " <?= $full_name ?> " >
</ fieldset >
< fieldset >
< label >< ? = __ ( 'E-mail:' ) ?> </label>
< input dojoType = 'dijit.form.ValidationTextBox' name = 'email' required = '1' value = " <?= $email ?> " >
</ fieldset >
< ? php if ( ! SINGLE_USER_MODE && ! empty ( $_SESSION [ " hide_hello " ])) { ?>
< fieldset >
< label >< ? = __ ( 'Access level:' ) ?> </label>
< ? = $access_level_names [ $row [ " access_level " ]] ?>
</ fieldset >
< ? php } ?>
< hr />
< button dojoType = 'dijit.form.Button' type = 'submit' class = 'alt-primary' >
< ? = __ ( " Save data " ) ?>
</ button >
</ form >
< ? php
}
2019-02-20 14:21:32 +00:00
2021-02-14 08:29:38 +00:00
private function index_auth_password () {
2012-12-27 11:14:44 +00:00
if ( $_SESSION [ " auth_module " ]) {
2013-04-18 08:27:34 +00:00
$authenticator = PluginHost :: getInstance () -> get_plugin ( $_SESSION [ " auth_module " ]);
2012-08-16 14:21:35 +00:00
} else {
$authenticator = false ;
}
2021-02-14 08:29:38 +00:00
$otp_enabled = $this -> is_otp_enabled ();
2020-02-18 08:51:04 +00:00
2012-08-16 14:21:35 +00:00
if ( $authenticator && method_exists ( $authenticator , " change_password " )) {
2021-02-14 08:29:38 +00:00
?>
2011-12-13 06:00:42 +00:00
2021-02-14 08:29:38 +00:00
< div style = 'display : none' id = 'pwd_change_infobox' ></ div >
2011-12-13 06:00:42 +00:00
2021-02-14 08:29:38 +00:00
< form dojoType = 'dijit.form.Form' >
2011-12-13 06:00:42 +00:00
2021-02-14 08:29:38 +00:00
< ? php print_hidden ( " op " , " pref-prefs " ) ?>
< ? php print_hidden ( " method " , " changepassword " ) ?>
2015-07-06 09:10:15 +00:00
2021-02-14 08:29:38 +00:00
< script type = 'dojo/method' event = 'onSubmit' args = 'evt' >
evt . preventDefault ();
if ( this . validate ()) {
Notify . progress ( 'Changing password...' , true );
2015-07-06 09:10:15 +00:00
2021-02-14 08:29:38 +00:00
new Ajax . Request ( 'backend.php' , {
parameters : dojo . objectToQuery ( this . getValues ()),
onComplete : function ( transport ) {
Notify . close ();
if ( transport . responseText . indexOf ( 'ERROR: ' ) == 0 ) {
2015-07-06 09:10:15 +00:00
2021-02-14 08:29:38 +00:00
$ ( 'pwd_change_infobox' ) . innerHTML =
transport . responseText . replace ( 'ERROR: ' , '' );
2015-07-06 09:10:15 +00:00
2021-02-14 08:29:38 +00:00
} else {
$ ( 'pwd_change_infobox' ) . innerHTML =
transport . responseText . replace ( 'ERROR: ' , '' );
2015-07-06 09:10:15 +00:00
2021-02-14 08:29:38 +00:00
const warn = $ ( 'default_pass_warning' );
if ( warn ) Element . hide ( warn );
}
2011-12-13 06:00:42 +00:00
2021-02-14 08:29:38 +00:00
new Effect . Appear ( 'pwd_change_infobox' );
}
});
this . reset ();
}
</ script >
2012-09-04 08:39:33 +00:00
2021-02-14 08:29:38 +00:00
< ? php if ( $otp_enabled ) {
print_notice ( __ ( " Changing your current password will disable OTP. " ));
} ?>
2011-12-13 06:00:42 +00:00
2021-02-14 08:29:38 +00:00
< fieldset >
< label >< ? = __ ( " Old password: " ) ?> </label>
< input dojoType = 'dijit.form.ValidationTextBox' type = 'password' required = '1' name = 'old_password' >
</ fieldset >
2011-12-13 06:00:42 +00:00
2021-02-14 08:29:38 +00:00
< fieldset >
< label >< ? = __ ( " New password: " ) ?> </label>
< input dojoType = 'dijit.form.ValidationTextBox' type = 'password' regexp = '^[^<>]+' required = '1' name = 'new_password' >
</ fieldset >
2011-12-13 06:00:42 +00:00
2021-02-14 08:29:38 +00:00
< fieldset >
< label >< ? = __ ( " Confirm password: " ) ?> </label>
< input dojoType = 'dijit.form.ValidationTextBox' type = 'password' regexp = '^[^<>]+' required = '1' name = 'confirm_password' >
</ fieldset >
2011-12-13 06:00:42 +00:00
2021-02-14 08:29:38 +00:00
< hr />
2019-02-20 14:21:32 +00:00
2021-02-14 08:29:38 +00:00
< button dojoType = 'dijit.form.Button' type = 'submit' class = 'alt-primary' >
< ? = __ ( " Change password " ) ?>
</ button >
</ form >
2011-12-13 06:00:42 +00:00
2021-02-14 08:29:38 +00:00
< ? php
2011-12-13 06:00:42 +00:00
2020-02-18 08:51:04 +00:00
} else {
print_notice ( T_sprintf ( " Authentication module used for this session (<b>%s</b>) does not provide an ability to set passwords. " ,
$_SESSION [ " auth_module " ]));
}
2021-02-14 08:29:38 +00:00
}
2019-11-01 09:23:11 +00:00
2021-02-14 08:29:38 +00:00
private function index_auth_app_passwords () {
print_notice ( " You can create separate passwords for API clients. Using one is required if you enable OTP. " );
?>
2019-11-01 09:23:11 +00:00
2021-02-14 08:29:38 +00:00
< div id = 'app_passwords_holder' >
< ? php $this -> appPasswordList () ?>
</ div >
2019-11-01 09:23:11 +00:00
2021-02-14 08:29:38 +00:00
< hr >
2019-11-01 09:23:11 +00:00
2021-02-14 08:29:38 +00:00
< button style = 'float : left' class = 'alt-primary' dojoType = 'dijit.form.Button' onclick = " Helpers.AppPasswords.generate() " >
< ? = __ ( 'Generate new password' ) ?>
</ button >
2019-11-01 12:03:57 +00:00
2021-02-14 08:29:38 +00:00
< button style = 'float : left' class = 'alt-danger' dojoType = 'dijit.form.Button'
onclick = " Helpers.AppPasswords.removeSelected() " >
< ? = __ ( 'Remove selected passwords' ) ?>
</ button >
2019-11-01 12:03:57 +00:00
2021-02-14 08:29:38 +00:00
< ? php
}
2019-11-01 12:03:57 +00:00
2021-02-14 08:29:38 +00:00
private function is_otp_enabled () {
$sth = $this -> pdo -> prepare ( " SELECT otp_enabled FROM ttrss_users
WHERE id = ? " );
$sth -> execute ([ $_SESSION [ " uid " ]]);
2019-11-01 12:03:57 +00:00
2021-02-14 08:29:38 +00:00
if ( $row = $sth -> fetch ()) {
return sql_bool_to_bool ( $row [ " otp_enabled " ]);
}
2019-11-01 09:23:11 +00:00
2021-02-14 08:29:38 +00:00
return false ;
}
2012-09-03 14:33:46 +00:00
2021-02-14 08:29:38 +00:00
private function index_auth_2fa () {
$otp_enabled = $this -> is_otp_enabled ();
2012-09-03 14:33:46 +00:00
2021-02-14 08:29:38 +00:00
if ( $_SESSION [ " auth_module " ] == " auth_internal " ) {
2020-02-18 08:51:04 +00:00
if ( $otp_enabled ) {
print_warning ( " One time passwords are currently enabled. Enter your current password below to disable. " );
2021-02-14 08:29:38 +00:00
?>
< form dojoType = 'dijit.form.Form' >
< ? php print_hidden ( " op " , " pref-prefs " ) ?>
< ? php print_hidden ( " method " , " otpdisable " ) ?>
< script type = 'dojo/method' event = 'onSubmit' args = 'evt' >
evt . preventDefault ();
if ( this . validate ()) {
Notify . progress ( 'Disabling OTP' , true );
new Ajax . Request ( 'backend.php' , {
parameters : dojo . objectToQuery ( this . getValues ()),
onComplete : function ( transport ) {
Notify . close ();
if ( transport . responseText . indexOf ( 'ERROR: ' ) == 0 ) {
Notify . error ( transport . responseText . replace ( 'ERROR: ' , '' ));
} else {
window . location . reload ();
}
}
});
this . reset ();
}
</ script >
2020-02-18 08:51:04 +00:00
2021-02-14 08:29:38 +00:00
< fieldset >
< label >< ? = __ ( " Your password: " ) ?> </label>
< input dojoType = 'dijit.form.ValidationTextBox' type = 'password' required = '1' name = 'password' >
</ fieldset >
2012-09-04 08:39:33 +00:00
2021-02-14 08:29:38 +00:00
< hr />
2019-08-02 05:03:20 +00:00
2021-02-14 08:29:38 +00:00
< button dojoType = 'dijit.form.Button' type = 'submit' class = 'alt-danger' >
< ? = __ ( " Disable OTP " ) ?>
</ button >
2012-09-04 08:39:33 +00:00
2021-02-14 08:29:38 +00:00
</ form >
2012-09-04 08:39:33 +00:00
2021-02-14 08:29:38 +00:00
< ? php
2012-09-04 08:39:33 +00:00
2020-02-18 08:51:04 +00:00
} else {
2012-09-04 08:39:33 +00:00
2020-02-18 08:51:04 +00:00
print_warning ( " You will need a compatible Authenticator to use this. Changing your password would automatically disable OTP. " );
print_notice ( " You will need to generate app passwords for the API clients if you enable OTP. " );
2012-09-04 08:39:33 +00:00
2020-02-18 08:51:04 +00:00
if ( function_exists ( " imagecreatefromstring " )) {
print " <h3> " . __ ( " Scan the following code by the Authenticator application or copy the key manually " ) . " </h3> " ;
2020-09-17 05:43:39 +00:00
$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 '> " ;
2019-11-01 07:32:58 +00:00
} else {
2020-02-18 08:51:04 +00:00
print_error ( " PHP GD functions are required to generate QR codes. " );
print " <h3> " . __ ( " Use the following OTP key with a compatible Authenticator application " ) . " </h3> " ;
}
2012-09-03 14:33:46 +00:00
2020-02-18 08:51:04 +00:00
$otp_secret = $this -> otpsecret ();
2021-02-14 08:29:38 +00:00
?>
< form dojoType = 'dijit.form.Form' id = 'changeOtpForm' >
< ? php print_hidden ( " op " , " pref-prefs " ) ?>
< ? php print_hidden ( " method " , " otpenable " ) ?>
< 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 ();
if ( this . validate ()) {
Notify . progress ( 'Saving data...' , true );
new Ajax . Request ( 'backend.php' , {
parameters : dojo . objectToQuery ( this . getValues ()),
onComplete : function ( transport ) {
Notify . close ();
if ( transport . responseText . indexOf ( 'ERROR:' ) == 0 ) {
Notify . error ( transport . responseText . replace ( 'ERROR:' , '' ));
} else {
window . location . reload ();
}
}
});
}
</ script >
2019-11-01 07:32:58 +00:00
2021-02-14 08:29:38 +00:00
< fieldset >
< label >< ? = __ ( " Your password: " ) ?> </label>
< input dojoType = 'dijit.form.ValidationTextBox' type = 'password' required = '1' name = 'password' >
</ fieldset >
2012-09-04 08:39:33 +00:00
2021-02-14 08:29:38 +00:00
< fieldset >
< label >< ? = __ ( " One time password: " ) ?> </label>
< input dojoType = 'dijit.form.ValidationTextBox' autocomplete = 'off' required = '1' name = 'otp' >
</ fieldset >
2012-09-04 08:39:33 +00:00
2021-02-14 08:29:38 +00:00
< hr />
2012-09-03 14:33:46 +00:00
2021-02-14 08:29:38 +00:00
< button dojoType = 'dijit.form.Button' type = 'submit' class = 'alt-primary' >
< ? = __ ( " Enable OTP " ) ?>
</ button >
2012-09-03 14:33:46 +00:00
2021-02-14 08:29:38 +00:00
</ form >
< ? php
2012-09-03 14:33:46 +00:00
}
2020-02-18 08:51:04 +00:00
} else {
print_notice ( " OTP is only available when using <b>auth_internal</b> authentication module. " );
2011-12-13 06:00:42 +00:00
}
2021-02-14 08:29:38 +00:00
}
2011-12-13 06:00:42 +00:00
2021-02-14 09:25:41 +00:00
function index_auth () {
2021-02-14 08:29:38 +00:00
?>
< 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
}
2011-12-13 06:00:42 +00:00
2021-02-14 08:29:38 +00:00
private function index_prefs_list () {
2021-02-05 20:41:32 +00:00
$profile = $_SESSION [ " profile " ] ? ? null ;
2018-12-04 07:47:01 +00:00
if ( $profile ) {
2013-03-24 16:50:20 +00:00
print_notice ( __ ( " Some preferences are only available in default profile. " ));
2021-02-15 13:07:22 +00:00
$this -> _init_user_prefs ( $_SESSION [ " uid " ], $profile );
2011-12-13 06:00:42 +00:00
} else {
2021-02-15 13:07:22 +00:00
$this -> _init_user_prefs ( $_SESSION [ " uid " ]);
2011-12-13 06:00:42 +00:00
}
2019-02-21 19:08:21 +00:00
$prefs_available = [];
2017-12-02 09:01:56 +00:00
$sth = $this -> pdo -> prepare ( " SELECT DISTINCT
2013-04-02 12:20:06 +00:00
ttrss_user_prefs . pref_name , value , type_name ,
2012-08-30 09:06:58 +00:00
ttrss_prefs_sections . order_id ,
2013-04-02 12:20:06 +00:00
def_value , section_id
2011-12-13 06:00:42 +00:00
FROM ttrss_prefs , ttrss_prefs_types , ttrss_prefs_sections , ttrss_user_prefs
WHERE type_id = ttrss_prefs_types . id AND
2017-12-02 09:01:56 +00:00
( profile = : profile OR ( : profile IS NULL AND profile IS NULL )) AND
2011-12-13 06:00:42 +00:00
section_id = ttrss_prefs_sections . id AND
ttrss_user_prefs . pref_name = ttrss_prefs . pref_name AND
2017-12-02 09:01:56 +00:00
owner_uid = : uid
2013-04-02 12:20:06 +00:00
ORDER BY ttrss_prefs_sections . order_id , pref_name " );
2018-12-04 07:47:01 +00:00
$sth -> execute ([ " :uid " => $_SESSION [ 'uid' ], " :profile " => $profile ]);
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
$listed_boolean_prefs = [];
2013-03-19 19:14:23 +00:00
2017-12-02 09:01:56 +00:00
while ( $line = $sth -> fetch ()) {
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
if ( in_array ( $line [ " pref_name " ], $this -> pref_blacklist )) {
2011-12-13 06:00:42 +00:00
continue ;
}
2019-02-21 19:08:21 +00:00
if ( $profile && in_array ( $line [ " pref_name " ], $this -> profile_blacklist )) {
continue ;
}
2013-04-02 12:20:06 +00:00
2019-02-21 19:08:21 +00:00
$pref_name = $line [ " pref_name " ];
2021-02-15 13:07:22 +00:00
$short_desc = $this -> _get_short_desc ( $pref_name );
2013-04-02 12:20:06 +00:00
2019-02-21 19:08:21 +00:00
if ( ! $short_desc )
2011-12-13 06:00:42 +00:00
continue ;
2019-02-21 19:08:21 +00:00
$prefs_available [ $pref_name ] = [
'type_name' => $line [ " type_name " ],
'value' => $line [ 'value' ],
2021-02-15 13:07:22 +00:00
'help_text' => $this -> _get_help_text ( $pref_name ),
2019-02-21 19:08:21 +00:00
'short_desc' => $short_desc
];
}
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
foreach ( array_keys ( $this -> pref_item_map ) as $section ) {
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
print " <h2> $section </h2> " ;
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
foreach ( $this -> pref_item_map [ $section ] as $pref_name ) {
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
if ( $pref_name == 'BLOCK_SEPARATOR' && ! $profile ) {
print " <hr/> " ;
continue ;
}
2011-12-13 06:00:42 +00:00
2019-04-10 10:03:26 +00:00
if ( $pref_name == " DEFAULT_SEARCH_LANGUAGE " && DB_TYPE != " pgsql " ) {
continue ;
}
2021-02-14 08:29:38 +00:00
if ( isset ( $prefs_available [ $pref_name ])) {
$item = $prefs_available [ $pref_name ];
2013-04-29 11:54:23 +00:00
2019-02-25 16:22:20 +00:00
print " <fieldset class='prefs'> " ;
2011-12-13 06:00:42 +00:00
2019-02-25 14:15:05 +00:00
print " <label for='CB_ $pref_name '> " ;
2019-02-21 19:08:21 +00:00
print $item [ 'short_desc' ] . " : " ;
print " </label> " ;
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
$value = $item [ 'value' ];
$type_name = $item [ 'type_name' ];
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
if ( $pref_name == " USER_LANGUAGE " ) {
print_select_hash ( $pref_name , $value , get_translations (),
2019-04-13 20:36:15 +00:00
" style='width : 220px; margin : 0px' dojoType='fox.form.Select' " );
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
} else if ( $pref_name == " USER_TIMEZONE " ) {
2013-03-28 17:04:29 +00:00
2019-02-21 19:08:21 +00:00
$timezones = explode ( " \n " , file_get_contents ( " lib/timezones.txt " ));
2013-03-28 17:04:29 +00:00
2019-02-21 19:08:21 +00:00
print_select ( $pref_name , $value , $timezones , 'dojoType="dijit.form.FilteringSelect"' );
2020-12-21 05:50:34 +00:00
} else if ( $pref_name == " BLACKLISTED_TAGS " ) { # TODO: other possible <textarea> prefs go here
print " <div> " ;
print " <textarea dojoType='dijit.form.SimpleTextarea' rows='4'
style = 'width: 500px; font-size : 12px;'
name = '$pref_name' > $value </ textarea >< br /> " ;
print " <div class='help-text-bottom text-muted'> " . $this -> pref_help_bottom [ $pref_name ] . " </div> " ;
print " </div> " ;
2019-02-21 19:08:21 +00:00
} else if ( $pref_name == " USER_CSS_THEME " ) {
2017-01-26 19:37:22 +00:00
2019-02-21 19:08:21 +00:00
$themes = array_merge ( glob ( " themes/*.php " ), glob ( " themes/*.css " ), glob ( " themes.local/*.css " ));
$themes = array_map ( " basename " , $themes );
$themes = array_filter ( $themes , " theme_exists " );
asort ( $themes );
2018-12-06 11:49:33 +00:00
2020-02-22 13:22:44 +00:00
if ( ! theme_exists ( $value )) $value = " " ;
2018-12-06 11:49:33 +00:00
2019-04-13 20:36:15 +00:00
print " <select name=' $pref_name ' id=' $pref_name ' dojoType='fox.form.Select'> " ;
2018-12-06 11:49:33 +00:00
2020-02-22 13:22:44 +00:00
$issel = $value == " " ? " selected='selected' " : " " ;
print " <option $issel value=''> " . __ ( " default " ) . " </option> " ;
2013-03-28 17:04:29 +00:00
2019-02-21 19:08:21 +00:00
foreach ( $themes as $theme ) {
$issel = $value == $theme ? " selected='selected' " : " " ;
print " <option $issel value=' $theme '> $theme </option> " ;
}
2019-02-21 13:21:16 +00:00
2019-02-21 19:08:21 +00:00
print " </select> " ;
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
print " <button dojoType= \" dijit.form.Button \" class='alt-info'
2021-02-12 18:51:32 +00:00
onclick = \ " Helpers.Prefs.customizeCSS() \" > " . __ ( 'Customize' ) . " </button> " ;
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
print " <button dojoType='dijit.form.Button' onclick='window.open( \" https://tt-rss.org/wiki/Themes \" )'>
< i class = 'material-icons' > open_in_new </ i > " .__( " More themes ... " ). " </ button > " ;
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
} else if ( $pref_name == " DEFAULT_UPDATE_INTERVAL " ) {
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
global $update_intervals_nodefault ;
2013-03-19 19:14:23 +00:00
2019-02-21 19:08:21 +00:00
print_select_hash ( $pref_name , $value , $update_intervals_nodefault ,
2019-04-13 20:36:15 +00:00
'dojoType="fox.form.Select"' );
2019-04-10 10:03:26 +00:00
} else if ( $pref_name == " DEFAULT_SEARCH_LANGUAGE " ) {
print_select ( $pref_name , $value , Pref_Feeds :: get_ts_languages (),
2019-04-13 20:36:15 +00:00
'dojoType="fox.form.Select"' );
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
} else if ( $type_name == " bool " ) {
array_push ( $listed_boolean_prefs , $pref_name );
2011-12-13 06:00:42 +00:00
2021-02-14 08:29:38 +00:00
$is_checked = ( $value == " true " ) ? " checked= \" checked \" " : " " ;
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
if ( $pref_name == " PURGE_UNREAD_ARTICLES " && FORCE_ARTICLE_PURGE != 0 ) {
2021-02-14 08:29:38 +00:00
$is_disabled = " disabled= \" 1 \" " ;
$is_checked = " checked= \" checked \" " ;
2019-02-21 19:08:21 +00:00
} else {
2021-02-14 08:29:38 +00:00
$is_disabled = " " ;
2019-02-21 19:08:21 +00:00
}
2011-12-13 06:00:42 +00:00
2021-02-14 08:29:38 +00:00
print " <input type='checkbox' name=' $pref_name ' $is_checked $is_disabled
2019-02-21 19:08:21 +00:00
dojoType = 'dijit.form.CheckBox' id = 'CB_$pref_name' value = '1' > " ;
2011-12-13 06:00:42 +00:00
2020-12-21 05:50:34 +00:00
} else if ( in_array ( $pref_name , [ 'FRESH_ARTICLE_MAX_AGE' ,
'PURGE_OLD_DAYS' , 'LONG_DATE_FORMAT' , 'SHORT_DATE_FORMAT' ])) {
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
$regexp = ( $type_name == 'integer' ) ? 'regexp="^\d*$"' : '' ;
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
if ( $pref_name == " PURGE_OLD_DAYS " && FORCE_ARTICLE_PURGE != 0 ) {
2021-02-14 08:29:38 +00:00
$is_disabled = " disabled='1' " ;
2019-02-21 19:08:21 +00:00
$value = FORCE_ARTICLE_PURGE ;
} else {
2021-02-14 08:29:38 +00:00
$is_disabled = " " ;
2019-02-21 19:08:21 +00:00
}
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
if ( $type_name == 'integer' )
print " <input dojoType= \" dijit.form.NumberSpinner \"
2021-02-14 08:29:38 +00:00
required = '1' $is_disabled
2019-02-21 19:08:21 +00:00
name = \ " $pref_name\ " value = \ " $value\ " > " ;
else
print " <input dojoType= \" dijit.form.TextBox \"
2021-02-14 08:29:38 +00:00
required = '1' $regexp $is_disabled
2019-02-21 19:08:21 +00:00
name = \ " $pref_name\ " value = \ " $value\ " > " ;
2011-12-13 06:00:42 +00:00
2019-02-21 19:08:21 +00:00
} else if ( $pref_name == " SSL_CERT_SERIAL " ) {
print " <input dojoType='dijit.form.ValidationTextBox'
id = 'SSL_CERT_SERIAL' readonly = '1'
name = \ " $pref_name\ " value = \ " $value\ " > " ;
$cert_serial = htmlspecialchars ( get_ssl_certificate_id ());
$has_serial = ( $cert_serial ) ? " false " : " true " ;
print " <button dojoType='dijit.form.Button' disabled=' $has_serial '
onclick = \ " dijit.byId('SSL_CERT_SERIAL').attr('value', ' $cert_serial ') \" > " .
__ ( 'Register' ) . " </button> " ;
print " <button dojoType='dijit.form.Button' class='alt-danger'
onclick = \ " dijit.byId('SSL_CERT_SERIAL').attr('value', '') \" > " .
__ ( 'Clear' ) . " </button> " ;
2019-08-02 05:03:20 +00:00
print " <button dojoType='dijit.form.Button' class='alt-info'
onclick = 'window.open(\"https://tt-rss.org/wiki/SSL%20Certificate%20Authentication\")' >
2019-02-21 19:08:21 +00:00
< i class = 'material-icons' > help </ i > " .__( " More info ... " ). " </ button > " ;
} else if ( $pref_name == 'DIGEST_PREFERRED_TIME' ) {
print " <input dojoType= \" dijit.form.ValidationTextBox \"
id = \ " $pref_name\ " regexp = \ " [012]? \ d: \ d \ d \" placeHolder= \" 12:00 \"
name = \ " $pref_name\ " value = \ " $value\ " > " ;
$item [ 'help_text' ] .= " . " . T_sprintf ( " Current server time: %s " , date ( " H:i " ));
} else {
$regexp = ( $type_name == 'integer' ) ? 'regexp="^\d*$"' : '' ;
print " <input dojoType= \" dijit.form.ValidationTextBox \" $regexp name= \" $pref_name\ " value = \ " $value\ " > " ;
}
if ( $item [ 'help_text' ])
2019-03-08 07:11:57 +00:00
print " <div class='help-text text-muted'><label for='CB_ $pref_name '> " . $item [ 'help_text' ] . " </label></div> " ;
2019-02-21 19:08:21 +00:00
print " </fieldset> " ;
}
}
2011-12-13 06:00:42 +00:00
}
2021-02-14 08:29:38 +00:00
print_hidden ( " boolean_prefs " , htmlspecialchars ( join ( " , " , $listed_boolean_prefs )));
}
2011-12-13 06:00:42 +00:00
2021-02-14 08:29:38 +00:00
private function index_prefs () {
?>
< form dojoType = 'dijit.form.Form' id = 'changeSettingsForm' >
< ? php print_hidden ( " op " , " pref-prefs " ) ?>
< ? php print_hidden ( " method " , " saveconfig " ) ?>
< script type = 'dojo/method' event = 'onSubmit' args = 'evt, quit' >
if ( evt ) evt . preventDefault ();
if ( this . validate ()) {
console . log ( dojo . objectToQuery ( this . getValues ()));
2011-12-13 06:00:42 +00:00
2021-02-14 08:29:38 +00:00
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 >
< 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 " >
< 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 >
< button dojoType = " dijit.form.Button " onclick = " return Helpers.Profiles.edit() " >
< ? = __ ( 'Manage profiles' ) ?>
</ button >
< button dojoType = " dijit.form.Button " class = " alt-danger " onclick = " return Helpers.Prefs.confirmReset() " >
< ? = __ ( 'Reset to defaults' ) ?>
</ button >
< ? php PluginHost :: getInstance () -> run_hooks ( PluginHost :: HOOK_PREFS_TAB_SECTION , " prefPrefsPrefsOutside " ) ?>
</ div >
2013-04-04 10:53:36 +00:00
</ div >
2021-02-14 08:29:38 +00:00
</ form >
< ? php
}
2019-11-14 04:01:45 +00:00
2021-02-14 08:29:38 +00:00
private function index_plugins_system () {
2019-02-25 14:15:05 +00:00
print_notice ( " System plugins are enabled in <strong>config.php</strong> for all users. " );
2012-12-24 20:45:10 +00:00
2021-02-14 08:29:38 +00:00
$system_enabled = array_map ( " trim " , explode ( " , " , ( string ) PLUGINS ));
2012-12-24 20:45:10 +00:00
2013-05-07 07:35:10 +00:00
$tmppluginhost = new PluginHost ();
2015-10-08 14:02:32 +00:00
$tmppluginhost -> load_all ( $tmppluginhost :: KIND_ALL , $_SESSION [ " uid " ], true );
2012-12-24 20:45:10 +00:00
foreach ( $tmppluginhost -> get_plugins () as $name => $plugin ) {
2012-12-25 06:02:08 +00:00
$about = $plugin -> about ();
2012-12-24 20:45:10 +00:00
2021-02-05 20:41:32 +00:00
if ( $about [ 3 ] ? ? false ) {
2021-02-14 08:29:38 +00:00
$is_checked = in_array ( $name , $system_enabled ) ? " checked " : " " ;
?>
< fieldset class = 'prefs plugin' >
< 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]) ?>
</ label >
< ? 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
2012-12-24 20:45:10 +00:00
}
}
2021-02-14 08:29:38 +00:00
}
2012-12-24 20:45:10 +00:00
2021-02-14 08:29:38 +00:00
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 );
2012-12-24 20:45:10 +00:00
foreach ( $tmppluginhost -> get_plugins () as $name => $plugin ) {
2012-12-25 06:02:08 +00:00
$about = $plugin -> about ();
2012-12-24 20:45:10 +00:00
2021-02-08 12:41:15 +00:00
if ( empty ( $about [ 3 ]) || $about [ 3 ] == false ) {
2012-12-24 20:45:10 +00:00
2021-02-14 08:29:38 +00:00
$is_checked = " " ;
$is_disabled = " " ;
2019-02-25 14:15:05 +00:00
2012-12-24 20:45:10 +00:00
if ( in_array ( $name , $system_enabled )) {
2021-02-14 08:29:38 +00:00
$is_checked = " checked='1' " ;
$is_disabled = " disabled='1' " ;
2012-12-24 20:45:10 +00:00
} else if ( in_array ( $name , $user_enabled )) {
2021-02-14 08:29:38 +00:00
$is_checked = " checked='1' " ;
2013-03-27 14:16:30 +00:00
}
2021-02-14 08:29:38 +00:00
?>
< fieldset class = 'prefs plugin' >
< label >< ? = $name ?> :</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 >
< ? php if ( count ( $tmppluginhost -> get_all ( $plugin )) > 0 ) {
if ( in_array ( $name , $system_enabled ) || in_array ( $name , $user_enabled )) { ?>
< button dojoType = 'dijit.form.Button'
onclick = 'Helpers.Prefs.clearPluginData("<?= htmlspecialchars($name) ?>")' >
< 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
}
}
}
2021-02-14 09:25:41 +00:00
function index_plugins () {
2021-02-14 08:29:38 +00:00
?>
< 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 );
2012-12-27 15:20:12 +00:00
2021-02-14 08:29:38 +00:00
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 ();
}
}
});
2019-02-25 14:15:05 +00:00
}
2021-02-14 08:29:38 +00:00
</ script >
2012-12-24 20:45:10 +00:00
2021-02-14 08:29:38 +00:00
< ? php print_hidden ( " op " , " pref-prefs " ) ?>
< ? php print_hidden ( " method " , " setplugins " ) ?>
2012-12-24 20:45:10 +00:00
2021-02-14 08:29:38 +00:00
< div dojoType = " dijit.layout.BorderContainer " gutters = " false " >
< 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. " );
}
$feed_handler_whitelist = [ " Af_Comics " ];
2012-12-24 20:45:10 +00:00
2021-02-14 08:29:38 +00:00
$feed_handlers = array_merge (
PluginHost :: getInstance () -> get_hooks ( PluginHost :: HOOK_FEED_FETCHED ),
PluginHost :: getInstance () -> get_hooks ( PluginHost :: HOOK_FEED_PARSED ),
PluginHost :: getInstance () -> get_hooks ( PluginHost :: HOOK_FETCH_FEED ));
2019-02-21 13:21:16 +00:00
2021-02-14 08:29:38 +00:00
$feed_handlers = array_filter ( $feed_handlers , function ( $plugin ) use ( $feed_handler_whitelist ) {
return in_array ( get_class ( $plugin ), $feed_handler_whitelist ) === false ; });
2019-02-21 13:21:16 +00:00
2021-02-14 08:29:38 +00:00
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>) "
);
}
?>
2018-12-04 12:31:21 +00:00
2021-02-14 08:29:38 +00:00
< h2 >< ? = __ ( " System plugins " ) ?> </h2>
2012-08-23 16:23:19 +00:00
2021-02-14 08:29:38 +00:00
< ? php $this -> index_plugins_system () ?>
2018-12-04 12:33:20 +00:00
2021-02-14 08:29:38 +00:00
< h2 >< ? = __ ( " User plugins " ) ?> </h2>
2012-12-23 12:15:34 +00:00
2021-02-14 08:29:38 +00:00
< ? php $this -> index_plugins_user () ?>
2018-12-06 05:56:28 +00:00
2021-02-14 08:29:38 +00:00
</ 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')?> " >
2021-02-14 09:25:41 +00:00
< script type = 'dojo/method' event = 'onSelected' args = 'evt' >
if ( this . domNode . querySelector ( '.loading' ))
window . setTimeout (() => {
xhrPost ( " backend.php " , { op : 'pref-prefs' , method : 'index_auth' }, ( transport ) => {
this . attr ( 'content' , transport . responseText );
});
}, 100 );
</ script >
< span class = 'loading' >< ? = __ ( " Loading, please wait... " ) ?> </span>
2021-02-14 08:29:38 +00:00
</ 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') ?> " >
2021-02-14 09:25:41 +00:00
< script type = 'dojo/method' event = 'onSelected' args = 'evt' >
if ( this . domNode . querySelector ( '.loading' ))
window . setTimeout (() => {
xhrPost ( " backend.php " , { op : 'pref-prefs' , method : 'index_plugins' }, ( transport ) => {
this . attr ( 'content' , transport . responseText );
});
}, 200 );
</ script >
< span class = 'loading' >< ? = __ ( " Loading, please wait... " ) ?> </span>
2021-02-14 08:29:38 +00:00
</ div >
< ? php PluginHost :: getInstance () -> run_hooks ( PluginHost :: HOOK_PREFS_TAB , " prefPrefs " ) ?>
</ div >
< ? php
2011-12-13 06:00:42 +00:00
}
2012-08-23 16:23:19 +00:00
2012-08-30 09:06:58 +00:00
function toggleAdvanced () {
$_SESSION [ " prefs_show_advanced " ] = ! $_SESSION [ " prefs_show_advanced " ];
}
2012-09-03 14:33:46 +00:00
2019-11-01 07:32:58 +00:00
function otpsecret () {
$sth = $this -> pdo -> prepare ( " SELECT salt, otp_enabled
FROM ttrss_users
WHERE id = ? " );
$sth -> execute ([ $_SESSION [ 'uid' ]]);
if ( $row = $sth -> fetch ()) {
$otp_enabled = sql_bool_to_bool ( $row [ " otp_enabled " ]);
if ( ! $otp_enabled ) {
$base32 = new \OTPHP\Base32 ();
$secret = $base32 -> encode ( mb_substr ( sha1 ( $row [ " salt " ]), 0 , 12 ), false );
return $secret ;
}
}
return false ;
}
2012-09-03 14:33:46 +00:00
function otpqrcode () {
2020-09-17 05:43:39 +00:00
$csrf_token_hash = clean ( $_REQUEST [ " csrf_token_hash " ]);
2012-09-03 14:33:46 +00:00
2020-09-17 05:45:17 +00:00
if ( sha1 ( $_SESSION [ " csrf_token " ]) === $csrf_token_hash ) {
2020-09-17 05:43:39 +00:00
require_once " lib/phpqrcode/phpqrcode.php " ;
2012-09-03 14:33:46 +00:00
2020-09-17 05:43:39 +00:00
$sth = $this -> pdo -> prepare ( " SELECT login
FROM ttrss_users
WHERE id = ? " );
$sth -> execute ([ $_SESSION [ 'uid' ]]);
2017-12-02 09:01:56 +00:00
2020-09-17 05:43:39 +00:00
if ( $row = $sth -> fetch ()) {
$secret = $this -> otpsecret ();
$login = $row [ 'login' ];
if ( $secret ) {
QRcode :: png ( " otpauth://totp/ " . urlencode ( $login ) .
" ?secret= $secret &issuer= " . urlencode ( " Tiny Tiny RSS " ));
}
2017-12-02 09:01:56 +00:00
}
2020-09-17 05:43:39 +00:00
} else {
header ( " Content-Type: text/json " );
print error_json ( 6 );
2012-09-03 14:42:17 +00:00
}
2012-09-03 14:33:46 +00:00
}
2012-09-04 08:39:33 +00:00
function otpenable () {
2013-04-16 17:07:26 +00:00
2017-12-03 20:35:38 +00:00
$password = clean ( $_REQUEST [ " password " ]);
$otp = clean ( $_REQUEST [ " otp " ]);
2012-09-04 08:39:33 +00:00
2013-04-18 08:27:34 +00:00
$authenticator = PluginHost :: getInstance () -> get_plugin ( $_SESSION [ " auth_module " ]);
2012-12-27 11:14:44 +00:00
2012-09-04 08:39:33 +00:00
if ( $authenticator -> check_password ( $_SESSION [ " uid " ], $password )) {
2019-11-01 07:32:58 +00:00
$secret = $this -> otpsecret ();
2013-04-16 17:07:26 +00:00
2019-11-01 07:32:58 +00:00
if ( $secret ) {
2013-04-16 17:07:26 +00:00
2018-06-20 15:27:34 +00:00
$base32 = new \OTPHP\Base32 ();
2013-04-16 17:07:26 +00:00
2017-12-02 09:01:56 +00:00
$topt = new \OTPHP\TOTP ( $secret );
2013-04-16 17:07:26 +00:00
2017-12-02 09:01:56 +00:00
$otp_check = $topt -> now ();
2012-09-04 08:39:33 +00:00
2017-12-02 09:01:56 +00:00
if ( $otp == $otp_check ) {
2018-06-20 15:27:34 +00:00
$sth = $this -> pdo -> prepare ( " UPDATE ttrss_users
2017-12-02 09:01:56 +00:00
SET otp_enabled = true WHERE id = ? " );
$sth -> execute ([ $_SESSION [ 'uid' ]]);
print " OK " ;
} else {
print " ERROR: " . __ ( " Incorrect one time password " );
}
2012-09-04 08:39:33 +00:00
}
2017-12-02 09:01:56 +00:00
2012-09-04 08:39:33 +00:00
} else {
2013-04-16 17:07:26 +00:00
print " ERROR: " . __ ( " Incorrect password " );
2012-09-04 08:39:33 +00:00
}
2012-09-03 14:33:46 +00:00
2012-09-04 08:39:33 +00:00
}
2017-12-03 17:46:27 +00:00
static function isdefaultpassword () {
$authenticator = PluginHost :: getInstance () -> get_plugin ( $_SESSION [ " auth_module " ]);
2017-12-15 09:15:15 +00:00
if ( $authenticator &&
method_exists ( $authenticator , " check_password " ) &&
$authenticator -> check_password ( $_SESSION [ " uid " ], " password " )) {
2017-12-03 17:46:27 +00:00
return true ;
}
return false ;
}
2012-09-04 08:39:33 +00:00
function otpdisable () {
2017-12-03 20:35:38 +00:00
$password = clean ( $_REQUEST [ " password " ]);
2012-09-04 08:39:33 +00:00
2013-04-18 08:27:34 +00:00
$authenticator = PluginHost :: getInstance () -> get_plugin ( $_SESSION [ " auth_module " ]);
2012-09-04 08:39:33 +00:00
if ( $authenticator -> check_password ( $_SESSION [ " uid " ], $password )) {
2019-10-09 06:10:43 +00:00
$sth = $this -> pdo -> prepare ( " SELECT email, login FROM ttrss_users WHERE id = ? " );
$sth -> execute ([ $_SESSION [ 'uid' ]]);
if ( $row = $sth -> fetch ()) {
$mailer = new Mailer ();
2020-03-13 11:40:35 +00:00
$tpl = new Templator ();
2019-10-09 06:10:43 +00:00
2020-03-13 11:40:35 +00:00
$tpl -> readTemplateFromFile ( " otp_disabled_template.txt " );
2019-10-09 06:10:43 +00:00
$tpl -> setVariable ( 'LOGIN' , $row [ " login " ]);
$tpl -> setVariable ( 'TTRSS_HOST' , SELF_URL_PATH );
$tpl -> addBlock ( 'message' );
$tpl -> generateOutputToString ( $message );
$mailer -> mail ([ " to_name " => $row [ " login " ],
" to_address " => $row [ " email " ],
" subject " => " [tt-rss] OTP change notification " ,
" message " => $message ]);
}
2017-12-02 09:01:56 +00:00
$sth = $this -> pdo -> prepare ( " UPDATE ttrss_users SET otp_enabled = false WHERE
id = ? " );
$sth -> execute ([ $_SESSION [ 'uid' ]]);
2012-09-04 08:39:33 +00:00
print " OK " ;
} else {
print " ERROR: " . __ ( " Incorrect password " );
2012-09-03 14:33:46 +00:00
}
2012-09-04 08:39:33 +00:00
2012-09-03 14:33:46 +00:00
}
2012-12-24 20:45:10 +00:00
function setplugins () {
2017-12-03 20:35:38 +00:00
if ( is_array ( clean ( $_REQUEST [ " plugins " ])))
$plugins = join ( " , " , clean ( $_REQUEST [ " plugins " ]));
2013-02-28 05:13:00 +00:00
else
$plugins = " " ;
2012-12-24 20:45:10 +00:00
2018-12-26 19:04:35 +00:00
set_pref ( " _ENABLED_PLUGINS " , $plugins );
2012-12-24 20:45:10 +00:00
}
2012-12-27 15:20:12 +00:00
function clearplugindata () {
2017-12-03 20:35:38 +00:00
$name = clean ( $_REQUEST [ " name " ]);
2012-12-27 15:20:12 +00:00
2013-04-18 08:27:34 +00:00
PluginHost :: getInstance () -> clear_data ( PluginHost :: getInstance () -> get_plugin ( $name ));
2012-12-27 15:20:12 +00:00
}
2013-04-01 08:30:34 +00:00
function customizeCSS () {
2013-04-17 14:34:18 +00:00
$value = get_pref ( " USER_STYLESHEET " );
2013-04-01 08:30:34 +00:00
$value = str_replace ( " <br/> " , " \n " , $value );
2021-02-12 06:02:44 +00:00
print json_encode ([ " value " => $value ]);
2013-04-01 08:30:34 +00:00
}
2013-04-01 08:34:49 +00:00
function editPrefProfiles () {
2019-04-07 10:21:52 +00:00
print " <div dojoType='fox.Toolbar'> " ;
2013-04-01 08:34:49 +00:00
2019-04-13 20:36:15 +00:00
print " <div dojoType='fox.form.DropDownButton'> " .
2013-04-01 08:34:49 +00:00
" <span> " . __ ( 'Select' ) . " </span> " ;
2019-02-22 07:48:56 +00:00
print " <div dojoType='dijit.Menu' style='display: none'> " ;
2018-12-07 11:03:33 +00:00
print " <div onclick= \" Tables.select('pref-profiles-list', true) \"
2019-02-22 07:48:56 +00:00
dojoType = 'dijit.MenuItem' > " .__('All'). " </ div > " ;
2018-12-07 11:03:33 +00:00
print " <div onclick= \" Tables.select('pref-profiles-list', false) \"
2019-02-22 07:48:56 +00:00
dojoType = 'dijit.MenuItem' > " .__('None'). " </ div > " ;
2013-04-01 08:34:49 +00:00
print " </div></div> " ;
2019-02-22 07:48:56 +00:00
print " <div style='float : right'> " ;
2013-04-01 08:34:49 +00:00
2019-02-22 07:48:56 +00:00
print " <input name='newprofile' dojoType='dijit.form.ValidationTextBox'
required = '1' >
< button dojoType = 'dijit.form.Button'
2013-04-01 08:34:49 +00:00
onclick = \ " dijit.byId('profileEditDlg').addProfile() \" > " .
__ ( 'Create profile' ) . " </button></div> " ;
print " </div> " ;
2017-12-02 09:01:56 +00:00
$sth = $this -> pdo -> prepare ( " SELECT title,id FROM ttrss_settings_profiles
WHERE owner_uid = ? ORDER BY title " );
$sth -> execute ([ $_SESSION [ 'uid' ]]);
2013-04-01 08:34:49 +00:00
2021-02-12 07:35:13 +00:00
print " <form onsubmit='return false'> " ;
2013-04-01 08:34:49 +00:00
2021-02-12 07:35:13 +00:00
print " <div class='panel panel-scrollable'> " ;
2013-04-01 08:34:49 +00:00
2018-12-07 11:03:33 +00:00
print " <table width='100%' id='pref-profiles-list'> " ;
2013-04-01 08:34:49 +00:00
2018-12-07 11:03:33 +00:00
print " <tr> " ; # data-row-id='0' <-- no point, shouldn't be removed
2013-04-01 08:34:49 +00:00
2018-12-07 11:03:33 +00:00
print " <td><input onclick='Tables.onRowChecked(this);' dojoType='dijit.form.CheckBox' type='checkbox'></td> " ;
2013-04-01 08:34:49 +00:00
2021-02-10 19:06:01 +00:00
if ( ! isset ( $_SESSION [ " profile " ])) {
2013-04-01 08:34:49 +00:00
$is_active = __ ( " (active) " );
} else {
$is_active = " " ;
}
2018-12-07 11:03:33 +00:00
print " <td width='100%'><span> " . __ ( " Default profile " ) . " $is_active </span></td> " ;
2013-04-01 08:34:49 +00:00
print " </tr> " ;
2017-12-02 09:01:56 +00:00
while ( $line = $sth -> fetch ()) {
2013-04-01 08:34:49 +00:00
$profile_id = $line [ " id " ];
2018-12-07 11:03:33 +00:00
print " <tr data-row-id=' $profile_id '> " ;
2013-04-01 08:34:49 +00:00
$edit_title = htmlspecialchars ( $line [ " title " ]);
2018-12-07 11:03:33 +00:00
print " <td><input onclick='Tables.onRowChecked(this);' dojoType='dijit.form.CheckBox' type='checkbox'></td> " ;
2013-04-01 08:34:49 +00:00
2021-02-10 19:03:08 +00:00
if ( isset ( $_SESSION [ " profile " ]) && $_SESSION [ " profile " ] == $line [ " id " ]) {
2013-04-01 08:34:49 +00:00
$is_active = __ ( " (active) " );
} else {
$is_active = " " ;
}
2019-02-22 07:48:56 +00:00
print " <td><span dojoType='dijit.InlineEditBox'
width = '300px' autoSave = 'false'
profile - id = '$profile_id' > " . $edit_title .
" <script type='dojo/method' event='onChange' args='item'>
2013-04-01 08:34:49 +00:00
var elem = this ;
dojo . xhrPost ({
url : 'backend.php' ,
content : { op : 'rpc' , method : 'saveprofile' ,
value : this . value ,
id : this . srcNodeRef . getAttribute ( 'profile-id' )},
load : function ( response ) {
elem . attr ( 'value' , response );
}
});
</ script >
</ span > $is_active </ td > " ;
print " </tr> " ;
}
print " </table> " ;
print " </div> " ;
2019-02-22 07:48:56 +00:00
print " <footer>
2021-02-12 07:35:13 +00:00
< button style = 'float : left' class = 'alt-danger' dojoType = 'dijit.form.Button' onclick = 'App.dialogOf(this).removeSelected()' > " .
__ ( 'Remove selected profiles' ) . " </button>
< button dojoType = 'dijit.form.Button' class = 'alt-primary' type = 'submit' onclick = 'App.dialogOf(this).execute()' > " .
__ ( 'Activate profile' ) . " </button>
< button dojoType = 'dijit.form.Button' onclick = 'App.dialogOf(this).hide()' > " .
__ ( 'Cancel' ) . " </button> " ;
2019-02-22 07:48:56 +00:00
print " </footer> " ;
2013-04-01 08:34:49 +00:00
2021-02-12 07:35:13 +00:00
print " </form> " ;
2013-04-01 08:34:49 +00:00
}
2021-02-15 13:07:22 +00:00
private function _get_short_desc ( $pref_name ) {
2020-12-12 16:09:25 +00:00
if ( isset ( $this -> pref_help [ $pref_name ][ 0 ])) {
2013-04-02 12:20:06 +00:00
return $this -> pref_help [ $pref_name ][ 0 ];
}
return " " ;
}
2013-04-01 08:34:49 +00:00
2021-02-15 13:07:22 +00:00
private function _get_help_text ( $pref_name ) {
2020-12-12 16:09:25 +00:00
if ( isset ( $this -> pref_help [ $pref_name ][ 1 ])) {
2013-04-02 12:20:06 +00:00
return $this -> pref_help [ $pref_name ][ 1 ];
}
return " " ;
}
2019-11-01 12:03:57 +00:00
private function appPasswordList () {
2021-02-14 08:39:26 +00:00
?>
< div dojoType = 'fox.Toolbar' >
< div dojoType = 'fox.form.DropDownButton' >
< span >< ? = __ ( 'Select' ) ?> </span>
< div dojoType = 'dijit.Menu' style = 'display: none' >
< div onclick = " Tables.select('app-password-list', true) "
dojoType = " dijit.MenuItem " >< ? = __ ( 'All' ) ?> </div>
< div onclick = " Tables.select('app-password-list', false) "
dojoType = " dijit.MenuItem " >< ? = __ ( 'None' ) ?> </div>
</ div >
</ div >
</ div >
2019-11-01 12:03:57 +00:00
2021-02-14 08:39:26 +00:00
< div class = 'panel panel-scrollable' >
< table width = '100%' id = 'app-password-list' >
< tr >
< th width = '2%' > </ th >
< th align = 'left' >< ? = __ ( " Description " ) ?> </th>
< th align = 'right' >< ? = __ ( " Created " ) ?> </th>
< th align = 'right' >< ? = __ ( " Last used " ) ?> </th>
</ tr >
< ? php
$sth = $this -> pdo -> prepare ( " SELECT id, title, created, last_used
FROM ttrss_app_passwords WHERE owner_uid = ? " );
$sth -> execute ([ $_SESSION [ 'uid' ]]);
while ( $row = $sth -> fetch ()) { ?>
< tr data - row - id = '<?= $row[' id '] ?>' >
< td align = 'center' >
< input onclick = 'Tables.onRowChecked(this)' dojoType = 'dijit.form.CheckBox' type = 'checkbox' >
</ td >
< td >
< ? = htmlspecialchars ( $row [ " title " ]) ?>
</ td >
< td align = 'right' class = 'text-muted' >
< ? = TimeHelper :: make_local_datetime ( $row [ 'created' ], false ) ?>
</ td >
< td align = 'right' class = 'text-muted' >
< ? = TimeHelper :: make_local_datetime ( $row [ 'last_used' ], false ) ?>
</ td >
</ tr >
< ? php } ?>
</ table >
</ div >
< ? php
2019-11-01 12:03:57 +00:00
}
2021-02-15 13:07:22 +00:00
private function _encrypt_app_password ( $password ) {
2019-11-01 12:03:57 +00:00
$salt = substr ( bin2hex ( get_random_bytes ( 24 )), 0 , 24 );
return " SSHA-512: " . hash ( 'sha512' , $salt . $password ) . " : $salt " ;
}
function deleteAppPassword () {
$ids = explode ( " , " , clean ( $_REQUEST [ 'ids' ]));
$ids_qmarks = arr_qmarks ( $ids );
$sth = $this -> pdo -> prepare ( " DELETE FROM ttrss_app_passwords WHERE id IN ( $ids_qmarks ) AND owner_uid = ? " );
$sth -> execute ( array_merge ( $ids , [ $_SESSION [ 'uid' ]]));
$this -> appPasswordList ();
}
function generateAppPassword () {
$title = clean ( $_REQUEST [ 'title' ]);
$new_password = make_password ( 16 );
2021-02-15 13:07:22 +00:00
$new_password_hash = $this -> _encrypt_app_password ( $new_password );
2019-11-01 12:03:57 +00:00
print_warning ( T_sprintf ( " Generated password <strong>%s</strong> for %s. Please remember it for future reference. " , $new_password , $title ));
2019-11-01 12:40:08 +00:00
$sth = $this -> pdo -> prepare ( " INSERT INTO ttrss_app_passwords
2019-11-01 12:03:57 +00:00
( title , pwd_hash , service , created , owner_uid )
2019-11-01 12:40:08 +00:00
VALUES
2019-11-01 12:03:57 +00:00
( ? , ? , ? , NOW (), ? ) " );
$sth -> execute ([ $title , $new_password_hash , Auth_Base :: AUTH_SERVICE_API , $_SESSION [ 'uid' ]]);
$this -> appPasswordList ();
}
2020-09-22 06:04:33 +00:00
2021-02-15 13:07:22 +00:00
static function _init_user_prefs ( $uid , $profile = false ) {
2020-09-22 06:04:33 +00:00
if ( get_schema_version () < 63 ) $profile_qpart = " " ;
$pdo = Db :: pdo ();
$in_nested_tr = false ;
try {
$pdo -> beginTransaction ();
} catch ( Exception $e ) {
$in_nested_tr = true ;
}
$sth = $pdo -> query ( " SELECT pref_name,def_value FROM ttrss_prefs " );
if ( ! is_numeric ( $profile ) || ! $profile || get_schema_version () < 63 ) $profile = null ;
$u_sth = $pdo -> prepare ( " SELECT pref_name
FROM ttrss_user_prefs WHERE owner_uid = : uid AND
( profile = : profile OR ( : profile IS NULL AND profile IS NULL )) " );
$u_sth -> execute ([ ':uid' => $uid , ':profile' => $profile ]);
$active_prefs = array ();
while ( $line = $u_sth -> fetch ()) {
array_push ( $active_prefs , $line [ " pref_name " ]);
}
while ( $line = $sth -> fetch ()) {
if ( array_search ( $line [ " pref_name " ], $active_prefs ) === false ) {
// print "adding " . $line["pref_name"] . "<br>";
if ( get_schema_version () < 63 ) {
$i_sth = $pdo -> prepare ( " INSERT INTO ttrss_user_prefs
( owner_uid , pref_name , value ) VALUES
( ? , ? , ? ) " );
$i_sth -> execute ([ $uid , $line [ " pref_name " ], $line [ " def_value " ]]);
} else {
$i_sth = $pdo -> prepare ( " INSERT INTO ttrss_user_prefs
( owner_uid , pref_name , value , profile ) VALUES
( ? , ? , ? , ? ) " );
$i_sth -> execute ([ $uid , $line [ " pref_name " ], $line [ " def_value " ], $profile ]);
}
}
}
if ( ! $in_nested_tr ) $pdo -> commit ();
}
2017-12-14 17:02:37 +00:00
}