X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=functions.php;h=737423913d6c7c17c8d58495e84e7450834a9ee1;hb=d00f22ac59dc01f55e3cc2ccad390705537bd88e;hp=613641b318356c40469d9bebfafd5c0696035e6b;hpb=66a251f901306b8dd5bd856efc75681d68880261;p=tt-rss.git diff --git a/functions.php b/functions.php index 613641b3..73742391 100644 --- a/functions.php +++ b/functions.php @@ -8,11 +8,25 @@ require_once 'config.php'; + if (DB_TYPE == "pgsql") { + define('SUBSTRING_FOR_DATE', 'SUBSTRING_FOR_DATE'); + } else { + define('SUBSTRING_FOR_DATE', 'SUBSTRING'); + } + + /** + * Return available translations names. + * + * @access public + * @return array A array of available translations. + */ function get_translations() { $tr = array( "auto" => "Detect automatically", "en_US" => "English", "fr_FR" => "Français", + "hu_HU" => "Magyar (Hungarian)", + "nb_NO" => "Norwegian bokmål", "ru_RU" => "Русский", "pt_BR" => "Portuguese/Brazil", "zh_CN" => "Simplified Chinese"); @@ -20,7 +34,7 @@ return $tr; } - if (ENABLE_TRANSLATIONS == true) { + if (ENABLE_TRANSLATIONS == true) { // If translations are enabled. require_once "accept-to-gettext.php"; require_once "gettext/gettext.inc"; @@ -38,7 +52,13 @@ } if ($lang) { - _setlocale(LC_MESSAGES, $lang); + if (defined('LC_MESSAGES')) { + _setlocale(LC_MESSAGES, $lang); + } else if (defined('LC_ALL')) { + _setlocale(LC_ALL, $lang); + } else { + die("can't setlocale(): please set ENABLE_TRANSLATIONS to false in config.php"); + } _bindtextdomain("messages", "locale"); _textdomain("messages"); _bind_textdomain_codeset("messages", "UTF-8"); @@ -47,7 +67,7 @@ startup_gettext(); - } else { + } else { // If translations are enabled. function __($msg) { return $msg; } @@ -55,7 +75,7 @@ // no-op return true; } - } + } // If translations are enabled. require_once 'db-prefs.php'; require_once 'compat.php'; @@ -67,18 +87,34 @@ define('MAGPIE_USER_AGENT_EXT', ' (Tiny Tiny RSS/' . VERSION . ')'); define('MAGPIE_OUTPUT_ENCODING', 'UTF-8'); - if (ENABLE_SIMPLEPIE) { - require_once "simplepie/simplepie.inc"; - } else { - require_once "magpierss/rss_fetch.inc"; - require_once 'magpierss/rss_utils.inc'; - } + require_once "simplepie/simplepie.inc"; + require_once "magpierss/rss_fetch.inc"; + require_once 'magpierss/rss_utils.inc'; + /** + * Print a timestamped debug message. + * + * @param string $msg The debug message. + * @return void + */ function _debug($msg) { $ts = strftime("%H:%M:%S", time()); + if (function_exists('posix_getpid')) { + $ts = "$ts/" . posix_getpid(); + } print "[$ts] $msg\n"; - } - + } // function _debug + + /** + * 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($link, $feed_id, $purge_interval, $debug = false) { if (!$purge_interval) $purge_interval = feed_purge_interval($link, $feed_id); @@ -153,8 +189,17 @@ if ($debug) { _debug("Purged feed $feed_id ($purge_interval): deleted $rows articles"); } - } - + } // function purge_feed + + /** + * Purge old posts from old feeds. + * + * @param mixed $link A database connection + * @param boolean $do_output Set to true to enable printed output, false by default. + * @param integer $limit The maximal number of removed posts. + * @access public + * @return void + */ function global_purge_old_posts($link, $do_output = false, $limit = false) { $random_qpart = sql_random_function(); @@ -204,7 +249,7 @@ _debug("Purged $rows orphaned posts."); } - } + } // function global_purge_old_posts function feed_purge_interval($link, $feed_id) { @@ -290,7 +335,7 @@ } $result = db_query($link, "SELECT feed_url,id, - SUBSTRING(last_updated,1,19) AS last_updated, + ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated, update_interval FROM ttrss_feeds WHERE owner_uid = '$user_id' ORDER BY $q_order"); @@ -354,9 +399,15 @@ } - // adapted from wordpress favicon plugin by Jeff Minard (http://thecodepro.com/) - // http://dev.wp-plugins.org/file/favatars/trunk/favatars.php - + /** + * 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) { if ($html = @fetch_file_contents($url)) { @@ -389,8 +440,15 @@ } else { return false; } - } + } // function get_favicon_url + /** + * Check if a link is a valid and working URL. + * + * @param mixed $link A URL to check + * @access public + * @return boolean True if the URL is valid, false otherwise. + */ function url_validate($link) { $url_parts = @parse_url($link); @@ -430,7 +488,7 @@ return false; } - } + } // function url_validate function check_feed_favicon($site_url, $feed, $link) { $favicon_url = get_favicon_url($site_url); @@ -460,27 +518,63 @@ function update_rss_feed($link, $feed_url, $feed, $ignore_daemon = false) { if (!$_GET["daemon"] && !$ignore_daemon) { - return; + return false; } if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) { _debug("update_rss_feed: start"); } - $result = db_query($link, "SELECT id,update_interval,auth_login,auth_pass,cache_images - FROM ttrss_feeds WHERE id = '$feed'"); + if (!$ignore_daemon) { + + if (DB_TYPE == "pgsql") { + $updstart_thresh_qpart = "(ttrss_feeds.last_update_started IS NULL OR ttrss_feeds.last_update_started < NOW() - INTERVAL '120 seconds')"; + } else { + $updstart_thresh_qpart = "(ttrss_feeds.last_update_started IS NULL OR ttrss_feeds.last_update_started < DATE_SUB(NOW(), INTERVAL 120 SECOND))"; + } + + $result = db_query($link, "SELECT id,update_interval,auth_login, + auth_pass,cache_images,update_method + FROM ttrss_feeds WHERE id = '$feed' AND $updstart_thresh_qpart"); + + } else { + + $result = db_query($link, "SELECT id,update_interval,auth_login, + auth_pass,cache_images,update_method + FROM ttrss_feeds WHERE id = '$feed'"); + + } if (db_num_rows($result) == 0) { if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) { - _debug("update_rss_feed: feed $feed [$feed_url] NOT FOUND"); + _debug("update_rss_feed: feed $feed [$feed_url] NOT FOUND/SKIPPED"); } - return; + return false; } + $update_method = db_fetch_result($result, 0, "update_method"); + + db_query($link, "UPDATE ttrss_feeds SET last_update_started = NOW() + WHERE id = '$feed'"); + $auth_login = db_fetch_result($result, 0, "auth_login"); $auth_pass = db_fetch_result($result, 0, "auth_pass"); - if (!ENABLE_SIMPLEPIE) { + if (ALLOW_SELECT_UPDATE_METHOD) { + if (ENABLE_SIMPLEPIE) { + $use_simplepie = $update_method != 1; + } else { + $use_simplepie = $update_method == 2; + } + } else { + $use_simplepie = ENABLE_SIMPLEPIE; + } + + if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) { + _debug("use simplepie: $use_simplepie (feed setting: $update_method)\n"); + } + + if (!$use_simplepie) { $auth_login = urlencode($auth_login); $auth_pass = urlencode($auth_pass); } @@ -512,7 +606,7 @@ error_reporting(0); } - if (!ENABLE_SIMPLEPIE) { + if (!$use_simplepie) { $rss = fetch_rss($fetch_url); } else { if (!is_dir(SIMPLEPIE_CACHE_DIR)) { @@ -521,7 +615,7 @@ $rss = new SimplePie(); $rss->set_useragent(SIMPLEPIE_USERAGENT . MAGPIE_USER_AGENT_EXT); -// $rss->set_timeout(MAGPIE_FETCH_TIME_OUT); +# $rss->set_timeout(10); $rss->set_feed_url($fetch_url); $rss->set_output_encoding('UTF-8'); @@ -556,7 +650,7 @@ $feed = db_escape_string($feed); - if (ENABLE_SIMPLEPIE) { + if ($use_simplepie) { $fetch_ok = !$rss->error(); } else { $fetch_ok = !!$rss; @@ -579,7 +673,7 @@ $owner_uid = db_fetch_result($result, 0, "owner_uid"); - if (ENABLE_SIMPLEPIE) { + if ($use_simplepie) { $site_url = $rss->get_link(); } else { $site_url = $rss->channel["link"]; @@ -595,7 +689,7 @@ if (!$registered_title || $registered_title == "[Unknown]") { - if (ENABLE_SIMPLEPIE) { + if ($use_simplepie) { $feed_title = db_escape_string($rss->get_title()); } else { $feed_title = db_escape_string($rss->channel["title"]); @@ -610,7 +704,7 @@ } // weird, weird Magpie - if (!ENABLE_SIMPLEPIE) { + if (!$use_simplepie) { if (!$site_url) $site_url = db_escape_string($rss->channel["link_"]); } @@ -621,7 +715,7 @@ // print "I: " . $rss->channel["image"]["url"]; - if (!ENABLE_SIMPLEPIE) { + if (!$use_simplepie) { $icon_url = $rss->image["url"]; } else { $icon_url = $rss->get_image_url(); @@ -636,32 +730,9 @@ _debug("update_rss_feed: loading filters..."); } - $filters = array(); - - $result = db_query($link, "SELECT reg_exp, - ttrss_filter_types.name AS name, - ttrss_filter_actions.name AS action, - inverse, - action_param - FROM ttrss_filters,ttrss_filter_types,ttrss_filter_actions WHERE - enabled = true AND - owner_uid = $owner_uid AND - ttrss_filter_types.id = filter_type AND - ttrss_filter_actions.id = action_id AND - (feed_id IS NULL OR feed_id = '$feed') ORDER BY reg_exp"); - - while ($line = db_fetch_assoc($result)) { - if (!$filters[$line["name"]]) $filters[$line["name"]] = array(); - - $filter["reg_exp"] = $line["reg_exp"]; - $filter["action"] = $line["action"]; - $filter["action_param"] = $line["action_param"]; - $filter["inverse"] = sql_bool_to_bool($line["inverse"]); - - array_push($filters[$line["name"]], $filter); - } + $filters = load_filters($link, $feed, $owner_uid); - if (ENABLE_SIMPLEPIE) { + if ($use_simplepie) { $iterator = $rss->get_items(); } else { $iterator = $rss->items; @@ -693,7 +764,12 @@ foreach ($iterator as $item) { - if (ENABLE_SIMPLEPIE) { + if ($_GET['xdebug']) { + print_r($item); + + } + + if ($use_simplepie) { $entry_guid = $item->get_id(); if (!$entry_guid) $entry_guid = $item->get_link(); if (!$entry_guid) $entry_guid = make_guid_from_title($item->get_title()); @@ -715,7 +791,7 @@ $entry_timestamp = ""; - if (ENABLE_SIMPLEPIE) { + if ($use_simplepie) { $entry_timestamp = strtotime($item->get_date()); } else { $rss_2_date = $item['pubdate']; @@ -741,13 +817,13 @@ $entry_timestamp_fmt = strftime("%Y/%m/%d %H:%M:%S", $entry_timestamp); - if (ENABLE_SIMPLEPIE) { + if ($use_simplepie) { $entry_title = $item->get_title(); } else { $entry_title = trim(strip_tags($item["title"])); } - if (ENABLE_SIMPLEPIE) { + if ($use_simplepie) { $entry_link = $item->get_link(); } else { // strange Magpie workaround @@ -763,13 +839,18 @@ $entry_link = strip_tags($entry_link); - if (ENABLE_SIMPLEPIE) { - $entry_content = $item->get_description(); + if ($use_simplepie) { + $entry_content = $item->get_content(); + if (!$entry_content) $entry_content = $item->get_description(); } else { $entry_content = $item["content:escaped"]; if (!$entry_content) $entry_content = $item["content:encoded"]; if (!$entry_content) $entry_content = $item["content"]; + + // Magpie bugs are getting ridiculous + if (trim($entry_content) == "Array") $entry_content = false; + if (!$entry_content) $entry_content = $item["atom_content"]; if (!$entry_content) $entry_content = $item["summary"]; if (!$entry_content) $entry_content = $item["description"]; @@ -778,20 +859,24 @@ if (is_array($entry_content)) { $entry_content = $entry_content["encoded"]; if (!$entry_content) $entry_content = $entry_content["escaped"]; - } + } } -// print_r($item); -// print_r(htmlspecialchars($entry_content)); -// print "
"; + if ($_GET["xdebug"]) { + print "update_rss_feed: content: "; + print_r(htmlspecialchars($entry_content)); + } $entry_content_unescaped = $entry_content; - if (ENABLE_SIMPLEPIE) { + if ($use_simplepie) { $entry_comments = strip_tags($item->data["comments"]); if ($item->get_author()) { $entry_author_item = $item->get_author(); - $entry_author = $entry_author_item->get_name(); + $entry_author = $entry_author_item->get_name(); + if (!$entry_author) $entry_author = $entry_author_item->get_email(); + + $entry_author = db_escape_string($entry_author); } } else { $entry_comments = strip_tags($item["comments"]); @@ -820,6 +905,7 @@ if (preg_match('/^[\t\n\r ]*$/', $entry_author)) $entry_author = ''; $entry_guid = db_escape_string(strip_tags($entry_guid)); + $entry_guid = mb_substr($entry_guid, 0, 250); $result = db_query($link, "SELECT id FROM ttrss_entries WHERE guid = '$entry_guid'"); @@ -833,7 +919,7 @@ $entry_comments = mb_substr(db_escape_string($entry_comments), 0, 250); $entry_author = mb_substr($entry_author, 0, 250); - if (ENABLE_SIMPLEPIE) { + if ($use_simplepie) { $num_comments = 0; #FIXME# } else { $num_comments = db_escape_string($item["slash"]["comments"]); @@ -843,11 +929,11 @@ // parse entries into tags - if (ENABLE_SIMPLEPIE) { + if ($use_simplepie) { $additional_tags = array(); $additional_tags_src = $item->get_categories(); - + if (is_array($additional_tags_src)) { foreach ($additional_tags_src as $tobj) { array_push($additional_tags, $tobj->get_term()); @@ -867,14 +953,21 @@ if ($t_ctr == 0) { $additional_tags = false; - } else if ($t_ctr == 1) { + } else if ($t_ctr > 0) { $additional_tags = array($item['category']); - } else { - $additional_tags = array(); + + if ($item['category@term']) { + array_push($additional_tags, $item['category@term']); + } + for ($i = 0; $i <= $t_ctr; $i++ ) { if ($item["category#$i"]) { array_push($additional_tags, $item["category#$i"]); } + + if ($item["category#$i@term"]) { + array_push($additional_tags, $item["category#$i@term"]); + } } } @@ -882,10 +975,9 @@ $t_ctr = $item['dc']['subject#']; - if ($t_ctr == 1) { + if ($t_ctr > 0) { $additional_tags = array($item['dc']['subject']); - } else if ($t_ctr > 1) { - $additional_tags = array(); + for ($i = 0; $i <= $t_ctr; $i++ ) { if ($item['dc']["subject#$i"]) { array_push($additional_tags, $item['dc']["subject#$i"]); @@ -894,9 +986,49 @@ } } + // enclosures + + $enclosures = array(); + + if ($use_simplepie) { + $encs = $item->get_enclosures(); + + if (is_array($encs)) { + foreach ($encs as $e) { + $e_item = array( + $e->link, $e->type, $e->length); + + array_push($enclosures, $e_item); + } + } + + } else { + $e_ctr = $item['enclosure#']; + + if ($e_ctr > 0) { + $e_item = array($item['enclosure@url'], + $item['enclosure@type'], + $item['enclosure@length']); + + array_push($enclosures, $e_item); + + for ($i = 0; $i <= $e_ctr; $i++ ) { + + if ($item["enclosure#$i@url"]) { + $e_item = array($item["enclosure#$i@url"], + $item["enclosure#$i@type"], + $item["enclosure#$i@length"]); + array_push($enclosures, $e_item); + } + } + } + + } + # sanitize content -// $entry_content = sanitize_rss($entry_content); + $entry_content = sanitize_article_content($entry_content); + $entry_title = sanitize_article_content($entry_title); if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) { _debug("update_rss_feed: done collecting data [TITLE:$entry_title]"); @@ -953,13 +1085,16 @@ $result = db_query($link, "SELECT id,content_hash,no_orig_date,title, - substring(date_entered,1,19) as date_entered, - substring(updated,1,19) as updated, + ".SUBSTRING_FOR_DATE."(date_entered,1,19) as date_entered, + ".SUBSTRING_FOR_DATE."(updated,1,19) as updated, num_comments FROM ttrss_entries WHERE guid = '$entry_guid'"); + $entry_ref_id = 0; + $entry_int_id = 0; + if (db_num_rows($result) == 1) { if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) { @@ -974,6 +1109,7 @@ 0, "date_entered")); $ref_id = db_fetch_result($result, 0, "id"); + $entry_ref_id = $ref_id; // check for user post link to main table @@ -1002,8 +1138,14 @@ // error_reporting (DEFAULT_ERROR_LEVEL); + $score = calculate_article_score($article_filters); + + if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) { + _debug("update_rss_feed: initial score: $score"); + } + $result = db_query($link, - "SELECT ref_id FROM ttrss_user_entries WHERE + "SELECT ref_id, int_id FROM ttrss_user_entries WHERE ref_id = '$ref_id' AND owner_uid = '$owner_uid' $dupcheck_qpart"); @@ -1014,7 +1156,7 @@ _debug("update_rss_feed: user record not found, creating..."); } - if (!find_article_filter($article_filters, 'catchup')) { + if ($score >= -500 && !find_article_filter($article_filters, 'catchup')) { $unread = 'true'; $last_read_qpart = 'NULL'; } else { @@ -1022,7 +1164,7 @@ $last_read_qpart = 'NOW()'; } - if (find_article_filter($article_filters, 'mark')) { + if (find_article_filter($article_filters, 'mark') || $score > 1000) { $marked = 'true'; } else { $marked = 'false'; @@ -1036,11 +1178,28 @@ $result = db_query($link, "INSERT INTO ttrss_user_entries - (ref_id, owner_uid, feed_id, unread, last_read, marked, published) + (ref_id, owner_uid, feed_id, unread, last_read, marked, + published, score) VALUES ('$ref_id', '$owner_uid', '$feed', $unread, - $last_read_qpart, $marked, $published)"); + $last_read_qpart, $marked, $published, '$score')"); + + $result = db_query($link, + "SELECT int_id FROM ttrss_user_entries WHERE + ref_id = '$ref_id' AND owner_uid = '$owner_uid' AND + feed_id = '$feed' LIMIT 1"); + + if (db_num_rows($result) == 1) { + $entry_int_id = db_fetch_result($result, 0, "int_id"); + } + } else { + $entry_ref_id = db_fetch_result($result, 0, "ref_id"); + $entry_int_id = db_fetch_result($result, 0, "int_id"); } - + + if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) { + _debug("update_rss_feed: RID: $entry_ref_id, IID: $entry_int_id"); + } + $post_needs_update = false; if (get_pref($link, "UPDATE_POST_ON_CHECKSUM_CHANGE", $owner_uid, false) && @@ -1092,6 +1251,33 @@ db_query($link, "COMMIT"); + if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) { + _debug("update_rss_feed: looking for enclosures..."); + } + + if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) { + print_r($enclosures); + } + + db_query($link, "BEGIN"); + + foreach ($enclosures as $enc) { + $enc_url = db_escape_string($enc[0]); + $enc_type = db_escape_string($enc[1]); + $enc_dur = db_escape_string($enc[2]); + + $result = db_query($link, "SELECT id FROM ttrss_enclosures + WHERE content_url = '$enc_url' AND post_id = '$entry_ref_id'"); + + if (db_num_rows($result) == 0) { + db_query($link, "INSERT INTO ttrss_enclosures + (content_url, content_type, title, duration, post_id) VALUES + ('$enc_url', '$enc_type', '', '$enc_dur', '$entry_ref_id')"); + } + } + + db_query($link, "COMMIT"); + if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) { _debug("update_rss_feed: looking for tags..."); } @@ -1147,17 +1333,6 @@ db_query($link, "BEGIN"); - $result = db_query($link, "SELECT id,int_id - FROM ttrss_entries,ttrss_user_entries - WHERE guid = '$entry_guid' - AND feed_id = '$feed' AND ref_id = id - AND owner_uid = '$owner_uid'"); - - if (db_num_rows($result) == 1) { - - $entry_id = db_fetch_result($result, 0, "id"); - $entry_int_id = db_fetch_result($result, 0, "int_id"); - foreach ($entry_tags as $tag) { $tag = sanitize_tag($tag); @@ -1178,7 +1353,7 @@ VALUES ('$owner_uid','$tag', '$entry_int_id')"); } } - } + db_query($link, "COMMIT"); } @@ -1194,7 +1369,7 @@ } else { - if (ENABLE_SIMPLEPIE) { + if ($use_simplepie) { $error_msg = mb_substr($rss->error(), 0, 250); } else { $error_msg = mb_substr(magpie_error(), 0, 250); @@ -1211,7 +1386,7 @@ last_updated = NOW() WHERE id = '$feed'"); } - if (ENABLE_SIMPLEPIE) { + if ($use_simplepie) { unset($rss); } @@ -1319,6 +1494,18 @@ return false; } + function calculate_article_score($filters) { + $score = 0; + + foreach ($filters as $f) { + if ($f[0] == "score") { + $score += $f[1]; + }; + } + return $score; + } + + function printFeedEntry($feed_id, $class, $feed_title, $unread, $icon_file, $link, $rtl_content = false, $last_updated = false, $last_error = false) { @@ -1471,10 +1658,15 @@ $pwd_hash1 = encrypt_password($password); $pwd_hash2 = encrypt_password($password, $login); - if ($force_auth && defined('_DEBUG_USER_SWITCH')) { + if (defined('ALLOW_REMOTE_USER_AUTH') && ALLOW_REMOTE_USER_AUTH + && $_SERVER["REMOTE_USER"]) { + + $login = db_escape_string($_SERVER["REMOTE_USER"]); + $query = "SELECT id,login,access_level FROM ttrss_users WHERE - login = '$login'"; + login = '$login'"; + } else { $query = "SELECT id,login,access_level,pwd_hash FROM ttrss_users WHERE @@ -1761,7 +1953,7 @@ function file_is_locked($filename) { if (function_exists('flock')) { error_reporting(0); - $fp = fopen($filename, "r"); + $fp = fopen(LOCK_DIRECTORY . "/$filename", "r"); error_reporting(DEFAULT_ERROR_LEVEL); if ($fp) { if (flock($fp, LOCK_EX | LOCK_NB)) { @@ -1771,13 +1963,15 @@ } fclose($fp); return true; + } else { + return false; } } - return false; + return true; // consider the file always locked and skip the test } function make_lockfile($filename) { - $fp = fopen($filename, "w"); + $fp = fopen(LOCK_DIRECTORY . "/$filename", "w"); if (flock($fp, LOCK_EX | LOCK_NB)) { return $fp; @@ -1787,7 +1981,7 @@ } function make_stampfile($filename) { - $fp = fopen($filename, "w"); + $fp = fopen(LOCK_DIRECTORY . "/$filename", "w"); if (flock($fp, LOCK_EX | LOCK_NB)) { fwrite($fp, time() . "\n"); @@ -1802,14 +1996,18 @@ function read_stampfile($filename) { error_reporting(0); - $fp = fopen($filename, "r"); + $fp = fopen(LOCK_DIRECTORY . "/$filename", "r"); error_reporting (DEFAULT_ERROR_LEVEL); - if (flock($fp, LOCK_EX)) { - $stamp = fgets($fp); - flock($fp, LOCK_UN); - fclose($fp); - return $stamp; + if ($fp) { + if (flock($fp, LOCK_EX)) { + $stamp = fgets($fp); + flock($fp, LOCK_UN); + fclose($fp); + return $stamp; + } else { + return false; + } } else { return false; } @@ -2415,7 +2613,7 @@ $old_counters = $_SESSION["fctr_last_value"]; /* $result = db_query($link, "SELECT id,last_error,parent_feed, - SUBSTRING(last_updated,1,19) AS last_updated, + ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated, (SELECT count(id) FROM ttrss_entries,ttrss_user_entries WHERE feed_id = ttrss_feeds.id AND @@ -2426,7 +2624,7 @@ $query = "SELECT ttrss_feeds.id, ttrss_feeds.title, - SUBSTRING(ttrss_feeds.last_updated,1,19) AS last_updated, + ".SUBSTRING_FOR_DATE."(ttrss_feeds.last_updated,1,19) AS last_updated, last_error, COUNT(ttrss_entries.id) AS count FROM ttrss_feeds @@ -2668,7 +2866,7 @@ } else if ($id == -3) { return __("Fresh articles"); } else if ($id < -10) { - $label_id = -10 - $id; + $label_id = -$id - 11; $result = db_query($link, "SELECT description FROM ttrss_labels WHERE id = '$label_id'"); if (db_num_rows($result) == 1) { return db_fetch_result($result, 0, "description"); @@ -2743,6 +2941,12 @@ print ""; + print ""; + + print ""; + print ""; } @@ -2949,7 +3153,7 @@ } else if ($feed == -3) { // fresh virtual feed $query_strategy_part = "unread = true"; - $intl = get_pref($link, "FRESH_ARTICLE_MAX_AGE"); + $intl = get_pref($link, "FRESH_ARTICLE_MAX_AGE", $owner_uid); if (DB_TYPE == "pgsql") { $query_strategy_part .= " AND date_entered > NOW() - INTERVAL '$intl hour' "; @@ -2975,12 +3179,14 @@ $query_strategy_part = "id > 0"; // dumb } - if (get_pref($link, 'REVERSE_HEADLINES')) { + if (get_pref($link, 'REVERSE_HEADLINES', $owner_uid)) { $order_by = "updated"; } else { $order_by = "updated DESC"; } + $order_by = "score DESC, $order_by"; + if ($override_order) { $order_by = $override_order; } @@ -3025,10 +3231,13 @@ } else if ($feed == -1) { $feed_title = __("Starred articles"); + if ($search) { $feed_title = __("Searched for") . " $search ($feed_title)"; } } else if ($feed == -2) { $feed_title = __("Published articles"); + if ($search) { $feed_title = __("Searched for") . " $search ($feed_title)"; } } else if ($feed == -3) { $feed_title = __("Fresh articles"); + if ($search) { $feed_title = __("Searched for") . " $search ($feed_title)"; } } else if ($feed < -10) { $label_id = -$feed - 11; $result = db_query($link, "SELECT description FROM ttrss_labels @@ -3058,20 +3267,35 @@ $offset_query_part = "OFFSET $offset"; } + if ($vfeed_query_part && get_pref($link, 'VFEED_GROUP_BY_FEED', $owner_uid)) { + if (!$override_order) { + $order_by = "ttrss_feeds.title, $order_by"; + } + + if ($feed == -3) { + $group_limit_part = "(select count(*) from + ttrss_user_entries AS t1, ttrss_entries AS t2 where + t1.ref_id = t2.id and t1.owner_uid = 2 and + t1.feed_id = ttrss_user_entries.feed_id and + t2.updated > ttrss_entries.updated) <= 5 AND"; + } + } + $query = "SELECT guid, ttrss_entries.id,ttrss_entries.title, updated, unread,feed_id,marked,published,link,last_read, - SUBSTRING(last_read,1,19) as last_read_noms, + ".SUBSTRING_FOR_DATE."(last_read,1,19) as last_read_noms, $vfeed_query_part $content_query_part - SUBSTRING(updated,1,19) as updated_noms, - author + ".SUBSTRING_FOR_DATE."(updated,1,19) as updated_noms, + author,score FROM ttrss_entries,ttrss_user_entries,ttrss_feeds WHERE - ttrss_feeds.hidden = false AND + $group_limit_part + ttrss_feeds.hidden = false AND ttrss_user_entries.feed_id = ttrss_feeds.id AND ttrss_user_entries.ref_id = ttrss_entries.id AND ttrss_user_entries.owner_uid = '$owner_uid' AND @@ -3095,14 +3319,14 @@ updated, unread,feed_id, marked,link,last_read, - SUBSTRING(last_read,1,19) as last_read_noms, + ".SUBSTRING_FOR_DATE."(last_read,1,19) as last_read_noms, $vfeed_query_part $content_query_part - SUBSTRING(updated,1,19) as updated_noms + ".SUBSTRING_FOR_DATE."(updated,1,19) as updated_noms FROM ttrss_entries,ttrss_user_entries,ttrss_tags WHERE - ref_id = ttrss_entries.id AND + ref_id = ttrss_entries.id AND ttrss_user_entries.owner_uid = '$owner_uid' AND post_int_id = int_id AND tag_name = '$feed' AND $view_query_part @@ -3221,6 +3445,13 @@ return $res; } + /** + * Send by mail a digest of last articles. + * + * @param mixed $link The database connection. + * @param integer $limit The maximum number of articles by digest. + * @return boolean Return false if digests are not enabled. + */ function send_headlines_digests($link, $limit = 100) { if (!DIGEST_ENABLE) return false; @@ -3330,7 +3561,7 @@ ttrss_user_entries.ref_id, link, SUBSTRING(content, 1, 120) AS excerpt, - SUBSTRING(last_updated,1,19) AS last_updated + ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated FROM ttrss_user_entries,ttrss_entries,ttrss_feeds WHERE @@ -3566,7 +3797,8 @@ function print_headline_subtoolbar($link, $feed_site_url, $feed_title, $bottom = false, $rtl_content = false, $feed_id = 0, $is_cat = false, $search = false, $match_on = false, - $search_mode = false, $offset = 0, $limit = 0) { + $search_mode = false, $offset = 0, $limit = 0, + $dashboard_menu = 0, $disable_feed = 0, $feed_small_icon = 0) { $user_page_offset = $offset + 1; @@ -3617,92 +3849,102 @@ } - if (strpos($_SESSION["client.userAgent"], "MSIE") === false) { - - print " - "; + print ""; + + } else { + // old style subtoolbar: + + print "". + __('Select:')." + ".__('All').", + ".__('Unread').", + ".__('None')." +   ". + __('Toggle:')." ".__('Unread').", + ".__('Starred')." +   ". + __('Mark as read:')." + ".__('Page').", + ".__('Feed').""; + + if ($search && $feed_id >= 0 && get_pref($link, 'ENABLE_LABELS') && GLOBAL_ENABLE_LABELS) { + + print "   + + ".__('Convert to label').""; + } + + print ""; + + } + } else { // dashboard menu actions - print ""; - + // not implemented + print ""; } -/* if ($search && $feed_id >= 0 && get_pref($link, 'ENABLE_LABELS') && GLOBAL_ENABLE_LABELS) { - print " - - ".__('Convert to Label').""; -} */ - print ""; - print ""; + print "Search: "; + + print ""; if ($feed_site_url) { if (!$bottom) { @@ -3722,17 +3964,19 @@ print " [$user_page_offset] "; } - print ""; - - if (!$bottom) { + if (!$bottom && !$disable_feed) { print " \"".__('Generated "; + } else if ($feed_small_icon) { + print "\"\""; } - + + print ""; + print ""; print ""; @@ -3808,6 +4052,11 @@ printCategoryHeader($link, -1, $cat_hidden, false); } + if (defined('_ENABLE_DASHBOARD')) { + printFeedEntry(-4, "virt", __("Dashboard"), 0, + "images/tag.png", $link); + } + $num_starred = getFeedUnread($link, -1); $num_published = getFeedUnread($link, -2); $num_fresh = getFeedUnread($link, -3); @@ -3923,7 +4172,7 @@ $age_qpart = getMaxAgeSubquery(); $result = db_query($link, "SELECT ttrss_feeds.*, - SUBSTRING(last_updated,1,19) AS last_updated_noms, + ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated_noms, (SELECT COUNT(id) FROM ttrss_entries,ttrss_user_entries WHERE feed_id = ttrss_feeds.id AND unread = true AND $age_qpart @@ -4058,7 +4307,7 @@ } printFeedEntry($feed_id, $class, $feed, $unread, - ICONS_DIR."/$feed_id.ico", $link, $rtl_content, + ICONS_URL."/$feed_id.ico", $link, $rtl_content, $last_updated, $line["last_error"]); ++$lnum; @@ -4255,7 +4504,7 @@ } $result = db_query($link, "SELECT title,link,content,feed_id,comments,int_id, - SUBSTRING(updated,1,16) as updated, + ".SUBSTRING_FOR_DATE."(updated,1,16) as updated, (SELECT icon_url FROM ttrss_feeds WHERE id = feed_id) as icon_url, num_comments, author @@ -4307,7 +4556,7 @@ $entry_author = $line["author"]; if ($entry_author) { - $entry_author = __(" - by ") . $entry_author; + $entry_author = __(" - ") . $entry_author; } $parsed_updated = date(get_pref($link, 'LONG_DATE_FORMAT'), @@ -4384,7 +4633,43 @@ $line["content"] = preg_replace("/href=/i", "target=\"_new\" href=", $line["content"]); } - print $line["content"] . ""; + print $line["content"]; + + $result = db_query($link, "SELECT * FROM ttrss_enclosures WHERE + post_id = '$id' AND content_url != ''"); + + if (db_num_rows($result) > 0) { + print "
"; + + if (db_num_rows($result) == 1) { + print __("Attachment:") . " "; + } else { + print __("Attachments:") . " "; + } + + $entries = array(); + + while ($line = db_fetch_assoc($result)) { + + $url = $line["content_url"]; + $ctype = $line["content_type"]; + + if (!$ctype) $ctype = __("unknown type"); + + $filename = substr($url, strrpos($url, "/")+1); + + $entry = "" . + $filename . " (" . $ctype . ")" . ""; + + array_push($entries, $entry); + } + + print join(", ", $entries); + + print "
"; + } + + print ""; print ""; @@ -4395,7 +4680,9 @@ } function outputHeadlinesList($link, $feed, $subop, $view_mode, $limit, $cat_view, - $next_unread_feed, $offset) { + $next_unread_feed, $offset, $vgr_last_feed = false) { + + $disable_cache = false; $timing_info = getmicrotime(); @@ -4407,6 +4694,8 @@ if ($subop == "undefined") $subop = ""; + $subop_split = split(":", $subop); + if ($subop == "CatchupSelected") { $ids = split(",", db_escape_string($_GET["ids"])); $cmode = sprintf("%d", $_GET["cmode"]); @@ -4428,6 +4717,11 @@ } } + if ($subop_split[0] == "MarkAllReadGR") { + catchup_feed($link, $subop_split[1], false); + } + + if ($feed_id > 0) { $result = db_query($link, "SELECT id FROM ttrss_feeds WHERE id = '$feed' LIMIT 1"); @@ -4464,6 +4758,11 @@ /// START ///////////////////////////////////////////////////////////////////////////////// $search = db_escape_string($_GET["query"]); + + if ($search) { + $disable_cache = true; + } + $search_mode = db_escape_string($_GET["search_mode"]); $match_on = db_escape_string($_GET["match_on"]); @@ -4485,6 +4784,8 @@ $feed_site_url = $qfh_ret[2]; $last_error = $qfh_ret[3]; + $vgroup_last_feed = $vgr_last_feed; + if ($feed == -2) { $feed_site_url = article_publish_url($link); } @@ -4522,7 +4823,8 @@ error_reporting (DEFAULT_ERROR_LEVEL); $num_unread = 0; - + $cur_feed_title = ''; + while ($line = db_fetch_assoc($result)) { $class = ($lnum % 2) ? "even" : "odd"; @@ -4601,13 +4903,45 @@ 100); } + $score = $line["score"]; + + $score_pic = get_score_pic($score); + + $score_title = __("(Click to change)"); + + $score_pic = ""; + + if ($score > 500) { + $hlc_suffix = "H"; + } else if ($score < -100) { + $hlc_suffix = "L"; + } else { + $hlc_suffix = ""; + } + $entry_author = $line["author"]; if ($entry_author) { - $entry_author = " - by $entry_author"; + $entry_author = " - $entry_author"; } if (!get_pref($link, 'COMBINED_DISPLAY_MODE')) { + + if (get_pref($link, 'VFEED_GROUP_BY_FEED')) { + if ($feed_id != $vgroup_last_feed) { + + $cur_feed_title = $line["feed_title"]; + $vgroup_last_feed = $feed_id; + + + $vf_catchup_link = "(mark as read)"; + + print "". + "". + $line["feed_title"]." $vf_catchup_link:"; + } + } print ""; @@ -4628,9 +4962,9 @@ # truncate_string($line["feed_title"],30)." "; # } else { - print ""; + print ""; - print "" . + print "" . $line["title"]; if (get_pref($link, 'SHOW_CONTENT_PREVIEW')) { @@ -4644,11 +4978,13 @@ # ". # $line["feed_title"]." - if ($line["feed_title"]) { - print " - (". - $line["feed_title"].") - "; + if (!get_pref($link, 'VFEED_GROUP_BY_FEED')) { + if ($line["feed_title"]) { + print " + (". + $line["feed_title"].") + "; + } } @@ -4656,12 +4992,28 @@ # } - print "$updated_fmt "; - + print "$updated_fmt "; + + print "$score_pic"; + print ""; } else { - + + if (get_pref($link, 'VFEED_GROUP_BY_FEED')) { + if ($feed_id != $vgroup_last_feed) { + + $cur_feed_title = $line["feed_title"]; + $vgroup_last_feed = $feed_id; + + $vf_catchup_link = "(mark as read)"; + + print "
". + "". + $line["feed_title"]." $vf_catchup_link
"; + } + } + if ($is_unread) { $add_class = "Unread"; } else { @@ -4670,7 +5022,7 @@ $expand_cdm = get_pref($link, 'CDM_EXPANDED'); - if ($expand_cdm) { + if ($expand_cdm && $score >= -100) { $cdm_cstyle = ""; } else { $cdm_cstyle = "style=\"display : none\""; @@ -4678,30 +5030,34 @@ print "
"; print "
"; - print "
$updated_fmt
"; - - print "$updated_fmt $score_pic
"; + + print "".$line["title"].""; + target=\"_blank\" href=\"".$line["link"]."\">".$line["title"]." + "; print $entry_author; - if (!$expand_cdm) { + if (!$expand_cdm || $score < -100) { print "  (".__('Show article').")"; } - if ($line["feed_title"]) { - print " (".$line["feed_title"].")"; + if (!get_pref($link, 'VFEED_GROUP_BY_FEED')) { + if ($line["feed_title"]) { + print " (".$line["feed_title"].")"; + } } - print "
"; + print ""; if (get_pref($link, 'OPEN_LINKS_IN_NEW_WINDOW')) { $line["content_preview"] = preg_replace("/href=/i", @@ -4711,7 +5067,42 @@ print "
"; // print "
"; + print $line["content_preview"]; + + $e_result = db_query($link, "SELECT * FROM ttrss_enclosures WHERE + post_id = '$id' AND content_url != ''"); + + if (db_num_rows($e_result) > 0) { + print "
"; + + if (db_num_rows($e_result) == 1) { + print __("Attachment:") . " "; + } else { + print __("Attachments:") . " "; + } + + $entries = array(); + + while ($e_line = db_fetch_assoc($e_result)) { + + $url = $e_line["content_url"]; + $ctype = $e_line["content_type"]; + if (!$ctype) $ctype = __("unknown type"); + + $filename = substr($url, strrpos($url, "/")+1); + + $entry = "" . + $filename . " (" . $ctype . ")" . ""; + + array_push($entries, $entry); + } + + print join(", ", $entries); + + print "
"; + } + print "
"; // print "
"; @@ -4790,7 +5181,20 @@ } else { - if (!$offset) print "
".__('No articles found.')."
"; + $message = ""; + + switch ($view_mode) { + case "unread": + $message = __("No unread articles found to display."); + break; + case "marked": + $message = __("No starred articles found to display."); + break; + default: + $message = __("No articles found to display."); + } + + if (!$offset) print "
$message
"; } if (!$offset) { @@ -4798,7 +5202,7 @@ print "
"; } - return array($topmost_article_ids, $headlines_count); + return array($topmost_article_ids, $headlines_count, $feed, $disable_cache, $vgroup_last_feed); } // from here: http://www.roscripts.com/Create_tag_cloud-71.html @@ -4897,33 +5301,246 @@ function article_publish_url($link) { - $url_path = 'http://' . $_SERVER["HTTP_HOST"] . parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH); + $url_path = ($_SERVER['HTTPS'] != "on" ? 'http://' : 'https://') . $_SERVER["HTTP_HOST"] . parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH); $url_path .= "?op=publish&key=" . get_pref($link, "_PREFS_PUBLISH_KEY"); return $url_path; } + /** + * Purge a feed contents, marked articles excepted. + * + * @param mixed $link The database connection. + * @param integer $id The id of the feed to purge. + * @return void + */ function clear_feed_articles($link, $id) { $result = db_query($link, "DELETE FROM ttrss_user_entries WHERE feed_id = '$id' AND marked = false AND owner_uid = " . $_SESSION["uid"]); $result = db_query($link, "DELETE FROM ttrss_entries WHERE (SELECT COUNT(int_id) FROM ttrss_user_entries WHERE ref_id = id) = 0"); - } - - function add_feed_url() { - $url_path = 'http://' . $_SERVER["HTTP_HOST"] . parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH); + } // function clear_feed_articles + + /** + * Compute the Mozilla Firefox feed adding URL from server HOST and REQUEST_URI. + * + * @return string The Mozilla Firefox feed adding URL. + */ + function add_feed_url() { + $url_path = ($_SERVER['HTTPS'] != "on" ? 'http://' : 'https://') . $_SERVER["HTTP_HOST"] . parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH); $url_path .= "?op=pref-feeds&quiet=1&subop=add&feed_url=%s"; return $url_path; - } - + } // function add_feed_url + + /** + * Encrypt a password in SHA1. + * + * @param string $pass The password to encrypt. + * @param string $login A optionnal login. + * @return string The encrypted password. + */ function encrypt_password($pass, $login = '') { if ($login) { return "SHA1X:" . sha1("$login:$pass"); } else { return "SHA1:" . sha1($pass); } + } // function encrypt_password + + /** + * Update a feed batch. + * Used by daemons to update n feeds by run. + * Only update feed needing a update, and not being processed + * by another process. + * + * @param mixed $link Database link + * @param integer $limit Maximum number of feeds in update batch. Default to DAEMON_FEED_LIMIT. + * @param boolean $from_http Set to true if you call this function from http to disable cli specific code. + * @param boolean $debug Set to false to disable debug output. Default to true. + * @return void + */ + function update_daemon_common($link, $limit = DAEMON_FEED_LIMIT, $from_http = false, $debug = true) { + // Process all other feeds using last_updated and interval parameters + + // Test if the user has loggued in recently. If not, it does not update its feeds. + if (DAEMON_UPDATE_LOGIN_LIMIT > 0) { + if (DB_TYPE == "pgsql") { + $login_thresh_qpart = "AND ttrss_users.last_login >= NOW() - INTERVAL '".DAEMON_UPDATE_LOGIN_LIMIT." days'"; + } else { + $login_thresh_qpart = "AND ttrss_users.last_login >= DATE_SUB(NOW(), INTERVAL ".DAEMON_UPDATE_LOGIN_LIMIT." DAY)"; + } + } else { + $login_thresh_qpart = ""; + } + + // Test if the feed need a update (update interval exceded). + if (DB_TYPE == "pgsql") { + $update_limit_qpart = "AND (( + ttrss_feeds.update_interval = 0 + AND ttrss_feeds.last_updated < NOW() - CAST((ttrss_user_prefs.value || ' minutes') AS INTERVAL) + ) OR ( + ttrss_feeds.update_interval > 0 + AND ttrss_feeds.last_updated < NOW() - CAST((ttrss_feeds.update_interval || ' minutes') AS INTERVAL) + ) OR ttrss_feeds.last_updated IS NULL)"; + } else { + $update_limit_qpart = "AND (( + ttrss_feeds.update_interval = 0 + AND ttrss_feeds.last_updated < DATE_SUB(NOW(), INTERVAL CONVERT(ttrss_user_prefs.value, SIGNED INTEGER) MINUTE) + ) OR ( + ttrss_feeds.update_interval > 0 + AND ttrss_feeds.last_updated < DATE_SUB(NOW(), INTERVAL ttrss_feeds.update_interval MINUTE) + ) OR ttrss_feeds.last_updated IS NULL)"; + } + + // Test if feed is currently being updated by another process. + if (DB_TYPE == "pgsql") { + $updstart_thresh_qpart = "AND (ttrss_feeds.last_update_started IS NULL OR ttrss_feeds.last_update_started < NOW() - INTERVAL '120 seconds')"; + } else { + $updstart_thresh_qpart = "AND (ttrss_feeds.last_update_started IS NULL OR ttrss_feeds.last_update_started < DATE_SUB(NOW(), INTERVAL 120 SECOND))"; + } + + // Test if there is a limit to number of updated feeds + $query_limit = ""; + if($limit) $query_limit = sprintf("LIMIT %d", $limit); + + $random_qpart = sql_random_function(); + + // We search for feed needing update. + $result = db_query($link, "SELECT ttrss_feeds.feed_url,ttrss_feeds.id, ttrss_feeds.owner_uid, + ".SUBSTRING_FOR_DATE."(ttrss_feeds.last_updated,1,19) AS last_updated, + ttrss_feeds.update_interval + FROM + ttrss_feeds, ttrss_users, ttrss_user_prefs + WHERE + ttrss_feeds.owner_uid = ttrss_users.id + AND ttrss_users.id = ttrss_user_prefs.owner_uid + AND ttrss_user_prefs.pref_name = 'DEFAULT_UPDATE_INTERVAL' + $login_thresh_qpart $update_limit_qpart + $updstart_thresh_qpart + ORDER BY $random_qpart $query_limit"); + + $user_prefs_cache = array(); + + if($debug) _debug(sprintf("Scheduled %d feeds to update...\n", db_num_rows($result))); + + // Here is a little cache magic in order to minimize risk of double feed updates. + $feeds_to_update = array(); + while ($line = db_fetch_assoc($result)) { + $feeds_to_update[$line['id']] = $line; + } + + // We update the feed last update started date before anything else. + // There is no lag due to feed contents downloads + // It prevent an other process to update the same feed. + $feed_ids = array_keys($feeds_to_update); + if($feed_ids) { + db_query($link, sprintf("UPDATE ttrss_feeds SET last_update_started = NOW() + WHERE id IN (%s)", implode(',', $feed_ids))); + } + + // For each feed, we call the feed update function. + while ($line = array_pop($feeds_to_update)) { + + if($debug) _debug("Feed: " . $line["feed_url"] . ", " . $line["last_updated"]); + + // We setup a alarm to alert if the feed take more than 300s to update. + // => HANG alarm. + if(!$from_http && function_exists('pcntl_alarm')) pcntl_alarm(300); + update_rss_feed($link, $line["feed_url"], $line["id"], true); + // Cancel the alarm (the update went well) + if(!$from_http && function_exists('pcntl_alarm')) pcntl_alarm(0); + + sleep(1); // prevent flood (FIXME make this an option?) + } + + // Send feed digests by email if needed. + if (DAEMON_SENDS_DIGESTS) send_headlines_digests($link); + + } // function update_daemon_common + + function generate_dashboard_feed($link) { + + print "
"; + + print_headline_subtoolbar($link, "", "Dashboard", + false, false, -4, false, false, false, + false, 0, 0, true, true, "tag.png"); + + print "
"; + print "
There is 666 unread articles in 666 feeds.
"; + print "
"; + + print "
"; + + print "]]>"; + print ""; + print ""; + print ""; + + print ""; + print ""; + } + + function sanitize_article_content($text) { + # we don't support CDATA sections in articles, they break our own escaping + $text = preg_replace("/\[\[CDATA/", "", $text); + $text = preg_replace("/\]\]\>/", "", $text); + return $text; + } + + function load_filters($link, $feed, $owner_uid, $action_id = false) { + $filters = array(); + + if ($action_id) $ftype_query_part = "action_id = '$action_id' AND"; + + $result = db_query($link, "SELECT reg_exp, + ttrss_filter_types.name AS name, + ttrss_filter_actions.name AS action, + inverse, + action_param + FROM ttrss_filters,ttrss_filter_types,ttrss_filter_actions WHERE + enabled = true AND + $ftype_query_part + owner_uid = $owner_uid AND + ttrss_filter_types.id = filter_type AND + ttrss_filter_actions.id = action_id AND + (feed_id IS NULL OR feed_id = '$feed') ORDER BY reg_exp"); + + while ($line = db_fetch_assoc($result)) { + if (!$filters[$line["name"]]) $filters[$line["name"]] = array(); + $filter["reg_exp"] = $line["reg_exp"]; + $filter["action"] = $line["action"]; + $filter["action_param"] = $line["action_param"]; + $filter["inverse"] = sql_bool_to_bool($line["inverse"]); + + array_push($filters[$line["name"]], $filter); + } + + return $filters; + } + + function get_score_pic($score) { + if ($score > 0) { + return "score_high.png"; + } else if ($score < 0) { + return "score_low.png"; + } else { + return "score_neutral.png"; + } + } + + function rounded_table_start($classname, $header = " ") { + print ""; + print ""; + print ""; + print ""; + print "
 $header 
 "; + } + + function rounded_table_end($footer = " ") { + print " 
 $footer 
"; } ?>