X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=functions.php;h=83159e62cabbefe1f79576f7bd34ee75ec6849a2;hb=e0d91d846dd5ac42a95a0832777cc76aaf579bc2;hp=7c3e8d0a30134390fe92502431b049c945ef60f3;hpb=78ccac0bdd34cfa1f8f6c724771b12ea3554f451;p=tt-rss.git diff --git a/functions.php b/functions.php index 7c3e8d0a..83159e62 100644 --- a/functions.php +++ b/functions.php @@ -114,11 +114,24 @@ $config = HTMLPurifier_Config::createDefault(); - $allowed = "p,a[href],i,em,b,strong,code,pre,blockquote,br,img[src|alt|title],ul,ol,li,h1,h2,h3,h4,s"; + $allowed = "p,a[href],i,em,b,strong,code,pre,blockquote,br,img[src|alt|title],ul,ol,li,h1,h2,h3,h4,s,object[classid|type|id|name|width|height|codebase],param[name|value],table,tr,td"; + + $config->set('HTML.SafeObject', true); + @$config->set('HTML', 'Allowed', $allowed); + $config->set('Output.FlashCompat', true); + $config->set('Attr.EnableID', true); + if (!defined('MOBILE_VERSION')) { + @$config->set('Cache', 'SerializerPath', CACHE_DIR . "/htmlpurifier"); + } else { + @$config->set('Cache', 'SerializerPath', "../" . CACHE_DIR . "/htmlpurifier"); + } - $config->set('HTML', 'Allowed', $allowed); $purifier = new HTMLPurifier($config); + $tz_offset = -1; + $utc_tz = new DateTimeZone('UTC'); + $schema_version = false; + /** * Print a timestamped debug message. * @@ -178,11 +191,6 @@ if (!$purge_unread) $query_limit = " unread = false AND "; if (DB_TYPE == "pgsql") { -/* $result = db_query($link, "DELETE FROM ttrss_user_entries WHERE - marked = false AND feed_id = '$feed_id' AND - (SELECT date_updated FROM ttrss_entries WHERE - id = ref_id) < NOW() - INTERVAL '$purge_interval days'"); */ - $pg_version = get_pgsql_version($link); if (preg_match("/^7\./", $pg_version) || preg_match("/^8\.0/", $pg_version)) { @@ -358,11 +366,11 @@ } } - function fetch_file_contents($url, $type = false, $login = false, $pass = false) { + function fetch_file_contents($url, $type = false, $login = false, $pass = false, $post_query = false) { $login = urlencode($login); $pass = urlencode($pass); - if (function_exists('curl_init')) { + if (function_exists('curl_init') && !ini_get("open_basedir")) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15); @@ -373,11 +381,19 @@ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY); + curl_setopt($ch, CURLOPT_USERAGENT, SELF_USER_AGENT); + curl_setopt($ch, CURLOPT_ENCODING , "gzip"); + + if ($post_query) { + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $post_query); + } if ($login && $pass) curl_setopt($ch, CURLOPT_USERPWD, "$login:$pass"); $contents = @curl_exec($ch); + if ($contents === false) { curl_close($ch); return false; @@ -393,7 +409,7 @@ return $contents; } else { - if ($login && $pass && $updated != 3) { + if ($login && $pass ){ $url_parts = array(); preg_match("/(^[^:]*):\/\/(.*)/", $url, $url_parts); @@ -451,21 +467,24 @@ } // function get_favicon_url function check_feed_favicon($site_url, $feed, $link) { - $favicon_url = get_favicon_url($site_url); - # print "FAVICON [$site_url]: $favicon_url\n"; $icon_file = ICONS_DIR . "/$feed.ico"; - if ($favicon_url && !file_exists($icon_file)) { - $contents = fetch_file_contents($favicon_url, "image"); - if ($contents) { - $fp = fopen($icon_file, "w"); + if (!file_exists($icon_file)) { + $favicon_url = get_favicon_url($site_url); - if ($fp) { - fwrite($fp, $contents); - fclose($fp); - chmod($icon_file, 0644); + if ($favicon_url) { + $contents = fetch_file_contents($favicon_url, "image"); + + if ($contents) { + $fp = @fopen($icon_file, "w"); + + if ($fp) { + fwrite($fp, $contents); + fclose($fp); + chmod($icon_file, 0644); + } } } } @@ -490,15 +509,18 @@ } } - function update_rss_feed_real($link, $feed, $ignore_daemon = false, $no_cache = false) { + function update_rss_feed_real($link, $feed, $ignore_daemon = false, $no_cache = false, + $override_url = false) { global $memcache; + $debug_enabled = defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']; + if (!$_REQUEST["daemon"] && !$ignore_daemon) { return false; } - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: start"); } @@ -525,7 +547,7 @@ } if (db_num_rows($result) == 0) { - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: feed $feed NOT FOUND/SKIPPED"); } return false; @@ -558,7 +580,7 @@ else $use_simplepie = false; - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update method: $update_method (feed setting: $update_method) (use simplepie: $use_simplepie)\n"); } @@ -571,11 +593,11 @@ $cache_images = sql_bool_to_bool(db_fetch_result($result, 0, "cache_images")); $fetch_url = db_fetch_result($result, 0, "feed_url"); - if ($update_interval < 0) { return; } + if ($update_interval < 0) { return false; } $feed = db_escape_string($feed); - if ($auth_login && $auth_pass && $updated != 3) { + if ($auth_login && $auth_pass ){ $url_parts = array(); preg_match("/(^[^:]*):\/\/(.*)/", $fetch_url, $url_parts); @@ -585,7 +607,10 @@ } - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($override_url) + $fetch_url = $override_url; + + if ($debug_enabled) { _debug("update_rss_feed: fetching [$fetch_url]..."); } @@ -593,7 +618,7 @@ if ($memcache && $obj = $memcache->get($obj_id)) { - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: data found in memcache."); } @@ -607,11 +632,15 @@ define('MAGPIE_CACHE_AGE', get_feed_update_interval($link, $feed) * 60); define('MAGPIE_CACHE_ON', !$no_cache); + define('MAGPIE_FETCH_TIME_OUT', 60); + define('MAGPIE_CACHE_DIR', CACHE_DIR . "/magpie"); $rss = @fetch_rss($fetch_url); } else { - if (!is_dir(SIMPLEPIE_CACHE_DIR)) { - mkdir(SIMPLEPIE_CACHE_DIR); + $simplepie_cache_dir = CACHE_DIR . "/simplepie"; + + if (!is_dir($simplepie_cache_dir)) { + mkdir($simplepie_cache_dir); } $rss = new SimplePie(); @@ -619,17 +648,18 @@ # $rss->set_timeout(10); $rss->set_feed_url($fetch_url); $rss->set_output_encoding('UTF-8'); + $rss->force_feed(true); if (SIMPLEPIE_CACHE_IMAGES && $cache_images) { - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("enabling image cache"); } $rss->set_image_handler("image.php", 'i'); } - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("feed update interval (sec): " . get_feed_update_interval($link, $feed)*60); } @@ -637,7 +667,7 @@ $rss->enable_cache(!$no_cache); if (!$no_cache) { - $rss->set_cache_location(SIMPLEPIE_CACHE_DIR); + $rss->set_cache_location($simplepie_cache_dir); $rss->set_cache_duration(get_feed_update_interval($link, $feed) * 60); } @@ -649,7 +679,7 @@ // print_r($rss); - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: fetch done, parsing..."); } @@ -663,7 +693,7 @@ if ($fetch_ok) { - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: processing feed data..."); } @@ -684,7 +714,9 @@ $site_url = $rss->channel["link"]; } - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + $site_url = rewrite_relative_url($fetch_url, $site_url); + + if ($debug_enabled) { _debug("update_rss_feed: checking favicon..."); } @@ -698,7 +730,7 @@ $feed_title = db_escape_string($rss->channel["title"]); } - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: registering title: $feed_title"); } @@ -730,15 +762,15 @@ db_query($link, "UPDATE ttrss_feeds SET icon_url = '$icon_url' WHERE id = '$feed'"); } - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: loading filters..."); } $filters = load_filters($link, $feed, $owner_uid); - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug'] == 2) { - print_r($filters); - } +// if ($debug_enabled) { +// print_r($filters); +// } if ($use_simplepie) { $iterator = $rss->get_items(); @@ -756,7 +788,7 @@ // clear any errors and mark feed as updated if fetched okay // even if it's blank - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: entry iterator is not an array, no articles?"); } @@ -766,7 +798,9 @@ return; // no articles } - if ($pubsub_state != 2) { + if ($pubsub_state != 2 && PUBSUBHUBBUB_ENABLED) { + + if ($debug_enabled) _debug("update_rss_feed: checking for PUSH hub..."); $feed_hub_url = false; if ($use_simplepie) { @@ -800,20 +834,27 @@ } } - if ($feed_hub_url && function_exists('curl_init')) { + if ($debug_enabled) _debug("update_rss_feed: feed hub url: $feed_hub_url"); + + if ($feed_hub_url && function_exists('curl_init') && + !ini_get("open_basedir")) { + $callback_url = get_self_url_prefix() . - "/backend.php?op=pubsub&id=$feed"; + "/public.php?op=pubsub&id=$feed"; $s = new Subscriber($feed_hub_url, $callback_url); - $s->subscribe($fetch_url); + $rc = $s->subscribe($fetch_url); + + if ($debug_enabled) + _debug("update_rss_feed: feed hub url found, subscribe request sent."); db_query($link, "UPDATE ttrss_feeds SET pubsub_state = 1 WHERE id = '$feed'"); } } - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: processing articles..."); } @@ -838,7 +879,7 @@ if (!$entry_guid) $entry_guid = make_guid_from_title($item["title"]); } - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: guid $entry_guid"); } @@ -869,7 +910,7 @@ $entry_timestamp_fmt = strftime("%Y/%m/%d %H:%M:%S", $entry_timestamp); - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: date $entry_timestamp [$entry_timestamp_fmt]"); } @@ -887,8 +928,11 @@ if (!$entry_link) $entry_link = $item["link"]; } - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + $entry_link = rewrite_relative_url($site_url, $entry_link); + + if ($debug_enabled) { _debug("update_rss_feed: title $entry_title"); + _debug("update_rss_feed: link $entry_link"); } if (!$entry_title) $entry_title = date("Y-m-d H:i:s", $entry_timestamp);; @@ -988,7 +1032,7 @@ if (!$num_comments) $num_comments = 0; - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: looking for tags [1]..."); } @@ -1006,7 +1050,7 @@ } } - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: category tags:"); print_r($additional_tags); } @@ -1050,7 +1094,7 @@ } } - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: looking for tags [2]..."); } @@ -1070,7 +1114,7 @@ for ($i = 0; $i < count($entry_tags); $i++) $entry_tags[$i] = mb_strtolower($entry_tags[$i], 'utf-8'); - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: unfiltered tags found:"); print_r($entry_tags); } @@ -1080,7 +1124,7 @@ $entry_content = sanitize_article_content($entry_content); $entry_title = sanitize_article_content($entry_title); - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: done collecting data [TITLE:$entry_title]"); } @@ -1088,7 +1132,7 @@ if (db_num_rows($result) == 0) { - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: base guid not found"); } @@ -1149,7 +1193,7 @@ if (db_num_rows($result) == 1) { - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: base guid found, checking for user record"); } @@ -1178,7 +1222,7 @@ $entry_content, $entry_link, $entry_timestamp, $entry_author, $entry_tags); - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: article filters: "); if (count($article_filters) != 0) { print_r($article_filters); @@ -1192,7 +1236,7 @@ $score = calculate_article_score($article_filters); - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: initial score: $score"); } @@ -1207,7 +1251,7 @@ // okay it doesn't exist - create user entry if (db_num_rows($result) == 0) { - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: user record not found, creating..."); } @@ -1234,13 +1278,13 @@ $result = db_query($link, "INSERT INTO ttrss_user_entries (ref_id, owner_uid, feed_id, unread, last_read, marked, - published, score, tag_cache, label_cache) + published, score, tag_cache, label_cache, uuid) VALUES ('$ref_id', '$owner_uid', '$feed', $unread, - $last_read_qpart, $marked, $published, '$score', '', '')"); + $last_read_qpart, $marked, $published, '$score', '', '', '')"); if (PUBSUBHUBBUB_HUB && $published == 'true') { $rss_link = get_self_url_prefix() . - "/backend.php?op=rss&id=-2&key=" . + "/public.php?op=rss&id=-2&key=" . get_feed_access_key($link, -2, false, $owner_uid); $p = new Publisher(PUBSUBHUBBUB_HUB); @@ -1257,7 +1301,7 @@ $entry_int_id = db_fetch_result($result, 0, "int_id"); } } else { - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: user record FOUND"); } @@ -1265,31 +1309,28 @@ $entry_int_id = db_fetch_result($result, 0, "int_id"); } - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: RID: $entry_ref_id, IID: $entry_int_id"); } $post_needs_update = false; + $update_insignificant = false; - if ($update_on_checksum_change && $content_hash != $orig_content_hash) { -// print ""; + if ($orig_num_comments != $num_comments) { $post_needs_update = true; + $update_insignificant = true; } - if (db_escape_string($orig_title) != $entry_title) { + if ($content_hash != $orig_content_hash) { $post_needs_update = true; + $update_insignificant = false; } - if ($orig_num_comments != $num_comments) { + if (db_escape_string($orig_title) != $entry_title) { $post_needs_update = true; + $update_insignificant = false; } -// this doesn't seem to be very reliable -// -// if ($orig_timestamp != $entry_timestamp && !$orig_no_orig_date) { -// $post_needs_update = true; -// } - // if post needs update, update it and mark all user entries // linking to this post as updated if ($post_needs_update) { @@ -1303,30 +1344,33 @@ db_query($link, "UPDATE ttrss_entries SET title = '$entry_title', content = '$entry_content', content_hash = '$content_hash', + updated = '$entry_timestamp_fmt', num_comments = '$num_comments' WHERE id = '$ref_id'"); - if ($mark_unread_on_update) { - db_query($link, "UPDATE ttrss_user_entries - SET last_read = null, unread = true WHERE ref_id = '$ref_id'"); - } else { - db_query($link, "UPDATE ttrss_user_entries - SET last_read = null WHERE ref_id = '$ref_id' AND unread = false"); + if (!$update_insignificant) { + if ($mark_unread_on_update) { + db_query($link, "UPDATE ttrss_user_entries + SET last_read = null, unread = true WHERE ref_id = '$ref_id'"); + } else if ($update_on_checksum_change) { + db_query($link, "UPDATE ttrss_user_entries + SET last_read = null WHERE ref_id = '$ref_id' + AND unread = false"); + } } - } } db_query($link, "COMMIT"); - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: assigning labels..."); } assign_article_to_labels($link, $entry_ref_id, $article_filters, $owner_uid); - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: looking for enclosures..."); } @@ -1395,7 +1439,7 @@ } - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: article enclosures:"); print_r($enclosures); } @@ -1424,7 +1468,7 @@ foreach ($article_filters as $f) { if ($f[0] == "tag") { - $manual_tags = trim_array(split(",", $f[1])); + $manual_tags = trim_array(explode(",", $f[1])); foreach ($manual_tags as $tag) { if (tag_is_valid($tag)) { @@ -1436,7 +1480,7 @@ // Skip boring tags - $boring_tags = trim_array(split(",", mb_strtolower(get_pref($link, + $boring_tags = trim_array(explode(",", mb_strtolower(get_pref($link, 'BLACKLISTED_TAGS', $owner_uid, ''), 'utf-8'))); $filtered_tags = array(); @@ -1452,7 +1496,7 @@ $filtered_tags = array_unique($filtered_tags); - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: filtered article tags:"); print_r($filtered_tags); } @@ -1497,19 +1541,23 @@ db_query($link, "COMMIT"); } - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: article processed"); } } if (!$last_updated) { - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: new feed, catching it up..."); } catchup_feed($link, $feed, false, $owner_uid); } - purge_feed($link, $feed, 0); + if ($debug_enabled) { + _debug("purging feed..."); + } + + purge_feed($link, $feed, 0, $debug_enabled); db_query($link, "UPDATE ttrss_feeds SET last_updated = NOW(), last_error = '' WHERE id = '$feed'"); @@ -1524,7 +1572,7 @@ $error_msg = mb_substr(magpie_error(), 0, 250); } - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: error fetching feed: $error_msg"); } @@ -1539,7 +1587,7 @@ unset($rss); } - if (defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug']) { + if ($debug_enabled) { _debug("update_rss_feed: done"); } @@ -1792,8 +1840,7 @@ function lookup_user_id($link, $user) { - $result = db_query($link, "SELECT id FROM ttrss_users WHERE - login = '$login'"); + $result = db_query($link, "SELECT id FROM ttrss_users WHERE login = '$user'"); if (db_num_rows($result) == 1) { return db_fetch_result($result, 0, "id"); @@ -1802,10 +1849,7 @@ } } - function http_authenticate_user($link) { - -// error_log("http_authenticate_user: ".$_SERVER["PHP_AUTH_USER"]."\n", 3, '/tmp/tt-rss.log'); - +/* function http_authenticate_user($link) { if (!$_SERVER["PHP_AUTH_USER"]) { header('WWW-Authenticate: Basic realm="Tiny Tiny RSS RSSGen"'); @@ -1824,7 +1868,7 @@ } return true; - } + } */ function get_ssl_certificate_id() { if ($_SERVER["REDIRECT_SSL_CLIENT_M_SERIAL"]) { @@ -1887,6 +1931,19 @@ FROM ttrss_users WHERE login = '$login'"; + if (defined('AUTO_CREATE_USER') && AUTO_CREATE_USER + && $_SERVER["REMOTE_USER"]) { + $result = db_query($link, $query); + + // First login ? + if (db_num_rows($result) == 0) { + $query2 = "INSERT INTO ttrss_users + (login,access_level,last_login,created) + VALUES ('$login', 0, null, NOW())"; + db_query($link, $query2); + } + } + } else { $query = "SELECT id,login,access_level,pwd_hash FROM ttrss_users WHERE @@ -1904,6 +1961,25 @@ db_query($link, "UPDATE ttrss_users SET last_login = NOW() WHERE id = " . $_SESSION["uid"]); + + // LemonLDAP can send user informations via HTTP HEADER + if (defined('AUTO_CREATE_USER') && AUTO_CREATE_USER){ + // update user name + $fullname = $_SERVER['HTTP_USER_NAME'] ? $_SERVER['HTTP_USER_NAME'] : $_SERVER['AUTHENTICATE_CN']; + if ($fullname){ + $fullname = db_escape_string($fullname); + db_query($link, "UPDATE ttrss_users SET full_name = '$fullname' WHERE id = " . + $_SESSION["uid"]); + } + // update user mail + $email = $_SERVER['HTTP_USER_MAIL'] ? $_SERVER['HTTP_USER_MAIL'] : $_SERVER['AUTHENTICATE_MAIL']; + if ($email){ + $email = db_escape_string($email); + db_query($link, "UPDATE ttrss_users SET email = '$email' WHERE id = " . + $_SESSION["uid"]); + } + } + $_SESSION["ip_address"] = $_SERVER["REMOTE_ADDR"]; $_SESSION["pwd_hash"] = db_fetch_result($result, 0, "pwd_hash"); @@ -2026,6 +2102,8 @@ } function login_sequence($link, $mobile = false) { + $_SESSION["prefs_cache"] = array(); + if (!SINGLE_USER_MODE) { $login_action = $_POST["login_action"]; @@ -2089,6 +2167,9 @@ setcookie("ttrss_lang", $_SESSION["language"], time() + SESSION_COOKIE_LIFETIME); } + + // try to remove possible duplicates from feed counter cache +// ccache_cleanup($link, $_SESSION["uid"]); } } else { @@ -2239,21 +2320,30 @@ if (!$owner_uid) $owner_uid = $_SESSION['uid']; if (!$timestamp) $timestamp = '1970-01-01 0:00'; - $user_tz_string = get_pref($link, 'USER_TIMEZONE', $owner_uid); + global $utc_tz; + global $tz_offset; - try { - $user_tz = new DateTimeZone($user_tz_string); - } catch (Exception $e) { - $user_tz = new DateTimeZone('UTC'); + # We store date in UTC internally + $dt = new DateTime($timestamp, $utc_tz); + + if ($tz_offset == -1) { + + $user_tz_string = get_pref($link, 'USER_TIMEZONE', $owner_uid); + + try { + $user_tz = new DateTimeZone($user_tz_string); + } catch (Exception $e) { + $user_tz = $utc_tz; + } + + $tz_offset = $user_tz->getOffset($dt); } - # We store date in UTC internally - $dt = new DateTime($timestamp, new DateTimeZone('UTC')); - $user_timestamp = $dt->format('U') + $user_tz->getOffset($dt); + $user_timestamp = $dt->format('U') + $tz_offset; if (!$no_smart_dt) { return smart_date_time($link, $user_timestamp, - $user_tz->getOffset($dt), $owner_uid); + $tz_offset, $owner_uid); } else { if ($long) $format = get_pref($link, 'LONG_DATE_FORMAT', $owner_uid); @@ -2297,7 +2387,7 @@ } function sql_bool_to_bool($s) { - if ($s == "t" || $s == "1") { + if ($s == "t" || $s == "1" || $s == "true") { return true; } else { return false; @@ -2319,14 +2409,19 @@ return "even"; } + // Session caching removed due to causing wrong redirects to upgrade + // script when get_schema_version() is called on an obsolete session + // created on a previous schema version. function get_schema_version($link, $nocache = false) { - if (!$_SESSION["schema_version"] || $nocache) { + global $schema_version; + + if (!$schema_version) { $result = db_query($link, "SELECT schema_version FROM ttrss_version"); $version = db_fetch_result($result, 0, "schema_version"); - $_SESSION["schema_version"] = $version; + $schema_version = $version; return $version; } else { - return $_SESSION["schema_version"]; + return $schema_version; } } @@ -2335,7 +2430,7 @@ global $ERRORS; $error_code = 0; - $schema_version = get_schema_version($link); + $schema_version = get_schema_version($link, true); if ($schema_version != SCHEMA_VERSION) { $error_code = 5; @@ -2411,8 +2506,9 @@ if (!$owner_uid) $owner_uid = $_SESSION['uid']; - if (preg_match("/^-?[0-9][0-9]*$/", $feed) != false) { + //if (preg_match("/^-?[0-9][0-9]*$/", $feed) != false) { + if (is_numeric($feed)) { if ($cat_view) { if ($feed >= 0) { @@ -2436,7 +2532,6 @@ } } else if ($feed == -2) { - db_query($link, "UPDATE ttrss_user_entries SET unread = false,last_read = NOW() WHERE (SELECT COUNT(*) FROM ttrss_user_labels2 WHERE article_id = ref_id) > 0 @@ -2536,11 +2631,7 @@ if (strchr($omode, "l")) $data = array_merge($data, getLabelCounters($link)); if (strchr($omode, "f")) $data = array_merge($data, getFeedCounters($link, $active_feed)); if (strchr($omode, "t")) $data = array_merge($data, getTagCounters($link)); - if (strchr($omode, "c")) { - if (get_pref($link, 'ENABLE_FEED_CATS')) { - $data = array_merge($data, getCategoryCounters($link)); - } - } + if (strchr($omode, "c")) $data = array_merge($data, getCategoryCounters($link)); return $data; } @@ -2949,7 +3040,7 @@ function get_pgsql_version($link) { $result = db_query($link, "SELECT version() AS version"); - $version = split(" ", db_fetch_result($result, 0, "version")); + $version = explode(" ", db_fetch_result($result, 0, "version")); return $version[1]; } @@ -3175,7 +3266,7 @@ return "Unknown label ($label_id)"; } - } else if ($id > 0) { + } else if (is_numeric($id) && $id > 0) { $result = db_query($link, "SELECT title FROM ttrss_feeds WHERE id = '$id'"); if (db_num_rows($result) == 1) { return db_fetch_result($result, 0, "title"); @@ -3196,7 +3287,6 @@ $params["theme"] = get_user_theme($link); $params["theme_options"] = get_user_theme_options($link); - $params["daemon_enabled"] = ENABLE_UPDATE_DAEMON; $params["sign_progress"] = theme_image($link, "images/indicator_white.gif"); $params["sign_progress_tiny"] = theme_image($link, "images/indicator_tiny.gif"); @@ -3253,7 +3343,7 @@ $data['last_article_id'] = getLastArticleId($link); $data['cdm_expanded'] = get_pref($link, 'CDM_EXPANDED'); - if (ENABLE_UPDATE_DAEMON) { + if (file_exists(LOCK_DIRECTORY . "/update_daemon.lock")) { $data['daemon_is_running'] = (int) file_is_locked("update_daemon.lock"); @@ -3291,11 +3381,11 @@ return $data; } - function getSearchSql($link, $search, $match_on) { + function search_to_sql($link, $search, $match_on) { $search_query_part = ""; - $keywords = split(" ", $search); + $keywords = explode(" ", $search); $query_keywords = array(); foreach ($keywords as $k) { @@ -3306,13 +3396,37 @@ $not = ""; } - if (strpos($k, "@") === 0) { + $commandpair = explode(":", mb_strtolower($k), 2); + + if ($commandpair[0] == "note" && $commandpair[1]) { + + if ($commandpair[1] == "true") + array_push($query_keywords, "($not (note IS NOT NULL AND note != ''))"); + else + array_push($query_keywords, "($not (note IS NULL OR note = ''))"); + + } else if ($commandpair[0] == "star" && $commandpair[1]) { + + if ($commandpair[1] == "true") + array_push($query_keywords, "($not (marked = true))"); + else + array_push($query_keywords, "($not (marked = false))"); + + } else if ($commandpair[0] == "pub" && $commandpair[1]) { + + if ($commandpair[1] == "true") + array_push($query_keywords, "($not (published = true))"); + else + array_push($query_keywords, "($not (published = false))"); + + } else if (strpos($k, "@") === 0) { $user_tz_string = get_pref($link, '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 ($match_on == "both") { array_push($query_keywords, "(UPPER(ttrss_entries.title) $not LIKE UPPER('%$k%') @@ -3329,7 +3443,8 @@ return $search_query_part; } - function queryFeedHeadlines($link, $feed, $limit, $view_mode, $cat_view, $search, $search_mode, $match_on, $override_order = false, $offset = 0, $owner_uid = 0) { + + function queryFeedHeadlines($link, $feed, $limit, $view_mode, $cat_view, $search, $search_mode, $match_on, $override_order = false, $offset = 0, $owner_uid = 0, $filter = false, $since_id = 0) { if (!$owner_uid) $owner_uid = $_SESSION["uid"]; @@ -3346,7 +3461,7 @@ $search_query_part = "ref_id = -1 AND "; } else { - $search_query_part = getSearchSql($link, $search, $match_on); + $search_query_part = search_to_sql($link, $search, $match_on); $search_query_part .= " AND "; } @@ -3354,6 +3469,18 @@ $search_query_part = ""; } + if ($filter) { + $filter_query_part = filter_to_sql($filter); + } else { + $filter_query_part = ""; + } + + if ($since_id) { + $since_id_part = "ttrss_entries.id > $since_id AND "; + } else { + $since_id_part = ""; + } + $view_query_part = ""; if ($view_mode == "adaptive" || $view_query_part == "noscores") { @@ -3522,7 +3649,7 @@ if ($cat_view) { $feed_title = getCategoryTitle($link, $feed); } else { - if ((int)$feed == $feed && $feed > 0) { + if (is_numeric($feed) && $feed > 0) { $result = db_query($link, "SELECT title,site_url,last_error FROM ttrss_feeds WHERE id = '$feed' AND owner_uid = $owner_uid"); @@ -3569,7 +3696,13 @@ guid, ttrss_entries.id,ttrss_entries.title, updated, + label_cache, + tag_cache, + always_display_enclosures, + site_url, note, + num_comments, + comments, unread,feed_id,marked,published,link,last_read,orig_feed_id, ".SUBSTRING_FOR_DATE."(last_read,1,19) as last_read_noms, $vfeed_query_part @@ -3583,7 +3716,9 @@ ttrss_user_entries.ref_id = ttrss_entries.id AND ttrss_user_entries.owner_uid = '$owner_uid' AND $search_query_part + $filter_query_part $view_query_part + $since_id_part $query_strategy_part ORDER BY $order_by $limit_query_part $offset_query_part"; @@ -3594,31 +3729,73 @@ } else { // browsing by tag + $select_qpart = "SELECT DISTINCT " . + "date_entered," . + "guid," . + "note," . + "ttrss_entries.id as id," . + "title," . + "updated," . + "unread," . + "feed_id," . + "orig_feed_id," . + "site_url," . + "always_display_enclosures, ". + "marked," . + "num_comments, " . + "comments, " . + "tag_cache," . + "label_cache," . + "link," . + "last_read," . + SUBSTRING_FOR_DATE . "(last_read,1,19) as last_read_noms," . + $since_id_part . + $vfeed_query_part . + $content_query_part . + SUBSTRING_FOR_DATE . "(updated,1,19) as updated_noms," . + "score "; + $feed_kind = "Tags"; + $all_tags = explode(",", $feed); + if ($search_mode == 'any') { + $tag_sql = "tag_name in (" . implode(", ", array_map("db_quote", $all_tags)) . ")"; + $from_qpart = " FROM ttrss_entries,ttrss_user_entries,ttrss_tags "; + $where_qpart = " WHERE " . + "ref_id = ttrss_entries.id AND " . + "ttrss_user_entries.owner_uid = $owner_uid AND " . + "post_int_id = int_id AND $tag_sql AND " . + $view_query_part . + $search_query_part . + $query_strategy_part . " ORDER BY $order_by " . + $limit_query_part; - $result = db_query($link, "SELECT DISTINCT - date_entered, - guid, - note, - ttrss_entries.id as id,title, - updated, - unread,feed_id,orig_feed_id, - marked,link,last_read, - ".SUBSTRING_FOR_DATE."(last_read,1,19) as last_read_noms, - $vfeed_query_part - $content_query_part - ".SUBSTRING_FOR_DATE."(updated,1,19) as updated_noms, - score - FROM - ttrss_entries,ttrss_user_entries,ttrss_tags - WHERE - 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 - $search_query_part - $query_strategy_part ORDER BY $order_by - $limit_query_part"); + } else { + $i = 1; + $sub_selects = array(); + $sub_ands = array(); + foreach ($all_tags as $term) { + array_push($sub_selects, "(SELECT post_int_id from ttrss_tags WHERE tag_name = " . db_quote($term) . " AND owner_uid = $owner_uid) as A$i"); + $i++; + } + if ($i > 2) { + $x = 1; + $y = 2; + do { + array_push($sub_ands, "A$x.post_int_id = A$y.post_int_id"); + $x++; + $y++; + } while ($y < $i); + } + array_push($sub_ands, "A1.post_int_id = ttrss_user_entries.int_id and ttrss_user_entries.owner_uid = $owner_uid"); + array_push($sub_ands, "ttrss_user_entries.ref_id = ttrss_entries.id"); + $from_qpart = " FROM " . implode(", ", $sub_selects) . ", ttrss_user_entries, ttrss_entries"; + $where_qpart = " WHERE " . implode(" AND ", $sub_ands); + } + // error_log("TAG SQL: " . $tag_sql); + // $tag_sql = "tag_name = '$feed'"; DEFAULT way + + // error_log("[". $select_qpart . "][" . $from_qpart . "][" .$where_qpart . "]"); + $result = db_query($link, $select_qpart . $from_qpart . $where_qpart); } return array($result, $feed_title, $feed_site_url, $last_error); @@ -3630,7 +3807,8 @@ require_once "lib/MiniTemplator.class.php"; - $note_style = "float : right; background-color : #fff7d5; border-width : 1px; ". + $note_style = "background-color : #fff7d5; + border-width : 1px; ". "padding : 5px; border-style : dashed; border-color : #e7d796;". "margin-bottom : 1em; color : #9a8c59;"; @@ -3652,7 +3830,7 @@ $last_error = $qfh_ret[3]; $feed_self_url = get_self_url_prefix() . - "/backend.php?op=rss&id=-2&key=" . + "/public.php?op=rss&id=-2&key=" . get_feed_access_key($link, -2, false); if (!$feed_site_url) $feed_site_url = get_self_url_prefix(); @@ -3682,7 +3860,7 @@ $content = sanitize_rss($link, $line["content_preview"], false, $owner_uid); if ($line['note']) { - $content = "
" . $line['note'] . "
" . + $content = "
Article note: " . $line['note'] . "
" . $content; } @@ -3749,9 +3927,9 @@ $res = trim($str); if (!$res) return ''; - if (get_pref($link, "STRIP_UNSAFE_TAGS", $owner) || $force_strip_tags) { - $res = $purifier->purify($res); - } +// if (get_pref($link, "STRIP_UNSAFE_TAGS", $owner) || $force_strip_tags) { + $res = $purifier->purify($res); +// } if (get_pref($link, "STRIP_IMAGES", $owner)) { $res = preg_replace('/]+>/is', '', $res); @@ -4061,7 +4239,7 @@ if (PUBSUBHUBBUB_HUB) { $rss_link = get_self_url_prefix() . - "/backend.php?op=rss&id=-2&key=" . + "/public.php?op=rss&id=-2&key=" . get_feed_access_key($link, -2, false); $p = new Publisher(PUBSUBHUBBUB_HUB); @@ -4193,8 +4371,14 @@ if ($is_cat) $cat_q = "&is_cat=$is_cat"; + if ($search) { + $search_q = "&q=$search&m=$match_on&smode=$search_mode"; + } else { + $search_q = ""; + } + $rss_link = htmlspecialchars(get_self_url_prefix() . - "/backend.php?op=rss&id=$feed_id$cat_q$search_q"); + "/public.php?op=rss&id=$feed_id$cat_q$search_q"); $reply .= ""; @@ -4229,7 +4413,7 @@ $fg_color = db_fetch_result($result, 0, "fg_color"); $bg_color = db_fetch_result($result, 0, "bg_color"); - $reply .= ""; + $reply .= ""; $reply .= $feed_title; $reply .= ""; } else { @@ -4241,12 +4425,6 @@ } } - if ($search) { - $search_q = "&q=$search&m=$match_on&smode=$search_mode"; - } else { - $search_q = ""; - } - $reply .= " + value=\"lib/button/musicplayer.swf?song_url=$url\" /> "; } } @@ -4596,8 +4776,7 @@ return $entry; } - function format_article($link, $id, $feed_id, $mark_as_read = true, - $zoom_mode = false) { + function format_article($link, $id, $mark_as_read = true, $zoom_mode = false) { $rv = array(); @@ -4647,6 +4826,7 @@ (SELECT icon_url FROM ttrss_feeds WHERE id = feed_id) as icon_url, (SELECT site_url FROM ttrss_feeds WHERE id = feed_id) as site_url, num_comments, + tag_cache, author, orig_feed_id, note @@ -4720,7 +4900,17 @@ $rv['content'] .= "
" . $line["title"] . "$entry_author
"; } - $tags_str = format_tags_string(get_article_tags($link, $id), $id); + $tag_cache = $line["tag_cache"]; + + if (!$tag_cache) + $tags = get_article_tags($link, $id); + else + $tags = explode(",", $tag_cache); + + $tags_str = format_tags_string($tags, $id); + $tags_str_full = join(", ", $tags); + + if (!$tags_str_full) $tags_str_full = __("no tags"); if (!$entry_comments) $entry_comments = " "; # placeholder @@ -4733,6 +4923,10 @@
(+)"; + $rv['content'] .= "
$tags_str_full
"; + $rv['content'] .= "Zoom"; } + $rv['content'] .= "Zoom"; + $rv['content'] .= "" . - "". - $feed_icon . ""; - $rv['content'] .= "
"; if ($line['note']) { $rv['content'] .= format_article_note($id, $line['note']); } $rv['content'] .= "
"; + $rv['content'] .= ""; + $rv['content'] .= "
"; $article_content = sanitize_rss($link, $line["content"], false, false, @@ -4851,22 +5050,19 @@ $topmost_article_ids = array(); - if (!$offset) { - $offset = 0; - } - + if (!$offset) $offset = 0; if ($subop == "undefined") $subop = ""; - $subop_split = split(":", $subop); + $subop_split = explode(":", $subop); - if ($subop == "CatchupSelected") { - $ids = split(",", db_escape_string($_REQUEST["ids"])); +/* if ($subop == "CatchupSelected") { + $ids = explode(",", db_escape_string($_REQUEST["ids"])); $cmode = sprintf("%d", $_REQUEST["cmode"]); catchupArticlesById($link, $ids, $cmode); - } + } */ - if ($subop == "ForceUpdate" && sprintf("%d", $feed) > 0) { + if ($subop == "ForceUpdate" && $feed && is_numeric($feed) > 0) { update_rss_feed($link, $feed, true); } @@ -4886,7 +5082,7 @@ // FIXME: might break tag display? - if ($feed > 0 && !$cat_view) { + if (is_numeric($feed) && $feed > 0 && !$cat_view) { $result = db_query($link, "SELECT id FROM ttrss_feeds WHERE id = '$feed' LIMIT 1"); @@ -4916,8 +5112,6 @@ $rtl_content = false; } - /// START ///////////////////////////////////////////////////////////////////////////////// - @$search = db_escape_string($_REQUEST["query"]); if ($search) { @@ -4931,12 +5125,15 @@ $match_on = "both"; } - $real_offset = $offset * $limit; - if ($_REQUEST["debug"]) $timing_info = print_checkpoint("H0", $timing_info); +// error_log("format_headlines_list: [" . $feed . "] subop [" . $subop . "]"); + if( $search_mode == '' && $subop != '' ){ + $search_mode = $subop; + } +// error_log("search_mode: " . $search_mode); $qfh_ret = queryFeedHeadlines($link, $feed, $limit, $view_mode, $cat_view, - $search, $search_mode, $match_on, $override_order, $real_offset); + $search, $search_mode, $match_on, $override_order, $offset); if ($_REQUEST["debug"]) $timing_info = print_checkpoint("H1", $timing_info); @@ -4947,36 +5144,50 @@ $vgroup_last_feed = $vgr_last_feed; - /// STOP ////////////////////////////////////////////////////////////////////////////////// - - if (!$offset) { +// if (!$offset) { if (db_num_rows($result) > 0) { - $reply['toolbar'] = format_headline_subtoolbar($link, $feed_site_url, $feed_title, + $reply['toolbar'] = format_headline_subtoolbar($link, $feed_site_url, + $feed_title, $feed, $cat_view, $search, $match_on, $search_mode, $view_mode, $last_error); } - } +// } $headlines_count = db_num_rows($result); if (db_num_rows($result) > 0) { - $lnum = $limit*$offset; + $lnum = $offset; $num_unread = 0; $cur_feed_title = ''; $fresh_intl = get_pref($link, "FRESH_ARTICLE_MAX_AGE") * 60 * 60; + if ($_REQUEST["debug"]) $timing_info = print_checkpoint("PS", $timing_info); + while ($line = db_fetch_assoc($result)) { $class = ($lnum % 2) ? "even" : "odd"; $id = $line["id"]; $feed_id = $line["feed_id"]; + $label_cache = $line["label_cache"]; + $labels = false; + + if ($label_cache) { + $label_cache = json_decode($label_cache, true); + + if ($label_cache) { + if ($label_cache["no-labels"] == 1) + $labels = array(); + else + $labels = $label_cache; + } + } - $labels = get_article_labels($link, $id); + if (!is_array($labels)) $labels = get_article_labels($link, $id); $labels_str = ""; $labels_str .= format_article_labels($labels, $id); @@ -5129,7 +5340,7 @@ $reply['content'] .= "" . - $line["title"]; + truncate_string($line["title"], 200); if (get_pref($link, 'SHOW_CONTENT_PREVIEW')) { if ($content_preview) { @@ -5141,24 +5352,27 @@ $reply['content'] .= $labels_str; - /* if (!get_pref($link, 'VFEED_GROUP_BY_FEED')) { + if (!get_pref($link, 'VFEED_GROUP_BY_FEED') && + defined('_SHOW_FEED_TITLE_IN_VFEEDS')) { if (@$line["feed_title"]) { - print " + $reply['content'] .= " (". $line["feed_title"].") "; } - } */ + } $reply['content'] .= "
"; - $reply['content'] .= "
"; $reply['content'] .= "$updated_fmt"; + $reply['content'] .= "
"; + $reply['content'] .= $score_pic; if ($line["feed_title"] && !get_pref($link, 'VFEED_GROUP_BY_FEED')) { $reply['content'] .= " $feed_icon_img"; } @@ -5203,18 +5417,7 @@ $reply['content'] .= "
"; - $reply['content'] .= "
"; - $reply['content'] .= "$updated_fmt"; - $reply['content'] .= "$score_pic"; - - if (!get_pref($link, "VFEED_GROUP_BY_FEED") && $line["feed_title"]) { - $reply['content'] .= "$feed_icon_img"; - } - $reply['content'] .= "
$update_pic
"; - - $reply['content'] .= "
"; + $reply['content'] .= "
"; $reply['content'] .= ""; @@ -5222,6 +5425,8 @@ $reply['content'] .= "$marked_pic"; $reply['content'] .= "$published_pic"; + $reply['content'] .= "
"; + $reply['content'] .= " @@ -5234,6 +5439,16 @@ $reply['content'] .= $labels_str; + if (!get_pref($link, 'VFEED_GROUP_BY_FEED') && + defined('_SHOW_FEED_TITLE_IN_VFEEDS')) { + if (@$line["feed_title"]) { + $reply['content'] .= " + (". + $line["feed_title"].") + "; + } + } + if (!$expand_cdm) $content_hidden = "style=\"display : none\""; else @@ -5244,6 +5459,18 @@ $reply['content'] .= ""; + $reply['content'] .= "
"; + $reply['content'] .= "$updated_fmt"; + $reply['content'] .= "$score_pic"; + + if (!get_pref($link, "VFEED_GROUP_BY_FEED") && $line["feed_title"]) { + $reply['content'] .= "$feed_icon_img"; + } + $reply['content'] .= "
$update_pic
"; + $reply['content'] .= "
"; + $reply['content'] .= "
"; $reply['content'] .= "
"; if ($line['note']) { $reply['content'] .= format_article_note($id, $line['note']); } $reply['content'] .= "
"; - $reply['content'] .= "$article_content"; + $reply['content'] .= ""; + $reply['content'] .= $expand_cdm ? $article_content : ''; + $reply['content'] .= ""; - $tmp_result = db_query($link, "SELECT always_display_enclosures FROM +/* $tmp_result = db_query($link, "SELECT always_display_enclosures FROM ttrss_feeds WHERE id = ". (($line['feed_id'] == null) ? $line['orig_feed_id'] : - $line['feed_id'])." AND owner_uid = ".$_SESSION["uid"]); + $line['feed_id'])." AND owner_uid = ".$_SESSION["uid"]); $always_display_enclosures = sql_bool_to_bool(db_fetch_result($tmp_result, - 0, "always_display_enclosures")); + 0, "always_display_enclosures")); */ + + $always_display_enclosures = sql_bool_to_bool($line["always_display_enclosures"]); $reply['content'] .= format_article_enclosures($link, $id, $always_display_enclosures, $article_content); @@ -5324,7 +5538,11 @@ $reply['content'] .= "
"; - $tags_str = format_tags_string(get_article_tags($link, $id), $id); + $tag_cache = $line["tag_cache"]; + + $tags_str = format_tags_string( + get_article_tags($link, $id, $_SESSION["uid"], $tag_cache), + $id); $reply['content'] .= "Tags @@ -5332,6 +5550,24 @@ (+)"; + $num_comments = $line["num_comments"]; + $entry_comments = ""; + + if ($num_comments > 0) { + if ($line["comments"]) { + $comments_url = $line["comments"]; + } else { + $comments_url = $line["link"]; + } + $entry_comments = "$num_comments comments"; + } else { + if ($line["comments"] && $line["link"] != $line["comments"]) { + $entry_comments = "comments"; + } + } + + if ($entry_comments) $reply['content'] .= " ($entry_comments)"; + $reply['content'] .= "
"; $reply['content'] .= " 0) print "
"; -# print "
"; -# } - - #print "]]>"; + if ($_REQUEST["debug"]) $timing_info = print_checkpoint("H2", $timing_info); return array($topmost_article_ids, $headlines_count, $feed, $disable_cache, - $vgroup_last_feed, $reply['content'], $reply['toolbar']); + $vgroup_last_feed, $reply); } // from here: http://www.roscripts.com/Create_tag_cloud-71.html @@ -5453,6 +5686,8 @@ $tags[$line["tag_name"]] = $line["count"]; } + if( count($tags) == 0 ){ return; } + ksort($tags); $max_size = 32; // max font size in pixels @@ -5508,22 +5743,9 @@ } function get_self_url_prefix() { - - /* $url_path = ""; - - if ($_SERVER['HTTPS'] != "on") { - $url_path = "http://"; - } else { - $url_path = "https://"; - } - - $url_path .= $_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']); - - return $url_path; */ - return SELF_URL_PATH; - } + function opml_publish_url($link){ $url_path = get_self_url_prefix(); @@ -5631,9 +5853,9 @@ // 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')"; + $updstart_thresh_qpart = "AND (ttrss_feeds.last_update_started IS NULL OR ttrss_feeds.last_update_started < NOW() - INTERVAL '5 minutes')"; } else { - $updstart_thresh_qpart = "AND (ttrss_feeds.last_update_started IS NULL OR ttrss_feeds.last_update_started < DATE_SUB(NOW(), INTERVAL 120 SECOND))"; + $updstart_thresh_qpart = "AND (ttrss_feeds.last_update_started IS NULL OR ttrss_feeds.last_update_started < DATE_SUB(NOW(), INTERVAL 5 MINUTE))"; } // Test if there is a limit to number of updated feeds @@ -5791,11 +6013,11 @@ function update_feedbrowser_cache($link) { - $result = db_query($link, "SELECT feed_url,title, COUNT(id) AS subscribers + $result = db_query($link, "SELECT feed_url, site_url, title, COUNT(id) AS subscribers FROM ttrss_feeds WHERE (SELECT COUNT(id) = 0 FROM ttrss_feeds AS tf WHERE tf.feed_url = ttrss_feeds.feed_url - AND (private IS true OR feed_url LIKE '%:%@%/%')) - GROUP BY feed_url, title ORDER BY subscribers DESC LIMIT 1000"); + AND (private IS true OR auth_login != '' OR auth_pass != '' OR feed_url LIKE '%:%@%/%')) + GROUP BY feed_url, site_url, title ORDER BY subscribers DESC LIMIT 1000"); db_query($link, "BEGIN"); @@ -5807,6 +6029,7 @@ $subscribers = db_escape_string($line["subscribers"]); $feed_url = db_escape_string($line["feed_url"]); $title = db_escape_string($line["title"]); + $site_url = db_escape_string($line["site_url"]); $tmp_result = db_query($link, "SELECT subscribers FROM ttrss_feedbrowser_cache WHERE feed_url = '$feed_url'"); @@ -5814,8 +6037,8 @@ if (db_num_rows($tmp_result) == 0) { db_query($link, "INSERT INTO ttrss_feedbrowser_cache - (feed_url, title, subscribers) VALUES ('$feed_url', - '$title', '$subscribers')"); + (feed_url, site_url, title, subscribers) VALUES ('$feed_url', + '$site_url', '$title', '$subscribers')"); ++$count; @@ -6018,6 +6241,38 @@ return $unread; } + function ccache_cleanup($link, $owner_uid) { + + if (DB_TYPE == "pgsql") { + db_query($link, "DELETE FROM ttrss_counters_cache AS c1 WHERE + (SELECT count(*) FROM ttrss_counters_cache AS c2 + WHERE c1.feed_id = c2.feed_id AND c2.owner_uid = c1.owner_uid) > 1 + AND owner_uid = '$owner_uid'"); + + db_query($link, "DELETE FROM ttrss_cat_counters_cache AS c1 WHERE + (SELECT count(*) FROM ttrss_cat_counters_cache AS c2 + WHERE c1.feed_id = c2.feed_id AND c2.owner_uid = c1.owner_uid) > 1 + AND owner_uid = '$owner_uid'"); + } else { + db_query($link, "DELETE c1 FROM + ttrss_counters_cache AS c1, + ttrss_counters_cache AS c2 + WHERE + c1.owner_uid = '$owner_uid' AND + c1.owner_uid = c2.owner_uid AND + c1.feed_id = c2.feed_id"); + + db_query($link, "DELETE c1 FROM + ttrss_cat_counters_cache AS c1, + ttrss_cat_counters_cache AS c2 + WHERE + c1.owner_uid = '$owner_uid' AND + c1.owner_uid = c2.owner_uid AND + c1.feed_id = c2.feed_id"); + + } + } + function label_find_id($link, $label, $owner_uid) { $result = db_query($link, "SELECT id FROM ttrss_labels2 WHERE caption = '$label' @@ -6261,12 +6516,6 @@ $num_tags = 0; -/* if (get_user_theme($link) == "3pane") { - $tag_limit = 3; - } else { - $tag_limit = 6; - } */ - $tag_limit = 6; $formatted_tags = array(); @@ -6320,8 +6569,9 @@ function format_article_note($id, $note) { - $str = "
$note
"; + $str = "
+
". + __('(edit note)')."
$note
"; return $str; } @@ -6394,9 +6644,9 @@ db_query($link, "COMMIT"); -/* if (file_exists(ICONS_DIR . "/$id.ico")) { + if (file_exists(ICONS_DIR . "/$id.ico")) { unlink(ICONS_DIR . "/$id.ico"); - } */ + } ccache_remove($link, $id, $owner_uid); @@ -6655,7 +6905,8 @@ } function api_get_headlines($link, $feed_id, $limit, $offset, - $filter, $is_cat, $show_excerpt, $show_content, $view_mode, $order) { + $filter, $is_cat, $show_excerpt, $show_content, $view_mode, $order, + $include_attachments, $since_id) { /* do not rely on params below */ @@ -6665,7 +6916,7 @@ $qfh_ret = queryFeedHeadlines($link, $feed_id, $limit, $view_mode, $is_cat, $search, $search_mode, $match_on, - $order, $offset); + $order, $offset, 0, false, $since_id); $result = $qfh_ret[0]; $feed_title = $qfh_ret[1]; @@ -6689,6 +6940,10 @@ "tags" => get_article_tags($link, $line["id"]), ); + if ($include_attachments) + $headline_row['attachments'] = get_article_enclosures($link, + $line['id']); + if ($show_excerpt) { $excerpt = truncate_string(strip_tags($line["content_preview"]), 100); $headline_row["excerpt"] = $excerpt; @@ -7200,4 +7455,372 @@ return $result; } + function filter_to_sql($filter) { + $query = ""; + + if (DB_TYPE == "pgsql") + $reg_qpart = "~"; + else + $reg_qpart = "REGEXP"; + + switch ($filter["type"]) { + case "title": + $query = "LOWER(ttrss_entries.title) $reg_qpart LOWER('". + $filter['reg_exp'] . "')"; + break; + case "content": + $query = "LOWER(ttrss_entries.content) $reg_qpart LOWER('". + $filter['reg_exp'] . "')"; + break; + case "both": + $query = "LOWER(ttrss_entries.title) $reg_qpart LOWER('". + $filter['reg_exp'] . "') OR LOWER(" . + "ttrss_entries.content) $reg_qpart LOWER('" . $filter['reg_exp'] . "')"; + break; + case "tag": + $query = "LOWER(ttrss_user_entries.tag_cache) $reg_qpart LOWER('". + $filter['reg_exp'] . "')"; + break; + case "link": + $query = "LOWER(ttrss_entries.link) $reg_qpart LOWER('". + $filter['reg_exp'] . "')"; + break; + case "date": + + if ($filter["filter_param"] == "before") + $cmp_qpart = "<"; + else + $cmp_qpart = ">="; + + $timestamp = date("Y-m-d H:N:s", strtotime($filter["reg_exp"])); + $query = "ttrss_entries.date_entered $cmp_qpart '$timestamp'"; + break; + case "author": + $query = "LOWER(ttrss_entries.author) $reg_qpart LOWER('". + $filter['reg_exp'] . "')"; + break; + } + + if ($filter["inverse"]) + $query = "NOT ($query)"; + + if ($query) { + if (DB_TYPE == "pgsql") { + $query = " ($query) AND ttrss_entries.date_entered > NOW() - INTERVAL '14 days'"; + } else { + $query = " ($query) AND ttrss_entries.date_entered > DATE_SUB(NOW(), INTERVAL 14 DAY)"; + } + $query .= " AND "; + } + + + return $query; + } + + // Status codes: + // -1 - never connected + // 0 - no data received + // 1 - data received successfully + // 2 - did not receive valid data + // >10 - server error, code + 10 (e.g. 16 means server error 6) + + function get_linked_feeds($link, $instance_id = false) { + if ($instance_id) + $instance_qpart = "id = '$instance_id' AND "; + else + $instance_qpart = ""; + + if (DB_TYPE == "pgsql") { + $date_qpart = "last_connected < NOW() - INTERVAL '6 hours'"; + } else { + $date_qpart = "last_connected < DATE_SUB(NOW(), INTERVAL 6 HOUR)"; + } + + $result = db_query($link, "SELECT id, access_key, access_url FROM ttrss_linked_instances + WHERE $instance_qpart $date_qpart ORDER BY last_connected"); + + while ($line = db_fetch_assoc($result)) { + $id = $line['id']; + + _debug("Updating: " . $line['access_url'] . " ($id)"); + + $fetch_url = $line['access_url'] . '/public.php?op=fbexport'; + $post_query = 'key=' . $line['access_key']; + + $feeds = fetch_file_contents($fetch_url, false, false, false, $post_query); + + // try doing it the old way + if (!$feeds) { + $fetch_url = $line['access_url'] . '/backend.php?op=fbexport'; + $feeds = fetch_file_contents($fetch_url, false, false, false, $post_query); + } + + if ($feeds) { + $feeds = json_decode($feeds, true); + + if ($feeds) { + if ($feeds['error']) { + $status = $feeds['error']['code'] + 10; + } else { + $status = 1; + + if (count($feeds['feeds']) > 0) { + + db_query($link, "DELETE FROM ttrss_linked_feeds + WHERE instance_id = '$id'"); + + foreach ($feeds['feeds'] as $feed) { + $feed_url = db_escape_string($feed['feed_url']); + $title = db_escape_string($feed['title']); + $subscribers = db_escape_string($feed['subscribers']); + $site_url = db_escape_string($feed['site_url']); + + db_query($link, "INSERT INTO ttrss_linked_feeds + (feed_url, site_url, title, subscribers, instance_id, created, updated) + VALUES + ('$feed_url', '$site_url', '$title', '$subscribers', '$id', NOW(), NOW())"); + } + } else { + // received 0 feeds, this might indicate that + // the instance on the other hand is rebuilding feedbrowser cache + // we will try again later + + // TODO: maybe perform expiration based on updated here? + } + + _debug("Processed " . count($feeds['feeds']) . " feeds."); + } + } else { + $status = 2; + } + + } else { + $status = 0; + } + + _debug("Status: $status"); + + db_query($link, "UPDATE ttrss_linked_instances SET + last_status_out = '$status', last_connected = NOW() WHERE id = '$id'"); + + } + } + + function handle_public_request($link, $op) { + switch ($op) { + + case "getUnread": + $login = db_escape_string($_REQUEST["login"]); + $fresh = $_REQUEST["fresh"] == "1"; + + $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); + + if ($fresh) { + print ";"; + print getFeedArticles($link, -3, false, true, $uid); + } + + } else { + print "-1;User not found"; + } + + break; // getUnread + + case "getProfiles": + $login = db_escape_string($_REQUEST["login"]); + $password = db_escape_string($_REQUEST["password"]); + + if (authenticate_user($link, $login, $password)) { + $result = db_query($link, "SELECT * FROM ttrss_settings_profiles + WHERE owner_uid = " . $_SESSION["uid"] . " ORDER BY title"); + + print ""; + + $_SESSION = array(); + } + break; // getprofiles + + case "pubsub": + $mode = db_escape_string($_REQUEST['hub_mode']); + $feed_id = (int) db_escape_string($_REQUEST['id']); + $feed_url = db_escape_string($_REQUEST['hub_topic']); + + if (!PUBSUBHUBBUB_ENABLED) { + header('HTTP/1.0 404 Not Found'); + echo "404 Not found"; + return; + } + + // TODO: implement hub_verifytoken checking + + $result = db_query($link, "SELECT feed_url FROM ttrss_feeds + WHERE id = '$feed_id'"); + + if (db_num_rows($result) != 0) { + + $check_feed_url = db_fetch_result($result, 0, "feed_url"); + + if ($check_feed_url && ($check_feed_url == $feed_url || !$feed_url)) { + if ($mode == "subscribe") { + + db_query($link, "UPDATE ttrss_feeds SET pubsub_state = 2 + WHERE id = '$feed_id'"); + + print $_REQUEST['hub_challenge']; + return; + + } else if ($mode == "unsubscribe") { + + db_query($link, "UPDATE ttrss_feeds SET pubsub_state = 0 + WHERE id = '$feed_id'"); + + print $_REQUEST['hub_challenge']; + return; + + } else if (!$mode) { + + // Received update ping, schedule feed update. + //update_rss_feed($link, $feed_id, true, true); + + db_query($link, "UPDATE ttrss_feeds SET + last_update_started = '1970-01-01', + last_updated = '1970-01-01' WHERE id = '$feed_id' AND + owner_uid = ".$_SESSION["uid"]); + + } + } else { + header('HTTP/1.0 404 Not Found'); + echo "404 Not found"; + } + } else { + header('HTTP/1.0 404 Not Found'); + echo "404 Not found"; + } + + break; // pubsub + + case "logout": + logout_user(); + header("Location: tt-rss.php"); + break; // logout + + case "fbexport": + + $access_key = db_escape_string($_POST["key"]); + + // TODO: rate limit checking using last_connected + $result = db_query($link, "SELECT id FROM ttrss_linked_instances + WHERE access_key = '$access_key'"); + + if (db_num_rows($result) == 1) { + + $instance_id = db_fetch_result($result, 0, "id"); + + $result = db_query($link, "SELECT feed_url, site_url, title, subscribers + FROM ttrss_feedbrowser_cache ORDER BY subscribers DESC LIMIT 100"); + + $feeds = array(); + + while ($line = db_fetch_assoc($result)) { + array_push($feeds, $line); + } + + db_query($link, "UPDATE ttrss_linked_instances SET + last_status_in = 1 WHERE id = '$instance_id'"); + + print json_encode(array("feeds" => $feeds)); + } else { + print json_encode(array("error" => array("code" => 6))); + } + break; // fbexport + + case "share": + $uuid = db_escape_string($_REQUEST["key"]); + + $result = db_query($link, "SELECT ref_id, owner_uid FROM ttrss_user_entries WHERE + uuid = '$uuid'"); + + if (db_num_rows($result) != 0) { + header("Content-Type: text/html"); + + $id = db_fetch_result($result, 0, "ref_id"); + $owner_uid = db_fetch_result($result, 0, "owner_uid"); + + $_SESSION["uid"] = $owner_uid; + $article = format_article($link, $id, false, true); + $_SESSION["uid"] = ""; + + print_r($article['content']); + + } else { + print "Article not found."; + } + + break; + + case "rss": + $feed = db_escape_string($_REQUEST["id"]); + $key = db_escape_string($_REQUEST["key"]); + $is_cat = $_REQUEST["is_cat"] != false; + $limit = (int)db_escape_string($_REQUEST["limit"]); + + $search = db_escape_string($_REQUEST["q"]); + $match_on = db_escape_string($_REQUEST["m"]); + $search_mode = db_escape_string($_REQUEST["smode"]); + $view_mode = db_escape_string($_REQUEST["view-mode"]); + + if (SINGLE_USER_MODE) { + authenticate_user($link, "admin", null); + } + + $owner_id = false; + + if ($key) { + $result = db_query($link, "SELECT owner_uid FROM + ttrss_access_keys WHERE access_key = '$key' AND feed_id = '$feed'"); + + if (db_num_rows($result) == 1) + $owner_id = db_fetch_result($result, 0, "owner_uid"); + } + + if ($owner_id) { + $_SESSION['uid'] = $owner_id; + + generate_syndicated_feed($link, 0, $feed, $is_cat, $limit, + $search, $search_mode, $match_on, $view_mode); + } else { + header('HTTP/1.1 403 Forbidden'); + } + break; // rss + + + case "globalUpdateFeeds": + // Update all feeds needing a update. + update_daemon_common($link, 0, true, true); + break; // globalUpdateFeeds + + + default: + header("Content-Type: text/plain"); + print json_encode(array("error" => array("code" => 7))); + break; // fallback + + } + } ?>