diff options
Diffstat (limited to 'classes')
-rwxr-xr-x | classes/article.php | 29 | ||||
-rw-r--r-- | classes/backend.php | 19 | ||||
-rw-r--r-- | classes/dbupdater.php | 19 | ||||
-rw-r--r-- | classes/digest.php | 11 | ||||
-rw-r--r-- | classes/dlg.php | 52 | ||||
-rwxr-xr-x | classes/feeds.php | 133 | ||||
-rwxr-xr-x | classes/handler/public.php | 91 | ||||
-rwxr-xr-x | classes/logger/sql.php | 3 | ||||
-rw-r--r-- | classes/mailer.php | 3 | ||||
-rw-r--r-- | classes/opml.php | 72 | ||||
-rw-r--r-- | classes/plugin.php | 19 | ||||
-rwxr-xr-x | classes/pluginhost.php | 9 | ||||
-rwxr-xr-x | classes/pref/feeds.php | 295 | ||||
-rwxr-xr-x | classes/pref/filters.php | 162 | ||||
-rw-r--r-- | classes/pref/labels.php | 50 | ||||
-rw-r--r-- | classes/pref/prefs.php | 172 | ||||
-rw-r--r-- | classes/pref/users.php | 141 | ||||
-rwxr-xr-x | classes/rpc.php | 18 | ||||
-rwxr-xr-x | classes/rssutils.php | 63 |
19 files changed, 613 insertions, 748 deletions
diff --git a/classes/article.php b/classes/article.php index fd693a4fe..028901368 100755 --- a/classes/article.php +++ b/classes/article.php @@ -211,8 +211,6 @@ class Article extends Handler_Protected { function editArticleTags() { - print __("Tags for this article (separated by commas):")."<br>"; - $param = clean($_REQUEST['param']); $tags = Article::get_article_tags($param); @@ -223,23 +221,22 @@ class Article extends Handler_Protected { print_hidden("op", "article"); print_hidden("method", "setArticleTags"); - print "<table width='100%'><tr><td>"; + print "<header class='horizontal'>" . __("Tags for this article (separated by commas):")."</header>"; - print "<textarea dojoType=\"dijit.form.SimpleTextarea\" rows='4' - style='height : 100px; font-size : 12px; width : 98%' id=\"tags_str\" + print "<section>"; + print "<textarea dojoType='dijit.form.SimpleTextarea' rows='4' + style='height : 100px; font-size : 12px; width : 98%' id='tags_str' name='tags_str'>$tags_str</textarea> - <div class=\"autocomplete\" id=\"tags_choices\" - style=\"display:none\"></div>"; - - print "</td></tr></table>"; - - print "<div class='dlgButtons'>"; - - print "<button dojoType=\"dijit.form.Button\" - onclick=\"dijit.byId('editTagsDlg').execute()\">".__('Save')."</button> "; - print "<button dojoType=\"dijit.form.Button\" + <div class='autocomplete' id='tags_choices' + style='display:none'></div>"; + print "</section>"; + + print "<footer>"; + print "<button dojoType='dijit.form.Button' + type='submit' class='alt-primary' onclick=\"dijit.byId('editTagsDlg').execute()\">".__('Save')."</button> "; + print "<button dojoType='dijit.form.Button' onclick=\"dijit.byId('editTagsDlg').hide()\">".__('Cancel')."</button>"; - print "</div>"; + print "</footer>"; } diff --git a/classes/backend.php b/classes/backend.php index bd6b1ff19..4be38e0c4 100644 --- a/classes/backend.php +++ b/classes/backend.php @@ -7,13 +7,18 @@ class Backend extends Handler { } function digestTest() { - header("Content-type: text/html"); - - $rv = Digest::prepare_headlines_digest($_SESSION['uid'], 1, 1000); + if (isset($_SESSION['uid'])) { + header("Content-type: text/html"); - $rv[3] = "<pre>" . $rv[3] . "</pre>"; + $rv = Digest::prepare_headlines_digest($_SESSION['uid'], 1, 1000); - print_r($rv); + print "<h1>HTML</h1>"; + print $rv[0]; + print "<h1>Plain text</h1>"; + print "<pre>".$rv[3]."</pre>"; + } else { + print error_json(6); + } } private function display_main_help() { @@ -149,13 +154,13 @@ class Backend extends Handler { print "</ul>"; } - print "<div class='dlgButtons'>"; + print "<footer>"; print "<button dojoType='dijit.form.Button' style='float : left' class='alt-info' onclick='window.open(\"https://tt-rss.org/wiki/InterfaceTips\")'> <i class='material-icons'>help</i> ".__("More info...")."</button>"; print "<button dojoType='dijit.form.Button' onclick=\"return dijit.byId('helpDlg').hide()\">".__('Close this window')."</button>"; - print "</div>"; + print "</footer>"; } } diff --git a/classes/dbupdater.php b/classes/dbupdater.php index c32afedee..94307aea0 100644 --- a/classes/dbupdater.php +++ b/classes/dbupdater.php @@ -42,15 +42,22 @@ class DbUpdater { foreach ($lines as $line) { if (strpos($line, "--") !== 0 && $line) { - if (!$this->pdo->query($line)) { + + if ($html_output) + print "<pre>$line</pre>"; + else + Debug::log("> $line"); + + try { + $this->pdo->query($line); // PDO returns errors as exceptions now + } catch (PDOException $e) { if ($html_output) { - print_notice("Query: $line"); - print_error("Error: " . implode(", ", $this->pdo->errorInfo())); + print "<div class='text-error'>Error: " . $e->getMessage() . "</div>"; } else { - Debug::log("Query: $line"); - Debug::log("Error: " . implode(", ", $this->pdo->errorInfo())); + Debug::log("Error: " . $e->getMessage()); } + $this->pdo->rollBack(); return false; } } @@ -73,4 +80,4 @@ class DbUpdater { } } -}
\ No newline at end of file +} diff --git a/classes/digest.php b/classes/digest.php index 0d2cac77e..68a14ef68 100644 --- a/classes/digest.php +++ b/classes/digest.php @@ -166,6 +166,15 @@ class Digest $line['feed_title'] = $line['cat_title'] . " / " . $line['feed_title']; } + $article_labels = Article::get_article_labels($line["ref_id"], $user_id); + $article_labels_formatted = ""; + + if (is_array($article_labels) && count($article_labels) > 0) { + $article_labels_formatted = implode(", ", array_map(function($a) { + return $a[1]; + }, $article_labels)); + } + $tpl->setVariable('FEED_TITLE', $line["feed_title"]); $tpl->setVariable('ARTICLE_TITLE', $line["title"]); $tpl->setVariable('ARTICLE_LINK', $line["link"]); @@ -174,6 +183,7 @@ class Digest truncate_string(strip_tags($line["content"]), 300)); // $tpl->setVariable('ARTICLE_CONTENT', // strip_tags($article_content)); + $tpl->setVariable('ARTICLE_LABELS', $article_labels_formatted, true); $tpl->addBlock('article'); @@ -181,6 +191,7 @@ class Digest $tpl_t->setVariable('ARTICLE_TITLE', $line["title"]); $tpl_t->setVariable('ARTICLE_LINK', $line["link"]); $tpl_t->setVariable('ARTICLE_UPDATED', $updated); + $tpl_t->setVariable('ARTICLE_LABELS', $article_labels_formatted, true); // $tpl_t->setVariable('ARTICLE_EXCERPT', // truncate_string(strip_tags($line["excerpt"]), 100)); diff --git a/classes/dlg.php b/classes/dlg.php index 89b88825e..4489af51a 100644 --- a/classes/dlg.php +++ b/classes/dlg.php @@ -14,7 +14,7 @@ class Dlg extends Handler_Protected { } function importOpml() { - print __("If you have imported labels and/or filters, you might need to reload preferences to see your new data.") . "</p>"; + print_notice("If you have imported labels and/or filters, you might need to reload preferences to see your new data."); print "<div class='panel panel-scrollable'>"; @@ -24,11 +24,11 @@ class Dlg extends Handler_Protected { print "</div>"; - print "<div align='center'>"; - print "<button dojoType=\"dijit.form.Button\" + print "<footer class='text-center'>"; + print "<button dojoType='dijit.form.Button' onclick=\"dijit.byId('opmlImportDlg').execute()\">". __('Close this window')."</button>"; - print "</div>"; + print "</footer>"; print "</div>"; @@ -38,25 +38,25 @@ class Dlg extends Handler_Protected { function pubOPMLUrl() { $url_path = Opml::opml_publish_url(); - print "<div class='dlgSec'>" . __("Your Public OPML URL is:") . "</div>"; + print "<header>" . __("Your Public OPML URL is:") . "</header>"; - print "<div class='dlgSecCont'>"; + print "<section>"; print "<div class='panel text-center'>"; print "<a id='pub_opml_url' href='$url_path' target='_blank'>$url_path</a>"; print "</div>"; - print "</div>"; + print "</section>"; - print "<div align='center'>"; + print "<footer class='text-center'>"; - print "<button dojoType=\"dijit.form.Button\" onclick=\"return Helpers.OPML.changeKey()\">". + print "<button dojoType='dijit.form.Button' onclick=\"return Helpers.OPML.changeKey()\">". __('Generate new URL')."</button> "; - print "<button dojoType=\"dijit.form.Button\" onclick=\"return CommonDialogs.closeInfoBox()\">". + print "<button dojoType='dijit.form.Button' onclick=\"return CommonDialogs.closeInfoBox()\">". __('Close this window')."</button>"; - print "</div>"; + print "</footer>"; //return; } @@ -84,12 +84,10 @@ class Dlg extends Handler_Protected { print "</div>"; - print "<div align='center'>"; - + print "<footer class='text-center'>"; print "<button onclick=\"return CommonDialogs.closeInfoBox()\">". __('Close this window')."</button>"; - - print "</div>"; + print "</footer>"; //return; } @@ -149,11 +147,11 @@ class Dlg extends Handler_Protected { print "</div>"; - print "<div align='center'>"; - print "<button dojoType=\"dijit.form.Button\" + print "<footer class='text-center'>"; + print "<button dojoType='dijit.form.Button' onclick=\"return CommonDialogs.closeInfoBox()\">". __('Close this window')."</button>"; - print "</div>"; + print "</footer>"; } @@ -169,15 +167,15 @@ class Dlg extends Handler_Protected { $feed_title = Feeds::getFeedTitle($feed_id, $is_cat); - print "<div class='dlgSec'>".T_sprintf("%s can be accessed via the following secret URL:", $feed_title)."</div>"; + print "<header>".T_sprintf("%s can be accessed via the following secret URL:", $feed_title)."</header>"; - print "<div class='dlgSecCont'>"; + print "<section>"; print "<div class='panel text-center'>"; print "<a id='gen_feed_url' href='$url_path' target='_blank'>$url_path</a>"; print "</div>"; - print "</div>"; + print "</section>"; - print "<div class='dlgButtons'>"; + print "<footer>"; print "<button dojoType='dijit.form.Button' style='float : left' class='alt-info' onclick='window.open(\"https://tt-rss.org/wiki/GeneratedFeeds\")'> <i class='material-icons'>help</i> ".__("More info...")."</button>"; @@ -188,7 +186,7 @@ class Dlg extends Handler_Protected { print "<button dojoType='dijit.form.Button' onclick=\"return CommonDialogs.closeInfoBox()\">". __('Close this window')."</button>"; - print "</div>"; + print "</footer>"; //return; } @@ -197,12 +195,12 @@ class Dlg extends Handler_Protected { print_warning(__("You are using default tt-rss password. Please change it in the Preferences (Personal data / Authentication).")); - print "<div align='center'>"; - print "<button dojoType=\"dijit.form.Button\" onclick=\"document.location.href = 'prefs.php'\">". + print "<footer class='text-center'>"; + print "<button dojoType='dijit.form.Button' onclick=\"document.location.href = 'prefs.php'\">". __('Open Preferences')."</button> "; - print "<button dojoType=\"dijit.form.Button\" + print "<button dojoType='dijit.form.Button' onclick=\"return CommonDialogs.closeInfoBox()\">". __('Close this window')."</button>"; - print "</div>"; + print "</footeer>"; } } diff --git a/classes/feeds.php b/classes/feeds.php index aac9b627f..f7a6aea7b 100755 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -6,7 +6,7 @@ class Feeds extends Handler_Protected { private $params; function csrf_ignore($method) { - $csrf_ignored = array("index", "feedbrowser", "quickaddfeed", "search"); + $csrf_ignored = array("index", "quickaddfeed", "search"); return array_search($method, $csrf_ignored) !== false; } @@ -645,36 +645,30 @@ class Feeds extends Handler_Protected { print_notice("Provided URL is a HTML page referencing multiple feeds, please select required feed from the dropdown menu below."); print "<p></div>"; - //print "<div class=\"dlgSec\">".__("Feed or site URL")."</div>"; - print "<div class=\"dlgSecCont\">"; - - print "<div style='float : right'> - <img style='display : none' - id='feed_add_spinner' src='images/indicator_white.gif'></div>"; + print "<section>"; print "<fieldset>"; - - print "<input style=\"font-size : 16px; width : 540px;\" + print "<div style='float : right'><img style='display : none' id='feed_add_spinner' src='images/indicator_white.gif'></div>"; + print "<input style='font-size : 16px; width : 500px;' placeHolder=\"".__("Feed or site URL")."\" - dojoType=\"dijit.form.ValidationTextBox\" required=\"1\" name=\"feed\" id=\"feedDlg_feedUrl\">"; + dojoType='dijit.form.ValidationTextBox' required='1' name='feed' id='feedDlg_feedUrl'>"; print "</fieldset>"; print "<fieldset>"; if (get_pref('ENABLE_FEED_CATS')) { - print "<label>" . __('Place in category:') . "</label> "; + print "<label class='inline'>" . __('Place in category:') . "</label> "; print_feed_cat_select("cat", false, 'dojoType="dijit.form.Select"'); } print "</fieldset>"; - print "</div>"; + print "</section>"; print '<div id="feedDlg_feedsContainer" style="display : none"> - - <div class="dlgSec">' . __('Available feeds') . '</div> - <div class="dlgSecCont"> + <header>' . __('Available feeds') . '</header> + <section> <fieldset> <select id="feedDlg_feedContainerSelect" dojoType="dijit.form.Select" size="3"> @@ -683,94 +677,40 @@ class Feeds extends Handler_Protected { </script> </select> </fieldset> - </div></div>'; + </section> + </div>'; print "<div id='feedDlg_loginContainer' style='display : none'> - - <div class=\"dlgSec\">".__("Authentication")."</div> - <div class=\"dlgSecCont\"> + <section> <fieldset> <input dojoType=\"dijit.form.TextBox\" name='login'\" placeHolder=\"".__("Login")."\" autocomplete=\"new-password\" style=\"width : 10em;\"> - </fieldset><fieldset> <input placeHolder=\"".__("Password")."\" dojoType=\"dijit.form.TextBox\" type='password' autocomplete=\"new-password\" style=\"width : 10em;\" name='pass'\"> </fieldset> - </div></div>"; - + </section> + </div>"; - print "<div style=\"clear : both\"> - <input type=\"checkbox\" name=\"need_auth\" dojoType=\"dijit.form.CheckBox\" id=\"feedDlg_loginCheck\" + print "<section>"; + print "<label> + <label class='checkbox'><input type='checkbox' name='need_auth' dojoType='dijit.form.CheckBox' id='feedDlg_loginCheck' onclick='displayIfChecked(this, \"feedDlg_loginContainer\")'> - <label for=\"feedDlg_loginCheck\">". - __('This feed requires authentication.')."</div>"; + ".__('This feed requires authentication.')."</label>"; + print "</section>"; - print "<div class=\"dlgButtons\"> - <button dojoType=\"dijit.form.Button\" class=\"alt-primary\" type=\"submit\" onclick=\"return dijit.byId('feedAddDlg').execute()\">".__('Subscribe')."</button>"; + print "<footer>"; + print "<button dojoType='dijit.form.Button' class='alt-primary' type='submit' + onclick=\"return dijit.byId('feedAddDlg').execute()\">".__('Subscribe')."</button>"; - if (!(defined('_DISABLE_FEED_BROWSER') && _DISABLE_FEED_BROWSER)) { - print "<button dojoType=\"dijit.form.Button\" onclick=\"return CommonDialogs.feedBrowser()\">".__('More feeds')."</button>"; - } - - print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedAddDlg').hide()\">".__('Cancel')."</button> - </div>"; + print "<button dojoType='dijit.form.Button' onclick=\"return dijit.byId('feedAddDlg').hide()\">".__('Cancel')."</button>"; + print "</footer>"; print "</form>"; - - //return; - } - - function feedBrowser() { - if (defined('_DISABLE_FEED_BROWSER') && _DISABLE_FEED_BROWSER) return; - - $browser_search = $_REQUEST["search"]; - - print_hidden("op", "rpc"); - print_hidden("method", "updateFeedBrowser"); - - print "<div dojoType=\"dijit.Toolbar\"> - <div style='float : right'> - <img style='display : none' - id='feed_browser_spinner' src='images/indicator_white.gif'> - <input name=\"search\" dojoType=\"dijit.form.TextBox\" size=\"20\" type=\"search\" - onchange=\"dijit.byId('feedBrowserDlg').update()\" value=\"$browser_search\"> - <button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedBrowserDlg').update()\">".__('Search')."</button> - </div>"; - - print " <select name=\"mode\" dojoType=\"dijit.form.Select\" onchange=\"dijit.byId('feedBrowserDlg').update()\"> - <option value='1'>" . __('Popular feeds') . "</option> - <option value='2'>" . __('Feed archive') . "</option> - </select> "; - - print __("limit:"); - - print " <select dojoType=\"dijit.form.Select\" name=\"limit\" onchange=\"dijit.byId('feedBrowserDlg').update()\">"; - - foreach (array(25, 50, 100, 200) as $l) { - //$issel = ($l == $limit) ? "selected=\"1\"" : ""; - print "<option value=\"$l\">$l</option>"; - } - - print "</select> "; - - print "</div>"; - - require_once "feedbrowser.php"; - - print "<ul class='browseFeedList' id='browseFeedList'>"; - print make_feed_browser("", 25); - print "</ul>"; - - print "<div align='center'> - <button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedBrowserDlg').execute()\">".__('Subscribe')."</button> - <button dojoType=\"dijit.form.Button\" style='display : none' id='feed_archive_remove' onclick=\"dijit.byId('feedBrowserDlg').removeFromArchive()\">".__('Remove')."</button> - <button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedBrowserDlg').hide()\" >".__('Cancel')."</button></div>"; - } function search() { @@ -781,38 +721,36 @@ class Feeds extends Handler_Protected { print "<form onsubmit='return false;'>"; - //print "<div class=\"dlgSec\">".__('Look for')."</div>"; - - print "<div class=\"dlgSecCont\">"; + print "<section>"; print "<fieldset>"; - print "<input dojoType=\"dijit.form.ValidationTextBox\" - style=\"font-size : 16px; width : 540px;\" + print "<input dojoType='dijit.form.ValidationTextBox' + style='font-size : 16px; width : 540px;' placeHolder=\"".T_sprintf("Search %s...", $this->getFeedTitle($active_feed_id, $is_cat))."\" - required=\"1\" name=\"query\" type=\"search\" value=''>"; + required='1' name='query' type='search' value=''>"; print "</fieldset>"; - if (DB_TYPE == "pgsql") { print "<fieldset>"; - print "<label>" . __("Language:") . "</label>"; + print "<label class='inline'>" . __("Language:") . "</label>"; print_select("search_language", "", Pref_Feeds::get_ts_languages(), "dojoType='dijit.form.Select' title=\"".__('Used for word stemming')."\""); print "</fieldset>"; } - print "</div>"; + print "</section>"; - print "<div class=\"dlgButtons\">"; + print "<footer>"; if (count(PluginHost::getInstance()->get_hooks(PluginHost::HOOK_SEARCH)) == 0) { print "<button dojoType='dijit.form.Button' style='float : left' class='alt-info' onclick='window.open(\"https://tt-rss.org/wiki/SearchSyntax\")'> <i class='material-icons'>help</i> ".__("Search syntax")."</button>"; } - print "<button dojoType=\"dijit.form.Button\" type=\"submit\" class=\"alt-primary\" onclick=\"dijit.byId('searchDlg').execute()\">".__('Search')."</button> - <button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('searchDlg').hide()\">".__('Cancel')."</button> - </div>"; + print "<button dojoType='dijit.form.Button' type='submit' class='alt-primary' onclick=\"dijit.byId('searchDlg').execute()\">".__('Search')."</button> + <button dojoType='dijit.form.Button' onclick=\"dijit.byId('searchDlg').hide()\">".__('Cancel')."</button>"; + + print "</footer>"; print "</form>"; } @@ -839,6 +777,7 @@ class Feeds extends Handler_Protected { $rehash_checked = isset($_REQUEST["force_rehash"]) ? "checked" : ""; ?> + <!DOCTYPE html> <html> <head> <?php echo stylesheet_tag("css/default.css") ?> diff --git a/classes/handler/public.php b/classes/handler/public.php index 37fe8612a..a8f72e21c 100755 --- a/classes/handler/public.php +++ b/classes/handler/public.php @@ -525,6 +525,7 @@ class Handler_Public extends Handler { header('Content-Type: text/html; charset=utf-8'); ?> + <!DOCTYPE html> <html> <head> <title><?php echo __("Share with Tiny Tiny RSS") ?> ?></title> @@ -622,7 +623,7 @@ class Handler_Public extends Handler { } else { - $return = urlencode($_SERVER["REQUEST_URI"]) + $return = urlencode(make_self_url()); ?> @@ -711,7 +712,9 @@ class Handler_Public extends Handler { user_error("Failed login attempt for $login from {$_SERVER['REMOTE_ADDR']}", E_USER_WARNING); } - if (clean($_REQUEST['return'])) { + $return = clean($_REQUEST['return']); + + if ($_REQUEST['return'] && mb_strpos($return, SELF_URL_PATH) === 0) { header("Location: " . clean($_REQUEST['return'])); } else { header("Location: " . get_self_url_prefix()); @@ -742,6 +745,7 @@ class Handler_Public extends Handler { header('Content-Type: text/html; charset=utf-8'); ?> + <!DOCTYPE html> <html> <head> <title>Tiny Tiny RSS</title> @@ -770,7 +774,21 @@ class Handler_Public extends Handler { <?php if (!$feed_url) { - print_error("No feed to subscribe to."); + ?> + <form method="post"> + <input type="hidden" name="op" value="subscribe"> + <fieldset> + <label>Feed or site URL:</label> + <input style="width: 300px" dojoType="dijit.form.ValidationTextBox" required="1" name="feed_url"> + </fieldset> + + <button class="alt-primary" dojoType="dijit.form.Button" type="submit"> + <?php echo __("Subscribe") ?> + </button> + + <a href="index.php"><?php echo __("Return to Tiny Tiny RSS") ?></a> + </form> + <?php } else { $rc = Feeds::subscribe_to_feed($feed_url); @@ -814,9 +832,11 @@ class Handler_Public extends Handler { } print "</select>"; - print "<button class='alt-primary' dojoType='dijit.form.Button' type='submit'>".__("Subscribe to selected feed")."</button>"; print "</fieldset>"; + print "<button class='alt-primary' dojoType='dijit.form.Button' type='submit'>".__("Subscribe to selected feed")."</button>"; + print "<a href='index.php'>".__("Return to Tiny Tiny RSS")."</a>"; + print "</form>"; } @@ -832,20 +852,18 @@ class Handler_Public extends Handler { } else { $feed_id = 0; } - print "<p>"; if ($feed_id) { - print "<form method='GET' style='float : left' action=\"$tp_uri\"> + print "<form method='GET' action=\"$tp_uri\"> <input type='hidden' name='tab' value='feedConfig'> <input type='hidden' name='method' value='editfeed'> <input type='hidden' name='methodparam' value='$feed_id'> <button dojoType='dijit.form.Button' class='alt-info' type='submit'>".__("Edit subscription options")."</button> + <a href='index.php'>".__("Return to Tiny Tiny RSS")."</a> </form>"; } } - print "<a href='index.php'>".__("Return to Tiny Tiny RSS")."</a>"; - print "</div></div></body></html>"; } else { @@ -866,7 +884,7 @@ class Handler_Public extends Handler { header('Content-Type: text/html; charset=utf-8'); ?> - + <!DOCTYPE html> <html> <head> <title>Tiny Tiny RSS</title> @@ -941,12 +959,12 @@ class Handler_Public extends Handler { print "<form method='POST' action='public.php'> <input type='hidden' name='method' value='do'> <input type='hidden' name='op' value='forgotpass'> - + <fieldset> <label>".__("Login:")."</label> <input dojoType='dijit.form.TextBox' type='text' name='login' value='' required> </fieldset> - + <fieldset> <label>".__("Email:")."</label> <input dojoType='dijit.form.TextBox' type='email' name='email' value='' required> @@ -959,13 +977,13 @@ class Handler_Public extends Handler { <label>".T_sprintf("How much is %d + %d:", $_SESSION["pwdreset:testvalue1"], $_SESSION["pwdreset:testvalue2"])."</label> <input dojoType='dijit.form.TextBox' type='text' name='test' value='' required> </fieldset> - + <hr/> <fieldset> <button dojoType='dijit.form.Button' type='submit' class='alt-danger'>".__("Reset password")."</button> <a href='index.php'>".__("Return to Tiny Tiny RSS")."</a> </fieldset> - + </form>"; } else if ($method == 'do') { @@ -1018,7 +1036,7 @@ class Handler_Public extends Handler { $mailer = new Mailer(); - $rc = $mailer->mail(["to_name" => $login, + $rc = $mailer->mail(["to_name" => $login, "to_address" => $email, "subject" => __("[tt-rss] Password reset request"), "message" => $message]); @@ -1033,8 +1051,6 @@ class Handler_Public extends Handler { $sth->execute([$resetpass_token_full, $login, $email]); - //Pref_Users::resetUserPassword($id, false); - } else { print_error("User ID not found."); } @@ -1071,6 +1087,7 @@ class Handler_Public extends Handler { } ?> + <!DOCTYPE html> <html> <head> <title>Database Updater</title> @@ -1116,32 +1133,35 @@ class Handler_Public extends Handler { if ($op == "performupdate") { if ($updater->isUpdateRequired()) { - print "<h2>" . __("Performing updates") . "</h2>"; - - print "<h3>" . T_sprintf("Updating to schema version %d", SCHEMA_VERSION) . "</h3>"; - - print "<ul>"; + print "<h2>" . T_sprintf("Performing updates to version %d", SCHEMA_VERSION) . "</h2>"; for ($i = $updater->getSchemaVersion() + 1; $i <= SCHEMA_VERSION; $i++) { - print "<li>" . T_sprintf("Performing update up to version %d...", $i); + print "<ul>"; + + print "<li class='text-info'>" . T_sprintf("Updating to version %d", $i) . "</li>"; + print "<li>"; $result = $updater->performUpdateTo($i, true); + print "</li>"; if (!$result) { - print "<span class='err'>".__("FAILED!")."</span></li></ul>"; + print "</ul>"; - print_warning("One of the updates failed. Either retry the process or perform updates manually."); + print_error("One of the updates failed. Either retry the process or perform updates manually."); - print "<a href='index.php'>".__("Return to Tiny Tiny RSS")."</a>"; + print "<form method='POST'> + <input type='hidden' name='subop' value='performupdate'> + <button type='submit' dojoType='dijit.form.Button' class='alt-danger' onclick='return confirmOP()'>".__("Try again")."</button> + <a href='index.php'>".__("Return to Tiny Tiny RSS")."</a> + </form>"; return; } else { - print "<span class='ok'>".__("OK!")."</span></li>"; + print "<li class='text-success'>" . __("Completed.") . "</li>"; + print "</ul>"; } } - print "</ul>"; - print_notice("Your Tiny Tiny RSS database is now updated to the latest version."); print "<a href='index.php'>".__("Return to Tiny Tiny RSS")."</a>"; @@ -1154,14 +1174,15 @@ class Handler_Public extends Handler { } else { if ($updater->isUpdateRequired()) { - print "<h2>" . __("Database update required") . "</h2>"; - - print_notice("<h4>". - sprintf("Your Tiny Tiny RSS database needs update to the latest version: %d to %d.", - $updater->getSchemaVersion(), SCHEMA_VERSION). - "</h4>"); + print "<h2>".T_sprintf("Tiny Tiny RSS database needs update to the latest version (%d to %d).", + $updater->getSchemaVersion(), SCHEMA_VERSION)."</h2>"; - print_warning("Please backup your database before proceeding."); + if (DB_TYPE == "mysql") { + print_error("<strong>READ THIS:</strong> Due to MySQL limitations, your database is not completely protected while updating. ". + "Errors may put it in an inconsistent state requiring manual rollback. <strong>BACKUP YOUR DATABASE BEFORE CONTINUING.</strong>"); + } else { + print_warning("Please backup your database before proceeding."); + } print "<form method='POST'> <input type='hidden' name='subop' value='performupdate'> diff --git a/classes/logger/sql.php b/classes/logger/sql.php index 73552c143..a2f4cd32c 100755 --- a/classes/logger/sql.php +++ b/classes/logger/sql.php @@ -12,6 +12,9 @@ class Logger_SQL { $owner_uid = $_SESSION["uid"] ? $_SESSION["uid"] : null; + if (DB_TYPE == "mysql") + $context = substr($context, 0, 65534); + $sth = $this->pdo->prepare("INSERT INTO ttrss_error_log (errno, errstr, filename, lineno, context, owner_uid, created_at) VALUES (?, ?, ?, ?, ?, ?, NOW())"); diff --git a/classes/mailer.php b/classes/mailer.php index fbdf111a7..eea9f5ff6 100644 --- a/classes/mailer.php +++ b/classes/mailer.php @@ -19,7 +19,8 @@ class Mailer { $from_combined = $from_name ? "$from_name <$from_address>" : $from_address; $to_combined = $to_name ? "$to_name <$to_address>" : $to_address; - Logger::get()->log("Sending mail from $from_combined to $to_combined <$to_address> [$subject]: $message"); + if (defined('_LOG_SENT_MAIL') && _LOG_SENT_MAIL) + Logger::get()->log("Sending mail from $from_combined to $to_combined <$to_address> [$subject]: $message"); // HOOK_SEND_MAIL plugin instructions: // 1. return 1 or true if mail is handled diff --git a/classes/opml.php b/classes/opml.php index fe43a096c..720798065 100644 --- a/classes/opml.php +++ b/classes/opml.php @@ -9,10 +9,10 @@ class Opml extends Handler_Protected { function export() { $output_name = "tt-rss_".date("Y-m-d").".opml"; - $show_settings = $_REQUEST["include_settings"]; + $include_settings = $_REQUEST["include_settings"] == "1"; $owner_uid = $_SESSION["uid"]; - $rc = $this->opml_export($output_name, $owner_uid, false, ($show_settings == 1)); + $rc = $this->opml_export($output_name, $owner_uid, false, $include_settings); return $rc; } @@ -48,7 +48,7 @@ class Opml extends Handler_Protected { // Export - private function opml_export_category($owner_uid, $cat_id, $hide_private_feeds=false) { + private function opml_export_category($owner_uid, $cat_id, $hide_private_feeds = false, $include_settings = true) { $cat_id = (int) $cat_id; @@ -59,15 +59,25 @@ class Opml extends Handler_Protected { $out = ""; + $ttrss_specific_qpart = ""; + if ($cat_id) { - $sth = $this->pdo->prepare("SELECT title FROM ttrss_feed_categories WHERE id = ? - AND owner_uid = ?"); + $sth = $this->pdo->prepare("SELECT title,order_id + FROM ttrss_feed_categories WHERE id = ? + AND owner_uid = ?"); $sth->execute([$cat_id, $owner_uid]); $row = $sth->fetch(); $cat_title = htmlspecialchars($row['title']); + + if ($include_settings) { + $order_id = (int)$row["order_id"]; + $ttrss_specific_qpart = "ttrssSortOrder=\"$order_id\""; + } + } else { + $cat_title = ""; } - if ($cat_title) $out .= "<outline text=\"$cat_title\">\n"; + if ($cat_title) $out .= "<outline text=\"$cat_title\" $ttrss_specific_qpart>\n"; $sth = $this->pdo->prepare("SELECT id,title FROM ttrss_feed_categories WHERE @@ -77,10 +87,10 @@ class Opml extends Handler_Protected { $sth->execute([':cat' => $cat_id, ':uid' => $owner_uid]); while ($line = $sth->fetch()) { - $out .= $this->opml_export_category($owner_uid, $line["id"], $hide_private_feeds); + $out .= $this->opml_export_category($owner_uid, $line["id"], $hide_private_feeds, $include_settings); } - $fsth = $this->pdo->prepare("select title, feed_url, site_url + $fsth = $this->pdo->prepare("select title, feed_url, site_url, update_interval, order_id FROM ttrss_feeds WHERE (cat_id = :cat OR (:cat = 0 AND cat_id IS NULL)) AND owner_uid = :uid AND $hide_qpart ORDER BY order_id, title"); @@ -92,13 +102,22 @@ class Opml extends Handler_Protected { $url = htmlspecialchars($fline["feed_url"]); $site_url = htmlspecialchars($fline["site_url"]); + if ($include_settings) { + $update_interval = (int)$fline["update_interval"]; + $order_id = (int)$fline["order_id"]; + + $ttrss_specific_qpart = "ttrssSortOrder=\"$order_id\" ttrssUpdateInterval=\"$update_interval\""; + } else { + $ttrss_specific_qpart = ""; + } + if ($site_url) { $html_url_qpart = "htmlUrl=\"$site_url\""; } else { $html_url_qpart = ""; } - $out .= "<outline type=\"rss\" text=\"$title\" xmlUrl=\"$url\" $html_url_qpart/>\n"; + $out .= "<outline type=\"rss\" text=\"$title\" xmlUrl=\"$url\" $ttrss_specific_qpart $html_url_qpart/>\n"; } if ($cat_title) $out .= "</outline>\n"; @@ -106,7 +125,7 @@ class Opml extends Handler_Protected { return $out; } - function opml_export($name, $owner_uid, $hide_private_feeds=false, $include_settings=true) { + function opml_export($name, $owner_uid, $hide_private_feeds = false, $include_settings = true) { if (!$owner_uid) return; if (!isset($_REQUEST["debug"])) { @@ -125,7 +144,7 @@ class Opml extends Handler_Protected { </head>"; $out .= "<body>"; - $out .= $this->opml_export_category($owner_uid, 0, $hide_private_feeds); + $out .= $this->opml_export_category($owner_uid, 0, $hide_private_feeds, $include_settings); # export tt-rss settings @@ -176,7 +195,7 @@ class Opml extends Handler_Protected { WHERE filter_id = ?"); $tmph->execute([$line['id']]); - while ($tmp_line = $tmph->fetch()) { + while ($tmp_line = $tmph->fetch(PDO::FETCH_ASSOC)) { unset($tmp_line["id"]); unset($tmp_line["filter_id"]); @@ -224,7 +243,7 @@ class Opml extends Handler_Protected { WHERE filter_id = ?"); $tmph->execute([$line['id']]); - while ($tmp_line = $tmph->fetch()) { + while ($tmp_line = $tmph->fetch(PDO::FETCH_ASSOC)) { unset($tmp_line["id"]); unset($tmp_line["filter_id"]); @@ -298,11 +317,17 @@ class Opml extends Handler_Protected { if (!$cat_id) $cat_id = null; + $update_interval = (int) $attrs->getNamedItem('ttrssUpdateInterval')->nodeValue; + if (!$update_interval) $update_interval = 0; + + $order_id = (int) $attrs->getNamedItem('ttrssSortOrder')->nodeValue; + if (!$order_id) $order_id = 0; + $sth = $this->pdo->prepare("INSERT INTO ttrss_feeds - (title, feed_url, owner_uid, cat_id, site_url, order_id) VALUES - (?, ?, ?, ?, ?, 0)"); + (title, feed_url, owner_uid, cat_id, site_url, order_id, update_interval) VALUES + (?, ?, ?, ?, ?, ?, ?)"); - $sth->execute([$feed_title, $feed_url, $owner_uid, $cat_id, $site_url]); + $sth->execute([$feed_title, $feed_url, $owner_uid, $cat_id, $site_url, $order_id, $update_interval]); } else { $this->opml_notice(T_sprintf("Duplicate feed: %s", $feed_title == '[Unknown]' ? $feed_url : $feed_title)); @@ -370,7 +395,7 @@ class Opml extends Handler_Protected { $filter_id = $row['id']; if ($filter_id) { - $this->opml_notice(T_sprintf("Adding filter...")); + $this->opml_notice(T_sprintf("Adding filter %s...", $title)); foreach ($filter["rules"] as $rule) { $feed_id = null; @@ -387,8 +412,6 @@ class Opml extends Handler_Protected { array_push($match_on, ($is_cat ? "CAT:" : "") . $name); } else { - $match_id = false; - if (!$is_cat) { $tsth = $this->pdo->prepare("SELECT id FROM ttrss_feeds WHERE title = ? AND owner_uid = ?"); @@ -397,6 +420,8 @@ class Opml extends Handler_Protected { if ($row = $tsth->fetch()) { $match_id = $row['id']; + + array_push($match_on, $match_id); } } else { $tsth = $this->pdo->prepare("SELECT id FROM ttrss_feed_categories @@ -405,10 +430,10 @@ class Opml extends Handler_Protected { if ($row = $tsth->fetch()) { $match_id = $row['id']; + + array_push($match_on, "CAT:$match_id"); } } - - if ($match_id) array_push($match_on, $match_id); } } @@ -487,7 +512,10 @@ class Opml extends Handler_Protected { $cat_id = $this->get_feed_category($cat_title, $parent_id); if ($cat_id === false) { - add_feed_category($cat_title, $parent_id); + $order_id = (int) $root_node->attributes->getNamedItem('ttrssSortOrder')->nodeValue; + if (!$order_id) $order_id = 0; + + add_feed_category($cat_title, $parent_id, $order_id); $cat_id = $this->get_feed_category($cat_title, $parent_id); } diff --git a/classes/plugin.php b/classes/plugin.php index b90c603b7..5ac4a6a9a 100644 --- a/classes/plugin.php +++ b/classes/plugin.php @@ -40,4 +40,21 @@ abstract class Plugin { function api_version() { return Plugin::API_VERSION_COMPAT; } -}
\ No newline at end of file + + /* gettext-related helpers */ + + function __($msgid) { + return _dgettext(PluginHost::object_to_domain($this), $msgid); + } + + function _ngettext($singular, $plural, $number) { + return _dngettext(PluginHost::object_to_domain($this), $singular, $plural, $number); + } + + function T_sprintf() { + $args = func_get_args(); + $msgid = array_shift($args); + + return vsprintf($this->__($msgid), $args); + } +} diff --git a/classes/pluginhost.php b/classes/pluginhost.php index 96b1ce499..f0dc0286c 100755 --- a/classes/pluginhost.php +++ b/classes/pluginhost.php @@ -63,6 +63,10 @@ class PluginHost { const KIND_SYSTEM = 2; const KIND_USER = 3; + static function object_to_domain($plugin) { + return strtolower(get_class($plugin)); + } + function __construct() { $this->pdo = Db::pdo(); @@ -211,6 +215,11 @@ class PluginHost { continue; } + if (file_exists(dirname($file) . "/locale")) { + _bindtextdomain($class, dirname($file) . "/locale"); + _bind_textdomain_codeset($class, "UTF-8"); + } + $this->last_registered = $class; switch ($kind) { diff --git a/classes/pref/feeds.php b/classes/pref/feeds.php index a033bf04f..f9ba853f8 100755 --- a/classes/pref/feeds.php +++ b/classes/pref/feeds.php @@ -502,7 +502,7 @@ class Pref_Feeds extends Handler_Protected { $rc = 2; } - @unlink($icon_file); + if (is_file($icon_file)) @unlink($icon_file); print "<script type=\"text/javascript\">"; print "parent.CommonDialogs.uploadIconHandler($rc);"; @@ -531,16 +531,16 @@ class Pref_Feeds extends Handler_Protected { print_hidden("op", "pref-feeds"); print_hidden("method", "editSave"); - print "<div class=\"dlgSec\">".__("Feed")."</div>"; - print "<div class=\"dlgSecCont\">"; + print "<header>".__("Feed")."</header>"; + print "<section>"; /* Title */ print "<fieldset>"; - print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\" + print "<input dojoType='dijit.form.ValidationTextBox' required='1' placeHolder=\"".__("Feed Title")."\" - style=\"font-size : 16px; width: 500px\" name=\"title\" value=\"$title\">"; + style='font-size : 16px; width: 500px' name='title' value=\"$title\">"; print "</fieldset>"; @@ -551,10 +551,10 @@ class Pref_Feeds extends Handler_Protected { print "<fieldset>"; print "<label>" . __('URL:') . "</label> "; - print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\" + print "<input dojoType='dijit.form.ValidationTextBox' required='1' placeHolder=\"".__("Feed URL")."\" - regExp='^(http|https)://.*' style=\"width : 300px\" - name=\"feed_url\" value=\"$feed_url\">"; + regExp='^(http|https)://.*' style='width : 300px' + name='feed_url' value=\"$feed_url\">"; $last_error = $row["last_error"]; @@ -588,10 +588,10 @@ class Pref_Feeds extends Handler_Protected { print "<fieldset>"; print "<label>" . __('Site URL:') . "</label> "; - print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\" + print "<input dojoType='dijit.form.ValidationTextBox' required='1' placeHolder=\"".__("Site URL")."\" - regExp='^(http|https)://.*' style=\"width : 300px\" - name=\"site_url\" value=\"$site_url\">"; + regExp='^(http|https)://.*' style='width : 300px' + name='site_url' value=\"$site_url\">"; print "</fieldset>"; @@ -609,10 +609,10 @@ class Pref_Feeds extends Handler_Protected { print "</fieldset>"; } - print "</div>"; + print "</section>"; - print "<div class=\"dlgSec\">".__("Update")."</div>"; - print "<div class=\"dlgSecCont\">"; + print "<header>".__("Update")."</header>"; + print "<section>"; /* Update Interval */ @@ -641,7 +641,7 @@ class Pref_Feeds extends Handler_Protected { print "</fieldset>"; - print "</div>"; + print "</section>"; $auth_login = htmlspecialchars($row["auth_login"]); $auth_pass = htmlspecialchars($row["auth_pass"]); @@ -650,58 +650,40 @@ class Pref_Feeds extends Handler_Protected { $auth_style = $auth_enabled ? '' : 'display: none'; print "<div id='feedEditDlg_loginContainer' style='$auth_style'>"; - print "<div class=\"dlgSec\">".__("Authentication")."</div>"; - print "<div class=\"dlgSecCont\">"; + print "<header>".__("Authentication")."</header>"; + print "<section>"; print "<fieldset>"; - print "<input dojoType=\"dijit.form.TextBox\" id=\"feedEditDlg_login\" - placeHolder=\"".__("Login")."\" - autocomplete=\"new-password\" - name=\"auth_login\" value=\"$auth_login\">"; + print "<input dojoType='dijit.form.TextBox' id='feedEditDlg_login' + placeHolder='".__("Login")."' + autocomplete='new-password' + name='auth_login' value=\"$auth_login\">"; - print "</fieldset>"; - print "<fieldset>"; + print "</fieldset><fieldset>"; - print "<input dojoType=\"dijit.form.TextBox\" type=\"password\" name=\"auth_pass\" - autocomplete=\"new-password\" - placeHolder=\"".__("Password")."\" + print "<input dojoType='dijit.form.TextBox' type='password' name='auth_pass' + autocomplete='new-password' + placeHolder='".__("Password")."' value=\"$auth_pass\">"; - print "<div dojoType=\"dijit.Tooltip\" connectId=\"feedEditDlg_login\" position=\"below\"> + print "<div dojoType='dijit.Tooltip' connectId='feedEditDlg_login' position='below'> ".__('<b>Hint:</b> you need to fill in your login information if your feed requires authentication, except for Twitter feeds.')." </div>"; print "</fieldset>"; - print "</div></div>"; + print "</section></div>"; $auth_checked = $auth_enabled ? 'checked' : ''; - print "<div style=\"clear : both\"> - <input type=\"checkbox\" $auth_checked name=\"need_auth\" dojoType=\"dijit.form.CheckBox\" id=\"feedEditDlg_loginCheck\" + print "<label class='checkbox'> + <input type='checkbox' $auth_checked name='need_auth' dojoType='dijit.form.CheckBox' id='feedEditDlg_loginCheck' onclick='displayIfChecked(this, \"feedEditDlg_loginContainer\")'> - <label for=\"feedEditDlg_loginCheck\">". - __('This feed requires authentication.')."</div>"; + ".__('This feed requires authentication.')."</label>"; print '</div><div dojoType="dijit.layout.ContentPane" title="'.__('Options').'">'; - //print "<div class=\"dlgSec\">".__("Options")."</div>"; - print "<div class=\"dlgSecSimple\">"; - - $private = $row["private"]; - - if ($private) { - $checked = "checked=\"1\""; - } else { - $checked = ""; - } - - print "<fieldset class='narrow'>"; - - print "<label class='checkbox'><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"private\" id=\"private\" - $checked> ".__('Hide from Popular feeds')."</label>"; - - print "</fieldset>"; + print "<section class='narrow'>"; $include_in_digest = $row["include_in_digest"]; @@ -745,9 +727,8 @@ class Pref_Feeds extends Handler_Protected { print "<fieldset class='narrow'>"; - print "<label class='checkbox'><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"hide_images\" - name=\"hide_images\" - $checked> ".__('Do not embed media')."</label>"; + print "<label class='checkbox'><input dojoType='dijit.form.CheckBox' type='checkbox' id='hide_images' + name='hide_images' $checked> ".__('Do not embed media')."</label>"; print "</fieldset>"; @@ -761,9 +742,8 @@ class Pref_Feeds extends Handler_Protected { print "<fieldset class='narrow'>"; - print "<label class='checkbox'><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"cache_images\" - name=\"cache_images\" - $checked> ". __('Cache media')."</label>"; + print "<label class='checkbox'><input dojoType='dijit.form.CheckBox' type='checkbox' id='cache_images' + name='cache_images' $checked> ". __('Cache media')."</label>"; print "</fieldset>"; @@ -777,41 +757,36 @@ class Pref_Feeds extends Handler_Protected { print "<fieldset class='narrow'>"; - print "<label class='checkbox'><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"mark_unread_on_update\" - name=\"mark_unread_on_update\" - $checked> ".__('Mark updated articles as unread')."</label>"; + print "<label class='checkbox'><input dojoType='dijit.form.CheckBox' type='checkbox' id='mark_unread_on_update' + name='mark_unread_on_update' $checked> ".__('Mark updated articles as unread')."</label>"; print "</fieldset>"; - print "</div>"; - print '</div><div dojoType="dijit.layout.ContentPane" title="'.__('Icon').'">'; /* Icon */ - print "<div class=\"dlgSecSimple\">"; - - print "<img class=\"feedIcon\" src=\"".Feeds::getFeedIcon($feed_id)."\">"; + print "<img class='feedIcon' src=\"".Feeds::getFeedIcon($feed_id)."\">"; - print "<iframe name=\"icon_upload_iframe\" - style=\"width: 400px; height: 100px; display: none;\"></iframe>"; + print "<iframe name='icon_upload_iframe' + style='width: 400px; height: 100px; display: none;'></iframe>"; - print "<form style='display : block' target=\"icon_upload_iframe\" - enctype=\"multipart/form-data\" method=\"POST\" - action=\"backend.php\"> - <label class=\"dijitButton\">".__("Choose file...")." - <input style=\"display: none\" id=\"icon_file\" size=\"10\" name=\"icon_file\" type=\"file\"> + print "<form style='display : block' target='icon_upload_iframe' + enctype='multipart/form-data' method='POST' + action='backend.php'> + <label class='dijitButton'>".__("Choose file...")." + <input style='display: none' id='icon_file' size='10' name='icon_file' type='file'> </label> - <input type=\"hidden\" name=\"op\" value=\"pref-feeds\"> - <input type=\"hidden\" name=\"feed_id\" value=\"$feed_id\"> - <input type=\"hidden\" name=\"method\" value=\"uploadicon\"> - <button class=\"\" dojoType=\"dijit.form.Button\" onclick=\"return CommonDialogs.uploadFeedIcon();\" - type=\"submit\">".__('Replace')."</button> - <button class=\"alt-danger\" dojoType=\"dijit.form.Button\" onclick=\"return CommonDialogs.removeFeedIcon($feed_id);\" - type=\"submit\">".__('Remove')."</button> + <input type='hidden' name='op' value='pref-feeds'> + <input type='hidden' name='feed_id' value=\"$feed_id\"> + <input type='hidden' name='method' value=\"uploadicon\"> + <button dojoType='dijit.form.Button' onclick=\"return CommonDialogs.uploadFeedIcon();\" + type='submit'>".__('Replace')."</button> + <button class='alt-danger' dojoType='dijit.form.Button' onclick=\"return CommonDialogs.removeFeedIcon($feed_id);\" + type='submit'>".__('Remove')."</button> </form>"; - print "</div>"; + print "</section>"; print '</div><div dojoType="dijit.layout.ContentPane" title="'.__('Plugins').'">'; @@ -822,16 +797,12 @@ class Pref_Feeds extends Handler_Protected { $title = htmlspecialchars($title, ENT_QUOTES); - print "<div class='dlgButtons'> - <div style=\"float : left\"> - <button class=\"alt-danger\" dojoType=\"dijit.form.Button\" onclick='return CommonDialogs.unsubscribeFeed($feed_id, \"$title\")'>". - __('Unsubscribe')."</button>"; - - print "</div>"; - - print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedEditDlg').execute()\">".__('Save')."</button> - <button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedEditDlg').hide()\">".__('Cancel')."</button> - </div>"; + print "<footer> + <button style='float : left' class='alt-danger' dojoType='dijit.form.Button' onclick='return CommonDialogs.unsubscribeFeed($feed_id, \"$title\")'>". + __('Unsubscribe')."</button> + <button dojoType='dijit.form.Button' class='alt-primary' onclick=\"return dijit.byId('feedEditDlg').execute()\">".__('Save')."</button> + <button dojoType='dijit.form.Button' onclick=\"return dijit.byId('feedEditDlg').hide()\">".__('Cancel')."</button> + </footer>"; } } @@ -849,8 +820,8 @@ class Pref_Feeds extends Handler_Protected { print_hidden("op", "pref-feeds"); print_hidden("method", "batchEditSave"); - print "<div class=\"dlgSec\">".__("Feed")."</div>"; - print "<div class=\"dlgSecCont\">"; + print "<header>".__("Feed")."</header>"; + print "<section>"; /* Category */ @@ -882,10 +853,10 @@ class Pref_Feeds extends Handler_Protected { print "</fieldset>"; } - print "</div>"; + print "</section>"; - print "<div class=\"dlgSec\">".__("Update")."</div>"; - print "<div class=\"dlgSecCont\">"; + print "<header>".__("Update")."</header>"; + print "<section>"; /* Update Interval */ @@ -916,93 +887,78 @@ class Pref_Feeds extends Handler_Protected { print "</fieldset>"; } - print "</div>"; - print "<div class=\"dlgSec\">".__("Authentication")."</div>"; - print "<div class=\"dlgSecCont\">"; + print "</section>"; + print "<header>".__("Authentication")."</header>"; + print "<section>"; print "<fieldset>"; - print "<input dojoType=\"dijit.form.TextBox\" - placeHolder=\"".__("Login")."\" disabled=\"1\" - autocomplete=\"new-password\" - name=\"auth_login\" value=\"\">"; + print "<input dojoType='dijit.form.TextBox' + placeHolder=\"".__("Login")."\" disabled='1' + autocomplete='new-password' + name='auth_login' value=''>"; $this->batch_edit_cbox("auth_login"); - print "</fieldset>"; - print "<fieldset>"; - - print "<input dojoType=\"dijit.form.TextBox\" type=\"password\" name=\"auth_pass\" - autocomplete=\"new-password\" - placeHolder=\"".__("Password")."\" disabled=\"1\" - value=\"\">"; + print "<input dojoType='dijit.form.TextBox' type='password' name='auth_pass' + autocomplete='new-password' + placeHolder=\"".__("Password")."\" disabled='1' + value=''>"; $this->batch_edit_cbox("auth_pass"); print "</fieldset>"; - print "</div>"; - print "<div class=\"dlgSec\">".__("Options")."</div>"; - print "<div class=\"dlgSecCont\">"; + print "</section>"; + print "<header>".__("Options")."</header>"; + print "<section>"; print "<fieldset class='narrow'>"; - print "<label class='checkbox'><input disabled=\"1\" type=\"checkbox\" name=\"private\" id=\"private\" - dojoType=\"dijit.form.CheckBox\"> ".__('Hide from Popular feeds')."</label>"; - - print " "; $this->batch_edit_cbox("private", "private_l"); - - print "</fieldset><fieldset class='narrow'>"; - - print "<label class='checkbox'><input disabled=\"1\" type=\"checkbox\" id=\"include_in_digest\" - name=\"include_in_digest\" - dojoType=\"dijit.form.CheckBox\"> ".__('Include in e-mail digest')."</label>"; + print "<label class='checkbox'><input disabled='1' type='checkbox' id='include_in_digest' + name='include_in_digest' dojoType='dijit.form.CheckBox'> ".__('Include in e-mail digest')."</label>"; print " "; $this->batch_edit_cbox("include_in_digest", "include_in_digest_l"); print "</fieldset><fieldset class='narrow'>"; - print "<label class='checkbox'><input disabled=\"1\" type=\"checkbox\" id=\"always_display_enclosures\" - name=\"always_display_enclosures\" - dojoType=\"dijit.form.CheckBox\"> ".__('Always display image attachments')."</label>"; + print "<label class='checkbox'><input disabled='1' type='checkbox' id='always_display_enclosures' + name='always_display_enclosures' dojoType='dijit.form.CheckBox'> ".__('Always display image attachments')."</label>"; print " "; $this->batch_edit_cbox("always_display_enclosures", "always_display_enclosures_l"); print "</fieldset><fieldset class='narrow'>"; - print "<label class='checkbox'><input disabled=\"1\" type=\"checkbox\" id=\"hide_images\" - name=\"hide_images\" - dojoType=\"dijit.form.CheckBox\"> ". __('Do not embed media')."</label>"; + print "<label class='checkbox'><input disabled='1' type='checkbox' id='hide_images' + name='hide_images' dojoType='dijit.form.CheckBox'> ". __('Do not embed media')."</label>"; print " "; $this->batch_edit_cbox("hide_images", "hide_images_l"); print "</fieldset><fieldset class='narrow'>"; - print "<label class='checkbox'><input disabled=\"1\" type=\"checkbox\" id=\"cache_images\" - name=\"cache_images\" - dojoType=\"dijit.form.CheckBox\"> ".__('Cache media')."</label>"; + print "<label class='checkbox'><input disabled='1' type='checkbox' id='cache_images' + name='cache_images' dojoType='dijit.form.CheckBox'> ".__('Cache media')."</label>"; print " "; $this->batch_edit_cbox("cache_images", "cache_images_l"); print "</fieldset><fieldset class='narrow'>"; - print "<label class='checkbox'><input disabled=\"1\" type=\"checkbox\" id=\"mark_unread_on_update\" - name=\"mark_unread_on_update\" - dojoType=\"dijit.form.CheckBox\"> ".__('Mark updated articles as unread')."</label>"; + print "<label class='checkbox'><input disabled='1' type='checkbox' id='mark_unread_on_update' + name='mark_unread_on_update' dojoType='dijit.form.CheckBox'> ".__('Mark updated articles as unread')."</label>"; print " "; $this->batch_edit_cbox("mark_unread_on_update", "mark_unread_on_update_l"); print "</fieldset>"; - print "</div>"; + print "</section>"; - print "<div class='dlgButtons'> - <button dojoType=\"dijit.form.Button\" type='submit' class='alt-primary' + print "<footer> + <button dojoType='dijit.form.Button' type='submit' class='alt-primary' onclick=\"return dijit.byId('feedEditDlg').execute()\">". __('Save')."</button> - <button dojoType=\"dijit.form.Button\" + <button dojoType='dijit.form.Button' onclick=\"return dijit.byId('feedEditDlg').hide()\">". __('Cancel')."</button> - </div>"; + </footer>"; return; } @@ -1499,16 +1455,14 @@ class Pref_Feeds extends Handler_Protected { ORDER BY last_article"); $sth->execute([$_SESSION['uid']]); - print "<p" .__("These feeds have not been updated with new content for 3 months (oldest first):") . "</p>"; - - print "<div dojoType=\"dijit.Toolbar\">"; - print "<div dojoType=\"dijit.form.DropDownButton\">". + print "<div dojoType='dijit.Toolbar'>"; + print "<div dojoType='dijit.form.DropDownButton'>". "<span>" . __('Select')."</span>"; - print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">"; + print "<div dojoType='dijit.Menu' style='display: none'>"; print "<div onclick=\"Tables.select('inactive-feeds-list', true)\" - dojoType=\"dijit.MenuItem\">".__('All')."</div>"; + dojoType='dijit.MenuItem'>".__('All')."</div>"; print "<div onclick=\"Tables.select('inactive-feeds-list', false)\" - dojoType=\"dijit.MenuItem\">".__('None')."</div>"; + dojoType='dijit.MenuItem'>".__('None')."</div>"; print "</div></div>"; print "</div>"; #toolbar @@ -1524,16 +1478,16 @@ class Pref_Feeds extends Handler_Protected { print "<tr data-row-id='$feed_id'>"; print "<td width='5%' align='center'><input - onclick='Tables.onRowChecked(this);' dojoType=\"dijit.form.CheckBox\" - type=\"checkbox\"></td>"; + onclick='Tables.onRowChecked(this);' dojoType='dijit.form.CheckBox' + type='checkbox'></td>"; print "<td>"; - print "<a class=\"visibleLink\" href=\"#\" ". + print "<a href='#' ". "title=\"".__("Click to edit feed")."\" ". "onclick=\"CommonDialogs.editFeed(".$line["id"].")\">". htmlspecialchars($line["title"])."</a>"; - print "</td><td class=\"insensitive\" align='right'>"; + print "</td><td class='insensitive' align='right'>"; print make_local_datetime($line['last_article'], false); print "</td>"; print "</tr>"; @@ -1544,16 +1498,12 @@ class Pref_Feeds extends Handler_Protected { print "</table>"; print "</div>"; - print "<div class='dlgButtons'>"; - print "<div style='float : left'>"; - print "<button class=\"alt-danger\" dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('inactiveFeedsDlg').removeSelected()\">" - .__('Unsubscribe from selected feeds')."</button> "; - print "</div>"; - - print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('inactiveFeedsDlg').hide()\">". - __('Close this window')."</button>"; - - print "</div>"; + print "<footer> + <button style='float : left' class=\"alt-danger\" dojoType='dijit.form.Button' onclick=\"dijit.byId('inactiveFeedsDlg').removeSelected()\">" + .__('Unsubscribe from selected feeds')."</button> + <button dojoType='dijit.form.Button' onclick=\"dijit.byId('inactiveFeedsDlg').hide()\">" + .__('Close this window')."</button> + </footer>"; } @@ -1607,16 +1557,14 @@ class Pref_Feeds extends Handler_Protected { print "</table>"; print "</div>"; - print "<div class='dlgButtons'>"; - print "<div style='float : left'>"; - print "<button class=\"alt-danger\" dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('errorFeedsDlg').removeSelected()\">" + print "<footer>"; + print "<button style='float : left' class=\"alt-danger\" dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('errorFeedsDlg').removeSelected()\">" .__('Unsubscribe from selected feeds')."</button> "; - print "</div>"; print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('errorFeedsDlg').hide()\">". __('Close this window')."</button>"; - print "</div>"; + print "</footer>"; } private function remove_feed_category($id, $owner_uid) { @@ -1665,8 +1613,8 @@ class Pref_Feeds extends Handler_Protected { $new_feed_id = (int)$row['id'] + 1; $sth = $pdo->prepare("INSERT INTO ttrss_archived_feeds - (id, owner_uid, title, feed_url, site_url) - SELECT ?, owner_uid, title, feed_url, site_url from ttrss_feeds + (id, owner_uid, title, feed_url, site_url, created) + SELECT ?, owner_uid, title, feed_url, site_url, NOW() from ttrss_feeds WHERE id = ?"); $sth->execute([$new_feed_id, $id]); @@ -1710,9 +1658,8 @@ class Pref_Feeds extends Handler_Protected { print_hidden("op", "pref-feeds"); print_hidden("method", "batchaddfeeds"); - print "<div class='dlgSecHoriz'>".__("One valid feed per line (no detection is done)")."</div>"; - - print "<div class='dlgSecCont'>"; + print "<header class='horizontal'>".__("One valid feed per line (no detection is done)")."</header>"; + print "<section>"; print "<textarea style='font-size : 12px; width : 98%; height: 200px;' @@ -1725,16 +1672,18 @@ class Pref_Feeds extends Handler_Protected { print "</fieldset>"; } + print "</section>"; + print "<div id='feedDlg_loginContainer' style='display : none'>"; - print "<div class='dlgSec'>" . __("Authentication") . "</div>"; - print "<div class='dlgSecCont'>"; + print "<header>" . __("Authentication") . "</header>"; + print "<section>"; print "<input dojoType='dijit.form.TextBox' name='login' placeHolder=\"".__("Login")."\"> <input placeHolder=\"".__("Password")."\" dojoType=\"dijit.form.TextBox\" type='password' autocomplete='new-password' name='pass''></div>"; - print "</div>"; + print "</section>"; print "</div>"; print "<fieldset class='narrow'> @@ -1743,10 +1692,10 @@ class Pref_Feeds extends Handler_Protected { __('Feeds require authentication.')."</label></div>"; print "</fieldset>"; - print "<div class='dlgButtons'> + print "<footer> <button dojoType='dijit.form.Button' type='submit' class='alt-primary' onclick=\"return dijit.byId('batchSubDlg').execute()\">".__('Subscribe')."</button> <button dojoType='dijit.form.Button' onclick=\"return dijit.byId('batchSubDlg').hide()\">".__('Cancel')."</button> - </div>"; + </footer>"; } function batchAddFeeds() { diff --git a/classes/pref/filters.php b/classes/pref/filters.php index 99bb885cf..f5a580e78 100755 --- a/classes/pref/filters.php +++ b/classes/pref/filters.php @@ -170,10 +170,10 @@ class Pref_Filters extends Handler_Protected { print "<ul class='panel panel-scrollable list list-unstyled' id='prefFilterTestResultList'>"; print "</ul>"; - print "<div style='text-align : center'>"; - print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('filterTestDlg').hide()\">". + print "<footer class='text-center'>"; + print "<button dojoType='dijit.form.Button' onclick=\"dijit.byId('filterTestDlg').hide()\">". __('Close this window')."</button>"; - print "</div>"; + print "</footer>"; } @@ -346,15 +346,13 @@ class Pref_Filters extends Handler_Protected { print_hidden("method", "editSave"); print_hidden("csrf_token", $_SESSION['csrf_token']); - print "<div class='dlgSec'>".__("Caption")."</div>"; - print "<div class='dlgSecCont'>"; - + print "<header>".__("Caption")."</header>"; + print "<section>"; print "<input required=\"true\" dojoType=\"dijit.form.ValidationTextBox\" style=\"width : 20em;\" name=\"title\" value=\"$title\">"; + print "</section>"; - print "</div>"; - - print "<div class='dlgSecHoriz'>".__("Match")."</div>"; - print "<div class='dlgSecCont'>"; + print "<header class='horizontal'>".__("Match")."</header>"; + print "<section>"; print "<div dojoType=\"dijit.Toolbar\">"; @@ -410,11 +408,11 @@ class Pref_Filters extends Handler_Protected { print "</ul>"; - print "</div>"; + print "</section>"; - print "<div class='dlgSecHoriz'>".__("Apply actions")."</div>"; + print "<header class='horizontal'>".__("Apply actions")."</header>"; - print "<div class='dlgSecCont'>"; + print "<section>"; print "<div dojoType=\"dijit.Toolbar\">"; @@ -456,10 +454,10 @@ class Pref_Filters extends Handler_Protected { print "</ul>"; - print "</div>"; + print "</section>"; - print "<div class='dlgSec'>".__("Options")."</div>"; - print "<div class='dlgSecCont'>"; + print "<header>".__("Options")."</header>"; + print "<section>"; if ($enabled) { $checked = "checked=\"1\""; @@ -495,9 +493,9 @@ class Pref_Filters extends Handler_Protected { print "</fieldset>"; - print "</div>"; + print "</section>"; - print "<div class=\"dlgButtons\">"; + print "<footer>"; print "<div style=\"float : left\">"; print "<button dojoType=\"dijit.form.Button\" class=\"alt-danger\" onclick=\"return dijit.byId('filterEditDlg').removeFilter()\">". @@ -513,7 +511,7 @@ class Pref_Filters extends Handler_Protected { print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').hide()\">". __('Cancel')."</button>"; - print "</div>"; + print "</footer>"; print "</form>"; } @@ -849,31 +847,30 @@ class Pref_Filters extends Handler_Protected { print_hidden("method", "add"); print_hidden("csrf_token", $_SESSION['csrf_token']); - print "<div class='dlgSec'>".__("Caption")."</div>"; - - print "<div class='dlgSecCont'>"; - print "<input required=\"true\" dojoType=\"dijit.form.ValidationTextBox\" style=\"width : 20em;\" name=\"title\" value=\"\">"; - print "</div>"; + print "<header>".__("Caption")."</header>"; - print "<div class='dlgSecHoriz'>".__("Match")."</div>"; + print "<section>"; + print "<input required='true' dojoType='dijit.form.ValidationTextBox' style='width : 20em;' name='title' value=''>"; + print "</section>"; - print "<div class='dlgSecCont'>"; + print "<header class='horizontal'>".__("Match")."</header >"; + print "<section>"; - print "<div dojoType=\"dijit.Toolbar\">"; + print "<div dojoType='dijit.Toolbar'>"; - print "<div dojoType=\"dijit.form.DropDownButton\">". + print "<div dojoType='dijit.form.DropDownButton'>". "<span>" . __('Select')."</span>"; - print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">"; + print "<div dojoType='dijit.Menu' style='display: none'>"; print "<div onclick=\"dijit.byId('filterEditDlg').selectRules(true)\" - dojoType=\"dijit.MenuItem\">".__('All')."</div>"; + dojoType='dijit.MenuItem'>".__('All')."</div>"; print "<div onclick=\"dijit.byId('filterEditDlg').selectRules(false)\" - dojoType=\"dijit.MenuItem\">".__('None')."</div>"; + dojoType='dijit.MenuItem'>".__('None')."</div>"; print "</div></div>"; - print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').addRule()\">". + print "<button dojoType='dijit.form.Button' onclick=\"return dijit.byId('filterEditDlg').addRule()\">". __('Add')."</button> "; - print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').deleteRule()\">". + print "<button dojoType='dijit.form.Button' onclick=\"return dijit.byId('filterEditDlg').deleteRule()\">". __('Delete')."</button> "; print "</div>"; @@ -882,74 +879,69 @@ class Pref_Filters extends Handler_Protected { # print "<li>No rules</li>"; print "</ul>"; - print "</div>"; - print "</div>"; + print "</section>"; - print "<div class='dlgSecHoriz'>".__("Apply actions")."</div>"; + print "<header class='horizontal'>".__("Apply actions")."</header>"; - print "<div class='dlgSecCont'>"; + print "<section>"; - print "<div dojoType=\"dijit.Toolbar\">"; + print "<div dojoType='dijit.Toolbar'>"; - print "<div dojoType=\"dijit.form.DropDownButton\">". + print "<div dojoType='dijit.form.DropDownButton'>". "<span>" . __('Select')."</span>"; - print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">"; + print "<div dojoType='dijit.Menu' style='display: none'>"; print "<div onclick=\"dijit.byId('filterEditDlg').selectActions(true)\" - dojoType=\"dijit.MenuItem\">".__('All')."</div>"; + dojoType='dijit.MenuItem'>".__('All')."</div>"; print "<div onclick=\"dijit.byId('filterEditDlg').selectActions(false)\" - dojoType=\"dijit.MenuItem\">".__('None')."</div>"; + dojoType='dijit.MenuItem'>".__('None')."</div>"; print "</div></div>"; - print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').addAction()\">". + print "<button dojoType='dijit.form.Button' onclick=\"return dijit.byId('filterEditDlg').addAction()\">". __('Add')."</button> "; - print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').deleteAction()\">". + print "<button dojoType='dijit.form.Button' onclick=\"return dijit.byId('filterEditDlg').deleteAction()\">". __('Delete')."</button> "; print "</div>"; - print "<ul id='filterDlg_Actions'>"; # print "<li>No actions</li>"; print "</ul>"; - print "</div>"; - print "<div class='dlgSec'>".__("Options")."</div>"; + print "</section>"; + + print "<header>".__("Options")."</header>"; - print "<div class='dlgSecCont'>"; + print "<section>"; print "<fieldset class='narrow'>"; - print "<label class='checkbox'><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"enabled\" id=\"enabled\" checked=\"1\"> + print "<label class='checkbox'><input dojoType='dijit.form.CheckBox' type='checkbox' name='enabled' id='enabled' checked='1'> ".__('Enabled')."</label>"; print "</fieldset><fieldset class='narrow'>"; - print "<label class='checkbox'><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"match_any_rule\" id=\"match_any_rule\"> + print "<label class='checkbox'><input dojoType='dijit.form.CheckBox' type='checkbox' name='match_any_rule' id='match_any_rule'> ".__('Match any rule')."</label>"; print "</fieldset><fieldset class='narrow'>"; - print "<label class='checkbox'><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"inverse\" id=\"inverse\"> + print "<label class='checkbox'><input dojoType='dijit.form.CheckBox' type='checkbox' name='inverse' id='inverse'> ".__('Inverse matching')."</label>"; print "</fieldset>"; - print "</div>"; - -// print "</div>"; + print "</section>"; - print "<div class=\"dlgButtons\">"; + print "<footer>"; - print "<button dojoType=\"dijit.form.Button\" class=\"alt-info\" onclick=\"return dijit.byId('filterEditDlg').test()\">". + print "<button dojoType='dijit.form.Button' class='alt-info' onclick=\"return dijit.byId('filterEditDlg').test()\">". __('Test')."</button> "; - - print "<button dojoType=\"dijit.form.Button\" type=\"submit\" class=\"alt-primary\" onclick=\"return dijit.byId('filterEditDlg').execute()\">". + print "<button dojoType='dijit.form.Button' type='submit' class='alt-primary' onclick=\"return dijit.byId('filterEditDlg').execute()\">". __('Create')."</button> "; - - print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterEditDlg').hide()\">". + print "<button dojoType='dijit.form.Button' onclick=\"return dijit.byId('filterEditDlg').hide()\">". __('Cancel')."</button>"; - print "</div>"; + print "</footer>"; } @@ -979,9 +971,9 @@ class Pref_Filters extends Handler_Protected { $filter_types[$line["id"]] = __($line["description"]); } - print "<div class=\"dlgSec\">".__("Match")."</div>"; + print "<header>".__("Match")."</header>"; - print "<div class=\"dlgSecCont\">"; + print "<section>"; print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"true\" id=\"filterDlg_regExp\" @@ -1015,9 +1007,9 @@ class Pref_Filters extends Handler_Protected { print "</fieldset>"; - print "</div>"; + print "</section>"; - print "<div class='dlgButtons'>"; + print "<footer>"; print "<button dojoType='dijit.form.Button' style='float : left' class='alt-info' onclick='window.open(\"https://tt-rss.org/wiki/ContentFilters\")'> <i class='material-icons'>help</i> ".__("More info...")."</button>"; @@ -1028,7 +1020,7 @@ class Pref_Filters extends Handler_Protected { print "<button dojoType='dijit.form.Button' onclick=\"return dijit.byId('filterNewRuleDlg').hide()\">". __('Cancel')."</button>"; - print "</div>"; + print "</footer>"; print "</form>"; } @@ -1046,12 +1038,12 @@ class Pref_Filters extends Handler_Protected { print "<form name='filter_new_action_form' id='filter_new_action_form' onsubmit='return false;'>"; - print "<div class=\"dlgSec\">".__("Perform Action")."</div>"; + print "<header>".__("Perform Action")."</header>"; - print "<div class=\"dlgSecCont\">"; + print "<section>"; - print "<select name=\"action_id\" dojoType=\"dijit.form.Select\" - onchange=\"Filters.filterDlgCheckAction(this)\">"; + print "<select name='action_id' dojoType='dijit.form.Select' + onchange='Filters.filterDlgCheckAction(this)'>"; $res = $this->pdo->query("SELECT id,description FROM ttrss_filter_actions ORDER BY name"); @@ -1072,16 +1064,16 @@ class Pref_Filters extends Handler_Protected { $label_param_hidden = ($action_id == 7) ? "" : "display : none"; $plugin_param_hidden = ($action_id == 9) ? "" : "display : none"; - print "<span id=\"filterDlg_paramBox\" style=\"$param_box_hidden\">"; + print "<span id='filterDlg_paramBox' style=\"$param_box_hidden\">"; print " "; //print " " . __("with parameters:") . " "; - print "<input dojoType=\"dijit.form.TextBox\" - id=\"filterDlg_actionParam\" style=\"$param_hidden\" - name=\"action_param\" value=\"$action_param\">"; + print "<input dojoType='dijit.form.TextBox' + id='filterDlg_actionParam' style=\"$param_hidden\" + name='action_param' value=\"$action_param\">"; print_label_select("action_param_label", $action_param, - "id=\"filterDlg_actionParamLabel\" style=\"$label_param_hidden\" - dojoType=\"dijit.form.Select\""); + "id='filterDlg_actionParamLabel' style=\"$label_param_hidden\" + dojoType='dijit.form.Select'"); $filter_actions = PluginHost::getInstance()->get_filter_actions(); $filter_action_hash = array(); @@ -1104,24 +1096,24 @@ class Pref_Filters extends Handler_Protected { } print_select_hash("filterDlg_actionParamPlugin", $action_param, $filter_action_hash, - "style=\"$plugin_param_hidden\" dojoType=\"dijit.form.Select\" $filter_plugin_disabled", + "style=\"$plugin_param_hidden\" dojoType='dijit.form.Select' $filter_plugin_disabled", "action_param_plugin"); print "</span>"; print " "; // tiny layout hack - print "</div>"; + print "</section>"; - print "<div class=\"dlgButtons\">"; + print "<footer>"; - print "<button dojoType=\"dijit.form.Button\" class=\"alt-primary\" type=\"submit\" onclick=\"return dijit.byId('filterNewActionDlg').execute()\">". + print "<button dojoType='dijit.form.Button' class='alt-primary' type='submit' onclick=\"return dijit.byId('filterNewActionDlg').execute()\">". ($action ? __("Save action") : __('Add action'))."</button> "; - print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('filterNewActionDlg').hide()\">". + print "<button dojoType='dijit.form.Button' onclick=\"return dijit.byId('filterNewActionDlg').hide()\">". __('Cancel')."</button>"; - print "</div>"; + print "</footer>"; print "</form>"; } @@ -1129,11 +1121,11 @@ class Pref_Filters extends Handler_Protected { private function getFilterName($id) { $sth = $this->pdo->prepare( - "SELECT title,match_any_rule,COUNT(DISTINCT r.id) AS num_rules,COUNT(DISTINCT a.id) AS num_actions + "SELECT title,match_any_rule,f.inverse AS inverse,COUNT(DISTINCT r.id) AS num_rules,COUNT(DISTINCT a.id) AS num_actions FROM ttrss_filters2 AS f LEFT JOIN ttrss_filters2_rules AS r ON (r.filter_id = f.id) LEFT JOIN ttrss_filters2_actions AS a - ON (a.filter_id = f.id) WHERE f.id = ? GROUP BY f.title, f.match_any_rule"); + ON (a.filter_id = f.id) WHERE f.id = ? GROUP BY f.title, f.match_any_rule, f.inverse"); $sth->execute([$id]); if ($row = $sth->fetch()) { @@ -1142,6 +1134,7 @@ class Pref_Filters extends Handler_Protected { $num_rules = $row["num_rules"]; $num_actions = $row["num_actions"]; $match_any_rule = $row["match_any_rule"]; + $inverse = $row["inverse"]; if (!$title) $title = __("[No caption]"); @@ -1160,6 +1153,7 @@ class Pref_Filters extends Handler_Protected { } if ($match_any_rule) $title .= " (" . __("matches any rule") . ")"; + if ($inverse) $title .= " (" . __("inverse") . ")"; if ($num_actions > 0) $actions = sprintf(_ngettext("%s (+%d action)", "%s (+%d actions)", (int) $num_actions), $actions, $num_actions); diff --git a/classes/pref/labels.php b/classes/pref/labels.php index 28befe42b..5dadddab4 100644 --- a/classes/pref/labels.php +++ b/classes/pref/labels.php @@ -22,9 +22,9 @@ class Pref_Labels extends Handler_Protected { print "<form onsubmit='return false;'>"; - print "<div class=\"dlgSec\">".__("Caption")."</div>"; + print "<header>".__("Caption")."</header>"; - print "<div class=\"dlgSecCont\">"; + print "<section>"; $fg_color = $line['fg_color']; $bg_color = $line['bg_color'] ? $line['bg_color'] : '#fff7d5'; @@ -33,53 +33,47 @@ class Pref_Labels extends Handler_Protected { id='labelEdit_caption' name='caption' dojoType='dijit.form.ValidationTextBox' required='true' value=\"".htmlspecialchars($line['caption'])."\">"; - print "</div>"; - print "<div class=\"dlgSec\">" . __("Colors") . "</div>"; - print "<div class=\"dlgSecCont\">"; + print "</section>"; - print "<table cellspacing=\"0\">"; - - print "<tr><th style='text-align : left'>".__("Foreground:")."</th><th style='text-align : left'>".__("Background:"). - "</td></tr>"; + print "<header>" . __("Colors") . "</header>"; + print "<section>"; + print "<table>"; + print "<tr><th style='text-align : left'>".__("Foreground:")."</th><th style='text-align : left'>".__("Background:")."</th></tr>"; print "<tr><td style='padding-right : 10px'>"; - print "<input dojoType=\"dijit.form.TextBox\" - style=\"display : none\" id=\"labelEdit_fgColor\" - name=\"fg_color\" value=\"$fg_color\">"; - print "<input dojoType=\"dijit.form.TextBox\" - style=\"display : none\" id=\"labelEdit_bgColor\" - name=\"bg_color\" value=\"$bg_color\">"; + print "<input dojoType='dijit.form.TextBox' + style='display : none' id='labelEdit_fgColor' + name='fg_color' value='$fg_color'>"; + print "<input dojoType='dijit.form.TextBox' + style='display : none' id='labelEdit_bgColor' + name='bg_color' value='$bg_color'>"; - print "<div dojoType=\"dijit.ColorPalette\"> - <script type=\"dojo/method\" event=\"onChange\" args=\"fg_color\"> + print "<div dojoType='dijit.ColorPalette'> + <script type='dojo/method' event='onChange' args='fg_color'> dijit.byId('labelEdit_fgColor').attr('value', fg_color); dijit.byId('labelEdit_caption').domNode.setStyle({color: fg_color}); </script> </div>"; - print "</div>"; print "</td><td>"; - print "<div dojoType=\"dijit.ColorPalette\"> - <script type=\"dojo/method\" event=\"onChange\" args=\"bg_color\"> + print "<div dojoType='dijit.ColorPalette'> + <script type='dojo/method' event='onChange' args='bg_color'> dijit.byId('labelEdit_bgColor').attr('value', bg_color); dijit.byId('labelEdit_caption').domNode.setStyle({backgroundColor: bg_color}); </script> </div>"; - print "</div>"; print "</td></tr></table>"; - print "</div>"; - -# print "</form>"; + print "</section>"; - print "<div class=\"dlgButtons\">"; - print "<button dojoType=\"dijit.form.Button\" type=\"submit\" class=\"alt-primary\" onclick=\"dijit.byId('labelEditDlg').execute()\">". + print "<footer>"; + print "<button dojoType='dijit.form.Button' type='submit' class='alt-primary' onclick=\"dijit.byId('labelEditDlg').execute()\">". __('Save')."</button>"; - print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('labelEditDlg').hide()\">". + print "<button dojoType='dijit.form.Button' onclick=\"dijit.byId('labelEditDlg').hide()\">". __('Cancel')."</button>"; - print "</div>"; + print "</footer>"; print "</form>"; } diff --git a/classes/pref/prefs.php b/classes/pref/prefs.php index fb1c1db06..b611646a9 100644 --- a/classes/pref/prefs.php +++ b/classes/pref/prefs.php @@ -562,9 +562,9 @@ class Pref_Prefs extends Handler_Protected { if ($item = $prefs_available[$pref_name]) { - print "<fieldset class='prefs-set'>"; + print "<fieldset class='prefs'>"; - print "<label for='CB_$pref_name' style='width : 300px'>"; + print "<label for='CB_$pref_name'>"; print $item['short_desc'] . ":"; print "</label>"; @@ -763,18 +763,8 @@ class Pref_Prefs extends Handler_Protected { print_warning("Your PHP configuration has open_basedir restrictions enabled. Some plugins relying on CURL for functionality may not work correctly."); } - print "<table width='100%' class='prefPluginsList'>"; - - print "<tr><td colspan='5'><h2>".__("System plugins")."</h2>". - format_notice(__("System plugins are enabled in <strong>config.php</strong> for all users.")). - "</td></tr>"; - - print "<tr> - <th width=\"5%\"> </th> - <th width='10%'>".__('Plugin')."</th> - <th width=''>".__('Description')."</th> - <th width='5%'>".__('Version')."</th> - <th width='10%'>".__('Author')."</th></tr>"; + print "<h2>".__("System plugins")."</h2>"; + print_notice("System plugins are enabled in <strong>config.php</strong> for all users."); $system_enabled = array_map("trim", explode(",", PLUGINS)); $user_enabled = array_map("trim", explode(",", get_pref("_ENABLED_PLUGINS"))); @@ -793,102 +783,73 @@ class Pref_Prefs extends Handler_Protected { $checked = ""; } - print "<tr>"; - - print "<td align='center'><input disabled='1' - dojoType=\"dijit.form.CheckBox\" $checked - type=\"checkbox\"></td>"; + print "<fieldset class='prefs plugin'> + <label>$name:</label> + <label class='checkbox description insensitive' id='PLABEL-$name'> + <input disabled='1' + dojoType='dijit.form.CheckBox' $checked type='checkbox'> + ".htmlspecialchars($about[1]). "</label>"; - $icon_class = $checked ? "plugin-enabled" : "plugin-disabled"; - - print "<td><label><i class='material-icons $icon_class'>extension</i> $name</label></td>"; - print "<td>" . htmlspecialchars($about[1]); - if (@$about[4]) { - print " — <a target=\"_blank\" rel=\"noopener noreferrer\" class=\"visibleLink\" - href=\"".htmlspecialchars($about[4])."\">".__("more info")."</a>"; - } - print "</td>"; - print "<td>" . htmlspecialchars(sprintf("%.2f", $about[0])) . "</td>"; - print "<td>" . htmlspecialchars($about[2]) . "</td>"; - - if (count($tmppluginhost->get_all($plugin)) > 0) { - if (in_array($name, $system_enabled)) { - print "<td><a href='#' onclick=\"Helpers.clearPluginData('$name')\" - class='visibleLink'>".__("Clear data")."</a></td>"; + if (@$about[4]) { + 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 "</tr>"; + 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 "<tr><td colspan='4'><br/><h2>".__("User plugins")."</h2></td></tr>"; - - print "<tr> - <th width=\"5%\"> </th> - <th width='10%'>".__('Plugin')."</th> - <th width=''>".__('Description')."</th> - <th width='5%'>".__('Version')."</th> - <th width='10%'>".__('Author')."</th></tr>"; - + print "<h2>".__("User plugins")."</h2>"; foreach ($tmppluginhost->get_plugins() as $name => $plugin) { $about = $plugin->about(); if (!$about[3]) { + $checked = ""; + $disabled = ""; + if (in_array($name, $system_enabled)) { $checked = "checked='1'"; $disabled = "disabled='1'"; - $rowclass = ''; } else if (in_array($name, $user_enabled)) { $checked = "checked='1'"; - $disabled = ""; - $rowclass = "Selected"; - } else { - $checked = ""; - $disabled = ""; - $rowclass = ''; - } - - print "<tr class='$rowclass'>"; - - $icon_class = $checked ? "plugin-enabled" : "plugin-disabled"; - - print "<td align='center'><input id='FPCHK-$name' name='plugins[]' value='$name' onclick='Tables.onRowChecked(this);' - dojoType=\"dijit.form.CheckBox\" $checked $disabled - type=\"checkbox\"></td>"; - - print "<td><label for='FPCHK-$name'><i class='material-icons $icon_class'>extension</i> $name</label></td>"; - print "<td><label for='FPCHK-$name'>" . htmlspecialchars($about[1]) . "</label>"; - if (@$about[4]) { - print " — <a target=\"_blank\" rel=\"noopener noreferrer\" class=\"visibleLink\" - href=\"".htmlspecialchars($about[4])."\">".__("more info")."</a>"; } - print "</td>"; - print "<td>" . htmlspecialchars(sprintf("%.2f", $about[0])) . "</td>"; - print "<td>" . htmlspecialchars($about[2]) . "</td>"; + print "<fieldset class='prefs plugin'> + <label>$name:</label> + <label class='checkbox description insensitive' id='PLABEL-$name'> + <input name='plugins[]' value='$name' dojoType='dijit.form.CheckBox' $checked $disabled type='checkbox'> + ".htmlspecialchars($about[1])."</label>"; if (count($tmppluginhost->get_all($plugin)) > 0) { if (in_array($name, $system_enabled) || in_array($name, $user_enabled)) { - print "<td><a href='#' onclick=\"Helpers.clearPluginData('$name')\" class='visibleLink'>".__("Clear data")."</a></td>"; + print " <button dojoType='dijit.form.Button' + onclick=\"Helpers.clearPluginData('$name')\"> + <i class='material-icons'>clear</i> ".__("Clear data")."</button>"; } } - print "</tr>"; - + if (@$about[4]) { + 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'>". + htmlspecialchars(T_sprintf("v%.2f, by %s", $about[0], $about[2])). + "</div>"; + print "</fieldset>"; } - } - print "</table>"; - - //print "<p>" . __("You will need to reload Tiny Tiny RSS for plugin changes to take effect.") . "</p>"; - print "</div>"; #content-pane print '<div dojoType="dijit.layout.ContentPane" region="bottom">'; @@ -904,7 +865,6 @@ class Pref_Prefs extends Handler_Protected { print "</form>"; - PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB, "hook_prefs_tab", "prefPrefs"); @@ -1039,35 +999,34 @@ class Pref_Prefs extends Handler_Protected { print_hidden("key", "USER_STYLESHEET"); print "<textarea class='panel user-css-editor' dojoType='dijit.form.SimpleTextarea' - style='font-size : 12px;' - name='value'>$value</textarea>"; + style='font-size : 12px;' name='value'>$value</textarea>"; - print "<div class='dlgButtons'>"; - print "<button dojoType=\"dijit.form.Button\" + print "<footer>"; + print "<button dojoType='dijit.form.Button' onclick=\"dijit.byId('cssEditDlg').execute()\">".__('Save')."</button> "; - print "<button dojoType=\"dijit.form.Button\" + print "<button dojoType='dijit.form.Button' onclick=\"dijit.byId('cssEditDlg').hide()\">".__('Cancel')."</button>"; - print "</div>"; + print "</footer>"; } function editPrefProfiles() { - print "<div dojoType=\"dijit.Toolbar\">"; + print "<div dojoType='dijit.Toolbar'>"; - print "<div dojoType=\"dijit.form.DropDownButton\">". + print "<div dojoType='dijit.form.DropDownButton'>". "<span>" . __('Select')."</span>"; - print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">"; + print "<div dojoType='dijit.Menu' style='display: none'>"; print "<div onclick=\"Tables.select('pref-profiles-list', true)\" - dojoType=\"dijit.MenuItem\">".__('All')."</div>"; + dojoType='dijit.MenuItem'>".__('All')."</div>"; print "<div onclick=\"Tables.select('pref-profiles-list', false)\" - dojoType=\"dijit.MenuItem\">".__('None')."</div>"; + dojoType='dijit.MenuItem'>".__('None')."</div>"; print "</div></div>"; - print "<div style=\"float : right\">"; + print "<div style='float : right'>"; - print "<input name=\"newprofile\" dojoType=\"dijit.form.ValidationTextBox\" - required=\"1\"> - <button dojoType=\"dijit.form.Button\" + print "<input name='newprofile' dojoType='dijit.form.ValidationTextBox' + required='1'> + <button dojoType='dijit.form.Button' onclick=\"dijit.byId('profileEditDlg').addProfile()\">". __('Create profile')."</button></div>"; @@ -1113,10 +1072,10 @@ class Pref_Prefs extends Handler_Protected { $is_active = ""; } - print "<td><span dojoType=\"dijit.InlineEditBox\" - width=\"300px\" autoSave=\"false\" - profile-id=\"$profile_id\">" . $edit_title . - "<script type=\"dojo/method\" event=\"onChange\" args=\"item\"> + print "<td><span dojoType='dijit.InlineEditBox' + width='300px' autoSave='false' + profile-id='$profile_id'>" . $edit_title . + "<script type='dojo/method' event='onChange' args='item'> var elem = this; dojo.xhrPost({ url: 'backend.php', @@ -1137,17 +1096,14 @@ class Pref_Prefs extends Handler_Protected { print "</form>"; print "</div>"; - print "<div class='dlgButtons'> - <div style='float : left'> - <button class=\"alt-danger\" dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('profileEditDlg').removeSelected()\">". + print "<footer> + <button style='float : left' class='alt-danger' dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('profileEditDlg').removeSelected()\">". __('Remove selected profiles')."</button> - <button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('profileEditDlg').activateProfile()\">". + <button dojoType='dijit.form.Button' class='alt-primary' type='submit' onclick=\"dijit.byId('profileEditDlg').activateProfile()\">". __('Activate profile')."</button> - </div>"; - - print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('profileEditDlg').hide()\">". - __('Close this window')."</button>"; - print "</div>"; + <button dojoType='dijit.form.Button' onclick=\"dijit.byId('profileEditDlg').hide()\">". + __('Cancel')."</button>"; + print "</footer>"; } diff --git a/classes/pref/users.php b/classes/pref/users.php index 86dd8aac1..7b75bb872 100644 --- a/classes/pref/users.php +++ b/classes/pref/users.php @@ -20,7 +20,7 @@ class Pref_Users extends Handler_Protected { function edit() { global $access_level_names; - print "<form id=\"user_edit_form\" onsubmit='return false' dojoType=\"dijit.form.Form\">"; + print "<form id='user_edit_form' onsubmit='return false' dojoType='dijit.form.Form'>"; print '<div dojoType="dijit.layout.TabContainer" style="height : 400px"> <div dojoType="dijit.layout.ContentPane" title="'.__('Edit user').'">'; @@ -44,26 +44,28 @@ class Pref_Users extends Handler_Protected { $sel_disabled = ($id == $_SESSION["uid"] || $login == "admin") ? "disabled" : ""; - print "<div class=\"dlgSec\">".__("User")."</div>"; - print "<div class=\"dlgSecCont\">"; + print "<header>".__("User")."</header>"; + print "<section>"; if ($sel_disabled) { print_hidden("login", "$login"); } - print "<input size=\"30\" style=\"font-size : 16px\" - dojoType=\"dijit.form.ValidationTextBox\" required=\"1\" - $sel_disabled - name=\"login\" value=\"$login\">"; + print "<fieldset>"; + print "<label>" . __("Login:") . "</label>"; + print "<input style='font-size : 16px' + dojoType='dijit.form.ValidationTextBox' required='1' + $sel_disabled name='login' value=\"$login\">"; + print "</fieldset>"; - print "</div>"; + print "</section>"; - print "<div class=\"dlgSec\">".__("Authentication")."</div>"; - print "<div class=\"dlgSecCont\">"; + print "<header>".__("Authentication")."</header>"; + print "<section>"; print "<fieldset>"; - print __('Access level: ') . " "; + print "<label>" . __('Access level: ') . "</label> "; if (!$sel_disabled) { print_select_hash("access_level", $access_level, $access_level_names, @@ -77,20 +79,24 @@ class Pref_Users extends Handler_Protected { print "</fieldset>"; print "<fieldset>"; - print "<input dojoType=\"dijit.form.TextBox\" type=\"password\" size=\"20\" placeholder=\"Change password\" - name=\"password\">"; + print "<label>" . __("New password:") . "</label> "; + print "<input dojoType='dijit.form.TextBox' type='password' size='20' placeholder='Change password' + name='password'>"; print "</fieldset>"; - print "</div>"; + print "</section>"; - print "<div class=\"dlgSec\">".__("Options")."</div>"; - print "<div class=\"dlgSecCont\">"; + print "<header>".__("Options")."</header>"; + print "<section>"; - print "<input dojoType=\"dijit.form.TextBox\" size=\"30\" name=\"email\" placeholder=\"E-mail\" - value=\"$email\">"; + print "<fieldset>"; + print "<label>" . __("E-mail:") . "</label> "; + print "<input dojoType='dijit.form.TextBox' size='30' name='email' + value=\"$email\">"; + print "</fieldset>"; - print "</div>"; + print "</section>"; print "</table>"; @@ -103,11 +109,12 @@ class Pref_Users extends Handler_Protected { print '</div>'; print '</div>'; - print "<div class=\"dlgButtons\"> - <button dojoType=\"dijit.form.Button\" class=\"alt-primary\" type=\"submit\" onclick=\"dijit.byId('userEditDlg').execute()\">". + print "<footer> + <button dojoType='dijit.form.Button' class='alt-primary' type='submit' onclick=\"dijit.byId('userEditDlg').execute()\">". __('Save')."</button> - <button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('userEditDlg').hide()\">". - __('Cancel')."</button></div>"; + <button dojoType='dijit.form.Button' onclick=\"dijit.byId('userEditDlg').hide()\">". + __('Cancel')."</button> + </footer>"; print "</form>"; @@ -224,7 +231,7 @@ class Pref_Users extends Handler_Protected { function add() { $login = trim(clean($_REQUEST["login"])); - $tmp_user_pwd = make_password(8); + $tmp_user_pwd = make_password(); $salt = substr(bin2hex(get_random_bytes(125)), 0, 250); $pwd_hash = encrypt_password($tmp_user_pwd, $salt, true); @@ -264,21 +271,19 @@ class Pref_Users extends Handler_Protected { } } - static function resetUserPassword($uid, $show_password) { + static function resetUserPassword($uid, $format_output = false) { $pdo = Db::pdo(); - $sth = $pdo->prepare("SELECT login, email - FROM ttrss_users WHERE id = ?"); + $sth = $pdo->prepare("SELECT login FROM ttrss_users WHERE id = ?"); $sth->execute([$uid]); if ($row = $sth->fetch()) { $login = $row["login"]; - $email = $row["email"]; $new_salt = substr(bin2hex(get_random_bytes(125)), 0, 250); - $tmp_user_pwd = make_password(8); + $tmp_user_pwd = make_password(); $pwd_hash = encrypt_password($tmp_user_pwd, $new_salt, true); @@ -287,44 +292,19 @@ class Pref_Users extends Handler_Protected { WHERE id = ?"); $sth->execute([$pwd_hash, $new_salt, $uid]); - if ($show_password) { - print_notice(T_sprintf("Changed password of user %s to %s", $login, $tmp_user_pwd)); - } else { - print_notice(T_sprintf("Sending new password of user %s to %s", $login, $email)); - - if ($email) { - require_once "lib/MiniTemplator.class.php"; - - $tpl = new MiniTemplator; - - $tpl->readTemplateFromFile("templates/resetpass_template.txt"); + $message = T_sprintf("Changed password of user %s to %s", "<strong>$login</strong>", "<strong>$tmp_user_pwd</strong>"); - $tpl->setVariable('LOGIN', $login); - $tpl->setVariable('NEWPASS', $tmp_user_pwd); - - $tpl->addBlock('message'); - - $message = ""; - - $tpl->generateOutputToString($message); - - $mailer = new Mailer(); - - $rc = $mailer->mail(["to_name" => $login, - "to_address" => $email, - "subject" => __("[tt-rss] Password change notification"), - "message" => $message]); - - if (!$rc) print_error($mailer->error()); - } - } + if ($format_output) + print_notice($message); + else + print $message; } } function resetPass() { $uid = clean($_REQUEST["id"]); - Pref_Users::resetUserPassword($uid, true); + Pref_Users::resetUserPassword($uid); } function index() { @@ -344,9 +324,9 @@ class Pref_Users extends Handler_Protected { } print "<div style='float : right; padding-right : 4px;'> - <input dojoType=\"dijit.form.TextBox\" id=\"user_search\" size=\"20\" type=\"search\" + <input dojoType='dijit.form.TextBox' id='user_search' size='20' type='search' value=\"$user_search\"> - <button dojoType=\"dijit.form.Button\" oncl1ick=\"Users.reload()\">". + <button dojoType='dijit.form.Button' onclick='Users.reload()'>". __('Search')."</button> </div>"; @@ -356,23 +336,23 @@ class Pref_Users extends Handler_Protected { $sort = "login"; } - print "<div dojoType=\"dijit.form.DropDownButton\">". + print "<div dojoType='dijit.form.DropDownButton'>". "<span>" . __('Select')."</span>"; - print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">"; + print "<div dojoType='dijit.Menu' style='display: none'>"; print "<div onclick=\"Tables.select('prefUserList', true)\" - dojoType=\"dijit.MenuItem\">".__('All')."</div>"; + dojoType='dijit.MenuItem'>".__('All')."</div>"; print "<div onclick=\"Tables.select('prefUserList', false)\" - dojoType=\"dijit.MenuItem\">".__('None')."</div>"; + dojoType='dijit.MenuItem'>".__('None')."</div>"; print "</div></div>"; - print "<button dojoType=\"dijit.form.Button\" onclick=\"Users.add()\">".__('Create user')."</button>"; + print "<button dojoType='dijit.form.Button' onclick='Users.add()'>".__('Create user')."</button>"; print " - <button dojoType=\"dijit.form.Button\" onclick=\"Users.editSelected()\">". + <button dojoType='dijit.form.Button' onclick='Users.editSelected()'>". __('Edit')."</button dojoType=\"dijit.form.Button\"> - <button dojoType=\"dijit.form.Button\" onclick=\"Users.removeSelected()\">". + <button dojoType='dijit.form.Button' onclick='Users.removeSelected()'>". __('Remove')."</button dojoType=\"dijit.form.Button\"> - <button dojoType=\"dijit.form.Button\" onclick=\"Users.resetSelected()\">". + <button dojoType='dijit.form.Button' onclick='Users.resetSelected()'>". __('Reset password')."</button dojoType=\"dijit.form.Button\">"; PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION, @@ -400,16 +380,15 @@ class Pref_Users extends Handler_Protected { ORDER BY $sort"); $sth->execute([":search" => $user_search ? "%$user_search%" : ""]); - print "<p><table width=\"100%\" cellspacing=\"0\" - class=\"prefUserList\" id=\"prefUserList\">"; + print "<p><table width='100%' cellspacing='0' class='prefUserList' id='prefUserList'>"; - print "<tr class=\"title\"> - <td align='center' width=\"5%\"> </td> - <td width='20%'><a href=\"#\" onclick=\"Users.reload('login')\">".__('Login')."</a></td> - <td width='20%'><a href=\"#\" onclick=\"Users.reload('access_level')\">".__('Access Level')."</a></td> - <td width='10%'><a href=\"#\" onclick=\"Users.reload('num_feeds')\">".__('Subscribed feeds')."</a></td> - <td width='20%'><a href=\"#\" onclick=\"Users.reload('created')\">".__('Registered')."</a></td> - <td width='20%'><a href=\"#\" onclick=\"Users.reload('last_login')\">".__('Last login')."</a></td></tr>"; + print "<tr class='title'> + <td align='center' width='5%'> </td> + <td width='20%'><a href='#' onclick=\"Users.reload('login')\">".__('Login')."</a></td> + <td width='20%'><a href='#' onclick=\"Users.reload('access_level')\">".__('Access Level')."</a></td> + <td width='10%'><a href='#' onclick=\"Users.reload('num_feeds')\">".__('Subscribed feeds')."</a></td> + <td width='20%'><a href='#' onclick=\"Users.reload('created')\">".__('Registered')."</a></td> + <td width='20%'><a href='#' onclick=\"Users.reload('last_login')\">".__('Last login')."</a></td></tr>"; $lnum = 0; @@ -417,14 +396,14 @@ class Pref_Users extends Handler_Protected { $uid = $line["id"]; - print "<tr data-row-id=\"$uid\" onclick='Users.edit($uid)'>"; + print "<tr data-row-id='$uid' onclick='Users.edit($uid)'>"; $line["login"] = htmlspecialchars($line["login"]); $line["created"] = make_local_datetime($line["created"], false); $line["last_login"] = make_local_datetime($line["last_login"], false); print "<td align='center'><input onclick='Tables.onRowChecked(this); event.stopPropagation();' - dojoType=\"dijit.form.CheckBox\" type=\"checkbox\"></td>"; + dojoType='dijit.form.CheckBox' type='checkbox'></td>"; print "<td title='".__('Click to edit')."'><i class='material-icons'>person</i> " . $line["login"] . "</td>"; diff --git a/classes/rpc.php b/classes/rpc.php index 7220e10ea..037e14132 100755 --- a/classes/rpc.php +++ b/classes/rpc.php @@ -240,8 +240,8 @@ class RPC extends Handler_Protected { $new_feed_id = (int)$row['id'] + 1; $sth = $this->pdo->prepare("INSERT INTO ttrss_archived_feeds - (id, owner_uid, title, feed_url, site_url) - SELECT ?, owner_uid, title, feed_url, site_url from ttrss_feeds + (id, owner_uid, title, feed_url, site_url, created) + SELECT ?, owner_uid, title, feed_url, site_url, NOW() from ttrss_feeds WHERE id = ?"); $sth->execute([$new_feed_id, $feed_id]); @@ -347,20 +347,6 @@ class RPC extends Handler_Protected { print "</ul>"; } - function updateFeedBrowser() { - if (defined('_DISABLE_FEED_BROWSER') && _DISABLE_FEED_BROWSER) return; - - $search = clean($_REQUEST["search"]); - $limit = clean($_REQUEST["limit"]); - $mode = (int) clean($_REQUEST["mode"]); - - require_once "feedbrowser.php"; - - print json_encode(array("content" => - make_feed_browser($search, $limit, $mode), - "mode" => $mode)); - } - // Silent function massSubscribe() { diff --git a/classes/rssutils.php b/classes/rssutils.php index 6048c8310..8feffa662 100755 --- a/classes/rssutils.php +++ b/classes/rssutils.php @@ -19,51 +19,9 @@ class RSSUtils { return preg_replace('/[\x{10000}-\x{10FFFF}]/u', "\xEF\xBF\xBD", $str); } - static function update_feedbrowser_cache() { - + static function cleanup_feed_browser() { $pdo = Db::pdo(); - - $sth = $pdo->query("SELECT feed_url, site_url, title, COUNT(id) AS subscribers - FROM ttrss_feeds WHERE feed_url NOT IN (SELECT feed_url FROM ttrss_feeds - WHERE private IS true OR auth_login != '' OR auth_pass != '' OR feed_url LIKE '%:%@%/%') - GROUP BY feed_url, site_url, title ORDER BY subscribers DESC LIMIT 1000"); - - $pdo->beginTransaction(); - $pdo->query("DELETE FROM ttrss_feedbrowser_cache"); - - $count = 0; - - while ($line = $sth->fetch()) { - - $subscribers = $line["subscribers"]; - $feed_url = $line["feed_url"]; - $title = $line["title"]; - $site_url = $line["site_url"]; - - $tmph = $pdo->prepare("SELECT subscribers FROM - ttrss_feedbrowser_cache WHERE feed_url = ?"); - $tmph->execute([$feed_url]); - - if (!$tmph->fetch()) { - - $tmph = $pdo->prepare("INSERT INTO ttrss_feedbrowser_cache - (feed_url, site_url, title, subscribers) - VALUES - (?, ?, ?, ?)"); - - $tmph->execute([$feed_url, $site_url, $title, $subscribers]); - - ++$count; - - } - - } - - $pdo->commit(); - - return $count; - } static function update_daemon_common($limit = DAEMON_FEED_LIMIT) { @@ -1288,6 +1246,20 @@ class RSSUtils { } } + static function expire_feed_archive() { + Debug::log("Removing old archived feeds..."); + + $pdo = Db::pdo(); + + if (DB_TYPE == "pgsql") { + $pdo->query("DELETE FROM ttrss_archived_feeds + WHERE created < NOW() - INTERVAL '1 month'"); + } else { + $pdo->query("DELETE FROM ttrss_archived_feeds + WHERE created < DATE_SUB(NOW(), INTERVAL 1 MONTH)"); + } + } + static function expire_lock_files() { Debug::log("Removing old lock files...", Debug::$LOG_VERBOSE); @@ -1526,9 +1498,8 @@ class RSSUtils { RSSUtils::expire_cached_files(); RSSUtils::expire_lock_files(); RSSUtils::expire_error_log(); - - $count = RSSUtils::update_feedbrowser_cache(); - Debug::log("Feedbrowser updated, $count feeds processed."); + RSSUtils::expire_feed_archive(); + RSSUtils::cleanup_feed_browser(); Article::purge_orphans(); RSSUtils::cleanup_counters_cache(); |