X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=classes%2Ffeeds.php;h=30d26f361937aa4cb95defbcfd106977ff89a231;hb=09bc54c6901c5e4f6ec1d2a8b00fbf450aa258dd;hp=99eb0fbf2d8c6b22ca92c96568af7eabcfc2fd74;hpb=b1d1bc901fa11e51855a29401d56b6b74ea9cec9;p=tt-rss.git diff --git a/classes/feeds.php b/classes/feeds.php index 99eb0fbf..30d26f36 100755 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -39,7 +39,7 @@ class Feeds extends Handler_Protected { $search_q = ""; } - $reply .= ""; + $reply = ""; $rss_link = htmlspecialchars(get_self_url_prefix() . "/public.php?op=rss&id=$feed_id$cat_q$search_q"); @@ -193,24 +193,28 @@ class Feeds extends Handler_Protected { if (!$any_needs_curl) { - $result = $this->dbh->query( - "SELECT cache_images," . SUBSTRING_FOR_DATE . "(last_updated,1,19) AS last_updated - FROM ttrss_feeds WHERE id = '$feed'"); + $sth = $this->pdo->prepare("SELECT cache_images," . SUBSTRING_FOR_DATE . "(last_updated,1,19) AS last_updated + FROM ttrss_feeds WHERE id = ?"); + $sth->execute([$feed]); - if ($this->dbh->num_rows($result) != 0) { - $last_updated = strtotime($this->dbh->fetch_result($result, 0, "last_updated")); - $cache_images = sql_bool_to_bool($this->dbh->fetch_result($result, 0, "cache_images")); + if ($row = $sth->fetch()) { + $last_updated = strtotime($row["last_updated"]); + $cache_images = $row["cache_images"]; if (!$cache_images && time() - $last_updated > 120) { RSSUtils::update_rss_feed($feed, true); } else { - $this->dbh->query("UPDATE ttrss_feeds SET last_updated = '1970-01-01', last_update_started = '1970-01-01' - WHERE id = '$feed'"); + $sth = $this->pdo->prepare("UPDATE ttrss_feeds + SET last_updated = '1970-01-01', last_update_started = '1970-01-01' + WHERE id = ?"); + $sth->execute([$feed]); } } } else { - $this->dbh->query("UPDATE ttrss_feeds SET last_updated = '1970-01-01', last_update_started = '1970-01-01' - WHERE id = '$feed'"); + $sth = $this->pdo->prepare("UPDATE ttrss_feeds + SET last_updated = '1970-01-01', last_update_started = '1970-01-01' + WHERE id = ?"); + $sth->execute([$feed]); } } @@ -221,16 +225,16 @@ class Feeds extends Handler_Protected { // FIXME: might break tag display? if (is_numeric($feed) && $feed > 0 && !$cat_view) { - $result = $this->dbh->query( - "SELECT id FROM ttrss_feeds WHERE id = '$feed' LIMIT 1"); + $sth = $this->pdo->prepare("SELECT id FROM ttrss_feeds WHERE id = ? LIMIT 1"); + $sth->execute([$feed]); - if ($this->dbh->num_rows($result) == 0) { + if (!$sth->fetch()) { $reply['content'] = "
".__('Feed not found.')."
"; } } - @$search = $this->dbh->escape_string($_REQUEST["query"]); - @$search_language = $this->dbh->escape_string($_REQUEST["search_language"]); // PGSQL only + @$search = $_REQUEST["query"]; + @$search_language = $_REQUEST["search_language"]; // PGSQL only if ($search) { $disable_cache = true; @@ -238,7 +242,6 @@ class Feeds extends Handler_Protected { if ($_REQUEST["debug"]) $timing_info = print_checkpoint("H0", $timing_info); - if (!$cat_view && is_numeric($feed) && $feed < PLUGIN_FEED_BASE_INDEX && $feed > LABEL_BASE_INDEX) { $handler = PluginHost::getInstance()->get_feed_handler( PluginHost::feed_to_pfeed_id($feed)); @@ -300,8 +303,6 @@ class Feeds extends Handler_Protected { $feed, $cat_view, $search, $last_error, $last_updated); - $headlines_count = is_numeric($result) ? 0 : $this->dbh->num_rows($result); - if ($offset == 0) { foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_HEADLINES_BEFORE) as $p) { $reply['content'] .= $p->hook_headlines_before($feed, $cat_view, $qfh_ret); @@ -310,521 +311,506 @@ class Feeds extends Handler_Protected { $reply['content'] = ''; - if ($headlines_count > 0) { + $headlines_count = 0; + + $lnum = $offset; + $num_unread = 0; + if ($_REQUEST["debug"]) $timing_info = print_checkpoint("PS", $timing_info); + $expand_cdm = get_pref('CDM_EXPANDED'); + + while ($line = $result->fetch()) { + + ++$headlines_count; + + $line["content_preview"] = "— " . truncate_string(strip_tags($line["content"]), 250); - $lnum = $offset; + foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) { + $line = $p->hook_query_headlines($line, 250, false); + } - $num_unread = 0; - $cur_feed_title = ''; + if (get_pref('SHOW_CONTENT_PREVIEW')) { + $content_preview = $line["content_preview"]; + } - if ($_REQUEST["debug"]) $timing_info = print_checkpoint("PS", $timing_info); + $id = $line["id"]; + $feed_id = $line["feed_id"]; + $label_cache = $line["label_cache"]; + $labels = false; - $expand_cdm = get_pref('CDM_EXPANDED'); + if ($label_cache) { + $label_cache = json_decode($label_cache, true); - while ($line = $this->dbh->fetch_assoc($result)) { + if ($label_cache) { + if ($label_cache["no-labels"] == 1) + $labels = array(); + else + $labels = $label_cache; + } + } - $line["content_preview"] = "— " . truncate_string(strip_tags($line["content"]), 250); + if (!is_array($labels)) $labels = Article::get_article_labels($id); - foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) { - $line = $p->hook_query_headlines($line, 250, false); - } + $labels_str = ""; + $labels_str .= Article::format_article_labels($labels); + $labels_str .= ""; - if (get_pref('SHOW_CONTENT_PREVIEW')) { - $content_preview = $line["content_preview"]; - } + if (count($topmost_article_ids) < 3) { + array_push($topmost_article_ids, $id); + } - $id = $line["id"]; - $feed_id = $line["feed_id"]; - $label_cache = $line["label_cache"]; - $labels = false; + $class = ""; - if ($label_cache) { - $label_cache = json_decode($label_cache, true); + if ($line["unread"]) { + $class .= " Unread"; + ++$num_unread; + } - if ($label_cache) { - if ($label_cache["no-labels"] == 1) - $labels = array(); - else - $labels = $label_cache; - } - } + if ($line["marked"]) { + $marked_pic = "\"Unstar"; + $class .= " marked"; + } else { + $marked_pic = "\"Star"; + } - if (!is_array($labels)) $labels = Article::get_article_labels($id); + if ($line["published"]) { + $published_pic = "\"Unpublish"; + $class .= " published"; + } else { + $published_pic = "\"Publish"; + } - $labels_str = ""; - $labels_str .= Article::format_article_labels($labels); - $labels_str .= ""; + $updated_fmt = make_local_datetime($line["updated"], false, false, false, true); + $date_entered_fmt = T_sprintf("Imported at %s", + make_local_datetime($line["date_entered"], false)); - if (count($topmost_article_ids) < 3) { - array_push($topmost_article_ids, $id); - } + $score = $line["score"]; - $class = ""; + $score_pic = "images/" . get_score_pic($score); - if (sql_bool_to_bool($line["unread"])) { - $class .= " Unread"; - ++$num_unread; - } + $score_pic = ""; - if (sql_bool_to_bool($line["marked"])) { - $marked_pic = "\"Unstar"; - $class .= " marked"; - } else { - $marked_pic = "\"Star"; - } + if ($score > 500) { + $hlc_suffix = "high"; + } else if ($score < -100) { + $hlc_suffix = "low"; + } else { + $hlc_suffix = ""; + } - if (sql_bool_to_bool($line["published"])) { - $published_pic = "\"Unpublish"; - $class .= " published"; - } else { - $published_pic = "\"Publish"; - } + $entry_author = $line["author"]; -# $content_link = "" . -# $line["title"] . ""; + if ($entry_author) { + $entry_author = " — $entry_author"; + } -# $content_link = "" . -# $line["title"] . ""; + $has_feed_icon = feed_has_icon($feed_id); -# $content_link = "" . -# $line["title"] . ""; + if ($has_feed_icon) { + $feed_icon_img = "\"\""; + } else { + $feed_icon_img = "\"\""; + } - $updated_fmt = make_local_datetime($line["updated"], false, false, false, true); - $date_entered_fmt = T_sprintf("Imported at %s", - make_local_datetime($line["date_entered"], false)); + $entry_site_url = $line["site_url"]; - $score = $line["score"]; + //setting feed headline background color, needs to change text color based on dark/light + $fav_color = $line['favicon_avg_color']; - $score_pic = "images/" . get_score_pic($score); + require_once "colors.php"; -/* $score_title = __("(Click to change)"); - $score_pic = ""; */ + if ($fav_color && $fav_color != 'fail') { + if (!isset($rgba_cache[$feed_id])) { + $rgba_cache[$feed_id] = join(",", _color_unpack($fav_color)); + } + } - $score_pic = ""; + if (!get_pref('COMBINED_DISPLAY_MODE')) { - if ($score > 500) { - $hlc_suffix = "high"; - } else if ($score < -100) { - $hlc_suffix = "low"; - } else { - $hlc_suffix = ""; - } + if ($vfeed_group_enabled) { + if ($feed_id != $vgroup_last_feed && $line["feed_title"]) { - $entry_author = $line["author"]; + $cur_feed_title = $line["feed_title"]; + $vgroup_last_feed = $feed_id; - if ($entry_author) { - $entry_author = " — $entry_author"; - } + $cur_feed_title = htmlspecialchars($cur_feed_title); - $has_feed_icon = feed_has_icon($feed_id); + $vf_catchup_link = "".__('mark feed as read').""; - if ($has_feed_icon) { - $feed_icon_img = "\"\""; - } else { - $feed_icon_img = "\"\""; - } + $reply['content'] .= "
". + "
$feed_icon_img
". + "". + $line["feed_title"]." + $vf_catchup_link
"; - $entry_site_url = $line["site_url"]; - //setting feed headline background color, needs to change text color based on dark/light - $fav_color = $line['favicon_avg_color']; + } + } - require_once "colors.php"; + $mouseover_attrs = "onmouseover='postMouseIn(event, $id)' + onmouseout='postMouseOut($id)'"; - if ($fav_color && $fav_color != 'fail') { - if (!isset($rgba_cache[$feed_id])) { - $rgba_cache[$feed_id] = join(",", _color_unpack($fav_color)); - } - } + $reply['content'] .= "
"; - if (!get_pref('COMBINED_DISPLAY_MODE')) { + $reply['content'] .= "
"; - if ($vfeed_group_enabled) { - if ($feed_id != $vgroup_last_feed && $line["feed_title"]) { + $reply['content'] .= ""; - $cur_feed_title = $line["feed_title"]; - $vgroup_last_feed = $feed_id; + $reply['content'] .= "$marked_pic"; + $reply['content'] .= "$published_pic"; - $cur_feed_title = htmlspecialchars($cur_feed_title); + $reply['content'] .= "
"; - $vf_catchup_link = "".__('mark feed as read').""; + $reply['content'] .= "
"; + $reply['content'] .= "" . + truncate_string($line["title"], 200); - $reply['content'] .= ""; + if (get_pref('SHOW_CONTENT_PREVIEW')) { + $reply['content'] .= "" . $line["content_preview"] . ""; + } + $reply['content'] .= ""; - } - } + $reply['content'] .= $labels_str; - $mouseover_attrs = "onmouseover='postMouseIn(event, $id)' - onmouseout='postMouseOut($id)'"; + $reply['content'] .= "
"; - $reply['content'] .= "
"; + if (!$vfeed_group_enabled) { + if (@$line["feed_title"]) { + $rgba = @$rgba_cache[$feed_id]; - $reply['content'] .= "
"; + $reply['content'] .= "". + truncate_string($line["feed_title"],30).""; + } + } - $reply['content'] .= ""; - $reply['content'] .= "$marked_pic"; - $reply['content'] .= "$published_pic"; + $reply['content'] .= ""; - $reply['content'] .= "
"; + $reply['content'] .= "
$updated_fmt
+ "; - $reply['content'] .= "
"; - $reply['content'] .= "" . - truncate_string($line["title"], 200); + $reply['content'] .= "
"; - if (get_pref('SHOW_CONTENT_PREVIEW')) { - $reply['content'] .= "" . $line["content_preview"] . ""; - } + $reply['content'] .= $score_pic; - $reply['content'] .= ""; + if ($line["feed_title"] && !$vfeed_group_enabled) { - $reply['content'] .= $labels_str; + $reply['content'] .= " + $feed_icon_img"; + } - $reply['content'] .= "
"; + $reply['content'] .= "
"; + $reply['content'] .= "
"; - if (!$vfeed_group_enabled) { - if (@$line["feed_title"]) { - $rgba = @$rgba_cache[$feed_id]; + } else { - $reply['content'] .= "". - truncate_string($line["feed_title"],30).""; - } - } + if ($line["tag_cache"]) + $tags = explode(",", $line["tag_cache"]); + else + $tags = false; + $line["content"] = sanitize($line["content"], + $line['hide_images'], false, $entry_site_url, $highlight_words, $line["id"]); - $reply['content'] .= ""; + foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_RENDER_ARTICLE_CDM) as $p) { + $line = $p->hook_render_article_cdm($line); + } - $reply['content'] .= "
$updated_fmt
-
"; + if ($vfeed_group_enabled && $line["feed_title"]) { + if ($feed_id != $vgroup_last_feed) { - $reply['content'] .= "
"; + $cur_feed_title = $line["feed_title"]; + $vgroup_last_feed = $feed_id; - $reply['content'] .= $score_pic; + $cur_feed_title = htmlspecialchars($cur_feed_title); - if ($line["feed_title"] && !$vfeed_group_enabled) { + $vf_catchup_link = "".__('mark feed as read').""; - $reply['content'] .= " - $feed_icon_img"; - } + $has_feed_icon = feed_has_icon($feed_id); - $reply['content'] .= "
"; - $reply['content'] .= "
"; + if ($has_feed_icon) { + $feed_icon_img = "\"\""; + } else { + //$feed_icon_img = "\"\""; + } - } else { + $reply['content'] .= "
". + "
$feed_icon_img
". + "". + $line["feed_title"]." $vf_catchup_link
"; - if ($line["tag_cache"]) - $tags = explode(",", $line["tag_cache"]); - else - $tags = false; + } + } - $line["content"] = sanitize($line["content"], - sql_bool_to_bool($line['hide_images']), false, $entry_site_url, $highlight_words, $line["id"]); + $mouseover_attrs = "onmouseover='postMouseIn(event, $id)' + onmouseout='postMouseOut($id)'"; - foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_RENDER_ARTICLE_CDM) as $p) { - $line = $p->hook_render_article_cdm($line); - } + $expanded_class = $expand_cdm ? "expanded" : "expandable"; - if ($vfeed_group_enabled && $line["feed_title"]) { - if ($feed_id != $vgroup_last_feed) { + $tmp_content = "
"; - $cur_feed_title = $line["feed_title"]; - $vgroup_last_feed = $feed_id; + $tmp_content .= "
"; + $tmp_content .= "
"; - $cur_feed_title = htmlspecialchars($cur_feed_title); + $tmp_content .= ""; - $vf_catchup_link = "".__('mark feed as read').""; + $tmp_content .= "$marked_pic"; + $tmp_content .= "$published_pic"; - $has_feed_icon = feed_has_icon($feed_id); + $tmp_content .= "
"; - if ($has_feed_icon) { - $feed_icon_img = "\"\""; - } else { - //$feed_icon_img = "\"\""; - } + if ($highlight_words && count($highlight_words > 0)) { + foreach ($highlight_words as $word) { + $line["title"] = preg_replace("/(\Q$word\E)/i", + "$1", $line["title"]); + } + } - $reply['content'] .= "
". - "
$feed_icon_img
". - "". - $line["feed_title"]." $vf_catchup_link
"; + // data-article-id included for context menu + $tmp_content .= " + ". + $line["title"] . + " $entry_author"; - } - } + $tmp_content .= $labels_str; - $mouseover_attrs = "onmouseover='postMouseIn(event, $id)' - onmouseout='postMouseOut($id)'"; + $tmp_content .= ""; - $expanded_class = $expand_cdm ? "expanded" : "expandable"; - - $tmp_content = "
"; + if (!$expand_cdm) + $content_hidden = "style=\"display : none\""; + else + $excerpt_hidden = "style=\"display : none\""; - $tmp_content .= "
"; - $tmp_content .= "
"; + $tmp_content .= "" . $content_preview . ""; - $tmp_content .= ""; + $tmp_content .= ""; - $tmp_content .= "$marked_pic"; - $tmp_content .= "$published_pic"; + if (!$vfeed_group_enabled) { + if (@$line["feed_title"]) { + $rgba = @$rgba_cache[$feed_id]; - $tmp_content .= "
"; + $tmp_content .= ""; + } + } - if ($highlight_words && count($highlight_words > 0)) { - foreach ($highlight_words as $word) { - $line["title"] = preg_replace("/(\Q$word\E)/i", - "$1", $line["title"]); - } - } + $tmp_content .= "$updated_fmt"; - // data-article-id included for context menu - $tmp_content .= " - ". - $line["title"] . - " $entry_author"; - - $tmp_content .= $labels_str; - - $tmp_content .= ""; - - if (!$expand_cdm) - $content_hidden = "style=\"display : none\""; - else - $excerpt_hidden = "style=\"display : none\""; - - $tmp_content .= "" . $content_preview . ""; - - $tmp_content .= ""; - - if (!$vfeed_group_enabled) { - if (@$line["feed_title"]) { - $rgba = @$rgba_cache[$feed_id]; - - $tmp_content .= ""; - } - } + $tmp_content .= "
"; + $tmp_content .= "$score_pic"; - $tmp_content .= "$updated_fmt"; + if (!get_pref("VFEED_GROUP_BY_FEED") && $line["feed_title"]) { + $tmp_content .= "$feed_icon_img"; + } + $tmp_content .= "
"; //scoreWrap - $tmp_content .= "
"; - $tmp_content .= "$score_pic"; + $tmp_content .= "
"; //cdmHeader - if (!get_pref("VFEED_GROUP_BY_FEED") && $line["feed_title"]) { - $tmp_content .= "$feed_icon_img"; - } - $tmp_content .= "
"; //scoreWrap + $tmp_content .= "
"; - $tmp_content .= "
"; //cdmHeader + $tmp_content .= "
"; + if ($line['note']) { + $tmp_content .= Article::format_article_note($id, $line['note']); + } + $tmp_content .= "
"; //POSTNOTE - $tmp_content .= "
"; + if (!$line['lang']) $line['lang'] = 'en'; - $tmp_content .= "
"; - if ($line['note']) { - $tmp_content .= Article::format_article_note($id, $line['note']); - } - $tmp_content .= "
"; //POSTNOTE + $tmp_content .= "
"; - if (!$line['lang']) $line['lang'] = 'en'; + if ($line["orig_feed_id"]) { - $tmp_content .= "
"; + $ofgh = $this->pdo->prepare("SELECT * FROM ttrss_archived_feeds + WHERE id = ? AND owner_uid = ?"); + $ofgh->execute([$line["orig_feed_id"], $_SESSION['uid']]); - if ($line["orig_feed_id"]) { + if ($tmp_line = $ofgh->fetch()) { - $tmp_result = $this->dbh->query("SELECT * FROM ttrss_archived_feeds - WHERE id = ".$line["orig_feed_id"] . " AND owner_uid = " . $_SESSION["uid"]); + $tmp_content .= "
"; + $tmp_content .= __("Originally from:"); - if ($this->dbh->num_rows($tmp_result) != 0) { + $tmp_content .= " "; - $tmp_content .= "
"; - $tmp_content .= __("Originally from:"); + $tmp_content .= "" . + $tmp_line['title'] . ""; - $tmp_content .= " "; + $tmp_content .= " "; - $tmp_line = $this->dbh->fetch_assoc($tmp_result); + $tmp_content .= ""; + $tmp_content .= ""; - $tmp_content .= "" . - $tmp_line['title'] . ""; + $tmp_content .= "
"; + } + } - $tmp_content .= " "; + $tmp_content .= ""; + $tmp_content .= ""; + $tmp_content .= htmlspecialchars($line["content"]); + $tmp_content .= ""; + $tmp_content .= ""; - $tmp_content .= ""; - $tmp_content .= ""; + $tmp_content .= "
"; //cdmContentInner - $tmp_content .= "
"; - } - } + $tmp_content .= "
"; - $tmp_content .= ""; - $tmp_content .= ""; - $tmp_content .= htmlspecialchars($line["content"]); - $tmp_content .= ""; - $tmp_content .= ""; + $always_display_enclosures = $line["always_display_enclosures"]; + $tmp_content .= Article::format_article_enclosures($id, $always_display_enclosures, + $line["content"], $line["hide_images"]); - $tmp_content .= "
"; //cdmContentInner + $tmp_content .= "
"; // cdmIntermediate - $tmp_content .= "
"; + $tmp_content .= "
"; - $always_display_enclosures = sql_bool_to_bool($line["always_display_enclosures"]); - $tmp_content .= Article::format_article_enclosures($id, $always_display_enclosures, $line["content"], sql_bool_to_bool($line["hide_images"])); + foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_ARTICLE_LEFT_BUTTON) as $p) { + $tmp_content .= $p->hook_article_left_button($line); + } - $tmp_content .= "
"; // cdmIntermediate + $tags_str = Article::format_tags_string($tags, $id); - $tmp_content .= "
"; + $tmp_content .= ""; - foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_ARTICLE_LEFT_BUTTON) as $p) { - $tmp_content .= $p->hook_article_left_button($line); - } + $tmp_content .= "Tags + $tags_str + (+)"; - $tags_str = Article::format_tags_string($tags, $id); + $num_comments = (int) $line["num_comments"]; + $entry_comments = ""; - $tmp_content .= ""; + if ($num_comments > 0) { + if ($line["comments"]) { + $comments_url = htmlspecialchars($line["comments"]); + } else { + $comments_url = htmlspecialchars($line["link"]); + } + $entry_comments = "$num_comments ". + _ngettext("comment", "comments", $num_comments).""; - $tmp_content .= "Tags - $tags_str - (+)"; + } else { + if ($line["comments"] && $line["link"] != $line["comments"]) { + $entry_comments = "".__("comments").""; + } + } - $num_comments = (int) $line["num_comments"]; - $entry_comments = ""; + if ($entry_comments) $tmp_content .= " ($entry_comments)"; - if ($num_comments > 0) { - if ($line["comments"]) { - $comments_url = htmlspecialchars($line["comments"]); - } else { - $comments_url = htmlspecialchars($line["link"]); - } - $entry_comments = "$num_comments ". - _ngettext("comment", "comments", $num_comments).""; + $tmp_content .= ""; + $tmp_content .= "
"; - } else { - if ($line["comments"] && $line["link"] != $line["comments"]) { - $entry_comments = "".__("comments").""; - } - } + foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_ARTICLE_BUTTON) as $p) { + $tmp_content .= $p->hook_article_button($line); + } - if ($entry_comments) $tmp_content .= " ($entry_comments)"; + $tmp_content .= "
"; // buttons - $tmp_content .= "
"; - $tmp_content .= "
"; + $tmp_content .= "
"; // cdmFooter + $tmp_content .= "
"; // cdmContent + $tmp_content .= "
"; // RROW.cdm -// $tmp_content .= "$marked_pic"; -// $tmp_content .= "$published_pic"; + foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_FORMAT_ARTICLE_CDM) as $p) { + $tmp_content = $p->hook_format_article_cdm($tmp_content, $line); + } - foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_ARTICLE_BUTTON) as $p) { - $tmp_content .= $p->hook_article_button($line); - } + $reply['content'] .= $tmp_content; + } - $tmp_content .= "
"; // buttons + ++$lnum; + } - $tmp_content .= "
"; // cdmFooter - $tmp_content .= "
"; // cdmContent - $tmp_content .= "
"; // RROW.cdm + if ($_REQUEST["debug"]) $timing_info = print_checkpoint("PE", $timing_info); - foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_FORMAT_ARTICLE_CDM) as $p) { - $tmp_content = $p->hook_format_article_cdm($tmp_content, $line); - } + if (!$headlines_count) { - $reply['content'] .= $tmp_content; - } + if (!is_numeric($result)) { - ++$lnum; - } + switch ($view_mode) { + case "unread": + $message = __("No unread articles found to display."); + break; + case "updated": + $message = __("No updated articles found to display."); + break; + case "marked": + $message = __("No starred articles found to display."); + break; + default: + if ($feed < LABEL_BASE_INDEX) { + $message = __("No articles found to display. You can assign articles to labels manually from article header context menu (applies to all selected articles) or use a filter."); + } else { + $message = __("No articles found to display."); + } + } - if ($_REQUEST["debug"]) $timing_info = print_checkpoint("PE", $timing_info); - - } else if (!is_numeric($result)) { - $message = ""; - - switch ($view_mode) { - case "unread": - $message = __("No unread articles found to display."); - break; - case "updated": - $message = __("No updated articles found to display."); - break; - case "marked": - $message = __("No starred articles found to display."); - break; - default: - if ($feed < LABEL_BASE_INDEX) { - $message = __("No articles found to display. You can assign articles to labels manually from article header context menu (applies to all selected articles) or use a filter."); - } else { - $message = __("No articles found to display."); - } - } + if (!$offset && $message) { + $reply['content'] = "
$message"; - if (!$offset && $message) { - $reply['content'] = "
$message"; + $reply['content'] .= "

"; - $reply['content'] .= "

"; + $sth = $this->pdo->prepare("SELECT " . SUBSTRING_FOR_DATE . "(MAX(last_updated), 1, 19) AS last_updated FROM ttrss_feeds + WHERE owner_uid = ?"); + $sth->execute([$_SESSION['uid']]); + $row = $sth->fetch(); - $result = $this->dbh->query("SELECT ".SUBSTRING_FOR_DATE."(MAX(last_updated), 1, 19) AS last_updated FROM ttrss_feeds - WHERE owner_uid = " . $_SESSION['uid']); + $last_updated = make_local_datetime($row["last_updated"], false); - $last_updated = $this->dbh->fetch_result($result, 0, "last_updated"); - $last_updated = make_local_datetime($last_updated, false); + $reply['content'] .= sprintf(__("Feeds last updated at %s"), $last_updated); - $reply['content'] .= sprintf(__("Feeds last updated at %s"), $last_updated); + $sth = $this->pdo->prepare("SELECT COUNT(id) AS num_errors + FROM ttrss_feeds WHERE last_error != '' AND owner_uid = ?"); + $sth->execute([$_SESSION['uid']]); + $row = $sth->fetch(); - $result = $this->dbh->query("SELECT COUNT(id) AS num_errors - FROM ttrss_feeds WHERE last_error != '' AND owner_uid = ".$_SESSION["uid"]); + $num_errors = $row["num_errors"]; - $num_errors = $this->dbh->fetch_result($result, 0, "num_errors"); + if ($num_errors > 0) { + $reply['content'] .= "
"; + $reply['content'] .= "" . + __('Some feeds have update errors (click for details)') . ""; + } + $reply['content'] .= "

"; - if ($num_errors > 0) { - $reply['content'] .= "
"; - $reply['content'] .= "". - __('Some feeds have update errors (click for details)').""; } - $reply['content'] .= "

"; - + } else if (is_numeric($result) && $result == -1) { + $reply['first_id_changed'] = true; } - } else if (is_numeric($result) && $result == -1) { - $reply['first_id_changed'] = true; } if ($_REQUEST["debug"]) $timing_info = print_checkpoint("H2", $timing_info); @@ -834,8 +820,10 @@ class Feeds extends Handler_Protected { } function catchupAll() { - $this->dbh->query("UPDATE ttrss_user_entries SET - last_read = NOW(), unread = false WHERE unread = true AND owner_uid = " . $_SESSION["uid"]); + $sth = $this->pdo->prepare("UPDATE ttrss_user_entries SET + last_read = NOW(), unread = false WHERE unread = true AND owner_uid = ?"); + $sth->execute([$_SESSION['uid']]); + CCache::zero_all($_SESSION["uid"]); } @@ -846,16 +834,16 @@ class Feeds extends Handler_Protected { if ($_REQUEST["debug"]) $timing_info = print_checkpoint("0", $timing_info); - $feed = $this->dbh->escape_string($_REQUEST["feed"]); - $method = $this->dbh->escape_string($_REQUEST["m"]); - $view_mode = $this->dbh->escape_string($_REQUEST["view_mode"]); + $feed = $_REQUEST["feed"]; + $method = $_REQUEST["m"]; + $view_mode = $_REQUEST["view_mode"]; $limit = 30; @$cat_view = $_REQUEST["cat"] == "true"; - @$next_unread_feed = $this->dbh->escape_string($_REQUEST["nuf"]); - @$offset = $this->dbh->escape_string($_REQUEST["skip"]); - @$vgroup_last_feed = $this->dbh->escape_string($_REQUEST["vgrlf"]); - $order_by = $this->dbh->escape_string($_REQUEST["order_by"]); - $check_first_id = $this->dbh->escape_string($_REQUEST["fid"]); + @$next_unread_feed = $_REQUEST["nuf"]; + @$offset = $_REQUEST["skip"]; + @$vgroup_last_feed = $_REQUEST["vgrlf"]; + $order_by = $_REQUEST["order_by"]; + $check_first_id = $_REQUEST["fid"]; if (is_numeric($feed)) $feed = (int) $feed; @@ -867,21 +855,30 @@ class Feeds extends Handler_Protected { return; } - $result = false; - + $sth = false; if ($feed < LABEL_BASE_INDEX) { + $label_feed = Labels::feed_to_label_id($feed); - $result = $this->dbh->query("SELECT id FROM ttrss_labels2 WHERE - id = '$label_feed' AND owner_uid = " . $_SESSION['uid']); + + $sth = $this->pdo->prepare("SELECT id FROM ttrss_labels2 WHERE + id = ? AND owner_uid = ?"); + $sth->execute([$label_feed, $_SESSION['uid']]); + } else if (!$cat_view && is_numeric($feed) && $feed > 0) { - $result = $this->dbh->query("SELECT id FROM ttrss_feeds WHERE - id = '$feed' AND owner_uid = " . $_SESSION['uid']); + + $sth = $this->pdo->prepare("SELECT id FROM ttrss_feeds WHERE + id = ? AND owner_uid = ?"); + $sth->execute([$feed, $_SESSION['uid']]); + } else if ($cat_view && is_numeric($feed) && $feed > 0) { - $result = $this->dbh->query("SELECT id FROM ttrss_feed_categories WHERE - id = '$feed' AND owner_uid = " . $_SESSION['uid']); + + $sth = $this->pdo->prepare("SELECT id FROM ttrss_feed_categories WHERE + id = ? AND owner_uid = ?"); + + $sth->execute([$feed, $_SESSION['uid']]); } - if ($result && $this->dbh->num_rows($result) == 0) { + if ($sth && !$sth->fetch()) { print json_encode($this->generate_error_feed(__("Feed not found."))); return; } @@ -898,14 +895,16 @@ class Feeds extends Handler_Protected { /* bump login timestamp if needed */ if (time() - $_SESSION["last_login_update"] > 3600) { - $this->dbh->query("UPDATE ttrss_users SET last_login = NOW() WHERE id = " . - $_SESSION["uid"]); + $sth = $this->pdo->prepare("UPDATE ttrss_users SET last_login = NOW() WHERE id = ?"); + $sth->execute([$_SESSION['uid']]); + $_SESSION["last_login_update"] = time(); } if (!$cat_view && is_numeric($feed) && $feed > 0) { - $this->dbh->query("UPDATE ttrss_feeds SET last_viewed = NOW() - WHERE id = '$feed' AND owner_uid = ".$_SESSION["uid"]); + $sth = $this->pdo->prepare("UPDATE ttrss_feeds SET last_viewed = NOW() + WHERE id = ? AND owner_uid = ?"); + $sth->execute([$feed, $_SESSION['uid']]); } $reply['headlines'] = array(); @@ -915,7 +914,7 @@ class Feeds extends Handler_Protected { switch ($order_by) { case "title": - $override_order = "ttrss_entries.title"; + $override_order = "ttrss_entries.title, date_entered, updated"; break; case "date_reverse": $override_order = "score DESC, date_entered, updated"; @@ -976,18 +975,21 @@ class Feeds extends Handler_Protected { $reply['headlines']['content'] .= "

"; - $result = $this->dbh->query("SELECT ".SUBSTRING_FOR_DATE."(MAX(last_updated), 1, 19) AS last_updated FROM ttrss_feeds - WHERE owner_uid = " . $_SESSION['uid']); + $sth = $this->pdo->prepare("SELECT ".SUBSTRING_FOR_DATE."(MAX(last_updated), 1, 19) AS last_updated FROM ttrss_feeds + WHERE owner_uid = ?"); + $sth->execute([$_SESSION['uid']]); + $row = $sth->fetch(); - $last_updated = $this->dbh->fetch_result($result, 0, "last_updated"); - $last_updated = make_local_datetime($last_updated, false); + $last_updated = make_local_datetime($row["last_updated"], false); $reply['headlines']['content'] .= sprintf(__("Feeds last updated at %s"), $last_updated); - $result = $this->dbh->query("SELECT COUNT(id) AS num_errors - FROM ttrss_feeds WHERE last_error != '' AND owner_uid = ".$_SESSION["uid"]); + $sth = $this->pdo->prepare("SELECT COUNT(id) AS num_errors + FROM ttrss_feeds WHERE last_error != '' AND owner_uid = ?"); + $sth->execute([$_SESSION['uid']]); + $row = $sth->fetch(); - $num_errors = $this->dbh->fetch_result($result, 0, "num_errors"); + $num_errors = $row["num_errors"]; if ($num_errors > 0) { $reply['headlines']['content'] .= "
"; @@ -1104,7 +1106,7 @@ class Feeds extends Handler_Protected { function feedBrowser() { if (defined('_DISABLE_FEED_BROWSER') && _DISABLE_FEED_BROWSER) return; - $browser_search = $this->dbh->escape_string($_REQUEST["search"]); + $browser_search = $_REQUEST["search"]; print_hidden("op", "rpc"); print_hidden("method", "updateFeedBrowser"); @@ -1150,7 +1152,7 @@ class Feeds extends Handler_Protected { } function search() { - $this->params = explode(":", $this->dbh->escape_string($_REQUEST["param"]), 2); + $this->params = explode(":", $_REQUEST["param"], 2); $active_feed_id = sprintf("%d", $this->params[0]); $is_cat = $this->params[1] != "false"; @@ -1199,10 +1201,10 @@ class Feeds extends Handler_Protected { ?> - + Feed Debugger - +

Feed Debugger: getFeedTitle($feed_id) ?>

@@ -1237,9 +1239,10 @@ class Feeds extends Handler_Protected { if (!$owner_uid) $owner_uid = $_SESSION['uid']; + $pdo = Db::pdo(); + // Todo: all this interval stuff needs some generic generator function - $date_qpart = "false"; $search_qpart = is_array($search) && $search[0] ? search_to_sql($search[0], $search[1])[0] : 'true'; switch ($mode) { @@ -1284,50 +1287,55 @@ class Feeds extends Handler_Protected { $cat_qpart = "cat_id IS NULL"; } - db_query("UPDATE ttrss_user_entries + $sth = $pdo->prepare("UPDATE ttrss_user_entries SET unread = false, last_read = NOW() WHERE ref_id IN (SELECT id FROM (SELECT DISTINCT id FROM ttrss_entries, ttrss_user_entries WHERE ref_id = id - AND owner_uid = $owner_uid AND unread = true AND feed_id IN + AND owner_uid = ? AND unread = true AND feed_id IN (SELECT id FROM ttrss_feeds WHERE $cat_qpart) AND $date_qpart AND $search_qpart) as tmp)"); + $sth->execute([$owner_uid]); } else if ($feed == -2) { - db_query("UPDATE ttrss_user_entries + $sth = $pdo->prepare("UPDATE ttrss_user_entries SET unread = false,last_read = NOW() WHERE (SELECT COUNT(*) FROM ttrss_user_labels2, ttrss_entries WHERE article_id = ref_id AND id = ref_id AND $date_qpart AND $search_qpart) > 0 - AND unread = true AND owner_uid = $owner_uid"); + AND unread = true AND owner_uid = ?"); + $sth->execute([$owner_uid]); } } else if ($feed > 0) { - db_query("UPDATE ttrss_user_entries + $sth = $pdo->prepare("UPDATE ttrss_user_entries SET unread = false, last_read = NOW() WHERE ref_id IN (SELECT id FROM (SELECT DISTINCT id FROM ttrss_entries, ttrss_user_entries WHERE ref_id = id - AND owner_uid = $owner_uid AND unread = true AND feed_id = $feed AND $date_qpart AND $search_qpart) as tmp)"); + AND owner_uid = ? AND unread = true AND feed_id = ? AND $date_qpart AND $search_qpart) as tmp)"); + $sth->execute([$owner_uid, $feed]); } else if ($feed < 0 && $feed > LABEL_BASE_INDEX) { // special, like starred if ($feed == -1) { - db_query("UPDATE ttrss_user_entries + $sth = $pdo->prepare("UPDATE ttrss_user_entries SET unread = false, last_read = NOW() WHERE ref_id IN (SELECT id FROM (SELECT DISTINCT id FROM ttrss_entries, ttrss_user_entries WHERE ref_id = id - AND owner_uid = $owner_uid AND unread = true AND marked = true AND $date_qpart AND $search_qpart) as tmp)"); + AND owner_uid = ? AND unread = true AND marked = true AND $date_qpart AND $search_qpart) as tmp)"); + $sth->execute([$owner_uid]); } if ($feed == -2) { - db_query("UPDATE ttrss_user_entries + $sth = $pdo->prepare("UPDATE ttrss_user_entries SET unread = false, last_read = NOW() WHERE ref_id IN (SELECT id FROM (SELECT DISTINCT id FROM ttrss_entries, ttrss_user_entries WHERE ref_id = id - AND owner_uid = $owner_uid AND unread = true AND published = true AND $date_qpart AND $search_qpart) as tmp)"); + AND owner_uid = ? AND unread = true AND published = true AND $date_qpart AND $search_qpart) as tmp)"); + $sth->execute([$owner_uid]); } if ($feed == -3) { - $intl = get_pref("FRESH_ARTICLE_MAX_AGE"); + $intl = (int) get_pref("FRESH_ARTICLE_MAX_AGE"); if (DB_TYPE == "pgsql") { $match_part = "date_entered > NOW() - INTERVAL '$intl hour' "; @@ -1336,43 +1344,47 @@ class Feeds extends Handler_Protected { INTERVAL $intl HOUR) "; } - db_query("UPDATE ttrss_user_entries + $sth = $pdo->prepare("UPDATE ttrss_user_entries SET unread = false, last_read = NOW() WHERE ref_id IN (SELECT id FROM (SELECT DISTINCT id FROM ttrss_entries, ttrss_user_entries WHERE ref_id = id - AND owner_uid = $owner_uid AND score >= 0 AND unread = true AND $date_qpart AND $match_part AND $search_qpart) as tmp)"); + AND owner_uid = ? AND score >= 0 AND unread = true AND $date_qpart AND $match_part AND $search_qpart) as tmp)"); + $sth->execute([$owner_uid]); } if ($feed == -4) { - db_query("UPDATE ttrss_user_entries + $sth = $pdo->prepare("UPDATE ttrss_user_entries SET unread = false, last_read = NOW() WHERE ref_id IN (SELECT id FROM (SELECT DISTINCT id FROM ttrss_entries, ttrss_user_entries WHERE ref_id = id - AND owner_uid = $owner_uid AND unread = true AND $date_qpart AND $search_qpart) as tmp)"); + AND owner_uid = ? AND unread = true AND $date_qpart AND $search_qpart) as tmp)"); + $sth->execute([$owner_uid]); } } else if ($feed < LABEL_BASE_INDEX) { // label $label_id = Labels::feed_to_label_id($feed); - db_query("UPDATE ttrss_user_entries + $sth = $pdo->prepare("UPDATE ttrss_user_entries SET unread = false, last_read = NOW() WHERE ref_id IN (SELECT id FROM (SELECT DISTINCT ttrss_entries.id FROM ttrss_entries, ttrss_user_entries, ttrss_user_labels2 WHERE ref_id = id - AND label_id = '$label_id' AND ref_id = article_id - AND owner_uid = $owner_uid AND unread = true AND $date_qpart AND $search_qpart) as tmp)"); + AND label_id = ? AND ref_id = article_id + AND owner_uid = ? AND unread = true AND $date_qpart AND $search_qpart) as tmp)"); + $sth->execute([$label_id, $owner_uid]); } CCache::update($feed, $owner_uid, $cat_view); } else { // tag - db_query("UPDATE ttrss_user_entries + $sth = $pdo->prepare("UPDATE ttrss_user_entries SET unread = false, last_read = NOW() WHERE ref_id IN (SELECT id FROM (SELECT DISTINCT ttrss_entries.id FROM ttrss_entries, ttrss_user_entries, ttrss_tags WHERE ref_id = ttrss_entries.id - AND post_int_id = int_id AND tag_name = '$feed' - AND ttrss_user_entries.owner_uid = $owner_uid AND unread = true AND $date_qpart AND $search_qpart) as tmp)"); + AND post_int_id = int_id AND tag_name = ? + AND ttrss_user_entries.owner_uid = ? AND unread = true AND $date_qpart AND $search_qpart) as tmp)"); + $sth->execute([$feed, $owner_uid]); } } @@ -1383,6 +1395,8 @@ class Feeds extends Handler_Protected { $n_feed = (int) $feed; $need_entries = false; + $pdo = Db::pdo(); + if (!$owner_uid) $owner_uid = $_SESSION["uid"]; if ($unread_only) { @@ -1391,19 +1405,23 @@ class Feeds extends Handler_Protected { $unread_qpart = "true"; } + $match_part = ""; + if ($is_cat) { return Feeds::getCategoryUnread($n_feed, $owner_uid); } else if ($n_feed == -6) { return 0; } else if ($feed != "0" && $n_feed == 0) { - $feed = db_escape_string($feed); - - $result = db_query("SELECT SUM((SELECT COUNT(int_id) + $sth = $pdo->prepare("SELECT SUM((SELECT COUNT(int_id) FROM ttrss_user_entries,ttrss_entries WHERE int_id = post_int_id AND ref_id = id AND $unread_qpart)) AS count FROM ttrss_tags - WHERE owner_uid = $owner_uid AND tag_name = '$feed'"); - return db_fetch_result($result, 0, "count"); + WHERE owner_uid = ? AND tag_name = ?"); + + $sth->execute([$owner_uid, $feed]); + $row = $sth->fetch(); + + return $row["count"]; } else if ($n_feed == -1) { $match_part = "marked = true"; @@ -1412,7 +1430,7 @@ class Feeds extends Handler_Protected { } else if ($n_feed == -3) { $match_part = "unread = true AND score >= 0"; - $intl = get_pref("FRESH_ARTICLE_MAX_AGE", $owner_uid); + $intl = (int) get_pref("FRESH_ARTICLE_MAX_AGE", $owner_uid); if (DB_TYPE == "pgsql") { $match_part .= " AND date_entered > NOW() - INTERVAL '$intl hour' "; @@ -1437,7 +1455,6 @@ class Feeds extends Handler_Protected { $label_id = Labels::feed_to_label_id($feed); return Feeds::getLabelUnread($label_id, $owner_uid); - } if ($match_part) { @@ -1450,25 +1467,26 @@ class Feeds extends Handler_Protected { $from_where = ""; } - $query = "SELECT count(int_id) AS unread + $sth = $pdo->prepare("SELECT count(int_id) AS unread FROM $from_qpart WHERE - $unread_qpart AND $from_where ($match_part) AND ttrss_user_entries.owner_uid = $owner_uid"; - - //echo "[$feed/$query]\n"; + $unread_qpart AND $from_where ($match_part) AND ttrss_user_entries.owner_uid = ?"); + $sth->execute([$owner_uid]); + $row = $sth->fetch(); - $result = db_query($query); + return $row["unread"]; } else { - $result = db_query("SELECT COUNT(post_int_id) AS unread + $sth = $pdo->prepare("SELECT COUNT(post_int_id) AS unread FROM ttrss_tags,ttrss_user_entries,ttrss_entries - WHERE tag_name = '$feed' AND post_int_id = int_id AND ref_id = ttrss_entries.id - AND $unread_qpart AND ttrss_tags.owner_uid = " . $owner_uid); - } + WHERE tag_name = ? AND post_int_id = int_id AND ref_id = ttrss_entries.id + AND $unread_qpart AND ttrss_tags.owner_uid = ,"); - $unread = db_fetch_result($result, 0, "unread"); + $sth->execute([$feed, $owner_uid]); + $row = $sth->fetch(); - return $unread; + return $row["unread"]; + } } /** @@ -1490,6 +1508,8 @@ class Feeds extends Handler_Protected { global $fetch_last_error; global $fetch_last_error_content; + $pdo = Db::pdo(); + $url = fix_url($url); if (!$url || !validate_feed_url($url)) return array("code" => 2); @@ -1526,32 +1546,35 @@ class Feeds extends Handler_Protected { $cat_qpart = "'$cat_id'"; } - $result = db_query( - "SELECT id FROM ttrss_feeds - WHERE feed_url = '$url' AND owner_uid = ".$_SESSION["uid"]); + if (!(int)$cat_id) $cat_id = null; - $auth_pass = db_escape_string($auth_pass); + $sth = $pdo->prepare("SELECT id FROM ttrss_feeds + WHERE feed_url = ? AND owner_uid = ?"); + $sth->execute([$url, $_SESSION['uid']]); - if (db_num_rows($result) == 0) { - $result = db_query( + if ($row = $sth->fetch()) { + return array("code" => 0, "feed_id" => (int) $row["id"]); + } else { + $sth = $pdo->prepare( "INSERT INTO ttrss_feeds (owner_uid,feed_url,title,cat_id, auth_login,auth_pass,update_method,auth_pass_encrypted) - VALUES ('".$_SESSION["uid"]."', '$url', - '[Unknown]', $cat_qpart, '$auth_login', '$auth_pass', 0, false)"); + VALUES (?, ?, ?, ?, ?, ?, 0, false)"); - $result = db_query( - "SELECT id FROM ttrss_feeds WHERE feed_url = '$url' - AND owner_uid = " . $_SESSION["uid"]); + $sth->execute([$_SESSION['uid'], $url, "[Unknown]", $cat_id, $auth_login, $auth_pass]); - $feed_id = db_fetch_result($result, 0, "id"); + $sth = $pdo->prepare("SELECT id FROM ttrss_feeds WHERE feed_url = ? + AND owner_uid = ?"); + $sth->execute([$url, $_SESSION['uid']]); + $row = $sth->fetch(); + + $feed_id = $row["id"]; if ($feed_id) { RSSUtils::set_basic_feed_info($feed_id); } return array("code" => 1, "feed_id" => (int) $feed_id); - } else { - return array("code" => 0, "feed_id" => (int) db_fetch_result($result, 0, "id")); + } } @@ -1589,6 +1612,8 @@ class Feeds extends Handler_Protected { } static function getFeedTitle($id, $cat = false) { + $pdo = Db::pdo(); + if ($cat) { return Feeds::getCategoryTitle($id); } else if ($id == -1) { @@ -1604,21 +1629,29 @@ class Feeds extends Handler_Protected { } else if ($id == -6) { return __("Recently read"); } else if ($id < LABEL_BASE_INDEX) { + $label_id = Labels::feed_to_label_id($id); - $result = db_query("SELECT caption FROM ttrss_labels2 WHERE id = '$label_id'"); - if (db_num_rows($result) == 1) { - return db_fetch_result($result, 0, "caption"); + + $sth = $pdo->prepare("SELECT caption FROM ttrss_labels2 WHERE id = ?"); + $sth->execute([$label_id]); + + if ($row = $sth->fetch()) { + return $row["caption"]; } else { return "Unknown label ($label_id)"; } } else if (is_numeric($id) && $id > 0) { - $result = db_query("SELECT title FROM ttrss_feeds WHERE id = '$id'"); - if (db_num_rows($result) == 1) { - return db_fetch_result($result, 0, "title"); + + $sth = $pdo->prepare("SELECT title FROM ttrss_feeds WHERE id = ?"); + $sth->execute([$id]); + + if ($row = $sth->fetch()) { + return $row["title"]; } else { return "Unknown feed ($id)"; } + } else { return $id; } @@ -1628,19 +1661,20 @@ class Feeds extends Handler_Protected { if (!$owner_uid) $owner_uid = $_SESSION["uid"]; + $pdo = Db::pdo(); + if ($cat >= 0) { - if ($cat != 0) { - $cat_query = "cat_id = '$cat'"; - } else { - $cat_query = "cat_id IS NULL"; - } + if (!$cat) $cat = null; + + $sth = $pdo->prepare("SELECT id FROM ttrss_feeds + WHERE (cat_id = :cat OR (:cat IS NULL AND cat_id IS NULL)) + AND owner_uid = :uid"); - $result = db_query("SELECT id FROM ttrss_feeds WHERE $cat_query - AND owner_uid = " . $owner_uid); + $sth->execute([":cat" => $cat, ":uid" => $owner_uid]); $cat_feeds = array(); - while ($line = db_fetch_assoc($result)) { + while ($line = $sth->fetch()) { array_push($cat_feeds, "feed_id = " . $line["id"]); } @@ -1648,15 +1682,16 @@ class Feeds extends Handler_Protected { $match_part = implode(" OR ", $cat_feeds); - $result = db_query("SELECT COUNT(int_id) AS unread + $sth = $pdo->prepare("SELECT COUNT(int_id) AS unread FROM ttrss_user_entries WHERE unread = true AND ($match_part) - AND owner_uid = " . $owner_uid); + AND owner_uid = ?"); + $sth->execute([$owner_uid]); $unread = 0; # this needs to be rewritten - while ($line = db_fetch_assoc($result)) { + while ($line = $sth->fetch()) { $unread += $line["unread"]; } @@ -1665,16 +1700,14 @@ class Feeds extends Handler_Protected { return getFeedUnread(-1) + getFeedUnread(-2) + getFeedUnread(-3) + getFeedUnread(0); } else if ($cat == -2) { - $result = db_query(" - SELECT COUNT(unread) AS unread FROM + $sth = $pdo->prepare("SELECT COUNT(unread) AS unread FROM ttrss_user_entries, ttrss_user_labels2 WHERE article_id = ref_id AND unread = true - AND ttrss_user_entries.owner_uid = '$owner_uid'"); - - $unread = db_fetch_result($result, 0, "unread"); - - return $unread; + AND ttrss_user_entries.owner_uid = ?"); + $sth->execute([$owner_uid]); + $row = $sth->fetch(); + return $row["unread"]; } } @@ -1682,12 +1715,15 @@ class Feeds extends Handler_Protected { static function getCategoryChildrenUnread($cat, $owner_uid = false) { if (!$owner_uid) $owner_uid = $_SESSION["uid"]; - $result = db_query("SELECT id FROM ttrss_feed_categories WHERE parent_cat = '$cat' - AND owner_uid = $owner_uid"); + $pdo = Db::pdo(); + + $sth = $pdo->prepare("SELECT id FROM ttrss_feed_categories WHERE parent_cat = ? + AND owner_uid = ?"); + $sth->execute([$cat, $owner_uid]); $unread = 0; - while ($line = db_fetch_assoc($result)) { + while ($line = $sth->fetch()) { $unread += Feeds::getCategoryUnread($line["id"], $owner_uid); $unread += Feeds::getCategoryChildrenUnread($line["id"], $owner_uid); } @@ -1697,16 +1733,16 @@ class Feeds extends Handler_Protected { static function getGlobalUnread($user_id = false) { - if (!$user_id) { - $user_id = $_SESSION["uid"]; - } + if (!$user_id) $user_id = $_SESSION["uid"]; - $result = db_query("SELECT SUM(value) AS c_id FROM ttrss_counters_cache - WHERE owner_uid = '$user_id' AND feed_id > 0"); + $pdo = Db::pdo(); - $c_id = db_fetch_result($result, 0, "c_id"); + $sth = $pdo->prepare("SELECT SUM(value) AS c_id FROM ttrss_counters_cache + WHERE owner_uid = ? AND feed_id > 0"); + $sth->execute([$user_id]); + $row = $sth->fetch(); - return $c_id; + return $row["c_id"]; } static function getCategoryTitle($cat_id) { @@ -1717,11 +1753,14 @@ class Feeds extends Handler_Protected { return __("Labels"); } else { - $result = db_query("SELECT title FROM ttrss_feed_categories WHERE - id = '$cat_id'"); + $pdo = Db::pdo(); - if (db_num_rows($result) == 1) { - return db_fetch_result($result, 0, "title"); + $sth = $pdo->prepare("SELECT title FROM ttrss_feed_categories WHERE + id = ?"); + $sth->execute([$cat_id]); + + if ($row = $sth->fetch()) { + return $row["title"]; } else { return __("Uncategorized"); } @@ -1731,11 +1770,15 @@ class Feeds extends Handler_Protected { static function getLabelUnread($label_id, $owner_uid = false) { if (!$owner_uid) $owner_uid = $_SESSION["uid"]; - $result = db_query("SELECT COUNT(ref_id) AS unread FROM ttrss_user_entries, ttrss_user_labels2 - WHERE owner_uid = '$owner_uid' AND unread = true AND label_id = '$label_id' AND article_id = ref_id"); + $pdo = Db::pdo(); + + $sth = $pdo->prepare("SELECT COUNT(ref_id) AS unread FROM ttrss_user_entries, ttrss_user_labels2 + WHERE owner_uid = ? AND unread = true AND label_id = ? AND article_id = ref_id"); - if (db_num_rows($result) != 0) { - return db_fetch_result($result, 0, "unread"); + $sth->execute([$owner_uid, $label_id]); + + if ($row = $sth->fetch()) { + return $row["unread"]; } else { return 0; } @@ -1743,6 +1786,11 @@ class Feeds extends Handler_Protected { static function queryFeedHeadlines($params) { + $pdo = Db::pdo(); + + // WARNING: due to highly dynamic nature of this query its going to quote parameters + // right before adding them to SQL part + $feed = $params["feed"]; $limit = isset($params["limit"]) ? $params["limit"] : 30; $view_mode = $params["view_mode"]; @@ -1762,7 +1810,7 @@ class Feeds extends Handler_Protected { $skip_first_id_check = isset($params["skip_first_id_check"]) ? $params["skip_first_id_check"] : false; $ext_tables_part = ""; - $query_strategy_part = ""; + $limit_query_part = ""; $search_words = array(); @@ -1782,7 +1830,7 @@ class Feeds extends Handler_Protected { } if ($since_id) { - $since_id_part = "ttrss_entries.id > $since_id AND "; + $since_id_part = "ttrss_entries.id > ".$pdo->quote($since_id)." AND "; } else { $since_id_part = ""; } @@ -1822,7 +1870,7 @@ class Feeds extends Handler_Protected { } if ($limit > 0) { - $limit_query_part = "LIMIT " . $limit; + $limit_query_part = "LIMIT " . (int)$limit; } $allow_archived = false; @@ -1848,7 +1896,7 @@ class Feeds extends Handler_Protected { implode(",", $subcats).")"; } else { - $query_strategy_part = "cat_id = '$feed'"; + $query_strategy_part = "cat_id = " . $pdo->quote($feed); } } else { @@ -1858,7 +1906,7 @@ class Feeds extends Handler_Protected { $vfeed_query_part = "ttrss_feeds.title AS feed_title,"; } else { - $query_strategy_part = "feed_id = '$feed'"; + $query_strategy_part = "feed_id = " . $pdo->quote($feed); } } else if ($feed == 0 && !$cat_view) { // archive virtual feed $query_strategy_part = "feed_id IS NULL"; @@ -1913,7 +1961,7 @@ class Feeds extends Handler_Protected { } else if ($feed == -3) { // fresh virtual feed $query_strategy_part = "unread = true AND score >= 0"; - $intl = get_pref("FRESH_ARTICLE_MAX_AGE", $owner_uid); + $intl = (int) get_pref("FRESH_ARTICLE_MAX_AGE", $owner_uid); if (DB_TYPE == "pgsql") { $query_strategy_part .= " AND date_entered > NOW() - INTERVAL '$intl hour' "; @@ -1929,7 +1977,7 @@ class Feeds extends Handler_Protected { } else if ($feed <= LABEL_BASE_INDEX) { // labels $label_id = Labels::feed_to_label_id($feed); - $query_strategy_part = "label_id = '$label_id' AND + $query_strategy_part = "label_id = ".$pdo->quote($label_id)." AND ttrss_labels2.id = ttrss_user_labels2.label_id AND ttrss_user_labels2.article_id = ref_id"; @@ -1955,8 +2003,6 @@ class Feeds extends Handler_Protected { $vfeed_query_part = $override_vfeed; } - $feed_title = ""; - if ($search) { $feed_title = T_sprintf("Search results: %s", $search); } else { @@ -1964,24 +2010,25 @@ class Feeds extends Handler_Protected { $feed_title = Feeds::getCategoryTitle($feed); } else { if (is_numeric($feed) && $feed > 0) { - $result = db_query("SELECT title,site_url,last_error,last_updated - FROM ttrss_feeds WHERE id = '$feed' AND owner_uid = $owner_uid"); - - $feed_title = db_fetch_result($result, 0, "title"); - $feed_site_url = db_fetch_result($result, 0, "site_url"); - $last_error = db_fetch_result($result, 0, "last_error"); - $last_updated = db_fetch_result($result, 0, "last_updated"); + $ssth = $pdo->prepare("SELECT title,site_url,last_error,last_updated + FROM ttrss_feeds WHERE id = ? AND owner_uid = ?"); + $ssth->execute([$feed, $owner_uid]); + $row = $ssth->fetch(); + + $feed_title = $row["title"]; + $feed_site_url = $row["site_url"]; + $last_error = $row["last_error"]; + $last_updated = $row["last_updated"]; } else { $feed_title = Feeds::getFeedTitle($feed); } } } - $content_query_part = "content, "; if ($limit_query_part) { - $offset_query_part = "OFFSET $offset"; + $offset_query_part = "OFFSET " . (int)$offset; } else { $offset_query_part = ""; } @@ -1990,9 +2037,9 @@ class Feeds extends Handler_Protected { // proper override_order applied above if ($vfeed_query_part && !$ignore_vfeed_group && get_pref('VFEED_GROUP_BY_FEED', $owner_uid)) { if (!$override_order) { - $order_by = "ttrss_feeds.title, $order_by"; + $order_by = "ttrss_feeds.title, ".$pdo->quote($order_by); } else { - $order_by = "ttrss_feeds.title, $override_order"; + $order_by = "ttrss_feeds.title, ".$pdo->quote($override_order); } } @@ -2045,7 +2092,7 @@ class Feeds extends Handler_Protected { $from_qpart WHERE $feed_check_qpart - ttrss_user_entries.owner_uid = '$owner_uid' AND + ttrss_user_entries.owner_uid = ".$pdo->quote($owner_uid)." AND $search_query_part $start_ts_query_part $since_id_part @@ -2056,9 +2103,10 @@ class Feeds extends Handler_Protected { print $query; } - $result = db_query($query); - if ($result && db_num_rows($result) > 0) { - $first_id = (int)db_fetch_result($result, 0, "id"); + $res = $pdo->query($query); + + if ($row = $res->fetch()) { + $first_id = (int)$row["id"]; if ($offset > 0 && $first_id && $check_first_id && $first_id != $check_first_id) { return array(-1, $feed_title, $feed_site_url, $last_error, $last_updated, $search_words, $first_id); @@ -2091,7 +2139,7 @@ class Feeds extends Handler_Protected { $from_qpart WHERE $feed_check_qpart - ttrss_user_entries.owner_uid = '$owner_uid' AND + ttrss_user_entries.owner_uid = ".$pdo->quote($owner_uid)." AND $search_query_part $start_ts_query_part $view_query_part @@ -2101,7 +2149,7 @@ class Feeds extends Handler_Protected { if ($_REQUEST["debug"]) print $query; - $result = db_query($query); + $res = $pdo->query($query); } else { // browsing by tag @@ -2135,9 +2183,9 @@ class Feeds extends Handler_Protected { FROM ttrss_entries, ttrss_user_entries, ttrss_tags WHERE ref_id = ttrss_entries.id AND - ttrss_user_entries.owner_uid = $owner_uid AND + ttrss_user_entries.owner_uid = ".$pdo->quote($owner_uid)." AND post_int_id = int_id AND - tag_name = '$feed' AND + tag_name = ".$pdo->quote($feed)." AND $view_query_part $search_query_part $query_strategy_part ORDER BY $order_by @@ -2145,20 +2193,23 @@ class Feeds extends Handler_Protected { if ($_REQUEST["debug"]) print $query; - $result = db_query($query); + $res = $pdo->query($query); } - return array($result, $feed_title, $feed_site_url, $last_error, $last_updated, $search_words, $first_id); + return array($res, $feed_title, $feed_site_url, $last_error, $last_updated, $search_words, $first_id); } static function getParentCategories($cat, $owner_uid) { $rv = array(); - $result = db_query("SELECT parent_cat FROM ttrss_feed_categories - WHERE id = '$cat' AND parent_cat IS NOT NULL AND owner_uid = $owner_uid"); + $pdo = Db::pdo(); - while ($line = db_fetch_assoc($result)) { + $sth = $pdo->prepare("SELECT parent_cat FROM ttrss_feed_categories + WHERE id = ? AND parent_cat IS NOT NULL AND owner_uid = ?"); + $sth->execute([$cat, $owner_uid]); + + while ($line = $sth->fetch()) { array_push($rv, $line["parent_cat"]); $rv = array_merge($rv, Feeds::getParentCategories($line["parent_cat"], $owner_uid)); } @@ -2169,10 +2220,13 @@ class Feeds extends Handler_Protected { static function getChildCategories($cat, $owner_uid) { $rv = array(); - $result = db_query("SELECT id FROM ttrss_feed_categories - WHERE parent_cat = '$cat' AND owner_uid = $owner_uid"); + $pdo = Db::pdo(); + + $sth = $pdo->prepare("SELECT id FROM ttrss_feed_categories + WHERE parent_cat = ? AND owner_uid = ?"); + $sth->execute([$cat, $owner_uid]); - while ($line = db_fetch_assoc($result)) { + while ($line = $sth->fetch()) { array_push($rv, $line["id"]); $rv = array_merge($rv, Feeds::getChildCategories($line["id"], $owner_uid)); } @@ -2181,11 +2235,14 @@ class Feeds extends Handler_Protected { } static function getFeedCategory($feed) { - $result = db_query("SELECT cat_id FROM ttrss_feeds - WHERE id = '$feed'"); + $pdo = Db::pdo(); + + $sth = $pdo->prepare("SELECT cat_id FROM ttrss_feeds + WHERE id = ?"); + $sth->execute([$feed]); - if (db_num_rows($result) > 0) { - return db_fetch_result($result, 0, "cat_id"); + if ($row = $sth->fetch()) { + return $row["cat_id"]; } else { return false; }