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 = "