X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=include%2Ffunctions.php;h=b338bde5bc5eb468c43d99db34a61c51a68268c7;hb=8dcb2b47628346226b18940b5cde7849f7a24687;hp=ddd166f3a24d6cfbff093845830bdecace683678;hpb=f9ebb32ca0a84ec5553d0494cdfc628753fcb36a;p=tt-rss.git diff --git a/include/functions.php b/include/functions.php index ddd166f3..b338bde5 100644 --- a/include/functions.php +++ b/include/functions.php @@ -1,6 +1,6 @@ "Italiano", "ja_JP" => "日本語 (Japanese)", "nb_NO" => "Norwegian bokmål", + "pl_PL" => "Polski", "ru_RU" => "Русский", "pt_BR" => "Portuguese/Brazil", "zh_CN" => "Simplified Chinese"); @@ -69,14 +71,11 @@ $lang = _TRANSLATION_OVERRIDE_DEFAULT; } - if ($_COOKIE["ttrss_lang"] && $_COOKIE["ttrss_lang"] != "auto") { - $lang = $_COOKIE["ttrss_lang"]; - } - /* In login action of mobile version */ if ($_POST["language"] && defined('MOBILE_VERSION')) { $lang = $_POST["language"]; - $_COOKIE["ttrss_lang"] = $lang; + } else { + $lang = $_SESSION["language"]; } if ($lang) { @@ -110,8 +109,7 @@ ini_set('user_agent', SELF_USER_AGENT); require_once 'lib/pubsubhubbub/publisher.php'; - - $purifier = false; + require_once 'lib/htmLawed.php'; $tz_offset = -1; $utc_tz = new DateTimeZone('UTC'); @@ -465,151 +463,6 @@ print ""; } - function get_article_filters($filters, $title, $content, $link, $timestamp, $author, $tags) { - $matches = array(); - - if ($filters["title"]) { - foreach ($filters["title"] as $filter) { - $reg_exp = $filter["reg_exp"]; - $inverse = $filter["inverse"]; - if ((!$inverse && @preg_match("/$reg_exp/i", $title)) || - ($inverse && !@preg_match("/$reg_exp/i", $title))) { - - array_push($matches, array($filter["action"], $filter["action_param"])); - } - } - } - - if ($filters["content"]) { - foreach ($filters["content"] as $filter) { - $reg_exp = $filter["reg_exp"]; - $inverse = $filter["inverse"]; - - if ((!$inverse && @preg_match("/$reg_exp/i", $content)) || - ($inverse && !@preg_match("/$reg_exp/i", $content))) { - - array_push($matches, array($filter["action"], $filter["action_param"])); - } - } - } - - if ($filters["both"]) { - foreach ($filters["both"] as $filter) { - $reg_exp = $filter["reg_exp"]; - $inverse = $filter["inverse"]; - - if ($inverse) { - if (!@preg_match("/$reg_exp/i", $title) && !preg_match("/$reg_exp/i", $content)) { - array_push($matches, array($filter["action"], $filter["action_param"])); - } - } else { - if (@preg_match("/$reg_exp/i", $title) || preg_match("/$reg_exp/i", $content)) { - array_push($matches, array($filter["action"], $filter["action_param"])); - } - } - } - } - - if ($filters["link"]) { - $reg_exp = $filter["reg_exp"]; - foreach ($filters["link"] as $filter) { - $reg_exp = $filter["reg_exp"]; - $inverse = $filter["inverse"]; - - if ((!$inverse && @preg_match("/$reg_exp/i", $link)) || - ($inverse && !@preg_match("/$reg_exp/i", $link))) { - - array_push($matches, array($filter["action"], $filter["action_param"])); - } - } - } - - if ($filters["date"]) { - $reg_exp = $filter["reg_exp"]; - foreach ($filters["date"] as $filter) { - $date_modifier = $filter["filter_param"]; - $inverse = $filter["inverse"]; - $check_timestamp = strtotime($filter["reg_exp"]); - - # no-op when timestamp doesn't parse to prevent misfires - - if ($check_timestamp) { - $match_ok = false; - - if ($date_modifier == "before" && $timestamp < $check_timestamp || - $date_modifier == "after" && $timestamp > $check_timestamp) { - $match_ok = true; - } - - if ($inverse) $match_ok = !$match_ok; - - if ($match_ok) { - array_push($matches, array($filter["action"], $filter["action_param"])); - } - } - } - } - - if ($filters["author"]) { - foreach ($filters["author"] as $filter) { - $reg_exp = $filter["reg_exp"]; - $inverse = $filter["inverse"]; - if ((!$inverse && @preg_match("/$reg_exp/i", $author)) || - ($inverse && !@preg_match("/$reg_exp/i", $author))) { - - array_push($matches, array($filter["action"], $filter["action_param"])); - } - } - } - - if ($filters["tag"]) { - - $tag_string = join(",", $tags); - - foreach ($filters["tag"] as $filter) { - $reg_exp = $filter["reg_exp"]; - $inverse = $filter["inverse"]; - - if ((!$inverse && @preg_match("/$reg_exp/i", $tag_string)) || - ($inverse && !@preg_match("/$reg_exp/i", $tag_string))) { - - array_push($matches, array($filter["action"], $filter["action_param"])); - } - } - } - - - return $matches; - } - - function find_article_filter($filters, $filter_name) { - foreach ($filters as $f) { - if ($f[0] == $filter_name) { - return $f; - }; - } - return false; - } - - function calculate_article_score($filters) { - $score = 0; - - foreach ($filters as $f) { - if ($f[0] == "score") { - $score += $f[1]; - }; - } - return $score; - } - - function assign_article_to_labels($link, $id, $filters, $owner_uid) { - foreach ($filters as $f) { - if ($f[0] == "label") { - label_add_article($link, $id, $f[1], $owner_uid); - }; - } - } - function getmicrotime() { list($usec, $sec) = explode(" ",microtime()); return ((float)$usec + (float)$sec); @@ -862,78 +715,30 @@ return true; } - function login_sequence($link, $mobile = false) { - $_SESSION["prefs_cache"] = array(); - - if (!SINGLE_USER_MODE) { - - $login_action = $_POST["login_action"]; - - # try to authenticate user if called from login form - if ($login_action == "do_login") { - $login = db_escape_string($_POST["login"]); - $password = $_POST["password"]; - $remember_me = $_POST["remember_me"]; - - if (authenticate_user($link, $login, $password)) { - $_POST["password"] = ""; - - $_SESSION["language"] = $_POST["language"]; - $_SESSION["ref_schema_version"] = get_schema_version($link, true); - $_SESSION["bw_limit"] = !!$_POST["bw_limit"]; - - if ($_POST["profile"]) { - - $profile = db_escape_string($_POST["profile"]); - - $result = db_query($link, "SELECT id FROM ttrss_settings_profiles - WHERE id = '$profile' AND owner_uid = " . $_SESSION["uid"]); - - if (db_num_rows($result) != 0) { - $_SESSION["profile"] = $profile; - $_SESSION["prefs_cache"] = array(); - } - } - - if ($_REQUEST['return']) { - header("Location: " . $_REQUEST['return']); - } else { - header("Location: " . $_SERVER["REQUEST_URI"]); - } - - exit; - - return; - } else { - $_SESSION["login_error_msg"] = __("Incorrect username or password"); - } - } - + function login_sequence($link, $login_form = 0) { + if (SINGLE_USER_MODE) { + return authenticate_user($link, "admin", null); + } else { if (!$_SESSION["uid"] || !validate_session($link)) { if (AUTH_AUTO_LOGIN && authenticate_user($link, null, null)) { $_SESSION["ref_schema_version"] = get_schema_version($link, true); } else { authenticate_user($link, null, null, true); - render_login_form($link, $mobile); - exit; } + + if (!$_SESSION["uid"]) render_login_form($link, $login_form); + } else { /* bump login timestamp */ db_query($link, "UPDATE ttrss_users SET last_login = NOW() WHERE id = " . $_SESSION["uid"]); - - if ($_SESSION["language"] && SESSION_COOKIE_LIFETIME > 0) { - setcookie("ttrss_lang", $_SESSION["language"], - time() + SESSION_COOKIE_LIFETIME); - } - - // try to remove possible duplicates from feed counter cache -// ccache_cleanup($link, $_SESSION["uid"]); } - } else { - return authenticate_user($link, "admin", null); + if ($_SESSION["uid"] && $_SESSION["language"] && SESSION_COOKIE_LIFETIME > 0) { + setcookie("ttrss_lang", $_SESSION["language"], + time() + SESSION_COOKIE_LIFETIME); + } } } @@ -1251,24 +1056,22 @@ if ($feed >= 0) { if ($feed > 0) { - $cat_qpart = "cat_id = '$feed'"; + $children = getChildCategories($link, $feed, $owner_uid); + array_push($children, $feed); + + $children = join(",", $children); + + $cat_qpart = "cat_id IN ($children)"; } else { $cat_qpart = "cat_id IS NULL"; } - $tmp_result = db_query($link, "SELECT id - FROM ttrss_feeds WHERE $cat_qpart AND owner_uid = $owner_uid"); - - while ($tmp_line = db_fetch_assoc($tmp_result)) { - - $tmp_feed = $tmp_line["id"]; + db_query($link, "UPDATE ttrss_user_entries + SET unread = false,last_read = NOW() + WHERE feed_id IN (SELECT id FROM ttrss_feeds WHERE $cat_qpart) + AND $ref_check_qpart + AND owner_uid = $owner_uid"); - db_query($link, "UPDATE ttrss_user_entries - SET unread = false,last_read = NOW() - WHERE feed_id = '$tmp_feed' - AND $ref_check_qpart - AND owner_uid = $owner_uid"); - } } else if ($feed == -2) { db_query($link, "UPDATE ttrss_user_entries @@ -1397,7 +1200,7 @@ if (db_num_rows($result) == 1) { return db_fetch_result($result, 0, "title"); } else { - return "Uncategorized"; + return __("Uncategorized"); } } } @@ -1431,8 +1234,7 @@ } $cv = array("id" => $line["cat_id"], "kind" => "cat", - "child_counter" => $child_counter, - "counter" => $line["unread"]); + "counter" => $line["unread"] + $child_counter); array_push($ret_arr, $cv); } @@ -1440,7 +1242,7 @@ /* Special case: NULL category doesn't actually exist in the DB */ $cv = array("id" => 0, "kind" => "cat", - "counter" => ccache_find($link, 0, $_SESSION["uid"], true)); + "counter" => (int) ccache_find($link, 0, $_SESSION["uid"], true)); array_push($ret_arr, $cv); @@ -1650,7 +1452,7 @@ } $cv = array("id" => "global-unread", - "counter" => $global_unread); + "counter" => (int) $global_unread); array_push($ret_arr, $cv); @@ -1660,7 +1462,7 @@ $subscribed_feeds = db_fetch_result($result, 0, "fn"); $cv = array("id" => "subscribed-feeds", - "counter" => $subscribed_feeds); + "counter" => (int) $subscribed_feeds); array_push($ret_arr, $cv); @@ -1706,7 +1508,7 @@ $count = getFeedUnread($link, $i); $cv = array("id" => $i, - "counter" => $count); + "counter" => (int) $count); // if (get_pref($link, 'EXTENDED_FEEDLIST')) // $cv["xmsg"] = getFeedArticles($link, $i)." ".__("total"); @@ -1734,7 +1536,7 @@ $count = getFeedUnread($link, $id); $cv = array("id" => $id, - "counter" => $count); + "counter" => (int) $count); if ($descriptions) $cv["description"] = $label_name; @@ -1779,7 +1581,7 @@ $cv = array("id" => $id, "updated" => $last_updated, - "counter" => $count, + "counter" => (int) $count, "has_img" => (int) $has_img); if ($last_error) @@ -1829,32 +1631,24 @@ $update_method = 0; - $result = db_query($link, "SELECT twitter_oauth FROM ttrss_users - WHERE id = ".$_SESSION['uid']); + $contents = @fetch_file_contents($url, false, $auth_login, $auth_pass); - $has_oauth = db_fetch_result($result, 0, 'twitter_oauth'); + if (!$contents) { + return array("code" => 5, "message" => $fetch_last_error); + } - if (!$need_auth || !$has_oauth || strpos($url, '://api.twitter.com') === false) { - if (!fetch_file_contents($url, false, $auth_login, $auth_pass)) - return array("code" => 5, "message" => $fetch_last_error); + if (is_html($contents)) { + $feedUrls = get_feeds_from_html($url, $contents); - if (url_is_html($url, $auth_login, $auth_pass)) { - $feedUrls = get_feeds_from_html($url, $auth_login, $auth_pass); - if (count($feedUrls) == 0) { - return array("code" => 3); - } else if (count($feedUrls) > 1) { - return array("code" => 4); - } - //use feed url as new URL - $url = key($feedUrls); + if (count($feedUrls) == 0) { + return array("code" => 3); + } else if (count($feedUrls) > 1) { + return array("code" => 4, "feeds" => $feedUrls); } + //use feed url as new URL + $url = key($feedUrls); + } - } else { - if (!fetch_twitter_rss($link, $url, $_SESSION['uid'])) - return array("code" => 5); - - $update_method = 3; - } if ($cat_id == "0" || !$cat_id) { $cat_qpart = "NULL"; } else { @@ -2093,8 +1887,10 @@ } } - function getFeedTitle($link, $id) { - if ($id == -1) { + function getFeedTitle($link, $id, $cat = false) { + if ($cat) { + return getCategoryTitle($link, $id); + } else if ($id == -1) { return __("Starred articles"); } else if ($id == -2) { return __("Published articles"); @@ -2148,7 +1944,6 @@ $params["icons_url"] = ICONS_URL; $params["cookie_lifetime"] = SESSION_COOKIE_LIFETIME; - $params["default_include_children"] = get_pref($link, "_DEFAULT_INCLUDE_CHILDREN"); $params["default_view_mode"] = get_pref($link, "_DEFAULT_VIEW_MODE"); $params["default_view_limit"] = (int) get_pref($link, "_DEFAULT_VIEW_LIMIT"); $params["default_view_order_by"] = get_pref($link, "_DEFAULT_VIEW_ORDER_BY"); @@ -2286,6 +2081,20 @@ return $search_query_part; } + function getParentCategories($link, $cat, $owner_uid) { + $rv = array(); + + $result = db_query($link, "SELECT parent_cat FROM ttrss_feed_categories + WHERE id = '$cat' AND parent_cat IS NOT NULL AND owner_uid = $owner_uid"); + + while ($line = db_fetch_assoc($result)) { + array_push($rv, $line["parent_cat"]); + $rv = array_merge($rv, getParentCategories($link, $line["parent_cat"], $owner_uid)); + } + + return $rv; + } + function getChildCategories($link, $cat, $owner_uid) { $rv = array(); @@ -2326,7 +2135,30 @@ } if ($filter) { - $filter_query_part = filter_to_sql($filter); + + if (DB_TYPE == "pgsql") { + $query_strategy_part .= " AND updated > NOW() - INTERVAL '14 days' "; + } else { + $query_strategy_part .= " AND updated > DATE_SUB(NOW(), INTERVAL 14 DAY) "; + } + + $override_order = "updated DESC"; + + $filter_query_part = filter_to_sql($link, $filter, $owner_uid); + + // Try to check if SQL regexp implementation chokes on a valid regexp + $result = db_query($link, "SELECT true AS true FROM ttrss_entries, + ttrss_user_entries, ttrss_feeds, ttrss_feed_categories + WHERE $filter_query_part LIMIT 1", false); + + $test = db_fetch_result($result, 0, "true"); + + if (!$test) { + $filter_query_part = "false AND"; + } else { + $filter_query_part .= " AND"; + } + } else { $filter_query_part = ""; } @@ -2374,44 +2206,35 @@ $limit_query_part = "LIMIT " . $limit; } + $allow_archived = false; + $vfeed_query_part = ""; // override query strategy and enable feed display when searching globally if ($search && $search_mode == "all_feeds") { - $query_strategy_part = "ttrss_entries.id > 0"; + $query_strategy_part = "true"; $vfeed_query_part = "ttrss_feeds.title AS feed_title,"; /* tags */ - } else if (preg_match("/^-?[0-9][0-9]*$/", $feed) == false) { - $query_strategy_part = "ttrss_entries.id > 0"; + } else if (!is_numeric($feed)) { + $query_strategy_part = "true"; $vfeed_query_part = "(SELECT title FROM ttrss_feeds WHERE id = feed_id) as feed_title,"; - } else if ($feed > 0 && $search && $search_mode == "this_cat") { - + } else if ($search && $search_mode == "this_cat") { $vfeed_query_part = "ttrss_feeds.title AS feed_title,"; - $tmp_result = false; - - if ($cat_view) { - $tmp_result = db_query($link, "SELECT id - FROM ttrss_feeds WHERE cat_id = '$feed'"); - } else { - $tmp_result = db_query($link, "SELECT id - FROM ttrss_feeds WHERE cat_id = (SELECT cat_id FROM ttrss_feeds - WHERE id = '$feed') AND id != '$feed'"); - } - - $cat_siblings = array(); - - if (db_num_rows($tmp_result) > 0) { - while ($p = db_fetch_assoc($tmp_result)) { - array_push($cat_siblings, "feed_id = " . $p["id"]); + if ($feed > 0) { + if ($include_children) { + $subcats = getChildCategories($link, $feed, $owner_uid); + array_push($subcats, $feed); + $cats_qpart = join(",", $subcats); + } else { + $cats_qpart = $feed; } - $query_strategy_part = sprintf("(feed_id = %d OR %s)", - $feed, implode(" OR ", $cat_siblings)); + $query_strategy_part = "ttrss_feeds.cat_id IN ($cats_qpart)"; } else { - $query_strategy_part = "ttrss_entries.id > 0"; + $query_strategy_part = "ttrss_feeds.cat_id IS NULL"; } } else if ($feed > 0) { @@ -2423,13 +2246,10 @@ # sub-cats $subcats = getChildCategories($link, $feed, $owner_uid); - if (count($subcats) == 0) { - $query_strategy_part = "cat_id = '$feed'"; - } else { - array_push($subcats, $feed); - $query_strategy_part = "cat_id IN (". + array_push($subcats, $feed); + $query_strategy_part = "cat_id IN (". implode(",", $subcats).")"; - } + } else { $query_strategy_part = "cat_id = '$feed'"; } @@ -2445,17 +2265,23 @@ } } else if ($feed == 0 && !$cat_view) { // archive virtual feed $query_strategy_part = "feed_id IS NULL"; + $allow_archived = true; } else if ($feed == 0 && $cat_view) { // uncategorized $query_strategy_part = "cat_id IS NULL AND feed_id IS NOT NULL"; $vfeed_query_part = "ttrss_feeds.title AS feed_title,"; } else if ($feed == -1) { // starred virtual feed $query_strategy_part = "marked = true"; $vfeed_query_part = "ttrss_feeds.title AS feed_title,"; + $allow_archived = true; + } else if ($feed == -2) { // published virtual feed OR labels category if (!$cat_view) { $query_strategy_part = "published = true"; $vfeed_query_part = "ttrss_feeds.title AS feed_title,"; + $allow_archived = true; + + if (!$override_order) $override_order = "last_read DESC, updated DESC"; } else { $vfeed_query_part = "ttrss_feeds.title AS feed_title,"; @@ -2468,7 +2294,9 @@ } else if ($feed == -6) { // recently read $query_strategy_part = "unread = false AND last_read IS NOT NULL"; $vfeed_query_part = "ttrss_feeds.title AS feed_title,"; - $override_order = "last_read DESC"; + $allow_archived = true; + + if (!$override_order) $override_order = "last_read DESC"; } else if ($feed == -3) { // fresh virtual feed $query_strategy_part = "unread = true AND score >= 0"; @@ -2493,9 +2321,10 @@ $vfeed_query_part = "ttrss_feeds.title AS feed_title,"; $ext_tables_part = ",ttrss_labels2,ttrss_user_labels2"; + $allow_archived = true; } else { - $query_strategy_part = "id > 0"; // dumb + $query_strategy_part = "true"; } if (get_pref($link, "SORT_HEADLINES_BY_FEED_DATE", $owner_uid)) { @@ -2521,7 +2350,7 @@ $feed_title = ""; if ($search) { - $feed_title = "Search results"; + $feed_title = T_sprintf("Search results: %s", $search); } else { if ($cat_view) { $feed_title = getCategoryTitle($link, $feed); @@ -2539,9 +2368,9 @@ } } - $content_query_part = "content as content_preview,"; + $content_query_part = "content as content_preview, cached_content, "; - if (preg_match("/^-?[0-9][0-9]*$/", $feed) != false) { + if (is_numeric($feed)) { if ($feed >= 0) { $feed_kind = "Feeds"; @@ -2553,18 +2382,21 @@ $offset_query_part = "OFFSET $offset"; } + // proper override_order applied above if ($vfeed_query_part && get_pref($link, 'VFEED_GROUP_BY_FEED', $owner_uid)) { if (!$override_order) { $order_by = "ttrss_feeds.title, $order_by"; + } else { + $order_by = "ttrss_feeds.title, $override_order"; } } - if ($feed != "0") { + if (!$allow_archived) { $from_qpart = "ttrss_entries,ttrss_user_entries,ttrss_feeds$ext_tables_part"; $feed_check_qpart = "ttrss_user_entries.feed_id = ttrss_feeds.id AND"; } else { - $from_qpart = "ttrss_entries,ttrss_user_entries$ext_tables_part + $from_qpart = "ttrss_entries$ext_tables_part,ttrss_user_entries LEFT JOIN ttrss_feeds ON (feed_id = ttrss_feeds.id)"; } @@ -2679,36 +2511,12 @@ } function sanitize($link, $str, $force_strip_tags = false, $owner = false, $site_url = false) { - global $purifier; - if (!$owner) $owner = $_SESSION["uid"]; $res = trim($str); if (!$res) return ''; - // create global Purifier object if needed - if (!$purifier) { - require_once 'lib/htmlpurifier/library/HTMLPurifier.auto.php'; - - $config = HTMLPurifier_Config::createDefault(); - - $allowed = "p,a[href],i,em,b,strong,code,pre,blockquote,br,img[src|alt|title|align|hspace],ul,ol,li,h1,h2,h3,h4,s,object[classid|type|id|name|width|height|codebase],param[name|value],table,tr,td,span[class]"; - - $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('Filter.YouTube', true); - - $purifier = new HTMLPurifier($config); - } - - $res = $purifier->purify($res); + $config = array('safe' => 1, 'deny_attribute' => 'style, width, height, class, id', 'comment' => 1, 'cdata' => 1); + $res = htmLawed($res, $config); if (get_pref($link, "STRIP_IMAGES", $owner)) { $res = preg_replace('/]+>/is', '', $res); @@ -3041,7 +2849,7 @@ WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]); } else if ($cmode == 1) { db_query($link, "UPDATE ttrss_user_entries SET - published = true + published = true,last_read = NOW() WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]); } else { db_query($link, "UPDATE ttrss_user_entries SET @@ -3189,17 +2997,16 @@ return true; } - function render_login_form($link, $mobile = 0) { - switch ($mobile) { + function render_login_form($link, $form_id = 0) { + switch ($form_id) { case 0: require_once "login_form.php"; break; case 1: require_once "mobile/login_form.php"; break; - case 2: - require_once "mobile/classic/login_form.php"; } + exit; } // from http://developer.apple.com/internet/safari/faq.html @@ -3305,15 +3112,17 @@ //if (!$zoom_mode) { print "
0) { if ($line["comments"]) { - $comments_url = $line["comments"]; + $comments_url = htmlspecialchars($line["comments"]); } else { - $comments_url = $line["link"]; + $comments_url = htmlspecialchars($line["link"]); } $entry_comments = "$num_comments comments"; } else { if ($line["comments"] && $line["link"] != $line["comments"]) { - $entry_comments = "comments"; + $entry_comments = "comments"; } } @@ -3381,7 +3191,7 @@ "; } - $title_escaped = db_escape_string($line['title']); + $title_escaped = htmlspecialchars($line['title']); $rv['content'] .= "
" . truncate_string(strip_tags($line['title']), 15) . "
"; @@ -3406,14 +3216,14 @@ $rv['content'] .= "
$parsed_updated
"; if ($line["link"]) { - $rv['content'] .= ""; } else { - $rv['content'] .= "
" . $line["title"] . "$entry_author
"; + $rv['content'] .= "
" . $line["title"] . "$entry_author
"; } $tag_cache = $line["tag_cache"]; @@ -3448,15 +3258,10 @@ onclick=\"postOpenInNewTab(event, $id)\" alt='Zoom' title='".__('Open article in new tab')."'>"; - $button_plugins = explode(",", ARTICLE_BUTTON_PLUGINS); - - foreach ($button_plugins as $p) { - $pclass = trim("button_${p}"); + global $pluginhost; - if (class_exists($pclass)) { - $plugin = new $pclass($link); - $rv['content'] .= $plugin->render($id, $line); - } + foreach ($pluginhost->get_hooks($pluginhost::HOOK_ARTICLE_BUTTON) as $p) { + $rv['content'] .= $p->hook_article_button($line); } $rv['content'] .= "/", "", $text); - return $text; - } - - function load_filters($link, $feed, $owner_uid, $action_id = false) { + function load_filters($link, $feed_id, $owner_uid, $action_id = false) { $filters = array(); + $cat_id = (int)getFeedCategory($link, $feed_id); - if ($action_id) $ftype_query_part = "action_id = '$action_id' AND"; + $result = db_query($link, "SELECT * FROM ttrss_filters2 WHERE + owner_uid = $owner_uid AND enabled = true"); - $result = db_query($link, "SELECT reg_exp, - ttrss_filter_types.name AS name, - ttrss_filter_actions.name AS action, - inverse, - action_param, - filter_param - FROM ttrss_filters - LEFT JOIN ttrss_feeds ON (ttrss_feeds.id = '$feed'), - ttrss_filter_types,ttrss_filter_actions - WHERE - enabled = true AND - $ftype_query_part - ttrss_filters.owner_uid = $owner_uid AND - ttrss_filter_types.id = filter_type AND - ttrss_filter_actions.id = action_id AND - ((cat_filter = true AND ttrss_feeds.cat_id = ttrss_filters.cat_id) OR - (cat_filter = true AND ttrss_feeds.cat_id IS NULL AND - ttrss_filters.cat_id IS NULL) OR - (cat_filter = false AND (feed_id IS NULL OR feed_id = '$feed'))) - ORDER BY reg_exp"); + $check_cats = join(",", array_merge( + getParentCategories($link, $cat_id, $owner_uid), + array($cat_id))); while ($line = db_fetch_assoc($result)) { + $filter_id = $line["id"]; + + $result2 = db_query($link, "SELECT + r.reg_exp, r.feed_id, r.cat_id, r.cat_filter, t.name AS type_name + FROM ttrss_filters2_rules AS r, + ttrss_filter_types AS t + WHERE + (cat_id IS NULL OR cat_id IN ($check_cats)) AND + (feed_id IS NULL OR feed_id = '$feed_id') AND + filter_type = t.id AND filter_id = '$filter_id'"); + + $rules = array(); + $actions = array(); + + while ($rule_line = db_fetch_assoc($result2)) { +# print_r($rule_line); + + $rule = array(); + $rule["reg_exp"] = $rule_line["reg_exp"]; + $rule["type"] = $rule_line["type_name"]; + + array_push($rules, $rule); + } + + $result2 = db_query($link, "SELECT a.action_param,t.name AS type_name + FROM ttrss_filters2_actions AS a, + ttrss_filter_actions AS t + WHERE + action_id = t.id AND filter_id = '$filter_id'"); + + while ($action_line = db_fetch_assoc($result2)) { +# print_r($action_line); - if (!$filters[$line["name"]]) $filters[$line["name"]] = array(); - $filter["reg_exp"] = $line["reg_exp"]; - $filter["action"] = $line["action"]; - $filter["action_param"] = $line["action_param"]; - $filter["filter_param"] = $line["filter_param"]; - $filter["inverse"] = sql_bool_to_bool($line["inverse"]); + $action = array(); + $action["type"] = $action_line["type_name"]; + $action["param"] = $action_line["action_param"]; - array_push($filters[$line["name"]], $filter); + array_push($actions, $action); } + $filter = array(); + $filter["match_any_rule"] = sql_bool_to_bool($line["match_any_rule"]); + $filter["rules"] = $rules; + $filter["actions"] = $actions; + + if (count($rules) > 0 && count($actions) > 0) { + array_push($filters, $filter); + } + } + return $filters; } @@ -3726,6 +3556,12 @@ db_query($link, "SET NAMES " . MYSQL_CHARSET); } } + + global $pluginhost; + + $pluginhost = new PluginHost($link); + $pluginhost->load(PLUGINS); + return true; } else { print "Unable to connect to database:" . db_last_error(); @@ -3966,24 +3802,26 @@ } } - function get_article_labels($link, $id) { + function get_article_labels($link, $id, $owner_uid = false) { $rv = array(); + if (!$owner_uid) $owner_uid = $_SESSION["uid"]; $result = db_query($link, "SELECT label_cache FROM ttrss_user_entries WHERE ref_id = '$id' AND owner_uid = " . - $_SESSION["uid"]); - - $label_cache = db_fetch_result($result, 0, "label_cache"); + $owner_uid); - if ($label_cache) { + if (db_num_rows($result) > 0) { + $label_cache = db_fetch_result($result, 0, "label_cache"); - $label_cache = json_decode($label_cache, true); + if ($label_cache) { + $label_cache = json_decode($label_cache, true); - if ($label_cache["no-labels"] == 1) - return $rv; - else - return $label_cache; + if ($label_cache["no-labels"] == 1) + return $rv; + else + return $label_cache; + } } $result = db_query($link, @@ -3991,7 +3829,7 @@ FROM ttrss_labels2, ttrss_user_labels2 WHERE id = label_id AND article_id = '$id' - AND owner_uid = ".$_SESSION["uid"] . " + AND owner_uid = ". $owner_uid . " ORDER BY caption"); while ($line = db_fetch_assoc($result)) { @@ -4001,9 +3839,9 @@ } if (count($rv) > 0) - label_update_cache($link, $id, $rv); + label_update_cache($link, $owner_uid, $id, $rv); else - label_update_cache($link, $id, array("no-labels" => 1)); + label_update_cache($link, $owner_uid, $id, array("no-labels" => 1)); return $rv; } @@ -4021,7 +3859,19 @@ } } - function label_update_cache($link, $id, $labels = false, $force = false) { + function get_all_labels($link, $owner_uid) { + $rv = array(); + + $result = db_query($link, "SELECT fg_color, bg_color, caption FROM ttrss_labels2 WHERE owner_uid = " . $owner_uid); + + while ($line = db_fetch_assoc($result)) { + array_push($rv, $line); + } + + return $rv; + } + + function label_update_cache($link, $owner_uid, $id, $labels = false, $force = false) { if ($force) label_clear_cache($link, $id); @@ -4032,7 +3882,7 @@ $labels = db_escape_string(json_encode($labels)); db_query($link, "UPDATE ttrss_user_entries SET - label_cache = '$labels' WHERE ref_id = '$id'"); + label_cache = '$labels' WHERE ref_id = '$id' AND owner_uid = '$owner_uid'"); } @@ -4448,7 +4298,7 @@ return $rv; } - function api_get_feeds($link, $cat_id, $unread_only, $limit, $offset) { + function api_get_feeds($link, $cat_id, $unread_only, $limit, $offset, $include_nested = false) { $feeds = array(); @@ -4478,7 +4328,7 @@ /* Virtual feeds */ if ($cat_id == -4 || $cat_id == -1) { - foreach (array(-1, -2, -3, -4, 0) as $i) { + foreach (array(-1, -2, -3, -4, -6, 0) as $i) { $unread = getFeedUnread($link, $i); if ($unread || !$unread_only) { @@ -4496,6 +4346,30 @@ } } + /* Child cats */ + + if ($include_nested && $cat_id) { + $result = db_query($link, "SELECT + id, title FROM ttrss_feed_categories + WHERE parent_cat = '$cat_id' AND owner_uid = " . $_SESSION["uid"] . + " ORDER BY id, title"); + + while ($line = db_fetch_assoc($result)) { + $unread = getFeedUnread($link, $line["id"], true) + + getCategoryChildrenUnread($link, $line["id"]); + + if ($unread || !$unread_only) { + $row = array( + "id" => $line["id"], + "title" => $line["title"], + "unread" => $unread, + "is_cat" => true, + ); + array_push($feeds, $row); + } + } + } + /* Real feeds */ if ($limit) { @@ -4554,11 +4428,12 @@ function api_get_headlines($link, $feed_id, $limit, $offset, $filter, $is_cat, $show_excerpt, $show_content, $view_mode, $order, $include_attachments, $since_id, - $search = "", $search_mode = "", $match_on = "") { + $search = "", $search_mode = "", $match_on = "", + $include_nested = false, $sanitize_content = true) { $qfh_ret = queryFeedHeadlines($link, $feed_id, $limit, $view_mode, $is_cat, $search, $search_mode, $match_on, - $order, $offset, 0, false, $since_id); + $order, $offset, 0, false, $since_id, $include_nested); $result = $qfh_ret[0]; $feed_title = $qfh_ret[1]; @@ -4598,7 +4473,17 @@ } if ($show_content) { - $headline_row["content"] = $line["content_preview"]; + + if ($line["cached_content"] != "") { + $line["content_preview"] =& $line["cached_content"]; + } + + if ($sanitize_content) { + $headline_row["content"] = sanitize($link, + $line["content_preview"], false, false, $line["site_url"]); + } else { + $headline_row["content"] = $line["content_preview"]; + } } // unify label output to ease parsing @@ -4608,6 +4493,11 @@ $headline_row["feed_title"] = $line["feed_title"]; + $headline_row["comments_count"] = (int)$line["num_comments"]; + $headline_row["comments_link"] = $line["comments"]; + + $headline_row["always_display_attachments"] = sql_bool_to_bool($line["always_display_enclosures"]); + array_push($headlines, $headline_row); } @@ -4728,22 +4618,13 @@ return false; } - /** - * Extracts RSS/Atom feed URLs from the given HTML URL. - * - * @param string $url HTML page URL - * - * @return array Array of feeds. Key is the full URL, value the title - */ - function get_feeds_from_html($url, $login = false, $pass = false) + function get_feeds_from_html($url, $content) { $url = fix_url($url); $baseUrl = substr($url, 0, strrpos($url, '/') + 1); libxml_use_internal_errors(true); - $content = @fetch_file_contents($url, false, $login, $pass); - $doc = new DOMDocument(); $doc->loadHTML($content); $xpath = new DOMXPath($doc); @@ -4764,23 +4645,12 @@ return $feedUrls; } - /** - * Checks if the content behind the given URL is a HTML file - * - * @param string $url URL to check - * - * @return boolean True if the URL contains HTML content - */ - function url_is_html($url, $login = false, $pass = false) { - $content = substr(fetch_file_contents($url, false, $login, $pass), 0, 1000); - - if (stripos($content, '') === false - && stripos($content, ' 0) { + $qpart .= " AND feed_id = " . db_escape_string($rule["feed_id"]); + } - $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 (isset($rule["cat_id"])) { - if ($filter["inverse"]) - $query = "NOT ($query)"; + if ($rule["cat_id"] > 0) { + $children = getChildCategories($link, $rule["cat_id"], $owner_uid); + array_push($children, $rule["cat_id"]); - 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)"; + $children = join(",", $children); + + $cat_qpart = "cat_id IN ($children)"; + } else { + $cat_qpart = "cat_id IS NULL"; + } + + $qpart .= " AND $cat_qpart"; } - $query .= " AND "; + + array_push($query, "($qpart)"); + } + } - return $query; + if (count($query) > 0) { + return "(" . join($filter["match_any_rule"] ? "OR" : "AND", $query) . ")"; } else { - return false; + return "(false)"; } } @@ -5186,6 +5063,12 @@ if ($feeds) { if ($feeds['error']) { $status = $feeds['error']['code'] + 10; + + // access denied + if ($status == 16) { + db_query($link, "DELETE FROM ttrss_linked_feeds + WHERE instance_id = '$id'"); + } } else { $status = 1; @@ -5595,4 +5478,106 @@ return $tempname; } + function getFeedCategory($link, $feed) { + $result = db_query($link, "SELECT cat_id FROM ttrss_feeds + WHERE id = '$feed'"); + + if (db_num_rows($result) > 0) { + return db_fetch_result($result, 0, "cat_id"); + } else { + return false; + } + + } + + function create_published_article($link, $title, $url, $content, $labels_str, + $owner_uid) { + + $guid = sha1($url . $owner_uid); // include owner_uid to prevent global GUID clash + $content_hash = sha1($content); + + if ($labels_str != "") { + $labels = explode(",", $labels_str); + } else { + $labels = array(); + } + + $rc = false; + + if (!$title) $title = $url; + if (!$title && !$url) return false; + + if (filter_var($url, FILTER_VALIDATE_URL) === FALSE) return false; + + db_query($link, "BEGIN"); + + // only check for our user data here, others might have shared this with different content etc + $result = db_query($link, "SELECT id FROM ttrss_entries, ttrss_user_entries WHERE + link = '$url' AND ref_id = id AND owner_uid = '$owner_uid' LIMIT 1"); + + if (db_num_rows($result) != 0) { + $ref_id = db_fetch_result($result, 0, "id"); + + $result = db_query($link, "SELECT int_id FROM ttrss_user_entries WHERE + ref_id = '$ref_id' AND owner_uid = '$owner_uid' LIMIT 1"); + + if (db_num_rows($result) != 0) { + $int_id = db_fetch_result($result, 0, "int_id"); + + db_query($link, "UPDATE ttrss_entries SET + content = '$content', content_hash = '$content_hash' WHERE id = '$ref_id'"); + + db_query($link, "UPDATE ttrss_user_entries SET published = true WHERE + int_id = '$int_id' AND owner_uid = '$owner_uid'"); + } else { + + db_query($link, "INSERT INTO ttrss_user_entries + (ref_id, uuid, feed_id, orig_feed_id, owner_uid, published, tag_cache, label_cache, last_read, note, unread) + VALUES + ('$ref_id', '', NULL, NULL, $owner_uid, true, '', '', NOW(), '', false)"); + } + + if (count($labels) != 0) { + foreach ($labels as $label) { + label_add_article($link, $ref_id, trim($label), $owner_uid); + } + } + + $rc = true; + + } else { + $result = db_query($link, "INSERT INTO ttrss_entries + (title, guid, link, updated, content, content_hash, date_entered, date_updated) + VALUES + ('$title', '$guid', '$url', NOW(), '$content', '$content_hash', NOW(), NOW())"); + + $result = db_query($link, "SELECT id FROM ttrss_entries WHERE guid = '$guid'"); + + if (db_num_rows($result) != 0) { + $ref_id = db_fetch_result($result, 0, "id"); + + db_query($link, "INSERT INTO ttrss_user_entries + (ref_id, uuid, feed_id, orig_feed_id, owner_uid, published, tag_cache, label_cache, last_read, note, unread) + VALUES + ('$ref_id', '', NULL, NULL, $owner_uid, true, '', '', NOW(), '', false)"); + + if (count($labels) != 0) { + foreach ($labels as $label) { + label_add_article($link, $ref_id, trim($label), $owner_uid); + } + } + + $rc = true; + } + } + + db_query($link, "COMMIT"); + + return $rc; + } + + function implements_interface($class, $interface) { + return in_array($interface, class_implements($class)); + } + ?>