update 1.14
|
@ -4,7 +4,7 @@ Tiny Tiny RSS
|
||||||
Web-based news feed aggregator, designed to allow you to read news from
|
Web-based news feed aggregator, designed to allow you to read news from
|
||||||
any location, while feeling as close to a real desktop application as possible.
|
any location, while feeling as close to a real desktop application as possible.
|
||||||
|
|
||||||
http://tt-rss.org
|
http://tt-rss.org (http://mirror.tt-rss.org)
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
0
source/cache/export/.empty
vendored
Executable file
0
source/cache/images/.empty
vendored
Executable file
0
source/cache/js/.empty
vendored
Executable file
0
source/cache/simplepie/.empty
vendored
Executable file
0
source/cache/upload/.empty
vendored
Normal file
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
class API extends Handler {
|
class API extends Handler {
|
||||||
|
|
||||||
const API_LEVEL = 7;
|
const API_LEVEL = 9;
|
||||||
|
|
||||||
const STATUS_OK = 0;
|
const STATUS_OK = 0;
|
||||||
const STATUS_ERR = 1;
|
const STATUS_ERR = 1;
|
||||||
|
@ -77,6 +77,7 @@ class API extends Handler {
|
||||||
$this->wrap(self::STATUS_OK, array("session_id" => session_id(),
|
$this->wrap(self::STATUS_OK, array("session_id" => session_id(),
|
||||||
"api_level" => self::API_LEVEL));
|
"api_level" => self::API_LEVEL));
|
||||||
} else { // else we are not logged in
|
} else { // else we are not logged in
|
||||||
|
user_error("Failed login attempt for $login from {$_SERVER['REMOTE_ADDR']}", E_USER_WARNING);
|
||||||
$this->wrap(self::STATUS_ERR, array("error" => "LOGIN_ERROR"));
|
$this->wrap(self::STATUS_ERR, array("error" => "LOGIN_ERROR"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -199,9 +200,13 @@ class API extends Handler {
|
||||||
$include_nested = sql_bool_to_bool($_REQUEST["include_nested"]);
|
$include_nested = sql_bool_to_bool($_REQUEST["include_nested"]);
|
||||||
$sanitize_content = !isset($_REQUEST["sanitize"]) ||
|
$sanitize_content = !isset($_REQUEST["sanitize"]) ||
|
||||||
sql_bool_to_bool($_REQUEST["sanitize"]);
|
sql_bool_to_bool($_REQUEST["sanitize"]);
|
||||||
|
$force_update = sql_bool_to_bool($_REQUEST["force_update"]);
|
||||||
|
|
||||||
$override_order = false;
|
$override_order = false;
|
||||||
switch ($_REQUEST["order_by"]) {
|
switch ($_REQUEST["order_by"]) {
|
||||||
|
case "title":
|
||||||
|
$override_order = "ttrss_entries.title";
|
||||||
|
break;
|
||||||
case "date_reverse":
|
case "date_reverse":
|
||||||
$override_order = "score DESC, date_entered, updated";
|
$override_order = "score DESC, date_entered, updated";
|
||||||
break;
|
break;
|
||||||
|
@ -218,7 +223,7 @@ class API extends Handler {
|
||||||
$headlines = $this->api_get_headlines($feed_id, $limit, $offset,
|
$headlines = $this->api_get_headlines($feed_id, $limit, $offset,
|
||||||
$filter, $is_cat, $show_excerpt, $show_content, $view_mode, $override_order,
|
$filter, $is_cat, $show_excerpt, $show_content, $view_mode, $override_order,
|
||||||
$include_attachments, $since_id, $search, $search_mode,
|
$include_attachments, $since_id, $search, $search_mode,
|
||||||
$include_nested, $sanitize_content);
|
$include_nested, $sanitize_content, $force_update);
|
||||||
|
|
||||||
$this->wrap(self::STATUS_OK, $headlines);
|
$this->wrap(self::STATUS_OK, $headlines);
|
||||||
} else {
|
} else {
|
||||||
|
@ -310,7 +315,7 @@ class API extends Handler {
|
||||||
if ($article_id) {
|
if ($article_id) {
|
||||||
|
|
||||||
$query = "SELECT id,title,link,content,feed_id,comments,int_id,
|
$query = "SELECT id,title,link,content,feed_id,comments,int_id,
|
||||||
marked,unread,published,score,
|
marked,unread,published,score,note,lang,
|
||||||
".SUBSTRING_FOR_DATE."(updated,1,16) as updated,
|
".SUBSTRING_FOR_DATE."(updated,1,16) as updated,
|
||||||
author,(SELECT title FROM ttrss_feeds WHERE id = feed_id) AS feed_title
|
author,(SELECT title FROM ttrss_feeds WHERE id = feed_id) AS feed_title
|
||||||
FROM ttrss_entries,ttrss_user_entries
|
FROM ttrss_entries,ttrss_user_entries
|
||||||
|
@ -342,7 +347,9 @@ class API extends Handler {
|
||||||
"feed_id" => $line["feed_id"],
|
"feed_id" => $line["feed_id"],
|
||||||
"attachments" => $attachments,
|
"attachments" => $attachments,
|
||||||
"score" => (int)$line["score"],
|
"score" => (int)$line["score"],
|
||||||
"feed_title" => $line["feed_title"]
|
"feed_title" => $line["feed_title"],
|
||||||
|
"note" => $line["note"],
|
||||||
|
"lang" => $line["lang"]
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_RENDER_ARTICLE_API) as $p) {
|
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_RENDER_ARTICLE_API) as $p) {
|
||||||
|
@ -423,7 +430,7 @@ class API extends Handler {
|
||||||
|
|
||||||
$checked = false;
|
$checked = false;
|
||||||
foreach ($article_labels as $al) {
|
foreach ($article_labels as $al) {
|
||||||
if ($al[0] == $line['id']) {
|
if (feed_to_label_id($al[0]) == $line['id']) {
|
||||||
$checked = true;
|
$checked = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -447,7 +454,7 @@ class API extends Handler {
|
||||||
$assign = (bool) $this->dbh->escape_string($_REQUEST['assign']) == "true";
|
$assign = (bool) $this->dbh->escape_string($_REQUEST['assign']) == "true";
|
||||||
|
|
||||||
$label = $this->dbh->escape_string(label_find_caption(
|
$label = $this->dbh->escape_string(label_find_caption(
|
||||||
$label_id, $_SESSION["uid"]));
|
feed_to_label_id($label_id), $_SESSION["uid"]));
|
||||||
|
|
||||||
$num_updated = 0;
|
$num_updated = 0;
|
||||||
|
|
||||||
|
@ -511,7 +518,7 @@ class API extends Handler {
|
||||||
if ($unread || !$unread_only) {
|
if ($unread || !$unread_only) {
|
||||||
|
|
||||||
$row = array(
|
$row = array(
|
||||||
"id" => $cv["id"],
|
"id" => (int) $cv["id"],
|
||||||
"title" => $cv["description"],
|
"title" => $cv["description"],
|
||||||
"unread" => $cv["counter"],
|
"unread" => $cv["counter"],
|
||||||
"cat_id" => -2,
|
"cat_id" => -2,
|
||||||
|
@ -557,7 +564,7 @@ class API extends Handler {
|
||||||
|
|
||||||
if ($unread || !$unread_only) {
|
if ($unread || !$unread_only) {
|
||||||
$row = array(
|
$row = array(
|
||||||
"id" => $line["id"],
|
"id" => (int) $line["id"],
|
||||||
"title" => $line["title"],
|
"title" => $line["title"],
|
||||||
"unread" => $unread,
|
"unread" => $unread,
|
||||||
"is_cat" => true,
|
"is_cat" => true,
|
||||||
|
@ -626,7 +633,28 @@ class API extends Handler {
|
||||||
$filter, $is_cat, $show_excerpt, $show_content, $view_mode, $order,
|
$filter, $is_cat, $show_excerpt, $show_content, $view_mode, $order,
|
||||||
$include_attachments, $since_id,
|
$include_attachments, $since_id,
|
||||||
$search = "", $search_mode = "",
|
$search = "", $search_mode = "",
|
||||||
$include_nested = false, $sanitize_content = true) {
|
$include_nested = false, $sanitize_content = true, $force_update = false) {
|
||||||
|
|
||||||
|
if ($force_update && $feed_id > 0 && is_numeric($feed_id)) {
|
||||||
|
// Update the feed if required with some basic flood control
|
||||||
|
|
||||||
|
$result = db_query(
|
||||||
|
"SELECT cache_images,".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
|
||||||
|
FROM ttrss_feeds WHERE id = '$feed_id'");
|
||||||
|
|
||||||
|
if (db_num_rows($result) != 0) {
|
||||||
|
$last_updated = strtotime(db_fetch_result($result, 0, "last_updated"));
|
||||||
|
$cache_images = sql_bool_to_bool(db_fetch_result($result, 0, "cache_images"));
|
||||||
|
|
||||||
|
if (!$cache_images && time() - $last_updated > 120) {
|
||||||
|
include "rssfuncs.php";
|
||||||
|
update_rss_feed($feed_id, true, true);
|
||||||
|
} else {
|
||||||
|
db_query("UPDATE ttrss_feeds SET last_updated = '1970-01-01', last_update_started = '1970-01-01'
|
||||||
|
WHERE id = '$feed_id'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$qfh_ret = queryFeedHeadlines($feed_id, $limit,
|
$qfh_ret = queryFeedHeadlines($feed_id, $limit,
|
||||||
$view_mode, $is_cat, $search, $search_mode,
|
$view_mode, $is_cat, $search, $search_mode,
|
||||||
|
@ -638,7 +666,7 @@ class API extends Handler {
|
||||||
$headlines = array();
|
$headlines = array();
|
||||||
|
|
||||||
while ($line = db_fetch_assoc($result)) {
|
while ($line = db_fetch_assoc($result)) {
|
||||||
$line["content_preview"] = truncate_string(strip_tags($line["content_preview"]), 100);
|
$line["content_preview"] = truncate_string(strip_tags($line["content"]), 100);
|
||||||
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
|
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
|
||||||
$line = $p->hook_query_headlines($line, 100, true);
|
$line = $p->hook_query_headlines($line, 100, true);
|
||||||
}
|
}
|
||||||
|
@ -700,6 +728,8 @@ class API extends Handler {
|
||||||
$headline_row["author"] = $line["author"];
|
$headline_row["author"] = $line["author"];
|
||||||
|
|
||||||
$headline_row["score"] = (int)$line["score"];
|
$headline_row["score"] = (int)$line["score"];
|
||||||
|
$headline_row["note"] = $line["note"];
|
||||||
|
$headline_row["lang"] = $line["lang"];
|
||||||
|
|
||||||
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_RENDER_ARTICLE_API) as $p) {
|
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_RENDER_ARTICLE_API) as $p) {
|
||||||
$headline_row = $p->hook_render_article_api(array("headline" => $headline_row));
|
$headline_row = $p->hook_render_article_api(array("headline" => $headline_row));
|
||||||
|
|
|
@ -30,7 +30,6 @@ class Article extends Handler_Protected {
|
||||||
$id = $this->dbh->escape_string($_REQUEST["id"]);
|
$id = $this->dbh->escape_string($_REQUEST["id"]);
|
||||||
$cids = explode(",", $this->dbh->escape_string($_REQUEST["cids"]));
|
$cids = explode(",", $this->dbh->escape_string($_REQUEST["cids"]));
|
||||||
$mode = $this->dbh->escape_string($_REQUEST["mode"]);
|
$mode = $this->dbh->escape_string($_REQUEST["mode"]);
|
||||||
$omode = $this->dbh->escape_string($_REQUEST["omode"]);
|
|
||||||
|
|
||||||
// in prefetch mode we only output requested cids, main article
|
// in prefetch mode we only output requested cids, main article
|
||||||
// just gets marked as read (it already exists in client cache)
|
// just gets marked as read (it already exists in client cache)
|
||||||
|
@ -108,7 +107,7 @@ class Article extends Handler_Protected {
|
||||||
|
|
||||||
// only check for our user data here, others might have shared this with different content etc
|
// only check for our user data here, others might have shared this with different content etc
|
||||||
$result = db_query("SELECT id FROM ttrss_entries, ttrss_user_entries WHERE
|
$result = db_query("SELECT id FROM ttrss_entries, ttrss_user_entries WHERE
|
||||||
link = '$url' AND ref_id = id AND owner_uid = '$owner_uid' LIMIT 1");
|
guid = '$guid' AND ref_id = id AND owner_uid = '$owner_uid' LIMIT 1");
|
||||||
|
|
||||||
if (db_num_rows($result) != 0) {
|
if (db_num_rows($result) != 0) {
|
||||||
$ref_id = db_fetch_result($result, 0, "id");
|
$ref_id = db_fetch_result($result, 0, "id");
|
||||||
|
|
|
@ -16,7 +16,6 @@ class Dlg extends Handler_Protected {
|
||||||
print __("If you have imported labels and/or filters, you might need to reload preferences to see your new data.") . "</p>";
|
print __("If you have imported labels and/or filters, you might need to reload preferences to see your new data.") . "</p>";
|
||||||
|
|
||||||
print "<div class=\"prefFeedOPMLHolder\">";
|
print "<div class=\"prefFeedOPMLHolder\">";
|
||||||
$owner_uid = $_SESSION["uid"];
|
|
||||||
|
|
||||||
$this->dbh->query("BEGIN");
|
$this->dbh->query("BEGIN");
|
||||||
|
|
||||||
|
@ -176,7 +175,7 @@ class Dlg extends Handler_Protected {
|
||||||
|
|
||||||
while ($row = $this->dbh->fetch_assoc($result)) {
|
while ($row = $this->dbh->fetch_assoc($result)) {
|
||||||
$tmp = htmlspecialchars($row["tag_name"]);
|
$tmp = htmlspecialchars($row["tag_name"]);
|
||||||
print "<option value=\"" . str_replace(" ", "%20", $tmp) . "\">$tmp</option>";
|
print "<option value=\"$tmp\">$tmp</option>";
|
||||||
}
|
}
|
||||||
|
|
||||||
print "</select>";
|
print "</select>";
|
||||||
|
|
|
@ -4,5 +4,7 @@ class FeedEnclosure {
|
||||||
public $type;
|
public $type;
|
||||||
public $length;
|
public $length;
|
||||||
public $title;
|
public $title;
|
||||||
|
public $height;
|
||||||
|
public $width;
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -43,9 +43,9 @@ class FeedItem_Atom extends FeedItem_Common {
|
||||||
$base = $this->xpath->evaluate("string(ancestor-or-self::*[@xml:base][1]/@xml:base)", $link);
|
$base = $this->xpath->evaluate("string(ancestor-or-self::*[@xml:base][1]/@xml:base)", $link);
|
||||||
|
|
||||||
if ($base)
|
if ($base)
|
||||||
return rewrite_relative_url($base, $link->getAttribute("href"));
|
return rewrite_relative_url($base, trim($link->getAttribute("href")));
|
||||||
else
|
else
|
||||||
return $link->getAttribute("href");
|
return trim($link->getAttribute("href"));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ class FeedItem_Atom extends FeedItem_Common {
|
||||||
$title = $this->elem->getElementsByTagName("title")->item(0);
|
$title = $this->elem->getElementsByTagName("title")->item(0);
|
||||||
|
|
||||||
if ($title) {
|
if ($title) {
|
||||||
return $title->nodeValue;
|
return trim($title->nodeValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,13 +106,13 @@ class FeedItem_Atom extends FeedItem_Common {
|
||||||
|
|
||||||
foreach ($categories as $cat) {
|
foreach ($categories as $cat) {
|
||||||
if ($cat->hasAttribute("term"))
|
if ($cat->hasAttribute("term"))
|
||||||
array_push($cats, $cat->getAttribute("term"));
|
array_push($cats, trim($cat->getAttribute("term")));
|
||||||
}
|
}
|
||||||
|
|
||||||
$categories = $this->xpath->query("dc:subject", $this->elem);
|
$categories = $this->xpath->query("dc:subject", $this->elem);
|
||||||
|
|
||||||
foreach ($categories as $cat) {
|
foreach ($categories as $cat) {
|
||||||
array_push($cats, $cat->nodeValue);
|
array_push($cats, trim($cat->nodeValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $cats;
|
return $cats;
|
||||||
|
@ -137,7 +137,7 @@ class FeedItem_Atom extends FeedItem_Common {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$enclosures = $this->xpath->query("media:content | media:group/media:content", $this->elem);
|
$enclosures = $this->xpath->query("media:content", $this->elem);
|
||||||
|
|
||||||
foreach ($enclosures as $enclosure) {
|
foreach ($enclosures as $enclosure) {
|
||||||
$enc = new FeedEnclosure();
|
$enc = new FeedEnclosure();
|
||||||
|
@ -145,6 +145,8 @@ class FeedItem_Atom extends FeedItem_Common {
|
||||||
$enc->type = $enclosure->getAttribute("type");
|
$enc->type = $enclosure->getAttribute("type");
|
||||||
$enc->link = $enclosure->getAttribute("url");
|
$enc->link = $enclosure->getAttribute("url");
|
||||||
$enc->length = $enclosure->getAttribute("length");
|
$enc->length = $enclosure->getAttribute("length");
|
||||||
|
$enc->height = $enclosure->getAttribute("height");
|
||||||
|
$enc->width = $enclosure->getAttribute("width");
|
||||||
|
|
||||||
$desc = $this->xpath->query("media:description", $enclosure)->item(0);
|
$desc = $this->xpath->query("media:description", $enclosure)->item(0);
|
||||||
if ($desc) $enc->title = strip_tags($desc->nodeValue);
|
if ($desc) $enc->title = strip_tags($desc->nodeValue);
|
||||||
|
@ -152,6 +154,46 @@ class FeedItem_Atom extends FeedItem_Common {
|
||||||
array_push($encs, $enc);
|
array_push($encs, $enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$enclosures = $this->xpath->query("media:group", $this->elem);
|
||||||
|
|
||||||
|
foreach ($enclosures as $enclosure) {
|
||||||
|
$enc = new FeedEnclosure();
|
||||||
|
|
||||||
|
$content = $this->xpath->query("media:content", $enclosure)->item(0);
|
||||||
|
|
||||||
|
if ($content) {
|
||||||
|
$enc->type = $content->getAttribute("type");
|
||||||
|
$enc->link = $content->getAttribute("url");
|
||||||
|
$enc->length = $content->getAttribute("length");
|
||||||
|
$enc->height = $content->getAttribute("height");
|
||||||
|
$enc->width = $content->getAttribute("width");
|
||||||
|
|
||||||
|
$desc = $this->xpath->query("media:description", $content)->item(0);
|
||||||
|
if ($desc) {
|
||||||
|
$enc->title = strip_tags($desc->nodeValue);
|
||||||
|
} else {
|
||||||
|
$desc = $this->xpath->query("media:description", $enclosure)->item(0);
|
||||||
|
if ($desc) $enc->title = strip_tags($desc->nodeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
array_push($encs, $enc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$enclosures = $this->xpath->query("media:thumbnail", $this->elem);
|
||||||
|
|
||||||
|
foreach ($enclosures as $enclosure) {
|
||||||
|
$enc = new FeedEnclosure();
|
||||||
|
|
||||||
|
$enc->type = "image/generic";
|
||||||
|
$enc->link = $enclosure->getAttribute("url");
|
||||||
|
$enc->height = $enclosure->getAttribute("height");
|
||||||
|
$enc->width = $enclosure->getAttribute("width");
|
||||||
|
|
||||||
|
array_push($encs, $enc);
|
||||||
|
}
|
||||||
|
|
||||||
return $encs;
|
return $encs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,13 +44,26 @@ abstract class FeedItem_Common extends FeedItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo
|
|
||||||
function get_comments_url() {
|
function get_comments_url() {
|
||||||
|
//RSS only. Use a query here to avoid namespace clashes (e.g. with slash).
|
||||||
|
//might give a wrong result if a default namespace was declared (possible with XPath 2.0)
|
||||||
|
$com_url = $this->xpath->query("comments", $this->elem)->item(0);
|
||||||
|
|
||||||
|
if($com_url)
|
||||||
|
return $com_url->nodeValue;
|
||||||
|
|
||||||
|
//Atom Threading Extension (RFC 4685) stuff. Could be used in RSS feeds, so it's in common.
|
||||||
|
//'text/html' for type is too restrictive?
|
||||||
|
$com_url = $this->xpath->query("atom:link[@rel='replies' and contains(@type,'text/html')]/@href", $this->elem)->item(0);
|
||||||
|
|
||||||
|
if($com_url)
|
||||||
|
return $com_url->nodeValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_comments_count() {
|
function get_comments_count() {
|
||||||
$comments = $this->xpath->query("slash:comments", $this->elem)->item(0);
|
//also query for ATE stuff here
|
||||||
|
$query = "slash:comments|thread:total|atom:link[@rel='replies']/@thread:count";
|
||||||
|
$comments = $this->xpath->query($query, $this->elem)->item(0);
|
||||||
|
|
||||||
if ($comments) {
|
if ($comments) {
|
||||||
return $comments->nodeValue;
|
return $comments->nodeValue;
|
||||||
|
|
|
@ -33,20 +33,20 @@ class FeedItem_RSS extends FeedItem_Common {
|
||||||
|| $link->getAttribute("rel") == "alternate"
|
|| $link->getAttribute("rel") == "alternate"
|
||||||
|| $link->getAttribute("rel") == "standout")) {
|
|| $link->getAttribute("rel") == "standout")) {
|
||||||
|
|
||||||
return $link->getAttribute("href");
|
return trim($link->getAttribute("href"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$link = $this->elem->getElementsByTagName("guid")->item(0);
|
$link = $this->elem->getElementsByTagName("guid")->item(0);
|
||||||
|
|
||||||
if ($link && $link->hasAttributes() && $link->getAttribute("isPermaLink") == "true") {
|
if ($link && $link->hasAttributes() && $link->getAttribute("isPermaLink") == "true") {
|
||||||
return $link->nodeValue;
|
return trim($link->nodeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
$link = $this->elem->getElementsByTagName("link")->item(0);
|
$link = $this->elem->getElementsByTagName("link")->item(0);
|
||||||
|
|
||||||
if ($link) {
|
if ($link) {
|
||||||
return $link->nodeValue;
|
return trim($link->nodeValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,21 +54,26 @@ class FeedItem_RSS extends FeedItem_Common {
|
||||||
$title = $this->elem->getElementsByTagName("title")->item(0);
|
$title = $this->elem->getElementsByTagName("title")->item(0);
|
||||||
|
|
||||||
if ($title) {
|
if ($title) {
|
||||||
return $title->nodeValue;
|
return trim($title->nodeValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_content() {
|
function get_content() {
|
||||||
$content = $this->xpath->query("content:encoded", $this->elem)->item(0);
|
$contentA = $this->xpath->query("content:encoded", $this->elem)->item(0);
|
||||||
|
$contentB = $this->elem->getElementsByTagName("description")->item(0);
|
||||||
|
|
||||||
if ($content) {
|
if ($contentA && !$contentB) {
|
||||||
return $content->nodeValue;
|
return $contentA->nodeValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = $this->elem->getElementsByTagName("description")->item(0);
|
|
||||||
|
|
||||||
if ($content) {
|
if ($contentB && !$contentA) {
|
||||||
return $content->nodeValue;
|
return $contentB->nodeValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($contentA && $contentB) {
|
||||||
|
return mb_strlen($contentA->nodeValue) > mb_strlen($contentB->nodeValue) ?
|
||||||
|
$contentA->nodeValue : $contentB->nodeValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,13 +90,13 @@ class FeedItem_RSS extends FeedItem_Common {
|
||||||
$cats = array();
|
$cats = array();
|
||||||
|
|
||||||
foreach ($categories as $cat) {
|
foreach ($categories as $cat) {
|
||||||
array_push($cats, $cat->nodeValue);
|
array_push($cats, trim($cat->nodeValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
$categories = $this->xpath->query("dc:subject", $this->elem);
|
$categories = $this->xpath->query("dc:subject", $this->elem);
|
||||||
|
|
||||||
foreach ($categories as $cat) {
|
foreach ($categories as $cat) {
|
||||||
array_push($cats, $cat->nodeValue);
|
array_push($cats, trim($cat->nodeValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $cats;
|
return $cats;
|
||||||
|
@ -108,11 +113,13 @@ class FeedItem_RSS extends FeedItem_Common {
|
||||||
$enc->type = $enclosure->getAttribute("type");
|
$enc->type = $enclosure->getAttribute("type");
|
||||||
$enc->link = $enclosure->getAttribute("url");
|
$enc->link = $enclosure->getAttribute("url");
|
||||||
$enc->length = $enclosure->getAttribute("length");
|
$enc->length = $enclosure->getAttribute("length");
|
||||||
|
$enc->height = $enclosure->getAttribute("height");
|
||||||
|
$enc->width = $enclosure->getAttribute("width");
|
||||||
|
|
||||||
array_push($encs, $enc);
|
array_push($encs, $enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
$enclosures = $this->xpath->query("media:content | media:group/media:content", $this->elem);
|
$enclosures = $this->xpath->query("media:content", $this->elem);
|
||||||
|
|
||||||
foreach ($enclosures as $enclosure) {
|
foreach ($enclosures as $enclosure) {
|
||||||
$enc = new FeedEnclosure();
|
$enc = new FeedEnclosure();
|
||||||
|
@ -120,6 +127,8 @@ class FeedItem_RSS extends FeedItem_Common {
|
||||||
$enc->type = $enclosure->getAttribute("type");
|
$enc->type = $enclosure->getAttribute("type");
|
||||||
$enc->link = $enclosure->getAttribute("url");
|
$enc->link = $enclosure->getAttribute("url");
|
||||||
$enc->length = $enclosure->getAttribute("length");
|
$enc->length = $enclosure->getAttribute("length");
|
||||||
|
$enc->height = $enclosure->getAttribute("height");
|
||||||
|
$enc->width = $enclosure->getAttribute("width");
|
||||||
|
|
||||||
$desc = $this->xpath->query("media:description", $enclosure)->item(0);
|
$desc = $this->xpath->query("media:description", $enclosure)->item(0);
|
||||||
if ($desc) $enc->title = strip_tags($desc->nodeValue);
|
if ($desc) $enc->title = strip_tags($desc->nodeValue);
|
||||||
|
@ -127,6 +136,46 @@ class FeedItem_RSS extends FeedItem_Common {
|
||||||
array_push($encs, $enc);
|
array_push($encs, $enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$enclosures = $this->xpath->query("media:group", $this->elem);
|
||||||
|
|
||||||
|
foreach ($enclosures as $enclosure) {
|
||||||
|
$enc = new FeedEnclosure();
|
||||||
|
|
||||||
|
$content = $this->xpath->query("media:content", $enclosure)->item(0);
|
||||||
|
|
||||||
|
if ($content) {
|
||||||
|
$enc->type = $content->getAttribute("type");
|
||||||
|
$enc->link = $content->getAttribute("url");
|
||||||
|
$enc->length = $content->getAttribute("length");
|
||||||
|
$enc->height = $content->getAttribute("height");
|
||||||
|
$enc->width = $content->getAttribute("width");
|
||||||
|
|
||||||
|
$desc = $this->xpath->query("media:description", $content)->item(0);
|
||||||
|
if ($desc) {
|
||||||
|
$enc->title = strip_tags($desc->nodeValue);
|
||||||
|
} else {
|
||||||
|
$desc = $this->xpath->query("media:description", $enclosure)->item(0);
|
||||||
|
if ($desc) $enc->title = strip_tags($desc->nodeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
array_push($encs, $enc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$enclosures = $this->xpath->query("media:thumbnail", $this->elem);
|
||||||
|
|
||||||
|
foreach ($enclosures as $enclosure) {
|
||||||
|
$enc = new FeedEnclosure();
|
||||||
|
|
||||||
|
$enc->type = "image/generic";
|
||||||
|
$enc->link = $enclosure->getAttribute("url");
|
||||||
|
$enc->height = $enclosure->getAttribute("height");
|
||||||
|
$enc->width = $enclosure->getAttribute("width");
|
||||||
|
|
||||||
|
array_push($encs, $enc);
|
||||||
|
}
|
||||||
|
|
||||||
return $encs;
|
return $encs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
class FeedParser {
|
class FeedParser {
|
||||||
private $doc;
|
private $doc;
|
||||||
private $error;
|
private $error;
|
||||||
|
private $libxml_errors = array();
|
||||||
private $items;
|
private $items;
|
||||||
private $link;
|
private $link;
|
||||||
private $title;
|
private $title;
|
||||||
|
@ -12,6 +13,16 @@ class FeedParser {
|
||||||
const FEED_RSS = 1;
|
const FEED_RSS = 1;
|
||||||
const FEED_ATOM = 2;
|
const FEED_ATOM = 2;
|
||||||
|
|
||||||
|
function normalize_encoding($data) {
|
||||||
|
if (preg_match('/^(<\?xml[\t\n\r ].*?encoding[\t\n\r ]*=[\t\n\r ]*["\'])(.+?)(["\'].*?\?>)/s', $data, $matches) === 1) {
|
||||||
|
$data = mb_convert_encoding($data, 'UTF-8', $matches[2]);
|
||||||
|
|
||||||
|
$data = preg_replace('/^<\?xml[\t\n\r ].*?\?>/s', $matches[1] . "UTF-8" . $matches[3] , $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
function __construct($data) {
|
function __construct($data) {
|
||||||
libxml_use_internal_errors(true);
|
libxml_use_internal_errors(true);
|
||||||
libxml_clear_errors();
|
libxml_clear_errors();
|
||||||
|
@ -23,32 +34,8 @@ class FeedParser {
|
||||||
$error = libxml_get_last_error();
|
$error = libxml_get_last_error();
|
||||||
|
|
||||||
// libxml compiled without iconv?
|
// libxml compiled without iconv?
|
||||||
if ($error && ($error->code == 32 || $error->code == 9)) {
|
if ($error && $error->code == 32) {
|
||||||
if (preg_match('/^(<\?xml[\t\n\r ].*?encoding=["\'])(.+?)(["\'].*?\?>)/s', $data, $matches) === 1) {
|
$data = $this->normalize_encoding($data);
|
||||||
$enc = $matches[2];
|
|
||||||
|
|
||||||
$data = mb_convert_encoding($data, 'UTF-8', $enc);
|
|
||||||
|
|
||||||
$data = preg_replace('/^<\?xml[\t\n\r ].*?\?>/s', $matches[1] . "UTF-8" . $matches[3] , $data);
|
|
||||||
|
|
||||||
|
|
||||||
// apparently not all UTF-8 characters are valid for XML
|
|
||||||
$data = preg_replace('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $data);
|
|
||||||
|
|
||||||
if ($data) {
|
|
||||||
libxml_clear_errors();
|
|
||||||
|
|
||||||
$this->doc = new DOMDocument();
|
|
||||||
$this->doc->loadXML($data);
|
|
||||||
|
|
||||||
$error = libxml_get_last_error();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// some terrible invalid unicode entity?
|
|
||||||
if ($error && $error->code == 9) {
|
|
||||||
$data = mb_convert_encoding($data, 'UTF-8', 'UTF-8');
|
|
||||||
|
|
||||||
if ($data) {
|
if ($data) {
|
||||||
libxml_clear_errors();
|
libxml_clear_errors();
|
||||||
|
@ -60,7 +47,41 @@ class FeedParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->error = $this->format_error($error);
|
// some terrible invalid unicode entity?
|
||||||
|
if ($error) {
|
||||||
|
foreach (libxml_get_errors() as $err) {
|
||||||
|
if ($err->code == 9) {
|
||||||
|
// if the source feed is not in utf8, next conversion will fail
|
||||||
|
$data = $this->normalize_encoding($data);
|
||||||
|
|
||||||
|
// remove dangling bytes
|
||||||
|
$data = mb_convert_encoding($data, 'UTF-8', 'UTF-8');
|
||||||
|
|
||||||
|
// apparently not all UTF-8 characters are valid for XML
|
||||||
|
$data = preg_replace('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $data);
|
||||||
|
|
||||||
|
if ($data) {
|
||||||
|
libxml_clear_errors();
|
||||||
|
|
||||||
|
$this->doc = new DOMDocument();
|
||||||
|
$this->doc->loadXML($data);
|
||||||
|
|
||||||
|
$error = libxml_get_last_error();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($error) {
|
||||||
|
foreach (libxml_get_errors() as $error) {
|
||||||
|
if ($error->level == LIBXML_ERR_FATAL) {
|
||||||
|
if(!isset($this->error)) //currently only the first error is reported
|
||||||
|
$this->error = $this->format_error($error);
|
||||||
|
$this->libxml_errors [] = $this->format_error($error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
libxml_clear_errors();
|
libxml_clear_errors();
|
||||||
|
|
||||||
$this->items = array();
|
$this->items = array();
|
||||||
|
@ -76,12 +97,13 @@ class FeedParser {
|
||||||
$xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/');
|
$xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/');
|
||||||
$xpath->registerNamespace('dc', 'http://purl.org/dc/elements/1.1/');
|
$xpath->registerNamespace('dc', 'http://purl.org/dc/elements/1.1/');
|
||||||
$xpath->registerNamespace('content', 'http://purl.org/rss/1.0/modules/content/');
|
$xpath->registerNamespace('content', 'http://purl.org/rss/1.0/modules/content/');
|
||||||
|
$xpath->registerNamespace('thread', 'http://purl.org/syndication/thread/1.0');
|
||||||
|
|
||||||
$this->xpath = $xpath;
|
$this->xpath = $xpath;
|
||||||
|
|
||||||
$root = $xpath->query("(//atom03:feed|//atom:feed|//channel|//rdf:rdf|//rdf:RDF)");
|
$root = $xpath->query("(//atom03:feed|//atom:feed|//channel|//rdf:rdf|//rdf:RDF)");
|
||||||
|
|
||||||
if ($root) {
|
if ($root && $root->length > 0) {
|
||||||
$root = $root->item(0);
|
$root = $root->item(0);
|
||||||
|
|
||||||
if ($root) {
|
if ($root) {
|
||||||
|
@ -183,6 +205,10 @@ class FeedParser {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->title) $this->title = trim($this->title);
|
||||||
|
if ($this->link) $this->link = trim($this->link);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if( !isset($this->error) ){
|
if( !isset($this->error) ){
|
||||||
$this->error = "Unknown/unsupported feed type";
|
$this->error = "Unknown/unsupported feed type";
|
||||||
|
@ -205,6 +231,10 @@ class FeedParser {
|
||||||
return $this->error;
|
return $this->error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function errors() {
|
||||||
|
return $this->libxml_errors;
|
||||||
|
}
|
||||||
|
|
||||||
function get_link() {
|
function get_link() {
|
||||||
return $this->link;
|
return $this->link;
|
||||||
}
|
}
|
||||||
|
@ -226,7 +256,7 @@ class FeedParser {
|
||||||
|
|
||||||
foreach ($links as $link) {
|
foreach ($links as $link) {
|
||||||
if (!$rel || $link->hasAttribute('rel') && $link->getAttribute('rel') == $rel) {
|
if (!$rel || $link->hasAttribute('rel') && $link->getAttribute('rel') == $rel) {
|
||||||
array_push($rv, $link->getAttribute('href'));
|
array_push($rv, trim($link->getAttribute('href')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -235,7 +265,7 @@ class FeedParser {
|
||||||
|
|
||||||
foreach ($links as $link) {
|
foreach ($links as $link) {
|
||||||
if (!$rel || $link->hasAttribute('rel') && $link->getAttribute('rel') == $rel) {
|
if (!$rel || $link->hasAttribute('rel') && $link->getAttribute('rel') == $rel) {
|
||||||
array_push($rv, $link->getAttribute('href'));
|
array_push($rv, trim($link->getAttribute('href')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -13,12 +13,6 @@ class Feeds extends Handler_Protected {
|
||||||
$feed_id, $is_cat, $search,
|
$feed_id, $is_cat, $search,
|
||||||
$search_mode, $view_mode, $error, $feed_last_updated) {
|
$search_mode, $view_mode, $error, $feed_last_updated) {
|
||||||
|
|
||||||
$page_prev_link = "viewFeedGoPage(-1)";
|
|
||||||
$page_next_link = "viewFeedGoPage(1)";
|
|
||||||
$page_first_link = "viewFeedGoPage(0)";
|
|
||||||
|
|
||||||
$catchup_page_link = "catchupPage()";
|
|
||||||
$catchup_feed_link = "catchupCurrentFeed()";
|
|
||||||
$catchup_sel_link = "catchupSelection()";
|
$catchup_sel_link = "catchupSelection()";
|
||||||
|
|
||||||
$archive_sel_link = "archiveSelection()";
|
$archive_sel_link = "archiveSelection()";
|
||||||
|
@ -43,6 +37,8 @@ class Feeds extends Handler_Protected {
|
||||||
$search_q = "";
|
$search_q = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$reply .= "<span class=\"holder\">";
|
||||||
|
|
||||||
$rss_link = htmlspecialchars(get_self_url_prefix() .
|
$rss_link = htmlspecialchars(get_self_url_prefix() .
|
||||||
"/public.php?op=rss&id=$feed_id$cat_q$search_q");
|
"/public.php?op=rss&id=$feed_id$cat_q$search_q");
|
||||||
|
|
||||||
|
@ -50,8 +46,14 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$error_class = $error ? "error" : "";
|
$error_class = $error ? "error" : "";
|
||||||
|
|
||||||
$reply .= "<span class='r'>";
|
$reply .= "<span class='r'>
|
||||||
$reply .= "<span id='selected_prompt'></span>";
|
<a href=\"#\"
|
||||||
|
title=\"".__("View as RSS feed")."\"
|
||||||
|
onclick=\"displayDlg('".__("View as RSS")."','generatedFeed', '$feed_id:$is_cat:$rss_link')\">
|
||||||
|
<img class=\"noborder\" src=\"images/pub_set.png\"></a>";
|
||||||
|
|
||||||
|
|
||||||
|
# $reply .= "<span>";
|
||||||
$reply .= "<span id='feed_title' class='$error_class'>";
|
$reply .= "<span id='feed_title' class='$error_class'>";
|
||||||
|
|
||||||
if ($feed_site_url) {
|
if ($feed_site_url) {
|
||||||
|
@ -60,11 +62,11 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$target = "target=\"_blank\"";
|
$target = "target=\"_blank\"";
|
||||||
$reply .= "<a title=\"$last_updated\" $target href=\"$feed_site_url\">".
|
$reply .= "<a title=\"$last_updated\" $target href=\"$feed_site_url\">".
|
||||||
truncate_string($feed_title,30)."</a>";
|
truncate_string($feed_title, 30)."</a>";
|
||||||
|
|
||||||
if ($error) {
|
if ($error) {
|
||||||
$error = htmlspecialchars($error);
|
$error = htmlspecialchars($error);
|
||||||
$reply .= " <img title=\"$error\" src='images/error.png' alt='error' class=\"noborder\" style=\"vertical-align : middle\">";
|
$reply .= " <img title=\"$error\" src='images/error.png' alt='error' class=\"noborder\">";
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -73,17 +75,16 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$reply .= "</span>";
|
$reply .= "</span>";
|
||||||
|
|
||||||
$reply .= "
|
|
||||||
<a href=\"#\"
|
|
||||||
title=\"".__("View as RSS feed")."\"
|
|
||||||
onclick=\"displayDlg('".__("View as RSS")."','generatedFeed', '$feed_id:$is_cat:$rss_link')\">
|
|
||||||
<img class=\"noborder\" style=\"vertical-align : middle\" src=\"images/pub_set.png\"></a>";
|
|
||||||
|
|
||||||
$reply .= "</span>";
|
$reply .= "</span>";
|
||||||
|
|
||||||
|
# $reply .= "</span>";
|
||||||
|
|
||||||
// left part
|
// left part
|
||||||
|
|
||||||
$reply .= __('Select:')."
|
$reply .= "<span class=\"main\">";
|
||||||
|
$reply .= "<span id='selected_prompt'></span>";
|
||||||
|
|
||||||
|
$reply .= "
|
||||||
<a href=\"#\" onclick=\"$sel_all_link\">".__('All')."</a>,
|
<a href=\"#\" onclick=\"$sel_all_link\">".__('All')."</a>,
|
||||||
<a href=\"#\" onclick=\"$sel_unread_link\">".__('Unread')."</a>,
|
<a href=\"#\" onclick=\"$sel_unread_link\">".__('Unread')."</a>,
|
||||||
<a href=\"#\" onclick=\"$sel_inv_link\">".__('Invert')."</a>,
|
<a href=\"#\" onclick=\"$sel_inv_link\">".__('Invert')."</a>,
|
||||||
|
@ -132,14 +133,14 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$reply .= "</select>";
|
$reply .= "</select>";
|
||||||
|
|
||||||
//$reply .= "</div>";
|
|
||||||
|
|
||||||
//$reply .= "</h2";
|
//$reply .= "</h2";
|
||||||
|
|
||||||
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_HEADLINE_TOOLBAR_BUTTON) as $p) {
|
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_HEADLINE_TOOLBAR_BUTTON) as $p) {
|
||||||
echo $p->hook_headline_toolbar_button($feed_id, $is_cat);
|
$reply .= $p->hook_headline_toolbar_button($feed_id, $is_cat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$reply .= "</span></span>";
|
||||||
|
|
||||||
return $reply;
|
return $reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +149,7 @@ class Feeds extends Handler_Protected {
|
||||||
$override_order = false, $include_children = false) {
|
$override_order = false, $include_children = false) {
|
||||||
|
|
||||||
if (isset($_REQUEST["DevForceUpdate"]))
|
if (isset($_REQUEST["DevForceUpdate"]))
|
||||||
header("Content-Type: text/plain");
|
header("Content-Type: text/plain; charset=utf-8");
|
||||||
|
|
||||||
$disable_cache = false;
|
$disable_cache = false;
|
||||||
|
|
||||||
|
@ -247,6 +248,8 @@ class Feeds extends Handler_Protected {
|
||||||
false, 0, $include_children);
|
false, 0, $include_children);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$vfeed_group_enabled = get_pref("VFEED_GROUP_BY_FEED") && $feed != -6;
|
||||||
|
|
||||||
if ($_REQUEST["debug"]) $timing_info = print_checkpoint("H1", $timing_info);
|
if ($_REQUEST["debug"]) $timing_info = print_checkpoint("H1", $timing_info);
|
||||||
|
|
||||||
$result = $qfh_ret[0];
|
$result = $qfh_ret[0];
|
||||||
|
@ -278,6 +281,12 @@ class Feeds extends Handler_Protected {
|
||||||
}
|
}
|
||||||
} */
|
} */
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->dbh->num_rows($result) > 0) {
|
if ($this->dbh->num_rows($result) > 0) {
|
||||||
|
|
||||||
$lnum = $offset;
|
$lnum = $offset;
|
||||||
|
@ -285,14 +294,12 @@ class Feeds extends Handler_Protected {
|
||||||
$num_unread = 0;
|
$num_unread = 0;
|
||||||
$cur_feed_title = '';
|
$cur_feed_title = '';
|
||||||
|
|
||||||
$fresh_intl = get_pref("FRESH_ARTICLE_MAX_AGE") * 60 * 60;
|
|
||||||
|
|
||||||
if ($_REQUEST["debug"]) $timing_info = print_checkpoint("PS", $timing_info);
|
if ($_REQUEST["debug"]) $timing_info = print_checkpoint("PS", $timing_info);
|
||||||
|
|
||||||
$expand_cdm = get_pref('CDM_EXPANDED');
|
$expand_cdm = get_pref('CDM_EXPANDED');
|
||||||
|
|
||||||
while ($line = $this->dbh->fetch_assoc($result)) {
|
while ($line = $this->dbh->fetch_assoc($result)) {
|
||||||
$line["content_preview"] = "— " . truncate_string(strip_tags($line["content_preview"]), 250);
|
$line["content_preview"] = "— " . truncate_string(strip_tags($line["content"]), 250);
|
||||||
|
|
||||||
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
|
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
|
||||||
$line = $p->hook_query_headlines($line, 250, false);
|
$line = $p->hook_query_headlines($line, 250, false);
|
||||||
|
@ -422,7 +429,7 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
if (!get_pref('COMBINED_DISPLAY_MODE')) {
|
if (!get_pref('COMBINED_DISPLAY_MODE')) {
|
||||||
|
|
||||||
if (get_pref('VFEED_GROUP_BY_FEED')) {
|
if ($vfeed_group_enabled) {
|
||||||
if ($feed_id != $vgroup_last_feed && $line["feed_title"]) {
|
if ($feed_id != $vgroup_last_feed && $line["feed_title"]) {
|
||||||
|
|
||||||
$cur_feed_title = $line["feed_title"];
|
$cur_feed_title = $line["feed_title"];
|
||||||
|
@ -430,12 +437,12 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$cur_feed_title = htmlspecialchars($cur_feed_title);
|
$cur_feed_title = htmlspecialchars($cur_feed_title);
|
||||||
|
|
||||||
$vf_catchup_link = "(<a class='catchup' onclick='catchupFeedInGroup($feed_id);' href='#'>".__('Mark as read')."</a>)";
|
$vf_catchup_link = "<a class='catchup' onclick='catchupFeedInGroup($feed_id);' href='#'>".__('mark feed as read')."</a>";
|
||||||
|
|
||||||
$reply['content'] .= "<div class='cdmFeedTitle'>".
|
$reply['content'] .= "<div id='FTITLE-$feed_id' class='cdmFeedTitle'>".
|
||||||
"<div style=\"float : right\">$feed_icon_img</div>".
|
"<div style='float : right'>$feed_icon_img</div>".
|
||||||
"<a class='title' href=\"#\" onclick=\"viewfeed($feed_id)\">".
|
"<a class='title' href=\"#\" onclick=\"viewfeed($feed_id)\">". $line["feed_title"]."</a>
|
||||||
$line["feed_title"]."</a> $vf_catchup_link</div>";
|
$vf_catchup_link</div>";
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -443,7 +450,7 @@ class Feeds extends Handler_Protected {
|
||||||
$mouseover_attrs = "onmouseover='postMouseIn(event, $id)'
|
$mouseover_attrs = "onmouseover='postMouseIn(event, $id)'
|
||||||
onmouseout='postMouseOut($id)'";
|
onmouseout='postMouseOut($id)'";
|
||||||
|
|
||||||
$reply['content'] .= "<div class='hl $class' id='RROW-$id' $mouseover_attrs>";
|
$reply['content'] .= "<div class='hl $class' orig-feed-id='$feed_id' id='RROW-$id' $mouseover_attrs>";
|
||||||
|
|
||||||
$reply['content'] .= "<div class='hlLeft'>";
|
$reply['content'] .= "<div class='hlLeft'>";
|
||||||
|
|
||||||
|
@ -473,17 +480,18 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$reply['content'] .= "</div>";
|
$reply['content'] .= "</div>";
|
||||||
|
|
||||||
$reply['content'] .= "<span class=\"hlUpdated\">";
|
if (!$vfeed_group_enabled) {
|
||||||
|
|
||||||
if (!get_pref('VFEED_GROUP_BY_FEED')) {
|
|
||||||
if (@$line["feed_title"]) {
|
if (@$line["feed_title"]) {
|
||||||
$rgba = @$rgba_cache[$feed_id];
|
$rgba = @$rgba_cache[$feed_id];
|
||||||
|
|
||||||
$reply['content'] .= "<a class=\"hlFeed\" style=\"background : rgba($rgba, 0.3)\" href=\"#\" onclick=\"viewfeed($feed_id)\">".
|
$reply['content'] .= "<span class=\"hlFeed\"><a style=\"background : rgba($rgba, 0.3)\" href=\"#\" onclick=\"viewfeed($feed_id)\">".
|
||||||
truncate_string($line["feed_title"],30)."</a>";
|
truncate_string($line["feed_title"],30)."</a></span>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$reply['content'] .= "<span class=\"hlUpdated\">";
|
||||||
|
|
||||||
$reply['content'] .= "<div title='$date_entered_fmt'>$updated_fmt</div>
|
$reply['content'] .= "<div title='$date_entered_fmt'>$updated_fmt</div>
|
||||||
</span>";
|
</span>";
|
||||||
|
|
||||||
|
@ -491,12 +499,12 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$reply['content'] .= $score_pic;
|
$reply['content'] .= $score_pic;
|
||||||
|
|
||||||
if ($line["feed_title"] && !get_pref('VFEED_GROUP_BY_FEED')) {
|
if ($line["feed_title"] && !$vfeed_group_enabled) {
|
||||||
|
|
||||||
$reply['content'] .= "<span onclick=\"viewfeed($feed_id)\"
|
$reply['content'] .= "<span onclick=\"viewfeed($feed_id)\"
|
||||||
style=\"cursor : pointer\"
|
style=\"cursor : pointer\"
|
||||||
title=\"".htmlspecialchars($line['feed_title'])."\">
|
title=\"".htmlspecialchars($line['feed_title'])."\">
|
||||||
$feed_icon_img<span>";
|
$feed_icon_img</span>";
|
||||||
}
|
}
|
||||||
|
|
||||||
$reply['content'] .= "</div>";
|
$reply['content'] .= "</div>";
|
||||||
|
@ -516,7 +524,7 @@ class Feeds extends Handler_Protected {
|
||||||
$line = $p->hook_render_article_cdm($line);
|
$line = $p->hook_render_article_cdm($line);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_pref('VFEED_GROUP_BY_FEED') && $line["feed_title"]) {
|
if ($vfeed_group_enabled && $line["feed_title"]) {
|
||||||
if ($feed_id != $vgroup_last_feed) {
|
if ($feed_id != $vgroup_last_feed) {
|
||||||
|
|
||||||
$cur_feed_title = $line["feed_title"];
|
$cur_feed_title = $line["feed_title"];
|
||||||
|
@ -524,7 +532,7 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$cur_feed_title = htmlspecialchars($cur_feed_title);
|
$cur_feed_title = htmlspecialchars($cur_feed_title);
|
||||||
|
|
||||||
$vf_catchup_link = "(<a class='catchup' onclick='javascript:catchupFeedInGroup($feed_id);' href='#'>".__('mark as read')."</a>)";
|
$vf_catchup_link = "<a class='catchup' onclick='catchupFeedInGroup($feed_id);' href='#'>".__('mark feed as read')."</a>";
|
||||||
|
|
||||||
$has_feed_icon = feed_has_icon($feed_id);
|
$has_feed_icon = feed_has_icon($feed_id);
|
||||||
|
|
||||||
|
@ -534,7 +542,7 @@ class Feeds extends Handler_Protected {
|
||||||
//$feed_icon_img = "<img class=\"tinyFeedIcon\" src=\"images/blank_icon.gif\" alt=\"\">";
|
//$feed_icon_img = "<img class=\"tinyFeedIcon\" src=\"images/blank_icon.gif\" alt=\"\">";
|
||||||
}
|
}
|
||||||
|
|
||||||
$reply['content'] .= "<div class='cdmFeedTitle'>".
|
$reply['content'] .= "<div id='FTITLE-$feed_id' class='cdmFeedTitle'>".
|
||||||
"<div style=\"float : right\">$feed_icon_img</div>".
|
"<div style=\"float : right\">$feed_icon_img</div>".
|
||||||
"<a href=\"#\" class='title' onclick=\"viewfeed($feed_id)\">".
|
"<a href=\"#\" class='title' onclick=\"viewfeed($feed_id)\">".
|
||||||
$line["feed_title"]."</a> $vf_catchup_link</div>";
|
$line["feed_title"]."</a> $vf_catchup_link</div>";
|
||||||
|
@ -547,9 +555,9 @@ class Feeds extends Handler_Protected {
|
||||||
$expanded_class = $expand_cdm ? "expanded" : "expandable";
|
$expanded_class = $expand_cdm ? "expanded" : "expandable";
|
||||||
|
|
||||||
$reply['content'] .= "<div class=\"cdm $hlc_suffix $expanded_class $class\"
|
$reply['content'] .= "<div class=\"cdm $hlc_suffix $expanded_class $class\"
|
||||||
id=\"RROW-$id\" $mouseover_attrs>";
|
id=\"RROW-$id\" orig-feed-id='$feed_id' $mouseover_attrs>";
|
||||||
|
|
||||||
$reply['content'] .= "<div class=\"cdmHeader\" style=\"$row_background\">";
|
$reply['content'] .= "<div class=\"cdmHeader\">";
|
||||||
$reply['content'] .= "<div style=\"vertical-align : middle\">";
|
$reply['content'] .= "<div style=\"vertical-align : middle\">";
|
||||||
|
|
||||||
$reply['content'] .= "<input dojoType=\"dijit.form.CheckBox\"
|
$reply['content'] .= "<input dojoType=\"dijit.form.CheckBox\"
|
||||||
|
@ -592,7 +600,7 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$reply['content'] .= "</span>";
|
$reply['content'] .= "</span>";
|
||||||
|
|
||||||
if (!get_pref('VFEED_GROUP_BY_FEED')) {
|
if (!$vfeed_group_enabled) {
|
||||||
if (@$line["feed_title"]) {
|
if (@$line["feed_title"]) {
|
||||||
$rgba = @$rgba_cache[$feed_id];
|
$rgba = @$rgba_cache[$feed_id];
|
||||||
|
|
||||||
|
@ -725,7 +733,7 @@ class Feeds extends Handler_Protected {
|
||||||
$reply['content'] .= "</div>";
|
$reply['content'] .= "</div>";
|
||||||
$reply['content'] .= "</div>";
|
$reply['content'] .= "</div>";
|
||||||
|
|
||||||
$reply['content'] .= "</div><hr/>";
|
$reply['content'] .= "</div>";
|
||||||
|
|
||||||
$reply['content'] .= "</div>";
|
$reply['content'] .= "</div>";
|
||||||
|
|
||||||
|
@ -803,8 +811,6 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
if ($_REQUEST["debug"]) $timing_info = print_checkpoint("0", $timing_info);
|
if ($_REQUEST["debug"]) $timing_info = print_checkpoint("0", $timing_info);
|
||||||
|
|
||||||
$omode = $this->dbh->escape_string($_REQUEST["omode"]);
|
|
||||||
|
|
||||||
$feed = $this->dbh->escape_string($_REQUEST["feed"]);
|
$feed = $this->dbh->escape_string($_REQUEST["feed"]);
|
||||||
$method = $this->dbh->escape_string($_REQUEST["m"]);
|
$method = $this->dbh->escape_string($_REQUEST["m"]);
|
||||||
$view_mode = $this->dbh->escape_string($_REQUEST["view_mode"]);
|
$view_mode = $this->dbh->escape_string($_REQUEST["view_mode"]);
|
||||||
|
@ -897,7 +903,7 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
//$topmost_article_ids = $ret[0];
|
//$topmost_article_ids = $ret[0];
|
||||||
$headlines_count = $ret[1];
|
$headlines_count = $ret[1];
|
||||||
$returned_feed = $ret[2];
|
/* $returned_feed = $ret[2]; */
|
||||||
$disable_cache = $ret[3];
|
$disable_cache = $ret[3];
|
||||||
$vgroup_last_feed = $ret[4];
|
$vgroup_last_feed = $ret[4];
|
||||||
|
|
||||||
|
@ -978,6 +984,10 @@ class Feeds extends Handler_Protected {
|
||||||
print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"rpc\">";
|
print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"rpc\">";
|
||||||
print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"addfeed\">";
|
print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"addfeed\">";
|
||||||
|
|
||||||
|
print "<div id='fadd_multiple_notify' style='display : none'>";
|
||||||
|
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=\"dlgSec\">".__("Feed or site URL")."</div>";
|
||||||
print "<div class=\"dlgSecCont\">";
|
print "<div class=\"dlgSecCont\">";
|
||||||
|
|
||||||
|
@ -1073,20 +1083,18 @@ class Feeds extends Handler_Protected {
|
||||||
print " <select dojoType=\"dijit.form.Select\" name=\"limit\" onchange=\"dijit.byId('feedBrowserDlg').update()\">";
|
print " <select dojoType=\"dijit.form.Select\" name=\"limit\" onchange=\"dijit.byId('feedBrowserDlg').update()\">";
|
||||||
|
|
||||||
foreach (array(25, 50, 100, 200) as $l) {
|
foreach (array(25, 50, 100, 200) as $l) {
|
||||||
$issel = ($l == $limit) ? "selected=\"1\"" : "";
|
//$issel = ($l == $limit) ? "selected=\"1\"" : "";
|
||||||
print "<option $issel value=\"$l\">$l</option>";
|
print "<option value=\"$l\">$l</option>";
|
||||||
}
|
}
|
||||||
|
|
||||||
print "</select> ";
|
print "</select> ";
|
||||||
|
|
||||||
print "</div>";
|
print "</div>";
|
||||||
|
|
||||||
$owner_uid = $_SESSION["uid"];
|
|
||||||
|
|
||||||
require_once "feedbrowser.php";
|
require_once "feedbrowser.php";
|
||||||
|
|
||||||
print "<ul class='browseFeedList' id='browseFeedList'>";
|
print "<ul class='browseFeedList' id='browseFeedList'>";
|
||||||
print make_feed_browser($search, 25);
|
print make_feed_browser("", 25);
|
||||||
print "</ul>";
|
print "</ul>";
|
||||||
|
|
||||||
print "<div align='center'>
|
print "<div align='center'>
|
||||||
|
@ -1145,7 +1153,7 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
print "<div class=\"dlgButtons\">";
|
print "<div class=\"dlgButtons\">";
|
||||||
|
|
||||||
if (!SPHINX_ENABLED) {
|
if (count(PluginHost::getInstance()->get_hooks(PluginHost::HOOK_SEARCH)) == 0) {
|
||||||
print "<div style=\"float : left\">
|
print "<div style=\"float : left\">
|
||||||
<a class=\"visibleLink\" target=\"_blank\" href=\"http://tt-rss.org/wiki/SearchSyntax\">".__("Search syntax")."</a>
|
<a class=\"visibleLink\" target=\"_blank\" href=\"http://tt-rss.org/wiki/SearchSyntax\">".__("Search syntax")."</a>
|
||||||
</div>";
|
</div>";
|
||||||
|
|
|
@ -3,7 +3,7 @@ class Handler_Public extends Handler {
|
||||||
|
|
||||||
private function generate_syndicated_feed($owner_uid, $feed, $is_cat,
|
private function generate_syndicated_feed($owner_uid, $feed, $is_cat,
|
||||||
$limit, $offset, $search, $search_mode,
|
$limit, $offset, $search, $search_mode,
|
||||||
$view_mode = false, $format = 'atom', $order = false, $orig_guid = false) {
|
$view_mode = false, $format = 'atom', $order = false, $orig_guid = false, $start_ts = false) {
|
||||||
|
|
||||||
require_once "lib/MiniTemplator.class.php";
|
require_once "lib/MiniTemplator.class.php";
|
||||||
|
|
||||||
|
@ -15,11 +15,15 @@ class Handler_Public extends Handler {
|
||||||
if (!$limit) $limit = 60;
|
if (!$limit) $limit = 60;
|
||||||
|
|
||||||
$date_sort_field = "date_entered DESC, updated DESC";
|
$date_sort_field = "date_entered DESC, updated DESC";
|
||||||
|
$date_check_field = "date_entered";
|
||||||
|
|
||||||
if ($feed == -2)
|
if ($feed == -2 && !$is_cat) {
|
||||||
$date_sort_field = "last_published DESC";
|
$date_sort_field = "last_published DESC";
|
||||||
else if ($feed == -1)
|
$date_check_field = "last_published";
|
||||||
|
} else if ($feed == -1 && !$is_cat) {
|
||||||
$date_sort_field = "last_marked DESC";
|
$date_sort_field = "last_marked DESC";
|
||||||
|
$date_check_field = "last_marked";
|
||||||
|
}
|
||||||
|
|
||||||
switch ($order) {
|
switch ($order) {
|
||||||
case "title":
|
case "title":
|
||||||
|
@ -33,15 +37,18 @@ class Handler_Public extends Handler {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//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, $override_strategy = false, $override_vfeed = false, $start_ts = false) {
|
||||||
|
|
||||||
$qfh_ret = queryFeedHeadlines($feed,
|
$qfh_ret = queryFeedHeadlines($feed,
|
||||||
1, $view_mode, $is_cat, $search, $search_mode,
|
1, $view_mode, $is_cat, $search, $search_mode,
|
||||||
$date_sort_field, $offset, $owner_uid,
|
$date_sort_field, $offset, $owner_uid,
|
||||||
false, 0, false, true);
|
false, 0, true, true, false, false, $start_ts);
|
||||||
|
|
||||||
$result = $qfh_ret[0];
|
$result = $qfh_ret[0];
|
||||||
|
|
||||||
if ($this->dbh->num_rows($result) != 0) {
|
if ($this->dbh->num_rows($result) != 0) {
|
||||||
$ts = strtotime($this->dbh->fetch_result($result, 0, "date_entered"));
|
|
||||||
|
$ts = strtotime($this->dbh->fetch_result($result, 0, $date_check_field));
|
||||||
|
|
||||||
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
|
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
|
||||||
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $ts) {
|
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $ts) {
|
||||||
|
@ -56,13 +63,13 @@ class Handler_Public extends Handler {
|
||||||
$qfh_ret = queryFeedHeadlines($feed,
|
$qfh_ret = queryFeedHeadlines($feed,
|
||||||
$limit, $view_mode, $is_cat, $search, $search_mode,
|
$limit, $view_mode, $is_cat, $search, $search_mode,
|
||||||
$date_sort_field, $offset, $owner_uid,
|
$date_sort_field, $offset, $owner_uid,
|
||||||
false, 0, false, true);
|
false, 0, true, true, false, false, $start_ts);
|
||||||
|
|
||||||
|
|
||||||
$result = $qfh_ret[0];
|
$result = $qfh_ret[0];
|
||||||
$feed_title = htmlspecialchars($qfh_ret[1]);
|
$feed_title = htmlspecialchars($qfh_ret[1]);
|
||||||
$feed_site_url = $qfh_ret[2];
|
$feed_site_url = $qfh_ret[2];
|
||||||
$last_error = $qfh_ret[3];
|
/* $last_error = $qfh_ret[3]; */
|
||||||
|
|
||||||
$feed_self_url = get_self_url_prefix() .
|
$feed_self_url = get_self_url_prefix() .
|
||||||
"/public.php?op=rss&id=$feed&key=" .
|
"/public.php?op=rss&id=$feed&key=" .
|
||||||
|
@ -86,7 +93,7 @@ class Handler_Public extends Handler {
|
||||||
|
|
||||||
$tpl->setVariable('SELF_URL', htmlspecialchars(get_self_url_prefix()), true);
|
$tpl->setVariable('SELF_URL', htmlspecialchars(get_self_url_prefix()), true);
|
||||||
while ($line = $this->dbh->fetch_assoc($result)) {
|
while ($line = $this->dbh->fetch_assoc($result)) {
|
||||||
$line["content_preview"] = truncate_string(strip_tags($line["content_preview"]), 100, '...');
|
$line["content_preview"] = truncate_string(strip_tags($line["content"]), 100, '...');
|
||||||
|
|
||||||
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
|
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
|
||||||
$line = $p->hook_query_headlines($line);
|
$line = $p->hook_query_headlines($line);
|
||||||
|
@ -100,7 +107,8 @@ class Handler_Public extends Handler {
|
||||||
$tpl->setVariable('ARTICLE_TITLE', htmlspecialchars($line['title']), true);
|
$tpl->setVariable('ARTICLE_TITLE', htmlspecialchars($line['title']), true);
|
||||||
$tpl->setVariable('ARTICLE_EXCERPT', $line["content_preview"], true);
|
$tpl->setVariable('ARTICLE_EXCERPT', $line["content_preview"], true);
|
||||||
|
|
||||||
$content = sanitize($line["content"], false, $owner_uid);
|
$content = sanitize($line["content"], false, $owner_uid,
|
||||||
|
$feed_site_url);
|
||||||
|
|
||||||
if ($line['note']) {
|
if ($line['note']) {
|
||||||
$content = "<div style=\"$note_style\">Article note: " . $line['note'] . "</div>" .
|
$content = "<div style=\"$note_style\">Article note: " . $line['note'] . "</div>" .
|
||||||
|
@ -118,7 +126,7 @@ class Handler_Public extends Handler {
|
||||||
$tpl->setVariable('ARTICLE_AUTHOR', htmlspecialchars($line['author']), true);
|
$tpl->setVariable('ARTICLE_AUTHOR', htmlspecialchars($line['author']), true);
|
||||||
|
|
||||||
$tpl->setVariable('ARTICLE_SOURCE_LINK', htmlspecialchars($line['site_url']), true);
|
$tpl->setVariable('ARTICLE_SOURCE_LINK', htmlspecialchars($line['site_url']), true);
|
||||||
$tpl->setVariable('ARTICLE_SOURCE_TITLE', htmlspecialchars($line['feed_title']), true);
|
$tpl->setVariable('ARTICLE_SOURCE_TITLE', htmlspecialchars($line['feed_title'] ? $line['feed_title'] : $feed_title), true);
|
||||||
|
|
||||||
$tags = get_article_tags($line["id"], $owner_uid);
|
$tags = get_article_tags($line["id"], $owner_uid);
|
||||||
|
|
||||||
|
@ -269,16 +277,22 @@ class Handler_Public extends Handler {
|
||||||
|
|
||||||
function pubsub() {
|
function pubsub() {
|
||||||
$mode = $this->dbh->escape_string($_REQUEST['hub_mode']);
|
$mode = $this->dbh->escape_string($_REQUEST['hub_mode']);
|
||||||
|
if (!$mode) $mode = $this->dbh->escape_string($_REQUEST['hub.mode']);
|
||||||
|
|
||||||
$feed_id = (int) $this->dbh->escape_string($_REQUEST['id']);
|
$feed_id = (int) $this->dbh->escape_string($_REQUEST['id']);
|
||||||
$feed_url = $this->dbh->escape_string($_REQUEST['hub_topic']);
|
$feed_url = $this->dbh->escape_string($_REQUEST['hub_topic']);
|
||||||
|
|
||||||
|
if (!$feed_url) $feed_url = $this->dbh->escape_string($_REQUEST['hub.topic']);
|
||||||
|
|
||||||
if (!PUBSUBHUBBUB_ENABLED) {
|
if (!PUBSUBHUBBUB_ENABLED) {
|
||||||
header('HTTP/1.0 404 Not Found');
|
header('HTTP/1.0 404 Not Found');
|
||||||
echo "404 Not found";
|
echo "404 Not found (Disabled by server)";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement hub_verifytoken checking
|
// TODO: implement hub_verifytoken checking
|
||||||
|
// TODO: store requested rel=self or whatever for verification
|
||||||
|
// (may be different from stored feed url) e.g. http://url/ or http://url
|
||||||
|
|
||||||
$result = $this->dbh->query("SELECT feed_url FROM ttrss_feeds
|
$result = $this->dbh->query("SELECT feed_url FROM ttrss_feeds
|
||||||
WHERE id = '$feed_id'");
|
WHERE id = '$feed_id'");
|
||||||
|
@ -287,7 +301,8 @@ class Handler_Public extends Handler {
|
||||||
|
|
||||||
$check_feed_url = $this->dbh->fetch_result($result, 0, "feed_url");
|
$check_feed_url = $this->dbh->fetch_result($result, 0, "feed_url");
|
||||||
|
|
||||||
if ($check_feed_url && ($check_feed_url == $feed_url || !$feed_url)) {
|
// ignore url checking for the time being
|
||||||
|
if ($check_feed_url && (true || $check_feed_url == $feed_url || !$feed_url)) {
|
||||||
if ($mode == "subscribe") {
|
if ($mode == "subscribe") {
|
||||||
|
|
||||||
$this->dbh->query("UPDATE ttrss_feeds SET pubsub_state = 2
|
$this->dbh->query("UPDATE ttrss_feeds SET pubsub_state = 2
|
||||||
|
@ -316,11 +331,11 @@ class Handler_Public extends Handler {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
header('HTTP/1.0 404 Not Found');
|
header('HTTP/1.0 404 Not Found');
|
||||||
echo "404 Not found";
|
echo "404 Not found (URL check failed)";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
header('HTTP/1.0 404 Not Found');
|
header('HTTP/1.0 404 Not Found');
|
||||||
echo "404 Not found";
|
echo "404 Not found (Feed not found)";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -363,9 +378,10 @@ class Handler_Public extends Handler {
|
||||||
$search_mode = $this->dbh->escape_string($_REQUEST["smode"]);
|
$search_mode = $this->dbh->escape_string($_REQUEST["smode"]);
|
||||||
$view_mode = $this->dbh->escape_string($_REQUEST["view-mode"]);
|
$view_mode = $this->dbh->escape_string($_REQUEST["view-mode"]);
|
||||||
$order = $this->dbh->escape_string($_REQUEST["order"]);
|
$order = $this->dbh->escape_string($_REQUEST["order"]);
|
||||||
|
$start_ts = $this->dbh->escape_string($_REQUEST["ts"]);
|
||||||
|
|
||||||
$format = $this->dbh->escape_string($_REQUEST['format']);
|
$format = $this->dbh->escape_string($_REQUEST['format']);
|
||||||
$orig_guid = !sql_bool_to_bool($_REQUEST["no_orig_guid"]);
|
$orig_guid = sql_bool_to_bool($_REQUEST["orig_guid"]);
|
||||||
|
|
||||||
if (!$format) $format = 'atom';
|
if (!$format) $format = 'atom';
|
||||||
|
|
||||||
|
@ -385,24 +401,24 @@ class Handler_Public extends Handler {
|
||||||
|
|
||||||
if ($owner_id) {
|
if ($owner_id) {
|
||||||
$this->generate_syndicated_feed($owner_id, $feed, $is_cat, $limit,
|
$this->generate_syndicated_feed($owner_id, $feed, $is_cat, $limit,
|
||||||
$offset, $search, $search_mode, $view_mode, $format, $order, $orig_guid);
|
$offset, $search, $search_mode, $view_mode, $format, $order, $orig_guid, $start_ts);
|
||||||
} else {
|
} else {
|
||||||
header('HTTP/1.1 403 Forbidden');
|
header('HTTP/1.1 403 Forbidden');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTask() {
|
function updateTask() {
|
||||||
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_UPDATE_TASK, "hook_update_task", $op);
|
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_UPDATE_TASK, "hook_update_task", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function housekeepingTask() {
|
function housekeepingTask() {
|
||||||
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_HOUSE_KEEPING, "hook_house_keeping", $op);
|
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_HOUSE_KEEPING, "hook_house_keeping", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function globalUpdateFeeds() {
|
function globalUpdateFeeds() {
|
||||||
RPC::updaterandomfeed_real($this->dbh);
|
RPC::updaterandomfeed_real($this->dbh);
|
||||||
|
|
||||||
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_UPDATE_TASK, "hook_update_task", $op);
|
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_UPDATE_TASK, "hook_update_task", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function sharepopup() {
|
function sharepopup() {
|
||||||
|
@ -411,11 +427,14 @@ class Handler_Public extends Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
header('Content-Type: text/html; charset=utf-8');
|
header('Content-Type: text/html; charset=utf-8');
|
||||||
print "<html><head><title>Tiny Tiny RSS</title>";
|
print "<html><head><title>Tiny Tiny RSS</title>
|
||||||
|
<link rel=\"shortcut icon\" type=\"image/png\" href=\"images/favicon.png\">
|
||||||
|
<link rel=\"icon\" type=\"image/png\" sizes=\"72x72\" href=\"images/favicon-72px.png\">";
|
||||||
|
|
||||||
stylesheet_tag("css/utility.css");
|
echo stylesheet_tag("css/utility.css");
|
||||||
javascript_tag("lib/prototype.js");
|
echo stylesheet_tag("css/dijit.css");
|
||||||
javascript_tag("lib/scriptaculous/scriptaculous.js?load=effects,dragdrop,controls");
|
echo javascript_tag("lib/prototype.js");
|
||||||
|
echo javascript_tag("lib/scriptaculous/scriptaculous.js?load=effects,controls");
|
||||||
print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
|
print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
|
||||||
</head><body id='sharepopup'>";
|
</head><body id='sharepopup'>";
|
||||||
|
|
||||||
|
@ -561,7 +580,7 @@ class Handler_Public extends Handler {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$_SESSION["login_error_msg"] = __("Incorrect username or password");
|
$_SESSION["login_error_msg"] = __("Incorrect username or password");
|
||||||
user_error("Failed login attempt from {$_SERVER['REMOTE_ADDR']}", E_USER_WARNING);
|
user_error("Failed login attempt for $login from {$_SERVER['REMOTE_ADDR']}", E_USER_WARNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($_REQUEST['return']) {
|
if ($_REQUEST['return']) {
|
||||||
|
@ -572,6 +591,18 @@ class Handler_Public extends Handler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* function subtest() {
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
|
||||||
|
$url = $_REQUEST["url"];
|
||||||
|
|
||||||
|
print "$url\n\n";
|
||||||
|
|
||||||
|
|
||||||
|
print_r(get_feeds_from_html($url, fetch_file_contents($url)));
|
||||||
|
|
||||||
|
} */
|
||||||
|
|
||||||
function subscribe() {
|
function subscribe() {
|
||||||
if (SINGLE_USER_MODE) {
|
if (SINGLE_USER_MODE) {
|
||||||
login_sequence();
|
login_sequence();
|
||||||
|
@ -587,6 +618,9 @@ class Handler_Public extends Handler {
|
||||||
<title>Tiny Tiny RSS</title>
|
<title>Tiny Tiny RSS</title>
|
||||||
<link rel=\"stylesheet\" type=\"text/css\" href=\"css/utility.css\">
|
<link rel=\"stylesheet\" type=\"text/css\" href=\"css/utility.css\">
|
||||||
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
|
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
|
||||||
|
<link rel=\"shortcut icon\" type=\"image/png\" href=\"images/favicon.png\">
|
||||||
|
<link rel=\"icon\" type=\"image/png\" sizes=\"72x72\" href=\"images/favicon-72px.png\">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<img class=\"floatingLogo\" src=\"images/logo_small.png\"
|
<img class=\"floatingLogo\" src=\"images/logo_small.png\"
|
||||||
|
@ -671,93 +705,6 @@ class Handler_Public extends Handler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function subscribe2() {
|
|
||||||
$feed_url = $this->dbh->escape_string(trim($_REQUEST["feed_url"]));
|
|
||||||
$cat_id = $this->dbh->escape_string($_REQUEST["cat_id"]);
|
|
||||||
$from = $this->dbh->escape_string($_REQUEST["from"]);
|
|
||||||
$feed_urls = array();
|
|
||||||
|
|
||||||
/* only read authentication information from POST */
|
|
||||||
|
|
||||||
$auth_login = $this->dbh->escape_string(trim($_POST["auth_login"]));
|
|
||||||
$auth_pass = $this->dbh->escape_string(trim($_POST["auth_pass"]));
|
|
||||||
|
|
||||||
$rc = subscribe_to_feed($feed_url, $cat_id, $auth_login, $auth_pass);
|
|
||||||
|
|
||||||
switch ($rc) {
|
|
||||||
case 1:
|
|
||||||
print_notice(T_sprintf("Subscribed to <b>%s</b>.", $feed_url));
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
print_error(T_sprintf("Could not subscribe to <b>%s</b>.", $feed_url));
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
print_error(T_sprintf("No feeds found in <b>%s</b>.", $feed_url));
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
print_warning(T_sprintf("Already subscribed to <b>%s</b>.", $feed_url));
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
print_notice(__("Multiple feed URLs found."));
|
|
||||||
$contents = @fetch_file_contents($url, false, $auth_login, $auth_pass);
|
|
||||||
if (is_html($contents)) {
|
|
||||||
$feed_urls = get_feeds_from_html($url, $contents);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
print_error(T_sprintf("Could not subscribe to <b>%s</b>.<br>Can't download the Feed URL.", $feed_url));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($feed_urls) {
|
|
||||||
print "<form action=\"backend.php\">";
|
|
||||||
print "<input type=\"hidden\" name=\"op\" value=\"pref-feeds\">";
|
|
||||||
print "<input type=\"hidden\" name=\"quiet\" value=\"1\">";
|
|
||||||
print "<input type=\"hidden\" name=\"method\" value=\"add\">";
|
|
||||||
|
|
||||||
print "<select name=\"feed_url\">";
|
|
||||||
|
|
||||||
foreach ($feed_urls as $url => $name) {
|
|
||||||
$url = htmlspecialchars($url);
|
|
||||||
$name = htmlspecialchars($name);
|
|
||||||
print "<option value=\"$url\">$name</option>";
|
|
||||||
}
|
|
||||||
|
|
||||||
print "<input type=\"submit\" value=\"".__("Subscribe to selected feed")."\">";
|
|
||||||
print "</form>";
|
|
||||||
}
|
|
||||||
|
|
||||||
$tp_uri = get_self_url_prefix() . "/prefs.php";
|
|
||||||
$tt_uri = get_self_url_prefix();
|
|
||||||
|
|
||||||
if ($rc <= 2){
|
|
||||||
$result = $this->dbh->query("SELECT id FROM ttrss_feeds WHERE
|
|
||||||
feed_url = '$feed_url' AND owner_uid = " . $_SESSION["uid"]);
|
|
||||||
|
|
||||||
$feed_id = $this->dbh->fetch_result($result, 0, "id");
|
|
||||||
} else {
|
|
||||||
$feed_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
print "<p>";
|
|
||||||
|
|
||||||
if ($feed_id) {
|
|
||||||
print "<form method=\"GET\" style='display: inline'
|
|
||||||
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\">
|
|
||||||
<input type=\"submit\" value=\"".__("Edit subscription options")."\">
|
|
||||||
</form>";
|
|
||||||
}
|
|
||||||
|
|
||||||
print "<form style='display: inline' method=\"GET\" action=\"$tt_uri\">
|
|
||||||
<input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
|
|
||||||
</form></p>";
|
|
||||||
|
|
||||||
print "</body></html>";
|
|
||||||
}
|
|
||||||
|
|
||||||
function index() {
|
function index() {
|
||||||
header("Content-Type: text/plain");
|
header("Content-Type: text/plain");
|
||||||
print json_encode(array("error" => array("code" => 7)));
|
print json_encode(array("error" => array("code" => 7)));
|
||||||
|
@ -766,11 +713,15 @@ class Handler_Public extends Handler {
|
||||||
function forgotpass() {
|
function forgotpass() {
|
||||||
startup_gettext();
|
startup_gettext();
|
||||||
|
|
||||||
header('Content-Type: text/html; charset=utf-8');
|
@$hash = $_REQUEST["hash"];
|
||||||
print "<html><head><title>Tiny Tiny RSS</title>";
|
|
||||||
|
|
||||||
stylesheet_tag("css/utility.css");
|
header('Content-Type: text/html; charset=utf-8');
|
||||||
javascript_tag("lib/prototype.js");
|
print "<html><head><title>Tiny Tiny RSS</title>
|
||||||
|
<link rel=\"shortcut icon\" type=\"image/png\" href=\"images/favicon.png\">
|
||||||
|
<link rel=\"icon\" type=\"image/png\" sizes=\"72x72\" href=\"images/favicon-72px.png\">";
|
||||||
|
|
||||||
|
echo stylesheet_tag("css/utility.css");
|
||||||
|
echo javascript_tag("lib/prototype.js");
|
||||||
|
|
||||||
print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
|
print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
|
||||||
</head><body id='forgotpass'>";
|
</head><body id='forgotpass'>";
|
||||||
|
@ -781,8 +732,45 @@ class Handler_Public extends Handler {
|
||||||
|
|
||||||
@$method = $_POST['method'];
|
@$method = $_POST['method'];
|
||||||
|
|
||||||
if (!$method) {
|
if ($hash) {
|
||||||
print_notice(__("You will need to provide valid account name and email. New password will be sent on your email address."));
|
$login = $_REQUEST["login"];
|
||||||
|
|
||||||
|
if ($login) {
|
||||||
|
$result = $this->dbh->query("SELECT id, resetpass_token FROM ttrss_users
|
||||||
|
WHERE login = '$login'");
|
||||||
|
|
||||||
|
if ($this->dbh->num_rows($result) != 0) {
|
||||||
|
$id = $this->dbh->fetch_result($result, 0, "id");
|
||||||
|
$resetpass_token_full = $this->dbh->fetch_result($result, 0, "resetpass_token");
|
||||||
|
list($timestamp, $resetpass_token) = explode(":", $resetpass_token_full);
|
||||||
|
|
||||||
|
if ($timestamp && $resetpass_token &&
|
||||||
|
$timestamp >= time() - 15*60*60 &&
|
||||||
|
$resetpass_token == $hash) {
|
||||||
|
|
||||||
|
$result = $this->dbh->query("UPDATE ttrss_users SET resetpass_token = NULL
|
||||||
|
WHERE id = $id");
|
||||||
|
|
||||||
|
Pref_Users::resetUserPassword($id, true);
|
||||||
|
|
||||||
|
print "<p>"."Completed."."</p>";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
print_error("Some of the information provided is missing or incorrect.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print_error("Some of the information provided is missing or incorrect.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print_error("Some of the information provided is missing or incorrect.");
|
||||||
|
}
|
||||||
|
|
||||||
|
print "<form method=\"GET\" action=\"index.php\">
|
||||||
|
<input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
|
||||||
|
</form>";
|
||||||
|
|
||||||
|
} else if (!$method) {
|
||||||
|
print_notice(__("You will need to provide valid account name and email. A password reset link will be sent to your email address."));
|
||||||
|
|
||||||
print "<form method='POST' action='public.php'>";
|
print "<form method='POST' action='public.php'>";
|
||||||
print "<input type='hidden' name='method' value='do'>";
|
print "<input type='hidden' name='method' value='do'>";
|
||||||
|
@ -823,17 +811,57 @@ class Handler_Public extends Handler {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
print_notice("Password reset instructions are being sent to your email address.");
|
||||||
|
|
||||||
$result = $this->dbh->query("SELECT id FROM ttrss_users
|
$result = $this->dbh->query("SELECT id FROM ttrss_users
|
||||||
WHERE login = '$login' AND email = '$email'");
|
WHERE login = '$login' AND email = '$email'");
|
||||||
|
|
||||||
if ($this->dbh->num_rows($result) != 0) {
|
if ($this->dbh->num_rows($result) != 0) {
|
||||||
$id = $this->dbh->fetch_result($result, 0, "id");
|
$id = $this->dbh->fetch_result($result, 0, "id");
|
||||||
|
|
||||||
Pref_Users::resetUserPassword($id, false);
|
if ($id) {
|
||||||
|
$resetpass_token = sha1(get_random_bytes(128));
|
||||||
|
$resetpass_link = get_self_url_prefix() . "/public.php?op=forgotpass&hash=" . $resetpass_token .
|
||||||
|
"&login=" . urlencode($login);
|
||||||
|
|
||||||
print "<p>";
|
require_once 'classes/ttrssmailer.php';
|
||||||
|
require_once "lib/MiniTemplator.class.php";
|
||||||
|
|
||||||
print "<p>"."Completed."."</p>";
|
$tpl = new MiniTemplator;
|
||||||
|
|
||||||
|
$tpl->readTemplateFromFile("templates/resetpass_link_template.txt");
|
||||||
|
|
||||||
|
$tpl->setVariable('LOGIN', $login);
|
||||||
|
$tpl->setVariable('RESETPASS_LINK', $resetpass_link);
|
||||||
|
|
||||||
|
$tpl->addBlock('message');
|
||||||
|
|
||||||
|
$message = "";
|
||||||
|
|
||||||
|
$tpl->generateOutputToString($message);
|
||||||
|
|
||||||
|
$mail = new ttrssMailer();
|
||||||
|
|
||||||
|
$rc = $mail->quickMail($email, $login,
|
||||||
|
__("[tt-rss] Password reset request"),
|
||||||
|
$message, false);
|
||||||
|
|
||||||
|
if (!$rc) print_error($mail->ErrorInfo);
|
||||||
|
|
||||||
|
$resetpass_token_full = $this->dbh->escape_string(time() . ":" . $resetpass_token);
|
||||||
|
|
||||||
|
$result = $this->dbh->query("UPDATE ttrss_users
|
||||||
|
SET resetpass_token = '$resetpass_token_full'
|
||||||
|
WHERE login = '$login' AND email = '$email'");
|
||||||
|
|
||||||
|
//Pref_Users::resetUserPassword($id, false);
|
||||||
|
|
||||||
|
print "<p>";
|
||||||
|
|
||||||
|
print "<p>"."Completed."."</p>";
|
||||||
|
} else {
|
||||||
|
print_error("User ID not found.");
|
||||||
|
}
|
||||||
|
|
||||||
print "<form method=\"GET\" action=\"index.php\">
|
print "<form method=\"GET\" action=\"index.php\">
|
||||||
<input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
|
<input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
|
||||||
|
@ -872,6 +900,8 @@ class Handler_Public extends Handler {
|
||||||
<title>Database Updater</title>
|
<title>Database Updater</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||||
<link rel="stylesheet" type="text/css" href="css/utility.css"/>
|
<link rel="stylesheet" type="text/css" href="css/utility.css"/>
|
||||||
|
<link rel=\"shortcut icon\" type=\"image/png\" href=\"images/favicon.png\">
|
||||||
|
<link rel=\"icon\" type=\"image/png\" sizes=\"72x72\" href=\"images/favicon-72px.png\">
|
||||||
</head>
|
</head>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
span.ok { color : #009000; font-weight : bold; }
|
span.ok { color : #009000; font-weight : bold; }
|
||||||
|
|
|
@ -257,8 +257,8 @@ class Opml extends Handler_Protected {
|
||||||
$feed_title = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('text')->nodeValue, 0, 250));
|
$feed_title = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('text')->nodeValue, 0, 250));
|
||||||
if (!$feed_title) $feed_title = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('title')->nodeValue, 0, 250));
|
if (!$feed_title) $feed_title = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('title')->nodeValue, 0, 250));
|
||||||
|
|
||||||
$feed_url = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('xmlUrl')->nodeValue, 0, 250));
|
$feed_url = $this->dbh->escape_string($attrs->getNamedItem('xmlUrl')->nodeValue);
|
||||||
if (!$feed_url) $feed_url = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('xmlURL')->nodeValue, 0, 250));
|
if (!$feed_url) $feed_url = $this->dbh->escape_string($attrs->getNamedItem('xmlURL')->nodeValue);
|
||||||
|
|
||||||
$site_url = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('htmlUrl')->nodeValue, 0, 250));
|
$site_url = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('htmlUrl')->nodeValue, 0, 250));
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,10 @@ class PluginHost {
|
||||||
const HOOK_FETCH_FEED = 22;
|
const HOOK_FETCH_FEED = 22;
|
||||||
const HOOK_QUERY_HEADLINES = 23;
|
const HOOK_QUERY_HEADLINES = 23;
|
||||||
const HOOK_HOUSE_KEEPING = 24;
|
const HOOK_HOUSE_KEEPING = 24;
|
||||||
|
const HOOK_SEARCH = 25;
|
||||||
|
const HOOK_FORMAT_ENCLOSURES = 26;
|
||||||
|
const HOOK_SUBSCRIBE_FEED = 27;
|
||||||
|
const HOOK_HEADLINES_BEFORE = 28;
|
||||||
|
|
||||||
const KIND_ALL = 1;
|
const KIND_ALL = 1;
|
||||||
const KIND_SYSTEM = 2;
|
const KIND_SYSTEM = 2;
|
||||||
|
@ -75,6 +79,16 @@ class PluginHost {
|
||||||
return $this->dbh;
|
return $this->dbh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function get_plugin_names() {
|
||||||
|
$names = array();
|
||||||
|
|
||||||
|
foreach ($this->plugins as $p) {
|
||||||
|
array_push($names, get_class($p));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $names;
|
||||||
|
}
|
||||||
|
|
||||||
function get_plugins() {
|
function get_plugins() {
|
||||||
return $this->plugins;
|
return $this->plugins;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +113,7 @@ class PluginHost {
|
||||||
|
|
||||||
function del_hook($type, $sender) {
|
function del_hook($type, $sender) {
|
||||||
if (is_array($this->hooks[$type])) {
|
if (is_array($this->hooks[$type])) {
|
||||||
$key = array_Search($this->hooks[$type], $sender);
|
$key = array_Search($sender, $this->hooks[$type]);
|
||||||
if ($key !== FALSE) {
|
if ($key !== FALSE) {
|
||||||
unset($this->hooks[$type][$key]);
|
unset($this->hooks[$type][$key]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
$cat['unread'] = 0;
|
$cat['unread'] = 0;
|
||||||
$cat['child_unread'] = 0;
|
$cat['child_unread'] = 0;
|
||||||
$cat['auxcounter'] = 0;
|
$cat['auxcounter'] = 0;
|
||||||
|
$cat['parent_id'] = $cat_id;
|
||||||
|
|
||||||
$cat['items'] = $this->get_category_items($line['id']);
|
$cat['items'] = $this->get_category_items($line['id']);
|
||||||
|
|
||||||
|
@ -395,7 +396,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
# print_r($data['items']);
|
# print_r($data['items']);
|
||||||
|
|
||||||
if (is_array($data) && is_array($data['items'])) {
|
if (is_array($data) && is_array($data['items'])) {
|
||||||
$cat_order_id = 0;
|
# $cat_order_id = 0;
|
||||||
|
|
||||||
$data_map = array();
|
$data_map = array();
|
||||||
$root_item = false;
|
$root_item = false;
|
||||||
|
@ -494,7 +495,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
$feed_id = $this->dbh->escape_string($_REQUEST["feed_id"]);
|
$feed_id = $this->dbh->escape_string($_REQUEST["feed_id"]);
|
||||||
|
|
||||||
if (is_file($icon_file) && $feed_id) {
|
if (is_file($icon_file) && $feed_id) {
|
||||||
if (filesize($icon_file) < 20000) {
|
if (filesize($icon_file) < 65535) {
|
||||||
|
|
||||||
$result = $this->dbh->query("SELECT id FROM ttrss_feeds
|
$result = $this->dbh->query("SELECT id FROM ttrss_feeds
|
||||||
WHERE id = '$feed_id' AND owner_uid = ". $_SESSION["uid"]);
|
WHERE id = '$feed_id' AND owner_uid = ". $_SESSION["uid"]);
|
||||||
|
@ -737,9 +738,9 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
<input type=\"hidden\" name=\"op\" value=\"pref-feeds\">
|
<input type=\"hidden\" name=\"op\" value=\"pref-feeds\">
|
||||||
<input type=\"hidden\" name=\"feed_id\" value=\"$feed_id\">
|
<input type=\"hidden\" name=\"feed_id\" value=\"$feed_id\">
|
||||||
<input type=\"hidden\" name=\"method\" value=\"uploadicon\">
|
<input type=\"hidden\" name=\"method\" value=\"uploadicon\">
|
||||||
<button dojoType=\"dijit.form.Button\" onclick=\"return uploadFeedIcon();\"
|
<button class=\"small\" dojoType=\"dijit.form.Button\" onclick=\"return uploadFeedIcon();\"
|
||||||
type=\"submit\">".__('Replace')."</button>
|
type=\"submit\">".__('Replace')."</button>
|
||||||
<button dojoType=\"dijit.form.Button\" onclick=\"return removeFeedIcon($feed_id);\"
|
<button class=\"small\" dojoType=\"dijit.form.Button\" onclick=\"return removeFeedIcon($feed_id);\"
|
||||||
type=\"submit\">".__('Remove')."</button>
|
type=\"submit\">".__('Remove')."</button>
|
||||||
</form>";
|
</form>";
|
||||||
|
|
||||||
|
@ -962,7 +963,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
|
|
||||||
if (!$batch) {
|
if (!$batch) {
|
||||||
|
|
||||||
$result = $this->dbh->query("UPDATE ttrss_feeds SET
|
$this->dbh->query("UPDATE ttrss_feeds SET
|
||||||
$category_qpart
|
$category_qpart
|
||||||
title = '$feed_title', feed_url = '$feed_link',
|
title = '$feed_title', feed_url = '$feed_link',
|
||||||
update_interval = '$upd_intl',
|
update_interval = '$upd_intl',
|
||||||
|
@ -1259,13 +1260,18 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
$interval_qpart = "DATE_SUB(NOW(), INTERVAL 3 MONTH)";
|
$interval_qpart = "DATE_SUB(NOW(), INTERVAL 3 MONTH)";
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->dbh->query("SELECT COUNT(*) AS num_inactive FROM ttrss_feeds WHERE
|
// could be performance-intensive and prevent feeds pref-panel from showing
|
||||||
|
if (!defined('_DISABLE_INACTIVE_FEEDS') || !_DISABLE_INACTIVE_FEEDS) {
|
||||||
|
$result = $this->dbh->query("SELECT COUNT(*) AS num_inactive FROM ttrss_feeds WHERE
|
||||||
(SELECT MAX(updated) FROM ttrss_entries, ttrss_user_entries WHERE
|
(SELECT MAX(updated) FROM ttrss_entries, ttrss_user_entries WHERE
|
||||||
ttrss_entries.id = ref_id AND
|
ttrss_entries.id = ref_id AND
|
||||||
ttrss_user_entries.feed_id = ttrss_feeds.id) < $interval_qpart AND
|
ttrss_user_entries.feed_id = ttrss_feeds.id) < $interval_qpart AND
|
||||||
ttrss_feeds.owner_uid = ".$_SESSION["uid"]);
|
ttrss_feeds.owner_uid = ".$_SESSION["uid"]);
|
||||||
|
|
||||||
$num_inactive = $this->dbh->fetch_result($result, 0, "num_inactive");
|
$num_inactive = $this->dbh->fetch_result($result, 0, "num_inactive");
|
||||||
|
} else {
|
||||||
|
$num_inactive = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ($num_inactive > 0) {
|
if ($num_inactive > 0) {
|
||||||
$inactive_button = "<button dojoType=\"dijit.form.Button\"
|
$inactive_button = "<button dojoType=\"dijit.form.Button\"
|
||||||
|
@ -1573,8 +1579,6 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
# class needed for selectTableRows()
|
# class needed for selectTableRows()
|
||||||
print "<tr class=\"placeholder\" $this_row_id>";
|
print "<tr class=\"placeholder\" $this_row_id>";
|
||||||
|
|
||||||
$edit_title = htmlspecialchars($line["title"]);
|
|
||||||
|
|
||||||
# id needed for selectTableRows()
|
# id needed for selectTableRows()
|
||||||
print "<td width='5%' align='center'><input
|
print "<td width='5%' align='center'><input
|
||||||
onclick='toggleSelectRow2(this);' dojoType=\"dijit.form.CheckBox\"
|
onclick='toggleSelectRow2(this);' dojoType=\"dijit.form.CheckBox\"
|
||||||
|
@ -1639,8 +1643,6 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
# class needed for selectTableRows()
|
# class needed for selectTableRows()
|
||||||
print "<tr class=\"placeholder\" $this_row_id>";
|
print "<tr class=\"placeholder\" $this_row_id>";
|
||||||
|
|
||||||
$edit_title = htmlspecialchars($line["title"]);
|
|
||||||
|
|
||||||
# id needed for selectTableRows()
|
# id needed for selectTableRows()
|
||||||
print "<td width='5%' align='center'><input
|
print "<td width='5%' align='center'><input
|
||||||
onclick='toggleSelectRow2(this);' dojoType=\"dijit.form.CheckBox\"
|
onclick='toggleSelectRow2(this);' dojoType=\"dijit.form.CheckBox\"
|
||||||
|
@ -1891,7 +1893,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
AND owner_uid = " . $owner_uid);
|
AND owner_uid = " . $owner_uid);
|
||||||
|
|
||||||
if ($this->dbh->num_rows($result) == 1) {
|
if ($this->dbh->num_rows($result) == 1) {
|
||||||
$key = $this->dbh->escape_string(sha1(uniqid(rand(), true)));
|
$key = $this->dbh->escape_string(uniqid(base_convert(rand(), 10, 36)));
|
||||||
|
|
||||||
$this->dbh->query("UPDATE ttrss_access_keys SET access_key = '$key'
|
$this->dbh->query("UPDATE ttrss_access_keys SET access_key = '$key'
|
||||||
WHERE feed_id = '$feed_id' AND is_cat = $sql_is_cat
|
WHERE feed_id = '$feed_id' AND is_cat = $sql_is_cat
|
||||||
|
|
|
@ -88,7 +88,6 @@ class Pref_Filters extends Handler_Protected {
|
||||||
|
|
||||||
$result = $qfh_ret[0];
|
$result = $qfh_ret[0];
|
||||||
|
|
||||||
$articles = array();
|
|
||||||
$found = 0;
|
$found = 0;
|
||||||
|
|
||||||
print __("Articles matching this filter:");
|
print __("Articles matching this filter:");
|
||||||
|
@ -97,15 +96,12 @@ class Pref_Filters extends Handler_Protected {
|
||||||
print "<table width=\"100%\" cellspacing=\"0\" id=\"prefErrorFeedList\">";
|
print "<table width=\"100%\" cellspacing=\"0\" id=\"prefErrorFeedList\">";
|
||||||
|
|
||||||
while ($line = $this->dbh->fetch_assoc($result)) {
|
while ($line = $this->dbh->fetch_assoc($result)) {
|
||||||
$line["content_preview"] = truncate_string(strip_tags($line["content_preview"]), 100, '...');
|
$line["content_preview"] = truncate_string(strip_tags($line["content"]), 100, '...');
|
||||||
|
|
||||||
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
|
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
|
||||||
$line = $p->hook_query_headlines($line, 100);
|
$line = $p->hook_query_headlines($line, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
$entry_timestamp = strtotime($line["updated"]);
|
|
||||||
$entry_tags = get_article_tags($line["id"], $_SESSION["uid"]);
|
|
||||||
|
|
||||||
$content_preview = $line["content_preview"];
|
$content_preview = $line["content_preview"];
|
||||||
|
|
||||||
if ($line["feed_title"])
|
if ($line["feed_title"])
|
||||||
|
@ -151,6 +147,40 @@ class Pref_Filters extends Handler_Protected {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getfilterrules_concise($filter_id) {
|
||||||
|
$result = $this->dbh->query("SELECT reg_exp,
|
||||||
|
inverse,
|
||||||
|
feed_id,
|
||||||
|
cat_id,
|
||||||
|
cat_filter,
|
||||||
|
ttrss_filter_types.description AS field
|
||||||
|
FROM
|
||||||
|
ttrss_filters2_rules, ttrss_filter_types
|
||||||
|
WHERE
|
||||||
|
filter_id = '$filter_id' AND filter_type = ttrss_filter_types.id");
|
||||||
|
|
||||||
|
$rv = "";
|
||||||
|
|
||||||
|
while ($line = $this->dbh->fetch_assoc($result)) {
|
||||||
|
|
||||||
|
$where = sql_bool_to_bool($line["cat_filter"]) ?
|
||||||
|
getCategoryTitle($line["cat_id"]) :
|
||||||
|
($line["feed_id"] ?
|
||||||
|
getFeedTitle($line["feed_id"]) : __("All feeds"));
|
||||||
|
|
||||||
|
# $where = $line["cat_id"] . "/" . $line["feed_id"];
|
||||||
|
|
||||||
|
$inverse = sql_bool_to_bool($line["inverse"]) ? "inverse" : "";
|
||||||
|
|
||||||
|
$rv .= "<span class='$inverse'>" . T_sprintf("%s on %s in %s %s",
|
||||||
|
strip_tags($line["reg_exp"]),
|
||||||
|
$line["field"],
|
||||||
|
$where,
|
||||||
|
sql_bool_to_bool($line["inverse"]) ? __("(inverse)") : "") . "</span>";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rv;
|
||||||
|
}
|
||||||
|
|
||||||
function getfiltertree() {
|
function getfiltertree() {
|
||||||
$root = array();
|
$root = array();
|
||||||
|
@ -174,24 +204,11 @@ class Pref_Filters extends Handler_Protected {
|
||||||
owner_uid = ".$_SESSION["uid"]." ORDER BY order_id, title");
|
owner_uid = ".$_SESSION["uid"]." ORDER BY order_id, title");
|
||||||
|
|
||||||
|
|
||||||
$action_id = -1;
|
|
||||||
$folder = array();
|
$folder = array();
|
||||||
$folder['items'] = array();
|
$folder['items'] = array();
|
||||||
|
|
||||||
while ($line = $this->dbh->fetch_assoc($result)) {
|
while ($line = $this->dbh->fetch_assoc($result)) {
|
||||||
|
|
||||||
/* if ($action_id != $line["action_id"]) {
|
|
||||||
if (count($folder['items']) > 0) {
|
|
||||||
array_push($root['items'], $folder);
|
|
||||||
}
|
|
||||||
|
|
||||||
$folder = array();
|
|
||||||
$folder['id'] = $line["action_id"];
|
|
||||||
$folder['name'] = __($line["action_name"]);
|
|
||||||
$folder['items'] = array();
|
|
||||||
$action_id = $line["action_id"];
|
|
||||||
} */
|
|
||||||
|
|
||||||
$name = $this->getFilterName($line["id"]);
|
$name = $this->getFilterName($line["id"]);
|
||||||
|
|
||||||
$match_ok = false;
|
$match_ok = false;
|
||||||
|
@ -227,6 +244,7 @@ class Pref_Filters extends Handler_Protected {
|
||||||
$filter['param'] = $name[1];
|
$filter['param'] = $name[1];
|
||||||
$filter['checkbox'] = false;
|
$filter['checkbox'] = false;
|
||||||
$filter['enabled'] = sql_bool_to_bool($line["enabled"]);
|
$filter['enabled'] = sql_bool_to_bool($line["enabled"]);
|
||||||
|
$filter['rules'] = $this->getfilterrules_concise($line['id']);
|
||||||
|
|
||||||
if (!$filter_search || $match_ok) {
|
if (!$filter_search || $match_ok) {
|
||||||
array_push($folder['items'], $filter);
|
array_push($folder['items'], $filter);
|
||||||
|
@ -433,8 +451,11 @@ class Pref_Filters extends Handler_Protected {
|
||||||
WHERE id = ".(int)$rule["filter_type"]);
|
WHERE id = ".(int)$rule["filter_type"]);
|
||||||
$filter_type = $this->dbh->fetch_result($result, 0, "description");
|
$filter_type = $this->dbh->fetch_result($result, 0, "description");
|
||||||
|
|
||||||
return T_sprintf("%s on %s in %s %s", strip_tags($rule["reg_exp"]),
|
$inverse = isset($rule["inverse"]) ? "inverse" : "";
|
||||||
$filter_type, $feed, isset($rule["inverse"]) ? __("(inverse)") : "");
|
|
||||||
|
return "<span class='filterRule $inverse'>" .
|
||||||
|
T_sprintf("%s on %s in %s %s", strip_tags($rule["reg_exp"]),
|
||||||
|
$filter_type, $feed, isset($rule["inverse"]) ? __("(inverse)") : "") . "</span>";
|
||||||
}
|
}
|
||||||
|
|
||||||
function printRuleName() {
|
function printRuleName() {
|
||||||
|
@ -471,7 +492,7 @@ class Pref_Filters extends Handler_Protected {
|
||||||
$inverse = checkbox_to_sql_bool($this->dbh->escape_string($_REQUEST["inverse"]));
|
$inverse = checkbox_to_sql_bool($this->dbh->escape_string($_REQUEST["inverse"]));
|
||||||
$title = $this->dbh->escape_string($_REQUEST["title"]);
|
$title = $this->dbh->escape_string($_REQUEST["title"]);
|
||||||
|
|
||||||
$result = $this->dbh->query("UPDATE ttrss_filters2 SET enabled = $enabled,
|
$this->dbh->query("UPDATE ttrss_filters2 SET enabled = $enabled,
|
||||||
match_any_rule = $match_any_rule,
|
match_any_rule = $match_any_rule,
|
||||||
inverse = $inverse,
|
inverse = $inverse,
|
||||||
title = '$title'
|
title = '$title'
|
||||||
|
|
|
@ -181,7 +181,8 @@ class Pref_Prefs extends Handler_Protected {
|
||||||
global $access_level_names;
|
global $access_level_names;
|
||||||
|
|
||||||
$prefs_blacklist = array("STRIP_UNSAFE_TAGS", "REVERSE_HEADLINES",
|
$prefs_blacklist = array("STRIP_UNSAFE_TAGS", "REVERSE_HEADLINES",
|
||||||
"SORT_HEADLINES_BY_FEED_DATE", "DEFAULT_ARTICLE_LIMIT");
|
"SORT_HEADLINES_BY_FEED_DATE", "DEFAULT_ARTICLE_LIMIT",
|
||||||
|
"FEEDS_SORT_BY_UNREAD");
|
||||||
|
|
||||||
/* "FEEDS_SORT_BY_UNREAD", "HIDE_READ_FEEDS", "REVERSE_HEADLINES" */
|
/* "FEEDS_SORT_BY_UNREAD", "HIDE_READ_FEEDS", "REVERSE_HEADLINES" */
|
||||||
|
|
||||||
|
@ -887,8 +888,9 @@ class Pref_Prefs extends Handler_Protected {
|
||||||
|
|
||||||
if (!$otp_enabled) {
|
if (!$otp_enabled) {
|
||||||
$secret = $base32->encode(sha1($this->dbh->fetch_result($result, 0, "salt")));
|
$secret = $base32->encode(sha1($this->dbh->fetch_result($result, 0, "salt")));
|
||||||
$topt = new \OTPHP\TOTP($secret);
|
print QRcode::png("otpauth://totp/".urlencode($login).
|
||||||
print QRcode::png($topt->provisioning_uri($login));
|
"?secret=$secret&issuer=".urlencode("Tiny Tiny RSS"));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -258,7 +258,7 @@ class Pref_Users extends Handler_Protected {
|
||||||
|
|
||||||
$pwd_hash = encrypt_password($tmp_user_pwd, $new_salt, true);
|
$pwd_hash = encrypt_password($tmp_user_pwd, $new_salt, true);
|
||||||
|
|
||||||
db_query("UPDATE ttrss_users SET pwd_hash = '$pwd_hash', salt = '$new_salt'
|
db_query("UPDATE ttrss_users SET pwd_hash = '$pwd_hash', salt = '$new_salt', otp_enabled = false
|
||||||
WHERE id = '$uid'");
|
WHERE id = '$uid'");
|
||||||
|
|
||||||
if ($show_password) {
|
if ($show_password) {
|
||||||
|
|
|
@ -95,7 +95,7 @@ class RPC extends Handler_Protected {
|
||||||
WHERE orig_feed_id = '$id') = 0 AND
|
WHERE orig_feed_id = '$id') = 0 AND
|
||||||
id = '$id' AND owner_uid = ".$_SESSION["uid"]);
|
id = '$id' AND owner_uid = ".$_SESSION["uid"]);
|
||||||
|
|
||||||
$rc = $this->dbh->affected_rows($result);
|
$this->dbh->affected_rows($result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ class RPC extends Handler_Protected {
|
||||||
$mark = "false";
|
$mark = "false";
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->dbh->query("UPDATE ttrss_user_entries SET marked = $mark,
|
$this->dbh->query("UPDATE ttrss_user_entries SET marked = $mark,
|
||||||
last_marked = NOW()
|
last_marked = NOW()
|
||||||
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
|
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
|
||||||
|
|
||||||
|
@ -148,8 +148,8 @@ class RPC extends Handler_Protected {
|
||||||
function delete() {
|
function delete() {
|
||||||
$ids = $this->dbh->escape_string($_REQUEST["ids"]);
|
$ids = $this->dbh->escape_string($_REQUEST["ids"]);
|
||||||
|
|
||||||
$result = $this->dbh->query("DELETE FROM ttrss_user_entries
|
$this->dbh->query("DELETE FROM ttrss_user_entries
|
||||||
WHERE ref_id IN ($ids) AND owner_uid = " . $_SESSION["uid"]);
|
WHERE ref_id IN ($ids) AND owner_uid = " . $_SESSION["uid"]);
|
||||||
|
|
||||||
purge_orphans();
|
purge_orphans();
|
||||||
|
|
||||||
|
@ -258,7 +258,6 @@ class RPC extends Handler_Protected {
|
||||||
function publ() {
|
function publ() {
|
||||||
$pub = $_REQUEST["pub"];
|
$pub = $_REQUEST["pub"];
|
||||||
$id = $this->dbh->escape_string($_REQUEST["id"]);
|
$id = $this->dbh->escape_string($_REQUEST["id"]);
|
||||||
$note = trim(strip_tags($this->dbh->escape_string($_REQUEST["note"])));
|
|
||||||
|
|
||||||
if ($pub == "1") {
|
if ($pub == "1") {
|
||||||
$pub = "true";
|
$pub = "true";
|
||||||
|
@ -266,7 +265,7 @@ class RPC extends Handler_Protected {
|
||||||
$pub = "false";
|
$pub = "false";
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->dbh->query("UPDATE ttrss_user_entries SET
|
$this->dbh->query("UPDATE ttrss_user_entries SET
|
||||||
published = $pub, last_published = NOW()
|
published = $pub, last_published = NOW()
|
||||||
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
|
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
|
||||||
|
|
||||||
|
@ -620,7 +619,7 @@ class RPC extends Handler_Protected {
|
||||||
|
|
||||||
$p = new Publisher(PUBSUBHUBBUB_HUB);
|
$p = new Publisher(PUBSUBHUBBUB_HUB);
|
||||||
|
|
||||||
$pubsub_result = $p->publish_update($rss_link);
|
/* $pubsub_result = */ $p->publish_update($rss_link);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,13 +104,9 @@
|
||||||
// Enable client PubSubHubbub support in tt-rss. When disabled, tt-rss
|
// Enable client PubSubHubbub support in tt-rss. When disabled, tt-rss
|
||||||
// won't try to subscribe to PUSH feed updates.
|
// won't try to subscribe to PUSH feed updates.
|
||||||
|
|
||||||
// *********************
|
// ****************************
|
||||||
// *** Sphinx search ***
|
// *** Sphinx search plugin ***
|
||||||
// *********************
|
// ****************************
|
||||||
|
|
||||||
define('SPHINX_ENABLED', false);
|
|
||||||
// Enable fulltext search using Sphinx (http://www.sphinxsearch.com)
|
|
||||||
// Please see http://tt-rss.org/wiki/SphinxSearch for more information.
|
|
||||||
|
|
||||||
define('SPHINX_SERVER', 'localhost:9312');
|
define('SPHINX_SERVER', 'localhost:9312');
|
||||||
// Hostname:port combination for the Sphinx server.
|
// Hostname:port combination for the Sphinx server.
|
||||||
|
@ -184,6 +180,12 @@
|
||||||
define('CHECK_FOR_NEW_VERSION', true);
|
define('CHECK_FOR_NEW_VERSION', true);
|
||||||
// Check for new versions of tt-rss automatically.
|
// Check for new versions of tt-rss automatically.
|
||||||
|
|
||||||
|
define('DETECT_ARTICLE_LANGUAGE', false);
|
||||||
|
// Detect article language when updating feeds, presently this is only
|
||||||
|
// used for hyphenation. This may increase amount of CPU time used by
|
||||||
|
// update processes, disable if necessary (i.e. you are being billed
|
||||||
|
// for CPU time).
|
||||||
|
|
||||||
define('ENABLE_GZIP_OUTPUT', false);
|
define('ENABLE_GZIP_OUTPUT', false);
|
||||||
// Selectively gzip output to improve wire performance. This requires
|
// Selectively gzip output to improve wire performance. This requires
|
||||||
// PHP Zlib extension on the server.
|
// PHP Zlib extension on the server.
|
||||||
|
@ -211,4 +213,3 @@
|
||||||
// if necessary (after migrating all new options from this file).
|
// if necessary (after migrating all new options from this file).
|
||||||
|
|
||||||
// vim:ft=php
|
// vim:ft=php
|
||||||
?>
|
|
||||||
|
|
|
@ -52,7 +52,8 @@ div.cdmHeader input {
|
||||||
|
|
||||||
div.cdmContentInner {
|
div.cdmContentInner {
|
||||||
margin : 10px;
|
margin : 10px;
|
||||||
line-height : 20px;
|
line-height : 1.5;
|
||||||
|
font-size : 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.cdmContentInner img {
|
div.cdmContentInner img {
|
||||||
|
@ -61,6 +62,16 @@ div.cdmContentInner img {
|
||||||
height : auto;
|
height : auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.cdmContentInner h1 {
|
||||||
|
font-size : 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.cdmContentInner h2,
|
||||||
|
div.cdmContentInner h3,
|
||||||
|
div.cdmContentInner h4 {
|
||||||
|
font-size : 15px;
|
||||||
|
}
|
||||||
|
|
||||||
div.cdmFooter {
|
div.cdmFooter {
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
font-weight : normal;
|
font-weight : normal;
|
||||||
|
@ -68,15 +79,25 @@ div.cdmFooter {
|
||||||
clear : both;
|
clear : both;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.cdm {
|
||||||
|
margin-right : 4px;
|
||||||
|
}
|
||||||
|
|
||||||
div.cdm.expanded {
|
div.cdm.expanded {
|
||||||
margin-top : 4px;
|
margin-top : 4px;
|
||||||
margin-bottom : 4px;
|
margin-bottom : 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.cdm.expanded div.cdmFooter {
|
||||||
|
border-style : solid;
|
||||||
|
border-width : 0px 0px 1px 0px;
|
||||||
|
border-color : #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
div.cdm.expandable {
|
div.cdm.expandable {
|
||||||
background-color : #f0f0f0;
|
background-color : #f0f0f0;
|
||||||
border-width : 0px 0px 1px 0px;
|
border-width : 0px 0px 1px 0px;
|
||||||
border-color : #c0c0c0;
|
border-color : #ddd;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,8 +119,6 @@ div.cdm.expandable.Selected {
|
||||||
}
|
}
|
||||||
|
|
||||||
div.cdm.expandable.active {
|
div.cdm.expandable.active {
|
||||||
box-shadow : inset 0px 0px 3px 0px rgba(0,0,0,0.1);
|
|
||||||
border-color : #88b0f0;
|
|
||||||
background : white ! important;
|
background : white ! important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,10 +134,15 @@ div.cdm.expandable.active div.cdmHeader span.titleWrap {
|
||||||
}
|
}
|
||||||
|
|
||||||
div.cdm.expandable div.cdmHeader a.title {
|
div.cdm.expandable div.cdmHeader a.title {
|
||||||
font-weight : bold;
|
font-weight : 600;
|
||||||
color : #555;
|
color : #555;
|
||||||
|
font-size : 14px;
|
||||||
-webkit-transition : color 0.2s;
|
-webkit-transition : color 0.2s;
|
||||||
transition : color 0.2s;
|
transition : color 0.2s;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.cdm.expandable.Unread div.cdmHeader a.title {
|
div.cdm.expandable.Unread div.cdmHeader a.title {
|
||||||
|
@ -127,6 +151,12 @@ div.cdm.expandable.Unread div.cdmHeader a.title {
|
||||||
|
|
||||||
div.cdm.expandable.active div.cdmHeader a.title {
|
div.cdm.expandable.active div.cdmHeader a.title {
|
||||||
color : #4684ff;
|
color : #4684ff;
|
||||||
|
font-size : 16px;
|
||||||
|
font-weight : 600;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.cdm.expanded div.cdmHeader {
|
div.cdm.expanded div.cdmHeader {
|
||||||
|
@ -134,11 +164,15 @@ div.cdm.expanded div.cdmHeader {
|
||||||
}
|
}
|
||||||
|
|
||||||
div.cdm.expanded div.cdmHeader a.title {
|
div.cdm.expanded div.cdmHeader a.title {
|
||||||
font-size : 14px;
|
font-size : 16px;
|
||||||
color : #999;
|
color : #999;
|
||||||
font-weight : bold;
|
font-weight : 600;
|
||||||
-webkit-transition : color 0.2s;
|
-webkit-transition : color 0.2s;
|
||||||
transition : color 0.2s;
|
transition : color 0.2s;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.cdm.expanded.active {
|
div.cdm.expanded.active {
|
||||||
|
@ -167,7 +201,7 @@ div.cdm.active div.cdmContent {
|
||||||
|
|
||||||
span.cdmExcerpt {
|
span.cdmExcerpt {
|
||||||
font-size : 11px;
|
font-size : 11px;
|
||||||
color : #555;
|
color : #999;
|
||||||
font-weight : normal;
|
font-weight : normal;
|
||||||
cursor : pointer;
|
cursor : pointer;
|
||||||
}
|
}
|
||||||
|
@ -222,7 +256,6 @@ div.cdm .hlFeed a {
|
||||||
|
|
||||||
div.cdmContentInner p {
|
div.cdmContentInner p {
|
||||||
max-width : 650px;
|
max-width : 650px;
|
||||||
text-align : justify;
|
|
||||||
-webkit-hyphens: auto;
|
-webkit-hyphens: auto;
|
||||||
-moz-hyphens: auto;
|
-moz-hyphens: auto;
|
||||||
hyphens: auto;
|
hyphens: auto;
|
||||||
|
@ -242,15 +275,15 @@ div.cdmHeader span.author {
|
||||||
div#floatingTitle {
|
div#floatingTitle {
|
||||||
position : absolute;
|
position : absolute;
|
||||||
z-index : 5;
|
z-index : 5;
|
||||||
top : 25px;
|
top : 0px;
|
||||||
right : 0px;
|
right : 0px;
|
||||||
left : 0px;
|
left : 0px;
|
||||||
border-color : #ccc;
|
border-color : #ddd;
|
||||||
border-width : 1px 0px 1px 0px;
|
border-width : 0px 0px 1px 0px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
background : #fcfcfc;
|
background : white;
|
||||||
color : #555;
|
color : #555;
|
||||||
box-shadow : 0px 1px 1px 0px rgba(0,0,0,0.1);
|
box-shadow : 0px 1px 1px -1px rgba(0,0,0,0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
div#floatingTitle > * {
|
div#floatingTitle > * {
|
||||||
|
@ -272,11 +305,15 @@ div#floatingTitle span.author {
|
||||||
}
|
}
|
||||||
|
|
||||||
div#floatingTitle a.title {
|
div#floatingTitle a.title {
|
||||||
font-size : 14px;
|
font-size : 16px;
|
||||||
color : #999;
|
color : #999;
|
||||||
font-weight : bold;
|
|
||||||
-webkit-transition : color 0.2s;
|
-webkit-transition : color 0.2s;
|
||||||
transition : color 0.2s;
|
transition : color 0.2s;
|
||||||
|
font-weight : 600;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#floatingTitle.Unread a.title {
|
div#floatingTitle.Unread a.title {
|
||||||
|
@ -284,7 +321,6 @@ div#floatingTitle.Unread a.title {
|
||||||
}
|
}
|
||||||
|
|
||||||
div#floatingTitle img.anchor {
|
div#floatingTitle img.anchor {
|
||||||
margin-right : 1px;
|
|
||||||
margin-left : 0px;
|
margin-left : 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,4 +377,24 @@ div#floatingTitle img.hlScorePic {
|
||||||
text-decoration : line-through;
|
text-decoration : line-through;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.cdmFeedTitle > * {
|
||||||
|
display : table-cell;
|
||||||
|
vertical-align : middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.cdmFeedTitle a.title {
|
||||||
|
width : 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.cdmFeedTitle a.catchup {
|
||||||
|
text-align : right;
|
||||||
|
color : #555;
|
||||||
|
padding-right : 10px;
|
||||||
|
font-size : 11px;
|
||||||
|
white-space : nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.cdmFeedTitle a.catchup:hover {
|
||||||
|
color : #4684ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
409
source/css/dijit.css
Normal file
|
@ -0,0 +1,409 @@
|
||||||
|
/* Tree */
|
||||||
|
|
||||||
|
.claro .dijitTreeRow .dijitCheckBox {
|
||||||
|
position : relative;
|
||||||
|
top : -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeLabel {
|
||||||
|
outline : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .feedParam {
|
||||||
|
color : #555;
|
||||||
|
float : right;
|
||||||
|
margin-right : 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .filterRules {
|
||||||
|
display : block;
|
||||||
|
color : #ccc;
|
||||||
|
font-size : 10px;
|
||||||
|
margin-left : 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .filterRules span {
|
||||||
|
display : block;
|
||||||
|
color : green;
|
||||||
|
}
|
||||||
|
|
||||||
|
#filterDlg_Matches span.filterRule {
|
||||||
|
color : green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .filterRules span.inverse,
|
||||||
|
#filterDlg_Matches span.filterRule.inverse {
|
||||||
|
color : red;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.claro .dijitTree .labelParam {
|
||||||
|
float : right;
|
||||||
|
margin-right : 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .dijitTreeLabel.Disabled,
|
||||||
|
.claro .dijitTree .labelParam.Disabled {
|
||||||
|
color : #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeRow.Error {
|
||||||
|
color : red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeRow.Hidden {
|
||||||
|
display : none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeNode .loadingNode {
|
||||||
|
margin-left : 3px;
|
||||||
|
height : 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitFolderClosed,
|
||||||
|
.claro .dijitFolderOpened {
|
||||||
|
display : none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeNode .dijitCheckBox {
|
||||||
|
margin-left : 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeIsRoot > .dijitTreeRow > .dijitTreeExpando {
|
||||||
|
margin-left : 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .dijitTreeExpando {
|
||||||
|
margin-top : 0px;
|
||||||
|
opacity : 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .dijitTreeNode {
|
||||||
|
padding : 0px;
|
||||||
|
border-width : 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .dijitTreeRow {
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .dijitTreeRowSelected {
|
||||||
|
background : white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .dijitTreeRowHover {
|
||||||
|
background : #f0f0f0;
|
||||||
|
border-color : #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .dijitTreeRowSelected {
|
||||||
|
background : white;
|
||||||
|
border-color : #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeRowSelected .dijitTreeLabel {
|
||||||
|
text-shadow : 1px 1px 2px #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeRow .dijitTreeExpando {
|
||||||
|
background-image: url("../images/treeExpandImages.png");
|
||||||
|
position : relative;
|
||||||
|
top : -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeRow .dijitTreeExpandoLeaf {
|
||||||
|
background : none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Toolbar */
|
||||||
|
|
||||||
|
.claro .dijitToolbar {
|
||||||
|
background : #f5f5f5;
|
||||||
|
border-color : #ddd;
|
||||||
|
/* text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif; */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .claro .dijitToolbar {
|
||||||
|
text-shadow : 1px 1px 2px #fff;
|
||||||
|
} */
|
||||||
|
|
||||||
|
.claro .dijitDialog .dijitToolbar {
|
||||||
|
border : 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dialog */
|
||||||
|
|
||||||
|
.claro .dijitDialog h2 {
|
||||||
|
margin-top : 0px;
|
||||||
|
margin-bottom : 4px;
|
||||||
|
border-width : 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitMenuItemLabel {
|
||||||
|
font-size : 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checkbox */
|
||||||
|
|
||||||
|
.claro .dijitCheckBox {
|
||||||
|
background-image : url("../images/untick.png");
|
||||||
|
background-color : transparent;
|
||||||
|
width : 15px;
|
||||||
|
height : 15px;
|
||||||
|
margin : 1px;
|
||||||
|
opacity : 0.7;
|
||||||
|
background-position : center center;
|
||||||
|
transition : opacity 0.25s;
|
||||||
|
-webkit-transition : opacity 0.25s;
|
||||||
|
/* border : 1px solid #b5bcc7; */
|
||||||
|
padding : 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitCheckBox:hover {
|
||||||
|
opacity : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitCheckBox.dijitCheckBoxDisabled:hover {
|
||||||
|
opacity : 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitCheckBox.dijitCheckBoxChecked {
|
||||||
|
border-color : #69C671;
|
||||||
|
background-image : url("../images/tick.png");
|
||||||
|
opacity : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Various buttons */
|
||||||
|
|
||||||
|
.claro .dijitButton .dijitButtonNode,
|
||||||
|
.claro .dijitComboButton .dijitButtonNode,
|
||||||
|
.claro .dijitToolbar .dijitDropDownButton .dijitButtonNode,
|
||||||
|
.claro .dijitToolbar .dijitComboButton,
|
||||||
|
.claro .dijitToolbar .dijitComboButton .dijitButtonNode {
|
||||||
|
background : none;
|
||||||
|
border-color : transparent;
|
||||||
|
box-shadow : none;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
input[type="submit"] {
|
||||||
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
font-size : 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
input[type="submit"],
|
||||||
|
.claro .dijitButton,
|
||||||
|
.claro .dijitComboButton {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 4px 12px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px;
|
||||||
|
color: #333333;
|
||||||
|
text-align: center;
|
||||||
|
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
|
||||||
|
vertical-align: middle;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
|
||||||
|
background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
|
||||||
|
background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||||
|
border-bottom-color: #b3b3b3;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover,
|
||||||
|
button:focus,
|
||||||
|
button:active,
|
||||||
|
input[type="submit"]:hover,
|
||||||
|
input[type="submit"]:focus,
|
||||||
|
input[type="submit"]:active,
|
||||||
|
.claro .dijitButton:hover,
|
||||||
|
.claro .dijitButton:focus,
|
||||||
|
.claro .dijitButton:active,
|
||||||
|
.claro .dijitComboButton:hover,
|
||||||
|
.claro .dijitComboButton:focus,
|
||||||
|
.claro .dijitComboButton:active,
|
||||||
|
.claro .dijitButton.dijitButtonDisabled {
|
||||||
|
color: #333333;
|
||||||
|
background-color: #e6e6e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:active,
|
||||||
|
input[type="submit"]:active,
|
||||||
|
.claro .dijitButton:active,
|
||||||
|
.claro .dijitComboButton:active {
|
||||||
|
background-color: #cccccc \9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitToolbar .dijitButton,
|
||||||
|
.claro .dijitToolbar .dijitButton.dijitHover,
|
||||||
|
.claro .dijitToolbar .dijitComboButton,
|
||||||
|
.claro .dijitToolbar .dijitComboButton.dijitHover {
|
||||||
|
background : none;
|
||||||
|
border-color : transparent;
|
||||||
|
box-shadow : none;
|
||||||
|
padding : 0px;
|
||||||
|
margin : 0px;
|
||||||
|
line-height : auto;
|
||||||
|
text-shadow : none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitToolbar .dijitDropDownButton .dijitButtonText,
|
||||||
|
.claro .dijitToolbar .dijitComboButton .dijitButtonText {
|
||||||
|
padding : 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitToolbar .dijitDropDownButton .dijitButtonNode {
|
||||||
|
border-radius : 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitToolbar .dijitButton.dijitHover,
|
||||||
|
.claro .dijitToolbar .dijitDropDownButton.dijitHover .dijitButtonNode,
|
||||||
|
.claro .dijitToolbar .dijitComboButton.dijitHover {
|
||||||
|
border-color : #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitToolbar .dijitButton.dijitHover .dijitButtonNode,
|
||||||
|
.claro .dijitToolbar .dijitButton.dijitButtonActive .dijitButtonNode {
|
||||||
|
background : none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitToolbar .dijitButton .dijitButtonContents,
|
||||||
|
.claro .dijitToolbar .dijitDropDownButton .dijitButtonContents,
|
||||||
|
.claro .dijitToolbar .dijitComboButton .dijitButtonContents {
|
||||||
|
font-size : 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover,
|
||||||
|
button:focus,
|
||||||
|
input[type="submit"]:hover,
|
||||||
|
input[type="submit"]:focus,
|
||||||
|
.claro .dijitButton:hover,
|
||||||
|
.claro .dijitToolbar .dijitButton:hover .dijitButtonNode,
|
||||||
|
.claro .dijitToolbar .dijitButton.dijitHover .dijitButtonNode,
|
||||||
|
.claro .dijitButton:focus,
|
||||||
|
.claro .dijitComboButton:hover,
|
||||||
|
.claro .dijitComboButton:focus {
|
||||||
|
color: #333333;
|
||||||
|
text-decoration: none;
|
||||||
|
background-position: 0 -15px;
|
||||||
|
-webkit-transition: background-position 0.1s linear;
|
||||||
|
transition: background-position 0.1s linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:focus,
|
||||||
|
input[type="submit"]:focus,
|
||||||
|
.claro .dijitButton:focus,
|
||||||
|
.claro .dijitComboButton:focus {
|
||||||
|
outline: thin dotted #333;
|
||||||
|
outline: 5px auto -webkit-focus-ring-color;
|
||||||
|
outline-offset: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:active,
|
||||||
|
input[type="submit"]:active,
|
||||||
|
.claro .dijitButton:active,
|
||||||
|
.claro .dijitComboButton:active,
|
||||||
|
.claro .dijitToolbar .dijitDropDownButton.dijitOpened,
|
||||||
|
.claro .dijitToolbar .dijitComboButton.dijitOpened,
|
||||||
|
.claro .dijitToolbar .dijitButton.dijitButtonActive .dijitButtonNode {
|
||||||
|
background-image: none;
|
||||||
|
outline: 0;
|
||||||
|
-webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="submit"][disabled],
|
||||||
|
button[disabled],
|
||||||
|
.claro .dijitButton[disabled],
|
||||||
|
.claro .dijitButton.dijitButtonDisabled,
|
||||||
|
.claro .dijitComboButton.dijitButtonDisabled {
|
||||||
|
cursor: default;
|
||||||
|
background-image: none;
|
||||||
|
opacity: 0.65;
|
||||||
|
filter: alpha(opacity=65);
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitButton .dijitButtonContents,
|
||||||
|
.claro .dijitComboButton .dijitButtonContents {
|
||||||
|
font-size : 14px;
|
||||||
|
font-weight : normal;
|
||||||
|
line-height : 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitButton.small .dijitButtonText {
|
||||||
|
font-size : 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitMenu {
|
||||||
|
border-color : #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitMenu .dijitMenuItem.dijitHover,
|
||||||
|
.claro .dijitMenu .dijitMenuItem.dijitFocused,
|
||||||
|
.claro .dijitMenuTable .dijitMenuItem.dijitHover .dijitMenuItemLabel,
|
||||||
|
.claro .dijitMenuTable .dijitMenuItem.dijitFocused .dijitMenuItemLabel {
|
||||||
|
background : #eee;
|
||||||
|
border-color : transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitButton .dijitButtonNode,
|
||||||
|
.claro .dijitComboButton .dijitButtonNode {
|
||||||
|
padding : 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Other stuff */
|
||||||
|
|
||||||
|
/* .claro .dijitAccordionTitleFocus {
|
||||||
|
text-shadow : 1px 1px 2px #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitAccordionTitle {
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
|
} */
|
||||||
|
|
||||||
|
.claro .dijitAccordionInnerContainer.dijitAccordionInnerContainerSelected {
|
||||||
|
border-color : #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitAccordionContainer .dijitAccordionChildWrapper {
|
||||||
|
border-color : #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tabs */
|
||||||
|
|
||||||
|
.claro .dijitTabContent {
|
||||||
|
background : #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTabContent.dijitTabChecked,
|
||||||
|
.claro .dijitTabContent.dijitTabHover,
|
||||||
|
.claro .dijitTabContent.dijitFocused {
|
||||||
|
background : white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTabPaneWrapper,
|
||||||
|
.claro .dijitTabContainerTop-tabs,
|
||||||
|
.claro .dijitTab,
|
||||||
|
.claro .dijitAccordionInnerContainer {
|
||||||
|
border-color : #ddd;
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,14 @@
|
||||||
|
body#ttrssPrefs {
|
||||||
|
background-color : #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssPrefs #footer, body#ttrssPrefs #header {
|
||||||
|
background-color : #f5f5f5;
|
||||||
|
padding-left : 8px;
|
||||||
|
padding-right : 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#header a:hover {
|
#header a:hover {
|
||||||
color : black;
|
color : black;
|
||||||
}
|
}
|
||||||
|
@ -13,12 +24,12 @@ div#pref-tabs .dijitContentPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
div#pref-tabs {
|
div#pref-tabs {
|
||||||
|
box-shadow : 0px 1px 1px -1px rgba(0,0,0,0.1);
|
||||||
margin : 0px 5px 0px 5px;
|
margin : 0px 5px 0px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#pref-tabs .dijitContentPane h3 {
|
div#pref-tabs .dijitContentPane h3 {
|
||||||
font-size : 14px;
|
font-size : 14px;
|
||||||
font-weight : bold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pref-filter-wrap, #pref-filter-header, #pref-filter-content,
|
#pref-filter-wrap, #pref-filter-header, #pref-filter-content,
|
||||||
|
@ -52,11 +63,10 @@ div.prefProfileHolder, div.prefFeedOPMLHolder, div.inactiveFeedHolder {
|
||||||
height : 300px;
|
height : 300px;
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
border-width : 0px 1px 1px 1px;
|
border-width : 0px 1px 1px 1px;
|
||||||
border-color : #c0c0c0;
|
border-color : #ddd;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
margin : 0px 0px 5px 0px;
|
margin : 0px 0px 5px 0px;
|
||||||
background-color : #ecf4ff;
|
background-color : white;
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
div.filterTestHolder, div.prefFeedOPMLHolder {
|
div.filterTestHolder, div.prefFeedOPMLHolder {
|
||||||
border-width : 1px;
|
border-width : 1px;
|
||||||
|
@ -66,12 +76,10 @@ ul.selfUpdateList, ul.userFeedList {
|
||||||
height : 200px;
|
height : 200px;
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
list-style-type : none;
|
list-style-type : none;
|
||||||
border : 1px solid #c0c0c0;
|
border : 1px solid #ddd;
|
||||||
background-color : #ecf4ff;
|
background-color : #f5f5f5;
|
||||||
margin : 0px 0px 5px 0px;
|
margin : 0px 0px 5px 0px;
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
border-radius : 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div#feedlistLoading, div#filterlistLoading, div#labellistLoading {
|
div#feedlistLoading, div#filterlistLoading, div#labellistLoading {
|
||||||
|
@ -90,7 +98,8 @@ div#feedlistLoading img, div#filterlistLoading img, div#labellistLoading {
|
||||||
|
|
||||||
a.bookmarklet {
|
a.bookmarklet {
|
||||||
color : #4684ff;
|
color : #4684ff;
|
||||||
border : 1px solid #ecf4ff;
|
border : 1px solid #ddd;
|
||||||
|
background : #f5f5f5;
|
||||||
padding : 2px;
|
padding : 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +129,9 @@ table.prefErrorLog td.filename, table.prefErrorLog td.login, table.prefErrorLog
|
||||||
color : #555;
|
color : #555;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dijitAccordionContainer-child {
|
body#ttrssPrefs hr {
|
||||||
box-shadow : inset 0px 0px 3px rgba(0,0,0,0.2);
|
border-color : #ecf4ff;
|
||||||
|
max-width : 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,34 +7,28 @@ body#ttrssMain, body#ttrssPrefs, body#ttrssLogin, body {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
body#ttrssPrefs {
|
|
||||||
background-color : #ecf4ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssPrefs #footer, body#ttrssPrefs #header {
|
|
||||||
background-color : #ecf4ff;
|
|
||||||
padding-left : 8px;
|
|
||||||
padding-right : 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.postReply {
|
div.postReply {
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.postReply div.postHeader {
|
div.postReply div.postHeader {
|
||||||
border-width : 0px 0px 1px 0px;
|
|
||||||
border-style : solid;
|
|
||||||
border-color : #c0c0c0;
|
|
||||||
background : #fafafa;
|
|
||||||
box-shadow : 0px 0px 3px 0px rgba(0,0,0,0.1);
|
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
|
margin-right : 4px;
|
||||||
color : #909090;
|
color : #909090;
|
||||||
|
border-width : 0px 0px 1px 0px;
|
||||||
|
border-color : #ddd;
|
||||||
|
border-style : solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.postReply div.postTitle {
|
div.postReply div.postTitle {
|
||||||
overflow : hidden;
|
overflow : hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space : nowrap;
|
white-space : nowrap;
|
||||||
|
font-weight : 600;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.postReply div.postDate {
|
div.postReply div.postDate {
|
||||||
|
@ -66,13 +60,10 @@ div.postReply img.tagsPic {
|
||||||
div.articleNote {
|
div.articleNote {
|
||||||
background-color : #fff7d5;
|
background-color : #fff7d5;
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
border-radius : 4px;
|
|
||||||
margin : 5px;
|
margin : 5px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #e7d796;
|
border-color : #e7d796;
|
||||||
border-width : 1px;
|
border-width : 1px;
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
background-color : #fff7d5;
|
|
||||||
color : #9a8c59;
|
color : #9a8c59;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,29 +78,50 @@ div.postReply span.author {
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size : 18px;
|
font-size : 18px;
|
||||||
|
font-weight : 600;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-size : 16px;
|
font-size : 16px;
|
||||||
font-weight : bold;
|
font-weight : 600;
|
||||||
border-width : 0px 0px 1px 0px;
|
border-width : 0px 0px 1px 0px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #ecf4ff;
|
border-color : #ecf4ff;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
font-size : 12px;
|
font-size : 13px;
|
||||||
font-weight : bold;
|
|
||||||
border-width : 0px 0px 1px 0px;
|
border-width : 0px 0px 1px 0px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #ecf4ff;
|
border-color : #ecf4ff;
|
||||||
|
font-weight : 600;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size : 14px;
|
||||||
|
font-weight : 600;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border-width : 0px 0px 1px 0px;
|
border-width : 0px 0px 1px 0px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #c0c0c0;
|
border-color : #ccc;
|
||||||
max-width : 90%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
@ -138,7 +150,6 @@ a:hover {
|
||||||
min-width : 100px;
|
min-width : 100px;
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
-width : 200px;
|
-width : 200px;
|
||||||
box-shadow : 0px 0px 2px rgba(0,0,0,0.2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#notify img {
|
#notify img {
|
||||||
|
@ -181,7 +192,11 @@ a:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
.hl div.hlTitle a {
|
.hl div.hlTitle a {
|
||||||
font-weight : bold;
|
font-weight : 600;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
color : #777;
|
color : #777;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,13 +204,9 @@ a:hover {
|
||||||
color : black;
|
color : black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hl.active {
|
|
||||||
box-shadow : inset 0px 0px 3px 0px rgba(0,0,0,0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hl.active div.hlTitle a {
|
.hl.active div.hlTitle a {
|
||||||
color : #4684ff;
|
color : #4684ff;
|
||||||
text-shadow : 1px 1px 2px #fff;
|
/* text-shadow : 1px 1px 2px #fff; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.hl.Selected {
|
.hl.Selected {
|
||||||
|
@ -206,18 +217,11 @@ a:hover {
|
||||||
color : #909090;
|
color : #909090;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #headlines-frame div.hl:nth-child(even) {
|
|
||||||
background : #fafafa;
|
|
||||||
} */
|
|
||||||
|
|
||||||
#headlines-frame.normal {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.hl {
|
.hl {
|
||||||
border-width : 0px 0px 1px 0px;
|
border-width : 0px 0px 1px 0px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #c0c0c0;
|
border-color : #ddd;
|
||||||
|
padding : 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hl.active {
|
.hl.active {
|
||||||
|
@ -227,13 +231,11 @@ a:hover {
|
||||||
div.filterTestHolder {
|
div.filterTestHolder {
|
||||||
height : 300px;
|
height : 300px;
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
border-color : #c0c0c0;
|
border-color : #ddd;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
margin : 0px 0px 5px 0px;
|
margin : 0px 0px 5px 0px;
|
||||||
background-color : #ecf4ff;
|
background-color : #f5f5f5;
|
||||||
border-width : 1px;
|
border-width : 1px;
|
||||||
border-radius : 4px;
|
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -242,7 +244,7 @@ div.filterTestHolder {
|
||||||
color : #555;
|
color : #555;
|
||||||
padding-left : 10px;
|
padding-left : 10px;
|
||||||
border-width : 0px 0px 0px 4px;
|
border-width : 0px 0px 0px 4px;
|
||||||
border-color : #c0c0c0;
|
border-color : #ccc;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,9 +261,9 @@ div.filterTestHolder {
|
||||||
font-family : monospace;
|
font-family : monospace;
|
||||||
font-size : 12px;
|
font-size : 12px;
|
||||||
border-width : 0px;
|
border-width : 0px;
|
||||||
border-color : #c0c0c0;
|
border-color : #ccc;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
background : #fafafa;
|
background : #f5f5f5;
|
||||||
display : block;
|
display : block;
|
||||||
max-width : 98%;
|
max-width : 98%;
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
|
@ -274,9 +276,7 @@ div.notice, div.warning, div.error {
|
||||||
font-size : 12px;
|
font-size : 12px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #ccc;
|
border-color : #ccc;
|
||||||
border-radius : 4px;
|
|
||||||
border-width : 1px;
|
border-width : 1px;
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.notice div.inner, div.warning div.inner, div.error div.inner {
|
div.notice div.inner, div.warning div.inner, div.error div.inner {
|
||||||
|
@ -324,47 +324,66 @@ div.prefHelp {
|
||||||
color : #555;
|
color : #555;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#headlines-toolbar {
|
#main-toolbar > * {
|
||||||
border-width : 0px 0px 1px 0px;
|
white-space : nowrap;
|
||||||
background-color : #fcfcfc;
|
display : table-cell;
|
||||||
border-color : #c0c0c0;
|
color : #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-toolbar > *,
|
||||||
|
#main-toolbar table *,
|
||||||
|
#main-toolbar .actionChooser * {
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP", "Segoe UI Web", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
font-size : 12px;
|
font-size : 12px;
|
||||||
font-family : "Segoe UI", Tahoma, sans-serif;
|
|
||||||
color : #555;
|
|
||||||
padding : 0px;
|
|
||||||
margin : 0px;
|
|
||||||
overflow : hidden;
|
|
||||||
height : 25px;
|
|
||||||
line-height : 25px;
|
|
||||||
padding-left : 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div#headlines-toolbar .dijitSelect {
|
#main-toolbar #headlines-toolbar {
|
||||||
font-size : 11px;
|
padding-right : 4px;
|
||||||
position : relative;
|
width : 100%;
|
||||||
top : -2px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div#headlines-toolbar span.r {
|
#main-toolbar #headlines-toolbar span.holder {
|
||||||
float: right;
|
display : table;
|
||||||
position: relative;
|
width : 100%;
|
||||||
padding : 0 4px 0px 4px;
|
}
|
||||||
|
|
||||||
|
#main-toolbar #headlines-toolbar span.holder > * {
|
||||||
|
display : table-cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-toolbar #headlines-toolbar .main {
|
||||||
text-align : right;
|
text-align : right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#main-toolbar #headlines-toolbar .main,
|
||||||
|
#main-toolbar #headlines-toolbar .r {
|
||||||
|
line-height : 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#headlines-toolbar span.r img {
|
||||||
|
margin-right : 4px;
|
||||||
|
position : relative;
|
||||||
|
top : 3px;
|
||||||
|
}
|
||||||
|
|
||||||
#headlines-toolbar span.r .error a {
|
#headlines-toolbar span.r .error a {
|
||||||
color : red;
|
color : red;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#headlines-toolbar span.r a {
|
#main-toolbar #selected_prompt {
|
||||||
color : #555;
|
font-style : italic;
|
||||||
|
text-align : right;
|
||||||
|
margin-right : 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.contentPreview {
|
span.contentPreview {
|
||||||
color : #999;
|
color : #999;
|
||||||
font-weight : normal;
|
font-weight : normal;
|
||||||
text-shadow : 1px 1px 2px #fff;
|
font-size : 12px;
|
||||||
font-size : 11px;
|
padding-left : 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.hlLabelRef {
|
span.hlLabelRef {
|
||||||
|
@ -397,63 +416,50 @@ div.postHeader div {
|
||||||
#allEntryTags {
|
#allEntryTags {
|
||||||
border-width : 0px 0px 1px 0px;
|
border-width : 0px 0px 1px 0px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #c0c0c0;
|
border-color : #ddd;
|
||||||
padding-bottom : 5px;
|
padding-bottom : 5px;
|
||||||
display : none;
|
display : none;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.hlFeed {
|
|
||||||
display : block;
|
|
||||||
white-space : nowrap;
|
|
||||||
font-size : 9px;
|
|
||||||
font-style : italic;
|
|
||||||
font-weight : normal;
|
|
||||||
border-radius : 4px;
|
|
||||||
display : inline-block;
|
|
||||||
padding : 1px 2px 1px 2px;
|
|
||||||
margin-bottom : 2px;
|
|
||||||
margin-top : 2px;
|
|
||||||
color : #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.hlFeed:hover {
|
|
||||||
color : #4684ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
img.markedPic, img.pubPic {
|
img.markedPic, img.pubPic {
|
||||||
cursor : pointer;
|
cursor : pointer;
|
||||||
vertical-align : middle;
|
vertical-align : middle;
|
||||||
|
opacity : 0.5;
|
||||||
|
-webkit-transition : opacity 0.25s;
|
||||||
|
transition : opacity 0.25s;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.markedPic:hover, img.pubPic:hover {
|
||||||
|
opacity : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
img[src*='pub_set.png'], img[src*='mark_set.png'] {
|
||||||
|
opacity : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.tagCloudContainer {
|
div.tagCloudContainer {
|
||||||
border : 1px solid #c0c0c0;
|
border : 1px solid #ddd;
|
||||||
background-color : #ecf4ff;
|
background-color : #f5f5f5;
|
||||||
margin : 5px 0px 5px 0px;
|
margin : 5px 0px 5px 0px;
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
text-align : center;
|
text-align : center;
|
||||||
border-radius : 4px;
|
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.errorExplained {
|
div.errorExplained {
|
||||||
border : 1px solid #c0c0c0;
|
border : 1px solid #ddd;
|
||||||
background-color : #ecf4ff;
|
background-color : #f5f5f5;
|
||||||
margin : 5px 0px 5px 0px;
|
margin : 5px 0px 5px 0px;
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
border-radius : 4px;
|
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ul.feedErrorsList {
|
ul.feedErrorsList {
|
||||||
max-height : 300px;
|
max-height : 300px;
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
list-style-type : none;
|
list-style-type : none;
|
||||||
border : 1px solid #c0c0c0;
|
border : 1px solid #ddd;
|
||||||
background-color : #ecf4ff;
|
background-color : #f5f5f5;
|
||||||
margin : 0px 0px 5px 0px;
|
margin : 0px 0px 5px 0px;
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
border-radius : 4px;
|
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ul.feedErrorsList em {
|
ul.feedErrorsList em {
|
||||||
|
@ -464,7 +470,7 @@ ul.browseFeedList {
|
||||||
height : 300px;
|
height : 300px;
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
border-width : 0px 1px 1px 1px;
|
border-width : 0px 1px 1px 1px;
|
||||||
border-color : #c0c0c0;
|
border-color : #ddd;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
margin : 0px 0px 5px 0px;
|
margin : 0px 0px 5px 0px;
|
||||||
background-color : white;
|
background-color : white;
|
||||||
|
@ -528,14 +534,6 @@ form {
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#main_toolbar_form {
|
|
||||||
margin : 0px;
|
|
||||||
padding : 0px;
|
|
||||||
display : table-cell;
|
|
||||||
white-space : nowrap;
|
|
||||||
width : 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.loadingPrompt {
|
div.loadingPrompt {
|
||||||
padding : 1em;
|
padding : 1em;
|
||||||
text-align : center;
|
text-align : center;
|
||||||
|
@ -545,20 +543,11 @@ div.loadingPrompt {
|
||||||
div.whiteBox {
|
div.whiteBox {
|
||||||
margin-left : 1px;
|
margin-left : 1px;
|
||||||
text-align : center;
|
text-align : center;
|
||||||
padding : 1em;
|
padding : 1em 1em 0px 1em;
|
||||||
}
|
font-size : 11px;
|
||||||
|
border-width : 0px 0px 1px 0px;
|
||||||
/* html, body#ttrssMain, #main {
|
border-style : solid;
|
||||||
width: 100%;
|
border-color : #ddd;
|
||||||
height: 100%;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
} */
|
|
||||||
|
|
||||||
#toolbar div.actionChooser {
|
|
||||||
display : table-cell;
|
|
||||||
text-align : right;
|
|
||||||
padding-right : 3px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.autocomplete {
|
div.autocomplete {
|
||||||
|
@ -589,11 +578,13 @@ div.autocomplete ul li {
|
||||||
cursor : pointer;
|
cursor : pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hlTitle {
|
.hl .hlTitle {
|
||||||
overflow : hidden;
|
overflow : hidden;
|
||||||
white-space : nowrap;
|
white-space : nowrap;
|
||||||
max-width : 500px;
|
max-width : 500px;
|
||||||
text-overflow : ellipsis;
|
text-overflow : ellipsis;
|
||||||
|
padding-left : 6px;
|
||||||
|
padding-right : 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#headlines-frame.wide .hlTitle {
|
div#headlines-frame.wide .hlTitle {
|
||||||
|
@ -602,6 +593,10 @@ div#headlines-frame.wide .hlTitle {
|
||||||
white-space : normal;
|
white-space : normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div#headlines-frame.wide .hl .hlFeed {
|
||||||
|
display : none;
|
||||||
|
}
|
||||||
|
|
||||||
.hl a.title.high, span.hlContent.high .contentPreview {
|
.hl a.title.high, span.hlContent.high .contentPreview {
|
||||||
color : #00aa00;
|
color : #00aa00;
|
||||||
}
|
}
|
||||||
|
@ -667,7 +662,6 @@ span.labelColorIndicator {
|
||||||
background-color : #fff7d5;
|
background-color : #fff7d5;
|
||||||
color : #063064;
|
color : #063064;
|
||||||
text-align : center;
|
text-align : center;
|
||||||
box-shadow : 0px 0px 1px 0px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div#cmdline {
|
div#cmdline {
|
||||||
|
@ -716,14 +710,39 @@ div.hlRight img {
|
||||||
max-height : 16px;
|
max-height : 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.hlUpdated {
|
.hl span.hlFeed {
|
||||||
color : #555;
|
|
||||||
min-width : 100px;
|
|
||||||
display : table-cell;
|
display : table-cell;
|
||||||
width : 100%;
|
|
||||||
vertical-align : middle;
|
vertical-align : middle;
|
||||||
text-align : right;
|
text-align : right;
|
||||||
font-size : 10px;
|
}
|
||||||
|
|
||||||
|
.hl span.hlFeed a {
|
||||||
|
border-radius : 4px;
|
||||||
|
display : inline-block;
|
||||||
|
padding : 1px 4px 1px 4px;
|
||||||
|
font-size : 11px;
|
||||||
|
font-style : italic;
|
||||||
|
font-weight : normal;
|
||||||
|
color : #555;
|
||||||
|
white-space : nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl span.hlFeed a:hover {
|
||||||
|
color : #4684ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl span.hlUpdated {
|
||||||
|
color : #555;
|
||||||
|
display : table-cell;
|
||||||
|
vertical-align : middle;
|
||||||
|
text-align : right;
|
||||||
|
font-size : 11px;
|
||||||
|
white-space : nowrap;
|
||||||
|
padding-left : 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.hlUpdated div {
|
||||||
|
display : inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.hlLeft {
|
div.hlLeft {
|
||||||
|
@ -771,21 +790,19 @@ div.fatalError textarea {
|
||||||
|
|
||||||
#content-wrap {
|
#content-wrap {
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
border-width : 0px 0px 0px 1px;
|
border-width : 0px;
|
||||||
border-style : solid;
|
|
||||||
border-color : #c0c0c0;
|
|
||||||
margin : 0px;
|
margin : 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#feeds-holder {
|
#feeds-holder {
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
border-color : #c0c0c0;
|
border-width : 0px 1px 0px 0px;
|
||||||
border-left-width : 0px;
|
border-style : solid;
|
||||||
border-bottom-width : 0px;
|
border-color : #ddd;
|
||||||
border-top-width : 0px;
|
|
||||||
overflow : hidden;
|
overflow : hidden;
|
||||||
box-shadow : inset 0px 0px 3px rgba(0,0,0,0.1);
|
background : #f5f5f5;
|
||||||
background : #f9fbff;
|
box-shadow : inset -1px 0px 2px -1px rgba(0,0,0,0.1);
|
||||||
|
-webkit-overflow-scrolling : touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
#headlines-wrap-inner {
|
#headlines-wrap-inner {
|
||||||
|
@ -796,11 +813,10 @@ div.fatalError textarea {
|
||||||
|
|
||||||
#headlines-frame {
|
#headlines-frame {
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
border-color : #c0c0c0;
|
|
||||||
border-style : solid;
|
|
||||||
border-width : 0px;
|
border-width : 0px;
|
||||||
|
border-color : #ddd;
|
||||||
margin-top : 0px;
|
margin-top : 0px;
|
||||||
box-shadow : inset 0px 0px 3px rgba(0,0,0,0.1);
|
-webkit-overflow-scrolling : touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
#headlines-toolbar_splitter, #toolbar_splitter {
|
#headlines-toolbar_splitter, #toolbar_splitter {
|
||||||
|
@ -813,7 +829,16 @@ div.fatalError textarea {
|
||||||
border-width : 0px;
|
border-width : 0px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
font-size : 12px;
|
font-size : 12px;
|
||||||
box-shadow : 0px 0px 2px rgba(0,0,0,0.1);
|
}
|
||||||
|
|
||||||
|
#main-toolbar {
|
||||||
|
background : white;
|
||||||
|
border-width : 0px 0px 1px 0px;
|
||||||
|
border-color : #ddd;
|
||||||
|
border-style : solid;
|
||||||
|
padding-left : 4px;
|
||||||
|
height : 26px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#header {
|
#header {
|
||||||
|
@ -837,12 +862,12 @@ div.fatalError textarea {
|
||||||
|
|
||||||
#content-insert {
|
#content-insert {
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
border-color : #c0c0c0;
|
border-color : #ddd;
|
||||||
border-bottom-width : 0px;
|
border-width : 0px;
|
||||||
border-right-width : 0px;
|
line-height: 1.5;
|
||||||
border-left-width : 0px;
|
font-size : 15px;
|
||||||
line-height: 20px;
|
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
|
-webkit-overflow-scrolling : touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
#feedTree .dijitTreeRow .dijitTreeLabel.Unread {
|
#feedTree .dijitTreeRow .dijitTreeLabel.Unread {
|
||||||
|
@ -853,33 +878,6 @@ div.fatalError textarea {
|
||||||
color : red;
|
color : red;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dijitTreeLabel {
|
|
||||||
outline : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feedParam {
|
|
||||||
color : #555;
|
|
||||||
float : right;
|
|
||||||
margin-right : 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.labelParam {
|
|
||||||
float : right;
|
|
||||||
margin-right : 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitTreeLabel.Disabled, .labelParam.Disabled {
|
|
||||||
color : #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitTreeRow.Error {
|
|
||||||
color : red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitTreeRow.Hidden {
|
|
||||||
display : none;
|
|
||||||
}
|
|
||||||
|
|
||||||
img.feedIcon, img.tinyFeedIcon {
|
img.feedIcon, img.tinyFeedIcon {
|
||||||
width : 16px;
|
width : 16px;
|
||||||
height : 16px;
|
height : 16px;
|
||||||
|
@ -888,24 +886,6 @@ img.feedIcon, img.tinyFeedIcon {
|
||||||
display : inline-block;
|
display : inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dijitToolbar {
|
|
||||||
text-shadow : 1px 1px 2px #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitAccordionTitleFocus {
|
|
||||||
text-shadow : 1px 1px 2px #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitDialog .dijitToolbar {
|
|
||||||
border : 1px solid #c0c0c0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitDialog h2 {
|
|
||||||
margin-top : 0px;
|
|
||||||
margin-bottom : 4px;
|
|
||||||
border-width : 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player {
|
.player {
|
||||||
display : inline-block;
|
display : inline-block;
|
||||||
color : #555;
|
color : #555;
|
||||||
|
@ -933,8 +913,19 @@ img.feedIcon, img.tinyFeedIcon {
|
||||||
height : 100%;
|
height : 100%;
|
||||||
margin-left : 1px;
|
margin-left : 1px;
|
||||||
text-align : center;
|
text-align : center;
|
||||||
padding : 1em;
|
|
||||||
color : #555;
|
color : #555;
|
||||||
|
font-size : 11px;
|
||||||
|
font-style : italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
#headlines-spacer a, #headlines-spacer span {
|
||||||
|
color : #555;
|
||||||
|
padding : 10px;
|
||||||
|
display : block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#headlines-spacer a:hover {
|
||||||
|
color : #88b0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul#filterDlg_Matches, ul#filterDlg_Actions {
|
ul#filterDlg_Matches, ul#filterDlg_Actions {
|
||||||
|
@ -942,12 +933,11 @@ ul#filterDlg_Matches, ul#filterDlg_Actions {
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
list-style-type : none;
|
list-style-type : none;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #c0c0c0;
|
border-color : #ddd;
|
||||||
border-width : 0px 1px 1px 1px;
|
border-width : 0px 1px 1px 1px;
|
||||||
background-color : #ecf4ff;
|
background-color : white;
|
||||||
margin : 0px 0px 5px 0px;
|
margin : 0px 0px 5px 0px;
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ul#filterDlg_Matches li, ul#filterDlg_Actions li {
|
ul#filterDlg_Matches li, ul#filterDlg_Actions li {
|
||||||
|
@ -955,20 +945,14 @@ ul#filterDlg_Matches li, ul#filterDlg_Actions li {
|
||||||
padding : 0px 0px 0px 5px;
|
padding : 0px 0px 0px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul#filterDlg_Matches li div.dijitCheckBox, ul#filterDlg_Actions li div.dijitCheckBox {
|
|
||||||
margin-right : 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.helpKbList {
|
ul.helpKbList {
|
||||||
max-height : 300px;
|
max-height : 300px;
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
list-style-type : none;
|
list-style-type : none;
|
||||||
border : 1px solid #c0c0c0;
|
border : 1px solid #ddd;
|
||||||
background-color : #ecf4ff;
|
background-color : #f5f5f5;
|
||||||
margin : 0px 0px 5px 0px;
|
margin : 0px 0px 5px 0px;
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
border-radius : 4px;
|
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ul.helpKbList span.hksequence {
|
ul.helpKbList span.hksequence {
|
||||||
|
@ -983,18 +967,22 @@ ul.helpKbList h2 {
|
||||||
margin-top : 0px;
|
margin-top : 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dijitTreeNode .loadingNode {
|
|
||||||
margin-left : 3px;
|
|
||||||
height : 9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.collapseBtn {
|
span.collapseBtn {
|
||||||
cursor : pointer;
|
cursor : pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.postContent h1 {
|
||||||
|
font-size : 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.postContent h2,
|
||||||
|
div.postContent h3,
|
||||||
|
div.postContent h4 {
|
||||||
|
font-size : 15px;
|
||||||
|
}
|
||||||
|
|
||||||
div.postContent p {
|
div.postContent p {
|
||||||
max-width : 650px;
|
max-width : 650px;
|
||||||
text-align : justify;
|
|
||||||
-webkit-hyphens: auto;
|
-webkit-hyphens: auto;
|
||||||
-moz-hyphens: auto;
|
-moz-hyphens: auto;
|
||||||
hyphens: auto;
|
hyphens: auto;
|
||||||
|
@ -1010,90 +998,12 @@ div.postHeader span.author {
|
||||||
font-weight : normal;
|
font-weight : normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
body#ttrssZoom {
|
|
||||||
margin-left : auto;
|
|
||||||
margin-right : auto;
|
|
||||||
padding : 20px;
|
|
||||||
max-width : 670px;
|
|
||||||
background : #f9fbff;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postHeader div.postFeedTitle {
|
|
||||||
float : left;
|
|
||||||
text-align : right;
|
|
||||||
padding-left : 0px;
|
|
||||||
font-size : 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postHeader a.postComments {
|
|
||||||
text-align : right;
|
|
||||||
padding-left : 0px;
|
|
||||||
font-size : 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postHeader div.postDate {
|
|
||||||
float : none;
|
|
||||||
text-align : right;
|
|
||||||
padding-left : 0px;
|
|
||||||
color : #777;
|
|
||||||
font-size : 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postHeader div.postTags {
|
|
||||||
color : #777;
|
|
||||||
font-size : 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postHeader div.postTitle {
|
|
||||||
white-space : normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postContent p {
|
|
||||||
max-width : 650px;
|
|
||||||
text-align : justify;
|
|
||||||
-webkit-hyphens: auto;
|
|
||||||
-moz-hyphens: auto;
|
|
||||||
hyphens: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postHeader {
|
|
||||||
margin : 10px;
|
|
||||||
border : 1px solid #ccc;
|
|
||||||
box-shadow : none;
|
|
||||||
border-radius : 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postReply {
|
|
||||||
border : 1px solid #ccc;
|
|
||||||
border-radius : 4px;
|
|
||||||
box-shadow : inset 0px 0px 3px rgba(0,0,0,0.1);
|
|
||||||
background : white;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postContent {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.footer {
|
|
||||||
margin-top : 1em;
|
|
||||||
text-align : center;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postContent img {
|
|
||||||
max-width : 650px;
|
|
||||||
height : auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
select.attachments {
|
select.attachments {
|
||||||
display : block;
|
display : block;
|
||||||
margin-top : 10px;
|
margin-top : 10px;
|
||||||
max-width : 120px;
|
max-width : 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.hl.active {
|
|
||||||
border-color : #88b0f0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#selected_prompt {
|
#selected_prompt {
|
||||||
margin-right : 25px;
|
margin-right : 25px;
|
||||||
}
|
}
|
||||||
|
@ -1107,46 +1017,28 @@ body#ttrssMain #feedTree .dijitTreeRow {
|
||||||
padding : 2px 0px 2px;
|
padding : 2px 0px 2px;
|
||||||
height : 22px;
|
height : 22px;
|
||||||
border-width : 1px;
|
border-width : 1px;
|
||||||
border-color : transparent;
|
|
||||||
color : #333;
|
color : #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
body#ttrssMain #feedTree .dijitFolderClosed,
|
ul#filterDlg_Matches li div.dijitCheckBox, ul#filterDlg_Actions li div.dijitCheckBox {
|
||||||
body#ttrssMain #feedTree .dijitFolderOpened {
|
margin-right : 5px;
|
||||||
display : none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitTreeNode .dijitCheckBox {
|
|
||||||
margin-left : 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssMain #feedTree .dijitTreeIsRoot > .dijitTreeRow > .dijitTreeExpando {
|
|
||||||
margin-left : 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssMain #feedTree .dijitTreeExpando {
|
|
||||||
margin-top : 0px;
|
|
||||||
opacity : 0.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssMain #feedTree .dijitTreeNode {
|
|
||||||
padding : 0px;
|
|
||||||
border-width : 0px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body#ttrssMain #feedTree {
|
body#ttrssMain #feedTree {
|
||||||
height : 100%;
|
height : 100%;
|
||||||
overflow-x : hidden;
|
overflow-x : hidden;
|
||||||
font-family : "Segoe UI", Tahoma, sans-serif;
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe UI Web", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
#feedTree .counterNode.aux {
|
body#ttrssMain #feedTree .counterNode.aux {
|
||||||
background : #f0f0f0;
|
background : #f0f0f0;
|
||||||
color : #999;
|
color : #999;
|
||||||
border-color : #f0f0f0;
|
border-color : #f0f0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#feedTree .counterNode {
|
body#ttrssMain #feedTree .counterNode {
|
||||||
font-weight : bold;
|
font-weight : bold;
|
||||||
display : inline-block;
|
display : inline-block;
|
||||||
font-size : 9px;
|
font-size : 9px;
|
||||||
|
@ -1159,31 +1051,12 @@ body#ttrssMain #feedTree {
|
||||||
float : right;
|
float : right;
|
||||||
position : relative;
|
position : relative;
|
||||||
line-height : 14px;
|
line-height : 14px;
|
||||||
margin-right : 4px;
|
margin-right : 8px;
|
||||||
margin-top : 3px;
|
margin-top : 3px;
|
||||||
min-width : 23px;
|
min-width : 23px;
|
||||||
height : 14px;
|
height : 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#feedTree .dijitTreeRow {
|
|
||||||
max-width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssPrefs hr {
|
|
||||||
border-color : #ecf4ff;
|
|
||||||
max-width : 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitMenuItemLabel {
|
|
||||||
font-size : 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitTreeRowSelected .dijitTreeLabel {
|
|
||||||
text-shadow : 1px 1px 2px #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedTree img[src*='indicator_white.gif'] {
|
#feedTree img[src*='indicator_white.gif'] {
|
||||||
position : relative;
|
position : relative;
|
||||||
top : -2px;
|
top : -2px;
|
||||||
|
@ -1198,3 +1071,23 @@ div.enclosure_title {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body#ttrssMain #headlines-frame .dijitCheckBox {
|
||||||
|
border-width : 0px;
|
||||||
|
opacity : 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssMain #headlines-frame .dijitCheckBoxHover,
|
||||||
|
body#ttrssMain #headlines-frame .dijitCheckBoxChecked {
|
||||||
|
opacity : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssMain #feedTree .dijitTreeRow img.dijitTreeExpandoLeaf {
|
||||||
|
width : 16px;
|
||||||
|
height : 16px;
|
||||||
|
vertical-align : middle;
|
||||||
|
position : relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
body {
|
body {
|
||||||
background : #f9fbff;
|
background : #f5f5f5;
|
||||||
color : black;
|
color : black;
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
@ -15,11 +15,11 @@ form {
|
||||||
}
|
}
|
||||||
|
|
||||||
div.content {
|
div.content {
|
||||||
|
overflow : hidden;
|
||||||
background : white;
|
background : white;
|
||||||
border : 1px solid #ccc;
|
border : 1px solid #ddd;
|
||||||
padding : 10px;
|
padding : 10px;
|
||||||
border-radius : 4px;
|
box-shadow : 0px 1px 1px -1px rgba(0,0,0,0.1);
|
||||||
box-shadow : inset 0 0 3px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p.warning {
|
p.warning {
|
||||||
|
@ -40,9 +40,7 @@ div.insensitive-small {
|
||||||
}
|
}
|
||||||
|
|
||||||
.floatingLogo {
|
.floatingLogo {
|
||||||
float : right;
|
display : none;
|
||||||
position : relative;
|
|
||||||
top : -10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
@ -61,7 +59,6 @@ div.notice, div.warning, div.error {
|
||||||
font-size : 12px;
|
font-size : 12px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #ccc;
|
border-color : #ccc;
|
||||||
border-radius : 4px;
|
|
||||||
border-width : 1px;
|
border-width : 1px;
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
||||||
}
|
}
|
||||||
|
|
105
source/css/zoom.css
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
body#ttrssZoom {
|
||||||
|
margin-left : auto;
|
||||||
|
margin-right : auto;
|
||||||
|
padding : 20px;
|
||||||
|
max-width : 670px;
|
||||||
|
background : #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postHeader div.postFeedTitle {
|
||||||
|
float : left;
|
||||||
|
text-align : right;
|
||||||
|
padding-left : 0px;
|
||||||
|
font-size : 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postHeader a.postComments {
|
||||||
|
text-align : right;
|
||||||
|
padding-left : 0px;
|
||||||
|
font-size : 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postHeader div.postDate {
|
||||||
|
float : none;
|
||||||
|
text-align : right;
|
||||||
|
padding-left : 0px;
|
||||||
|
color : #777;
|
||||||
|
font-size : 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postHeader div.postTags {
|
||||||
|
color : #777;
|
||||||
|
font-size : 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postHeader div.postTitle {
|
||||||
|
white-space : normal;
|
||||||
|
font-size : 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postContent {
|
||||||
|
font-size : 15px;
|
||||||
|
line-height : 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postContent p {
|
||||||
|
max-width : 650px;
|
||||||
|
-webkit-hyphens: auto;
|
||||||
|
-moz-hyphens: auto;
|
||||||
|
hyphens: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postHeader {
|
||||||
|
margin : 10px;
|
||||||
|
border-width : 0px 0px 1px 0px;
|
||||||
|
border-style : solid;
|
||||||
|
border-color : #eee;
|
||||||
|
background : white;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postReply {
|
||||||
|
border : 1px solid #ddd;
|
||||||
|
background : white;
|
||||||
|
box-shadow : 0px 1px 1px -1px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.footer {
|
||||||
|
margin-top : 1em;
|
||||||
|
text-align : center;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postContent img {
|
||||||
|
max-width : 630px;
|
||||||
|
height : auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postContent blockquote {
|
||||||
|
margin : 5px 0px 5px 0px;
|
||||||
|
color : #555;
|
||||||
|
padding-left : 10px;
|
||||||
|
border-width : 0px 0px 0px 4px;
|
||||||
|
border-color : #ccc;
|
||||||
|
border-style : solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postContent code {
|
||||||
|
color : #009900;
|
||||||
|
font-family : monospace;
|
||||||
|
font-size : 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postContent pre {
|
||||||
|
margin : 5px 0px 5px 0px;
|
||||||
|
padding : 10px;
|
||||||
|
color : #555;
|
||||||
|
font-family : monospace;
|
||||||
|
font-size : 12px;
|
||||||
|
border-width : 0px;
|
||||||
|
border-color : #ccc;
|
||||||
|
border-style : solid;
|
||||||
|
background : #f5f5f5;
|
||||||
|
display : block;
|
||||||
|
max-width : 98%;
|
||||||
|
overflow : auto;
|
||||||
|
}
|
||||||
|
|
0
source/feed-icons/.empty
Executable file
0
source/feed-icons/index.html
Normal file
|
@ -41,8 +41,6 @@
|
||||||
header("Content-type: image/png");
|
header("Content-type: image/png");
|
||||||
$stamp = gmdate("D, d M Y H:i:s", filemtime($filename)). " GMT";
|
$stamp = gmdate("D, d M Y H:i:s", filemtime($filename)). " GMT";
|
||||||
header("Last-Modified: $stamp", true);
|
header("Last-Modified: $stamp", true);
|
||||||
ob_clean(); // discard any data in the output buffer (if possible)
|
|
||||||
flush(); // flush headers (if possible)
|
|
||||||
readfile($filename);
|
readfile($filename);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
Before Width: | Height: | Size: 610 B After Width: | Height: | Size: 623 B |
Before Width: | Height: | Size: 718 B After Width: | Height: | Size: 717 B |
BIN
source/images/tick.png
Normal file
After Width: | Height: | Size: 537 B |
BIN
source/images/treeExpandImages.png
Normal file
After Width: | Height: | Size: 288 B |
BIN
source/images/untick.png
Normal file
After Width: | Height: | Size: 518 B |
|
@ -92,7 +92,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function ccache_update($feed_id, $owner_uid, $is_cat = false,
|
function ccache_update($feed_id, $owner_uid, $is_cat = false,
|
||||||
$update_pcat = true) {
|
$update_pcat = true, $pcat_fast = false) {
|
||||||
|
|
||||||
if (!is_numeric($feed_id)) return;
|
if (!is_numeric($feed_id)) return;
|
||||||
|
|
||||||
|
@ -127,11 +127,13 @@
|
||||||
|
|
||||||
/* Recalculate counters for child feeds */
|
/* Recalculate counters for child feeds */
|
||||||
|
|
||||||
$result = db_query("SELECT id FROM ttrss_feeds
|
if (!$pcat_fast) {
|
||||||
|
$result = db_query("SELECT id FROM ttrss_feeds
|
||||||
WHERE owner_uid = '$owner_uid' AND $cat_qpart");
|
WHERE owner_uid = '$owner_uid' AND $cat_qpart");
|
||||||
|
|
||||||
while ($line = db_fetch_assoc($result)) {
|
while ($line = db_fetch_assoc($result)) {
|
||||||
ccache_update($line["id"], $owner_uid, false, false);
|
ccache_update($line["id"], $owner_uid, false, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = db_query("SELECT SUM(value) AS sv
|
$result = db_query("SELECT SUM(value) AS sv
|
||||||
|
@ -177,7 +179,7 @@
|
||||||
|
|
||||||
$cat_id = (int) db_fetch_result($result, 0, "cat_id");
|
$cat_id = (int) db_fetch_result($result, 0, "cat_id");
|
||||||
|
|
||||||
ccache_update($cat_id, $owner_uid, true);
|
ccache_update($cat_id, $owner_uid, true, true, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,8 +127,6 @@
|
||||||
ORDER BY ttrss_feed_categories.title, ttrss_feeds.title, score DESC, date_updated DESC
|
ORDER BY ttrss_feed_categories.title, ttrss_feeds.title, score DESC, date_updated DESC
|
||||||
LIMIT $limit");
|
LIMIT $limit");
|
||||||
|
|
||||||
$cur_feed_title = "";
|
|
||||||
|
|
||||||
$headlines_count = db_num_rows($result);
|
$headlines_count = db_num_rows($result);
|
||||||
|
|
||||||
$headlines = array();
|
$headlines = array();
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
htmlspecialchars($line["title"])."</span></a>";
|
htmlspecialchars($line["title"])."</span></a>";
|
||||||
|
|
||||||
$feed_url = "<a target=\"_blank\" class=\"fb_feedUrl\"
|
$feed_url = "<a target=\"_blank\" class=\"fb_feedUrl\"
|
||||||
href=\"$feed_url\"><img src='images/pub_set.svg'
|
href=\"$feed_url\"><img src='images/pub_set.png'
|
||||||
style='vertical-align : middle'></a>";
|
style='vertical-align : middle'></a>";
|
||||||
|
|
||||||
$rv .= "<li>$check_box $feed_url $site_url".
|
$rv .= "<li>$check_box $feed_url $site_url".
|
||||||
|
@ -72,7 +72,6 @@
|
||||||
} else if ($mode == 2) {
|
} else if ($mode == 2) {
|
||||||
$feed_url = htmlspecialchars($line["feed_url"]);
|
$feed_url = htmlspecialchars($line["feed_url"]);
|
||||||
$site_url = htmlspecialchars($line["site_url"]);
|
$site_url = htmlspecialchars($line["site_url"]);
|
||||||
$title = htmlspecialchars($line["title"]);
|
|
||||||
|
|
||||||
$check_box = "<input onclick='toggleSelectListRow2(this)' dojoType=\"dijit.form.CheckBox\"
|
$check_box = "<input onclick='toggleSelectListRow2(this)' dojoType=\"dijit.form.CheckBox\"
|
||||||
type=\"checkbox\">";
|
type=\"checkbox\">";
|
||||||
|
@ -92,7 +91,7 @@
|
||||||
htmlspecialchars($line["title"])."</span></a>";
|
htmlspecialchars($line["title"])."</span></a>";
|
||||||
|
|
||||||
$feed_url = "<a target=\"_blank\" class=\"fb_feedUrl\"
|
$feed_url = "<a target=\"_blank\" class=\"fb_feedUrl\"
|
||||||
href=\"$feed_url\"><img src='images/pub_set.svg'
|
href=\"$feed_url\"><img src='images/pub_set.png'
|
||||||
style='vertical-align : middle'></a>";
|
style='vertical-align : middle'></a>";
|
||||||
|
|
||||||
|
|
||||||
|
|
2403
source/include/functions2.php
Normal file
|
@ -109,7 +109,7 @@
|
||||||
|
|
||||||
if (!$label_id) return;
|
if (!$label_id) return;
|
||||||
|
|
||||||
$result = db_query(
|
db_query(
|
||||||
"DELETE FROM ttrss_user_labels2
|
"DELETE FROM ttrss_user_labels2
|
||||||
WHERE
|
WHERE
|
||||||
label_id = '$label_id' AND
|
label_id = '$label_id' AND
|
||||||
|
|
|
@ -2,15 +2,22 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Tiny Tiny RSS : Login</title>
|
<title>Tiny Tiny RSS : Login</title>
|
||||||
<link rel="stylesheet" type="text/css" href="lib/dijit/themes/claro/claro.css"/>
|
<?php echo stylesheet_tag("lib/dijit/themes/claro/claro.css") ?>
|
||||||
<link rel="stylesheet" type="text/css" href="css/tt-rss.css">
|
<?php echo stylesheet_tag("css/tt-rss.css") ?>
|
||||||
|
<?php echo stylesheet_tag("css/dijit.css") ?>
|
||||||
<link rel="shortcut icon" type="image/png" href="images/favicon.png">
|
<link rel="shortcut icon" type="image/png" href="images/favicon.png">
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
<script type="text/javascript" src="lib/dojo/dojo.js"></script>
|
<?php
|
||||||
<script type="text/javascript" src="lib/dojo/tt-rss-layer.js"></script>
|
foreach (array("lib/prototype.js",
|
||||||
<script type="text/javascript" src="lib/prototype.js"></script>
|
"lib/dojo/dojo.js",
|
||||||
<script type="text/javascript" src="js/functions.js"></script>
|
"lib/dojo/tt-rss-layer.js",
|
||||||
<script type="text/javascript" charset="utf-8" src="errors.php?mode=js"></script>
|
"js/functions.js",
|
||||||
|
"errors.php?mode=js") as $jsfile) {
|
||||||
|
|
||||||
|
echo javascript_tag($jsfile);
|
||||||
|
|
||||||
|
} ?>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
require({cache:{}});
|
require({cache:{}});
|
||||||
Event.observe(window, 'load', function() {
|
Event.observe(window, 'load', function() {
|
||||||
|
|
|
@ -2,6 +2,19 @@
|
||||||
define_default('DAEMON_UPDATE_LOGIN_LIMIT', 30);
|
define_default('DAEMON_UPDATE_LOGIN_LIMIT', 30);
|
||||||
define_default('DAEMON_FEED_LIMIT', 500);
|
define_default('DAEMON_FEED_LIMIT', 500);
|
||||||
define_default('DAEMON_SLEEP_INTERVAL', 120);
|
define_default('DAEMON_SLEEP_INTERVAL', 120);
|
||||||
|
define_default('_MIN_CACHE_IMAGE_SIZE', 1024);
|
||||||
|
|
||||||
|
function calculate_article_hash($article, $pluginhost) {
|
||||||
|
$tmp = "";
|
||||||
|
|
||||||
|
foreach ($article as $k => $v) {
|
||||||
|
if ($k != "feed" && isset($v)) {
|
||||||
|
$tmp .= sha1("$k:" . (is_array($v) ? implode(",", $v) : $v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sha1(implode(",", $pluginhost->get_plugin_names()) . $tmp);
|
||||||
|
}
|
||||||
|
|
||||||
function update_feedbrowser_cache() {
|
function update_feedbrowser_cache() {
|
||||||
|
|
||||||
|
@ -79,7 +92,7 @@
|
||||||
$login_thresh_qpart = "";
|
$login_thresh_qpart = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if the feed need a update (update interval exceded).
|
// Test if the feed need a update (update interval exceeded).
|
||||||
if (DB_TYPE == "pgsql") {
|
if (DB_TYPE == "pgsql") {
|
||||||
$update_limit_qpart = "AND ((
|
$update_limit_qpart = "AND ((
|
||||||
ttrss_feeds.update_interval = 0
|
ttrss_feeds.update_interval = 0
|
||||||
|
@ -88,8 +101,10 @@
|
||||||
) OR (
|
) OR (
|
||||||
ttrss_feeds.update_interval > 0
|
ttrss_feeds.update_interval > 0
|
||||||
AND ttrss_feeds.last_updated < NOW() - CAST((ttrss_feeds.update_interval || ' minutes') AS INTERVAL)
|
AND ttrss_feeds.last_updated < NOW() - CAST((ttrss_feeds.update_interval || ' minutes') AS INTERVAL)
|
||||||
) OR ttrss_feeds.last_updated IS NULL
|
) OR (ttrss_feeds.last_updated IS NULL
|
||||||
OR last_updated = '1970-01-01 00:00:00')";
|
AND ttrss_user_prefs.value != '-1')
|
||||||
|
OR (last_updated = '1970-01-01 00:00:00'
|
||||||
|
AND ttrss_user_prefs.value != '-1'))";
|
||||||
} else {
|
} else {
|
||||||
$update_limit_qpart = "AND ((
|
$update_limit_qpart = "AND ((
|
||||||
ttrss_feeds.update_interval = 0
|
ttrss_feeds.update_interval = 0
|
||||||
|
@ -98,8 +113,10 @@
|
||||||
) OR (
|
) OR (
|
||||||
ttrss_feeds.update_interval > 0
|
ttrss_feeds.update_interval > 0
|
||||||
AND ttrss_feeds.last_updated < DATE_SUB(NOW(), INTERVAL ttrss_feeds.update_interval MINUTE)
|
AND ttrss_feeds.last_updated < DATE_SUB(NOW(), INTERVAL ttrss_feeds.update_interval MINUTE)
|
||||||
) OR ttrss_feeds.last_updated IS NULL
|
) OR (ttrss_feeds.last_updated IS NULL
|
||||||
OR last_updated = '1970-01-01 00:00:00')";
|
AND ttrss_user_prefs.value != '-1')
|
||||||
|
OR (last_updated = '1970-01-01 00:00:00'
|
||||||
|
AND ttrss_user_prefs.value != '-1'))";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if feed is currently being updated by another process.
|
// Test if feed is currently being updated by another process.
|
||||||
|
@ -118,6 +135,7 @@
|
||||||
ttrss_feeds, ttrss_users, ttrss_user_prefs
|
ttrss_feeds, ttrss_users, ttrss_user_prefs
|
||||||
WHERE
|
WHERE
|
||||||
ttrss_feeds.owner_uid = ttrss_users.id
|
ttrss_feeds.owner_uid = ttrss_users.id
|
||||||
|
AND ttrss_user_prefs.profile IS NULL
|
||||||
AND ttrss_users.id = ttrss_user_prefs.owner_uid
|
AND ttrss_users.id = ttrss_user_prefs.owner_uid
|
||||||
AND ttrss_user_prefs.pref_name = 'DEFAULT_UPDATE_INTERVAL'
|
AND ttrss_user_prefs.pref_name = 'DEFAULT_UPDATE_INTERVAL'
|
||||||
$login_thresh_qpart $update_limit_qpart
|
$login_thresh_qpart $update_limit_qpart
|
||||||
|
@ -151,6 +169,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
$nf = 0;
|
$nf = 0;
|
||||||
|
$bstarted = microtime(true);
|
||||||
|
|
||||||
// For each feed, we call the feed update function.
|
// For each feed, we call the feed update function.
|
||||||
foreach ($feeds_to_update as $feed) {
|
foreach ($feeds_to_update as $feed) {
|
||||||
|
@ -165,6 +184,7 @@
|
||||||
ttrss_user_prefs.owner_uid = ttrss_feeds.owner_uid AND
|
ttrss_user_prefs.owner_uid = ttrss_feeds.owner_uid AND
|
||||||
ttrss_users.id = ttrss_user_prefs.owner_uid AND
|
ttrss_users.id = ttrss_user_prefs.owner_uid AND
|
||||||
ttrss_user_prefs.pref_name = 'DEFAULT_UPDATE_INTERVAL' AND
|
ttrss_user_prefs.pref_name = 'DEFAULT_UPDATE_INTERVAL' AND
|
||||||
|
ttrss_user_prefs.profile IS NULL AND
|
||||||
feed_url = '".db_escape_string($feed)."' AND
|
feed_url = '".db_escape_string($feed)."' AND
|
||||||
(ttrss_feeds.update_interval > 0 OR
|
(ttrss_feeds.update_interval > 0 OR
|
||||||
ttrss_user_prefs.value != '-1')
|
ttrss_user_prefs.value != '-1')
|
||||||
|
@ -172,15 +192,27 @@
|
||||||
ORDER BY ttrss_feeds.id $query_limit");
|
ORDER BY ttrss_feeds.id $query_limit");
|
||||||
|
|
||||||
if (db_num_rows($tmp_result) > 0) {
|
if (db_num_rows($tmp_result) > 0) {
|
||||||
|
$rss = false;
|
||||||
|
|
||||||
while ($tline = db_fetch_assoc($tmp_result)) {
|
while ($tline = db_fetch_assoc($tmp_result)) {
|
||||||
if($debug) _debug(" => " . $tline["last_updated"] . ", " . $tline["id"] . " " . $tline["owner_uid"]);
|
if($debug) _debug(" => " . $tline["last_updated"] . ", " . $tline["id"] . " " . $tline["owner_uid"]);
|
||||||
update_rss_feed($tline["id"], true);
|
|
||||||
|
$fstarted = microtime(true);
|
||||||
|
$rss = update_rss_feed($tline["id"], true, false);
|
||||||
_debug_suppress(false);
|
_debug_suppress(false);
|
||||||
|
|
||||||
|
_debug(sprintf(" %.4f (sec)", microtime(true) - $fstarted));
|
||||||
|
|
||||||
++$nf;
|
++$nf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($nf > 0) {
|
||||||
|
_debug(sprintf("Processed %d feeds in %.4f (sec), %.4f (sec/feed avg)", $nf,
|
||||||
|
microtime(true) - $bstarted, (microtime(true) - $bstarted) / $nf));
|
||||||
|
}
|
||||||
|
|
||||||
require_once "digest.php";
|
require_once "digest.php";
|
||||||
|
|
||||||
// Send feed digests by email if needed.
|
// Send feed digests by email if needed.
|
||||||
|
@ -191,7 +223,7 @@
|
||||||
} // function update_daemon_common
|
} // function update_daemon_common
|
||||||
|
|
||||||
// ignore_daemon is not used
|
// ignore_daemon is not used
|
||||||
function update_rss_feed($feed, $ignore_daemon = false, $no_cache = false) {
|
function update_rss_feed($feed, $ignore_daemon = false, $no_cache = false, $rss = false) {
|
||||||
|
|
||||||
$debug_enabled = defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug'];
|
$debug_enabled = defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug'];
|
||||||
|
|
||||||
|
@ -199,7 +231,7 @@
|
||||||
_debug("start", $debug_enabled);
|
_debug("start", $debug_enabled);
|
||||||
|
|
||||||
$result = db_query("SELECT id,update_interval,auth_login,
|
$result = db_query("SELECT id,update_interval,auth_login,
|
||||||
feed_url,auth_pass,cache_images,last_updated,
|
feed_url,auth_pass,cache_images,
|
||||||
mark_unread_on_update, owner_uid,
|
mark_unread_on_update, owner_uid,
|
||||||
pubsub_state, auth_pass_encrypted,
|
pubsub_state, auth_pass_encrypted,
|
||||||
(SELECT max(date_entered) FROM
|
(SELECT max(date_entered) FROM
|
||||||
|
@ -211,7 +243,6 @@
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$last_updated = db_fetch_result($result, 0, "last_updated");
|
|
||||||
$last_article_timestamp = @strtotime(db_fetch_result($result, 0, "last_article_timestamp"));
|
$last_article_timestamp = @strtotime(db_fetch_result($result, 0, "last_article_timestamp"));
|
||||||
|
|
||||||
if (defined('_DISABLE_HTTP_304'))
|
if (defined('_DISABLE_HTTP_304'))
|
||||||
|
@ -252,34 +283,37 @@
|
||||||
$pluginhost->load($user_plugins, PluginHost::KIND_USER, $owner_uid);
|
$pluginhost->load($user_plugins, PluginHost::KIND_USER, $owner_uid);
|
||||||
$pluginhost->load_data();
|
$pluginhost->load_data();
|
||||||
|
|
||||||
$rss = false;
|
if ($rss && is_object($rss) && get_class($rss) == "FeedParser") {
|
||||||
$rss_hash = false;
|
_debug("using previously initialized parser object");
|
||||||
|
|
||||||
$force_refetch = isset($_REQUEST["force_refetch"]);
|
|
||||||
|
|
||||||
if (file_exists($cache_filename) &&
|
|
||||||
is_readable($cache_filename) &&
|
|
||||||
!$auth_login && !$auth_pass &&
|
|
||||||
filemtime($cache_filename) > time() - 30) {
|
|
||||||
|
|
||||||
_debug("using local cache.", $debug_enabled);
|
|
||||||
|
|
||||||
@$feed_data = file_get_contents($cache_filename);
|
|
||||||
|
|
||||||
if ($feed_data) {
|
|
||||||
$rss_hash = sha1($feed_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_debug("local cache will not be used for this feed", $debug_enabled);
|
$rss_hash = false;
|
||||||
}
|
|
||||||
|
|
||||||
if (!$rss) {
|
$force_refetch = isset($_REQUEST["force_refetch"]);
|
||||||
|
|
||||||
foreach ($pluginhost->get_hooks(PluginHost::HOOK_FETCH_FEED) as $plugin) {
|
foreach ($pluginhost->get_hooks(PluginHost::HOOK_FETCH_FEED) as $plugin) {
|
||||||
$feed_data = $plugin->hook_fetch_feed($feed_data, $fetch_url, $owner_uid, $feed);
|
$feed_data = $plugin->hook_fetch_feed($feed_data, $fetch_url, $owner_uid, $feed, $last_article_timestamp, $auth_login, $auth_pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try cache
|
||||||
|
if (!$feed_data &&
|
||||||
|
file_exists($cache_filename) &&
|
||||||
|
is_readable($cache_filename) &&
|
||||||
|
!$auth_login && !$auth_pass &&
|
||||||
|
filemtime($cache_filename) > time() - 30) {
|
||||||
|
|
||||||
|
_debug("using local cache [$cache_filename].", $debug_enabled);
|
||||||
|
|
||||||
|
@$feed_data = file_get_contents($cache_filename);
|
||||||
|
|
||||||
|
if ($feed_data) {
|
||||||
|
$rss_hash = sha1($feed_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_debug("local cache will not be used for this feed", $debug_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch feed from source
|
||||||
if (!$feed_data) {
|
if (!$feed_data) {
|
||||||
_debug("fetching [$fetch_url]...", $debug_enabled);
|
_debug("fetching [$fetch_url]...", $debug_enabled);
|
||||||
_debug("If-Modified-Since: ".gmdate('D, d M Y H:i:s \G\M\T', $last_article_timestamp), $debug_enabled);
|
_debug("If-Modified-Since: ".gmdate('D, d M Y H:i:s \G\M\T', $last_article_timestamp), $debug_enabled);
|
||||||
|
@ -318,6 +352,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} */
|
} */
|
||||||
|
|
||||||
|
// cache vanilla feed data for re-use
|
||||||
|
if ($feed_data && !$auth_pass && !$auth_login && is_writable(CACHE_DIR . "/simplepie")) {
|
||||||
|
$new_rss_hash = sha1($feed_data);
|
||||||
|
|
||||||
|
if ($new_rss_hash != $rss_hash) {
|
||||||
|
_debug("saving $cache_filename", $debug_enabled);
|
||||||
|
@file_put_contents($cache_filename, $feed_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$feed_data) {
|
if (!$feed_data) {
|
||||||
|
@ -356,10 +400,12 @@
|
||||||
$rss->init();
|
$rss->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once "lib/languagedetect/LanguageDetect.php";
|
if (DETECT_ARTICLE_LANGUAGE) {
|
||||||
|
require_once "lib/languagedetect/LanguageDetect.php";
|
||||||
|
|
||||||
$lang = new Text_LanguageDetect();
|
$lang = new Text_LanguageDetect();
|
||||||
$lang->setNameMode(2);
|
$lang->setNameMode(2);
|
||||||
|
}
|
||||||
|
|
||||||
// print_r($rss);
|
// print_r($rss);
|
||||||
|
|
||||||
|
@ -367,16 +413,6 @@
|
||||||
|
|
||||||
if (!$rss->error()) {
|
if (!$rss->error()) {
|
||||||
|
|
||||||
// cache data for later
|
|
||||||
if (!$auth_pass && !$auth_login && is_writable(CACHE_DIR . "/simplepie")) {
|
|
||||||
$new_rss_hash = sha1($rss_data);
|
|
||||||
|
|
||||||
if ($new_rss_hash != $rss_hash && count($rss->get_items()) > 0 ) {
|
|
||||||
_debug("saving $cache_filename", $debug_enabled);
|
|
||||||
@file_put_contents($cache_filename, $feed_data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We use local pluginhost here because we need to load different per-user feed plugins
|
// We use local pluginhost here because we need to load different per-user feed plugins
|
||||||
$pluginhost->run_hooks(PluginHost::HOOK_FEED_PARSED, "hook_feed_parsed", $rss);
|
$pluginhost->run_hooks(PluginHost::HOOK_FEED_PARSED, "hook_feed_parsed", $rss);
|
||||||
|
|
||||||
|
@ -495,7 +531,20 @@
|
||||||
|
|
||||||
_debug("feed hub url: $feed_hub_url", $debug_enabled);
|
_debug("feed hub url: $feed_hub_url", $debug_enabled);
|
||||||
|
|
||||||
if ($feed_hub_url && function_exists('curl_init') &&
|
$feed_self_url = $fetch_url;
|
||||||
|
|
||||||
|
$links = $rss->get_links('self');
|
||||||
|
|
||||||
|
if ($links && is_array($links)) {
|
||||||
|
foreach ($links as $l) {
|
||||||
|
$feed_self_url = $l;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_debug("feed self url = $feed_self_url");
|
||||||
|
|
||||||
|
if ($feed_hub_url && $feed_self_url && function_exists('curl_init') &&
|
||||||
!ini_get("open_basedir")) {
|
!ini_get("open_basedir")) {
|
||||||
|
|
||||||
require_once 'lib/pubsubhubbub/subscriber.php';
|
require_once 'lib/pubsubhubbub/subscriber.php';
|
||||||
|
@ -505,9 +554,9 @@
|
||||||
|
|
||||||
$s = new Subscriber($feed_hub_url, $callback_url);
|
$s = new Subscriber($feed_hub_url, $callback_url);
|
||||||
|
|
||||||
$rc = $s->subscribe($fetch_url);
|
$rc = $s->subscribe($feed_self_url);
|
||||||
|
|
||||||
_debug("feed hub url found, subscribe request sent.", $debug_enabled);
|
_debug("feed hub url found, subscribe request sent. [rc=$rc]", $debug_enabled);
|
||||||
|
|
||||||
db_query("UPDATE ttrss_feeds SET pubsub_state = 1
|
db_query("UPDATE ttrss_feeds SET pubsub_state = 1
|
||||||
WHERE id = '$feed'");
|
WHERE id = '$feed'");
|
||||||
|
@ -524,9 +573,6 @@
|
||||||
$entry_guid = $item->get_id();
|
$entry_guid = $item->get_id();
|
||||||
if (!$entry_guid) $entry_guid = $item->get_link();
|
if (!$entry_guid) $entry_guid = $item->get_link();
|
||||||
if (!$entry_guid) $entry_guid = make_guid_from_title($item->get_title());
|
if (!$entry_guid) $entry_guid = make_guid_from_title($item->get_title());
|
||||||
|
|
||||||
_debug("f_guid $entry_guid", $debug_enabled);
|
|
||||||
|
|
||||||
if (!$entry_guid) continue;
|
if (!$entry_guid) continue;
|
||||||
|
|
||||||
$entry_guid = "$owner_uid,$entry_guid";
|
$entry_guid = "$owner_uid,$entry_guid";
|
||||||
|
@ -543,9 +589,6 @@
|
||||||
|
|
||||||
if ($entry_timestamp == -1 || !$entry_timestamp || $entry_timestamp > time()) {
|
if ($entry_timestamp == -1 || !$entry_timestamp || $entry_timestamp > time()) {
|
||||||
$entry_timestamp = time();
|
$entry_timestamp = time();
|
||||||
$no_orig_date = 'true';
|
|
||||||
} else {
|
|
||||||
$no_orig_date = 'false';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$entry_timestamp_fmt = strftime("%Y/%m/%d %H:%M:%S", $entry_timestamp);
|
$entry_timestamp_fmt = strftime("%Y/%m/%d %H:%M:%S", $entry_timestamp);
|
||||||
|
@ -572,15 +615,19 @@
|
||||||
print "\n";
|
print "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
$entry_language = $lang->detect($entry_title . " " . $entry_content, 1);
|
$entry_language = "";
|
||||||
|
|
||||||
if (count($entry_language) > 0) {
|
if (DETECT_ARTICLE_LANGUAGE) {
|
||||||
$entry_language = array_keys($entry_language);
|
$entry_language = $lang->detect($entry_title . " " . $entry_content, 1);
|
||||||
$entry_language = db_escape_string(substr($entry_language[0], 0, 2));
|
|
||||||
|
|
||||||
_debug("detected language: $entry_language", $debug_enabled);
|
if (count($entry_language) > 0) {
|
||||||
} else{
|
$possible = array_keys($entry_language);
|
||||||
$entry_language = "";
|
$entry_language = $possible[0];
|
||||||
|
|
||||||
|
_debug("detected language: $entry_language", $debug_enabled);
|
||||||
|
} else {
|
||||||
|
$entry_language = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$entry_comments = $item->get_comments_url();
|
$entry_comments = $item->get_comments_url();
|
||||||
|
@ -618,24 +665,15 @@
|
||||||
|
|
||||||
_debug("done collecting data.", $debug_enabled);
|
_debug("done collecting data.", $debug_enabled);
|
||||||
|
|
||||||
// TODO: less memory-hungry implementation
|
$result = db_query("SELECT id, content_hash FROM ttrss_entries
|
||||||
|
WHERE guid = '".db_escape_string($entry_guid)."' OR guid = '$entry_guid_hashed'");
|
||||||
_debug("applying plugin filters..", $debug_enabled);
|
|
||||||
|
|
||||||
// FIXME not sure if owner_uid is a good idea here, we may have a base entry without user entry (?)
|
|
||||||
$result = db_query("SELECT plugin_data,title,content,link,tag_cache,author FROM ttrss_entries, ttrss_user_entries
|
|
||||||
WHERE ref_id = id AND (guid = '".db_escape_string($entry_guid)."' OR guid = '$entry_guid_hashed') AND owner_uid = $owner_uid");
|
|
||||||
|
|
||||||
if (db_num_rows($result) != 0) {
|
if (db_num_rows($result) != 0) {
|
||||||
$entry_plugin_data = db_fetch_result($result, 0, "plugin_data");
|
$base_entry_id = db_fetch_result($result, 0, "id");
|
||||||
$stored_article = array("title" => db_fetch_result($result, 0, "title"),
|
$entry_stored_hash = db_fetch_result($result, 0, "content_hash");
|
||||||
"content" => db_fetch_result($result, 0, "content"),
|
|
||||||
"link" => db_fetch_result($result, 0, "link"),
|
|
||||||
"tags" => explode(",", db_fetch_result($result, 0, "tag_cache")),
|
|
||||||
"author" => db_fetch_result($result, 0, "author"));
|
|
||||||
} else {
|
} else {
|
||||||
$entry_plugin_data = "";
|
$base_entry_id = false;
|
||||||
$stored_article = array();
|
$entry_stored_hash = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
$article = array("owner_uid" => $owner_uid, // read only
|
$article = array("owner_uid" => $owner_uid, // read only
|
||||||
|
@ -644,36 +682,63 @@
|
||||||
"content" => $entry_content,
|
"content" => $entry_content,
|
||||||
"link" => $entry_link,
|
"link" => $entry_link,
|
||||||
"tags" => $entry_tags,
|
"tags" => $entry_tags,
|
||||||
"plugin_data" => $entry_plugin_data,
|
|
||||||
"author" => $entry_author,
|
"author" => $entry_author,
|
||||||
"stored" => $stored_article,
|
"language" => $entry_language, // read only
|
||||||
"feed" => array("id" => $feed,
|
"feed" => array("id" => $feed,
|
||||||
"fetch_url" => $fetch_url,
|
"fetch_url" => $fetch_url,
|
||||||
"site_url" => $site_url)
|
"site_url" => $site_url)
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach ($pluginhost->get_hooks(PluginHost::HOOK_ARTICLE_FILTER) as $plugin) {
|
$entry_plugin_data = "";
|
||||||
$article = $plugin->hook_article_filter($article);
|
$entry_current_hash = calculate_article_hash($article, $pluginhost);
|
||||||
|
|
||||||
|
_debug("article hash: $entry_current_hash [stored=$entry_stored_hash]", $debug_enabled);
|
||||||
|
|
||||||
|
if ($entry_current_hash == $entry_stored_hash && !isset($_REQUEST["force_rehash"])) {
|
||||||
|
_debug("stored article seems up to date [IID: $base_entry_id], updating timestamp only", $debug_enabled);
|
||||||
|
|
||||||
|
// we keep encountering the entry in feeds, so we need to
|
||||||
|
// update date_updated column so that we don't get horrible
|
||||||
|
// dupes when the entry gets purged and reinserted again e.g.
|
||||||
|
// in the case of SLOW SLOW OMG SLOW updating feeds
|
||||||
|
|
||||||
|
$base_entry_id = db_fetch_result($result, 0, "id");
|
||||||
|
|
||||||
|
db_query("UPDATE ttrss_entries SET date_updated = NOW()
|
||||||
|
WHERE id = '$base_entry_id'");
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_debug("hash differs, applying plugin filters:", $debug_enabled);
|
||||||
|
|
||||||
|
foreach ($pluginhost->get_hooks(PluginHost::HOOK_ARTICLE_FILTER) as $plugin) {
|
||||||
|
_debug("... " . get_class($plugin), $debug_enabled);
|
||||||
|
|
||||||
|
$start = microtime(true);
|
||||||
|
$article = $plugin->hook_article_filter($article);
|
||||||
|
|
||||||
|
_debug("=== " . sprintf("%.4f (sec)", microtime(true) - $start), $debug_enabled);
|
||||||
|
|
||||||
|
$entry_plugin_data .= mb_strtolower(get_class($plugin)) . ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
$entry_plugin_data = db_escape_string($entry_plugin_data);
|
||||||
|
|
||||||
|
_debug("plugin data: $entry_plugin_data", $debug_enabled);
|
||||||
|
|
||||||
$entry_tags = $article["tags"];
|
$entry_tags = $article["tags"];
|
||||||
$entry_guid = db_escape_string($entry_guid);
|
$entry_guid = db_escape_string($entry_guid);
|
||||||
$entry_title = db_escape_string($article["title"]);
|
$entry_title = db_escape_string($article["title"]);
|
||||||
$entry_author = db_escape_string($article["author"]);
|
$entry_author = db_escape_string($article["author"]);
|
||||||
$entry_link = db_escape_string($article["link"]);
|
$entry_link = db_escape_string($article["link"]);
|
||||||
$entry_plugin_data = db_escape_string($article["plugin_data"]);
|
|
||||||
$entry_content = $article["content"]; // escaped below
|
$entry_content = $article["content"]; // escaped below
|
||||||
|
|
||||||
|
|
||||||
_debug("plugin data: $entry_plugin_data", $debug_enabled);
|
|
||||||
|
|
||||||
if ($cache_images && is_writable(CACHE_DIR . '/images'))
|
if ($cache_images && is_writable(CACHE_DIR . '/images'))
|
||||||
cache_images($entry_content, $site_url, $debug_enabled);
|
cache_images($entry_content, $site_url, $debug_enabled);
|
||||||
|
|
||||||
$entry_content = db_escape_string($entry_content, false);
|
$entry_content = db_escape_string($entry_content, false);
|
||||||
|
|
||||||
$content_hash = "SHA1:" . sha1($entry_content);
|
|
||||||
|
|
||||||
db_query("BEGIN");
|
db_query("BEGIN");
|
||||||
|
|
||||||
$result = db_query("SELECT id FROM ttrss_entries
|
$result = db_query("SELECT id FROM ttrss_entries
|
||||||
|
@ -707,8 +772,8 @@
|
||||||
'$entry_link',
|
'$entry_link',
|
||||||
'$entry_timestamp_fmt',
|
'$entry_timestamp_fmt',
|
||||||
'$entry_content',
|
'$entry_content',
|
||||||
'$content_hash',
|
'$entry_current_hash',
|
||||||
$no_orig_date,
|
false,
|
||||||
NOW(),
|
NOW(),
|
||||||
'$date_feed_processed',
|
'$date_feed_processed',
|
||||||
'$entry_comments',
|
'$entry_comments',
|
||||||
|
@ -720,28 +785,14 @@
|
||||||
$article_labels = array();
|
$article_labels = array();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// we keep encountering the entry in feeds, so we need to
|
|
||||||
// update date_updated column so that we don't get horrible
|
|
||||||
// dupes when the entry gets purged and reinserted again e.g.
|
|
||||||
// in the case of SLOW SLOW OMG SLOW updating feeds
|
|
||||||
|
|
||||||
$base_entry_id = db_fetch_result($result, 0, "id");
|
$base_entry_id = db_fetch_result($result, 0, "id");
|
||||||
|
|
||||||
db_query("UPDATE ttrss_entries SET date_updated = NOW()
|
|
||||||
WHERE id = '$base_entry_id'");
|
|
||||||
|
|
||||||
$article_labels = get_article_labels($base_entry_id, $owner_uid);
|
$article_labels = get_article_labels($base_entry_id, $owner_uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// now it should exist, if not - bad luck then
|
// now it should exist, if not - bad luck then
|
||||||
|
|
||||||
$result = db_query("SELECT
|
$result = db_query("SELECT id FROM ttrss_entries
|
||||||
id,content_hash,no_orig_date,title,plugin_data,guid,
|
|
||||||
".SUBSTRING_FOR_DATE."(date_updated,1,19) as date_updated,
|
|
||||||
".SUBSTRING_FOR_DATE."(updated,1,19) as updated,
|
|
||||||
num_comments
|
|
||||||
FROM
|
|
||||||
ttrss_entries
|
|
||||||
WHERE guid = '$entry_guid' OR guid = '$entry_guid_hashed'");
|
WHERE guid = '$entry_guid' OR guid = '$entry_guid_hashed'");
|
||||||
|
|
||||||
$entry_ref_id = 0;
|
$entry_ref_id = 0;
|
||||||
|
@ -751,14 +802,6 @@
|
||||||
|
|
||||||
_debug("base guid found, checking for user record", $debug_enabled);
|
_debug("base guid found, checking for user record", $debug_enabled);
|
||||||
|
|
||||||
// this will be used below in update handler
|
|
||||||
$orig_content_hash = db_fetch_result($result, 0, "content_hash");
|
|
||||||
$orig_title = db_fetch_result($result, 0, "title");
|
|
||||||
$orig_num_comments = db_fetch_result($result, 0, "num_comments");
|
|
||||||
$orig_date_updated = strtotime(db_fetch_result($result,
|
|
||||||
0, "date_updated"));
|
|
||||||
$orig_plugin_data = db_fetch_result($result, 0, "plugin_data");
|
|
||||||
|
|
||||||
$ref_id = db_fetch_result($result, 0, "id");
|
$ref_id = db_fetch_result($result, 0, "id");
|
||||||
$entry_ref_id = $ref_id;
|
$entry_ref_id = $ref_id;
|
||||||
|
|
||||||
|
@ -872,7 +915,7 @@
|
||||||
|
|
||||||
$p = new Publisher(PUBSUBHUBBUB_HUB);
|
$p = new Publisher(PUBSUBHUBBUB_HUB);
|
||||||
|
|
||||||
$pubsub_result = $p->publish_update($rss_link);
|
/* $pubsub_result = */ $p->publish_update($rss_link);
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = db_query(
|
$result = db_query(
|
||||||
|
@ -892,53 +935,20 @@
|
||||||
|
|
||||||
_debug("RID: $entry_ref_id, IID: $entry_int_id", $debug_enabled);
|
_debug("RID: $entry_ref_id, IID: $entry_int_id", $debug_enabled);
|
||||||
|
|
||||||
$post_needs_update = false;
|
db_query("UPDATE ttrss_entries
|
||||||
$update_insignificant = false;
|
SET title = '$entry_title',
|
||||||
|
content = '$entry_content',
|
||||||
|
content_hash = '$entry_current_hash',
|
||||||
|
updated = '$entry_timestamp_fmt',
|
||||||
|
num_comments = '$num_comments',
|
||||||
|
plugin_data = '$entry_plugin_data',
|
||||||
|
author = '$entry_author',
|
||||||
|
lang = '$entry_language'
|
||||||
|
WHERE id = '$ref_id'");
|
||||||
|
|
||||||
if ($orig_num_comments != $num_comments) {
|
if ($mark_unread_on_update) {
|
||||||
$post_needs_update = true;
|
db_query("UPDATE ttrss_user_entries
|
||||||
$update_insignificant = true;
|
SET last_read = null, unread = true WHERE ref_id = '$ref_id'");
|
||||||
}
|
|
||||||
|
|
||||||
if ($entry_plugin_data != $orig_plugin_data) {
|
|
||||||
$post_needs_update = true;
|
|
||||||
$update_insignificant = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($content_hash != $orig_content_hash) {
|
|
||||||
$post_needs_update = true;
|
|
||||||
$update_insignificant = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (db_escape_string($orig_title) != $entry_title) {
|
|
||||||
$post_needs_update = true;
|
|
||||||
$update_insignificant = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if post needs update, update it and mark all user entries
|
|
||||||
// linking to this post as updated
|
|
||||||
if ($post_needs_update) {
|
|
||||||
|
|
||||||
if (defined('DAEMON_EXTENDED_DEBUG')) {
|
|
||||||
_debug("post $entry_guid_hashed needs update...", $debug_enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
// print "<!-- post $orig_title needs update : $post_needs_update -->";
|
|
||||||
|
|
||||||
db_query("UPDATE ttrss_entries
|
|
||||||
SET title = '$entry_title', content = '$entry_content',
|
|
||||||
content_hash = '$content_hash',
|
|
||||||
updated = '$entry_timestamp_fmt',
|
|
||||||
num_comments = '$num_comments',
|
|
||||||
plugin_data = '$entry_plugin_data'
|
|
||||||
WHERE id = '$ref_id'");
|
|
||||||
|
|
||||||
if (!$update_insignificant) {
|
|
||||||
if ($mark_unread_on_update) {
|
|
||||||
db_query("UPDATE ttrss_user_entries
|
|
||||||
SET last_read = null, unread = true WHERE ref_id = '$ref_id'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -960,7 +970,7 @@
|
||||||
if (is_array($encs)) {
|
if (is_array($encs)) {
|
||||||
foreach ($encs as $e) {
|
foreach ($encs as $e) {
|
||||||
$e_item = array(
|
$e_item = array(
|
||||||
$e->link, $e->type, $e->length, $e->title);
|
$e->link, $e->type, $e->length, $e->title, $e->width, $e->height);
|
||||||
array_push($enclosures, $e_item);
|
array_push($enclosures, $e_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -980,14 +990,16 @@
|
||||||
$enc_type = db_escape_string($enc[1]);
|
$enc_type = db_escape_string($enc[1]);
|
||||||
$enc_dur = db_escape_string($enc[2]);
|
$enc_dur = db_escape_string($enc[2]);
|
||||||
$enc_title = db_escape_string($enc[3]);
|
$enc_title = db_escape_string($enc[3]);
|
||||||
|
$enc_width = intval($enc[4]);
|
||||||
|
$enc_height = intval($enc[5]);
|
||||||
|
|
||||||
$result = db_query("SELECT id FROM ttrss_enclosures
|
$result = db_query("SELECT id FROM ttrss_enclosures
|
||||||
WHERE content_url = '$enc_url' AND post_id = '$entry_ref_id'");
|
WHERE content_url = '$enc_url' AND post_id = '$entry_ref_id'");
|
||||||
|
|
||||||
if (db_num_rows($result) == 0) {
|
if (db_num_rows($result) == 0) {
|
||||||
db_query("INSERT INTO ttrss_enclosures
|
db_query("INSERT INTO ttrss_enclosures
|
||||||
(content_url, content_type, title, duration, post_id) VALUES
|
(content_url, content_type, title, duration, post_id, width, height) VALUES
|
||||||
('$enc_url', '$enc_type', '$enc_title', '$enc_dur', '$entry_ref_id')");
|
('$enc_url', '$enc_type', '$enc_title', '$enc_dur', '$entry_ref_id', $enc_width, $enc_height)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1101,21 +1113,27 @@
|
||||||
|
|
||||||
$error_msg = db_escape_string(mb_substr($rss->error(), 0, 245));
|
$error_msg = db_escape_string(mb_substr($rss->error(), 0, 245));
|
||||||
|
|
||||||
_debug("error fetching feed: $error_msg", $debug_enabled);
|
_debug("fetch error: $error_msg", $debug_enabled);
|
||||||
|
|
||||||
|
if (count($rss->errors()) > 1) {
|
||||||
|
foreach ($rss->errors() as $error) {
|
||||||
|
_debug("+ $error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
db_query(
|
db_query(
|
||||||
"UPDATE ttrss_feeds SET last_error = '$error_msg',
|
"UPDATE ttrss_feeds SET last_error = '$error_msg',
|
||||||
last_updated = NOW() WHERE id = '$feed'");
|
last_updated = NOW() WHERE id = '$feed'");
|
||||||
|
|
||||||
|
unset($rss);
|
||||||
}
|
}
|
||||||
|
|
||||||
unset($rss);
|
|
||||||
|
|
||||||
_debug("done", $debug_enabled);
|
_debug("done", $debug_enabled);
|
||||||
|
|
||||||
|
return $rss;
|
||||||
}
|
}
|
||||||
|
|
||||||
function cache_images($html, $site_url, $debug) {
|
function cache_images($html, $site_url, $debug) {
|
||||||
$cache_dir = CACHE_DIR . "/images";
|
|
||||||
|
|
||||||
libxml_use_internal_errors(true);
|
libxml_use_internal_errors(true);
|
||||||
|
|
||||||
$charset_hack = '<head>
|
$charset_hack = '<head>
|
||||||
|
@ -1139,7 +1157,7 @@
|
||||||
if (!file_exists($local_filename)) {
|
if (!file_exists($local_filename)) {
|
||||||
$file_content = fetch_file_contents($src);
|
$file_content = fetch_file_contents($src);
|
||||||
|
|
||||||
if ($file_content && strlen($file_content) > 1024) {
|
if ($file_content && strlen($file_content) > _MIN_CACHE_IMAGE_SIZE) {
|
||||||
file_put_contents($local_filename, $file_content);
|
file_put_contents($local_filename, $file_content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,11 +146,6 @@
|
||||||
array_push($errors, "PHP support for CURL is required for PubSubHubbub.");
|
array_push($errors, "PHP support for CURL is required for PubSubHubbub.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SPHINX_ENABLED && class_exists("SphinxClient")) {
|
|
||||||
array_push($errors, "Your PHP has a separate systemwide Sphinx client installed which conflicts with the client library used by tt-rss. Either remove the system library or disable Sphinx support.");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!class_exists("DOMDocument")) {
|
if (!class_exists("DOMDocument")) {
|
||||||
array_push($errors, "PHP support for DOMDocument is required, but was not found.");
|
array_push($errors, "PHP support for DOMDocument is required, but was not found.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
<?php # This file has been generated at: Thu May 30 08:39:20 MSK 2013
|
<?php # This file has been generated at: Fri Sep 27 13:42:37 MSK 2013
|
||||||
define('GENERATED_CONFIG_CHECK', 26);
|
define('GENERATED_CONFIG_CHECK', 26);
|
||||||
$requred_defines = array( 'DB_TYPE', 'DB_HOST', 'DB_USER', 'DB_NAME', 'DB_PASS', 'MYSQL_CHARSET', 'SELF_URL_PATH', 'FEED_CRYPT_KEY', 'SINGLE_USER_MODE', 'SIMPLE_UPDATE_MODE', 'PHP_EXECUTABLE', 'LOCK_DIRECTORY', 'CACHE_DIR', 'ICONS_DIR', 'ICONS_URL', 'AUTH_AUTO_CREATE', 'AUTH_AUTO_LOGIN', 'FORCE_ARTICLE_PURGE', 'PUBSUBHUBBUB_HUB', 'PUBSUBHUBBUB_ENABLED', 'SPHINX_ENABLED', 'SPHINX_SERVER', 'SPHINX_INDEX', 'ENABLE_REGISTRATION', 'REG_NOTIFY_ADDRESS', 'REG_MAX_USERS', 'SESSION_COOKIE_LIFETIME', 'SESSION_CHECK_ADDRESS', 'SMTP_FROM_NAME', 'SMTP_FROM_ADDRESS', 'DIGEST_SUBJECT', 'SMTP_SERVER', 'SMTP_LOGIN', 'SMTP_PASSWORD', 'SMTP_SECURE', 'CHECK_FOR_NEW_VERSION', 'ENABLE_GZIP_OUTPUT', 'PLUGINS', 'LOG_DESTINATION', 'CONFIG_VERSION'); ?>
|
$requred_defines = array( 'DB_TYPE', 'DB_HOST', 'DB_USER', 'DB_NAME', 'DB_PASS', 'MYSQL_CHARSET', 'SELF_URL_PATH', 'FEED_CRYPT_KEY', 'SINGLE_USER_MODE', 'SIMPLE_UPDATE_MODE', 'PHP_EXECUTABLE', 'LOCK_DIRECTORY', 'CACHE_DIR', 'ICONS_DIR', 'ICONS_URL', 'AUTH_AUTO_CREATE', 'AUTH_AUTO_LOGIN', 'FORCE_ARTICLE_PURGE', 'PUBSUBHUBBUB_HUB', 'PUBSUBHUBBUB_ENABLED', 'ENABLE_REGISTRATION', 'REG_NOTIFY_ADDRESS', 'REG_MAX_USERS', 'SESSION_COOKIE_LIFETIME', 'SESSION_CHECK_ADDRESS', 'SMTP_FROM_NAME', 'SMTP_FROM_ADDRESS', 'DIGEST_SUBJECT', 'SMTP_SERVER', 'SMTP_LOGIN', 'SMTP_PASSWORD', 'SMTP_SECURE', 'CHECK_FOR_NEW_VERSION', 'DETECT_ARTICLE_LANGUAGE', 'ENABLE_GZIP_OUTPUT', 'PLUGINS', 'LOG_DESTINATION', 'CONFIG_VERSION'); ?>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
define('VERSION_STATIC', '1.10');
|
define('VERSION_STATIC', '1.14');
|
||||||
|
|
||||||
function get_version() {
|
function get_version() {
|
||||||
date_default_timezone_set('UTC');
|
date_default_timezone_set('UTC');
|
||||||
|
|
|
@ -56,15 +56,19 @@
|
||||||
<head>
|
<head>
|
||||||
<title>Tiny Tiny RSS</title>
|
<title>Tiny Tiny RSS</title>
|
||||||
|
|
||||||
<?php stylesheet_tag("lib/dijit/themes/claro/claro.css"); ?>
|
<script type="text/javascript">
|
||||||
<?php stylesheet_tag("css/layout.css"); ?>
|
var __ttrss_version = "<?php echo VERSION ?>"
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<?php echo stylesheet_tag("lib/dijit/themes/claro/claro.css"); ?>
|
||||||
|
<?php echo stylesheet_tag("css/layout.css"); ?>
|
||||||
|
|
||||||
<?php if ($_SESSION["uid"]) {
|
<?php if ($_SESSION["uid"]) {
|
||||||
$theme = get_pref( "USER_CSS_THEME", $_SESSION["uid"], false);
|
$theme = get_pref( "USER_CSS_THEME", $_SESSION["uid"], false);
|
||||||
if ($theme && file_exists("themes/$theme")) {
|
if ($theme && file_exists("themes/$theme")) {
|
||||||
stylesheet_tag("themes/$theme");
|
echo stylesheet_tag("themes/$theme");
|
||||||
} else {
|
} else {
|
||||||
stylesheet_tag("themes/default.css");
|
echo stylesheet_tag("themes/default.css");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
@ -86,12 +90,12 @@
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
foreach (array("lib/prototype.js",
|
foreach (array("lib/prototype.js",
|
||||||
"lib/scriptaculous/scriptaculous.js?load=effects,dragdrop,controls",
|
"lib/scriptaculous/scriptaculous.js?load=effects,controls",
|
||||||
"lib/dojo/dojo.js",
|
"lib/dojo/dojo.js",
|
||||||
"lib/dojo/tt-rss-layer.js",
|
"lib/dojo/tt-rss-layer.js",
|
||||||
"errors.php?mode=js") as $jsfile) {
|
"errors.php?mode=js") as $jsfile) {
|
||||||
|
|
||||||
javascript_tag($jsfile);
|
echo javascript_tag($jsfile);
|
||||||
|
|
||||||
} ?>
|
} ?>
|
||||||
|
|
||||||
|
@ -153,6 +157,10 @@
|
||||||
<div id="toolbar" dojoType="dijit.layout.ContentPane" region="top">
|
<div id="toolbar" dojoType="dijit.layout.ContentPane" region="top">
|
||||||
<div id="main-toolbar" dojoType="dijit.Toolbar">
|
<div id="main-toolbar" dojoType="dijit.Toolbar">
|
||||||
|
|
||||||
|
<form id="headlines-toolbar" action="" onsubmit='return false'>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
<form id="main_toolbar_form" action="" onsubmit='return false'>
|
<form id="main_toolbar_form" action="" onsubmit='return false'>
|
||||||
|
|
||||||
<button dojoType="dijit.form.Button" id="collapse_feeds_btn"
|
<button dojoType="dijit.form.Button" id="collapse_feeds_btn"
|
||||||
|
@ -257,9 +265,6 @@
|
||||||
|
|
||||||
<div id="headlines-wrap-inner" dojoType="dijit.layout.BorderContainer" region="center">
|
<div id="headlines-wrap-inner" dojoType="dijit.layout.BorderContainer" region="center">
|
||||||
|
|
||||||
<div id="headlines-toolbar" dojoType="dijit.layout.ContentPane" region="top">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="floatingTitle" style="display : none"></div>
|
<div id="floatingTitle" style="display : none"></div>
|
||||||
|
|
||||||
<div id="headlines-frame" dojoType="dijit.layout.ContentPane"
|
<div id="headlines-frame" dojoType="dijit.layout.ContentPane"
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
<title>Tiny Tiny RSS - Installer</title>
|
<title>Tiny Tiny RSS - Installer</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
<link rel="stylesheet" type="text/css" href="../css/utility.css">
|
<link rel="stylesheet" type="text/css" href="../css/utility.css">
|
||||||
|
<link rel="stylesheet" type="text/css" href="../css/dijit.css">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
textarea { font-size : 12px; }
|
textarea { font-size : 12px; }
|
||||||
</style>
|
</style>
|
||||||
|
@ -10,6 +11,12 @@
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
// could be needed because of existing config.php
|
||||||
|
function define_default($param, $value) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
function make_password($length = 8) {
|
function make_password($length = 8) {
|
||||||
|
|
||||||
$password = "";
|
$password = "";
|
||||||
|
@ -263,7 +270,7 @@
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label>Password</label>
|
<label>Password</label>
|
||||||
<input required name="DB_PASS" size="20" type="password" value="<?php echo $DB_PASS ?>"/>
|
<input name="DB_PASS" size="20" type="password" value="<?php echo $DB_PASS ?>"/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
|
|
@ -58,12 +58,12 @@ dojo.declare("fox.FeedStoreModel", dijit.tree.ForestStoreModel, {
|
||||||
|
|
||||||
if (is_cat) {
|
if (is_cat) {
|
||||||
treeItem = this.store._itemsByIdentity['CAT:' + feed];
|
treeItem = this.store._itemsByIdentity['CAT:' + feed];
|
||||||
items = this.store._arrayOfTopLevelItems;
|
|
||||||
} else {
|
} else {
|
||||||
treeItem = this.store._itemsByIdentity['FEED:' + feed];
|
treeItem = this.store._itemsByIdentity['FEED:' + feed];
|
||||||
items = this.store._arrayOfAllItems;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
items = this.store._arrayOfAllItems;
|
||||||
|
|
||||||
for (var i = 0; i < items.length; i++) {
|
for (var i = 0; i < items.length; i++) {
|
||||||
if (items[i] == treeItem) {
|
if (items[i] == treeItem) {
|
||||||
|
|
||||||
|
@ -71,14 +71,18 @@ dojo.declare("fox.FeedStoreModel", dijit.tree.ForestStoreModel, {
|
||||||
var unread = this.store.getValue(items[j], 'unread');
|
var unread = this.store.getValue(items[j], 'unread');
|
||||||
var id = this.store.getValue(items[j], 'id');
|
var id = this.store.getValue(items[j], 'id');
|
||||||
|
|
||||||
if (unread > 0 && (is_cat || id.match("FEED:"))) return items[j];
|
if (unread > 0 && ((is_cat && id.match("CAT:")) || (!is_cat && id.match("FEED:")))) {
|
||||||
|
if( !is_cat || ! (this.store.hasAttribute(items[j], 'parent_id') && this.store.getValue(items[j], 'parent_id') == feed) ) return items[j];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var j = 0; j < i; j++) {
|
for (var j = 0; j < i; j++) {
|
||||||
var unread = this.store.getValue(items[j], 'unread');
|
var unread = this.store.getValue(items[j], 'unread');
|
||||||
var id = this.store.getValue(items[j], 'id');
|
var id = this.store.getValue(items[j], 'id');
|
||||||
|
|
||||||
if (unread > 0 && (is_cat || id.match("FEED:"))) return items[j];
|
if (unread > 0 && ((is_cat && id.match("CAT:")) || (!is_cat && id.match("FEED:")))) {
|
||||||
|
if( !is_cat || ! (this.store.hasAttribute(items[j], 'parent_id') && this.store.getValue(items[j], 'parent_id') == feed) ) return items[j];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -539,7 +543,7 @@ dojo.declare("fox.FeedTree", dijit.Tree, {
|
||||||
}
|
}
|
||||||
|
|
||||||
items = this.model.store._arrayOfAllItems;
|
items = this.model.store._arrayOfAllItems;
|
||||||
var item = items[0];
|
var item = items[0] == treeItem ? items[items.length-1] : items[0];
|
||||||
|
|
||||||
for (var i = 0; i < items.length; i++) {
|
for (var i = 0; i < items.length; i++) {
|
||||||
if (items[i] == treeItem) {
|
if (items[i] == treeItem) {
|
||||||
|
|
|
@ -24,6 +24,7 @@ dojo.declare("fox.PrefFilterTree", lib.CheckBoxTree, {
|
||||||
|
|
||||||
var enabled = this.model.store.getValue(args.item, 'enabled');
|
var enabled = this.model.store.getValue(args.item, 'enabled');
|
||||||
var param = this.model.store.getValue(args.item, 'param');
|
var param = this.model.store.getValue(args.item, 'param');
|
||||||
|
var rules = this.model.store.getValue(args.item, 'rules');
|
||||||
|
|
||||||
if (param) {
|
if (param) {
|
||||||
param = dojo.doc.createElement('span');
|
param = dojo.doc.createElement('span');
|
||||||
|
@ -32,6 +33,13 @@ dojo.declare("fox.PrefFilterTree", lib.CheckBoxTree, {
|
||||||
dojo.place(param, tnode.rowNode, 'first');
|
dojo.place(param, tnode.rowNode, 'first');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rules) {
|
||||||
|
param = dojo.doc.createElement('span');
|
||||||
|
param.className = 'filterRules';
|
||||||
|
param.innerHTML = rules;
|
||||||
|
dojo.place(param, tnode.rowNode, 'next');
|
||||||
|
}
|
||||||
|
|
||||||
if (this.model.store.getValue(args.item, 'id') != 'root') {
|
if (this.model.store.getValue(args.item, 'id') != 'root') {
|
||||||
var img = dojo.doc.createElement('img');
|
var img = dojo.doc.createElement('img');
|
||||||
img.src ='images/filter.png';
|
img.src ='images/filter.png';
|
||||||
|
|
|
@ -44,11 +44,8 @@ function exception_error(location, e, ext_info) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (ext_info) {
|
if (ext_info)
|
||||||
if (ext_info.responseText) {
|
ext_info = JSON.stringify(ext_info);
|
||||||
ext_info = ext_info.responseText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new Ajax.Request("backend.php", {
|
new Ajax.Request("backend.php", {
|
||||||
|
@ -104,13 +101,15 @@ function exception_error(location, e, ext_info) {
|
||||||
title: "Unhandled exception",
|
title: "Unhandled exception",
|
||||||
style: "width: 600px",
|
style: "width: 600px",
|
||||||
report: function() {
|
report: function() {
|
||||||
if (confirm(__("Are you sure to report this exception to tt-rss.org? The report will include your browser information. Your IP would be saved in the database."))) {
|
if (confirm(__("Are you sure to report this exception to tt-rss.org? The report will include information about your web browser and tt-rss configuration. Your IP will be saved in the database."))) {
|
||||||
|
|
||||||
document.forms['exceptionForm'].params.value = $H({
|
document.forms['exceptionForm'].params.value = $H({
|
||||||
browserName: navigator.appName,
|
browserName: navigator.appName,
|
||||||
browserVersion: navigator.appVersion,
|
browserVersion: navigator.appVersion,
|
||||||
browserPlatform: navigator.platform,
|
browserPlatform: navigator.platform,
|
||||||
browserCookies: navigator.cookieEnabled,
|
browserCookies: navigator.cookieEnabled,
|
||||||
|
ttrssVersion: __ttrss_version,
|
||||||
|
initParams: JSON.stringify(init_params),
|
||||||
}).toQueryString();
|
}).toQueryString();
|
||||||
|
|
||||||
document.forms['exceptionForm'].submit();
|
document.forms['exceptionForm'].submit();
|
||||||
|
@ -205,6 +204,7 @@ function notify_real(msg, no_hide, n_type) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
Element.show(n);
|
Element.show(n);
|
||||||
|
new Effect.Highlight(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* types:
|
/* types:
|
||||||
|
@ -829,7 +829,14 @@ function quickAddFeed() {
|
||||||
onComplete: function(transport) {
|
onComplete: function(transport) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
var reply = JSON.parse(transport.responseText);
|
try {
|
||||||
|
var reply = JSON.parse(transport.responseText);
|
||||||
|
} catch (e) {
|
||||||
|
Element.hide("feed_add_spinner");
|
||||||
|
alert(__("Failed to parse output. This can indicate server timeout and/or network issues. Backend output was logged to browser console."));
|
||||||
|
console.log('quickAddFeed, backend returned:' + transport.responseText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var rc = reply['result'];
|
var rc = reply['result'];
|
||||||
|
|
||||||
|
@ -854,6 +861,8 @@ function quickAddFeed() {
|
||||||
case 4:
|
case 4:
|
||||||
feeds = rc['feeds'];
|
feeds = rc['feeds'];
|
||||||
|
|
||||||
|
Element.show("fadd_multiple_notify");
|
||||||
|
|
||||||
var select = dijit.byId("feedDlg_feedContainerSelect");
|
var select = dijit.byId("feedDlg_feedContainerSelect");
|
||||||
|
|
||||||
while (select.getOptions().length > 0)
|
while (select.getOptions().length > 0)
|
||||||
|
@ -1148,33 +1157,48 @@ function quickAddFilter() {
|
||||||
href: query});
|
href: query});
|
||||||
|
|
||||||
if (!inPreferences()) {
|
if (!inPreferences()) {
|
||||||
|
var selectedText = getSelectionText();
|
||||||
|
|
||||||
var lh = dojo.connect(dialog, "onLoad", function(){
|
var lh = dojo.connect(dialog, "onLoad", function(){
|
||||||
dojo.disconnect(lh);
|
dojo.disconnect(lh);
|
||||||
|
|
||||||
var query = "op=rpc&method=getlinktitlebyid&id=" + getActiveArticleId();
|
if (selectedText != "") {
|
||||||
|
|
||||||
new Ajax.Request("backend.php", {
|
var feed_id = activeFeedIsCat() ? 'CAT:' + parseInt(getActiveFeedId()) :
|
||||||
parameters: query,
|
getActiveFeedId();
|
||||||
onComplete: function(transport) {
|
|
||||||
var reply = JSON.parse(transport.responseText);
|
|
||||||
|
|
||||||
var title = false;
|
var rule = { reg_exp: selectedText, feed_id: feed_id, filter_type: 1 };
|
||||||
|
|
||||||
if (reply && reply) title = reply.title;
|
addFilterRule(null, dojo.toJson(rule));
|
||||||
|
|
||||||
if (title || getActiveFeedId() || activeFeedIsCat()) {
|
} else {
|
||||||
|
|
||||||
console.log(title + " " + getActiveFeedId());
|
var query = "op=rpc&method=getlinktitlebyid&id=" + getActiveArticleId();
|
||||||
|
|
||||||
var feed_id = activeFeedIsCat() ? 'CAT:' + parseInt(getActiveFeedId()) :
|
new Ajax.Request("backend.php", {
|
||||||
getActiveFeedId();
|
parameters: query,
|
||||||
|
onComplete: function(transport) {
|
||||||
|
var reply = JSON.parse(transport.responseText);
|
||||||
|
|
||||||
var rule = { reg_exp: title, feed_id: feed_id, filter_type: 1 };
|
var title = false;
|
||||||
|
|
||||||
addFilterRule(null, dojo.toJson(rule));
|
if (reply && reply) title = reply.title;
|
||||||
}
|
|
||||||
|
|
||||||
} });
|
if (title || getActiveFeedId() || activeFeedIsCat()) {
|
||||||
|
|
||||||
|
console.log(title + " " + getActiveFeedId());
|
||||||
|
|
||||||
|
var feed_id = activeFeedIsCat() ? 'CAT:' + parseInt(getActiveFeedId()) :
|
||||||
|
getActiveFeedId();
|
||||||
|
|
||||||
|
var rule = { reg_exp: title, feed_id: feed_id, filter_type: 1 };
|
||||||
|
|
||||||
|
addFilterRule(null, dojo.toJson(rule));
|
||||||
|
}
|
||||||
|
|
||||||
|
} });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1270,10 +1294,8 @@ function backend_sanity_check_callback(transport) {
|
||||||
console.log('reading init-params...');
|
console.log('reading init-params...');
|
||||||
|
|
||||||
for (k in params) {
|
for (k in params) {
|
||||||
var v = params[k];
|
console.log("IP: " + k + " => " + JSON.stringify(params[k]));
|
||||||
console.log("IP: " + k + " => " + v);
|
if (k == "label_base_index") _label_base_index = parseInt(params[k]);
|
||||||
|
|
||||||
if (k == "label_base_index") _label_base_index = parseInt(v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init_params = params;
|
init_params = params;
|
||||||
|
@ -1934,3 +1956,25 @@ function feed_to_label_id(feed) {
|
||||||
return _label_base_index - 1 + Math.abs(feed);
|
return _label_base_index - 1 + Math.abs(feed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// http://stackoverflow.com/questions/6251937/how-to-get-selecteduser-highlighted-text-in-contenteditable-element-and-replac
|
||||||
|
|
||||||
|
function getSelectionText() {
|
||||||
|
var text = "";
|
||||||
|
|
||||||
|
if (typeof window.getSelection != "undefined") {
|
||||||
|
var sel = window.getSelection();
|
||||||
|
if (sel.rangeCount) {
|
||||||
|
var container = document.createElement("div");
|
||||||
|
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
|
||||||
|
container.appendChild(sel.getRangeAt(i).cloneContents());
|
||||||
|
}
|
||||||
|
text = container.innerHTML;
|
||||||
|
}
|
||||||
|
} else if (typeof document.selection != "undefined") {
|
||||||
|
if (document.selection.type == "Text") {
|
||||||
|
text = document.selection.createRange().textText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return text.stripTags();
|
||||||
|
}
|
||||||
|
|
|
@ -231,6 +231,7 @@ function init() {
|
||||||
dojo.require("dijit.form.Select");
|
dojo.require("dijit.form.Select");
|
||||||
dojo.require("dijit.form.SimpleTextarea");
|
dojo.require("dijit.form.SimpleTextarea");
|
||||||
dojo.require("dijit.form.TextBox");
|
dojo.require("dijit.form.TextBox");
|
||||||
|
dojo.require("dijit.form.ComboBox");
|
||||||
dojo.require("dijit.form.ValidationTextBox");
|
dojo.require("dijit.form.ValidationTextBox");
|
||||||
dojo.require("dijit.InlineEditBox");
|
dojo.require("dijit.InlineEditBox");
|
||||||
dojo.require("dijit.layout.AccordionContainer");
|
dojo.require("dijit.layout.AccordionContainer");
|
||||||
|
@ -500,6 +501,10 @@ function init() {
|
||||||
if (!isCdmMode()) {
|
if (!isCdmMode()) {
|
||||||
_widescreen_mode = !_widescreen_mode;
|
_widescreen_mode = !_widescreen_mode;
|
||||||
|
|
||||||
|
// reset stored sizes because geometry changed
|
||||||
|
setCookie("ttrss_ci_width", 0);
|
||||||
|
setCookie("ttrss_ci_height", 0);
|
||||||
|
|
||||||
switchPanelMode(_widescreen_mode);
|
switchPanelMode(_widescreen_mode);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -550,25 +555,11 @@ function init_second_stage() {
|
||||||
updateFeedList();
|
updateFeedList();
|
||||||
closeArticlePanel();
|
closeArticlePanel();
|
||||||
|
|
||||||
_widescreen_mode = getInitParam("widescreen");
|
|
||||||
switchPanelMode(_widescreen_mode);
|
|
||||||
|
|
||||||
if (parseInt(getCookie("ttrss_fh_width")) > 0) {
|
if (parseInt(getCookie("ttrss_fh_width")) > 0) {
|
||||||
dijit.byId("feeds-holder").domNode.setStyle(
|
dijit.byId("feeds-holder").domNode.setStyle(
|
||||||
{width: getCookie("ttrss_fh_width") + "px" });
|
{width: getCookie("ttrss_fh_width") + "px" });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parseInt(getCookie("ttrss_ci_width")) > 0) {
|
|
||||||
if (_widescreen_mode) {
|
|
||||||
dijit.byId("content-insert").domNode.setStyle(
|
|
||||||
{width: getCookie("ttrss_ci_width") + "px" });
|
|
||||||
|
|
||||||
} else {
|
|
||||||
dijit.byId("content-insert").domNode.setStyle(
|
|
||||||
{height: getCookie("ttrss_ci_height") + "px" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dijit.byId("main").resize();
|
dijit.byId("main").resize();
|
||||||
|
|
||||||
var tmph = dojo.connect(dijit.byId('feeds-holder'), 'resize',
|
var tmph = dojo.connect(dijit.byId('feeds-holder'), 'resize',
|
||||||
|
@ -624,6 +615,9 @@ function init_second_stage() {
|
||||||
hotkeys[1] = tmp;
|
hotkeys[1] = tmp;
|
||||||
setInitParam("hotkeys", hotkeys);
|
setInitParam("hotkeys", hotkeys);
|
||||||
|
|
||||||
|
_widescreen_mode = getInitParam("widescreen");
|
||||||
|
switchPanelMode(_widescreen_mode);
|
||||||
|
|
||||||
console.log("second stage ok");
|
console.log("second stage ok");
|
||||||
|
|
||||||
if (getInitParam("simple_update")) {
|
if (getInitParam("simple_update")) {
|
||||||
|
@ -706,6 +700,10 @@ function quickMenuGo(opid) {
|
||||||
if (!isCdmMode()) {
|
if (!isCdmMode()) {
|
||||||
_widescreen_mode = !_widescreen_mode;
|
_widescreen_mode = !_widescreen_mode;
|
||||||
|
|
||||||
|
// reset stored sizes because geometry changed
|
||||||
|
setCookie("ttrss_ci_width", 0);
|
||||||
|
setCookie("ttrss_ci_height", 0);
|
||||||
|
|
||||||
switchPanelMode(_widescreen_mode);
|
switchPanelMode(_widescreen_mode);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -989,6 +987,12 @@ function handle_rpc_json(transport, scheduled_call) {
|
||||||
try {
|
try {
|
||||||
var reply = JSON.parse(transport.responseText);
|
var reply = JSON.parse(transport.responseText);
|
||||||
|
|
||||||
|
var netalert_dijit = dijit.byId("net-alert");
|
||||||
|
var netalert = false;
|
||||||
|
|
||||||
|
if (netalert_dijit)
|
||||||
|
netalert = netalert_dijit.domNode;
|
||||||
|
|
||||||
if (reply) {
|
if (reply) {
|
||||||
|
|
||||||
var error = reply['error'];
|
var error = reply['error'];
|
||||||
|
@ -1035,16 +1039,21 @@ function handle_rpc_json(transport, scheduled_call) {
|
||||||
if (runtime_info)
|
if (runtime_info)
|
||||||
parse_runtime_info(runtime_info);
|
parse_runtime_info(runtime_info);
|
||||||
|
|
||||||
Element.hide(dijit.byId("net-alert").domNode);
|
if (netalert) Element.hide(netalert);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//notify_error("Error communicating with server.");
|
if (netalert)
|
||||||
Element.show(dijit.byId("net-alert").domNode);
|
Element.show(netalert);
|
||||||
|
else
|
||||||
|
notify_error("Communication problem with server.");
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Element.show(dijit.byId("net-alert").domNode);
|
if (netalert)
|
||||||
//notify_error("Error communicating with server.");
|
Element.show(netalert);
|
||||||
|
else
|
||||||
|
notify_error("Communication problem with server.");
|
||||||
|
|
||||||
console.log(e);
|
console.log(e);
|
||||||
//exception_error("handle_rpc_json", e, transport);
|
//exception_error("handle_rpc_json", e, transport);
|
||||||
}
|
}
|
||||||
|
@ -1064,11 +1073,13 @@ function switchPanelMode(wide) {
|
||||||
|
|
||||||
dijit.byId("content-insert").domNode.setStyle({width: '50%',
|
dijit.byId("content-insert").domNode.setStyle({width: '50%',
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
borderLeftWidth: '1px',
|
|
||||||
borderLeftColor: '#c0c0c0',
|
|
||||||
borderTopWidth: '0px' });
|
borderTopWidth: '0px' });
|
||||||
|
|
||||||
$("headlines-toolbar").setStyle({ borderBottomWidth: '0px' });
|
if (parseInt(getCookie("ttrss_ci_width")) > 0) {
|
||||||
|
dijit.byId("content-insert").domNode.setStyle(
|
||||||
|
{width: getCookie("ttrss_ci_width") + "px" });
|
||||||
|
}
|
||||||
|
|
||||||
$("headlines-frame").setStyle({ borderBottomWidth: '0px' });
|
$("headlines-frame").setStyle({ borderBottomWidth: '0px' });
|
||||||
$("headlines-frame").addClassName("wide");
|
$("headlines-frame").addClassName("wide");
|
||||||
|
|
||||||
|
@ -1078,10 +1089,12 @@ function switchPanelMode(wide) {
|
||||||
|
|
||||||
dijit.byId("content-insert").domNode.setStyle({width: 'auto',
|
dijit.byId("content-insert").domNode.setStyle({width: 'auto',
|
||||||
height: '50%',
|
height: '50%',
|
||||||
borderLeftWidth: '0px',
|
borderTopWidth: '0px'});
|
||||||
borderTopWidth: '1px'});
|
|
||||||
|
|
||||||
$("headlines-toolbar").setStyle({ borderBottomWidth: '1px' });
|
if (parseInt(getCookie("ttrss_ci_height")) > 0) {
|
||||||
|
dijit.byId("content-insert").domNode.setStyle(
|
||||||
|
{height: getCookie("ttrss_ci_height") + "px" });
|
||||||
|
}
|
||||||
|
|
||||||
$("headlines-frame").setStyle({ borderBottomWidth: '1px' });
|
$("headlines-frame").setStyle({ borderBottomWidth: '1px' });
|
||||||
$("headlines-frame").removeClassName("wide");
|
$("headlines-frame").removeClassName("wide");
|
||||||
|
|
|
@ -87,8 +87,12 @@ function headlines_callback2(transport, offset, background, infscroll_req) {
|
||||||
dijit.byId("headlines-frame").attr('content',
|
dijit.byId("headlines-frame").attr('content',
|
||||||
reply['headlines']['content']);
|
reply['headlines']['content']);
|
||||||
|
|
||||||
dijit.byId("headlines-toolbar").attr('content',
|
//dijit.byId("headlines-toolbar").attr('content',
|
||||||
reply['headlines']['toolbar']);
|
// reply['headlines']['toolbar']);
|
||||||
|
|
||||||
|
dojo.html.set($("headlines-toolbar"),
|
||||||
|
reply['headlines']['toolbar'],
|
||||||
|
{parseContent: true});
|
||||||
|
|
||||||
$$("#headlines-frame > div[id*=RROW]").each(function(row) {
|
$$("#headlines-frame > div[id*=RROW]").each(function(row) {
|
||||||
if (loaded_article_ids.indexOf(row.id) != -1) {
|
if (loaded_article_ids.indexOf(row.id) != -1) {
|
||||||
|
@ -104,6 +108,10 @@ function headlines_callback2(transport, offset, background, infscroll_req) {
|
||||||
|
|
||||||
initHeadlinesMenu();
|
initHeadlinesMenu();
|
||||||
|
|
||||||
|
if (_infscroll_disable)
|
||||||
|
hsp.innerHTML = "<a href='#' onclick='openNextUnreadFeed()'>" +
|
||||||
|
__("Click to open next unread feed.") + "</a>";
|
||||||
|
|
||||||
if (_search_query) {
|
if (_search_query) {
|
||||||
$("feed_title").innerHTML += "<span id='cancel_search'>" +
|
$("feed_title").innerHTML += "<span id='cancel_search'>" +
|
||||||
" (<a href='#' onclick='cancelSearch()'>" + __("Cancel search") + "</a>)" +
|
" (<a href='#' onclick='cancelSearch()'>" + __("Cancel search") + "</a>)" +
|
||||||
|
@ -143,9 +151,9 @@ function headlines_callback2(transport, offset, background, infscroll_req) {
|
||||||
|
|
||||||
if (!hsp) hsp = new Element("DIV", {"id": "headlines-spacer"});
|
if (!hsp) hsp = new Element("DIV", {"id": "headlines-spacer"});
|
||||||
|
|
||||||
if (getInitParam("cdm_auto_catchup") == 1) {
|
// if (getInitParam("cdm_auto_catchup") == 1) {
|
||||||
c.domNode.appendChild(hsp);
|
c.domNode.appendChild(hsp);
|
||||||
}
|
// }
|
||||||
|
|
||||||
console.log("added " + new_elems.size() + " headlines");
|
console.log("added " + new_elems.size() + " headlines");
|
||||||
|
|
||||||
|
@ -172,7 +180,8 @@ function headlines_callback2(transport, offset, background, infscroll_req) {
|
||||||
|
|
||||||
var hsp = $("headlines-spacer");
|
var hsp = $("headlines-spacer");
|
||||||
|
|
||||||
if (hsp) hsp.innerHTML = "";
|
if (hsp) hsp.innerHTML = "<a href='#' onclick='openNextUnreadFeed()'>" +
|
||||||
|
__("Click to open next unread feed.") + "</a>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,14 +199,11 @@ function headlines_callback2(transport, offset, background, infscroll_req) {
|
||||||
else
|
else
|
||||||
request_counters(true);
|
request_counters(true);
|
||||||
|
|
||||||
} else if (transport.responseText) {
|
} else {
|
||||||
console.error("Invalid object received: " + transport.responseText);
|
console.error("Invalid object received: " + transport.responseText);
|
||||||
dijit.byId("headlines-frame").attr('content', "<div class='whiteBox'>" +
|
dijit.byId("headlines-frame").attr('content', "<div class='whiteBox'>" +
|
||||||
__('Could not update headlines (invalid object received - see error console for details)') +
|
__('Could not update headlines (invalid object received - see error console for details)') +
|
||||||
"</div>");
|
"</div>");
|
||||||
} else {
|
|
||||||
//notify_error("Error communicating with server.");
|
|
||||||
Element.show(dijit.byId("net-alert").domNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_infscroll_request_sent = 0;
|
_infscroll_request_sent = 0;
|
||||||
|
@ -314,13 +320,11 @@ function article_callback2(transport, id) {
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
} else if (transport.responseText) {
|
} else {
|
||||||
console.error("Invalid object received: " + transport.responseText);
|
console.error("Invalid object received: " + transport.responseText);
|
||||||
|
|
||||||
render_article("<div class='whiteBox'>" +
|
render_article("<div class='whiteBox'>" +
|
||||||
__('Could not display article (invalid object received - see error console for details)') + "</div>");
|
__('Could not display article (invalid object received - see error console for details)') + "</div>");
|
||||||
} else {
|
|
||||||
Element.show(dijit.byId("net-alert").domNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var unread_in_buffer = $$("#headlines-frame > div[id*=RROW][class*=Unread]").length
|
var unread_in_buffer = $$("#headlines-frame > div[id*=RROW][class*=Unread]").length
|
||||||
|
@ -961,10 +965,12 @@ function getLoadedArticleIds() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// mode = all,none,unread,invert,marked,published
|
// mode = all,none,unread,invert,marked,published
|
||||||
function selectArticles(mode) {
|
function selectArticles(mode, query) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
var children = $$("#headlines-frame > div[id*=RROW]");
|
if (!query) query = "#headlines-frame > div[id*=RROW]";
|
||||||
|
|
||||||
|
var children = $$(query);
|
||||||
|
|
||||||
children.each(function(child) {
|
children.each(function(child) {
|
||||||
var id = child.id.replace("RROW-", "");
|
var id = child.id.replace("RROW-", "");
|
||||||
|
@ -1243,7 +1249,7 @@ function postMouseOut(id) {
|
||||||
|
|
||||||
function unpackVisibleHeadlines() {
|
function unpackVisibleHeadlines() {
|
||||||
try {
|
try {
|
||||||
if (!isCdmMode()) return;
|
if (!isCdmMode() || !getInitParam("cdm_expanded")) return;
|
||||||
|
|
||||||
$$("#headlines-frame > div[id*=RROW]").each(
|
$$("#headlines-frame > div[id*=RROW]").each(
|
||||||
function(child) {
|
function(child) {
|
||||||
|
@ -1306,15 +1312,20 @@ function headlines_scroll_handler(e) {
|
||||||
((e.scrollTop + e.offsetHeight) / e.scrollHeight >= 0.7))) {
|
((e.scrollTop + e.offsetHeight) / e.scrollHeight >= 0.7))) {
|
||||||
|
|
||||||
if (hsp)
|
if (hsp)
|
||||||
hsp.innerHTML = "<img src='images/indicator_tiny.gif'> " +
|
hsp.innerHTML = "<span class='loading'><img src='images/indicator_tiny.gif'> " +
|
||||||
__("Loading, please wait...");
|
__("Loading, please wait...") + "</span>";
|
||||||
|
|
||||||
loadMoreHeadlines();
|
loadMoreHeadlines();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (hsp) hsp.innerHTML = "";
|
if (hsp)
|
||||||
|
if (_infscroll_disable)
|
||||||
|
hsp.innerHTML = "<a href='#' onclick='openNextUnreadFeed()'>" +
|
||||||
|
__("Click to open next unread feed.") + "</a>";
|
||||||
|
else
|
||||||
|
hsp.innerHTML = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCdmMode()) {
|
if (isCdmMode()) {
|
||||||
|
@ -1350,6 +1361,20 @@ function headlines_scroll_handler(e) {
|
||||||
500);
|
500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_infscroll_disable) {
|
||||||
|
var child = $$("#headlines-frame div[id*=RROW]").last();
|
||||||
|
|
||||||
|
if (child && $("headlines-frame").scrollTop >
|
||||||
|
(child.offsetTop + child.offsetHeight - 50)) {
|
||||||
|
|
||||||
|
console.log("we seem to be at an end");
|
||||||
|
|
||||||
|
if (getInitParam("on_catchup_show_next_feed") == "1") {
|
||||||
|
openNextUnreadFeed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -1357,6 +1382,16 @@ function headlines_scroll_handler(e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openNextUnreadFeed() {
|
||||||
|
try {
|
||||||
|
var is_cat = activeFeedIsCat();
|
||||||
|
var nuf = getNextUnreadFeed(getActiveFeedId(), is_cat);
|
||||||
|
if (nuf) viewfeed(nuf, '', is_cat);
|
||||||
|
} catch (e) {
|
||||||
|
exception_error("openNextUnreadFeed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function catchupBatchedArticles() {
|
function catchupBatchedArticles() {
|
||||||
try {
|
try {
|
||||||
if (catchup_id_batch.length > 0 && !_infscroll_request_sent) {
|
if (catchup_id_batch.length > 0 && !_infscroll_request_sent) {
|
||||||
|
@ -1761,7 +1796,8 @@ function cdmClicked(event, id) {
|
||||||
return !event.shiftKey;
|
return !event.shiftKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else if (event.target.parents(".cdmHeader").length > 0) {
|
||||||
|
|
||||||
toggleSelected(id, true);
|
toggleSelected(id, true);
|
||||||
|
|
||||||
var elem = $("RROW-" + id);
|
var elem = $("RROW-" + id);
|
||||||
|
@ -2107,6 +2143,72 @@ function initHeadlinesMenu() {
|
||||||
|
|
||||||
menu.startup();
|
menu.startup();
|
||||||
|
|
||||||
|
/* vgroup feed title menu */
|
||||||
|
|
||||||
|
var nodes = $$("#headlines-frame > div[class='cdmFeedTitle']");
|
||||||
|
var ids = [];
|
||||||
|
|
||||||
|
nodes.each(function(node) {
|
||||||
|
ids.push(node.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ids.length > 0) {
|
||||||
|
if (dijit.byId("headlinesFeedTitleMenu"))
|
||||||
|
dijit.byId("headlinesFeedTitleMenu").destroyRecursive();
|
||||||
|
|
||||||
|
var menu = new dijit.Menu({
|
||||||
|
id: "headlinesFeedTitleMenu",
|
||||||
|
targetNodeIds: ids,
|
||||||
|
});
|
||||||
|
|
||||||
|
var tmph = dojo.connect(menu, '_openMyself', function (event) {
|
||||||
|
var callerNode = event.target, match = null, tries = 0;
|
||||||
|
|
||||||
|
while (match == null && callerNode && tries <= 3) {
|
||||||
|
console.log(callerNode.id);
|
||||||
|
|
||||||
|
match = callerNode.id.match("^[A-Z]+[-]([0-9]+)$");
|
||||||
|
callerNode = callerNode.parentNode;
|
||||||
|
++tries;
|
||||||
|
|
||||||
|
console.log(match[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match) this.callerRowId = parseInt(match[1]);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.addChild(new dijit.MenuItem({
|
||||||
|
label: __("Select articles in group"),
|
||||||
|
onClick: function(event) {
|
||||||
|
selectArticles("all",
|
||||||
|
"#headlines-frame > div[id*=RROW]"+
|
||||||
|
"[orig-feed-id='"+menu.callerRowId+"']");
|
||||||
|
|
||||||
|
}}));
|
||||||
|
|
||||||
|
menu.addChild(new dijit.MenuItem({
|
||||||
|
label: __("Mark group as read"),
|
||||||
|
onClick: function(event) {
|
||||||
|
selectArticles("none");
|
||||||
|
selectArticles("all",
|
||||||
|
"#headlines-frame > div[id*=RROW]"+
|
||||||
|
"[orig-feed-id='"+menu.callerRowId+"']");
|
||||||
|
|
||||||
|
catchupSelection();
|
||||||
|
}}));
|
||||||
|
|
||||||
|
|
||||||
|
menu.addChild(new dijit.MenuItem({
|
||||||
|
label: __("Mark feed as read"),
|
||||||
|
onClick: function(event) {
|
||||||
|
catchupFeedInGroup(menu.callerRowId);
|
||||||
|
}}));
|
||||||
|
|
||||||
|
menu.startup();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
exception_error("initHeadlinesMenu", e);
|
exception_error("initHeadlinesMenu", e);
|
||||||
}
|
}
|
||||||
|
|