"; $reply .= ""; $reply .= ""; if ($feed_site_url) { $last_updated = T_sprintf("Last updated: %s", $feed_last_updated); $target = "target=\"_blank\""; $reply .= "". truncate_string($feed_title,30).""; if ($error) { $reply .= " (Error)"; } } else { $reply .= $feed_title; } $reply .= ""; $reply .= " "; $reply .= ""; // left part $reply .= __('Select:')." ".__('All').", ".__('Unread').", ".__('Invert').", ".__('None').""; $reply .= " "; $reply .= ""; //$reply .= ""; //$reply .= "get_hooks(PluginHost::HOOK_HEADLINE_TOOLBAR_BUTTON) as $p) { echo $p->hook_headline_toolbar_button($feed_id, $is_cat); } return $reply; } private function format_headlines_list($feed, $method, $view_mode, $limit, $cat_view, $next_unread_feed, $offset, $vgr_last_feed = false, $override_order = false, $include_children = false) { if (isset($_REQUEST["DevForceUpdate"])) header("Content-Type: text/plain"); $disable_cache = false; $reply = array(); $rgba_cache = array(); $timing_info = microtime(true); $topmost_article_ids = array(); if (!$offset) $offset = 0; if ($method == "undefined") $method = ""; $method_split = explode(":", $method); if ($method == "ForceUpdate" && $feed > 0 && is_numeric($feed)) { // Update the feed if required with some basic flood control $result = $this->dbh->query( "SELECT cache_images,".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated FROM ttrss_feeds WHERE id = '$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 (!$cache_images && time() - $last_updated > 120 || isset($_REQUEST['DevForceUpdate'])) { include "rssfuncs.php"; update_rss_feed($feed, true, true); } else { $this->dbh->query("UPDATE ttrss_feeds SET last_updated = '1970-01-01', last_update_started = '1970-01-01' WHERE id = '$feed'"); } } } if ($method_split[0] == "MarkAllReadGR") { catchup_feed($method_split[1], false); } // 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"); if ($this->dbh->num_rows($result) == 0) { $reply['content'] = "
".__('Feed not found.')."
"; } } @$search = $this->dbh->escape_string($_REQUEST["query"]); if ($search) { $disable_cache = true; } @$search_mode = $this->dbh->escape_string($_REQUEST["search_mode"]); if ($_REQUEST["debug"]) $timing_info = print_checkpoint("H0", $timing_info); // error_log("format_headlines_list: [" . $feed . "] method [" . $method . "]"); if($search_mode == '' && $method != '' ){ $search_mode = $method; } // error_log("search_mode: " . $search_mode); 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)); // function queryFeedHeadlines($feed, $limit, $view_mode, $cat_view, $search, $search_mode, $override_order = false, $offset = 0, $owner_uid = 0, $filter = false, $since_id = 0, $include_children = false, $ignore_vfeed_group = false) { if ($handler) { $options = array( "limit" => $limit, "view_mode" => $view_mode, "cat_view" => $cat_view, "search" => $search, "search_mode" => $search_mode, "override_order" => $override_order, "offset" => $offset, "owner_uid" => $_SESSION["uid"], "filter" => false, "since_id" => 0, "include_children" => $include_children); $qfh_ret = $handler->get_headlines(PluginHost::feed_to_pfeed_id($feed), $options); } } else { $qfh_ret = queryFeedHeadlines($feed, $limit, $view_mode, $cat_view, $search, $search_mode, $override_order, $offset, 0, false, 0, $include_children); } if ($_REQUEST["debug"]) $timing_info = print_checkpoint("H1", $timing_info); $result = $qfh_ret[0]; $feed_title = $qfh_ret[1]; $feed_site_url = $qfh_ret[2]; $last_error = $qfh_ret[3]; $last_updated = strpos($qfh_ret[4], '1970-') === FALSE ? make_local_datetime($qfh_ret[4], false) : __("Never"); $vgroup_last_feed = $vgr_last_feed; $reply['toolbar'] = $this->format_headline_subtoolbar($feed_site_url, $feed_title, $feed, $cat_view, $search, $search_mode, $view_mode, $last_error, $last_updated); $headlines_count = $this->dbh->num_rows($result); /* if (get_pref('COMBINED_DISPLAY_MODE')) { $button_plugins = array(); foreach (explode(",", ARTICLE_BUTTON_PLUGINS) as $p) { $pclass = "button_" . trim($p); if (class_exists($pclass)) { $plugin = new $pclass(); array_push($button_plugins, $plugin); } } } */ if ($this->dbh->num_rows($result) > 0) { $lnum = $offset; $num_unread = 0; $cur_feed_title = ''; $fresh_intl = get_pref("FRESH_ARTICLE_MAX_AGE") * 60 * 60; if ($_REQUEST["debug"]) $timing_info = print_checkpoint("PS", $timing_info); $expand_cdm = get_pref('CDM_EXPANDED'); while ($line = $this->dbh->fetch_assoc($result)) { $class = ($lnum % 2) ? "even" : "odd"; $id = $line["id"]; $feed_id = $line["feed_id"]; $label_cache = $line["label_cache"]; $labels = false; if ($label_cache) { $label_cache = json_decode($label_cache, true); if ($label_cache) { if ($label_cache["no-labels"] == 1) $labels = array(); else $labels = $label_cache; } } if (!is_array($labels)) $labels = get_article_labels($id); $labels_str = ""; $labels_str .= format_article_labels($labels, $id); $labels_str .= ""; if (count($topmost_article_ids) < 3) { array_push($topmost_article_ids, $id); } if (sql_bool_to_bool($line["unread"])) { $class .= " Unread"; ++$num_unread; } if (sql_bool_to_bool($line["marked"])) { $marked_pic = "\"Unstar"; $class .= " marked"; } else { $marked_pic = "\"Star"; } if (sql_bool_to_bool($line["published"])) { $published_pic = "\"Unpublish"; $class .= " published"; } else { $published_pic = "\"Publish"; } # $content_link = "" . # $line["title"] . ""; # $content_link = "" . # $line["title"] . ""; # $content_link = "" . # $line["title"] . ""; $updated_fmt = make_local_datetime($line["updated"], false); $date_entered_fmt = T_sprintf("Imported at %s", make_local_datetime($line["date_entered"], false)); if (get_pref('SHOW_CONTENT_PREVIEW')) { $content_preview = truncate_string(strip_tags($line["content_preview"]), 250); } $score = $line["score"]; $score_pic = "images/" . get_score_pic($score); /* $score_title = __("(Click to change)"); $score_pic = ""; */ $score_pic = ""; if ($score > 500) { $hlc_suffix = "H"; } else if ($score < -100) { $hlc_suffix = "L"; } else { $hlc_suffix = ""; } $entry_author = $line["author"]; if ($entry_author) { $entry_author = " — $entry_author"; } $has_feed_icon = feed_has_icon($feed_id); if ($has_feed_icon) { $feed_icon_img = "\"\""; } else { $feed_icon_img = "\"\""; } $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"; if ($fav_color && $fav_color != 'fail') { if (!isset($rgba_cache[$feed_id])) { $rgba_cache[$feed_id] = join(",", _color_unpack($fav_color)); } $rgba = $rgba_cache[$feed_id]; if (sql_bool_to_bool($line["unread"])) $endalpha = '0.3'; else $endalpha = '0.1'; // W3C definition seems to work in FF and Chrome $row_background = "background-image : linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba($rgba, $endalpha) 100%);"; /* $row_background = "background-image : -moz-linear-gradient(left, rgba(255, 255, 255, 0) 50%, rgba($rgba, 0.2) 100%);". "background-image : linear-gradient(to right, rgba(255, 255, 255, 0) 50%, rgba($rgba, 0.2) 100%);"; "background-image : -webkit-gradient(linear, left top, right top, color-stop(50%, rgba(255,255,255,0)), color-stop(100%, rgba($rgba, 0.2)));"; */ } else { $row_background = ""; } if (!get_pref('COMBINED_DISPLAY_MODE')) { if (get_pref('VFEED_GROUP_BY_FEED')) { if ($feed_id != $vgroup_last_feed && $line["feed_title"]) { $cur_feed_title = $line["feed_title"]; $vgroup_last_feed = $feed_id; $cur_feed_title = htmlspecialchars($cur_feed_title); $vf_catchup_link = "(".__('Mark as read').")"; $reply['content'] .= "
". "
$feed_icon_img
". "". $line["feed_title"]." $vf_catchup_link
"; } } $mouseover_attrs = "onmouseover='postMouseIn(event, $id)' onmouseout='postMouseOut($id)'"; $reply['content'] .= "
"; $reply['content'] .= "
"; $reply['content'] .= ""; $reply['content'] .= "$marked_pic"; $reply['content'] .= "$published_pic"; $reply['content'] .= "
"; $reply['content'] .= "
"; $reply['content'] .= "" . truncate_string($line["title"], 200); if (get_pref('SHOW_CONTENT_PREVIEW')) { if ($content_preview) { $reply['content'] .= " - $content_preview"; } } $reply['content'] .= ""; $reply['content'] .= $labels_str; $reply['content'] .= "
"; $reply['content'] .= ""; if (!get_pref('VFEED_GROUP_BY_FEED')) { if (@$line["feed_title"]) { $reply['content'] .= ""; } } $reply['content'] .= "$updated_fmt "; $reply['content'] .= "
"; $reply['content'] .= $score_pic; if ($line["feed_title"] && !get_pref('VFEED_GROUP_BY_FEED')) { $reply['content'] .= " $feed_icon_img"; } $reply['content'] .= "
"; $reply['content'] .= "
"; } else { if ($line["tag_cache"]) $tags = explode(",", $line["tag_cache"]); else $tags = false; $line["content"] = sanitize($line["content_preview"], sql_bool_to_bool($line['hide_images']), false, $entry_site_url); foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_RENDER_ARTICLE_CDM) as $p) { $line = $p->hook_render_article_cdm($line); } if (get_pref('VFEED_GROUP_BY_FEED') && $line["feed_title"]) { if ($feed_id != $vgroup_last_feed) { $cur_feed_title = $line["feed_title"]; $vgroup_last_feed = $feed_id; $cur_feed_title = htmlspecialchars($cur_feed_title); $vf_catchup_link = "(".__('mark as read').")"; $has_feed_icon = feed_has_icon($feed_id); if ($has_feed_icon) { $feed_icon_img = "\"\""; } else { //$feed_icon_img = "\"\""; } $reply['content'] .= "
". "
$feed_icon_img
". "". $line["feed_title"]." $vf_catchup_link
"; } } $mouseover_attrs = "onmouseover='postMouseIn(event, $id)' onmouseout='postMouseOut($id)'"; $expanded_class = $expand_cdm ? "expanded" : "expandable"; $reply['content'] .= "
"; $reply['content'] .= "
"; $reply['content'] .= "
"; $reply['content'] .= ""; $reply['content'] .= "$marked_pic"; $reply['content'] .= "$published_pic"; $reply['content'] .= "
"; $reply['content'] .= " ". $line["title"] . " $entry_author"; $reply['content'] .= $labels_str; $reply['content'] .= ""; if (!$expand_cdm) $content_hidden = "style=\"display : none\""; else $excerpt_hidden = "style=\"display : none\""; $reply['content'] .= " - $content_preview"; $reply['content'] .= ""; if (!get_pref('VFEED_GROUP_BY_FEED')) { if (@$line["feed_title"]) { $reply['content'] .= ""; } } $reply['content'] .= " $updated_fmt"; $reply['content'] .= "
"; $reply['content'] .= "$score_pic"; if (!get_pref("VFEED_GROUP_BY_FEED") && $line["feed_title"]) { $reply['content'] .= "$feed_icon_img"; } $reply['content'] .= "
"; $reply['content'] .= "
"; $reply['content'] .= "
"; $reply['content'] .= "
"; if ($line['note']) { $reply['content'] .= format_article_note($id, $line['note']); } $reply['content'] .= "
"; $reply['content'] .= "
"; if ($line["orig_feed_id"]) { $tmp_result = $this->dbh->query("SELECT * FROM ttrss_archived_feeds WHERE id = ".$line["orig_feed_id"]); if ($this->dbh->num_rows($tmp_result) != 0) { $reply['content'] .= "
"; $reply['content'] .= __("Originally from:"); $reply['content'] .= " "; $tmp_line = $this->dbh->fetch_assoc($tmp_result); $reply['content'] .= "" . $tmp_line['title'] . ""; $reply['content'] .= " "; $reply['content'] .= ""; $reply['content'] .= ""; $reply['content'] .= "
"; } } $reply['content'] .= ""; // if (!$expand_cdm) { $reply['content'] .= ""; $reply['content'] .= htmlspecialchars($line["content"]); $reply['content'] .= ""; foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_ARTICLE_LEFT_BUTTON) as $p) { $reply['content'] .= $p->hook_article_left_button($line); } $tags_str = format_tags_string($tags, $id); $reply['content'] .= "Tags $tags_str (+)"; $num_comments = $line["num_comments"]; $entry_comments = ""; if ($num_comments > 0) { if ($line["comments"]) { $comments_url = htmlspecialchars($line["comments"]); } else { $comments_url = htmlspecialchars($line["link"]); } $entry_comments = "$num_comments comments"; } else { if ($line["comments"] && $line["link"] != $line["comments"]) { $entry_comments = "comments"; } } if ($entry_comments) $reply['content'] .= " ($entry_comments)"; $reply['content'] .= "
"; // $reply['content'] .= "$marked_pic"; // $reply['content'] .= "$published_pic"; foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_ARTICLE_BUTTON) as $p) { $reply['content'] .= $p->hook_article_button($line); } $reply['content'] .= "
"; $reply['content'] .= "
"; $reply['content'] .= "
"; $reply['content'] .= "
"; } ++$lnum; } if ($_REQUEST["debug"]) $timing_info = print_checkpoint("PE", $timing_info); } else { $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"; $reply['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']); $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); $result = $this->dbh->query("SELECT COUNT(id) AS num_errors FROM ttrss_feeds WHERE last_error != '' AND owner_uid = ".$_SESSION["uid"]); $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 ($_REQUEST["debug"]) $timing_info = print_checkpoint("H2", $timing_info); return array($topmost_article_ids, $headlines_count, $feed, $disable_cache, $vgroup_last_feed, $reply); } function catchupAll() { $this->dbh->query("UPDATE ttrss_user_entries SET last_read = NOW(), unread = false WHERE unread = true AND owner_uid = " . $_SESSION["uid"]); ccache_zero_all($_SESSION["uid"]); } function view() { $timing_info = microtime(true); $reply = array(); if ($_REQUEST["debug"]) $timing_info = print_checkpoint("0", $timing_info); $omode = $this->dbh->escape_string($_REQUEST["omode"]); $feed = $this->dbh->escape_string($_REQUEST["feed"]); $method = $this->dbh->escape_string($_REQUEST["m"]); $view_mode = $this->dbh->escape_string($_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"]); if (is_numeric($feed)) $feed = (int) $feed; /* Feed -5 is a special case: it is used to display auxiliary information * when there's nothing to load - e.g. no stuff in fresh feed */ if ($feed == -5) { print json_encode($this->generate_dashboard_feed()); return; } $result = false; if ($feed < LABEL_BASE_INDEX) { $label_feed = feed_to_label_id($feed); $result = $this->dbh->query("SELECT id FROM ttrss_labels2 WHERE id = '$label_feed' AND owner_uid = " . $_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']); } 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']); } if ($result && $this->dbh->num_rows($result) == 0) { print json_encode($this->generate_error_feed(__("Feed not found."))); return; } /* Updating a label ccache means recalculating all of the caches * so for performance reasons we don't do that here */ if ($feed >= 0) { ccache_update($feed, $_SESSION["uid"], $cat_view); } set_pref("_DEFAULT_VIEW_MODE", $view_mode); set_pref("_DEFAULT_VIEW_ORDER_BY", $order_by); /* 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"]); $_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"]); } $reply['headlines'] = array(); if (!$next_unread_feed) $reply['headlines']['id'] = $feed; else $reply['headlines']['id'] = $next_unread_feed; $reply['headlines']['is_cat'] = (bool) $cat_view; $override_order = false; switch ($order_by) { case "title": $override_order = "ttrss_entries.title"; break; case "date_reverse": $override_order = "date_entered, updated"; break; case "feed_dates": $override_order = "updated DESC"; break; } if ($_REQUEST["debug"]) $timing_info = print_checkpoint("04", $timing_info); $ret = $this->format_headlines_list($feed, $method, $view_mode, $limit, $cat_view, $next_unread_feed, $offset, $vgroup_last_feed, $override_order, true); //$topmost_article_ids = $ret[0]; $headlines_count = $ret[1]; $returned_feed = $ret[2]; $disable_cache = $ret[3]; $vgroup_last_feed = $ret[4]; $reply['headlines']['content'] =& $ret[5]['content']; $reply['headlines']['toolbar'] =& $ret[5]['toolbar']; if ($_REQUEST["debug"]) $timing_info = print_checkpoint("05", $timing_info); $reply['headlines-info'] = array("count" => (int) $headlines_count, "vgroup_last_feed" => $vgroup_last_feed, "disable_cache" => (bool) $disable_cache); if ($_REQUEST["debug"]) $timing_info = print_checkpoint("30", $timing_info); $reply['runtime-info'] = make_runtime_info(); print json_encode($reply); } private function generate_dashboard_feed() { $reply = array(); $reply['headlines']['id'] = -5; $reply['headlines']['is_cat'] = false; $reply['headlines']['toolbar'] = ''; $reply['headlines']['content'] = "
".__('No feed selected.'); $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']); $last_updated = $this->dbh->fetch_result($result, 0, "last_updated"); $last_updated = make_local_datetime($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"]); $num_errors = $this->dbh->fetch_result($result, 0, "num_errors"); if ($num_errors > 0) { $reply['headlines']['content'] .= "
"; $reply['headlines']['content'] .= "". __('Some feeds have update errors (click for details)').""; } $reply['headlines']['content'] .= "

"; $reply['headlines-info'] = array("count" => 0, "vgroup_last_feed" => '', "unread" => 0, "disable_cache" => true); return $reply; } private function generate_error_feed($error) { $reply = array(); $reply['headlines']['id'] = -6; $reply['headlines']['is_cat'] = false; $reply['headlines']['toolbar'] = ''; $reply['headlines']['content'] = "
". $error . "
"; $reply['headlines-info'] = array("count" => 0, "vgroup_last_feed" => '', "unread" => 0, "disable_cache" => true); return $reply; } function quickAddFeed() { print ""; print ""; print "
".__("Feed or site URL")."
"; print "
"; print "
"; print ""; print "
"; if (get_pref('ENABLE_FEED_CATS')) { print __('Place in category:') . " "; print_feed_cat_select("cat", false, 'dojoType="dijit.form.Select"'); } print "
"; print ''; print ""; print "
"; print ""; print "
"; if (!(defined('_DISABLE_FEED_BROWSER') && _DISABLE_FEED_BROWSER)) { print ""; } print "
"; //return; } function feedBrowser() { if (defined('_DISABLE_FEED_BROWSER') && _DISABLE_FEED_BROWSER) return; $browser_search = $this->dbh->escape_string($_REQUEST["search"]); print ""; print ""; print "
"; print " "; print __("limit:"); print " "; print "
"; $owner_uid = $_SESSION["uid"]; require_once "feedbrowser.php"; print ""; print "
"; } function search() { $this->params = explode(":", $this->dbh->escape_string($_REQUEST["param"]), 2); $active_feed_id = sprintf("%d", $this->params[0]); $is_cat = $this->params[1] != "false"; print "
".__('Look for')."
"; print "
"; print ""; print "
".__('Limit search to:')." "; print ""; print "
"; print "
"; if (!SPHINX_ENABLED) { print "
Search syntax
"; } print "
"; } } ?>