diff --git a/backend.php b/backend.php index c8271f4f..ce2e73d8 100644 --- a/backend.php +++ b/backend.php @@ -145,432 +145,439 @@ if (!sanity_check($link)) { return; } - if ($op == "rpc") { - handle_rpc_request($link); - } - - if ($op == "feeds") { + switch($op) { // Select action according to $op value. + case "rpc": + // Handle remote procedure calls. + handle_rpc_request($link); + break; // rpc - $tags = $_GET["tags"]; + case "feeds": + $tags = $_GET["tags"]; - $subop = $_GET["subop"]; + $subop = $_GET["subop"]; - if ($subop == "catchupAll") { - db_query($link, "UPDATE ttrss_user_entries SET - last_read = NOW(),unread = false WHERE owner_uid = " . $_SESSION["uid"]); - } + switch($subop) { + case "catchupAll": + db_query($link, "UPDATE ttrss_user_entries SET + last_read = NOW(),unread = false WHERE owner_uid = " . $_SESSION["uid"]); + break; - if ($subop == "collapse") { - $cat_id = db_escape_string($_GET["cid"]); + case "collapse": + $cat_id = db_escape_string($_GET["cid"]); - db_query($link, "UPDATE ttrss_feed_categories SET - collapsed = NOT collapsed WHERE id = '$cat_id' AND owner_uid = " . - $_SESSION["uid"]); - return; - } - - outputFeedList($link, $tags); - - } - - if ($op == "view") { - - $id = db_escape_string($_GET["id"]); - $feed_id = db_escape_string($_GET["feed"]); - $cids = split(",", db_escape_string($_GET["cids"])); - $mode = db_escape_string($_GET["mode"]); - $omode = db_escape_string($_GET["omode"]); - - print ""; - - // in prefetch mode we only output requested cids, main article - // just gets marked as read (it already exists in client cache) - - if ($mode == "") { - outputArticleXML($link, $id, $feed_id); - } else { - catchupArticleById($link, $id, 0); - } - - foreach ($cids as $cid) { - if ($cid) { - outputArticleXML($link, $cid, $feed_id, false); + db_query($link, "UPDATE ttrss_feed_categories SET + collapsed = NOT collapsed WHERE id = '$cat_id' AND owner_uid = " . + $_SESSION["uid"]); + return; + break; } - } - if ($mode != "prefetch_old") { - print ""; - getAllCounters($link, $omode); - print ""; - } + outputFeedList($link, $tags); + break; // feeds - print ""; - } + case "view": - if ($op == "viewfeed") { + $id = db_escape_string($_GET["id"]); + $feed_id = db_escape_string($_GET["feed"]); + $cids = split(",", db_escape_string($_GET["cids"])); + $mode = db_escape_string($_GET["mode"]); + $omode = db_escape_string($_GET["omode"]); - $print_exec_time = true; - $timing_info = getmicrotime(); + print ""; - print ""; + // in prefetch mode we only output requested cids, main article + // just gets marked as read (it already exists in client cache) - if ($_GET["debug"]) $timing_info = print_checkpoint("0", $timing_info); - - $omode = db_escape_string($_GET["omode"]); - - $feed = db_escape_string($_GET["feed"]); - $subop = db_escape_string($_GET["subop"]); - $view_mode = db_escape_string($_GET["view_mode"]); - $limit = db_escape_string($_GET["limit"]); - $cat_view = db_escape_string($_GET["cat"]); - $next_unread_feed = db_escape_string($_GET["nuf"]); - $offset = db_escape_string($_GET["skip"]); - - set_pref($link, "_DEFAULT_VIEW_MODE", $view_mode); - set_pref($link, "_DEFAULT_VIEW_LIMIT", $limit); - - if (!$cat_view && preg_match("/^[0-9][0-9]*$/", $feed)) { - db_query($link, "UPDATE ttrss_feeds SET last_viewed = NOW() - WHERE id = '$feed' AND owner_uid = ".$_SESSION["uid"]); - } - - print ""; - - print ""; - - $headlines_unread = getFeedUnread($link, $returned_feed); - - print ""; - printf("", $disable_cache); - - if ($_GET["debug"]) $timing_info = print_checkpoint("10", $timing_info); - - if (is_array($topmost_article_ids) && !get_pref($link, 'COMBINED_DISPLAY_MODE')) { - print ""; - foreach ($topmost_article_ids as $id) { - outputArticleXML($link, $id, $feed, false); - } - print ""; - } - - if ($_GET["debug"]) $timing_info = print_checkpoint("20", $timing_info); - - print ""; - getAllCounters($link, $omode, $feed); - print ""; - - if ($_GET["debug"]) $timing_info = print_checkpoint("30", $timing_info); - - print_runtime_info($link); - - print ""; - } - - if ($op == "pref-feeds") { - module_pref_feeds($link); - } - - if ($op == "pref-filters") { - module_pref_filters($link); - } - - if ($op == "pref-labels") { - module_pref_labels($link); - } - - if ($op == "pref-prefs") { - module_pref_prefs($link); - } - - if ($op == "pref-users") { - module_pref_users($link); - } - - if ($op == "help") { - module_help($link); - } - - if ($op == "dlg") { - module_popup_dialog($link); - } - - if ($op == "pref-pub-items") { - module_pref_pub_items($link); - } - - - // update feeds of all users, may be used anonymously - if ($op == "globalUpdateFeeds") { - - $result = db_query($link, "SELECT id FROM ttrss_users"); - - while ($line = db_fetch_assoc($result)) { - $user_id = $line["id"]; -// print ""; - update_all_feeds($link, false, $user_id); - } - - print " - - "; - - } - - if ($op == "user-details") { - - if (WEB_DEMO_MODE || $_SESSION["access_level"] < 10) { - return; - } - -/* print " - Tiny Tiny RSS : User Details - - - "; */ - - $uid = sprintf("%d", $_GET["id"]); - - print "
User details
"; - - print "
"; - - $result = db_query($link, "SELECT login, - SUBSTRING(last_login,1,16) AS last_login, - access_level, - (SELECT COUNT(int_id) FROM ttrss_user_entries - WHERE owner_uid = id) AS stored_articles, - SUBSTRING(created,1,16) AS created - FROM ttrss_users - WHERE id = '$uid'"); - - if (db_num_rows($result) == 0) { - print "

User not found

"; - return; - } - -# print "

User Details

"; - - $login = db_fetch_result($result, 0, "login"); - -# print "

$login

"; - - print ""; - - $last_login = date(get_pref($link, 'LONG_DATE_FORMAT'), - strtotime(db_fetch_result($result, 0, "last_login"))); - - $created = date(get_pref($link, 'LONG_DATE_FORMAT'), - strtotime(db_fetch_result($result, 0, "created"))); - - $access_level = db_fetch_result($result, 0, "access_level"); - $stored_articles = db_fetch_result($result, 0, "stored_articles"); - -# print ""; -# print ""; - print ""; - print ""; - print ""; - - $result = db_query($link, "SELECT COUNT(id) as num_feeds FROM ttrss_feeds - WHERE owner_uid = '$uid'"); - - $num_feeds = db_fetch_result($result, 0, "num_feeds"); - - print ""; - -/* $result = db_query($link, "SELECT - SUM(LENGTH(content)+LENGTH(title)+LENGTH(link)+LENGTH(guid)) AS db_size - FROM ttrss_user_entries,ttrss_entries - WHERE owner_uid = '$uid' AND ref_id = id"); - - $db_size = round(db_fetch_result($result, 0, "db_size") / 1024); - - print ""; */ - - print "
Username$login
Access level$access_level
".__('Registered')."$created
".__('Last logged in')."$last_login
".__('Stored articles')."$stored_articles
".__('Subscribed feeds count')."$num_feeds
Approx. used DB size$db_size KBytes
"; - - print "

".__('Subscribed feeds')."

"; - - $result = db_query($link, "SELECT id,title,site_url FROM ttrss_feeds - WHERE owner_uid = '$uid' ORDER BY title"); - - print ""; + case "viewfeed": - print "
"; + $print_exec_time = true; + $timing_info = getmicrotime(); - print "
-
"; + print ""; -// print ""; + if ($_GET["debug"]) $timing_info = print_checkpoint("0", $timing_info); - } + $omode = db_escape_string($_GET["omode"]); - if ($op == "pref-feed-browser") { - module_pref_feed_browser($link); - } + $feed = db_escape_string($_GET["feed"]); + $subop = db_escape_string($_GET["subop"]); + $view_mode = db_escape_string($_GET["view_mode"]); + $limit = db_escape_string($_GET["limit"]); + $cat_view = db_escape_string($_GET["cat"]); + $next_unread_feed = db_escape_string($_GET["nuf"]); + $offset = db_escape_string($_GET["skip"]); - if ($op == "publish") { - $key = db_escape_string($_GET["key"]); + set_pref($link, "_DEFAULT_VIEW_MODE", $view_mode); + set_pref($link, "_DEFAULT_VIEW_LIMIT", $limit); - $result = db_query($link, "SELECT login, owner_uid - FROM ttrss_user_prefs, ttrss_users WHERE - pref_name = '_PREFS_PUBLISH_KEY' AND - value = '$key' AND - ttrss_users.id = owner_uid"); + if (!$cat_view && preg_match("/^[0-9][0-9]*$/", $feed)) { + db_query($link, "UPDATE ttrss_feeds SET last_viewed = NOW() + WHERE id = '$feed' AND owner_uid = ".$_SESSION["uid"]); + } + + print ""; + + print ""; + + $headlines_unread = getFeedUnread($link, $returned_feed); + + print ""; + printf("", $disable_cache); + + if ($_GET["debug"]) $timing_info = print_checkpoint("10", $timing_info); + + if (is_array($topmost_article_ids) && !get_pref($link, 'COMBINED_DISPLAY_MODE')) { + print ""; + foreach ($topmost_article_ids as $id) { + outputArticleXML($link, $id, $feed, false); + } + print ""; + } + + if ($_GET["debug"]) $timing_info = print_checkpoint("20", $timing_info); + + print ""; + getAllCounters($link, $omode, $feed); + print ""; + + if ($_GET["debug"]) $timing_info = print_checkpoint("30", $timing_info); + + print_runtime_info($link); + + print ""; + break; // viewfeed + + case "pref-feeds": + module_pref_feeds($link); + break; // pref-feeds + + case "pref-filters": + module_pref_filters($link); + break; // pref-filters + + case "pref-labels": + module_pref_labels($link); + break; // pref-labels + + case "pref-prefs": + module_pref_prefs($link); + break; // pref-prefs + + case "pref-users": + module_pref_users($link); + break; // prefs-users + + case "help": + module_help($link); + break; // help + + case "dlg": + module_popup_dialog($link); + break; // dlg + + case "pref-pub-items": + module_pref_pub_items($link); + break; // pref-pub-items + + case "globalUpdateFeeds": + // update feeds of all users, may be used anonymously + + // Update all feeds needing a update. + update_daemon_common($link, 0, true, false); + + // FIXME : old feed update way. To be removed. + //$result = db_query($link, "SELECT id FROM ttrss_users"); + + //while ($line = db_fetch_assoc($result)) { + // $user_id = $line["id"]; + // print ""; + // update_all_feeds($link, false, $user_id); + //} + + print " + + "; + break; // globalUpdateFeeds + + case "user-details": + + if (WEB_DEMO_MODE || $_SESSION["access_level"] < 10) { + return; + } + + /* + print " + Tiny Tiny RSS : User Details + + + "; + */ + + $uid = sprintf("%d", $_GET["id"]); + + print "
User details
"; + + print "
"; + + $result = db_query($link, "SELECT login, + SUBSTRING(last_login,1,16) AS last_login, + access_level, + (SELECT COUNT(int_id) FROM ttrss_user_entries + WHERE owner_uid = id) AS stored_articles, + SUBSTRING(created,1,16) AS created + FROM ttrss_users + WHERE id = '$uid'"); + + if (db_num_rows($result) == 0) { + print "

User not found

"; + return; + } + + // print "

User Details

"; - if (db_num_rows($result) == 1) { - $owner = db_fetch_result($result, 0, "owner_uid"); $login = db_fetch_result($result, 0, "login"); - generate_syndicated_feed($link, $owner, -2, false); + // print "

$login

"; - } else { - print "User not found"; - } + print ""; - } + $last_login = date(get_pref($link, 'LONG_DATE_FORMAT'), + strtotime(db_fetch_result($result, 0, "last_login"))); - if ($op == "rss") { - $feed = db_escape_string($_GET["id"]); - $user = db_escape_string($_GET["user"]); - $pass = db_escape_string($_GET["pass"]); - $is_cat = $_GET["is_cat"] != false; + $created = date(get_pref($link, 'LONG_DATE_FORMAT'), + strtotime(db_fetch_result($result, 0, "created"))); - $search = db_escape_string($_GET["q"]); - $match_on = db_escape_string($_GET["m"]); - $search_mode = db_escape_string($_GET["smode"]); + $access_level = db_fetch_result($result, 0, "access_level"); + $stored_articles = db_fetch_result($result, 0, "stored_articles"); - if (!$_SESSION["uid"] && $user && $pass) { - authenticate_user($link, $user, $pass); - } + // print ""; + // print ""; + print ""; + print ""; + print ""; - if ($_SESSION["uid"] || - http_authenticate_user($link)) { + $result = db_query($link, "SELECT COUNT(id) as num_feeds FROM ttrss_feeds + WHERE owner_uid = '$uid'"); - generate_syndicated_feed($link, 0, $feed, $is_cat, - $search, $search_mode, $match_on); - } + $num_feeds = db_fetch_result($result, 0, "num_feeds"); - } + print ""; - if ($op == "labelFromSearch") { - $search = db_escape_string($_GET["search"]); - $search_mode = db_escape_string($_GET["smode"]); - $match_on = db_escape_string($_GET["match"]); - $is_cat = db_escape_string($_GET["is_cat"]); - $title = db_escape_string($_GET["title"]); - $feed = sprintf("%d", $_GET["feed"]); + /* + $result = db_query($link, "SELECT + SUM(LENGTH(content)+LENGTH(title)+LENGTH(link)+LENGTH(guid)) AS db_size + FROM ttrss_user_entries,ttrss_entries + WHERE owner_uid = '$uid' AND ref_id = id"); - $label_qparts = array(); + $db_size = round(db_fetch_result($result, 0, "db_size") / 1024); - $search_expr = getSearchSql($search, $match_on); + print ""; + */ + + print "
Username$login
Access level$access_level
".__('Registered')."$created
".__('Last logged in')."$last_login
".__('Stored articles')."$stored_articles
".__('Subscribed feeds count')."$num_feeds
Approx. used DB size$db_size KBytes
"; + + print "

".__('Subscribed feeds')."

"; + + $result = db_query($link, "SELECT id,title,site_url FROM ttrss_feeds + WHERE owner_uid = '$uid' ORDER BY title"); + + print ""; - $cat_id = db_fetch_result($tmp_result, 0, "cat_id"); + print "
"; - if ($cat_id > 0) { - $search_expr .= " AND ttrss_feeds.cat_id = $cat_id "; + print "
+
"; + + // print ""; + + break; // user-details + + case "pref-feed-browser": + module_pref_feed_browser($link); + break; // pref-feed-browser + + case "publish": + $key = db_escape_string($_GET["key"]); + + $result = db_query($link, "SELECT login, owner_uid + FROM ttrss_user_prefs, ttrss_users WHERE + pref_name = '_PREFS_PUBLISH_KEY' AND + value = '$key' AND + ttrss_users.id = owner_uid"); + + if (db_num_rows($result) == 1) { + $owner = db_fetch_result($result, 0, "owner_uid"); + $login = db_fetch_result($result, 0, "login"); + + generate_syndicated_feed($link, $owner, -2, false); + + } else { + print "User not found"; + } + break; // publish + + case "rss": + $feed = db_escape_string($_GET["id"]); + $user = db_escape_string($_GET["user"]); + $pass = db_escape_string($_GET["pass"]); + $is_cat = $_GET["is_cat"] != false; + + $search = db_escape_string($_GET["q"]); + $match_on = db_escape_string($_GET["m"]); + $search_mode = db_escape_string($_GET["smode"]); + + if (!$_SESSION["uid"] && $user && $pass) { + authenticate_user($link, $user, $pass); + } + + if ($_SESSION["uid"] || + http_authenticate_user($link)) { + + generate_syndicated_feed($link, 0, $feed, $is_cat, + $search, $search_mode, $match_on); + } + break; // rss + + case "labelFromSearch": + $search = db_escape_string($_GET["search"]); + $search_mode = db_escape_string($_GET["smode"]); + $match_on = db_escape_string($_GET["match"]); + $is_cat = db_escape_string($_GET["is_cat"]); + $title = db_escape_string($_GET["title"]); + $feed = sprintf("%d", $_GET["feed"]); + + $label_qparts = array(); + + $search_expr = getSearchSql($search, $match_on); + + if ($is_cat) { + if ($feed != 0) { + $search_expr .= " AND ttrss_feeds.cat_id = $feed "; } else { $search_expr .= " AND ttrss_feeds.cat_id IS NULL "; } } else { - $search_expr .= " AND ttrss_feeds.id = $feed "; + if ($search_mode == "all_feeds") { + // NOOP + } else if ($search_mode == "this_cat") { + + $tmp_result = db_query($link, "SELECT cat_id + FROM ttrss_feeds WHERE id = '$feed'"); + + $cat_id = db_fetch_result($tmp_result, 0, "cat_id"); + + if ($cat_id > 0) { + $search_expr .= " AND ttrss_feeds.cat_id = $cat_id "; + } else { + $search_expr .= " AND ttrss_feeds.cat_id IS NULL "; + } + } else { + $search_expr .= " AND ttrss_feeds.id = $feed "; + } + } - } + $search_expr = db_escape_string($search_expr); - $search_expr = db_escape_string($search_expr); + print $search_expr; - print $search_expr; + if ($title) { + $result = db_query($link, + "INSERT INTO ttrss_labels (sql_exp,description,owner_uid) + VALUES ('$search_expr', '$title', '".$_SESSION["uid"]."')"); + } + break; // labelFromSearch - if ($title) { - $result = db_query($link, - "INSERT INTO ttrss_labels (sql_exp,description,owner_uid) - VALUES ('$search_expr', '$title', '".$_SESSION["uid"]."')"); - } - } + case "getUnread": + $login = db_escape_string($_GET["login"]); - if ($op == "getUnread") { - $login = db_escape_string($_GET["login"]); + header("Content-Type: text/plain; charset=utf-8"); - header("Content-Type: text/plain; charset=utf-8"); + $result = db_query($link, "SELECT id FROM ttrss_users WHERE login = '$login'"); - $result = db_query($link, "SELECT id FROM ttrss_users WHERE login = '$login'"); + if (db_num_rows($result) == 1) { + $uid = db_fetch_result($result, 0, "id"); + print getGlobalUnread($link, $uid); + } else { + print "-1;User not found"; + } - if (db_num_rows($result) == 1) { - $uid = db_fetch_result($result, 0, "id"); - print getGlobalUnread($link, $uid); - } else { - print "-1;User not found"; - } + $print_exec_time = false; + break; // getUnread - $print_exec_time = false; - } + case "digestTest": + header("Content-Type: text/plain"); + print_r(prepare_headlines_digest($link, $_SESSION["uid"])); + $print_exec_time = false; + break; // digestTest - if ($op == "digestTest") { - header("Content-Type: text/plain"); - print_r(prepare_headlines_digest($link, $_SESSION["uid"])); - $print_exec_time = false; + case "digestSend": + header("Content-Type: text/plain"); + send_headlines_digests($link); + $print_exec_time = false; + break; // digestSend - } - - if ($op == "digestSend") { - header("Content-Type: text/plain"); - send_headlines_digests($link); - $print_exec_time = false; - - } + } // Select action according to $op value. + // We close the connection to database. db_close($link); ?> diff --git a/functions.php b/functions.php index 33a5a907..f9771879 100644 --- a/functions.php +++ b/functions.php @@ -72,11 +72,17 @@ 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()); $ts = "$ts/" . posix_getpid(); print "[$ts] $msg\n"; - } + } // function _debug function purge_feed($link, $feed_id, $purge_interval, $debug = false) { @@ -459,7 +465,7 @@ 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']) { @@ -490,7 +496,7 @@ if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) { _debug("update_rss_feed: feed $feed [$feed_url] NOT FOUND/SKIPPED"); } - return; + return false; } $update_method = db_fetch_result($result, 0, "update_method"); @@ -3356,6 +3362,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; @@ -5118,26 +5131,154 @@ 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 clear_feed_articles - function add_feed_url() { + /** + * 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 = 'http://' . $_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) + ))"; + } 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) + ))"; + } + + // 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); + + // We search for feed needing update. + $result = db_query($link, "SELECT ttrss_feeds.feed_url,ttrss_feeds.id, ttrss_feeds.owner_uid, + SUBSTRING(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 ttrss_feeds.last_updated ASC $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) pcntl_alarm(300); + update_rss_feed($link, $line["feed_url"], $line["id"], true); + // Cancel the alarm (the update went well) + if(!$from_http) 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 ?> diff --git a/update_daemon2.php b/update_daemon2.php index 315daa7e..1b4007ac 100644 --- a/update_daemon2.php +++ b/update_daemon2.php @@ -88,6 +88,7 @@ if (!pcntl_fork()) { pcntl_signal(SIGINT, 'sigint_handler'); + // Try to lock a file in order to avoid concurrent update. $lock_handle = make_lockfile("update_daemon.lock"); if (!$lock_handle) { @@ -115,6 +116,8 @@ while (true) { + // Since sleep is interupted by SIGCHLD, we need another way to + // respect the SPAWN_INTERVAL $next_spawn = $last_checkpoint + SPAWN_INTERVAL - time(); if ($next_spawn % 10 == 0) { @@ -180,89 +183,8 @@ // $last_purge = time(); // } - // Process all other feeds using last_updated and interval parameters - - $random_qpart = sql_random_function(); - - 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 = ""; - } - - 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) - ))"; - } 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) - ))"; - } - - - 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))"; - } - - $result = db_query($link, "SELECT ttrss_feeds.feed_url,ttrss_feeds.id, ttrss_feeds.owner_uid, - SUBSTRING(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 DESC LIMIT " . DAEMON_FEED_LIMIT); - - $user_prefs_cache = array(); - - _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))); - } - - while ($line = array_pop($feeds_to_update)) { - - _debug("Feed: " . $line["feed_url"] . ", " . $line["last_updated"]); - - pcntl_alarm(300); - update_rss_feed($link, $line["feed_url"], $line["id"], true); - pcntl_alarm(0); - - sleep(1); // prevent flood (FIXME make this an option?) - } - - if (DAEMON_SENDS_DIGESTS) send_headlines_digests($link); + // Call to the feed batch update function + update_daemon_common($link); _debug("Elapsed time: " . (time() - $start_timestamp) . " second(s)"); diff --git a/update_daemon_loop.php b/update_daemon_loop.php index 320bec41..737194ae 100644 --- a/update_daemon_loop.php +++ b/update_daemon_loop.php @@ -88,7 +88,7 @@ // Process all other feeds using last_updated and interval parameters - $random_qpart = sql_random_function(); +// $random_qpart = sql_random_function(); /* ttrss_entries.date_entered < NOW() - INTERVAL '$purge_interval days'"); @@ -104,85 +104,9 @@ marked = false AND feed_id = '$feed_id' AND ttrss_entries.date_entered < DATE_SUB(NOW(), INTERVAL $purge_interval DAY)"); */ - - 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 = ""; - } - 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) - ))"; - } 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) - ))"; - } - - 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))"; - } - - $result = db_query($link, "SELECT ttrss_feeds.feed_url,ttrss_feeds.id, ttrss_feeds.owner_uid, - SUBSTRING(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 DESC LIMIT " . DAEMON_FEED_LIMIT); - - $user_prefs_cache = array(); - - _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 (for exemple, forced update by user). - $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))); - } - - while ($line = array_pop($feeds_to_update)) { - - _debug("Feed: " . $line["feed_url"] . ", " . $line["last_updated"]); - - pcntl_alarm(300); - update_rss_feed($link, $line["feed_url"], $line["id"], true); - pcntl_alarm(0); - - sleep(1); // prevent flood (FIXME make this an option?) - } - - if (DAEMON_SENDS_DIGESTS) send_headlines_digests($link); + // Call to the feed batch update function + update_daemon_common($link); db_close($link); diff --git a/update_feeds.php b/update_feeds.php index 4909d881..4b6ad3c4 100644 --- a/update_feeds.php +++ b/update_feeds.php @@ -19,11 +19,13 @@ $lock_handle = make_lockfile($lock_filename); + // Try to lock a file in order to avoid concurrent update. if (!$lock_handle) { die("error: Can't create lockfile ($lock_filename). ". "Maybe another process is already running.\n"); } + // Create a database connection. $link = db_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME); if (!$link) { @@ -44,14 +46,10 @@ } } - $result = db_query($link, "SELECT id FROM ttrss_users"); - - while ($line = db_fetch_assoc($result)) { - $user_id = $line["id"]; - initialize_user_prefs($link, $user_id); - update_all_feeds($link, false, $user_id, true); - } + // Update all feeds needing a update. + update_daemon_common($link, $limit=0); + // Send feed digests by email if needed. if (DAEMON_SENDS_DIGESTS) send_headlines_digests($link); db_close($link);