<?php
define('EXPECTED_CONFIG_VERSION', 26);
- define('SCHEMA_VERSION', 103);
- define('SELF_USER_AGENT', 'Tiny Tiny RSS/' . VERSION . ' (http://tt-rss.org/)');
+ define('SCHEMA_VERSION', 106);
$fetch_last_error = false;
$pluginhost = false;
$tr = array(
"auto" => "Detect automatically",
"ca_CA" => "Català",
+ "cs_CZ" => "Česky",
"en_US" => "English",
"es_ES" => "Español",
"de_DE" => "Deutsch",
"hu_HU" => "Magyar (Hungarian)",
"it_IT" => "Italiano",
"ja_JP" => "日本語 (Japanese)",
+ "lv_LV" => "Latviešu",
"nb_NO" => "Norwegian bokmål",
"pl_PL" => "Polski",
"ru_RU" => "Русский",
$lang = _TRANSLATION_OVERRIDE_DEFAULT;
}
- /* In login action of mobile version */
- if ($_POST["language"] && defined('MOBILE_VERSION')) {
- $lang = $_POST["language"];
- } else if ($_SESSION["language"] && $_SESSION["language"] != "auto") {
+ if ($_SESSION["language"] && $_SESSION["language"] != "auto") {
$lang = $_SESSION["language"];
}
_setlocale(LC_ALL, $lang);
}
- if (defined('MOBILE_VERSION')) {
- _bindtextdomain("messages", "../locale");
- } else {
- _bindtextdomain("messages", "locale");
- }
+ _bindtextdomain("messages", "locale");
_textdomain("messages");
_bind_textdomain_codeset("messages", "UTF-8");
require_once 'ccache.php';
require_once 'labels.php';
+ define('SELF_USER_AGENT', 'Tiny Tiny RSS/' . VERSION . ' (http://tt-rss.org/)');
ini_set('user_agent', SELF_USER_AGENT);
require_once 'lib/pubsubhubbub/publisher.php';
- require_once 'lib/htmLawed.php';
$tz_offset = -1;
$utc_tz = new DateTimeZone('UTC');
* @return void
*/
function _debug($msg) {
- if (defined('QUIET') && QUIET) {
- return;
- }
$ts = strftime("%H:%M:%S", time());
if (function_exists('posix_getpid')) {
$ts = "$ts/" . posix_getpid();
}
- print "[$ts] $msg\n";
+
+ if (!(defined('QUIET') && QUIET)) {
+ print "[$ts] $msg\n";
+ }
+
+ if (defined('LOGFILE')) {
+ $fp = fopen(LOGFILE, 'a+');
+
+ if ($fp) {
+ fputs($fp, "[$ts] $msg\n");
+ fclose($fp);
+ }
+ }
+
} // function _debug
/**
if ($debug) {
_debug("Purged feed $feed_id ($purge_interval): deleted $rows articles");
}
+
+ return $rows;
} // function purge_feed
function feed_purge_interval($link, $feed_id) {
}
}
- function fetch_file_contents($url, $type = false, $login = false, $pass = false, $post_query = false) {
+ function fetch_file_contents($url, $type = false, $login = false, $pass = false, $post_query = false, $timeout = false) {
$login = urlencode($login);
$pass = urlencode($pass);
global $fetch_last_error;
if (function_exists('curl_init') && !ini_get("open_basedir")) {
- $ch = curl_init($url);
- curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
- curl_setopt($ch, CURLOPT_TIMEOUT, 45);
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
+ if (ini_get("safe_mode")) {
+ $ch = curl_init(geturl($url));
+ } else {
+ $ch = curl_init($url);
+ }
+
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout ? $timeout : 15);
+ curl_setopt($ch, CURLOPT_TIMEOUT, $timeout ? $timeout : 45);
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, !ini_get("safe_mode"));
curl_setopt($ch, CURLOPT_MAXREDIRS, 20);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_USERAGENT, SELF_USER_AGENT);
curl_setopt($ch, CURLOPT_ENCODING , "gzip");
+ curl_setopt($ch, CURLOPT_REFERER, $url);
if ($post_query) {
curl_setopt($ch, CURLOPT_POST, true);
$contents = @curl_exec($ch);
+ if (curl_errno($ch) === 23 || curl_errno($ch) === 61) {
+ curl_setopt($ch, CURLOPT_ENCODING, 'none');
+ $contents = @curl_exec($ch);
+ }
+
if ($contents === false) {
- $fetch_last_error = curl_error($ch);
+ $fetch_last_error = curl_errno($ch) . " " . curl_error($ch);
curl_close($ch);
return false;
}
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$content_type = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
- curl_close($ch);
if ($http_code != 200 || $type && strpos($content_type, "$type") === false) {
+ if (curl_errno($ch) != 0) {
+ $fetch_last_error = curl_errno($ch) . " " . curl_error($ch);
+ } else {
+ $fetch_last_error = "HTTP Code: $http_code";
+ }
+ curl_close($ch);
return false;
}
+ curl_close($ch);
+
return $contents;
} else {
if ($login && $pass ){
$data = @file_get_contents($url);
+ $gzdecoded = gzdecode($data);
+ if ($gzdecoded) $data = $gzdecoded;
+
if (!$data && function_exists('error_get_last')) {
$error = error_get_last();
$fetch_last_error = $error["message"];
else
$sel = "";
+ $v = trim($v);
+
print "<option value=\"$v\" $sel>$v</option>";
}
print "</select>";
else
$sel = "";
+ $v = trim($v);
+
print "<option $sel value=\"$v\">".$values[$v]."</option>";
}
print "</select>";
}
- function getmicrotime() {
- list($usec, $sec) = explode(" ",microtime());
- return ((float)$usec + (float)$sec);
- }
-
function print_radio($id, $default, $true_is, $values, $attributes = "") {
foreach ($values as $v) {
function initialize_user_prefs($link, $uid, $profile = false) {
- $uid = db_escape_string($uid);
+ $uid = db_escape_string($link, $uid);
if (!$profile) {
$profile = "NULL";
}
}
- function login_sequence($link, $login_form = 0) {
+ function login_sequence($link) {
$_SESSION["prefs_cache"] = false;
if (SINGLE_USER_MODE) {
authenticate_user($link, "admin", null);
+ cache_prefs($link);
load_user_plugins($link, $_SESSION["uid"]);
} else {
if (!$_SESSION["uid"] || !validate_session($link)) {
authenticate_user($link, null, null, true);
}
- if (!$_SESSION["uid"]) render_login_form($link, $login_form);
+ if (!$_SESSION["uid"]) render_login_form($link);
} else {
/* bump login timestamp */
}
if ($_SESSION["uid"]) {
+ cache_prefs($link);
load_user_plugins($link, $_SESSION["uid"]);
}
}
}
}
- // Deprecated, TODO: remove
- function theme_image($link, $filename) {
- return $filename;
- }
-
function convert_timestamp($timestamp, $source_tz, $dest_tz) {
try {
}
function sql_bool_to_bool($s) {
- if ($s == "t" || $s == "1" || $s == "true") {
+ if ($s == "t" || $s == "1" || strtolower($s) == "true") {
return true;
} else {
return false;
}
}
- if (db_escape_string("testTEST") != "testTEST") {
+ if (db_escape_string($link, "testTEST") != "testTEST") {
$error_code = 12;
}
function make_lockfile($filename) {
$fp = fopen(LOCK_DIRECTORY . "/$filename", "w");
- if (flock($fp, LOCK_EX | LOCK_NB)) {
+ if ($fp && flock($fp, LOCK_EX | LOCK_NB)) {
if (function_exists('posix_getpid')) {
fwrite($fp, posix_getpid() . "\n");
}
db_query($link, "UPDATE ttrss_user_entries
SET unread = false,last_read = NOW()
WHERE feed_id IN (SELECT id FROM ttrss_feeds WHERE $cat_qpart)
- AND $ref_check_qpart
+ AND $ref_check_qpart AND unread = true
AND owner_uid = $owner_uid");
} else if ($feed == -2) {
db_query($link, "UPDATE ttrss_user_entries
SET unread = false,last_read = NOW()
WHERE feed_id = '$feed'
- AND $ref_check_qpart
+ AND $ref_check_qpart AND unread = true
AND owner_uid = $owner_uid");
} else if ($feed < 0 && $feed > -10) { // special, like starred
db_query($link, "UPDATE ttrss_user_entries
SET unread = false,last_read = NOW()
WHERE marked = true
- AND $ref_check_qpart
+ AND $ref_check_qpart AND unread = true
AND owner_uid = $owner_uid");
}
db_query($link, "UPDATE ttrss_user_entries
SET unread = false,last_read = NOW()
WHERE published = true
- AND $ref_check_qpart
+ AND $ref_check_qpart AND unread = true
AND owner_uid = $owner_uid");
}
if ($feed == -4) {
db_query($link, "UPDATE ttrss_user_entries
SET unread = false,last_read = NOW()
- WHERE $ref_check_qpart AND owner_uid = $owner_uid");
+ WHERE $ref_check_qpart AND unread = true AND
+ owner_uid = $owner_uid");
}
} else if ($feed < -10) { // label
} else { // tag
db_query($link, "BEGIN");
- $tag_name = db_escape_string($feed);
+ $tag_name = db_escape_string($link, $feed);
$result = db_query($link, "SELECT post_int_id FROM ttrss_tags
WHERE tag_name = '$tag_name' AND owner_uid = $owner_uid");
while ($line = db_fetch_assoc($result)) {
db_query($link, "UPDATE ttrss_user_entries SET
unread = false, last_read = NOW()
- WHERE $ref_check_qpart AND int_id = " . $line["post_int_id"]);
+ WHERE $ref_check_qpart AND unread = true
+ AND int_id = " . $line["post_int_id"]);
}
db_query($link, "COMMIT");
}
return 0;
} else if ($feed != "0" && $n_feed == 0) {
- $feed = db_escape_string($feed);
+ $feed = db_escape_string($link, $feed);
$result = db_query($link, "SELECT SUM((SELECT COUNT(int_id)
FROM ttrss_user_entries,ttrss_entries WHERE int_id = post_int_id
$owner_uid = $_SESSION["uid"];
- $result = db_query($link, "SELECT id, caption FROM ttrss_labels2
- WHERE owner_uid = '$owner_uid'");
+ $result = db_query($link, "SELECT id,caption,COUNT(unread) AS unread
+ FROM ttrss_labels2 LEFT JOIN ttrss_user_labels2 ON
+ (ttrss_labels2.id = label_id)
+ LEFT JOIN ttrss_user_entries ON (ref_id = article_id AND unread = true)
+ WHERE ttrss_labels2.owner_uid = $owner_uid GROUP BY ttrss_labels2.id,
+ ttrss_labels2.caption");
while ($line = db_fetch_assoc($result)) {
$id = -$line["id"] - 11;
$label_name = $line["caption"];
- $count = getFeedUnread($link, $id);
+ $count = $line["unread"];
$cv = array("id" => $id,
"counter" => (int) $count);
function make_init_params($link) {
$params = array();
- $params["sign_progress"] = theme_image($link, "images/indicator_white.gif");
- $params["sign_progress_tiny"] = theme_image($link, "images/indicator_tiny.gif");
- $params["sign_excl"] = theme_image($link, "images/sign_excl.svg");
- $params["sign_info"] = theme_image($link, "images/sign_info.svg");
-
foreach (array("ON_CATCHUP_SHOW_NEXT_FEED", "HIDE_READ_FEEDS",
"ENABLE_FEED_CATS", "FEEDS_SORT_BY_UNREAD", "CONFIRM_FEED_CATCHUP",
"CDM_AUTO_CATCHUP", "FRESH_ARTICLE_MAX_AGE", "DEFAULT_ARTICLE_LIMIT",
"prev_feed" => __("Open previous feed"),
"next_article" => __("Open next article"),
"prev_article" => __("Open previous article"),
+ "next_article_noscroll" => __("Open next article (don't scroll long articles)"),
+ "prev_article_noscroll" => __("Open previous article (don't scroll long articles)"),
"search_dialog" => __("Show search dialog")),
__("Article") => array(
"toggle_mark" => __("Toggle starred"),
"article_scroll_up" => __("Scroll up"),
"select_article_cursor" => __("Select article under cursor"),
"email_article" => __("Email article"),
- "close_article" => __("Close article"),
- "toggle_widescreen" => __("Toggle widescreen mode")),
+ "close_article" => __("Close/collapse article"),
+ "toggle_widescreen" => __("Toggle widescreen mode"),
+ "toggle_embed_original" => __("Toggle embed original")),
__("Article selection") => array(
"select_all" => __("Select all articles"),
"select_unread" => __("Select unread"),
"feed_reverse" => __("Reverse headlines"),
"feed_debug_update" => __("Debug feed update"),
"catchup_all" => __("Mark all feeds as read"),
- "cat_toggle_collapse" => __("Un/collapse current category")),
+ "cat_toggle_collapse" => __("Un/collapse current category"),
+ "toggle_combined_mode" => __("Toggle combined mode")),
__("Go to") => array(
"goto_all" => __("All articles"),
"goto_fresh" => __("Fresh"),
"p" => "prev_article",
"(38)|up" => "prev_article",
"(40)|down" => "next_article",
+// "^(38)|Ctrl-up" => "prev_article_noscroll",
+// "^(40)|Ctrl-down" => "next_article_noscroll",
"(191)|/" => "search_dialog",
// "article" => array(
"s" => "toggle_mark",
- "S" => "toggle_publ",
+ "*s" => "toggle_publ",
"u" => "toggle_unread",
- "T" => "edit_tags",
- "D" => "dismiss_selected",
- "X" => "dismiss_read",
+ "*t" => "edit_tags",
+ "*d" => "dismiss_selected",
+ "*x" => "dismiss_read",
"o" => "open_in_new_window",
"c p" => "catchup_below",
"c n" => "catchup_above",
- "N" => "article_scroll_down",
- "P" => "article_scroll_up",
- "a W" => "toggle_widescreen",
+ "*n" => "article_scroll_down",
+ "*p" => "article_scroll_up",
+ "*(38)|Shift+up" => "article_scroll_up",
+ "*(40)|Shift+down" => "article_scroll_down",
+ "a *w" => "toggle_widescreen",
+ "a e" => "toggle_embed_original",
"e" => "email_article",
"a q" => "close_article",
// "article_selection" => array(
"a a" => "select_all",
"a u" => "select_unread",
- "a U" => "select_marked",
+ "a *u" => "select_marked",
"a p" => "select_published",
"a i" => "select_invert",
"a n" => "select_none",
"f e" => "feed_edit",
"f q" => "feed_catchup",
"f x" => "feed_reverse",
- "f D" => "feed_debug_update",
- "Q" => "catchup_all",
+ "f *d" => "feed_debug_update",
+ "f *c" => "toggle_combined_mode",
+ "*q" => "catchup_all",
"x" => "cat_toggle_collapse",
// "goto" => array(
"g a" => "goto_all",
"g s" => "goto_marked",
"g p" => "goto_published",
"g t" => "goto_tagcloud",
- "g P" => "goto_prefs",
+ "g *p" => "goto_prefs",
// "other" => array(
"(9)|Tab" => "select_article_cursor", // tab
"c l" => "create_label",
"^(191)|Ctrl+/" => "help_dialog",
);
+ if (get_pref($link, 'COMBINED_DISPLAY_MODE')) {
+ $hotkeys["^(38)|Ctrl-up"] = "prev_article_noscroll";
+ $hotkeys["^(40)|Ctrl-down"] = "next_article_noscroll";
+ }
+
global $pluginhost;
foreach ($pluginhost->get_hooks($pluginhost::HOOK_HOTKEY_MAP) as $plugin) {
$hotkeys = $plugin->hook_hotkey_map($hotkeys);
$data['last_article_id'] = getLastArticleId($link);
$data['cdm_expanded'] = get_pref($link, 'CDM_EXPANDED');
+ $data['dep_ts'] = calculate_dep_timestamp();
+
if (file_exists(LOCK_DIRECTORY . "/update_daemon.lock")) {
$data['daemon_is_running'] = (int) file_is_locked("update_daemon.lock");
return $data;
}
- function search_to_sql($link, $search, $match_on) {
+ function search_to_sql($link, $search) {
$search_query_part = "";
//$k = date("Y-m-d", strtotime(substr($k, 1)));
array_push($query_keywords, "(".SUBSTRING_FOR_DATE."(updated,1,LENGTH('$k')) $not = '$k')");
- } else if ($match_on == "both") {
+ } else {
array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER('%$k%')
OR UPPER(ttrss_entries.content) $not LIKE UPPER('%$k%'))");
- } else if ($match_on == "title") {
- array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER('%$k%'))");
- } else if ($match_on == "content") {
- array_push($query_keywords, "(UPPER(ttrss_entries.content) $not LIKE UPPER('%$k%'))");
}
}
return $rv;
}
- function queryFeedHeadlines($link, $feed, $limit, $view_mode, $cat_view, $search, $search_mode, $match_on, $override_order = false, $offset = 0, $owner_uid = 0, $filter = false, $since_id = 0, $include_children = false, $ignore_vfeed_group = false) {
+ function queryFeedHeadlines($link, $feed, $limit, $view_mode, $cat_view, $search, $search_mode, $override_order = false, $offset = 0, $owner_uid = 0, $filter = false, $since_id = 0, $include_children = false, $ignore_vfeed_group = false) {
if (!$owner_uid) $owner_uid = $_SESSION["uid"];
$search_query_part = "ref_id = -1 AND ";
} else {
- $search_query_part = search_to_sql($link, $search, $match_on);
+ $search_query_part = search_to_sql($link, $search);
$search_query_part .= " AND ";
}
$vfeed_query_part = "ttrss_feeds.title AS feed_title,";
$allow_archived = true;
+ if (!$override_order) $override_order = "last_marked DESC, updated DESC";
+
} else if ($feed == -2) { // published virtual feed OR labels category
if (!$cat_view) {
$vfeed_query_part = "ttrss_feeds.title AS feed_title,";
$allow_archived = true;
- if (!$override_order) $override_order = "last_read DESC, updated DESC";
+ if (!$override_order) $override_order = "last_published DESC, updated DESC";
} else {
$vfeed_query_part = "ttrss_feeds.title AS feed_title,";
num_comments,
comments,
int_id,
+ hide_images,
unread,feed_id,marked,published,link,last_read,orig_feed_id,
+ last_marked, last_published,
".SUBSTRING_FOR_DATE."(last_read,1,19) as last_read_noms,
$vfeed_query_part
$content_query_part
"label_cache," .
"link," .
"last_read," .
+ "(SELECT hide_images FROM ttrss_feeds WHERE id = feed_id) AS hide_images," .
+ "last_marked, last_published, " .
SUBSTRING_FOR_DATE . "(last_read,1,19) as last_read_noms," .
$since_id_part .
$vfeed_query_part .
}
- function sanitize($link, $str, $force_strip_tags = false, $owner = false, $site_url = false) {
+ function sanitize($link, $str, $force_remove_images = false, $owner = false, $site_url = false) {
if (!$owner) $owner = $_SESSION["uid"];
$res = trim($str); if (!$res) return '';
- $config = array('safe' => 1, 'deny_attribute' => 'style, width, height, class, id', 'comment' => 1, 'cdata' => 1, 'balance' => 0);
- $res = htmLawed($res, $config);
-
- if (get_pref($link, "STRIP_IMAGES", $owner)) {
- $res = preg_replace('/<img[^>]+>/is', '', $res);
- }
-
if (strpos($res, "href=") === false)
$res = rewrite_urls($res);
$xpath = new DOMXPath($doc);
$entries = $xpath->query('(//a[@href]|//img[@src])');
- $br_inserted = 0;
foreach ($entries as $entry) {
$entry->setAttribute('href',
rewrite_relative_url($site_url, $entry->getAttribute('href')));
- if ($entry->hasAttribute('src'))
- if (preg_match('/^image.php\?i=[a-z0-9]+$/', $entry->getAttribute('src')) == 0)
- $entry->setAttribute('src',
- rewrite_relative_url($site_url, $entry->getAttribute('src')));
+ if ($entry->hasAttribute('src')) {
+ $src = rewrite_relative_url($site_url, $entry->getAttribute('src'));
+
+ $cached_filename = CACHE_DIR . '/images/' . sha1($src) . '.png';
+
+ if (file_exists($cached_filename)) {
+ $src = SELF_URL_PATH . '/image.php?hash=' . sha1($src);
+ }
+
+ $entry->setAttribute('src', $src);
+ }
+
+ if ($entry->nodeName == 'img') {
+ if (($owner && get_pref($link, "STRIP_IMAGES", $owner)) ||
+ $force_remove_images) {
+
+ $p = $doc->createElement('p');
+
+ $a = $doc->createElement('a');
+ $a->setAttribute('href', $entry->getAttribute('src'));
+
+ $a->appendChild(new DOMText($entry->getAttribute('src')));
+ $a->setAttribute('target', '_blank');
+
+ $p->appendChild($a);
+
+ $entry->parentNode->replaceChild($p, $entry);
+ }
+ }
}
if (strtolower($entry->nodeName) == "a") {
$entry->setAttribute("target", "_blank");
}
+ }
- if (strtolower($entry->nodeName) == "img" && !$br_inserted) {
- $br = $doc->createElement("br");
+ $entries = $xpath->query('//iframe');
+ foreach ($entries as $entry) {
+ $entry->setAttribute('sandbox', 'allow-scripts');
- if ($entry->parentNode->nextSibling) {
- $entry->parentNode->insertBefore($br, $entry->nextSibling);
- $br_inserted = 1;
- }
+ }
+ global $pluginhost;
+
+ if (isset($pluginhost)) {
+ foreach ($pluginhost->get_hooks($pluginhost::HOOK_SANITIZE) as $plugin) {
+ $doc = $plugin->hook_sanitize($doc, $site_url);
}
}
- $node = $doc->getElementsByTagName('body')->item(0);
+ $doc->removeChild($doc->firstChild); //remove doctype
+ $doc = strip_harmful_tags($doc);
+ $res = $doc->saveHTML();
+ return $res;
+ }
+
+ function strip_harmful_tags($doc) {
+ $entries = $doc->getElementsByTagName("*");
- // http://tt-rss.org/redmine/issues/357
- return $doc->saveXML($node, LIBXML_NOEMPTYTAG);
+ $allowed_elements = array('a', 'address', 'audio', 'article',
+ 'b', 'big', 'blockquote', 'body', 'br', 'cite',
+ 'code', 'dd', 'del', 'details', 'div', 'dl', 'font',
+ 'dt', 'em', 'footer', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
+ 'header', 'html', 'i', 'img', 'ins', 'kbd',
+ 'li', 'nav', 'ol', 'p', 'pre', 'q', 's','small',
+ 'source', 'span', 'strike', 'strong', 'sub', 'summary',
+ 'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead',
+ 'tr', 'track', 'tt', 'u', 'ul', 'var', 'wbr', 'video' );
+
+ if ($_SESSION['hasSandbox']) array_push($allowed_elements, 'iframe');
+
+ $disallowed_attributes = array('id', 'style', 'class');
+
+ foreach ($entries as $entry) {
+ if (!in_array($entry->nodeName, $allowed_elements)) {
+ $entry->parentNode->removeChild($entry);
+ }
+
+ if ($entry->hasAttributes()) {
+ foreach (iterator_to_array($entry->attributes) as $attr) {
+
+ if (strpos($attr->nodeName, 'on') === 0) {
+ $entry->removeAttributeNode($attr);
+ }
+
+ if (in_array($attr->nodeName, $disallowed_attributes)) {
+ $entry->removeAttributeNode($attr);
+ }
+ }
+ }
+ }
+
+ return $doc;
}
function check_for_update($link) {
if (CHECK_FOR_NEW_VERSION && $_SESSION['access_level'] >= 10) {
- $version_url = "http://tt-rss.org/version.php?ver=" . VERSION;
+ $version_url = "http://tt-rss.org/version.php?ver=" . VERSION .
+ "&iid=" . sha1(SELF_URL_PATH);
$version_data = @fetch_file_contents($version_url);
function get_article_tags($link, $id, $owner_uid = 0, $tag_cache = false) {
- $a_id = db_escape_string($id);
+ $a_id = db_escape_string($link, $id);
if (!$owner_uid) $owner_uid = $_SESSION["uid"];
/* update the cache */
- $tags_str = db_escape_string(join(",", $tags));
+ $tags_str = db_escape_string($link, join(",", $tags));
db_query($link, "UPDATE ttrss_user_entries
SET tag_cache = '$tags_str' WHERE ref_id = '$id'
return true;
}
- function render_login_form($link, $form_id = 0) {
- switch ($form_id) {
- case 0:
- require_once "login_form.php";
- break;
- case 1:
- require_once "mobile/login_form.php";
- break;
- }
+ function render_login_form($link) {
+ require_once "login_form.php";
exit;
}
function format_warning($msg, $id = "") {
global $link;
return "<div class=\"warning\" id=\"$id\">
- <img src=\"".theme_image($link, "images/sign_excl.svg")."\">$msg</div>";
+ <img src=\"images/sign_excl.svg\">$msg</div>";
}
function format_notice($msg, $id = "") {
global $link;
return "<div class=\"notice\" id=\"$id\">
- <img src=\"".theme_image($link, "images/sign_info.svg")."\">$msg</div>";
+ <img src=\"images/sign_info.svg\">$msg</div>";
}
function format_error($msg, $id = "") {
global $link;
return "<div class=\"error\" id=\"$id\">
- <img src=\"".theme_image($link, "images/sign_excl.svg")."\">$msg</div>";
+ <img src=\"images/sign_excl.svg\">$msg</div>";
}
function print_notice($msg) {
$entry = "";
+ $url = htmlspecialchars($url);
+
if (strpos($ctype, "audio/") === 0) {
if ($_SESSION["hasAudio"] && (strpos($ctype, "ogg") !== false ||
$id = 'AUDIO-' . uniqid();
- $entry .= "<audio id=\"$id\"\" controls>
+ $entry .= "<audio id=\"$id\"\" controls style='display : none'>
<source type=\"$ctype\" src=\"$url\"></source>
</audio>";
</object>";
}
- if ($entry) $entry .= " " . basename($url);
+ if ($entry) $entry .= " <a target=\"_blank\"
+ href=\"$url\">" . basename($url) . "</a>";
return $entry;
//if (!$zoom_mode) { print "<article id='$id'><![CDATA["; };
- $result = db_query($link, "SELECT rtl_content, always_display_enclosures, cache_content FROM ttrss_feeds
- WHERE id = '$feed_id' AND owner_uid = $owner_uid");
-
- if (db_num_rows($result) == 1) {
- $rtl_content = sql_bool_to_bool(db_fetch_result($result, 0, "rtl_content"));
- $always_display_enclosures = sql_bool_to_bool(db_fetch_result($result, 0, "always_display_enclosures"));
- $cache_content = sql_bool_to_bool(db_fetch_result($result, 0, "cache_content"));
- } else {
- $rtl_content = false;
- $always_display_enclosures = false;
- $cache_content = false;
- }
-
- if ($rtl_content) {
- $rtl_tag = "dir=\"RTL\"";
- $rtl_class = "RTL";
- } else {
- $rtl_tag = "";
- $rtl_class = "";
- }
-
if ($mark_as_read) {
$result = db_query($link, "UPDATE ttrss_user_entries
SET unread = false,last_read = NOW()
$result = db_query($link, "SELECT id,title,link,content,feed_id,comments,int_id,
".SUBSTRING_FOR_DATE."(updated,1,16) as updated,
(SELECT site_url FROM ttrss_feeds WHERE id = feed_id) as site_url,
+ (SELECT hide_images FROM ttrss_feeds WHERE id = feed_id) as hide_images,
num_comments,
tag_cache,
author,
$line = db_fetch_assoc($result);
- $feed_site_url = $line['site_url'];
+ $tag_cache = $line["tag_cache"];
+
+ $line["tags"] = get_article_tags($link, $id, $owner_uid, $line["tag_cache"]);
+ unset($line["tag_cache"]);
+
+ $line["content"] = sanitize($link, $line["content"], false, $owner_uid, $line["site_url"]);
+
+ global $pluginhost;
+
+ foreach ($pluginhost->get_hooks($pluginhost::HOOK_RENDER_ARTICLE) as $p) {
+ $line = $p->hook_render_article($line);
+ }
$num_comments = $line["num_comments"];
$entry_comments = "";
$parsed_updated = make_local_datetime($link, $line["updated"], true,
$owner_uid, true);
- $rv['content'] .= "<div class=\"postDate$rtl_class\">$parsed_updated</div>";
+ $rv['content'] .= "<div class=\"postDate\">$parsed_updated</div>";
if ($line["link"]) {
$rv['content'] .= "<div class='postTitle'><a target='_blank'
$rv['content'] .= "<div class='postTitle'>" . $line["title"] . "$entry_author</div>";
}
- $tag_cache = $line["tag_cache"];
-
- if (!$tag_cache)
- $tags = get_article_tags($link, $id, $owner_uid);
- else
- $tags = explode(",", $tag_cache);
-
- $tags_str = format_tags_string($tags, $id);
- $tags_str_full = join(", ", $tags);
+ $tags_str = format_tags_string($line["tags"], $id);
+ $tags_str_full = join(", ", $line["tags"]);
if (!$tags_str_full) $tags_str_full = __("no tags");
if (!$entry_comments) $entry_comments = " "; # placeholder
$rv['content'] .= "<div class='postTags' style='float : right'>
- <img src='".theme_image($link, 'images/tag.png')."'
+ <img src='images/tag.png'
class='tagsPic' alt='Tags' title='Tags'> ";
if (!$zoom_mode) {
}
}
- if ($cache_content && $line["cached_content"] != "") {
- $line["content"] =& $line["cached_content"];
- }
-
- $article_content = sanitize($link, $line["content"], false, $owner_uid,
- $feed_site_url);
-
- $rv['content'] .= $article_content;
+ $rv['content'] .= $line["content"];
$rv['content'] .= format_article_enclosures($link, $id,
- $always_display_enclosures, $article_content);
+ $always_display_enclosures, $line["content"], $line["hide_images"]);
$rv['content'] .= "</div>";
}
function print_checkpoint($n, $s) {
- $ts = getmicrotime();
+ $ts = microtime(true);
echo sprintf("<!-- CP[$n] %.4f seconds -->", $ts - $s);
return $ts;
}
return $str;
}
- function toggle_collapse_cat($link, $cat_id, $mode) {
- if ($cat_id > 0) {
- $mode = bool_to_sql_bool($mode);
-
- db_query($link, "UPDATE ttrss_feed_categories SET
- collapsed = $mode WHERE id = '$cat_id' AND owner_uid = " .
- $_SESSION["uid"]);
- } else {
- $pref_name = '';
-
- switch ($cat_id) {
- case -1:
- $pref_name = '_COLLAPSED_SPECIAL';
- break;
- case -2:
- $pref_name = '_COLLAPSED_LABELS';
- break;
- case 0:
- $pref_name = '_COLLAPSED_UNCAT';
- break;
- }
-
- if ($pref_name) {
- if ($mode) {
- set_pref($link, $pref_name, 'true');
- } else {
- set_pref($link, $pref_name, 'false');
- }
- }
- }
- }
-
function get_feed_category($link, $feed_cat, $parent_cat_id = false) {
if ($parent_cat_id) {
if (db_num_rows($result) == 1) {
return db_fetch_result($result, 0, "access_key");
} else {
- $key = db_escape_string(sha1(uniqid(rand(), true)));
+ $key = db_escape_string($link, sha1(uniqid(rand(), true)));
$result = db_query($link, "INSERT INTO ttrss_access_keys
(access_key, feed_id, is_cat, owner_uid)
}
function format_article_enclosures($link, $id, $always_display_enclosures,
- $article_content) {
+ $article_content, $hide_images = false) {
$result = get_article_enclosures($link, $id);
$rv = '';
array_push($entries, $entry);
}
- if (!get_pref($link, "STRIP_IMAGES")) {
+ if ($_SESSION['uid'] && !get_pref($link, "STRIP_IMAGES")) {
if ($always_display_enclosures ||
!preg_match("/<img/i", $article_content)) {
if (preg_match("/image/", $entry["type"]) ||
preg_match("/\.(jpg|png|gif|bmp)/i", $entry["filename"])) {
- $rv .= "<p><img
- alt=\"".htmlspecialchars($entry["filename"])."\"
- src=\"" .htmlspecialchars($entry["url"]) . "\"/></p>";
+ if (!$hide_images) {
+ $rv .= "<p><img
+ alt=\"".htmlspecialchars($entry["filename"])."\"
+ src=\"" .htmlspecialchars($entry["url"]) . "\"/></p>";
+ } else {
+ $rv .= "<p><a target=\"_blank\"
+ href=\"".htmlspecialchars($entry["url"])."\"
+ >" .htmlspecialchars($entry["url"]) . "</a></p>";
+ }
}
}
}
// http://tt-rss.org/forum/viewtopic.php?f=1&t=970
if ($node)
- return $doc->saveXML($node, LIBXML_NOEMPTYTAG);
+ return $doc->saveXML($node);
else
return $html;
}
if ($regexp_valid) {
- $rule['reg_exp'] = db_escape_string($rule['reg_exp']);
+ $rule['reg_exp'] = db_escape_string($link, $rule['reg_exp']);
switch ($rule["type"]) {
case "title":
}
if (isset($rule["feed_id"]) && $rule["feed_id"] > 0) {
- $qpart .= " AND feed_id = " . db_escape_string($rule["feed_id"]);
+ $qpart .= " AND feed_id = " . db_escape_string($link, $rule["feed_id"]);
}
if (isset($rule["cat_id"])) {
return in_array($interface, class_implements($class));
}
+ function geturl($url){
+
+ (function_exists('curl_init')) ? '' : die('cURL Must be installed for geturl function to work. Ask your host to enable it or uncomment extension=php_curl.dll in php.ini');
+
+ $curl = curl_init();
+ $header[0] = "Accept: text/xml,application/xml,application/xhtml+xml,";
+ $header[0] .= "text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
+ $header[] = "Cache-Control: max-age=0";
+ $header[] = "Connection: keep-alive";
+ $header[] = "Keep-Alive: 300";
+ $header[] = "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7";
+ $header[] = "Accept-Language: en-us,en;q=0.5";
+ $header[] = "Pragma: ";
+
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0 Firefox/5.0');
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
+ curl_setopt($curl, CURLOPT_HEADER, true);
+ curl_setopt($curl, CURLOPT_REFERER, $url);
+ curl_setopt($curl, CURLOPT_ENCODING, 'gzip,deflate');
+ curl_setopt($curl, CURLOPT_AUTOREFERER, true);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ //curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); //CURLOPT_FOLLOWLOCATION Disabled...
+ curl_setopt($curl, CURLOPT_TIMEOUT, 60);
+
+ $html = curl_exec($curl);
+
+ $status = curl_getinfo($curl);
+ curl_close($curl);
+
+ if($status['http_code']!=200){
+ if($status['http_code'] == 301 || $status['http_code'] == 302) {
+ list($header) = explode("\r\n\r\n", $html, 2);
+ $matches = array();
+ preg_match("/(Location:|URI:)[^(\n)]*/", $header, $matches);
+ $url = trim(str_replace($matches[1],"",$matches[0]));
+ $url_parsed = parse_url($url);
+ return (isset($url_parsed))? geturl($url, $referer):'';
+ }
+ $oline='';
+ foreach($status as $key=>$eline){$oline.='['.$key.']'.$eline.' ';}
+ $line =$oline." \r\n ".$url."\r\n-----------------\r\n";
+# $handle = @fopen('./curl.error.log', 'a');
+# fwrite($handle, $line);
+ return FALSE;
+ }
+ return $url;
+ }
+
+ function get_minified_js($files) {
+ require_once 'lib/jshrink/Minifier.php';
+
+ $rv = '';
+
+ foreach ($files as $js) {
+ if (!isset($_GET['debug'])) {
+ $cached_file = CACHE_DIR . "/js/$js.js";
+
+ if (file_exists($cached_file) &&
+ is_readable($cached_file) &&
+ filemtime($cached_file) >= filemtime("js/$js.js")) {
+
+ $rv .= file_get_contents($cached_file);
+
+ } else {
+ $minified = JShrink\Minifier::minify(file_get_contents("js/$js.js"));
+ file_put_contents($cached_file, $minified);
+ $rv .= $minified;
+ }
+ } else {
+ $rv .= file_get_contents("js/$js.js");
+ }
+ }
+
+ return $rv;
+ }
+
+ function stylesheet_tag($filename) {
+ $timestamp = filemtime($filename);
+
+ echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"$filename?$timestamp\"/>\n";
+ }
+
+ function javascript_tag($filename) {
+ $query = "";
+
+ if (!(strpos($filename, "?") === FALSE)) {
+ $query = substr($filename, strpos($filename, "?")+1);
+ $filename = substr($filename, 0, strpos($filename, "?"));
+ }
+
+ $timestamp = filemtime($filename);
+
+ if ($query) $timestamp .= "&$query";
+
+ echo "<script type=\"text/javascript\" charset=\"utf-8\" src=\"$filename?$timestamp\"></script>\n";
+ }
+
+ function calculate_dep_timestamp() {
+ $files = array_merge(glob("js/*.js"), glob("*.css"));
+
+ $max_ts = -1;
+
+ foreach ($files as $file) {
+ if (filemtime($file) > $max_ts) $max_ts = filemtime($file);
+ }
+
+ return $max_ts;
+ }
+
+ function get_site_title() {
+ $original_title = "Tiny Tiny RSS";
+ if (defined("SITE_TITLE")) {
+ return SITE_TITLE;
+ }
+ return $original_title;
+ }
?>