diff options
Diffstat (limited to 'classes')
-rw-r--r-- | classes/api.php | 160 | ||||
-rw-r--r-- | classes/article.php | 4 | ||||
-rw-r--r-- | classes/auth/base.php | 4 | ||||
-rw-r--r-- | classes/db/pdo.php | 2 | ||||
-rw-r--r-- | classes/db/prefs.php | 2 | ||||
-rw-r--r-- | classes/feedenclosure.php | 7 | ||||
-rw-r--r-- | classes/feeditem.php | 15 | ||||
-rw-r--r-- | classes/feeditem/atom.php | 122 | ||||
-rw-r--r-- | classes/feeditem/common.php | 51 | ||||
-rw-r--r-- | classes/feeditem/rss.php | 119 | ||||
-rw-r--r-- | classes/feedparser.php | 214 | ||||
-rw-r--r-- | classes/feeds.php | 51 | ||||
-rw-r--r-- | classes/handler/public.php | 21 | ||||
-rw-r--r-- | classes/opml.php | 2 | ||||
-rw-r--r-- | classes/pluginhost.php | 5 | ||||
-rw-r--r-- | classes/pref/feeds.php | 63 | ||||
-rw-r--r-- | classes/pref/filters.php | 2 | ||||
-rw-r--r-- | classes/pref/prefs.php | 12 | ||||
-rw-r--r-- | classes/pref/users.php | 17 | ||||
-rw-r--r-- | classes/rpc.php | 4 | ||||
-rw-r--r-- | classes/sanitizedummy.php | 7 | ||||
-rw-r--r-- | classes/ttrssmailer.php | 2 |
22 files changed, 694 insertions, 192 deletions
diff --git a/classes/api.php b/classes/api.php index badd0b564..23866072f 100644 --- a/classes/api.php +++ b/classes/api.php @@ -2,7 +2,7 @@ class API extends Handler { - const API_LEVEL = 6; + const API_LEVEL = 7; const STATUS_OK = 0; const STATUS_ERR = 1; @@ -14,12 +14,12 @@ class API extends Handler { header("Content-Type: text/json"); if (!$_SESSION["uid"] && $method != "login" && $method != "isloggedin") { - print $this->wrap(self::STATUS_ERR, array("error" => 'NOT_LOGGED_IN')); + $this->wrap(self::STATUS_ERR, array("error" => 'NOT_LOGGED_IN')); return false; } if ($_SESSION["uid"] && $method != "logout" && !get_pref('ENABLE_API_ACCESS')) { - print $this->wrap(self::STATUS_ERR, array("error" => 'API_DISABLED')); + $this->wrap(self::STATUS_ERR, array("error" => 'API_DISABLED')); return false; } @@ -38,12 +38,12 @@ class API extends Handler { function getVersion() { $rv = array("version" => VERSION); - print $this->wrap(self::STATUS_OK, $rv); + $this->wrap(self::STATUS_OK, $rv); } function getApiLevel() { $rv = array("level" => self::API_LEVEL); - print $this->wrap(self::STATUS_OK, $rv); + $this->wrap(self::STATUS_OK, $rv); } function login() { @@ -65,33 +65,33 @@ class API extends Handler { } if (!$uid) { - print $this->wrap(self::STATUS_ERR, array("error" => "LOGIN_ERROR")); + $this->wrap(self::STATUS_ERR, array("error" => "LOGIN_ERROR")); return; } if (get_pref("ENABLE_API_ACCESS", $uid)) { if (authenticate_user($login, $password)) { // try login with normal password - print $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)); } else if (authenticate_user($login, $password_base64)) { // else try with base64_decoded password - print $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)); } else { // else we are not logged in - print $this->wrap(self::STATUS_ERR, array("error" => "LOGIN_ERROR")); + $this->wrap(self::STATUS_ERR, array("error" => "LOGIN_ERROR")); } } else { - print $this->wrap(self::STATUS_ERR, array("error" => "API_DISABLED")); + $this->wrap(self::STATUS_ERR, array("error" => "API_DISABLED")); } } function logout() { logout_user(); - print $this->wrap(self::STATUS_OK, array("status" => "OK")); + $this->wrap(self::STATUS_OK, array("status" => "OK")); } function isLoggedIn() { - print $this->wrap(self::STATUS_OK, array("status" => $_SESSION["uid"] != '')); + $this->wrap(self::STATUS_OK, array("status" => $_SESSION["uid"] != '')); } function getUnread() { @@ -99,15 +99,15 @@ class API extends Handler { $is_cat = $this->dbh->escape_string($_REQUEST["is_cat"]); if ($feed_id) { - print $this->wrap(self::STATUS_OK, array("unread" => getFeedUnread($feed_id, $is_cat))); + $this->wrap(self::STATUS_OK, array("unread" => getFeedUnread($feed_id, $is_cat))); } else { - print $this->wrap(self::STATUS_OK, array("unread" => getGlobalUnread())); + $this->wrap(self::STATUS_OK, array("unread" => getGlobalUnread())); } } /* Method added for ttrss-reader for Android */ function getCounters() { - print $this->wrap(self::STATUS_OK, getAllCounters()); + $this->wrap(self::STATUS_OK, getAllCounters()); } function getFeeds() { @@ -119,7 +119,7 @@ class API extends Handler { $feeds = $this->api_get_feeds($cat_id, $unread_only, $limit, $offset, $include_nested); - print $this->wrap(self::STATUS_OK, $feeds); + $this->wrap(self::STATUS_OK, $feeds); } function getCategories() { @@ -176,7 +176,7 @@ class API extends Handler { } } - print $this->wrap(self::STATUS_OK, $cats); + $this->wrap(self::STATUS_OK, $cats); } function getHeadlines() { @@ -197,7 +197,8 @@ class API extends Handler { $include_attachments = sql_bool_to_bool($_REQUEST["include_attachments"]); $since_id = (int)$this->dbh->escape_string($_REQUEST["since_id"]); $include_nested = sql_bool_to_bool($_REQUEST["include_nested"]); - $sanitize_content = true; + $sanitize_content = !isset($_REQUEST["sanitize"]) || + sql_bool_to_bool($_REQUEST["sanitize"]); $override_order = false; switch ($_REQUEST["order_by"]) { @@ -219,9 +220,9 @@ class API extends Handler { $include_attachments, $since_id, $search, $search_mode, $include_nested, $sanitize_content); - print $this->wrap(self::STATUS_OK, $headlines); + $this->wrap(self::STATUS_OK, $headlines); } else { - print $this->wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE')); + $this->wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE')); } } @@ -293,11 +294,11 @@ class API extends Handler { } } - print $this->wrap(self::STATUS_OK, array("status" => "OK", + $this->wrap(self::STATUS_OK, array("status" => "OK", "updated" => $num_updated)); } else { - print $this->wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE')); + $this->wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE')); } } @@ -306,54 +307,58 @@ class API extends Handler { $article_id = join(",", array_filter(explode(",", $this->dbh->escape_string($_REQUEST["article_id"])), is_numeric)); - $query = "SELECT id,title,link,content,cached_content,feed_id,comments,int_id, - marked,unread,published,score, - ".SUBSTRING_FOR_DATE."(updated,1,16) as updated, - author,(SELECT title FROM ttrss_feeds WHERE id = feed_id) AS feed_title - FROM ttrss_entries,ttrss_user_entries - WHERE id IN ($article_id) AND ref_id = id AND owner_uid = " . - $_SESSION["uid"] ; + if ($article_id) { - $result = $this->dbh->query($query); + $query = "SELECT id,title,link,content,cached_content,feed_id,comments,int_id, + marked,unread,published,score, + ".SUBSTRING_FOR_DATE."(updated,1,16) as updated, + author,(SELECT title FROM ttrss_feeds WHERE id = feed_id) AS feed_title + FROM ttrss_entries,ttrss_user_entries + WHERE id IN ($article_id) AND ref_id = id AND owner_uid = " . + $_SESSION["uid"] ; - $articles = array(); + $result = $this->dbh->query($query); - if ($this->dbh->num_rows($result) != 0) { + $articles = array(); - while ($line = $this->dbh->fetch_assoc($result)) { - - $attachments = get_article_enclosures($line['id']); - - $article = array( - "id" => $line["id"], - "title" => $line["title"], - "link" => $line["link"], - "labels" => get_article_labels($line['id']), - "unread" => sql_bool_to_bool($line["unread"]), - "marked" => sql_bool_to_bool($line["marked"]), - "published" => sql_bool_to_bool($line["published"]), - "comments" => $line["comments"], - "author" => $line["author"], - "updated" => (int) strtotime($line["updated"]), - "content" => $line["cached_content"] != "" ? $line["cached_content"] : $line["content"], - "feed_id" => $line["feed_id"], - "attachments" => $attachments, - "score" => (int)$line["score"], - "feed_title" => $line["feed_title"] - ); + if ($this->dbh->num_rows($result) != 0) { - foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_RENDER_ARTICLE_API) as $p) { - $article = $p->hook_render_article_api(array("article" => $article)); - } + while ($line = $this->dbh->fetch_assoc($result)) { + $attachments = get_article_enclosures($line['id']); - array_push($articles, $article); + $article = array( + "id" => $line["id"], + "title" => $line["title"], + "link" => $line["link"], + "labels" => get_article_labels($line['id']), + "unread" => sql_bool_to_bool($line["unread"]), + "marked" => sql_bool_to_bool($line["marked"]), + "published" => sql_bool_to_bool($line["published"]), + "comments" => $line["comments"], + "author" => $line["author"], + "updated" => (int) strtotime($line["updated"]), + "content" => $line["cached_content"] != "" ? $line["cached_content"] : $line["content"], + "feed_id" => $line["feed_id"], + "attachments" => $attachments, + "score" => (int)$line["score"], + "feed_title" => $line["feed_title"] + ); + + foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_RENDER_ARTICLE_API) as $p) { + $article = $p->hook_render_article_api(array("article" => $article)); + } - } - } - print $this->wrap(self::STATUS_OK, $articles); + array_push($articles, $article); + } + } + + $this->wrap(self::STATUS_OK, $articles); + } else { + $this->wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE')); + } } function getConfig() { @@ -370,7 +375,7 @@ class API extends Handler { $config["num_feeds"] = (int)$num_feeds; - print $this->wrap(self::STATUS_OK, $config); + $this->wrap(self::STATUS_OK, $config); } function updateFeed() { @@ -380,7 +385,7 @@ class API extends Handler { update_rss_feed($feed_id, true); - print $this->wrap(self::STATUS_OK, array("status" => "OK")); + $this->wrap(self::STATUS_OK, array("status" => "OK")); } function catchupFeed() { @@ -389,13 +394,13 @@ class API extends Handler { catchup_feed($feed_id, $is_cat); - print $this->wrap(self::STATUS_OK, array("status" => "OK")); + $this->wrap(self::STATUS_OK, array("status" => "OK")); } function getPref() { $pref_name = $this->dbh->escape_string($_REQUEST["pref_name"]); - print $this->wrap(self::STATUS_OK, array("value" => get_pref($pref_name))); + $this->wrap(self::STATUS_OK, array("value" => get_pref($pref_name))); } function getLabels() { @@ -432,7 +437,7 @@ class API extends Handler { "checked" => $checked)); } - print $this->wrap(self::STATUS_OK, $rv); + $this->wrap(self::STATUS_OK, $rv); } function setArticleLabel() { @@ -460,7 +465,7 @@ class API extends Handler { } } - print $this->wrap(self::STATUS_OK, array("status" => "OK", + $this->wrap(self::STATUS_OK, array("status" => "OK", "updated" => $num_updated)); } @@ -471,10 +476,10 @@ class API extends Handler { if ($plugin && method_exists($plugin, $method)) { $reply = $plugin->$method(); - print $this->wrap($reply[0], $reply[1]); + $this->wrap($reply[0], $reply[1]); } else { - print $this->wrap(self::STATUS_ERR, array("error" => 'UNKNOWN_METHOD', "method" => $method)); + $this->wrap(self::STATUS_ERR, array("error" => 'UNKNOWN_METHOD', "method" => $method)); } } @@ -484,9 +489,9 @@ class API extends Handler { $content = $this->dbh->escape_string(strip_tags($_REQUEST["content"])); if (Article::create_published_article($title, $url, $content, "", $_SESSION["uid"])) { - print $this->wrap(self::STATUS_OK, array("status" => 'OK')); + $this->wrap(self::STATUS_OK, array("status" => 'OK')); } else { - print $this->wrap(self::STATUS_ERR, array("error" => 'Publishing failed')); + $this->wrap(self::STATUS_ERR, array("error" => 'Publishing failed')); } } @@ -714,9 +719,9 @@ class API extends Handler { if ($this->dbh->num_rows($result) != 0) { Pref_Feeds::remove_feed($feed_id, $_SESSION["uid"]); - print $this->wrap(self::STATUS_OK, array("status" => "OK")); + $this->wrap(self::STATUS_OK, array("status" => "OK")); } else { - print $this->wrap(self::STATUS_ERR, array("error" => "FEED_NOT_FOUND")); + $this->wrap(self::STATUS_ERR, array("error" => "FEED_NOT_FOUND")); } } @@ -727,12 +732,11 @@ class API extends Handler { $password = $this->dbh->escape_string($_REQUEST["password"]); if ($feed_url) { - $rc = subscribe_to_feed($feed_url, $category_id, - $login, $password, false); + $rc = subscribe_to_feed($feed_url, $category_id, $login, $password); - print $this->wrap(self::STATUS_OK, array("status" => $rc)); + $this->wrap(self::STATUS_OK, array("status" => $rc)); } else { - print $this->wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE')); + $this->wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE')); } } @@ -746,9 +750,9 @@ class API extends Handler { if ($pf){ $data = $pf->makefeedtree(); - print $this->wrap(self::STATUS_OK, array("categories" => $data)); + $this->wrap(self::STATUS_OK, array("categories" => $data)); } else { - print $this->wrap(self::STATUS_ERR, array("error" => + $this->wrap(self::STATUS_ERR, array("error" => 'UNABLE_TO_INSTANTIATE_OBJECT')); } diff --git a/classes/article.php b/classes/article.php index 1198eefa9..398132d12 100644 --- a/classes/article.php +++ b/classes/article.php @@ -44,7 +44,7 @@ class Article extends Handler_Protected { } else if ($mode == "raw") { if ($_REQUEST['html']) { header("Content-Type: text/html"); - print '<link rel="stylesheet" type="text/css" href="tt-rss.css"/>'; + print '<link rel="stylesheet" type="text/css" href="css/tt-rss.css"/>'; } $article = format_article($id, false); @@ -215,7 +215,7 @@ class Article extends Handler_Protected { $this->dbh->query("UPDATE ttrss_user_entries SET score = '$score' WHERE ref_id IN ($ids) AND owner_uid = " . $_SESSION["uid"]); - print json_encode(array("id" => $id, + print json_encode(array("id" => $ids, "score_pic" => get_score_pic($score))); } diff --git a/classes/auth/base.php b/classes/auth/base.php index 83f99d109..69acd0985 100644 --- a/classes/auth/base.php +++ b/classes/auth/base.php @@ -16,10 +16,12 @@ class Auth_Base { // Auto-creates specified user if allowed by system configuration // Can be used instead of find_user_by_login() by external auth modules - function auto_create_user($login) { + function auto_create_user($login, $password = false) { if ($login && defined('AUTH_AUTO_CREATE') && AUTH_AUTO_CREATE) { $user_id = $this->find_user_by_login($login); + if (!$password) $password = make_password(); + if (!$user_id) { $login = $this->dbh->escape_string($login); $salt = substr(bin2hex(get_random_bytes(125)), 0, 250); diff --git a/classes/db/pdo.php b/classes/db/pdo.php index 59499139d..126f5150a 100644 --- a/classes/db/pdo.php +++ b/classes/db/pdo.php @@ -79,7 +79,7 @@ class Db_PDO implements IDb { } function last_error() { - return join(" ", $pdo->errorInfo()); + return join(" ", $this->pdo->errorInfo()); } function init() { diff --git a/classes/db/prefs.php b/classes/db/prefs.php index 26fb4666b..3e92bb89b 100644 --- a/classes/db/prefs.php +++ b/classes/db/prefs.php @@ -105,7 +105,7 @@ class Db_Prefs { return $this->convert($value, $type_name); } else { - user_error("Fatal error, unknown preferences key: $pref_name", $die_on_error ? E_USER_ERROR : E_USER_WARNING); + user_error("Fatal error, unknown preferences key: $pref_name (owner: $user_id)", $die_on_error ? E_USER_ERROR : E_USER_WARNING); return null; } } diff --git a/classes/feedenclosure.php b/classes/feedenclosure.php new file mode 100644 index 000000000..d610dd7c8 --- /dev/null +++ b/classes/feedenclosure.php @@ -0,0 +1,7 @@ +<?php +class FeedEnclosure { + public $link; + public $type; + public $length; +} +?> diff --git a/classes/feeditem.php b/classes/feeditem.php new file mode 100644 index 000000000..e64a13fdc --- /dev/null +++ b/classes/feeditem.php @@ -0,0 +1,15 @@ +<?php +abstract class FeedItem { + abstract function get_id(); + abstract function get_date(); + abstract function get_link(); + abstract function get_title(); + abstract function get_description(); + abstract function get_content(); + abstract function get_comments_url(); + abstract function get_comments_count(); + abstract function get_categories(); + abstract function get_enclosures(); + abstract function get_author(); +} +?> diff --git a/classes/feeditem/atom.php b/classes/feeditem/atom.php new file mode 100644 index 000000000..73a586d5b --- /dev/null +++ b/classes/feeditem/atom.php @@ -0,0 +1,122 @@ +<?php +class FeedItem_Atom extends FeedItem_Common { + function get_id() { + $id = $this->elem->getElementsByTagName("id")->item(0); + + if ($id) { + return $id->nodeValue; + } else { + return $this->get_link(); + } + } + + function get_date() { + $updated = $this->elem->getElementsByTagName("updated")->item(0); + + if ($updated) { + return strtotime($updated->nodeValue); + } + } + + function get_link() { + $links = $this->elem->getElementsByTagName("link"); + + foreach ($links as $link) { + if ($link && $link->hasAttribute("href") && (!$link->hasAttribute("rel") + || $link->getAttribute("rel") == "alternate")) { + return $link->getAttribute("href"); + } + } + } + + function get_title() { + $title = $this->elem->getElementsByTagName("title")->item(0); + + if ($title) { + return $title->nodeValue; + } + } + + function get_content() { + $content = $this->elem->getElementsByTagName("content")->item(0); + + if ($content) { + if ($content->hasAttribute('type')) { + if ($content->getAttribute('type') == 'xhtml') { + return $this->doc->saveXML($content->firstChild->nextSibling); + } + } + + return $content->nodeValue; + } + } + + function get_description() { + $content = $this->elem->getElementsByTagName("summary")->item(0); + + if ($content) { + if ($content->hasAttribute('type')) { + if ($content->getAttribute('type') == 'xhtml') { + return $this->doc->saveXML($content->firstChild->nextSibling); + } + } + + return $content->nodeValue; + } + + } + + function get_categories() { + $categories = $this->elem->getElementsByTagName("category"); + $cats = array(); + + foreach ($categories as $cat) { + if ($cat->hasAttribute("term")) + array_push($cats, $cat->getAttribute("term")); + } + + $categories = $this->xpath->query("dc:subject", $this->elem); + + foreach ($categories as $cat) { + array_push($cats, $cat->nodeValue); + } + + return $cats; + } + + function get_enclosures() { + $links = $this->elem->getElementsByTagName("link"); + + $encs = array(); + + foreach ($links as $link) { + if ($link && $link->hasAttribute("href") && $link->hasAttribute("rel")) { + if ($link->getAttribute("rel") == "enclosure") { + $enc = new FeedEnclosure(); + + $enc->type = $link->getAttribute("type"); + $enc->link = $link->getAttribute("href"); + $enc->length = $link->getAttribute("length"); + + array_push($encs, $enc); + } + } + } + + $enclosures = $this->xpath->query("media:content", $this->elem); + + foreach ($enclosures as $enclosure) { + $enc = new FeedEnclosure(); + + $enc->type = $enclosure->getAttribute("type"); + $enc->link = $enclosure->getAttribute("url"); + $enc->length = $enclosure->getAttribute("length"); + + array_push($encs, $enc); + } + + return $encs; + } + +} +?> diff --git a/classes/feeditem/common.php b/classes/feeditem/common.php new file mode 100644 index 000000000..0787a42cb --- /dev/null +++ b/classes/feeditem/common.php @@ -0,0 +1,51 @@ +<?php +abstract class FeedItem_Common extends FeedItem { + protected $elem; + protected $xpath; + protected $doc; + + function __construct($elem, $doc, $xpath) { + $this->elem = $elem; + $this->xpath = $xpath; + $this->doc = $doc; + } + + function get_author() { + $author = $this->elem->getElementsByTagName("author")->item(0); + + if ($author) { + $name = $author->getElementsByTagName("name")->item(0); + + if ($name) return $name->nodeValue; + + $email = $author->getElementsByTagName("email")->item(0); + + if ($email) return $email->nodeValue; + + if ($author->nodeValue) + return $author->nodeValue; + } + + $author = $this->xpath->query("dc:creator", $this->elem)->item(0); + + if ($author) { + return $author->nodeValue; + } + } + + // todo + function get_comments_url() { + + } + + function get_comments_count() { + $comments = $this->xpath->query("slash:comments", $this->elem)->item(0); + + if ($comments) { + return $comments->nodeValue; + } + } + + +} +?> diff --git a/classes/feeditem/rss.php b/classes/feeditem/rss.php new file mode 100644 index 000000000..34dfee1f1 --- /dev/null +++ b/classes/feeditem/rss.php @@ -0,0 +1,119 @@ +<?php +class FeedItem_RSS extends FeedItem_Common { + function get_id() { + $id = $this->elem->getElementsByTagName("guid")->item(0); + + if ($id) { + return $id->nodeValue; + } else { + return $this->get_link(); + } + } + + function get_date() { + $pubDate = $this->elem->getElementsByTagName("pubDate")->item(0); + + if ($pubDate) { + return strtotime($pubDate->nodeValue); + } + } + + function get_link() { + $link = $this->xpath->query("atom:link", $this->elem)->item(0); + + if ($link) { + return $link->getAttribute("href"); + } + + $link = $this->elem->getElementsByTagName("guid")->item(0); + + if ($link && $link->hasAttributes() && $link->getAttribute("isPermaLink") == "true") { + return $link->nodeValue; + } + + $link = $this->elem->getElementsByTagName("link")->item(0); + + if ($link) { + return $link->nodeValue; + } + } + + function get_title() { + $title = $this->elem->getElementsByTagName("title")->item(0); + + if ($title) { + return $title->nodeValue; + } + } + + function get_content() { + $content = $this->xpath->query("content:encoded", $this->elem)->item(0); + + if ($content) { + return $content->nodeValue; + } + + $content = $this->elem->getElementsByTagName("description")->item(0); + + if ($content) { + return $content->nodeValue; + } + } + + function get_description() { + $summary = $this->elem->getElementsByTagName("description")->item(0); + + if ($summary) { + return $summary->nodeValue; + } + } + + function get_categories() { + $categories = $this->elem->getElementsByTagName("category"); + $cats = array(); + + foreach ($categories as $cat) { + array_push($cats, $cat->nodeValue); + } + + $categories = $this->xpath->query("dc:subject", $this->elem); + + foreach ($categories as $cat) { + array_push($cats, $cat->nodeValue); + } + + return $cats; + } + + function get_enclosures() { + $enclosures = $this->elem->getElementsByTagName("enclosure"); + + $encs = array(); + + foreach ($enclosures as $enclosure) { + $enc = new FeedEnclosure(); + + $enc->type = $enclosure->getAttribute("type"); + $enc->link = $enclosure->getAttribute("url"); + $enc->length = $enclosure->getAttribute("length"); + + array_push($encs, $enc); + } + + $enclosures = $this->xpath->query("media:content", $this->elem); + + foreach ($enclosures as $enclosure) { + $enc = new FeedEnclosure(); + + $enc->type = $enclosure->getAttribute("type"); + $enc->link = $enclosure->getAttribute("url"); + $enc->length = $enclosure->getAttribute("length"); + + array_push($encs, $enc); + } + + return $encs; + } + +} +?> diff --git a/classes/feedparser.php b/classes/feedparser.php new file mode 100644 index 000000000..d93c575b2 --- /dev/null +++ b/classes/feedparser.php @@ -0,0 +1,214 @@ +<?php +class FeedParser { + private $doc; + private $error; + private $items; + private $link; + private $title; + private $type; + private $xpath; + + const FEED_RDF = 0; + const FEED_RSS = 1; + const FEED_ATOM = 2; + + function __construct($data) { + libxml_use_internal_errors(true); + libxml_clear_errors(); + $this->doc = new DOMDocument(); + $this->doc->loadXML($data); + + $error = libxml_get_last_error(); + + if ($error && $error->code == 9) { + libxml_clear_errors(); + + // we might want to try guessing input encoding here too + $data = iconv("UTF-8", "UTF-8//IGNORE", $data); + + $this->doc = new DOMDocument(); + $this->doc->loadXML($data); + + $error = libxml_get_last_error(); + } + + $this->error = $this->format_error($error); + libxml_clear_errors(); + + $this->items = array(); + } + + function init() { + $root = $this->doc->firstChild; + $xpath = new DOMXPath($this->doc); + $xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom'); + $xpath->registerNamespace('atom03', 'http://purl.org/atom/ns#'); + $xpath->registerNamespace('media', 'http://search.yahoo.com/mrss/'); + $xpath->registerNamespace('rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'); + $xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/'); + $xpath->registerNamespace('dc', 'http://purl.org/dc/elements/1.1/'); + $xpath->registerNamespace('content', 'http://purl.org/rss/1.0/modules/content/'); + + $this->xpath = $xpath; + + $root = $xpath->query("(//atom03:feed|//atom:feed|//channel|//rdf:rdf|//rdf:RDF)")->item(0); + + if ($root) { + switch (mb_strtolower($root->tagName)) { + case "rdf:rdf": + $this->type = $this::FEED_RDF; + break; + case "channel": + $this->type = $this::FEED_RSS; + break; + case "feed": + $this->type = $this::FEED_ATOM; + break; + default: + if( !isset($this->error) ){ + $this->error = "Unknown/unsupported feed type"; + } + return; + } + + switch ($this->type) { + case $this::FEED_ATOM: + + $title = $xpath->query("//atom:feed/atom:title")->item(0); + + if (!$title) + $title = $xpath->query("//atom03:feed/atom03:title")->item(0); + + + if ($title) { + $this->title = $title->nodeValue; + } + + $link = $xpath->query("//atom:feed/atom:link[not(@rel)]")->item(0); + + if (!$link) + $link = $xpath->query("//atom03:feed/atom03:link[not(@rel)]")->item(0); + + + if ($link && $link->hasAttributes()) { + $this->link = $link->getAttribute("href"); + } + + $articles = $xpath->query("//atom:entry"); + + if (!$articles || $articles->length == 0) + $articles = $xpath->query("//atom03:entry"); + + foreach ($articles as $article) { + array_push($this->items, new FeedItem_Atom($article, $this->doc, $this->xpath)); + } + + break; + case $this::FEED_RSS: + $title = $xpath->query("//channel/title")->item(0); + + if ($title) { + $this->title = $title->nodeValue; + } + + $link = $xpath->query("//channel/link")->item(0); + + if ($link) { + if ($link->getAttribute("href")) + $this->link = $link->getAttribute("href"); + else if ($link->nodeValue) + $this->link = $link->nodeValue; + } + + $articles = $xpath->query("//channel/item"); + + foreach ($articles as $article) { + array_push($this->items, new FeedItem_RSS($article, $this->doc, $this->xpath)); + } + + break; + case $this::FEED_RDF: + $xpath->registerNamespace('rssfake', 'http://purl.org/rss/1.0/'); + + $title = $xpath->query("//rssfake:channel/rssfake:title")->item(0); + + if ($title) { + $this->title = $title->nodeValue; + } + + $link = $xpath->query("//rssfake:channel/rssfake:link")->item(0); + + if ($link) { + $this->link = $link->nodeValue; + } + + $articles = $xpath->query("//rssfake:item"); + + foreach ($articles as $article) { + array_push($this->items, new FeedItem_RSS($article, $this->doc, $this->xpath)); + } + + break; + + } + } else { + if( !isset($this->error) ){ + $this->error = "Unknown/unsupported feed type"; + } + return; + } + } + + function format_error($error) { + if ($error) { + return sprintf("LibXML error %s at line %d (column %d): %s", + $error->code, $error->line, $error->column, + $error->message); + } else { + return ""; + } + } + + function error() { + return $this->error; + } + + function get_link() { + return $this->link; + } + + function get_title() { + return $this->title; + } + + function get_items() { + return $this->items; + } + + function get_links($rel) { + $rv = array(); + + switch ($this->type) { + case $this::FEED_ATOM: + $links = $this->xpath->query("//atom:feed/atom:link"); + + foreach ($links as $link) { + if (!$rel || $link->hasAttribute('rel') && $link->getAttribute('rel') == $rel) { + array_push($rv, $link->getAttribute('href')); + } + } + break; + case $this::FEED_RSS: + $links = $this->xpath->query("//atom:link"); + + foreach ($links as $link) { + if (!$rel || $link->hasAttribute('rel') && $link->getAttribute('rel') == $rel) { + array_push($rv, $link->getAttribute('href')); + } + } + break; + } + + return $rv; + } +} ?> diff --git a/classes/feeds.php b/classes/feeds.php index f21bb3ce5..12af76df0 100644 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -288,8 +288,6 @@ class Feeds extends Handler_Protected { $expand_cdm = get_pref('CDM_EXPANDED'); while ($line = $this->dbh->fetch_assoc($result)) { - $class = ($lnum % 2) ? "even" : "odd"; - $id = $line["id"]; $feed_id = $line["feed_id"]; $label_cache = $line["label_cache"]; @@ -316,6 +314,8 @@ class Feeds extends Handler_Protected { array_push($topmost_article_ids, $id); } + $class = ""; + if (sql_bool_to_bool($line["unread"])) { $class .= " Unread"; ++$num_unread; @@ -409,23 +409,6 @@ class Feeds extends Handler_Protected { if (!isset($rgba_cache[$feed_id])) { $rgba_cache[$feed_id] = join(",", _color_unpack($fav_color)); } - - $rgba = $rgba_cache[$feed_id]; - - if (sql_bool_to_bool($line["unread"])) - $endalpha = '0.3'; - else - $endalpha = '0.1'; - - // W3C definition seems to work in FF and Chrome - $row_background = "background-image : linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba($rgba, $endalpha) 100%);"; - - /* $row_background = "background-image : -moz-linear-gradient(left, rgba(255, 255, 255, 0) 50%, rgba($rgba, 0.2) 100%);". - "background-image : linear-gradient(to right, rgba(255, 255, 255, 0) 50%, rgba($rgba, 0.2) 100%);"; - "background-image : -webkit-gradient(linear, left top, right top, color-stop(50%, rgba(255,255,255,0)), - color-stop(100%, rgba($rgba, 0.2)));"; */ - } else { - $row_background = ""; } if (!get_pref('COMBINED_DISPLAY_MODE')) { @@ -451,7 +434,7 @@ class Feeds extends Handler_Protected { $mouseover_attrs = "onmouseover='postMouseIn(event, $id)' onmouseout='postMouseOut($id)'"; - $reply['content'] .= "<div class='hl $class' id='RROW-$id' $mouseover_attrs style='$row_background'>"; + $reply['content'] .= "<div class='hl $class' id='RROW-$id' $mouseover_attrs>"; $reply['content'] .= "<div class='hlLeft'>"; @@ -487,14 +470,14 @@ class Feeds extends Handler_Protected { if (!get_pref('VFEED_GROUP_BY_FEED')) { if (@$line["feed_title"]) { - $reply['content'] .= "<div class=\"hlFeed\"> - <a href=\"#\" onclick=\"viewfeed($feed_id)\">". - truncate_string($line["feed_title"],30)."</a> - </div>"; + $rgba = @$rgba_cache[$feed_id]; + + $reply['content'] .= "<a class=\"hlFeed\" style=\"background : rgba($rgba, 0.3)\" href=\"#\" onclick=\"viewfeed($feed_id)\">". + truncate_string($line["feed_title"],30)."</a>"; } } - $reply['content'] .= "<span title='$date_entered_fmt'>$updated_fmt</span> + $reply['content'] .= "<div title='$date_entered_fmt'>$updated_fmt</div> </span>"; $reply['content'] .= "<div class=\"hlRight\">"; @@ -514,8 +497,10 @@ class Feeds extends Handler_Protected { } else { - $line["tags"] = get_article_tags($id, $_SESSION["uid"], $line["tag_cache"]); - unset($line["tag_cache"]); + if ($line["tag_cache"]) + $tags = explode(",", $line["tag_cache"]); + else + $tags = false; $line["content"] = sanitize($line["content_preview"], sql_bool_to_bool($line['hide_images']), false, $entry_site_url); @@ -576,7 +561,7 @@ class Feeds extends Handler_Protected { target=\"_blank\" href=\"". htmlspecialchars($line["link"])."\">". $line["title"] . - " <span class=\"author\">$entry_author</span></a>"; + "</a> <span class=\"author\">$entry_author</span>"; $reply['content'] .= $labels_str; @@ -595,8 +580,11 @@ class Feeds extends Handler_Protected { if (!get_pref('VFEED_GROUP_BY_FEED')) { if (@$line["feed_title"]) { + $rgba = @$rgba_cache[$feed_id]; + $reply['content'] .= "<div class=\"hlFeed\"> - <a href=\"#\" onclick=\"viewfeed($feed_id)\">". + <a href=\"#\" style=\"background-color: rgba($rgba,0.3)\" + onclick=\"viewfeed($feed_id)\">". truncate_string($line["feed_title"],30)."</a> </div>"; } @@ -627,7 +615,6 @@ class Feeds extends Handler_Protected { } $reply['content'] .= "</div>"; - $reply['content'] .= "<div class=\"cdmContentInner\">"; if ($line["orig_feed_id"]) { @@ -682,7 +669,7 @@ class Feeds extends Handler_Protected { $reply['content'] .= $p->hook_article_left_button($line); } - $tags_str = format_tags_string($line["tags"], $id); + $tags_str = format_tags_string($tags, $id); $reply['content'] .= "<img src='images/tag.png' alt='Tags' title='Tags'> <span id=\"ATSTR-$id\">$tags_str</span> @@ -719,7 +706,7 @@ class Feeds extends Handler_Protected { $reply['content'] .= "</div>"; $reply['content'] .= "</div>"; - $reply['content'] .= "</div>"; + $reply['content'] .= "</div><hr/>"; $reply['content'] .= "</div>"; diff --git a/classes/handler/public.php b/classes/handler/public.php index d5933a18c..3e868d56e 100644 --- a/classes/handler/public.php +++ b/classes/handler/public.php @@ -382,9 +382,9 @@ class Handler_Public extends Handler { header('Content-Type: text/html; charset=utf-8'); print "<html><head><title>Tiny Tiny RSS</title>"; - print stylesheet_tag("utility.css"); - print javascript_tag("lib/prototype.js"); - print javascript_tag("lib/scriptaculous/scriptaculous.js?load=effects,dragdrop,controls"); + stylesheet_tag("css/utility.css"); + javascript_tag("lib/prototype.js"); + javascript_tag("lib/scriptaculous/scriptaculous.js?load=effects,dragdrop,controls"); print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/> </head><body id='sharepopup'>"; @@ -553,7 +553,7 @@ class Handler_Public extends Handler { print "<html> <head> <title>Tiny Tiny RSS</title> - <link rel=\"stylesheet\" type=\"text/css\" href=\"utility.css\"> + <link rel=\"stylesheet\" type=\"text/css\" href=\"css/utility.css\"> <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/> </head> <body> @@ -643,6 +643,7 @@ class Handler_Public extends Handler { $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 */ @@ -666,8 +667,10 @@ class Handler_Public extends Handler { break; case 4: print_notice(__("Multiple feed URLs found.")); - - $feed_urls = get_feeds_from_html($feed_url); + $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)); @@ -732,8 +735,8 @@ class Handler_Public extends Handler { header('Content-Type: text/html; charset=utf-8'); print "<html><head><title>Tiny Tiny RSS</title>"; - print stylesheet_tag("utility.css"); - print javascript_tag("lib/prototype.js"); + stylesheet_tag("css/utility.css"); + javascript_tag("lib/prototype.js"); print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/> </head><body id='forgotpass'>"; @@ -832,7 +835,7 @@ class Handler_Public extends Handler { <head> <title>Database Updater</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> - <link rel="stylesheet" type="text/css" href="utility.css"/> + <link rel="stylesheet" type="text/css" href="css/utility.css"/> </head> <style type="text/css"> span.ok { color : #009000; font-weight : bold; } diff --git a/classes/opml.php b/classes/opml.php index 3f4030dea..b37b72c21 100644 --- a/classes/opml.php +++ b/classes/opml.php @@ -24,7 +24,7 @@ class Opml extends Handler_Protected { print "<html> <head> - <link rel=\"stylesheet\" href=\"utility.css\" type=\"text/css\"> + <link rel=\"stylesheet\" href=\"css/utility.css\" type=\"text/css\"> <title>".__("OPML Utility")."</title> <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/> </head> diff --git a/classes/pluginhost.php b/classes/pluginhost.php index 8e2aefcf1..9ac1789f5 100644 --- a/classes/pluginhost.php +++ b/classes/pluginhost.php @@ -36,6 +36,7 @@ class PluginHost { const HOOK_ARTICLE_LEFT_BUTTON = 19; const HOOK_PREFS_EDIT_FEED = 20; const HOOK_PREFS_SAVE_FEED = 21; + const HOOK_FETCH_FEED = 22; const KIND_ALL = 1; const KIND_SYSTEM = 2; @@ -186,7 +187,7 @@ class PluginHost { } } - function del_handler($handler, $method) { + function del_handler($handler, $method, $sender) { $handler = str_replace("-", "_", strtolower($handler)); $method = strtolower($method); @@ -252,8 +253,6 @@ class PluginHost { function load_data($force = false) { if ($this->owner_uid) { - $plugin = $this->dbh->escape_string($plugin); - $result = $this->dbh->query("SELECT name, content FROM ttrss_plugin_storage WHERE owner_uid = '".$this->owner_uid."'"); diff --git a/classes/pref/feeds.php b/classes/pref/feeds.php index e31725111..d43740310 100644 --- a/classes/pref/feeds.php +++ b/classes/pref/feeds.php @@ -36,8 +36,7 @@ class Pref_Feeds extends Handler_Protected { // first one is set by API $show_empty_cats = $_REQUEST['force_show_empty'] || - ($_REQUEST['mode'] != 2 && !$search && - get_pref('_PREFS_SHOW_EMPTY_CATS')); + ($_REQUEST['mode'] != 2 && !$search); $items = array(); @@ -55,6 +54,7 @@ class Pref_Feeds extends Handler_Protected { $cat['type'] = 'category'; $cat['unread'] = 0; $cat['child_unread'] = 0; + $cat['auxcounter'] = 0; $cat['items'] = $this->get_category_items($line['id']); @@ -75,6 +75,7 @@ class Pref_Feeds extends Handler_Protected { $feed = array(); $feed['id'] = 'FEED:' . $feed_line['id']; $feed['bare_id'] = (int)$feed_line['id']; + $feed['auxcounter'] = 0; $feed['name'] = $feed_line['title']; $feed['checkbox'] = false; $feed['unread'] = 0; @@ -133,6 +134,7 @@ class Pref_Feeds extends Handler_Protected { $item = array(); $item['id'] = 'FEED:' . $feed_id; $item['bare_id'] = (int)$feed_id; + $item['auxcounter'] = 0; $item['name'] = $feed['title']; $item['checkbox'] = false; $item['error'] = ''; @@ -185,8 +187,7 @@ class Pref_Feeds extends Handler_Protected { if ($enable_cats) { $show_empty_cats = $_REQUEST['force_show_empty'] || - ($_REQUEST['mode'] != 2 && !$search && - get_pref('_PREFS_SHOW_EMPTY_CATS')); + ($_REQUEST['mode'] != 2 && !$search); $result = $this->dbh->query("SELECT id, title FROM ttrss_feed_categories WHERE owner_uid = " . $_SESSION["uid"] . " AND parent_cat IS NULL ORDER BY order_id, title"); @@ -195,6 +196,7 @@ class Pref_Feeds extends Handler_Protected { $cat = array(); $cat['id'] = 'CAT:' . $line['id']; $cat['bare_id'] = (int)$line['id']; + $cat['auxcounter'] = 0; $cat['name'] = $line['title']; $cat['items'] = array(); $cat['checkbox'] = false; @@ -217,6 +219,7 @@ class Pref_Feeds extends Handler_Protected { $cat = array(); $cat['id'] = 'CAT:0'; $cat['bare_id'] = 0; + $cat['auxcounter'] = 0; $cat['name'] = __("Uncategorized"); $cat['items'] = array(); $cat['type'] = 'category'; @@ -234,6 +237,7 @@ class Pref_Feeds extends Handler_Protected { $feed = array(); $feed['id'] = 'FEED:' . $feed_line['id']; $feed['bare_id'] = (int)$feed_line['id']; + $feed['auxcounter'] = 0; $feed['name'] = $feed_line['title']; $feed['checkbox'] = false; $feed['error'] = $feed_line['last_error']; @@ -265,6 +269,7 @@ class Pref_Feeds extends Handler_Protected { $feed = array(); $feed['id'] = 'FEED:' . $feed_line['id']; $feed['bare_id'] = (int)$feed_line['id']; + $feed['auxcounter'] = 0; $feed['name'] = $feed_line['title']; $feed['checkbox'] = false; $feed['error'] = $feed_line['last_error']; @@ -305,11 +310,6 @@ class Pref_Feeds extends Handler_Protected { return; } - function togglehiddenfeedcats() { - set_pref('_PREFS_SHOW_EMPTY_CATS', - (get_pref('_PREFS_SHOW_EMPTY_CATS') ? 'false' : 'true')); - } - private function process_category_order(&$data_map, $item_id, $parent_id = false, $nest_level = 0) { $debug = isset($_REQUEST["debug"]); @@ -794,7 +794,7 @@ class Pref_Feeds extends Handler_Protected { print "<input dojoType=\"dijit.form.ValidationTextBox\" disabled=\"1\" style=\"font-size : 16px; width : 20em;\" required=\"1\" - name=\"title\" value=\"$title\">"; + name=\"title\" value=\"\">"; $this->batch_edit_cbox("title"); @@ -805,7 +805,7 @@ class Pref_Feeds extends Handler_Protected { print __('URL:') . " "; print "<input dojoType=\"dijit.form.ValidationTextBox\" disabled=\"1\" required=\"1\" regExp='^(http|https)://.*' style=\"width : 20em\" - name=\"feed_url\" value=\"$feed_url\">"; + name=\"feed_url\" value=\"\">"; $this->batch_edit_cbox("feed_url"); @@ -817,7 +817,7 @@ class Pref_Feeds extends Handler_Protected { print __('Place in category:') . " "; - print_feed_cat_select("cat_id", $cat_id, + print_feed_cat_select("cat_id", false, 'disabled="1" dojoType="dijit.form.Select"'); $this->batch_edit_cbox("cat_id"); @@ -831,7 +831,7 @@ class Pref_Feeds extends Handler_Protected { /* Update Interval */ - print_select_hash("update_interval", $update_interval, $update_intervals, + print_select_hash("update_interval", "", $update_intervals, 'disabled="1" dojoType="dijit.form.Select"'); $this->batch_edit_cbox("update_interval"); @@ -844,7 +844,7 @@ class Pref_Feeds extends Handler_Protected { print __('Article purging:') . " "; - print_select_hash("purge_interval", $purge_interval, $purge_intervals, + print_select_hash("purge_interval", "", $purge_intervals, 'disabled="1" dojoType="dijit.form.Select"'); $this->batch_edit_cbox("purge_interval"); @@ -856,13 +856,13 @@ class Pref_Feeds extends Handler_Protected { print "<input dojoType=\"dijit.form.TextBox\" placeHolder=\"".__("Login")."\" disabled=\"1\" - name=\"auth_login\" value=\"$auth_login\">"; + name=\"auth_login\" value=\"\">"; $this->batch_edit_cbox("auth_login"); print "<br/><input dojoType=\"dijit.form.TextBox\" type=\"password\" name=\"auth_pass\" placeHolder=\"".__("Password")."\" disabled=\"1\" - value=\"$auth_pass\">"; + value=\"\">"; $this->batch_edit_cbox("auth_pass"); @@ -1351,9 +1351,6 @@ class Pref_Feeds extends Handler_Protected { print $error_button; print $inactive_button; - print "<button onclick=\"toggleHiddenFeedCats()\" - dojoType=\"dijit.form.Button\">".__('(Un)hide empty categories')."</button>"; - if (defined('_ENABLE_FEED_DEBUGGING')) { print "<select id=\"feedActionChooser\" onchange=\"feedActionChange()\"> @@ -1418,9 +1415,7 @@ class Pref_Feeds extends Handler_Protected { print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('OPML')."\">"; - print "<p>" . __("Using OPML you can export and import your feeds, filters, labels and Tiny Tiny RSS settings.") . " "; - - print __("Only main settings profile can be migrated using OPML.") . "</p>"; + print_notice(__("Using OPML you can export and import your feeds, filters, labels and Tiny Tiny RSS settings.") . __("Only main settings profile can be migrated using OPML.")); print "<iframe id=\"upload_iframe\" name=\"upload_iframe\" onload=\"opmlImportComplete(this)\" @@ -1463,7 +1458,7 @@ class Pref_Feeds extends Handler_Protected { print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Firefox integration')."\">"; - print "<p>" . __('This Tiny Tiny RSS site can be used as a Firefox Feed Reader by clicking the link below.') . "</p>"; + print_notice(__('This Tiny Tiny RSS site can be used as a Firefox Feed Reader by clicking the link below.')); print "<p>"; @@ -1480,26 +1475,30 @@ class Pref_Feeds extends Handler_Protected { print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Published & shared articles / Generated feeds')."\">"; - print "<h3>" . __("Published articles and generated feeds") . "</h3>"; - - print "<p>".__('Published articles are exported as a public RSS feed and can be subscribed by anyone who knows the URL specified below.')."</p>"; + print_notice(__('Published articles are exported as a public RSS feed and can be subscribed by anyone who knows the URL specified below.')); $rss_url = '-2::' . htmlspecialchars(get_self_url_prefix() . "/public.php?op=rss&id=-2&view-mode=all_articles");; + print "<p>"; + print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('".__("View as RSS")."','generatedFeed', '$rss_url')\">". __('Display URL')."</button> "; print "<button dojoType=\"dijit.form.Button\" onclick=\"return clearFeedAccessKeys()\">". __('Clear all generated URLs')."</button> "; - print "<h3>" . __("Articles shared by URL") . "</h3>"; + print "</p>"; - print "<p>" . __("You can disable all articles shared by unique URLs here.") . "</p>"; + print_warning(__("You can disable all articles shared by unique URLs here.")); + + print "<p>"; print "<button dojoType=\"dijit.form.Button\" onclick=\"return clearArticleAccessKeys()\">". __('Unshare all articles')."</button> "; + print "</p>"; + PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION, "hook_prefs_tab_section", "prefFeedsPublishedGenerated"); @@ -1549,6 +1548,7 @@ class Pref_Feeds extends Handler_Protected { $obj['updated'] = $updated; $obj['icon'] = getFeedIcon($feed_id); $obj['bare_id'] = $feed_id; + $obj['auxcounter'] = 0; return $obj; } @@ -1573,7 +1573,7 @@ class Pref_Feeds extends Handler_Protected { GROUP BY ttrss_feeds.title, ttrss_feeds.id, ttrss_feeds.site_url, ttrss_feeds.feed_url ORDER BY last_article"); - print "<h2" .__("These feeds have not been updated with new content for 3 months (oldest first):") . "</h2>"; + print "<p" .__("These feeds have not been updated with new content for 3 months (oldest first):") . "</p>"; print "<div dojoType=\"dijit.Toolbar\">"; print "<div dojoType=\"dijit.form.DropDownButton\">". @@ -1594,7 +1594,6 @@ class Pref_Feeds extends Handler_Protected { while ($line = $this->dbh->fetch_assoc($result)) { - $class = ($lnum % 2) ? "even" : "odd"; $feed_id = $line["id"]; $this_row_id = "id=\"FUPDD-$feed_id\""; @@ -1639,9 +1638,6 @@ class Pref_Feeds extends Handler_Protected { } function feedsWithErrors() { - print "<h2>" . __("These feeds have not been updated because of errors:") . - "</h2>"; - $result = $this->dbh->query("SELECT id,title,feed_url,last_error,site_url FROM ttrss_feeds WHERE last_error != '' AND owner_uid = ".$_SESSION["uid"]); @@ -1664,7 +1660,6 @@ class Pref_Feeds extends Handler_Protected { while ($line = $this->dbh->fetch_assoc($result)) { - $class = ($lnum % 2) ? "even" : "odd"; $feed_id = $line["id"]; $this_row_id = "id=\"FERDD-$feed_id\""; diff --git a/classes/pref/filters.php b/classes/pref/filters.php index 4dbee5906..bcc7b5aec 100644 --- a/classes/pref/filters.php +++ b/classes/pref/filters.php @@ -83,8 +83,6 @@ class Pref_Filters extends Handler_Protected { } } - $feed_title = getFeedTitle($feed); - $qfh_ret = queryFeedHeadlines(-4, 30, "", false, false, false, "date_entered DESC", 0, $_SESSION["uid"], $filter); diff --git a/classes/pref/prefs.php b/classes/pref/prefs.php index 45715488a..32071e3b3 100644 --- a/classes/pref/prefs.php +++ b/classes/pref/prefs.php @@ -40,7 +40,7 @@ class Pref_Prefs extends Handler_Protected { "FRESH_ARTICLE_MAX_AGE" => array(__("Maximum age of fresh articles (in hours)"), ""), "HIDE_READ_FEEDS" => array(__("Hide feeds with no unread articles"), ""), "HIDE_READ_SHOWS_SPECIAL" => array(__("Show special feeds when hiding read feeds"), ""), - "LONG_DATE_FORMAT" => array(__("Long date format"), ""), + "LONG_DATE_FORMAT" => array(__("Long date format"), __("The syntax used is identical to the PHP <a href='http://php.net/manual/function.date.php'>date()</a> function.")), "ON_CATCHUP_SHOW_NEXT_FEED" => array(__("On catchup show next feed"), __("Automatically open next feed with unread articles after marking one as read")), "PURGE_OLD_DAYS" => array(__("Purge articles after this number of days (0 - disables)"), ""), "PURGE_UNREAD_ARTICLES" => array(__("Purge unread articles"), ""), @@ -366,7 +366,7 @@ class Pref_Prefs extends Handler_Protected { } else if (function_exists("imagecreatefromstring")) { - print "<p>".__("You will need a compatible Authenticator to use this. Changing your password would automatically disable OTP.") . "</p>"; + print_warning(__("You will need a compatible Authenticator to use this. Changing your password would automatically disable OTP.")); print "<p>".__("Scan the following code by the Authenticator application:")."</p>"; @@ -705,8 +705,6 @@ class Pref_Prefs extends Handler_Protected { print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Plugins')."\">"; - print "<h2>".__("Plugins")."</h2>"; - print "<p>" . __("You will need to reload Tiny Tiny RSS for plugin changes to take effect.") . "</p>"; print_notice(__("Download more plugins at tt-rss.org <a class=\"visibleLink\" target=\"_blank\" href=\"http://tt-rss.org/forum/viewforum.php?f=22\">forums</a> or <a target=\"_blank\" class=\"visibleLink\" href=\"http://tt-rss.org/wiki/Plugins\">wiki</a>.")); @@ -747,7 +745,7 @@ class Pref_Prefs extends Handler_Protected { $system_enabled = array_map("trim", explode(",", PLUGINS)); $user_enabled = array_map("trim", explode(",", get_pref("_ENABLED_PLUGINS"))); - $tmppluginhost = new PluginHost(Db::get()); + $tmppluginhost = new PluginHost(); $tmppluginhost->load_all($tmppluginhost::KIND_ALL, $_SESSION["uid"]); $tmppluginhost->load_data(true); @@ -964,7 +962,7 @@ class Pref_Prefs extends Handler_Protected { $value = str_replace("<br/>", "\n", $value); - print_notice(T_sprintf("You can override colors, fonts and layout of your currently selected theme with custom CSS declarations here. <a target=\"_blank\" class=\"visibleLink\" href=\"%s\">This file</a> can be used as a baseline.", "tt-rss.css")); + print_notice(T_sprintf("You can override colors, fonts and layout of your currently selected theme with custom CSS declarations here. <a target=\"_blank\" class=\"visibleLink\" href=\"%s\">This file</a> can be used as a baseline.", "css/tt-rss.css")); 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=\"setpref\">"; @@ -1041,8 +1039,6 @@ class Pref_Prefs extends Handler_Protected { while ($line = $this->dbh->fetch_assoc($result)) { - $class = ($lnum % 2) ? "even" : "odd"; - $profile_id = $line["id"]; $this_row_id = "id=\"FCATR-$profile_id\""; diff --git a/classes/pref/users.php b/classes/pref/users.php index 4b7d2d69a..914491e4a 100644 --- a/classes/pref/users.php +++ b/classes/pref/users.php @@ -69,8 +69,6 @@ class Pref_Users extends Handler_Protected { print "<ul class=\"userFeedList\">"; - $row_class = "odd"; - while ($line = $this->dbh->fetch_assoc($result)) { $icon_file = ICONS_URL."/".$line["id"].".ico"; @@ -81,9 +79,7 @@ class Pref_Users extends Handler_Protected { $feed_icon = "<img class=\"tinyFeedIcon\" src=\"images/blank_icon.gif\">"; } - print "<li class=\"$row_class\">$feed_icon <a href=\"".$line["site_url"]."\">".$line["title"]."</a></li>"; - - $row_class = $row_class == "even" ? "odd" : "even"; + print "<li>$feed_icon <a href=\"".$line["site_url"]."\">".$line["title"]."</a></li>"; } @@ -252,9 +248,9 @@ class Pref_Users extends Handler_Protected { } } - static function resetUserPassword($link, $uid, $show_password) { + static function resetUserPassword($uid, $show_password) { - $result = db_query($link, "SELECT login,email + $result = db_query("SELECT login,email FROM ttrss_users WHERE id = '$uid'"); $login = db_fetch_result($result, 0, "login"); @@ -266,7 +262,7 @@ class Pref_Users extends Handler_Protected { $pwd_hash = encrypt_password($tmp_user_pwd, $new_salt, true); - db_query($link, "UPDATE ttrss_users SET pwd_hash = '$pwd_hash', salt = '$new_salt' + db_query("UPDATE ttrss_users SET pwd_hash = '$pwd_hash', salt = '$new_salt' WHERE id = '$uid'"); if ($show_password) { @@ -359,6 +355,9 @@ class Pref_Users extends Handler_Protected { <button dojoType=\"dijit.form.Button\" onclick=\"javascript:resetSelectedUserPass()\">". __('Reset password')."</button dojoType=\"dijit.form.Button\">"; + PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION, + "hook_prefs_tab_section", "prefUsersToolbar"); + print "</div>"; #toolbar print "</div>"; #pane print "<div id=\"pref-user-content\" dojoType=\"dijit.layout.ContentPane\" region=\"center\">"; @@ -408,8 +407,6 @@ class Pref_Users extends Handler_Protected { while ($line = $this->dbh->fetch_assoc($result)) { - $class = ($lnum % 2) ? "even" : "odd"; - $uid = $line["id"]; print "<tr id=\"UMRR-$uid\">"; diff --git a/classes/rpc.php b/classes/rpc.php index 2b07bbf91..46583feb5 100644 --- a/classes/rpc.php +++ b/classes/rpc.php @@ -291,7 +291,7 @@ class RPC extends Handler_Protected { $reply = array(); - if ($seq) $reply['seq'] = $seq; + if (!empty($_REQUEST['seq'])) $reply['seq'] = (int) $_REQUEST['seq']; if ($last_article_id != getLastArticleId()) { $reply['counters'] = getAllCounters(); @@ -464,7 +464,7 @@ class RPC extends Handler_Protected { $id = 0; } - print_feed_cat_select("cat_id", $id); + print_feed_cat_select("cat_id", $id, ''); } // Silent diff --git a/classes/sanitizedummy.php b/classes/sanitizedummy.php deleted file mode 100644 index 7182fb7f5..000000000 --- a/classes/sanitizedummy.php +++ /dev/null @@ -1,7 +0,0 @@ -<?php -class SanitizeDummy extends SimplePie_Sanitize { - function sanitize($data, $type, $base = '') { - return $data; - } -} -?> diff --git a/classes/ttrssmailer.php b/classes/ttrssmailer.php index fd7f969aa..1e8d07723 100644 --- a/classes/ttrssmailer.php +++ b/classes/ttrssmailer.php @@ -28,7 +28,7 @@ class ttrssMailer extends PHPMailer { $this->Host = $pair[0];
$this->Port = $pair[1];
- if (!$Port) $Port = 25;
+ if (!$this->Port) $this->Port = 25;
} else {
$this->Host = '';
$this->Port = '';
|