]> git.wh0rd.org - tt-rss.git/blobdiff - include/functions.php
api: add author to getHeadlines
[tt-rss.git] / include / functions.php
index 9a855a9bca470ab269cf2cba0aa1e69b061f27b9..307f662009b14dc83c304a86477f4a5e57c96508 100644 (file)
@@ -1,8 +1,12 @@
 <?php
        define('EXPECTED_CONFIG_VERSION', 26);
-       define('SCHEMA_VERSION', 107);
+       define('SCHEMA_VERSION', 111);
+
+       define('LABEL_BASE_INDEX', -1024);
+       define('PLUGIN_FEED_BASE_INDEX', -128);
 
        $fetch_last_error = false;
+       $fetch_last_error_code = false;
        $pluginhost = false;
 
        function __autoload($class) {
                }
        }
 
-       function fetch_file_contents($url, $type = false, $login = false, $pass = false, $post_query = false, $timeout = false) {
-               $login = urlencode($login);
-               $pass = urlencode($pass);
+       function fetch_file_contents($url, $type = false, $login = false, $pass = false, $post_query = false, $timeout = false, $timestamp = 0) {
 
                global $fetch_last_error;
+               global $fetch_last_error_code;
 
                if (function_exists('curl_init') && !ini_get("open_basedir")) {
 
                                $ch = curl_init($url);
                        }
 
+                       if ($timestamp) {
+                               curl_setopt($ch, CURLOPT_HTTPHEADER,
+                                       array("If-Modified-Since: ".gmdate('D, d M Y H:i:s \G\M\T', $timestamp)));
+                       }
+
                        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout ? $timeout : 15);
                        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout ? $timeout : 45);
                        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, !ini_get("safe_mode"));
                        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                        $content_type = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
 
+                       $fetch_last_error_code = $http_code;
+
                        if ($http_code != 200 || $type && strpos($content_type, "$type") === false) {
                                if (curl_errno($ch) != 0) {
                                        $fetch_last_error = curl_errno($ch) . " " . curl_error($ch);
 
                        return $contents;
                } else {
-                       if ($login && $pass ){
+                       if ($login && $pass){
                                $url_parts = array();
 
                                preg_match("/(^[^:]*):\/\/(.*)/", $url, $url_parts);
 
+                               $pass = urlencode($pass);
+
                                if ($url_parts[1] && $url_parts[2]) {
                                        $url = $url_parts[1] . "://$login:$pass@" . $url_parts[2];
                                }
                        if (array_search($line["pref_name"], $active_prefs) === FALSE) {
 //                             print "adding " . $line["pref_name"] . "<br>";
 
+                               $line["def_value"] = db_escape_string($link, $line["def_value"]);
+                               $line["pref_name"] = db_escape_string($link, $line["pref_name"]);
+
                                if (get_schema_version($link) < 63) {
                                        db_query($link, "INSERT INTO ttrss_user_prefs
                                                (owner_uid,pref_name,value) VALUES
        function authenticate_user($link, $login, $password, $check_only = false) {
 
                if (!SINGLE_USER_MODE) {
-
                        $user_id = false;
 
                        global $pluginhost;
                        }
 
                        if ($user_id && !$check_only) {
+                               @session_start();
+
                                $_SESSION["uid"] = $user_id;
 
                                $result = db_query($link, "SELECT login,access_level,pwd_hash FROM ttrss_users
                $_SESSION["prefs_cache"] = false;
 
                if (SINGLE_USER_MODE) {
+                       @session_start();
                        authenticate_user($link, "admin", null);
                        cache_prefs($link);
                        load_user_plugins($link, $_SESSION["uid"]);
 
                        //if (preg_match("/^-?[0-9][0-9]*$/", $feed) != false) {
 
-                       $ref_check_qpart = ($max_id &&
-                               !get_pref($link, 'REVERSE_HEADLINES')) ? "ref_id <= '$max_id'" : "true";
-
                        if (is_numeric($feed)) {
                                if ($cat_view) {
 
                                                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 unread = true
+                                                       AND unread = true
                                                        AND owner_uid = $owner_uid");
 
                                        } else if ($feed == -2) {
                                                db_query($link, "UPDATE ttrss_user_entries
                                                        SET unread = false,last_read = NOW() WHERE (SELECT COUNT(*)
                                                                FROM ttrss_user_labels2 WHERE article_id = ref_id) > 0
-                                                               AND $ref_check_qpart
                                                                AND unread = true AND owner_uid = $owner_uid");
                                        }
 
                                        db_query($link, "UPDATE ttrss_user_entries
                                                        SET unread = false,last_read = NOW()
                                                        WHERE feed_id = '$feed'
-                                                       AND $ref_check_qpart AND unread = true
+                                                       AND unread = true
                                                        AND owner_uid = $owner_uid");
 
-                               } else if ($feed < 0 && $feed > -10) { // special, like starred
+                               } else if ($feed < 0 && $feed > LABEL_BASE_INDEX) { // special, like starred
 
                                        if ($feed == -1) {
                                                db_query($link, "UPDATE ttrss_user_entries
                                                        SET unread = false,last_read = NOW()
                                                        WHERE marked = true
-                                                       AND $ref_check_qpart AND unread = true
+                                                       AND unread = true
                                                        AND owner_uid = $owner_uid");
                                        }
 
                                                db_query($link, "UPDATE ttrss_user_entries
                                                        SET unread = false,last_read = NOW()
                                                        WHERE published = true
-                                                       AND $ref_check_qpart AND unread = true
+                                                       AND unread = true
                                                        AND owner_uid = $owner_uid");
                                        }
 
                                        if ($feed == -4) {
                                                db_query($link, "UPDATE ttrss_user_entries
                                                        SET unread = false,last_read = NOW()
-                                                       WHERE $ref_check_qpart AND unread = true AND
+                                                       WHERE unread = true AND
                                                        owner_uid = $owner_uid");
                                        }
 
-                               } else if ($feed < -10) { // label
+                               } else if ($feed < LABEL_BASE_INDEX) { // label
 
-                                       $label_id = -$feed - 11;
+                                       $label_id = feed_to_label_id($feed);
 
                                        db_query($link, "UPDATE ttrss_user_entries, ttrss_user_labels2
                                                SET unread = false, last_read = NOW()
                                                        WHERE label_id = '$label_id' AND unread = true
-                                                       AND $ref_check_qpart
                                                        AND owner_uid = '$owner_uid' AND ref_id = article_id");
 
                                }
                                while ($line = db_fetch_assoc($result)) {
                                        db_query($link, "UPDATE ttrss_user_entries SET
                                                unread = false, last_read = NOW()
-                                               WHERE $ref_check_qpart AND unread = true
+                                               WHERE unread = true
                                                AND int_id = " . $line["post_int_id"]);
                                }
                                db_query($link, "COMMIT");
                                $match_part = "feed_id IS NULL";
                        }
 
-               } else if ($feed < -10) {
+               } else if ($feed < LABEL_BASE_INDEX) {
 
-                       $label_id = -$feed - 11;
+                       $label_id = feed_to_label_id($feed);
 
                        return getLabelUnread($link, $label_id, $owner_uid);
 
                        array_push($ret_arr, $cv);
                }
 
+               global $pluginhost;
+
+               if ($pluginhost) {
+                       $feeds = $pluginhost->get_feeds(-1);
+
+                       if (is_array($feeds)) {
+                               foreach ($feeds as $feed) {
+                                       $cv = array("id" => PluginHost::pfeed_to_feed_id($feed['id']),
+                                               "counter" => $feed['sender']->get_unread($feed['id']));
+
+                                       array_push($ret_arr, $cv);
+                               }
+                       }
+               }
+
                return $ret_arr;
        }
 
 
                while ($line = db_fetch_assoc($result)) {
 
-                       $id = -$line["id"] - 11;
+                       $id = label_to_feed_id($line["id"]);
 
                        $label_name = $line["caption"];
                        $count = $line["unread"];
        function getFeedCatTitle($link, $id) {
                if ($id == -1) {
                        return __("Special");
-               } else if ($id < -10) {
+               } else if ($id < LABEL_BASE_INDEX) {
                        return __("Labels");
                } else if ($id > 0) {
                        $result = db_query($link, "SELECT ttrss_feed_categories.title
                        return "images/recently_read.png";
                        break;
                default:
-                       if ($id < -10) {
+                       if ($id < LABEL_BASE_INDEX) {
                                return "images/label.png";
                        } else {
                                if (file_exists(ICONS_DIR . "/$id.ico"))
                        return __("Archived articles");
                } else if ($id == -6) {
                        return __("Recently read");
-               } else if ($id < -10) {
-                       $label_id = -$id - 11;
+               } else if ($id < LABEL_BASE_INDEX) {
+                       $label_id = feed_to_label_id($id);
                        $result = db_query($link, "SELECT caption FROM ttrss_labels2 WHERE id = '$label_id'");
                        if (db_num_rows($result) == 1) {
                                return db_fetch_result($result, 0, "caption");
                $params["default_view_limit"] = (int) get_pref($link, "_DEFAULT_VIEW_LIMIT");
                $params["default_view_order_by"] = get_pref($link, "_DEFAULT_VIEW_ORDER_BY");
                $params["bw_limit"] = (int) $_SESSION["bw_limit"];
+               $params["label_base_index"] = (int) LABEL_BASE_INDEX;
 
                $result = db_query($link, "SELECT MAX(id) AS mid, COUNT(*) AS nf FROM
                        ttrss_feeds WHERE owner_uid = " . $_SESSION["uid"]);
                                "feed_debug_update" => __("Debug feed update"),
                                "catchup_all" => __("Mark all feeds as read"),
                                "cat_toggle_collapse" => __("Un/collapse current category"),
-                               "toggle_combined_mode" => __("Toggle combined mode")),
+                               "toggle_combined_mode" => __("Toggle combined mode"),
+                               "toggle_cdm_expanded" => __("Toggle auto expand in combined mode")),
                        __("Go to") => array(
                                "goto_all" => __("All articles"),
                                "goto_fresh" => __("Fresh"),
                                "f x" => "feed_reverse",
                                "f *d" => "feed_debug_update",
                                "f *c" => "toggle_combined_mode",
+                               "f c" => "toggle_cdm_expanded",
                                "*q" => "catchup_all",
                                "x" => "cat_toggle_collapse",
 //                     "goto" => array(
 
                        $view_query_part = "";
 
-                       if ($view_mode == "adaptive" || $view_query_part == "noscores") {
+                       if ($view_mode == "adaptive") {
                                if ($search) {
                                        $view_query_part = " ";
                                } else if ($feed != -1) {
 
-                                       if (get_pref($link, "SORT_HEADLINES_BY_FEED_DATE", $owner_uid)) {
-                                               $a_date_sort_field = "updated";
-                                       } else {
-                                               $a_date_sort_field = "date_entered";
-                                       }
-
-                                       if (get_pref($link, 'REVERSE_HEADLINES', $owner_uid)) {
-                                               $a_order_by = "$a_date_sort_field";
-                                       } else {
-                                               $a_order_by = "$a_date_sort_field DESC";
-                                       }
+                                       $unread = getFeedUnread($link, $feed, $cat_view);
 
-                                       if (!$override_order) {
-                                               $override_order = "unread DESC, $a_order_by";
-                                       }
-
-                                       if (!$ignore_vfeed_group && ($is_cat || $feed_id < 0) &&
-                                                       get_pref($link, 'VFEED_GROUP_BY_FEED', $owner_uid)) {
+                                       if ($cat_view && $feed > 0 && $include_children)
+                                               $unread += getCategoryChildrenUnread($link, $feed);
 
-                                               $override_order = "ttrss_feeds.title, $override_order";
-                                       }
+                                       if ($unread > 0)
+                               $view_query_part = " unread = true AND ";
 
                                }
                        }
                                $view_query_part = " marked = true AND ";
                        }
 
+                       if ($view_mode == "has_note") {
+                               $view_query_part = " (note IS NOT NULL AND note != '') AND ";
+                       }
+
                        if ($view_mode == "published") {
                                $view_query_part = " published = true AND ";
                        }
 
-                       if ($view_mode == "unread") {
+                       if ($view_mode == "unread" && $feed != -6) {
                                $view_query_part = " unread = true AND ";
                        }
 
-                       if ($view_mode == "updated") {
-                               $view_query_part = " (last_read is null and unread = false) AND ";
-                       }
-
                        if ($limit > 0) {
                                $limit_query_part = "LIMIT " . $limit;
                        }
                                $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
                                $allow_archived = true;
 
-                               if (!$override_order) $override_order = "last_marked DESC, updated DESC";
+                               if (!$override_order) {
+                                       $override_order = "last_marked DESC, date_entered DESC, updated DESC";
+                               }
 
                        } else if ($feed == -2) { // published virtual feed OR labels category
 
                                        $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
                                        $allow_archived = true;
 
-                                       if (!$override_order) $override_order = "last_published DESC, updated DESC";
+                                       if (!$override_order) {
+                                               $override_order = "last_published DESC, date_entered DESC, updated DESC";
+                                       }
+
                                } else {
                                        $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
 
                                $intl = get_pref($link, "FRESH_ARTICLE_MAX_AGE", $owner_uid);
 
                                if (DB_TYPE == "pgsql") {
-                                       $query_strategy_part .= " AND updated > NOW() - INTERVAL '$intl hour' ";
+                                       $query_strategy_part .= " AND date_entered > NOW() - INTERVAL '$intl hour' ";
                                } else {
-                                       $query_strategy_part .= " AND updated > DATE_SUB(NOW(), INTERVAL $intl HOUR) ";
+                                       $query_strategy_part .= " AND date_entered > DATE_SUB(NOW(), INTERVAL $intl HOUR) ";
                                }
 
                                $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
                        } else if ($feed == -4) { // all articles virtual feed
                                $query_strategy_part = "true";
                                $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
-                       } else if ($feed <= -10) { // labels
-                               $label_id = -$feed - 11;
+                       } else if ($feed <= LABEL_BASE_INDEX) { // labels
+                               $label_id = feed_to_label_id($feed);
 
                                $query_strategy_part = "label_id = '$label_id' AND
                                        ttrss_labels2.id = ttrss_user_labels2.label_id AND
                                $date_sort_field = "date_entered";
                        }
 
-                       if (get_pref($link, 'REVERSE_HEADLINES', $owner_uid)) {
-                               $order_by = "$date_sort_field";
-                       } else {
-                               $order_by = "$date_sort_field DESC";
-                       }
+                       $order_by = "$date_sort_field DESC, updated DESC";
 
-                       if ($view_mode != "noscores") {
-                               $order_by = "score DESC, $order_by";
+                       if ($view_mode == "unread_first") {
+                               $order_by = "unread DESC, $order_by";
                        }
 
                        if ($override_order) {
                                                hide_images,
                                                unread,feed_id,marked,published,link,last_read,orig_feed_id,
                                                last_marked, last_published,
-                                               ".SUBSTRING_FOR_DATE."(last_read,1,19) as last_read_noms,
                                                $vfeed_query_part
                                                $content_query_part
-                                               ".SUBSTRING_FOR_DATE."(updated,1,19) as updated_noms,
                                                author,score
                                        FROM
                                                $from_qpart
                                                                "last_read," .
                                                                "(SELECT hide_images FROM ttrss_feeds WHERE id = feed_id) AS hide_images," .
                                                                "last_marked, last_published, " .
-                                                               SUBSTRING_FOR_DATE . "(last_read,1,19) as last_read_noms," .
                                                                $since_id_part .
                                                                $vfeed_query_part .
                                                                $content_query_part .
-                                                               SUBSTRING_FOR_DATE . "(updated,1,19) as updated_noms," .
                                                                "score ";
 
                                $feed_kind = "Tags";
 
                                if ($entry->nodeName == 'img') {
                                        if (($owner && get_pref($link, "STRIP_IMAGES", $owner)) ||
-                                                       $force_remove_images) {
+                                                       $force_remove_images || $_SESSION["bw_limit"]) {
 
                                                $p = $doc->createElement('p');
 
 
                }
 
+               $allowed_elements = array('a', 'address', 'audio', 'article',
+                       'b', 'big', 'blockquote', 'body', 'br', 'cite', 'center',
+                       'code', 'dd', 'del', 'details', 'div', 'dl', 'font',
+                       'dt', 'em', 'footer', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
+                       'header', 'html', 'i', 'img', 'ins', 'kbd',
+                       'li', 'nav', 'noscript', 'ol', 'p', 'pre', 'q', 's','small',
+                       'source', 'span', 'strike', 'strong', 'sub', 'summary',
+                       'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead',
+                       'tr', 'track', 'tt', 'u', 'ul', 'var', 'wbr', 'video' );
+
+               if ($_SESSION['hasSandbox']) $allowed_elements[] = 'iframe';
+
+               $disallowed_attributes = array('id', 'style', 'class');
+
                global $pluginhost;
 
                if (isset($pluginhost)) {
                        foreach ($pluginhost->get_hooks($pluginhost::HOOK_SANITIZE) as $plugin) {
-                               $doc = $plugin->hook_sanitize($doc, $site_url);
+                               $retval = $plugin->hook_sanitize($doc, $site_url, $allowed_elements, $disallowed_attributes);
+                               if (is_array($retval)) {
+                                       $doc = $retval[0];
+                                       $allowed_elements = $retval[1];
+                                       $disallowed_attributes = $retval[2];
+                               } else {
+                                       $doc = $retval;
+                               }
                        }
                }
 
                $doc->removeChild($doc->firstChild); //remove doctype
-               $doc = strip_harmful_tags($doc);
+               $doc = strip_harmful_tags($doc, $allowed_elements, $disallowed_attributes);
                $res = $doc->saveHTML();
                return $res;
        }
 
-       function strip_harmful_tags($doc) {
+       function strip_harmful_tags($doc, $allowed_elements, $disallowed_attributes) {
                $entries = $doc->getElementsByTagName("*");
 
-               $allowed_elements = array('a', 'address', 'audio', 'article',
-                       'b', 'big', 'blockquote', 'body', 'br', 'cite', 'center',
-                       'code', 'dd', 'del', 'details', 'div', 'dl', 'font',
-                       'dt', 'em', 'footer', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
-                       'header', 'html', 'i', 'img', 'ins', 'kbd',
-                       'li', 'nav', 'ol', 'p', 'pre', 'q', 's','small',
-                       'source', 'span', 'strike', 'strong', 'sub', 'summary',
-                       'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead',
-                       'tr', 'track', 'tt', 'u', 'ul', 'var', 'wbr', 'video' );
-
-               if ($_SESSION['hasSandbox']) array_push($allowed_elements, 'iframe');
-
-               $disallowed_attributes = array('id', 'style', 'class');
-
                foreach ($entries as $entry) {
                        if (!in_array($entry->nodeName, $allowed_elements)) {
                                $entry->parentNode->removeChild($entry);
        function format_warning($msg, $id = "") {
                global $link;
                return "<div class=\"warning\" id=\"$id\">
-                       <img src=\"images/sign_excl.svg\">$msg</div>";
+                       <img src=\"images/sign_excl.svg\"><div class='inner'>$msg</div></div>";
        }
 
        function format_notice($msg, $id = "") {
                global $link;
                return "<div class=\"notice\" id=\"$id\">
-                       <img src=\"images/sign_info.svg\">$msg</div>";
+                       <img src=\"images/sign_info.svg\"><div class='inner'>$msg</div></div>";
        }
 
        function format_error($msg, $id = "") {
                global $link;
                return "<div class=\"error\" id=\"$id\">
-                       <img src=\"images/sign_excl.svg\">$msg</div>";
+                       <img src=\"images/sign_excl.svg\"><div class='inner'>$msg</div></div>";
        }
 
        function print_notice($msg) {
                                array_push($entries, $entry);
                        }
 
-                       if ($_SESSION['uid'] && !get_pref($link, "STRIP_IMAGES")) {
+                       if ($_SESSION['uid'] && !get_pref($link, "STRIP_IMAGES") && !$_SESSION["bw_limit"]) {
                                if ($always_display_enclosures ||
                                                        !preg_match("/<img/i", $article_content)) {
 
                                $rv .= "<hr clear='both'/>";
                        }
 
-                       $rv .= "<br/><div dojoType=\"dijit.form.DropDownButton\">".
-                               "<span>" . __('Attachments')."</span>";
-                       $rv .= "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
+                       $rv .= "<select class=\"attachments\" onchange=\"openSelectedAttachment(this)\">".
+                               "<option value=''>" . __('Attachments')."</option>";
+
+                       foreach ($entries as $entry) {
+                               $rv .= "<option value=\"".htmlspecialchars($entry["url"])."\">" . htmlspecialchars($entry["filename"]) . "</option>";
 
-                       foreach ($entries_html as $entry) { $rv .= $entry; };
+                       };
 
-                       $rv .= "</div></div>";
+                       $rv .= "</select>";
                }
 
                return $rv;
 
                        if (count($ids) > 0) {
                                $ids = join(",", $ids);
-                               print ".";
 
                                $tmp_result = db_query($link, "DELETE FROM ttrss_tags WHERE id IN ($ids)");
                                $tags_deleted += db_affected_rows($link, $tmp_result);
                        $limit -= $limit_part;
                }
 
-               print "\n";
-
                return $tags_deleted;
        }
 
                                                break;
                                }
 
+                               if (isset($rule['inverse'])) $qpart = "NOT ($qpart)";
+
                                if (isset($rule["feed_id"]) && $rule["feed_id"] > 0) {
                                        $qpart .= " AND feed_id = " . db_escape_string($link, $rule["feed_id"]);
                                }
                                        $qpart .= " AND $cat_qpart";
                                }
 
-                               if (isset($rule['inverse'])) $qpart = "NOT ($qpart)";
-
                                array_push($query, "($qpart)");
 
                        }
                }
        }
 
+       function label_to_feed_id($label) {
+               return LABEL_BASE_INDEX - 1 - abs($label);
+       }
+
+       function feed_to_label_id($feed) {
+               return LABEL_BASE_INDEX - 1 + abs($feed);
+       }
+
 ?>