Commit 088fcf81 authored by Andrew Dolgov's avatar Andrew Dolgov

move more globals to more appropriate places

set libxml to always use internal errors
parent 4fa9aee4
......@@ -860,7 +860,7 @@ class Feeds extends Handler_Protected {
// fall back in case of no plugins
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 {
$search_qpart = "true";
......@@ -1456,7 +1456,7 @@ class Feeds extends Handler_Protected {
// fall back in case of no plugins
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") {
......@@ -1927,7 +1927,6 @@ class Feeds extends Handler_Protected {
$url = Feeds::fix_url($url);
$baseUrl = substr($url, 0, strrpos($url, '/') + 1);
libxml_use_internal_errors(true);
$feedUrls = [];
$doc = new DOMDocument();
......@@ -2070,5 +2069,254 @@ class Feeds extends Handler_Protected {
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 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");
if ($sort != "login") $sort = "$sort DESC";
......@@ -435,4 +435,12 @@ class Pref_Users extends Handler_Protected {
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);
purge_feed($feed, 0);
Feeds::purge_feed($feed, 0);
$sth = $pdo->prepare("UPDATE ttrss_feeds
SET last_updated = NOW(), last_unconditional = NOW(), last_error = '' WHERE id = ?");
......@@ -1205,32 +1205,31 @@ class RSSUtils {
}
static function cache_media($html, $site_url) {
libxml_use_internal_errors(true);
$doc = new DOMDocument();
$doc->loadHTML('<?xml encoding="UTF-8">' . $html);
$xpath = new DOMXPath($doc);
if ($doc->loadHTML($html)) {
$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])');
foreach ($entries as $entry) {
if ($entry->hasAttribute('src') && strpos($entry->getAttribute('src'), "data:") !== 0) {
$src = rewrite_relative_url($site_url, $entry->getAttribute('src'));
foreach ($entries as $entry) {
if ($entry->hasAttribute('src') && strpos($entry->getAttribute('src'), "data:") !== 0) {
$src = rewrite_relative_url($site_url, $entry->getAttribute('src'));
$local_filename = CACHE_DIR . "/images/" . sha1($src);
$local_filename = CACHE_DIR . "/images/" . sha1($src);
Debug::log("cache_media: checking $src", Debug::$LOG_VERBOSE);
Debug::log("cache_media: checking $src", Debug::$LOG_VERBOSE);
if (!file_exists($local_filename)) {
Debug::log("cache_media: downloading: $src to $local_filename", Debug::$LOG_VERBOSE);
if (!file_exists($local_filename)) {
Debug::log("cache_media: downloading: $src to $local_filename", Debug::$LOG_VERBOSE);
$file_content = fetch_file_contents($src);
$file_content = fetch_file_contents($src);
if ($file_content && strlen($file_content) > MIN_CACHE_FILE_SIZE) {
file_put_contents($local_filename, $file_content);
if ($file_content && strlen($file_content) > MIN_CACHE_FILE_SIZE) {
file_put_contents($local_filename, $file_content);
}
} else if (is_writable($local_filename)) {
touch($local_filename);
}
} else if (is_writable($local_filename)) {
touch($local_filename);
}
}
}
......@@ -1517,7 +1516,7 @@ class RSSUtils {
$icon_file = ICONS_DIR . "/$feed.ico";
if (!file_exists($icon_file)) {
$favicon_url = get_favicon_url($site_url);
$favicon_url = RSSUtils::get_favicon_url($site_url);
if ($favicon_url) {
// Limiting to "image" type misses those served with text/plain
......@@ -1679,4 +1678,46 @@ class RSSUtils {
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;
}
}
This diff is collapsed.
......@@ -27,7 +27,23 @@
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)
*/
function initial_sanity_check() {
......
......@@ -166,8 +166,6 @@ class Cache_Starred_Images extends Plugin implements IHandler {
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
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";
Debug::log("status: $status_filename", Debug::$LOG_EXTENDED);
......
......@@ -14,6 +14,51 @@
require_once "db.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'))
define('PHP_EXECUTABLE', '/usr/bin/php');
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment