move more globals to more appropriate places
set libxml to always use internal errors
This commit is contained in:
parent
4fa9aee4e7
commit
088fcf8131
|
@ -860,7 +860,7 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
// fall back in case of no plugins
|
// fall back in case of no plugins
|
||||||
if (!$search_qpart) {
|
if (!$search_qpart) {
|
||||||
list($search_qpart, $search_words) = search_to_sql($search[0], $search[1]);
|
list($search_qpart, $search_words) = Feeds::search_to_sql($search[0], $search[1]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$search_qpart = "true";
|
$search_qpart = "true";
|
||||||
|
@ -1456,7 +1456,7 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
// fall back in case of no plugins
|
// fall back in case of no plugins
|
||||||
if (!$search_query_part) {
|
if (!$search_query_part) {
|
||||||
list($search_query_part, $search_words) = search_to_sql($search, $search_language);
|
list($search_query_part, $search_words) = Feeds::search_to_sql($search, $search_language);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DB_TYPE == "pgsql") {
|
if (DB_TYPE == "pgsql") {
|
||||||
|
@ -1927,7 +1927,6 @@ class Feeds extends Handler_Protected {
|
||||||
$url = Feeds::fix_url($url);
|
$url = Feeds::fix_url($url);
|
||||||
$baseUrl = substr($url, 0, strrpos($url, '/') + 1);
|
$baseUrl = substr($url, 0, strrpos($url, '/') + 1);
|
||||||
|
|
||||||
libxml_use_internal_errors(true);
|
|
||||||
$feedUrls = [];
|
$feedUrls = [];
|
||||||
|
|
||||||
$doc = new DOMDocument();
|
$doc = new DOMDocument();
|
||||||
|
@ -2070,5 +2069,254 @@ class Feeds extends Handler_Protected {
|
||||||
return $key;
|
return $key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purge a feed old posts.
|
||||||
|
*
|
||||||
|
* @param mixed $link A database connection.
|
||||||
|
* @param mixed $feed_id The id of the purged feed.
|
||||||
|
* @param mixed $purge_interval Olderness of purged posts.
|
||||||
|
* @param boolean $debug Set to True to enable the debug. False by default.
|
||||||
|
* @access public
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
static function purge_feed($feed_id, $purge_interval) {
|
||||||
|
|
||||||
|
if (!$purge_interval) $purge_interval = Feeds::feed_purge_interval($feed_id);
|
||||||
|
|
||||||
|
$pdo = Db::pdo();
|
||||||
|
|
||||||
|
$sth = $pdo->prepare("SELECT owner_uid FROM ttrss_feeds WHERE id = ?");
|
||||||
|
$sth->execute([$feed_id]);
|
||||||
|
|
||||||
|
$owner_uid = false;
|
||||||
|
|
||||||
|
if ($row = $sth->fetch()) {
|
||||||
|
$owner_uid = $row["owner_uid"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($purge_interval == -1 || !$purge_interval) {
|
||||||
|
if ($owner_uid) {
|
||||||
|
CCache::update($feed_id, $owner_uid);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$owner_uid) return;
|
||||||
|
|
||||||
|
if (FORCE_ARTICLE_PURGE == 0) {
|
||||||
|
$purge_unread = get_pref("PURGE_UNREAD_ARTICLES",
|
||||||
|
$owner_uid, false);
|
||||||
|
} else {
|
||||||
|
$purge_unread = true;
|
||||||
|
$purge_interval = FORCE_ARTICLE_PURGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$purge_unread)
|
||||||
|
$query_limit = " unread = false AND ";
|
||||||
|
else
|
||||||
|
$query_limit = "";
|
||||||
|
|
||||||
|
$purge_interval = (int) $purge_interval;
|
||||||
|
|
||||||
|
if (DB_TYPE == "pgsql") {
|
||||||
|
$sth = $pdo->prepare("DELETE FROM ttrss_user_entries
|
||||||
|
USING ttrss_entries
|
||||||
|
WHERE ttrss_entries.id = ref_id AND
|
||||||
|
marked = false AND
|
||||||
|
feed_id = ? AND
|
||||||
|
$query_limit
|
||||||
|
ttrss_entries.date_updated < NOW() - INTERVAL '$purge_interval days'");
|
||||||
|
$sth->execute([$feed_id]);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$sth = $pdo->prepare("DELETE FROM ttrss_user_entries
|
||||||
|
USING ttrss_user_entries, ttrss_entries
|
||||||
|
WHERE ttrss_entries.id = ref_id AND
|
||||||
|
marked = false AND
|
||||||
|
feed_id = ? AND
|
||||||
|
$query_limit
|
||||||
|
ttrss_entries.date_updated < DATE_SUB(NOW(), INTERVAL $purge_interval DAY)");
|
||||||
|
$sth->execute([$feed_id]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows = $sth->rowCount();
|
||||||
|
|
||||||
|
CCache::update($feed_id, $owner_uid);
|
||||||
|
|
||||||
|
Debug::log("Purged feed $feed_id ($purge_interval): deleted $rows articles");
|
||||||
|
|
||||||
|
return $rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function feed_purge_interval($feed_id) {
|
||||||
|
|
||||||
|
$pdo = DB::pdo();
|
||||||
|
|
||||||
|
$sth = $pdo->prepare("SELECT purge_interval, owner_uid FROM ttrss_feeds
|
||||||
|
WHERE id = ?");
|
||||||
|
$sth->execute([$feed_id]);
|
||||||
|
|
||||||
|
if ($row = $sth->fetch()) {
|
||||||
|
$purge_interval = $row["purge_interval"];
|
||||||
|
$owner_uid = $row["owner_uid"];
|
||||||
|
|
||||||
|
if ($purge_interval == 0) $purge_interval = get_pref(
|
||||||
|
'PURGE_OLD_DAYS', $owner_uid);
|
||||||
|
|
||||||
|
return $purge_interval;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static function search_to_sql($search, $search_language) {
|
||||||
|
|
||||||
|
$keywords = str_getcsv(trim($search), " ");
|
||||||
|
$query_keywords = array();
|
||||||
|
$search_words = array();
|
||||||
|
$search_query_leftover = array();
|
||||||
|
|
||||||
|
$pdo = Db::pdo();
|
||||||
|
|
||||||
|
if ($search_language)
|
||||||
|
$search_language = $pdo->quote(mb_strtolower($search_language));
|
||||||
|
else
|
||||||
|
$search_language = $pdo->quote("english");
|
||||||
|
|
||||||
|
foreach ($keywords as $k) {
|
||||||
|
if (strpos($k, "-") === 0) {
|
||||||
|
$k = substr($k, 1);
|
||||||
|
$not = "NOT";
|
||||||
|
} else {
|
||||||
|
$not = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
$commandpair = explode(":", mb_strtolower($k), 2);
|
||||||
|
|
||||||
|
switch ($commandpair[0]) {
|
||||||
|
case "title":
|
||||||
|
if ($commandpair[1]) {
|
||||||
|
array_push($query_keywords, "($not (LOWER(ttrss_entries.title) LIKE ".
|
||||||
|
$pdo->quote('%' . mb_strtolower($commandpair[1]) . '%') ."))");
|
||||||
|
} else {
|
||||||
|
array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER('%$k%')
|
||||||
|
OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))");
|
||||||
|
array_push($search_words, $k);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "author":
|
||||||
|
if ($commandpair[1]) {
|
||||||
|
array_push($query_keywords, "($not (LOWER(author) LIKE ".
|
||||||
|
$pdo->quote('%' . mb_strtolower($commandpair[1]) . '%')."))");
|
||||||
|
} else {
|
||||||
|
array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER('%$k%')
|
||||||
|
OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))");
|
||||||
|
array_push($search_words, $k);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "note":
|
||||||
|
if ($commandpair[1]) {
|
||||||
|
if ($commandpair[1] == "true")
|
||||||
|
array_push($query_keywords, "($not (note IS NOT NULL AND note != ''))");
|
||||||
|
else if ($commandpair[1] == "false")
|
||||||
|
array_push($query_keywords, "($not (note IS NULL OR note = ''))");
|
||||||
|
else
|
||||||
|
array_push($query_keywords, "($not (LOWER(note) LIKE ".
|
||||||
|
$pdo->quote('%' . mb_strtolower($commandpair[1]) . '%')."))");
|
||||||
|
} else {
|
||||||
|
array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER(".$pdo->quote("%$k%").")
|
||||||
|
OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))");
|
||||||
|
if (!$not) array_push($search_words, $k);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "star":
|
||||||
|
|
||||||
|
if ($commandpair[1]) {
|
||||||
|
if ($commandpair[1] == "true")
|
||||||
|
array_push($query_keywords, "($not (marked = true))");
|
||||||
|
else
|
||||||
|
array_push($query_keywords, "($not (marked = false))");
|
||||||
|
} else {
|
||||||
|
array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER(".$pdo->quote("%$k%").")
|
||||||
|
OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))");
|
||||||
|
if (!$not) array_push($search_words, $k);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "pub":
|
||||||
|
if ($commandpair[1]) {
|
||||||
|
if ($commandpair[1] == "true")
|
||||||
|
array_push($query_keywords, "($not (published = true))");
|
||||||
|
else
|
||||||
|
array_push($query_keywords, "($not (published = false))");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER('%$k%')
|
||||||
|
OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))");
|
||||||
|
if (!$not) array_push($search_words, $k);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "unread":
|
||||||
|
if ($commandpair[1]) {
|
||||||
|
if ($commandpair[1] == "true")
|
||||||
|
array_push($query_keywords, "($not (unread = true))");
|
||||||
|
else
|
||||||
|
array_push($query_keywords, "($not (unread = false))");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER(".$pdo->quote("%$k%").")
|
||||||
|
OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))");
|
||||||
|
if (!$not) array_push($search_words, $k);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (strpos($k, "@") === 0) {
|
||||||
|
|
||||||
|
$user_tz_string = get_pref('USER_TIMEZONE', $_SESSION['uid']);
|
||||||
|
$orig_ts = strtotime(substr($k, 1));
|
||||||
|
$k = date("Y-m-d", convert_timestamp($orig_ts, $user_tz_string, 'UTC'));
|
||||||
|
|
||||||
|
//$k = date("Y-m-d", strtotime(substr($k, 1)));
|
||||||
|
|
||||||
|
array_push($query_keywords, "(".SUBSTRING_FOR_DATE."(updated,1,LENGTH('$k')) $not = '$k')");
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (DB_TYPE == "pgsql") {
|
||||||
|
$k = mb_strtolower($k);
|
||||||
|
array_push($search_query_leftover, $not ? "!$k" : $k);
|
||||||
|
} else {
|
||||||
|
array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER(".$pdo->quote("%$k%").")
|
||||||
|
OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$not) array_push($search_words, $k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($search_query_leftover) > 0) {
|
||||||
|
|
||||||
|
if (DB_TYPE == "pgsql") {
|
||||||
|
|
||||||
|
// if there's no joiners consider this a "simple" search and
|
||||||
|
// concatenate everything with &, otherwise don't try to mess with tsquery syntax
|
||||||
|
if (preg_match("/[&|]/", implode(" " , $search_query_leftover))) {
|
||||||
|
$tsquery = $pdo->quote(implode(" ", $search_query_leftover));
|
||||||
|
} else {
|
||||||
|
$tsquery = $pdo->quote(implode(" & ", $search_query_leftover));
|
||||||
|
}
|
||||||
|
|
||||||
|
array_push($query_keywords,
|
||||||
|
"(tsvector_combined @@ to_tsquery($search_language, $tsquery))");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$search_query_part = implode("AND", $query_keywords);
|
||||||
|
|
||||||
|
return array($search_query_part, $search_words);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -362,7 +362,7 @@ class Pref_Users extends Handler_Protected {
|
||||||
print "</div>"; #pane
|
print "</div>"; #pane
|
||||||
print "<div style='padding : 0px' dojoType='dijit.layout.ContentPane' region='center'>";
|
print "<div style='padding : 0px' dojoType='dijit.layout.ContentPane' region='center'>";
|
||||||
|
|
||||||
$sort = validate_field($sort,
|
$sort = $this->validate_field($sort,
|
||||||
["login", "access_level", "created", "num_feeds", "created", "last_login"], "login");
|
["login", "access_level", "created", "num_feeds", "created", "last_login"], "login");
|
||||||
|
|
||||||
if ($sort != "login") $sort = "$sort DESC";
|
if ($sort != "login") $sort = "$sort DESC";
|
||||||
|
@ -435,4 +435,12 @@ class Pref_Users extends Handler_Protected {
|
||||||
print "</div>"; #container
|
print "</div>"; #container
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function validate_field($string, $allowed, $default = "") {
|
||||||
|
if (in_array($string, $allowed))
|
||||||
|
return $string;
|
||||||
|
else
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1147,7 +1147,7 @@ class RSSUtils {
|
||||||
|
|
||||||
Debug::log("purging feed...", Debug::$LOG_VERBOSE);
|
Debug::log("purging feed...", Debug::$LOG_VERBOSE);
|
||||||
|
|
||||||
purge_feed($feed, 0);
|
Feeds::purge_feed($feed, 0);
|
||||||
|
|
||||||
$sth = $pdo->prepare("UPDATE ttrss_feeds
|
$sth = $pdo->prepare("UPDATE ttrss_feeds
|
||||||
SET last_updated = NOW(), last_unconditional = NOW(), last_error = '' WHERE id = ?");
|
SET last_updated = NOW(), last_unconditional = NOW(), last_error = '' WHERE id = ?");
|
||||||
|
@ -1205,10 +1205,8 @@ class RSSUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
static function cache_media($html, $site_url) {
|
static function cache_media($html, $site_url) {
|
||||||
libxml_use_internal_errors(true);
|
|
||||||
|
|
||||||
$doc = new DOMDocument();
|
$doc = new DOMDocument();
|
||||||
$doc->loadHTML('<?xml encoding="UTF-8">' . $html);
|
if ($doc->loadHTML($html)) {
|
||||||
$xpath = new DOMXPath($doc);
|
$xpath = new DOMXPath($doc);
|
||||||
|
|
||||||
$entries = $xpath->query('(//img[@src])|(//video/source[@src])|(//audio/source[@src])');
|
$entries = $xpath->query('(//img[@src])|(//video/source[@src])|(//audio/source[@src])');
|
||||||
|
@ -1235,6 +1233,7 @@ class RSSUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static function expire_error_log() {
|
static function expire_error_log() {
|
||||||
Debug::log("Removing old error log entries...");
|
Debug::log("Removing old error log entries...");
|
||||||
|
@ -1517,7 +1516,7 @@ class RSSUtils {
|
||||||
$icon_file = ICONS_DIR . "/$feed.ico";
|
$icon_file = ICONS_DIR . "/$feed.ico";
|
||||||
|
|
||||||
if (!file_exists($icon_file)) {
|
if (!file_exists($icon_file)) {
|
||||||
$favicon_url = get_favicon_url($site_url);
|
$favicon_url = RSSUtils::get_favicon_url($site_url);
|
||||||
|
|
||||||
if ($favicon_url) {
|
if ($favicon_url) {
|
||||||
// Limiting to "image" type misses those served with text/plain
|
// Limiting to "image" type misses those served with text/plain
|
||||||
|
@ -1679,4 +1678,46 @@ class RSSUtils {
|
||||||
|
|
||||||
return $filters;
|
return $filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to determine the favicon URL for a feed.
|
||||||
|
* adapted from wordpress favicon plugin by Jeff Minard (http://thecodepro.com/)
|
||||||
|
* http://dev.wp-plugins.org/file/favatars/trunk/favatars.php
|
||||||
|
*
|
||||||
|
* @param string $url A feed or page URL
|
||||||
|
* @access public
|
||||||
|
* @return mixed The favicon URL, or false if none was found.
|
||||||
|
*/
|
||||||
|
static function get_favicon_url($url) {
|
||||||
|
|
||||||
|
$favicon_url = false;
|
||||||
|
|
||||||
|
if ($html = @fetch_file_contents($url)) {
|
||||||
|
|
||||||
|
$doc = new DOMDocument();
|
||||||
|
if ($doc->loadHTML($html)) {
|
||||||
|
$xpath = new DOMXPath($doc);
|
||||||
|
|
||||||
|
$base = $xpath->query('/html/head/base[@href]');
|
||||||
|
foreach ($base as $b) {
|
||||||
|
$url = rewrite_relative_url($url, $b->getAttribute("href"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$entries = $xpath->query('/html/head/link[@rel="shortcut icon" or @rel="icon"]');
|
||||||
|
if (count($entries) > 0) {
|
||||||
|
foreach ($entries as $entry) {
|
||||||
|
$favicon_url = rewrite_relative_url($url, $entry->getAttribute("href"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$favicon_url)
|
||||||
|
$favicon_url = rewrite_relative_url($url, "/favicon.ico");
|
||||||
|
|
||||||
|
return $favicon_url;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
$fetch_curl_used = false;
|
$fetch_curl_used = false;
|
||||||
|
|
||||||
libxml_disable_entity_loader(true);
|
libxml_disable_entity_loader(true);
|
||||||
|
libxml_use_internal_errors(true);
|
||||||
|
|
||||||
// separate test because this is included before sanity checks
|
// separate test because this is included before sanity checks
|
||||||
if (function_exists("mb_internal_encoding")) mb_internal_encoding("UTF-8");
|
if (function_exists("mb_internal_encoding")) mb_internal_encoding("UTF-8");
|
||||||
|
@ -160,108 +161,6 @@
|
||||||
Debug::log($msg);
|
Debug::log($msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Purge a feed old posts.
|
|
||||||
*
|
|
||||||
* @param mixed $link A database connection.
|
|
||||||
* @param mixed $feed_id The id of the purged feed.
|
|
||||||
* @param mixed $purge_interval Olderness of purged posts.
|
|
||||||
* @param boolean $debug Set to True to enable the debug. False by default.
|
|
||||||
* @access public
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function purge_feed($feed_id, $purge_interval) {
|
|
||||||
|
|
||||||
if (!$purge_interval) $purge_interval = feed_purge_interval($feed_id);
|
|
||||||
|
|
||||||
$pdo = Db::pdo();
|
|
||||||
|
|
||||||
$sth = $pdo->prepare("SELECT owner_uid FROM ttrss_feeds WHERE id = ?");
|
|
||||||
$sth->execute([$feed_id]);
|
|
||||||
|
|
||||||
$owner_uid = false;
|
|
||||||
|
|
||||||
if ($row = $sth->fetch()) {
|
|
||||||
$owner_uid = $row["owner_uid"];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($purge_interval == -1 || !$purge_interval) {
|
|
||||||
if ($owner_uid) {
|
|
||||||
CCache::update($feed_id, $owner_uid);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$owner_uid) return;
|
|
||||||
|
|
||||||
if (FORCE_ARTICLE_PURGE == 0) {
|
|
||||||
$purge_unread = get_pref("PURGE_UNREAD_ARTICLES",
|
|
||||||
$owner_uid, false);
|
|
||||||
} else {
|
|
||||||
$purge_unread = true;
|
|
||||||
$purge_interval = FORCE_ARTICLE_PURGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$purge_unread)
|
|
||||||
$query_limit = " unread = false AND ";
|
|
||||||
else
|
|
||||||
$query_limit = "";
|
|
||||||
|
|
||||||
$purge_interval = (int) $purge_interval;
|
|
||||||
|
|
||||||
if (DB_TYPE == "pgsql") {
|
|
||||||
$sth = $pdo->prepare("DELETE FROM ttrss_user_entries
|
|
||||||
USING ttrss_entries
|
|
||||||
WHERE ttrss_entries.id = ref_id AND
|
|
||||||
marked = false AND
|
|
||||||
feed_id = ? AND
|
|
||||||
$query_limit
|
|
||||||
ttrss_entries.date_updated < NOW() - INTERVAL '$purge_interval days'");
|
|
||||||
$sth->execute([$feed_id]);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$sth = $pdo->prepare("DELETE FROM ttrss_user_entries
|
|
||||||
USING ttrss_user_entries, ttrss_entries
|
|
||||||
WHERE ttrss_entries.id = ref_id AND
|
|
||||||
marked = false AND
|
|
||||||
feed_id = ? AND
|
|
||||||
$query_limit
|
|
||||||
ttrss_entries.date_updated < DATE_SUB(NOW(), INTERVAL $purge_interval DAY)");
|
|
||||||
$sth->execute([$feed_id]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$rows = $sth->rowCount();
|
|
||||||
|
|
||||||
CCache::update($feed_id, $owner_uid);
|
|
||||||
|
|
||||||
Debug::log("Purged feed $feed_id ($purge_interval): deleted $rows articles");
|
|
||||||
|
|
||||||
return $rows;
|
|
||||||
} // function purge_feed
|
|
||||||
|
|
||||||
function feed_purge_interval($feed_id) {
|
|
||||||
|
|
||||||
$pdo = DB::pdo();
|
|
||||||
|
|
||||||
$sth = $pdo->prepare("SELECT purge_interval, owner_uid FROM ttrss_feeds
|
|
||||||
WHERE id = ?");
|
|
||||||
$sth->execute([$feed_id]);
|
|
||||||
|
|
||||||
if ($row = $sth->fetch()) {
|
|
||||||
$purge_interval = $row["purge_interval"];
|
|
||||||
$owner_uid = $row["owner_uid"];
|
|
||||||
|
|
||||||
if ($purge_interval == 0) $purge_interval = get_pref(
|
|
||||||
'PURGE_OLD_DAYS', $owner_uid);
|
|
||||||
|
|
||||||
return $purge_interval;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: max_size currently only works for CURL transfers
|
// TODO: max_size currently only works for CURL transfers
|
||||||
// TODO: multiple-argument way is deprecated, first parameter is a hash now
|
// TODO: multiple-argument way is deprecated, first parameter is a hash now
|
||||||
function fetch_file_contents($options /* previously: 0: $url , 1: $type = false, 2: $login = false, 3: $pass = false,
|
function fetch_file_contents($options /* previously: 0: $url , 1: $type = false, 2: $login = false, 3: $pass = false,
|
||||||
|
@ -544,48 +443,6 @@
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to determine the favicon URL for a feed.
|
|
||||||
* adapted from wordpress favicon plugin by Jeff Minard (http://thecodepro.com/)
|
|
||||||
* http://dev.wp-plugins.org/file/favatars/trunk/favatars.php
|
|
||||||
*
|
|
||||||
* @param string $url A feed or page URL
|
|
||||||
* @access public
|
|
||||||
* @return mixed The favicon URL, or false if none was found.
|
|
||||||
*/
|
|
||||||
function get_favicon_url($url) {
|
|
||||||
|
|
||||||
$favicon_url = false;
|
|
||||||
|
|
||||||
if ($html = @fetch_file_contents($url)) {
|
|
||||||
|
|
||||||
libxml_use_internal_errors(true);
|
|
||||||
|
|
||||||
$doc = new DOMDocument();
|
|
||||||
$doc->loadHTML('<?xml encoding="UTF-8">' . $html);
|
|
||||||
$xpath = new DOMXPath($doc);
|
|
||||||
|
|
||||||
$base = $xpath->query('/html/head/base[@href]');
|
|
||||||
foreach ($base as $b) {
|
|
||||||
$url = rewrite_relative_url($url, $b->getAttribute("href"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$entries = $xpath->query('/html/head/link[@rel="shortcut icon" or @rel="icon"]');
|
|
||||||
if (count($entries) > 0) {
|
|
||||||
foreach ($entries as $entry) {
|
|
||||||
$favicon_url = rewrite_relative_url($url, $entry->getAttribute("href"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$favicon_url)
|
|
||||||
$favicon_url = rewrite_relative_url($url, "/favicon.ico");
|
|
||||||
|
|
||||||
return $favicon_url;
|
|
||||||
} // function get_favicon_url
|
|
||||||
|
|
||||||
function initialize_user_prefs($uid, $profile = false) {
|
function initialize_user_prefs($uid, $profile = false) {
|
||||||
|
|
||||||
if (get_schema_version() < 63) $profile_qpart = "";
|
if (get_schema_version() < 63) $profile_qpart = "";
|
||||||
|
@ -1361,153 +1218,6 @@
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
function search_to_sql($search, $search_language) {
|
|
||||||
|
|
||||||
$keywords = str_getcsv(trim($search), " ");
|
|
||||||
$query_keywords = array();
|
|
||||||
$search_words = array();
|
|
||||||
$search_query_leftover = array();
|
|
||||||
|
|
||||||
$pdo = Db::pdo();
|
|
||||||
|
|
||||||
if ($search_language)
|
|
||||||
$search_language = $pdo->quote(mb_strtolower($search_language));
|
|
||||||
else
|
|
||||||
$search_language = $pdo->quote("english");
|
|
||||||
|
|
||||||
foreach ($keywords as $k) {
|
|
||||||
if (strpos($k, "-") === 0) {
|
|
||||||
$k = substr($k, 1);
|
|
||||||
$not = "NOT";
|
|
||||||
} else {
|
|
||||||
$not = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
$commandpair = explode(":", mb_strtolower($k), 2);
|
|
||||||
|
|
||||||
switch ($commandpair[0]) {
|
|
||||||
case "title":
|
|
||||||
if ($commandpair[1]) {
|
|
||||||
array_push($query_keywords, "($not (LOWER(ttrss_entries.title) LIKE ".
|
|
||||||
$pdo->quote('%' . mb_strtolower($commandpair[1]) . '%') ."))");
|
|
||||||
} else {
|
|
||||||
array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER('%$k%')
|
|
||||||
OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))");
|
|
||||||
array_push($search_words, $k);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "author":
|
|
||||||
if ($commandpair[1]) {
|
|
||||||
array_push($query_keywords, "($not (LOWER(author) LIKE ".
|
|
||||||
$pdo->quote('%' . mb_strtolower($commandpair[1]) . '%')."))");
|
|
||||||
} else {
|
|
||||||
array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER('%$k%')
|
|
||||||
OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))");
|
|
||||||
array_push($search_words, $k);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "note":
|
|
||||||
if ($commandpair[1]) {
|
|
||||||
if ($commandpair[1] == "true")
|
|
||||||
array_push($query_keywords, "($not (note IS NOT NULL AND note != ''))");
|
|
||||||
else if ($commandpair[1] == "false")
|
|
||||||
array_push($query_keywords, "($not (note IS NULL OR note = ''))");
|
|
||||||
else
|
|
||||||
array_push($query_keywords, "($not (LOWER(note) LIKE ".
|
|
||||||
$pdo->quote('%' . mb_strtolower($commandpair[1]) . '%')."))");
|
|
||||||
} else {
|
|
||||||
array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER(".$pdo->quote("%$k%").")
|
|
||||||
OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))");
|
|
||||||
if (!$not) array_push($search_words, $k);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "star":
|
|
||||||
|
|
||||||
if ($commandpair[1]) {
|
|
||||||
if ($commandpair[1] == "true")
|
|
||||||
array_push($query_keywords, "($not (marked = true))");
|
|
||||||
else
|
|
||||||
array_push($query_keywords, "($not (marked = false))");
|
|
||||||
} else {
|
|
||||||
array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER(".$pdo->quote("%$k%").")
|
|
||||||
OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))");
|
|
||||||
if (!$not) array_push($search_words, $k);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "pub":
|
|
||||||
if ($commandpair[1]) {
|
|
||||||
if ($commandpair[1] == "true")
|
|
||||||
array_push($query_keywords, "($not (published = true))");
|
|
||||||
else
|
|
||||||
array_push($query_keywords, "($not (published = false))");
|
|
||||||
|
|
||||||
} else {
|
|
||||||
array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER('%$k%')
|
|
||||||
OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))");
|
|
||||||
if (!$not) array_push($search_words, $k);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "unread":
|
|
||||||
if ($commandpair[1]) {
|
|
||||||
if ($commandpair[1] == "true")
|
|
||||||
array_push($query_keywords, "($not (unread = true))");
|
|
||||||
else
|
|
||||||
array_push($query_keywords, "($not (unread = false))");
|
|
||||||
|
|
||||||
} else {
|
|
||||||
array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER(".$pdo->quote("%$k%").")
|
|
||||||
OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))");
|
|
||||||
if (!$not) array_push($search_words, $k);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (strpos($k, "@") === 0) {
|
|
||||||
|
|
||||||
$user_tz_string = get_pref('USER_TIMEZONE', $_SESSION['uid']);
|
|
||||||
$orig_ts = strtotime(substr($k, 1));
|
|
||||||
$k = date("Y-m-d", convert_timestamp($orig_ts, $user_tz_string, 'UTC'));
|
|
||||||
|
|
||||||
//$k = date("Y-m-d", strtotime(substr($k, 1)));
|
|
||||||
|
|
||||||
array_push($query_keywords, "(".SUBSTRING_FOR_DATE."(updated,1,LENGTH('$k')) $not = '$k')");
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (DB_TYPE == "pgsql") {
|
|
||||||
$k = mb_strtolower($k);
|
|
||||||
array_push($search_query_leftover, $not ? "!$k" : $k);
|
|
||||||
} else {
|
|
||||||
array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER(".$pdo->quote("%$k%").")
|
|
||||||
OR UPPER(ttrss_entries.content) $not LIKE UPPER(".$pdo->quote("%$k%")."))");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$not) array_push($search_words, $k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($search_query_leftover) > 0) {
|
|
||||||
|
|
||||||
if (DB_TYPE == "pgsql") {
|
|
||||||
|
|
||||||
// if there's no joiners consider this a "simple" search and
|
|
||||||
// concatenate everything with &, otherwise don't try to mess with tsquery syntax
|
|
||||||
if (preg_match("/[&|]/", implode(" " , $search_query_leftover))) {
|
|
||||||
$tsquery = $pdo->quote(implode(" ", $search_query_leftover));
|
|
||||||
} else {
|
|
||||||
$tsquery = $pdo->quote(implode(" & ", $search_query_leftover));
|
|
||||||
}
|
|
||||||
|
|
||||||
array_push($query_keywords,
|
|
||||||
"(tsvector_combined @@ to_tsquery($search_language, $tsquery))");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$search_query_part = implode("AND", $query_keywords);
|
|
||||||
|
|
||||||
return array($search_query_part, $search_words);
|
|
||||||
}
|
|
||||||
|
|
||||||
function iframe_whitelisted($entry) {
|
function iframe_whitelisted($entry) {
|
||||||
$whitelist = array("youtube.com", "youtu.be", "vimeo.com", "player.vimeo.com");
|
$whitelist = array("youtube.com", "youtu.be", "vimeo.com", "player.vimeo.com");
|
||||||
|
|
||||||
|
@ -1586,8 +1296,6 @@
|
||||||
|
|
||||||
$res = trim($str); if (!$res) return '';
|
$res = trim($str); if (!$res) return '';
|
||||||
|
|
||||||
libxml_use_internal_errors(true);
|
|
||||||
|
|
||||||
$doc = new DOMDocument();
|
$doc = new DOMDocument();
|
||||||
$doc->loadHTML('<?xml encoding="UTF-8">' . $res);
|
$doc->loadHTML('<?xml encoding="UTF-8">' . $res);
|
||||||
$xpath = new DOMXPath($doc);
|
$xpath = new DOMXPath($doc);
|
||||||
|
@ -1901,51 +1609,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup_tags($days = 14, $limit = 1000) {
|
|
||||||
|
|
||||||
$days = (int) $days;
|
|
||||||
|
|
||||||
if (DB_TYPE == "pgsql") {
|
|
||||||
$interval_query = "date_updated < NOW() - INTERVAL '$days days'";
|
|
||||||
} else if (DB_TYPE == "mysql") {
|
|
||||||
$interval_query = "date_updated < DATE_SUB(NOW(), INTERVAL $days DAY)";
|
|
||||||
}
|
|
||||||
|
|
||||||
$tags_deleted = 0;
|
|
||||||
|
|
||||||
$pdo = Db::pdo();
|
|
||||||
|
|
||||||
while ($limit > 0) {
|
|
||||||
$limit_part = 500;
|
|
||||||
|
|
||||||
$sth = $pdo->prepare("SELECT ttrss_tags.id AS id
|
|
||||||
FROM ttrss_tags, ttrss_user_entries, ttrss_entries
|
|
||||||
WHERE post_int_id = int_id AND $interval_query AND
|
|
||||||
ref_id = ttrss_entries.id AND tag_cache != '' LIMIT ?");
|
|
||||||
$sth->bindValue(1, $limit_part, PDO::PARAM_INT);
|
|
||||||
$sth->execute();
|
|
||||||
|
|
||||||
$ids = array();
|
|
||||||
|
|
||||||
while ($line = $sth->fetch()) {
|
|
||||||
array_push($ids, $line['id']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($ids) > 0) {
|
|
||||||
$ids = join(",", $ids);
|
|
||||||
|
|
||||||
$usth = $pdo->query("DELETE FROM ttrss_tags WHERE id IN ($ids)");
|
|
||||||
$tags_deleted = $usth->rowCount();
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$limit -= $limit_part;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $tags_deleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
function print_user_stylesheet() {
|
function print_user_stylesheet() {
|
||||||
$value = get_pref('USER_STYLESHEET');
|
$value = get_pref('USER_STYLESHEET');
|
||||||
|
|
||||||
|
@ -1957,7 +1620,7 @@
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function filter_to_sql($filter, $owner_uid) {
|
/* function filter_to_sql($filter, $owner_uid) {
|
||||||
$query = array();
|
$query = array();
|
||||||
|
|
||||||
$pdo = Db::pdo();
|
$pdo = Db::pdo();
|
||||||
|
@ -2043,7 +1706,7 @@
|
||||||
if ($filter['inverse']) $fullquery = "(NOT $fullquery)";
|
if ($filter['inverse']) $fullquery = "(NOT $fullquery)";
|
||||||
|
|
||||||
return $fullquery;
|
return $fullquery;
|
||||||
}
|
} */
|
||||||
|
|
||||||
if (!function_exists('gzdecode')) {
|
if (!function_exists('gzdecode')) {
|
||||||
function gzdecode($string) { // no support for 2nd argument
|
function gzdecode($string) { // no support for 2nd argument
|
||||||
|
@ -2231,29 +1894,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_mysql_tables() {
|
|
||||||
$pdo = Db::pdo();
|
|
||||||
|
|
||||||
$sth = $pdo->prepare("SELECT engine, table_name FROM information_schema.tables WHERE
|
|
||||||
table_schema = ? AND table_name LIKE 'ttrss_%' AND engine != 'InnoDB'");
|
|
||||||
$sth->execute([DB_NAME]);
|
|
||||||
|
|
||||||
$bad_tables = [];
|
|
||||||
|
|
||||||
while ($line = $sth->fetch()) {
|
|
||||||
array_push($bad_tables, $line);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $bad_tables;
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate_field($string, $allowed, $default = "") {
|
|
||||||
if (in_array($string, $allowed))
|
|
||||||
return $string;
|
|
||||||
else
|
|
||||||
return $default;
|
|
||||||
}
|
|
||||||
|
|
||||||
function arr_qmarks($arr) {
|
function arr_qmarks($arr) {
|
||||||
return str_repeat('?,', count($arr) - 1) . '?';
|
return str_repeat('?,', count($arr) - 1) . '?';
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,22 @@
|
||||||
return $url_path;
|
return $url_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function check_mysql_tables() {
|
||||||
|
$pdo = Db::pdo();
|
||||||
|
|
||||||
|
$sth = $pdo->prepare("SELECT engine, table_name FROM information_schema.tables WHERE
|
||||||
|
table_schema = ? AND table_name LIKE 'ttrss_%' AND engine != 'InnoDB'");
|
||||||
|
$sth->execute([DB_NAME]);
|
||||||
|
|
||||||
|
$bad_tables = [];
|
||||||
|
|
||||||
|
while ($line = $sth->fetch()) {
|
||||||
|
array_push($bad_tables, $line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bad_tables;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
|
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -166,8 +166,6 @@ class Cache_Starred_Images extends Plugin implements IHandler {
|
||||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||||
*/
|
*/
|
||||||
function cache_article_images($content, $site_url, $owner_uid, $article_id) {
|
function cache_article_images($content, $site_url, $owner_uid, $article_id) {
|
||||||
libxml_use_internal_errors(true);
|
|
||||||
|
|
||||||
$status_filename = $this->cache_dir . $article_id . "-" . sha1($site_url) . ".status";
|
$status_filename = $this->cache_dir . $article_id . "-" . sha1($site_url) . ".status";
|
||||||
|
|
||||||
Debug::log("status: $status_filename", Debug::$LOG_EXTENDED);
|
Debug::log("status: $status_filename", Debug::$LOG_EXTENDED);
|
||||||
|
|
45
update.php
45
update.php
|
@ -14,6 +14,51 @@
|
||||||
require_once "db.php";
|
require_once "db.php";
|
||||||
require_once "db-prefs.php";
|
require_once "db-prefs.php";
|
||||||
|
|
||||||
|
function cleanup_tags($days = 14, $limit = 1000) {
|
||||||
|
|
||||||
|
$days = (int) $days;
|
||||||
|
|
||||||
|
if (DB_TYPE == "pgsql") {
|
||||||
|
$interval_query = "date_updated < NOW() - INTERVAL '$days days'";
|
||||||
|
} else if (DB_TYPE == "mysql") {
|
||||||
|
$interval_query = "date_updated < DATE_SUB(NOW(), INTERVAL $days DAY)";
|
||||||
|
}
|
||||||
|
|
||||||
|
$tags_deleted = 0;
|
||||||
|
|
||||||
|
$pdo = Db::pdo();
|
||||||
|
|
||||||
|
while ($limit > 0) {
|
||||||
|
$limit_part = 500;
|
||||||
|
|
||||||
|
$sth = $pdo->prepare("SELECT ttrss_tags.id AS id
|
||||||
|
FROM ttrss_tags, ttrss_user_entries, ttrss_entries
|
||||||
|
WHERE post_int_id = int_id AND $interval_query AND
|
||||||
|
ref_id = ttrss_entries.id AND tag_cache != '' LIMIT ?");
|
||||||
|
$sth->bindValue(1, $limit_part, PDO::PARAM_INT);
|
||||||
|
$sth->execute();
|
||||||
|
|
||||||
|
$ids = array();
|
||||||
|
|
||||||
|
while ($line = $sth->fetch()) {
|
||||||
|
array_push($ids, $line['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($ids) > 0) {
|
||||||
|
$ids = join(",", $ids);
|
||||||
|
|
||||||
|
$usth = $pdo->query("DELETE FROM ttrss_tags WHERE id IN ($ids)");
|
||||||
|
$tags_deleted = $usth->rowCount();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$limit -= $limit_part;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tags_deleted;
|
||||||
|
}
|
||||||
|
|
||||||
if (!defined('PHP_EXECUTABLE'))
|
if (!defined('PHP_EXECUTABLE'))
|
||||||
define('PHP_EXECUTABLE', '/usr/bin/php');
|
define('PHP_EXECUTABLE', '/usr/bin/php');
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue