]> git.wh0rd.org - tt-rss.git/blobdiff - functions.php
add function to open article summary in a popup window
[tt-rss.git] / functions.php
index 024232e9ae012a5e172071063eb0d610d58471d2..701d3ec57f59140aa0182a47d9e4b78915925806 100644 (file)
@@ -8,6 +8,12 @@
 
        require_once 'config.php';
 
+       if (DB_TYPE == "pgsql") {
+               define('SUBSTRING_FOR_DATE', 'SUBSTRING_FOR_DATE');
+       } else {
+               define('SUBSTRING_FOR_DATE', 'SUBSTRING');
+       }
+
        /**
         * Return available translations names.
         * 
@@ -20,7 +26,7 @@
                                        "en_US" => "English",
                                        "fr_FR" => "Français",
                                        "hu_HU" => "Magyar (Hungarian)",
-                                       "nb_NO" => "Norsk Bokmål",
+                                       "nb_NO" => "Norwegian bokmål",
                                        "ru_RU" => "Русский",
                                        "pt_BR" => "Portuguese/Brazil",
                                        "zh_CN" => "Simplified Chinese");
                        }
 
                        if ($lang) {
-                               _setlocale(LC_MESSAGES, $lang);
+                               if (defined('LC_MESSAGES')) {
+                                       _setlocale(LC_MESSAGES, $lang);
+                               } else if (defined('LC_ALL')) {
+                                       _setlocale(LC_ALL, $lang);
+                               } else {
+                                       die("can't setlocale(): please set ENABLE_TRANSLATIONS to false in config.php");
+                               }
                                _bindtextdomain("messages", "locale");
                                _textdomain("messages");
                                _bind_textdomain_codeset("messages", "UTF-8");
                }
 
                $result = db_query($link, "SELECT feed_url,id,
-                       SUBSTRING(last_updated,1,19) AS last_updated,
+                       ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated,
                        update_interval FROM ttrss_feeds WHERE owner_uid = '$user_id'
                        ORDER BY $q_order");
 
                                _debug("update_rss_feed: loading filters...");
                        }
 
-                       $filters = array();
-
-                       $result = db_query($link, "SELECT reg_exp,
-                               ttrss_filter_types.name AS name,
-                               ttrss_filter_actions.name AS action,
-                               inverse,
-                               action_param
-                               FROM ttrss_filters,ttrss_filter_types,ttrss_filter_actions WHERE                                        
-                                       enabled = true AND
-                                       owner_uid = $owner_uid AND
-                                       ttrss_filter_types.id = filter_type AND
-                                       ttrss_filter_actions.id = action_id AND
-                               (feed_id IS NULL OR feed_id = '$feed') ORDER BY reg_exp");
-
-                       while ($line = db_fetch_assoc($result)) {
-                               if (!$filters[$line["name"]]) $filters[$line["name"]] = array();
-
-                               $filter["reg_exp"] = $line["reg_exp"];
-                               $filter["action"] = $line["action"];
-                               $filter["action_param"] = $line["action_param"];
-                               $filter["inverse"] = sql_bool_to_bool($line["inverse"]);
-                       
-                               array_push($filters[$line["name"]], $filter);
-                       }
+                       $filters = load_filters($link, $feed, $owner_uid);
 
                        if ($use_simplepie) {
                                $iterator = $rss->get_items();
                                        $entry_content = $item["content:escaped"];
 
                                        if (!$entry_content) $entry_content = $item["content:encoded"];
+                                       if (!$entry_content) $entry_content = $item["content"]["encoded"];
                                        if (!$entry_content) $entry_content = $item["content"];
 
                                        // Magpie bugs are getting ridiculous
 
                                        if (!$entry_content) $entry_content = $item["atom_content"];
                                        if (!$entry_content) $entry_content = $item["summary"];
-                                       if (!$entry_content) $entry_content = $item["description"];
+
+                                       if (!$entry_content || 
+                                               strlen($entry_content) < strlen($item["description"])) {
+                                                       $entry_content = $item["description"];
+                                       };
 
                                        // WTF
                                        if (is_array($entry_content)) {
                                        }
 
                                } else {
+                                       // <enclosure>
+
                                        $e_ctr = $item['enclosure#'];
 
                                        if ($e_ctr > 0) {
                                                }
                                        }
 
+                                       // <media:content>
+                                       // can there be many of those? -fox
+
+                                       $m_ctr = $item['media']['content#'];
+
+                                       if ($m_ctr > 0) {
+                                               $e_item = array($item['media']['content@url'],
+                                                       $item['media']['content@medium'],
+                                                       $item['media']['content@length']);
+
+                                               array_push($enclosures, $e_item);
+                                       }
+
+                                       // FIXME: parse more of those, if needed.
                                }
 
                                # sanitize content
                                
-//                             $entry_content = sanitize_rss($entry_content);
+                               $entry_content = sanitize_article_content($entry_content);
+                               $entry_title = sanitize_article_content($entry_title);
 
                                if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) {
                                        _debug("update_rss_feed: done collecting data [TITLE:$entry_title]");
 
                                $result = db_query($link, "SELECT 
                                                id,content_hash,no_orig_date,title,
-                                               substring(date_entered,1,19) as date_entered,
-                                               substring(updated,1,19) as updated,
+                                               ".SUBSTRING_FOR_DATE."(date_entered,1,19) as date_entered,
+                                               ".SUBSTRING_FOR_DATE."(updated,1,19) as updated,
                                                num_comments
                                        FROM 
                                                ttrss_entries 
                                        }
 
                                        if (find_article_filter($article_filters, "filter")) {
+                                               db_query($link, "COMMIT"); // close transaction in progress
                                                continue;
                                        }
 
 //                                     error_reporting (DEFAULT_ERROR_LEVEL);
 
+                                       $score = calculate_article_score($article_filters);
+
+                                       if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) {
+                                               _debug("update_rss_feed: initial score: $score");
+                                       }
+
                                        $result = db_query($link,
                                                "SELECT ref_id, int_id FROM ttrss_user_entries WHERE
                                                        ref_id = '$ref_id' AND owner_uid = '$owner_uid'
                                                        _debug("update_rss_feed: user record not found, creating...");
                                                }
 
-                                               if (!find_article_filter($article_filters, 'catchup')) {
+                                               if ($score >= -500 && !find_article_filter($article_filters, 'catchup')) {
                                                        $unread = 'true';
                                                        $last_read_qpart = 'NULL';
                                                } else {
                                                        $last_read_qpart = 'NOW()';
                                                }                                               
 
-                                               if (find_article_filter($article_filters, 'mark')) {
+                                               if (find_article_filter($article_filters, 'mark') || $score > 1000) {
                                                        $marked = 'true';
                                                } else {
                                                        $marked = 'false';
 
                                                $result = db_query($link,
                                                        "INSERT INTO ttrss_user_entries 
-                                                               (ref_id, owner_uid, feed_id, unread, last_read, marked, published) 
+                                                               (ref_id, owner_uid, feed_id, unread, last_read, marked, 
+                                                                       published, score) 
                                                        VALUES ('$ref_id', '$owner_uid', '$feed', $unread,
-                                                               $last_read_qpart, $marked, $published)");
+                                                               $last_read_qpart, $marked, $published, '$score')");
 
                                                $result = db_query($link, 
                                                        "SELECT int_id FROM ttrss_user_entries WHERE
                return false;
        }
 
+       function calculate_article_score($filters) {
+               $score = 0;
+
+               foreach ($filters as $f) {
+                       if ($f[0] == "score") {
+                               $score += $f[1];
+                       };
+               }
+               return $score;
+       }
+
+
        function printFeedEntry($feed_id, $class, $feed_title, $unread, $icon_file, $link,
                $rtl_content = false, $last_updated = false, $last_error = false) {
 
                print "<span $rtl_tag id=\"FEEDN-$feed_id\">$feed</span>";
 
                if ($unread != 0) {
-                       $fctr_class = "";
+                       $fctr_class = "class=\"feedCtrHasUnread\"";
                } else {
-                       $fctr_class = "class=\"invisible\"";
+                       $fctr_class = "class=\"feedCtrNoUnread\"";
                }
 
                print " <span $rtl_tag $fctr_class id=\"FEEDCTR-$feed_id\">
                         (<span id=\"FEEDU-$feed_id\">$unread</span>)</span>";
 
                if (get_pref($link, "EXTENDED_FEEDLIST")) {                      
+                       $total = getFeedArticles($link, $feed_id);
                        print "<div class=\"feedExtInfo\">
-                               <span id=\"FLUPD-$feed_id\">$last_updated $error_notify_msg</span></div>";
+                               <span id=\"FLUPD-$feed_id\">$last_updated ($total total) $error_notify_msg</span></div>";
                }
                         
                print "</li>";
                        $pwd_hash2 = encrypt_password($password, $login);
 
                        if (defined('ALLOW_REMOTE_USER_AUTH') && ALLOW_REMOTE_USER_AUTH 
-                                       && $_SERVER["REMOTE_USER"]) {
+                                       && $_SERVER["REMOTE_USER"] && $login != "admin") {
 
                                $login = db_escape_string($_SERVER["REMOTE_USER"]);
 
-                               $query = "SELECT id,login,access_level
+                               $query = "SELECT id,login,access_level,pwd_hash
                    FROM ttrss_users WHERE
                                        login = '$login'";
 
                                        $_POST["password"] = "";
 
                                        $_SESSION["language"] = $_POST["language"];
+                                       $_SESSION["bw_limit"] = !!$_POST["bw_limit"];
 
                                        header("Location: " . $_SERVER["REQUEST_URI"]);
                                        exit;
                                }
                                fclose($fp);
                                return true;
+                       } else {
+                               return false;
                        }
                }
-               return false;
+               return true; // consider the file always locked and skip the test
        }
 
        function make_lockfile($filename) {
                $fp = fopen(LOCK_DIRECTORY . "/$filename", "r");
                error_reporting (DEFAULT_ERROR_LEVEL);
 
-               if (flock($fp, LOCK_EX)) {
-                       $stamp = fgets($fp);
-                       flock($fp, LOCK_UN);
-                       fclose($fp);
-                       return $stamp;
+               if ($fp) {
+                       if (flock($fp, LOCK_EX)) {
+                               $stamp = fgets($fp);
+                               flock($fp, LOCK_UN);
+                               fclose($fp);
+                               return $stamp;
+                       } else {
+                               return false;
+                       }
                } else {
                        return false;
                }
                                                $intl = get_pref($link, "FRESH_ARTICLE_MAX_AGE");
 
                                                if (DB_TYPE == "pgsql") {
-                                                       $match_part = "date_entered > NOW() - INTERVAL '$intl hour' "; 
+                                                       $match_part = "updated > NOW() - INTERVAL '$intl hour' "; 
                                                } else {
-                                                       $match_part = "date_entered > DATE_SUB(NOW(), 
+                                                       $match_part = "updated > DATE_SUB(NOW(), 
                                                                INTERVAL $intl HOUR) ";
                                                }
 
        }
 
        function getAllCounters($link, $omode = "flc", $active_feed = false) {
-/*             getLabelCounters($link);
-               getFeedCounters($link);
-               getTagCounters($link);
-               getGlobalCounters($link);
-               if (get_pref($link, 'ENABLE_FEED_CATS')) {
-                       getCategoryCounters($link);
-               } */
 
-               if (!$omode) $omode = "flc";
+               /* getting all counters is a resource intensive operation, so we
+                * rate limit it a little bit */
 
-               getGlobalCounters($link);
 
-               if (strchr($omode, "l")) getLabelCounters($link);
-               if (strchr($omode, "f")) getFeedCounters($link, SMART_RPC_COUNTERS, $active_feed);
-               if (strchr($omode, "t")) getTagCounters($link);
-               if (strchr($omode, "c")) {                      
-                       if (get_pref($link, 'ENABLE_FEED_CATS')) {
-                               getCategoryCounters($link);
+
+               if (get_pref($link, "SYNC_COUNTERS") || 
+                               time() - $_SESSION["get_all_counters_stamp"] > 5) {
+
+                       if (!$omode) $omode = "flc";
+       
+                       getGlobalCounters($link);
+       
+                       if (strchr($omode, "l")) getLabelCounters($link);
+                       if (strchr($omode, "f")) getFeedCounters($link, SMART_RPC_COUNTERS, $active_feed);
+                       if (strchr($omode, "t")) getTagCounters($link);
+                       if (strchr($omode, "c")) {                      
+                               if (get_pref($link, 'ENABLE_FEED_CATS')) {
+                                       getCategoryCounters($link);
+                               }
                        }
+
+                       $_SESSION["get_all_counters_stamp"] = time();
                }
+
        }       
 
        function getCategoryCounters($link) {
        }
 
        function getFeedUnread($link, $feed, $is_cat = false) {
+               return getFeedArticles($link, $feed, $is_cat, true);
+       }
+
+       function getFeedArticles($link, $feed, $is_cat = false, $unread_only = false) {
                $n_feed = sprintf("%d", $feed);
 
+               if ($unread_only) {
+                       $unread_qpart = "unread = true";
+               } else {
+                       $unread_qpart = "true";
+               }
+
                $age_qpart = getMaxAgeSubquery();
 
                if ($is_cat) {
                        $intl = get_pref($link, "FRESH_ARTICLE_MAX_AGE");
 
                        if (DB_TYPE == "pgsql") {
-                               $match_part .= " AND date_entered > NOW() - INTERVAL '$intl hour' "; 
+                               $match_part .= " AND updated > NOW() - INTERVAL '$intl hour' "; 
                        } else {
-                               $match_part .= " AND date_entered > DATE_SUB(NOW(), INTERVAL $intl HOUR) ";
+                               $match_part .= " AND updated > DATE_SUB(NOW(), INTERVAL $intl HOUR) ";
                        }
 
                } else if ($n_feed > 0) {
 
                                $result = db_query($link, "SELECT COUNT(int_id) AS unread 
                                        FROM ttrss_user_entries,ttrss_entries
-                                       WHERE   unread = true AND
+                                       WHERE   $unread_qpart AND
                                        ttrss_user_entries.ref_id = ttrss_entries.id AND
                                        $age_qpart AND
                                        ($match_part) AND
                                ttrss_user_entries.ref_id = ttrss_entries.id AND 
                                ttrss_feeds.hidden = false AND
                                $age_qpart AND
-                               unread = true AND ($match_part) AND ttrss_user_entries.owner_uid = " . $_SESSION["uid"]);
+                               $unread_qpart AND ($match_part) AND ttrss_user_entries.owner_uid = " . $_SESSION["uid"]);
                                
                } else {
                
                        $result = db_query($link, "SELECT COUNT(post_int_id) AS unread
                                FROM ttrss_tags,ttrss_user_entries,ttrss_entries 
                                WHERE tag_name = '$feed' AND post_int_id = int_id AND ref_id = ttrss_entries.id 
-                               AND unread = true AND $age_qpart AND
+                               AND $unread_qpart AND $age_qpart AND
                                        ttrss_tags.owner_uid = " . $_SESSION["uid"]);
                }
                
                $count = getFeedUnread($link, -1);
 
                if (!$ret_mode) {
-                       print "<counter type=\"label\" id=\"-1\" counter=\"$count\"/>";
+
+                       if (get_pref($link, 'EXTENDED_FEEDLIST')) {
+                               $xmsg_part = "xmsg=\"(" . getFeedArticles($link, $id) . " total)\"";
+                       } else {
+                               $xmsg_part = "";
+                       }
+
+                       print "<counter type=\"label\" id=\"-1\" counter=\"$count\" $xmsg_part/>";
                } else {
                        $ret_arr["-1"]["counter"] = $count;
                        $ret_arr["-1"]["description"] = __("Starred articles");
                $count = getFeedUnread($link, -2);
 
                if (!$ret_mode) {
-                       print "<counter type=\"label\" id=\"-2\" counter=\"$count\"/>";
+
+                       if (get_pref($link, 'EXTENDED_FEEDLIST')) {
+                               $xmsg_part = "xmsg=\"(" . getFeedArticles($link, $id) . " total)\"";
+                       } else {
+                               $xmsg_part = "";
+                       }
+
+                       print "<counter type=\"label\" id=\"-2\" counter=\"$count\" $xmsg_part/>";
                } else {
                        $ret_arr["-2"]["counter"] = $count;
                        $ret_arr["-2"]["description"] = __("Published articles");
                $count = getFeedUnread($link, -3);
 
                if (!$ret_mode) {
-                       print "<counter type=\"label\" id=\"-3\" counter=\"$count\"/>";
+
+                       if (get_pref($link, 'EXTENDED_FEEDLIST')) {
+                               $xmsg_part = "xmsg=\"(" . getFeedArticles($link, $id) . " total)\"";
+                       } else {
+                               $xmsg_part = "";
+                       }
+
+                       print "<counter type=\"label\" id=\"-3\" counter=\"$count\" $xmsg_part/>";
                } else {
                        $ret_arr["-3"]["counter"] = $count;
                        $ret_arr["-3"]["description"] = __("Fresh articles");
                                $old_counters[$id] = $count;
                                $lctrs_modified = true;
                                if (!$ret_mode) {
-                                       print "<counter type=\"label\" id=\"$id\" counter=\"$count\"/>";
+
+                                       if (get_pref($link, 'EXTENDED_FEEDLIST')) {
+                                               $xmsg_part = "xmsg=\"(" . getFeedArticles($link, $id) . " total)\"";
+                                       } else {
+                                               $xmsg_part = "";
+                                       }
+
+                                       print "<counter type=\"label\" id=\"$id\" counter=\"$count\" $xmsg_part/>";
                                } else {
                                        $ret_arr[$id]["counter"] = $count;
                                        $ret_arr[$id]["description"] = $label_name;
                $old_counters = $_SESSION["fctr_last_value"];
 
 /*             $result = db_query($link, "SELECT id,last_error,parent_feed,
-                       SUBSTRING(last_updated,1,19) AS last_updated,
+                       ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated,
                        (SELECT count(id) 
                                FROM ttrss_entries,ttrss_user_entries 
                                WHERE feed_id = ttrss_feeds.id AND 
 
                $query = "SELECT ttrss_feeds.id,
                                ttrss_feeds.title,
-                               SUBSTRING(ttrss_feeds.last_updated,1,19) AS last_updated, 
+                               ".SUBSTRING_FOR_DATE."(ttrss_feeds.last_updated,1,19) AS last_updated, 
                                last_error, 
                                COUNT(ttrss_entries.id) AS count 
                        FROM ttrss_feeds 
                                        $has_title_part = "";
                                }
 
-                               print "<counter type=\"feed\" id=\"$id\" counter=\"$count\" $has_img_part $error_part updated=\"$last_updated\" $has_title_part/>";
+                               if (get_pref($link, 'EXTENDED_FEEDLIST')) {
+                                       $xmsg_part = "xmsg=\"(" . getFeedArticles($link, $id) . " total)\"";
+                               }
+
+                               print "<counter type=\"feed\" id=\"$id\" counter=\"$count\" $has_img_part $error_part updated=\"$last_updated\" $xmsg_part $has_title_part/>";
                        }
                }
 
                } else if ($id == -3) {
                        return __("Fresh articles");
                } else if ($id < -10) {
-                       $label_id = -10 - $id;
+                       $label_id = -$id - 11;
                        $result = db_query($link, "SELECT description FROM ttrss_labels WHERE id = '$label_id'");
                        if (db_num_rows($result) == 1) {
                                return db_fetch_result($result, 0, "description");
                print "<param key=\"hide_feedlist\" value=\"" .
                        (int) get_pref($link, "HIDE_FEEDLIST") . "\"/>";
 
+               print "<param key=\"bw_limit\" value=\"".
+                       (int) $_SESSION["bw_limit"]."\"/>";
+
+               print "<param key=\"sync_counters\" value=\"" . 
+                       (int) get_pref($link, "SYNC_COUNTERS") . "\"/>";
+
                print "</init-params>";
        }
 
 
                if (CHECK_FOR_NEW_VERSION && $_SESSION["access_level"] >= 10) {
                        
-                       if ($_SESSION["last_version_check"] + 7200 < time()) {
+                       if ($_SESSION["last_version_check"] + 86400 < time()) {
                                $new_version_details = check_for_update($link);
 
                                print "<param key=\"new_version_available\" value=\"".
                                $intl = get_pref($link, "FRESH_ARTICLE_MAX_AGE", $owner_uid);
 
                                if (DB_TYPE == "pgsql") {
-                                       $query_strategy_part .= " AND date_entered > NOW() - INTERVAL '$intl hour' "; 
+                                       $query_strategy_part .= " AND updated > NOW() - INTERVAL '$intl hour' "; 
                                } else {
-                                       $query_strategy_part .= " AND date_entered > DATE_SUB(NOW(), INTERVAL $intl HOUR) ";
+                                       $query_strategy_part .= " AND updated > DATE_SUB(NOW(), INTERVAL $intl HOUR) ";
                                }
 
                                $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
                                $order_by = "updated DESC";
                        }
 
+                       $order_by = "score DESC, $order_by";
+
                        if ($override_order) {
                                $order_by = $override_order;
                        }
        
                        } else if ($feed == -1) {
                                $feed_title = __("Starred articles");
+                               if ($search) {  $feed_title = __("Searched for") . " $search ($feed_title)"; }
                        } else if ($feed == -2) {
                                $feed_title = __("Published articles");
+                               if ($search) {  $feed_title = __("Searched for") . " $search ($feed_title)"; }
                        } else if ($feed == -3) {
                                $feed_title = __("Fresh articles");
+                               if ($search) {  $feed_title = __("Searched for") . " $search ($feed_title)"; }
                        } else if ($feed < -10) {
                                $label_id = -$feed - 11;
                                $result = db_query($link, "SELECT description FROM ttrss_labels
                                        $offset_query_part = "OFFSET $offset";
                                }
 
+                               if ($vfeed_query_part && get_pref($link, 'VFEED_GROUP_BY_FEED', $owner_uid)) {
+                                       if (!$override_order) {
+                                               $order_by = "ttrss_feeds.title, $order_by";     
+                                       }
+
+                                       // Special output for Fresh feed
+
+/*                                     if ($feed == -3) {
+                                               $group_limit_part = "(select count(*) from 
+                                                       ttrss_user_entries AS t1, ttrss_entries AS t2 where
+                                                               t1.ref_id = t2.id and t1.owner_uid = 2 and
+                                                               t1.feed_id = ttrss_user_entries.feed_id and
+                                                               t2.updated > ttrss_entries.updated) <= 5 AND";
+} */
+                               }
+
                                $query = "SELECT 
                                                guid,
                                                ttrss_entries.id,ttrss_entries.title,
                                                updated,
                                                unread,feed_id,marked,published,link,last_read,
-                                               SUBSTRING(last_read,1,19) as last_read_noms,
+                                               ".SUBSTRING_FOR_DATE."(last_read,1,19) as last_read_noms,
                                                $vfeed_query_part
                                                $content_query_part
-                                               SUBSTRING(updated,1,19) as updated_noms,
-                                               author
+                                               ".SUBSTRING_FOR_DATE."(updated,1,19) as updated_noms,
+                                               author,score
                                        FROM
                                                ttrss_entries,ttrss_user_entries,ttrss_feeds
                                        WHERE
-                                       ttrss_feeds.hidden = false AND
+                                       $group_limit_part
+                                       ttrss_feeds.hidden = false AND 
                                        ttrss_user_entries.feed_id = ttrss_feeds.id AND
                                        ttrss_user_entries.ref_id = ttrss_entries.id AND
                                        ttrss_user_entries.owner_uid = '$owner_uid' AND
                                        updated,
                                        unread,feed_id,
                                        marked,link,last_read,                          
-                                       SUBSTRING(last_read,1,19) as last_read_noms,
+                                       ".SUBSTRING_FOR_DATE."(last_read,1,19) as last_read_noms,
                                        $vfeed_query_part
                                        $content_query_part
-                                       SUBSTRING(updated,1,19) as updated_noms
+                                       ".SUBSTRING_FOR_DATE."(updated,1,19) as updated_noms,
+                                       score
                                        FROM
                                                ttrss_entries,ttrss_user_entries,ttrss_tags
                                        WHERE
-                                               ref_id = ttrss_entries.id AND
+                                               ref_id = ttrss_entries.id AND 
                                                ttrss_user_entries.owner_uid = '$owner_uid' AND
                                                post_int_id = int_id AND tag_name = '$feed' AND
                                                $view_query_part
                if (get_pref($link, "STRIP_UNSAFE_TAGS") || $force_strip_tags) {
 
                        $res = strip_tags_long($res, 
-                               "<p><a><i><em><b><strong><blockquote><br><img><div><span><ul><ol><li>");
+                               "<p><a><i><em><b><strong><code><pre><blockquote><br><img><ul><ol><li>");
 
 //                     $res = preg_replace("/\r\n|\n|\r/", "", $res);
 //                     $res = strip_tags_long($res, "<p><a><i><em><b><strong><blockquote><br><img><div><span>");                       
                }
 
+               if (get_pref($link, "STRIP_IMAGES")) {
+                       
+                       $res = preg_replace('/<img[^>]+>/is', '', $res);
+
+               }
+
                return $res;
        }
 
                                ttrss_user_entries.ref_id,
                                link,
                                SUBSTRING(content, 1, 120) AS excerpt,
-                               SUBSTRING(last_updated,1,19) AS last_updated
+                               ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
                        FROM 
                                ttrss_user_entries,ttrss_entries,ttrss_feeds 
                        WHERE 
                                } else {
                                        return "New version of Tiny-Tiny RSS ($latest_version) is available:
                                                <div class='milestoneDetails'>$content</div>
-                                               Visit <a target=\"_new\" href=\"http://tt-rss.spb.ru/\">official site</a> for
+                                               Visit <a target=\"_blank\" href=\"http://tt-rss.spb.ru/\">official site</a> for
                                                download and update information.";      
                                }
 
                                $sel_all_link = "javascript:selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', true, '', true)";
                                $sel_unread_link = "javascript:selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', true, 'Unread', true)";
                                $sel_none_link = "javascript:selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', false)";
+                               $sel_inv_link = "javascript:invertHeadlineSelection()";
 
                                $tog_unread_link = "javascript:selectionToggleUnread()";
                                $tog_marked_link = "javascript:selectionToggleMarked()";
                                $sel_unread_link = "javascript:cdmSelectArticles('unread')";
                                $sel_none_link = "javascript:cdmSelectArticles('none')";
 
+                               $sel_inv_link = "javascript:invertHeadlineSelection()";
+
                                $tog_unread_link = "javascript:selectionToggleUnread(true)";
                                $tog_marked_link = "javascript:selectionToggleMarked(true)";
                                $tog_published_link = "javascript:selectionTogglePublished(true)";
                        if (!$dashboard_menu) {
 
                                if (strpos($_SESSION["client.userAgent"], "MSIE") === false) {
-       
+
                                        print "<td class=\"headlineActions$rtl_cpart\">
                                                <ul class=\"headlineDropdownMenu\">
                                                <li class=\"top2\">
                                                ".__('Select:')."
                                                        <a href=\"$sel_all_link\">".__('All')."</a>,
                                                        <a href=\"$sel_unread_link\">".__('Unread')."</a>,
+                                                       <a href=\"$sel_inv_link\">".__('Invert')."</a>,
                                                        <a href=\"$sel_none_link\">".__('None')."</a></li>
                                                <li class=\"vsep\">&nbsp;</li>
-                                               <li class=\"top\">".__('Toggle')."<ul>
-                                                       <li onclick=\"$tog_unread_link\">".__('Unread')."</li>
-                                                       <li onclick=\"$tog_marked_link\">".__('Starred')."</li>
-                                                       <li onclick=\"$tog_published_link\">".__('Published')."</li>
-                                                       </ul></li>
-                                               <li class=\"vsep\">&nbsp;</li>
-                                               <li class=\"top\">".__('Mark as read')."<ul>
-                                                       <li onclick=\"$catchup_sel_link\">".__('Selection')."</li>
-                                                       <!-- <li onclick=\"$catchup_page_link\">".__('This page')."</li> -->";
-       
-                                       if (!get_pref($link, 'COMBINED_DISPLAY_MODE')) {
-       
-                                       print "
+                                               <li class=\"top\">".__('Actions...')."<ul>
+                                                       <li><span class=\"insensitive\">".__('Selection toggle:')."</span></li>
+                                                       <li onclick=\"$tog_unread_link\">&nbsp;&nbsp;".__('Unread')."</li>
+                                                       <li onclick=\"$tog_marked_link\">&nbsp;&nbsp;".__('Starred')."</li>
+                                                       <li onclick=\"$tog_published_link\">&nbsp;&nbsp;".__('Published')."</li>
                                                        <li><span class=\"insensitive\">--------</span></li>
-                                                       <li onclick=\"catchupRelativeToArticle(0)\">".__("Above active article")."</li>
-                                                       <li onclick=\"catchupRelativeToArticle(1)\">".__("Below active article")."</li>
-                                                       <li><span class=\"insensitive\">--------</span></li>";
-                                       }
+                                                       <li><span class=\"insensitive\">".__('Mark as read:')."</span></li>
+                                                       <li onclick=\"$catchup_sel_link\">&nbsp;&nbsp;".__('Selection')."</li>";
+
+/*                             if (!get_pref($link, 'COMBINED_DISPLAY_MODE')) {
        
                                        print "
-                                                       <li onclick=\"$catchup_feed_link\">".__('Entire feed')."</li></ul></li>
-                                               ";
-       
-                                               $enable_pagination = get_pref($link, "_PREFS_ENABLE_PAGINATION");
-       
-                                               if ($limit != 0 && !$search && $enable_pagination) {
-                                                       print "
-                                                       <li class=\"vsep\">&nbsp;</li>
-                                                       <li class=\"top\"><a href=\"$page_next_link\">".__('Next page')."</a><ul>
-                                                               <li onclick=\"$page_prev_link\">".__('Previous page')."</li>
-                                                               <li onclick=\"$page_first_link\">".__('First page')."</li></ul></li>
-                                                               </ul>";
-                                                       }
-       
-                                               if ($search && $feed_id >= 0 && get_pref($link, 'ENABLE_LABELS') && GLOBAL_ENABLE_LABELS) {
-                                                       print "
-                                                               <li class=\"vsep\">&nbsp;</li>
-                                                               <li class=\"top3\">
-                                                               <a href=\"javascript:labelFromSearch('$search', '$search_mode',
-                                                                       '$match_on', '$feed_id', '$is_cat');\">
-                                                                       ".__('Convert to label')."</a></td>";
-                                               }
-                                               print " 
-                                               </td>"; 
+                                               <li onclick=\"catchupRelativeToArticle(0)\">&nbsp;&nbsp;".__("Above active article")."</li>
+                                               <li onclick=\"catchupRelativeToArticle(1)\">&nbsp;&nbsp;".__("Below active article")."</li>";
+                               } else {
+                                       print "
+                                               <li><span class=\"insensitive\">&nbsp;&nbsp;".__("Above active article")."</span></li>
+                                               <li><span class=\"insensitive\">&nbsp;&nbsp;".__("Below active article")."</span></li>";
+
+                               } */
+
+                               print "<li onclick=\"$catchup_feed_link\">&nbsp;&nbsp;".__('Entire feed')."</li>";
+
+                               print "<li><span class=\"insensitive\">--------</span></li>";
+                               print "<li><span class=\"insensitive\">".__('Other actions:')."</span></li>";
+               
+
+                               if ($search && $feed_id >= 0 && get_pref($link, 'ENABLE_LABELS') && GLOBAL_ENABLE_LABELS) {
+                                       print "
+                                               <li onclick=\"javascript:labelFromSearch('$search', '$search_mode',
+                                                       '$match_on', '$feed_id', '$is_cat');\">&nbsp;&nbsp;
+                                                       ".__('Search to label')."</li>";
+                               } else {
+                                       print "<li><span class=\"insensitive\">&nbsp;&nbsp;".__('Search to label')."</li>";
+
+                               }
+                               
+                               print   "</ul></li></ul>";
+                               print "</td>"; 
        
                                } else {
-                               // old style subtoolbar:
+                                       // old style subtoolbar:
        
                                        print "<td class=\"headlineActions$rtl_cpart\">".
                                                __('Select:')."
                                }
                        } else { // dashboard menu actions
 
-                                       print "<td class=\"headlineActions$rtl_cpart\">
-                                               <ul class=\"headlineDropdownMenu\">
-                                               <li class=\"top2\">
-                                                       <a href=\"#\" onclick=\"return displayDlg('quickAddFeed');\">".
-                                                               __('Subscribe to feed')."</a>
-                                               </li>
-                                               <li class=\"vsep\">&nbsp;</li>
-                                               <li class=\"top\">".__('Placeholder')."<ul>
-                                                       <li onclick=\"\">".__('Placeholder')."</li>
-                                                       <li onclick=\"\">".__('Placeholder')."</li>
-                                                       <li onclick=\"\">".__('Placeholder')."</li>
-                                                       </ul></li>
-                                               <li class=\"vsep\">&nbsp;</li>
-                                               <li class=\"top\">".__('Show')."<ul>
-                                                       <li onclick=\"\">".__('Update errors')."</li>
-                                                       </ul></li></ul>";
-
-                                       print "</td>";
-
+                               // not implemented
+                               print "</td>";
                        }
 
-/*                     if ($search && $feed_id >= 0 && get_pref($link, 'ENABLE_LABELS') && GLOBAL_ENABLE_LABELS) {
-                               print "<td class=\"headlineActions$rtl_cpart\">
-                                       <a href=\"javascript:labelFromSearch('$search', '$search_mode',
-                                                       '$match_on', '$feed_id', '$is_cat');\">
-                                               ".__('Convert to Label')."</a></td>";
-} */
-
                        print "<td class=\"headlineTitle$rtl_cpart\">";
 
-                       print "<span class=\"headlineInnerTitle\">";
+                       print "<span id=\"subtoolbar_search\" 
+                               style=\"display : none\"><input 
+                               id=\"subtoolbar_search_box\"
+                               onblur=\"javascript:enableHotkeys();\" 
+                               onfocus=\"javascript:disableHotkeys();\"
+                               onchange=\"subtoolbarSearch()\"
+                               onkeyup=\"subtoolbarSearch()\" type=\"search\"></span>";
+
+                       print "<span id=\"subtoolbar_ftitle\">";
 
                        if ($feed_site_url) {
                                if (!$bottom) {
-                                       $target = "target=\"_new\"";
+                                       $target = "target=\"_blank\"";
                                }
                                print "<a $target href=\"$feed_site_url\">".
                                        truncate_string($feed_title,30)."</a>";
                                print " [$user_page_offset] ";
                        }
 
-                       print "</span>";
-
                        if (!$bottom && !$disable_feed) {
                                print "
-                                       <a target=\"_new\" 
+                                       <a target=\"_blank\" 
                                                href=\"backend.php?op=rss&id=$feed_id&is_cat=$is_cat$search_q\">
                                                <img class=\"noborder\" 
                                                        alt=\"".__('Generated feed')."\" src=\"images/feed-icon-12x12.png\">
                        } else if ($feed_small_icon) {
                                print "<img class=\"noborder\" alt=\"\" src=\"images/$feed_small_icon\">";
                        }
-                               
+
+                       print "</span>";
+
                        print "</td>";
                        print "</tr></table>";
 
 
                        $catctr_class = ($cat_unread > 0) ? "catCtrHasUnread" : "catCtrNoUnread";
 
-                       print "<li class=\"feedCat\" id=\"FCAT-$cat_id\">
-                               <a id=\"FCATN-$cat_id\" href=\"javascript:toggleCollapseCat($cat_id)\">$tmp_category</a>";
-
                        if ($can_browse) {
-                               print "<a href=\"#\" onclick=\"javascript:viewCategory($cat_id)\" id=\"FCAP-$cat_id\">";
+                               $browse_cat_link = "onclick=\"javascript:viewCategory($cat_id)\"";
+                               $inner_title_class = "catTitle";
                        } else {
-                               print "<span id=\"FCAP-$cat_id\">";
+                               $browse_cat_link = "";
+                               $inner_title_class = "catTitleNL";
                        }
 
+                       if ($cat_id > 0) {
+                               $cat_class = "feedCat";
+                       } else {
+                               $cat_class = "virtCat";
+                       }
+
+                       print "<li class=\"$cat_class\" id=\"FCAT-$cat_id\">
+                               <img onclick=\"toggleCollapseCat($cat_id)\" class=\"catCollapse\"
+                                       title=\"".__('Click to collapse category')."\"
+                                       src=\"images/cat-collapse.png\"><span class=\"$inner_title_class\" 
+                                       id=\"FCATN-$cat_id\" $browse_cat_link
+                               \">$tmp_category</span>";
+
+                       print "<span id=\"FCAP-$cat_id\">";
+
                        print " <span id=\"FCATCTR-$cat_id\" 
                                class=\"$catctr_class\">($cat_unread)</span> $ellipsis";
 
-                       if ($can_browse) {
-                               print "</a>";
-                       } else {
-                               print "</span>";
-                       }
+                       print "</span>";
+
+                       //print "</li>";
 
-                       print "</li>";
+                       print "<ul class=\"feedCatList\" id=\"FCATLIST-$cat_id\" style='$holder_style'>";
 
-                       print "<li id=\"feedCatHolder\" class=\"$holder_class\"><ul class=\"feedCatList\" id=\"FCATLIST-$cat_id\" style='$holder_style'>";
        }
        
        function outputFeedList($link, $tags = false) {
                                $cat_hidden = false;
                        }
 
-#                      print "<li class=\"feedCat\">".__('Special')."</li>";
-#                      print "<li id=\"feedCatHolder\" class=\"feedCatHolder\"><ul class=\"feedCatList\">";            
-#                      print "<li class=\"feedCat\">".
-#                              "<a id=\"FCATN--1\" href=\"javascript:toggleCollapseCat(-1)\">".
-#                              __('Special')."</a> <span id='FCAP--1'>$ellipsis</span></li>";
-#
-#                      print "<li id=\"feedCatHolder\" class=\"feedCatHolder\">
-#                              <ul class=\"feedCatList\" id='FCATLIST--1' style='$holder_style'>";
-
-#                      $cat_unread = getCategoryUnread($link, -1);
-#                      $tmp_category = __("Special");
-#                      $catctr_class = ($cat_unread > 0) ? "catCtrHasUnread" : "catCtrNoUnread";
-
                        printCategoryHeader($link, -1, $cat_hidden, false);
                }
 
                        "images/pub_set.gif", $link);
 
                if (get_pref($link, 'ENABLE_FEED_CATS')) {
-                       print "</ul>";
+                       print "</ul></li>";
                }
 
                if (!$tags) {
 
                                                printCategoryHeader($link, -2, $cat_hidden, false);
 
-#                                              print "<li class=\"feedCat\">".
-#                                                      "<a id=\"FCATN--2\" href=\"javascript:toggleCollapseCat(-2)\">".
-#                                                      __('Labels')."</a> <span id='FCAP--2'>$ellipsis</span></li>";
-#
-#                                              print "<li id=\"feedCatHolder\" class=\"feedCatHolder\"><ul class=\"feedCatList\" id='FCATLIST--2' style='$holder_style'>";
                                        } else {
                                                print "<li><hr></li>";
                                        }
 
                        if (get_pref($link, 'ENABLE_FEED_CATS')) {
                                if (get_pref($link, "FEEDS_SORT_BY_UNREAD")) {
-                                       $order_by_qpart = "category,unread DESC,title";
+                                       $order_by_qpart = "order_id,category,unread DESC,title";
                                } else {
-                                       $order_by_qpart = "category,title";
+                                       $order_by_qpart = "order_id,category,title";
                                }
                        } else {
                                if (get_pref($link, "FEEDS_SORT_BY_UNREAD")) {
 
                        $age_qpart = getMaxAgeSubquery();
 
-                       $result = db_query($link, "SELECT ttrss_feeds.*,
-                               SUBSTRING(last_updated,1,19) AS last_updated_noms,
+                       $query = "SELECT ttrss_feeds.*,
+                               ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated_noms,
                                (SELECT COUNT(id) FROM ttrss_entries,ttrss_user_entries
                                        WHERE feed_id = ttrss_feeds.id AND unread = true
                                                AND $age_qpart
                                WHERE 
                                        ttrss_feeds.hidden = false AND
                                        ttrss_feeds.owner_uid = '$owner_uid' AND parent_feed IS NULL
-                               ORDER BY $order_by_qpart"); 
+                               ORDER BY $order_by_qpart"; 
+
+                       $result = db_query($link, $query);
 
                        $actid = $_GET["actid"];
        
                                
                                        $category = $tmp_category;
 
-                                       $collapsed = $line["collapsed"];
+                                       $collapsed = sql_bool_to_bool($line["collapsed"]);
 
                                        // workaround for NULL category
                                        if ($category == __("Uncategorized")) {
                                                }
                                        }
 
-                                       if ($collapsed == "t" || $collapsed == "1") {
-                                               $holder_class = "feedCatHolder";
-                                               $holder_style = "display:none;";
-                                               $ellipsis = "…";
-                                       } else {
-                                               $holder_class = "feedCatHolder";
-                                               $holder_style = "";
-                                               $ellipsis = "";
-                                       }
-
                                        $cat_id = sprintf("%d", $cat_id);
 
-                                       $cat_unread = getCategoryUnread($link, $cat_id);
+                                       printCategoryHeader($link, $cat_id, $collapsed, true);
 
-                                       $catctr_class = ($cat_unread > 0) ? "catCtrHasUnread" : "catCtrNoUnread";
-
-                                       print "<li class=\"feedCat\" id=\"FCAT-$cat_id\">
-                                               <a id=\"FCATN-$cat_id\" href=\"javascript:toggleCollapseCat($cat_id)\">$tmp_category</a>
-                                                       <a href=\"#\" onclick=\"javascript:viewCategory($cat_id)\" id=\"FCAP-$cat_id\">
-                                                       <span id=\"FCATCTR-$cat_id\" 
-                                                       class=\"$catctr_class\">($cat_unread)</span> $ellipsis
-                                                       </a></li>";
-
-                                       print "<li id=\"feedCatHolder\" class=\"$holder_class\"><ul class=\"feedCatList\" id=\"FCATLIST-$cat_id\" style='$holder_style'>";
                                }
        
                                printFeedEntry($feed_id, $class, $feed, $unread, 
 
                        if (get_pref($link, 'ENABLE_FEED_CATS')) {
                                print "<li class=\"feedCat\">".__('Tags')."</li>";
-                               print "<li id=\"feedCatHolder\"><ul class=\"feedCatList\">";
+                               print "<ul class=\"feedCatList\">";
                        }
 
                        $age_qpart = getMaxAgeSubquery();
                return vsprintf(__(array_shift($args)), $args);
        }
 
-       function outputArticleXML($link, $id, $feed_id, $mark_as_read = true) {
+       function outputArticleXML($link, $id, $feed_id, $mark_as_read = true,
+               $zoom_mode = false) {
 
                /* we can figure out feed_id from article id anyway, why do we
                 * pass feed_id here? */
 
                $feed_id = db_fetch_result($result, 0, "feed_id");
 
-               print "<article id='$id'><![CDATA[";
+               if (!$zoom_mode) { print "<article id='$id'><![CDATA["; };
 
                $result = db_query($link, "SELECT rtl_content FROM ttrss_feeds
                        WHERE id = '$feed_id' AND owner_uid = " . $_SESSION["uid"]);
                }
 
                $result = db_query($link, "SELECT title,link,content,feed_id,comments,int_id,
-                       SUBSTRING(updated,1,16) as updated,
+                       ".SUBSTRING_FOR_DATE."(updated,1,16) as updated,
                        (SELECT icon_url FROM ttrss_feeds WHERE id = feed_id) as icon_url,
                        num_comments,
                        author
                        $link_target = "";
 
                        if (get_pref($link, 'OPEN_LINKS_IN_NEW_WINDOW')) {
-                               $link_target = "target=\"_new\"";
+                               $link_target = "target=\"_blank\"";
                        }
 
                        $line = db_fetch_assoc($result);
                                }                               
                        }
 
+                       if ($zoom_mode) {
+                               header("Content-Type: text/html");
+                               print "<html><head>
+                                               <title>Tiny Tiny RSS - ".$line["title"]."</title>
+                                               <link rel=\"stylesheet\" type=\"text/css\" href=\"tt-rss.css\">
+                                       </head><body>";
+                       }
+
+
                        print "<div class=\"postReply\">";
 
-                       print "<div class=\"postHeader\">";
+                       print "<div class=\"postHeader\" onmouseover=\"enable_resize(true)\" 
+                               onmouseout=\"enable_resize(false)\">";
 
                        $entry_author = $line["author"];
 
                        $tags = get_article_tags($link, $id);
        
                        $tags_str = "";
+                       $tags_nolinks_str = "";
                        $f_tags_str = "";
 
                        $num_tags = 0;
                                
                                if ($num_tags == $tag_limit) {
                                        $tags_str .= "&hellip;";
+                                       $tags_nolinks_str .= "&hellip;";
 
                                } else if ($num_tags < $tag_limit) {
                                        $tags_str .= $tag_str;
+                                       $tags_nolinks_str .= "$tag, ";
                                }
                                $f_tags_str .= $tag_str;
                        }
 
                        $tags_str = preg_replace("/, $/", "", $tags_str);
+                       $tags_nolinks_str = preg_replace("/, $/", "", $tags_nolinks_str);
                        $f_tags_str = preg_replace("/, $/", "", $f_tags_str);
 
                        $all_tags_div = "<span class='cdmAllTagsCtr'>&hellip;<div class='cdmAllTags'>All Tags: $f_tags_str</div></span>";
                        if (!$entry_comments) $entry_comments = "&nbsp;"; # placeholder
 
                        if (!$tags_str) $tags_str = '<span class="tagList">'.__('no tags').'</span>';
+                       if (!$tags_nolinks_str) $tags_nolinks_str = '<span class="tagList">'.__('no tags').'</span>';
 
                        print "<div style='float : right'>
-                               <img src='images/tag.png' class='tagsPic' alt='Tags' title='Tags'>
-                               $tags_str 
-                               <a title=\"Edit tags for this article\" 
-                                       href=\"javascript:editArticleTags($id, $feed_id)\">(+)</a></div>
-                               <div clear='both'>$entry_comments</div>";
+                                       <img src='images/tag.png' class='tagsPic' alt='Tags' title='Tags'>";
+
+                       if (!$zoom_mode) {
+                               print "$tags_str 
+                                       <a title=\"".__('Edit tags for this article')."\" 
+                                               href=\"javascript:editArticleTags($id, $feed_id)\">(+)</a>                              
+                                       <img src=\"images/art-zoom.png\" class='tagsPic' 
+                                               style=\"cursor : pointer\"
+                                               onclick=\"zoomToArticle($id)\"
+                                               alt='Zoom' title='".__('Show article summary in new window')."'>";
+                       } else {
+                               print "$tags_nolinks_str";
+                       }
+                       print "</div>";
+                       print "<div clear='both'>$entry_comments</div>";
 
                        print "</div>";
 
                        $line["content"] = sanitize_rss($link, $line["content"]);
 
                        if (get_pref($link, 'OPEN_LINKS_IN_NEW_WINDOW')) {
-                               $line["content"] = preg_replace("/href=/i", "target=\"_new\" href=", $line["content"]);
+                               $line["content"] = preg_replace("/href=/i", "target=\"_blank\" href=", $line["content"]);
                        }
 
                        print $line["content"];
 
                                        $filename = substr($url, strrpos($url, "/")+1);
 
-                                       $entry = "<a target=\"_blank\" href=\"" . htmlspecialchars($url) . "\">" .
+                                       $entry = ""; 
+                                       
+                                       if (($ctype == __("audio/mpeg")) && 
+                                               (get_pref($link, "ENABLE_FLASH_PLAYER")) ) { 
+                                       
+                                               $entry .= "<object type=\"application/x-shockwave-flash\" data=\"extras/button/musicplayer.swf?song_url=$url\" width=\"17\" height=\"17\"> <param name=\"movie\" value=\"extras/button/musicplayer.swf?song_url=$url\" /> </object> ";
+
+                                       }
+
+                                       $entry .= "<a target=\"_blank\" href=\"" . htmlspecialchars($url) . "\">" .
                                                $filename . " (" . $ctype . ")" . "</a>";
 
                                        array_push($entries, $entry);
 
                }
 
-               print "]]></article>";
+               if (!$zoom_mode) { 
+                       print "]]></article>"; 
+               } else {
+                       print "
+                               <div style=\"text-align : center\">
+                               <input type=\"submit\" onclick=\"return window.close()\" 
+                               value=\"".__("Close this window")."\"></div>";
+                       print "</body></html>";
+
+               }
 
        }
 
        function outputHeadlinesList($link, $feed, $subop, $view_mode, $limit, $cat_view,
-                                       $next_unread_feed, $offset) {
+                                       $next_unread_feed, $offset, $vgr_last_feed = false) {
 
                $disable_cache = false;
 
 
                if ($subop == "undefined") $subop = "";
 
+               $subop_split = split(":", $subop);
+
                if ($subop == "CatchupSelected") {
                        $ids = split(",", db_escape_string($_GET["ids"]));
                        $cmode = sprintf("%d", $_GET["cmode"]);
                        }
                }
 
+               if ($subop_split[0] == "MarkAllReadGR")  {
+                       catchup_feed($link, $subop_split[1], false);
+               }
+
+
                if ($feed_id > 0) {             
                        $result = db_query($link,
                                "SELECT id FROM ttrss_feeds WHERE id = '$feed' LIMIT 1");
                $feed_site_url = $qfh_ret[2];
                $last_error = $qfh_ret[3];
 
+               $vgroup_last_feed = $vgr_last_feed;
+
                if ($feed == -2) {
                        $feed_site_url = article_publish_url($link);
                }
                        error_reporting (DEFAULT_ERROR_LEVEL);
        
                        $num_unread = 0;
-       
+                       $cur_feed_title = '';
+
                        while ($line = db_fetch_assoc($result)) {
 
                                $class = ($lnum % 2) ? "even" : "odd";
                                                alt=\"Publish article\" onclick='javascript:tPub($id)'>";
                                }
 
-#                              $content_link = "<a target=\"_new\" href=\"".$line["link"]."\">" .
+#                              $content_link = "<a target=\"_blank\" href=\"".$line["link"]."\">" .
 #                                      $line["title"] . "</a>";
 
-                               $content_link = "<a href=\"javascript:view($id,$feed_id);\">" .
-                                       $line["title"] . "</a>";
+#                              $content_link = "<a 
+#                                      href=\"" . htmlspecialchars($line["link"]) . "\"
+#                                      onclick=\"view($id,$feed_id);\">" .
+#                                      $line["title"] . "</a>";
 
 #                              $content_link = "<a href=\"javascript:viewContentUrl('".$line["link"]."');\">" .
 #                                      $line["title"] . "</a>";
                                                100);
                                }
 
+                               $score = $line["score"];
+
+                               $score_pic = get_score_pic($score);
+
+                               $score_title = __("(Click to change)");
+
+                               $score_pic = "<img class='hlScorePic' src=\"images/$score_pic\" 
+                                       onclick=\"adjustArticleScore($id, $score)\" title=\"$score $score_title\">";
+
+                               if ($score > 500) {
+                                       $hlc_suffix = "H";
+                               } else if ($score < -100) {
+                                       $hlc_suffix = "L";
+                               } else {
+                                       $hlc_suffix = "";
+                               }
+
                                $entry_author = $line["author"];
 
                                if ($entry_author) {
                                        $entry_author = " - $entry_author";
                                }
 
+                               $has_feed_icon = is_file(ICONS_DIR . "/$feed_id.ico");
+
+                               if ($has_feed_icon) {
+                                       $feed_icon_img = "<img class=\"tinyFeedIcon\" src=\"".ICONS_URL."/$feed_id.ico\" alt=\"\">";
+                               } else {
+                                       //$feed_icon_img = "<img class=\"tinyFeedIcon\" src=\"images/blank_icon.gif\" alt=\"\">";
+                               }
+
                                if (!get_pref($link, 'COMBINED_DISPLAY_MODE')) {
-                                       
-                                       print "<tr class='$class' id='RROW-$id'>";
+
+                                       if (get_pref($link, 'VFEED_GROUP_BY_FEED')) {
+                                               if ($feed_id != $vgroup_last_feed && $line["feed_title"]) {
+
+                                                       $cur_feed_title = $line["feed_title"];
+                                                       $vgroup_last_feed = $feed_id;
+
+                                                       $cur_feed_title = htmlspecialchars($cur_feed_title);
+
+                                                       $vf_catchup_link = "(<a onclick='javascript:catchupFeedInGroup($feed_id);' href='#'>mark as read</a>)";
+
+                                                       print "<tr class='feedTitle'><td colspan='7'>".
+                                                               "<div style=\"float : right\">$feed_icon_img</div>".
+                                                               "<a href=\"javascript:viewfeed($feed_id, '', false)\">".
+                                                               $line["feed_title"]."</a> $vf_catchup_link</td></tr>";
+                                               }
+                                       }
+
+                                       $mouseover_attrs = "onmouseover='postMouseIn($id)' 
+                                               onmouseout='postMouseOut($id)'";
+
+                                       print "<tr class='$class' id='RROW-$id' $mouseover_attrs>";
                
                                        print "<td class='hlUpdPic'>$update_pic</td>";
                
 #                                                              truncate_string($line["feed_title"],30)."</a>&nbsp;</td>";
 #                                      } else {                        
 
-                                       print "<td class='hlContent' valign='middle'>";
+                                       print "<td onclick='view($id,$feed_id)' class='hlContent$hlc_suffix' valign='middle'>";
 
-                                       print "<a href=\"javascript:view($id,$feed_id);\">" .
+                                       print "<a id=\"RTITLE-$id\" 
+                                               href=\"" . htmlspecialchars($line["link"]) . "\"
+                                               onclick=\"return view($id,$feed_id);\">" .
                                                $line["title"];
 
                                        if (get_pref($link, 'SHOW_CONTENT_PREVIEW')) {
 #                                                      <a href=\"javascript:viewfeed($feed_id, '', false)\">".
 #                                                      $line["feed_title"]."</a>       
 
-                                       if ($line["feed_title"]) {                      
-                                               print "<span class=\"hlFeed\">
-                                                       (<a href=\"javascript:viewfeed($feed_id, '', false)\">".
-                                                       $line["feed_title"]."</a>)
-                                               </span>";
+                                       if (!get_pref($link, 'VFEED_GROUP_BY_FEED')) {
+                                               if ($line["feed_title"]) {                      
+                                                       print "<span class=\"hlFeed\">
+                                                               (<a href=\"javascript:viewfeed($feed_id, '', false)\">".
+                                                               $line["feed_title"]."</a>)
+                                                       </span>";
+                                               }
                                        }
-
-
                                        print "</td>";
-                                       
+
 #                                      }
                                        
-                                       print "<td class=\"hlUpdated\"><nobr>$updated_fmt&nbsp;</nobr></td>";
-               
+                                       print "<td class=\"hlUpdated\" onclick='view($id,$feed_id)'><nobr>$updated_fmt&nbsp;</nobr></td>";
+
+                                       print "<td class='hlMarkedPic'>$score_pic</td>";
+
+                                       if ($line["feed_title"] && !get_pref($link, 'VFEED_GROUP_BY_FEED')) {
+                                               print "<td onclick=\"viewfeed($feed_id)\" class=\"hlFeedIcon\">$feed_icon_img</td>";
+                                       }
+
                                        print "</tr>";
 
                                } else {
-                                       
+
+                                       if (get_pref($link, 'VFEED_GROUP_BY_FEED') && $line["feed_title"]) {
+                                               if ($feed_id != $vgroup_last_feed) {
+
+                                                       $cur_feed_title = $line["feed_title"];
+                                                       $vgroup_last_feed = $feed_id;
+
+                                                       $cur_feed_title = htmlspecialchars($cur_feed_title);
+
+                                                       $vf_catchup_link = "(<a onclick='javascript:catchupFeedInGroup($feed_id);' href='#'>mark as read</a>)";
+
+                                                       $has_feed_icon = is_file(ICONS_DIR . "/$feed_id.ico");
+
+                                                       if ($has_feed_icon) {
+                                                               $feed_icon_img = "<img class=\"tinyFeedIcon\" src=\"".ICONS_URL."/$feed_id.ico\" alt=\"\">";
+                                                       } else {
+                                                               //$feed_icon_img = "<img class=\"tinyFeedIcon\" src=\"images/blank_icon.gif\" alt=\"\">";
+                                                       }
+
+                                                       print "<div class='cdmFeedTitle'>".
+                                                               "<div style=\"float : right\">$feed_icon_img</div>".
+                                                               "<a href=\"javascript:viewfeed($feed_id, '', false)\">".
+                                                               $line["feed_title"]."</a> $vf_catchup_link</div>";
+                                               }
+                                       }
+
                                        if ($is_unread) {
                                                $add_class = "Unread";
                                        } else {
                                        }       
 
                                        $expand_cdm = get_pref($link, 'CDM_EXPANDED');
+                                       $show_excerpt = false;
 
-                                       if ($expand_cdm) {
+                                       if ($expand_cdm && $score >= -100) {
                                                $cdm_cstyle = "";
+                                               $show_excerpt = false;
                                        } else {
                                                $cdm_cstyle = "style=\"display : none\"";
+                                               $show_excerpt = true;
                                        }
 
+                                       $mouseover_attrs = "onmouseover='postMouseIn($id)' 
+                                               onmouseout='postMouseOut($id)'";
+
                                        print "<div class=\"cdmArticle$add_class\" 
-                                               id=\"RROW-$id\" onmouseover='cdmMouseIn(this)' 
-                                               onmouseout='cdmMouseOut(this)'>";
+                                               id=\"RROW-$id\"                                         
+                                               $mouseover_attrs'>";
 
                                        print "<div class=\"cdmHeader\">";
 
-                                       print "<div class=\"articleUpdated\">$updated_fmt</div>";
-                                       
-                                       print "<a class=\"title\" 
+                                       if (!get_pref($link, "VFEED_GROUP_BY_FEED") || !$line["feed_title"]) {
+                                               $cdm_feed_icon = "<span style=\"cursor : pointer\" onclick=\"viewfeed($feed_id)\">$feed_icon_img</span>";
+                                       }
+
+                                       print "<div class=\"articleUpdated\">$updated_fmt $score_pic $cdm_feed_icon
+                                               </div>";
+
+                                       print "<span id=\"RTITLE-$id\" class=\"titleWrap$hlc_suffix\"><a class=\"title\" 
                                                onclick=\"javascript:toggleUnread($id, 0)\"
-                                               target=\"_new\" href=\"".$line["link"]."\">".$line["title"]."</a>";
+                                               target=\"_blank\" href=\"".$line["link"]."\">".$line["title"]."</a>
+                                               ";
 
                                        print $entry_author;
 
-                                       if (!$expand_cdm) {
+/*                                     if (!$expand_cdm || $score < -100) {
                                                print "&nbsp;<a id=\"CICH-$id\" 
                                                        href=\"javascript:cdmExpandArticle($id)\">
                                                        (".__('Show article').")</a>";
-                                       } 
+                                       } */
 
 
-                                       if ($line["feed_title"]) {      
-                                               print "&nbsp;(<a href='javascript:viewfeed($feed_id)'>".$line["feed_title"]."</a>)";
+                                       if (!get_pref($link, 'VFEED_GROUP_BY_FEED')) {
+                                               if ($line["feed_title"]) {      
+                                                       print "&nbsp;(<a href='javascript:viewfeed($feed_id)'>".$line["feed_title"]."</a>)";
+                                               }
                                        }
 
-                                       print "</div>";
+                                       print "</span></div>";
 
                                        if (get_pref($link, 'OPEN_LINKS_IN_NEW_WINDOW')) {
                                                $line["content_preview"] = preg_replace("/href=/i", 
-                                                       "target=\"_new\" href=", $line["content_preview"]);
+                                                       "target=\"_blank\" href=", $line["content_preview"]);
                                        }
 
-                                       print "<div class=\"cdmContent\" id=\"CICD-$id\" $cdm_cstyle>";
+                                       if ($show_excerpt) {
+                                               print "<div class=\"cdmExcerpt\" id=\"CEXC-$id\"
+                                                       onclick=\"cdmExpandArticle($id)\"
+                                                       title=\"".__('Click to expand article')."\">";
+                                               print truncate_string(strip_tags($line["content_preview"]), 100);
+                                               print "</div>";
+                                       }
+       
+                                       print "<div class=\"cdmContent\" 
+                                               onclick=\"cdmClicked($id)\"
+                                               id=\"CICD-$id\" $cdm_cstyle>";
 
 //                                     print "<div class=\"cdmInnerContent\" id=\"CICD-$id\" $cdm_cstyle>";
-                                       print $line["content_preview"];
+
+                                       print sanitize_rss($link, $line["content_preview"]);
 
                                        $e_result = db_query($link, "SELECT * FROM ttrss_enclosures WHERE
                                                post_id = '$id' AND content_url != ''");
 
                                        $filename = substr($url, strrpos($url, "/")+1);
 
-                                       $entry = "<a target=\"_blank\" href=\"" . htmlspecialchars($url) . "\">" .
+                                       $entry = ""; 
+                                       
+                                       if (($ctype == __("audio/mpeg")) && 
+                                               (get_pref($link, "ENABLE_FLASH_PLAYER")) ) { 
+                                               
+                                               $entry .= "<object type=\"application/x-shockwave-flash\" data=\"extras/button/musicplayer.swf?song_url=$url\" width=\"17\" height=\"17\"> <param name=\"movie\" value=\"extras/button/musicplayer.swf?song_url=$url\" /> </object> "; 
+                                       
+                                       }
+
+                                       $entry .= "<a target=\"_blank\" href=\"" . htmlspecialchars($url) . "\">" .
                                                $filename . " (" . $ctype . ")" . "</a>";
 
                                        array_push($entries, $entry);
 
                                        print "</span><span class='s1'>$marked_pic</span> ";
                                        print "<span class='s1'>$published_pic</span> ";
+                                       print "<span class='s1'><img src=\"images/art-zoom.png\" class='tagsPic' 
+                                               onclick=\"zoomToArticle($id)\"
+                                               style=\"cursor : pointer\"
+                                               alt='Zoom' 
+                                               title='".__('Show article summary in new window')."'></span>";
 
                                        $tags = get_article_tags($link, $id);
 
                        print "</div>";
                }
 
-               return array($topmost_article_ids, $headlines_count, $feed, $disable_cache);
+               return array($topmost_article_ids, $headlines_count, $feed, $disable_cache, $vgroup_last_feed);
        }
 
 // from here: http://www.roscripts.com/Create_tag_cloud-71.html
 
        function article_publish_url($link) {
 
-               $url_path = ($_SERVER['HTTPS'] != "on" ? 'http://' :  'https://') . $_SERVER["HTTP_HOST"] . parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
+               $url_path = "";
+               
 
-               $url_path .= "?op=publish&key=" . get_pref($link, "_PREFS_PUBLISH_KEY");
+               if ($_SERVER['HTTPS'] != "on") {
+                       $url_path = "http://";
+               } else {
+                       $url_path = "https://";
+               }
+
+               $url_path .= $_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']);
+               $url_path .= "/backend.php?op=publish&key=" . get_pref($link, "_PREFS_PUBLISH_KEY");
 
                return $url_path;
        }
 
                // We search for feed needing update.
                $result = db_query($link, "SELECT ttrss_feeds.feed_url,ttrss_feeds.id, ttrss_feeds.owner_uid,
-                               SUBSTRING(ttrss_feeds.last_updated,1,19) AS last_updated,
+                               ".SUBSTRING_FOR_DATE."(ttrss_feeds.last_updated,1,19) AS last_updated,
                                ttrss_feeds.update_interval 
                        FROM 
                                ttrss_feeds, ttrss_users, ttrss_user_prefs
                print "</articles>";
        }
 
+       function sanitize_article_content($text) {
+               # we don't support CDATA sections in articles, they break our own escaping
+               $text = preg_replace("/\[\[CDATA/", "", $text);
+               $text = preg_replace("/\]\]\>/", "", $text);
+               return $text;
+       }
+
+       function load_filters($link, $feed, $owner_uid, $action_id = false) {
+               $filters = array();
+
+               if ($action_id) $ftype_query_part = "action_id = '$action_id' AND";
+
+               $result = db_query($link, "SELECT reg_exp,
+                       ttrss_filter_types.name AS name,
+                       ttrss_filter_actions.name AS action,
+                       inverse,
+                       action_param
+                       FROM ttrss_filters,ttrss_filter_types,ttrss_filter_actions WHERE                                        
+                               enabled = true AND
+                               $ftype_query_part
+                               owner_uid = $owner_uid AND
+                               ttrss_filter_types.id = filter_type AND
+                               ttrss_filter_actions.id = action_id AND
+                               (feed_id IS NULL OR feed_id = '$feed') ORDER BY reg_exp");
+
+               while ($line = db_fetch_assoc($result)) {
+                       if (!$filters[$line["name"]]) $filters[$line["name"]] = array();
+                               $filter["reg_exp"] = $line["reg_exp"];
+                               $filter["action"] = $line["action"];
+                               $filter["action_param"] = $line["action_param"];
+                               $filter["inverse"] = sql_bool_to_bool($line["inverse"]);
+                       
+                               array_push($filters[$line["name"]], $filter);
+                       }
+
+               return $filters;
+       }
+
+       function get_score_pic($score) {
+               if ($score > 100) { 
+                       return "score_high.png"; 
+               } else if ($score > 0) { 
+                       return "score_half_high.png"; 
+               } else if ($score < -100) {
+                       return "score_low.png"; 
+               } else if ($score < 0) {
+                       return "score_half_low.png"; 
+               } else { 
+                       return "score_neutral.png"; 
+               }
+       }
+
+       function rounded_table_start($classname, $header = "&nbsp;") {
+               print "<table width='100%' class='$classname' cellspacing='0' cellpadding='0'>";
+               print "<tr><td class='c1'>&nbsp;</td><td class='top'>$header</td><td class='c2'>&nbsp;</tr>";
+               print "<tr><td class='left'>&nbsp;</td><td class='content'>";
+       }
+
+       function rounded_table_end($footer = "&nbsp;") {
+               print "</td><td class='right'>&nbsp;</td></tr>";
+               print "<tr><td class='c4'>&nbsp;</td><td class='bottom'>$footer</td><td class='c3'>&nbsp;</tr>";
+               print "</table>";
+       }
+
+       function print_label_dlg_common_examples() {
+
+               print __("Match ") . " ";
+
+/*             print "<select name=\"label_andor\">";
+               print "<option value=\"and\">AND</option>";
+               print "<option value=\"or\">OR</option>";
+               print "</select>"; */
+
+               print "<select name=\"label_fields\" onchange=\"labelFieldsCheck(this)\">";
+               print "<option value=\"unread\">".__("Unread articles")."</option>";
+               print "<option value=\"updated\">".__("Updated articles")."</option>";
+               print "<option value=\"kw_title\">".__("Title contains")."</option>";
+               print "<option value=\"kw_content\">".__("Content contains")."</option>";
+               print "<option value=\"scoreE\">".__("Score equals")."</option>";
+               print "<option value=\"scoreG\">".__("Score is greater than")."</option>";
+               print "<option value=\"scoreL\">".__("Score is less than")."</option>";
+               print "<option value=\"newerH\">".__("Articles newer than X hours")."</option>";
+               print "<option value=\"newerD\">".__("Articles newer than X days")."</option>";
+
+               print "</select>";
+
+               print "<input style=\"display : none\" name=\"label_fields_param\"
+                       size=\"10\">";
+
+               print " <input type=\"submit\" 
+                       onclick=\"return addLabelExample()\"
+                       value=\"".__("Add")."\">";
+       }
 ?>