]> git.wh0rd.org - tt-rss.git/blobdiff - include/functions.php
remove expandable CDM headlines
[tt-rss.git] / include / functions.php
index b6e49716cd88ee710ede90a9fb835fb996f35761..1dd9a7a1cc7fd106d5d7a5130bac9612600fe9a6 100755 (executable)
@@ -13,7 +13,6 @@
        $fetch_last_error_content = false; // curl only for the time being
        $fetch_effective_url = false;
        $fetch_curl_used = false;
-       $suppress_debugging = false;
 
        libxml_disable_entity_loader(true);
 
 
        $schema_version = false;
 
-       function _debug_suppress($suppress) {
-               global $suppress_debugging;
-
-               $suppress_debugging = $suppress;
+       // TODO: compat wrapper, remove at some point
+       function _debug($msg) {
+           Debug::log($msg);
        }
 
-       /**
-        * Print a timestamped debug message.
-        *
-        * @param string $msg The debug message.
-        * @return void
-        */
-       function _debug($msg, $show = true) {
-               global $suppress_debugging;
-
-               //echo "[$suppress_debugging] $msg $show\n";
-
-               if ($suppress_debugging) return false;
-
-               $ts = strftime("%H:%M:%S", time());
-               if (function_exists('posix_getpid')) {
-                       $ts = "$ts/" . posix_getpid();
-               }
-
-               if ($show && !(defined('QUIET') && QUIET)) {
-                       print "[$ts] $msg\n";
-               }
-
-               if (defined('LOGFILE'))  {
-                       $fp = fopen(LOGFILE, 'a+');
-
-                       if ($fp) {
-                               $locked = false;
-
-                               if (function_exists("flock")) {
-                                       $tries = 0;
-
-                                       // try to lock logfile for writing
-                                       while ($tries < 5 && !$locked = flock($fp, LOCK_EX | LOCK_NB)) {
-                                               sleep(1);
-                                               ++$tries;
-                                       }
-
-                                       if (!$locked) {
-                                               fclose($fp);
-                                               return;
-                                       }
-                               }
-
-                               fputs($fp, "[$ts] $msg\n");
-
-                               if (function_exists("flock")) {
-                                       flock($fp, LOCK_UN);
-                               }
-
-                               fclose($fp);
-                       }
-               }
-
-       } // function _debug
-
        /**
         * Purge a feed old posts.
         *
         * @access public
         * @return void
         */
-       function purge_feed($feed_id, $purge_interval, $debug = false) {
+       function purge_feed($feed_id, $purge_interval) {
 
                if (!$purge_interval) $purge_interval = feed_purge_interval($feed_id);
 
 
                CCache::update($feed_id, $owner_uid);
 
-               if ($debug) {
-                       _debug("Purged feed $feed_id ($purge_interval): deleted $rows articles");
-               }
+        Debug::log("Purged feed $feed_id ($purge_interval): deleted $rows articles");
 
                return $rows;
        } // function purge_feed
                                // holy shit closures in php
                                // download & upload are *expected* sizes respectively, could be zero
                                curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, function($curl_handle, $download_size, $downloaded, $upload_size, $uploaded) use( &$max_size) {
-                                       //_debug("[curl progressfunction] $downloaded $max_size");
+                                       Debug::log("[curl progressfunction] $downloaded $max_size", Debug::$LOG_EXTENDED);
 
                                        return ($downloaded > $max_size) ? 1 : 0; // if max size is set, abort when exceeding it
                                });
 
                if (!SINGLE_USER_MODE) {
                        $user_id = false;
+                       $auth_module = false;
 
                        foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_AUTH_USER) as $plugin) {
 
                                $user_id = (int) $plugin->authenticate($login, $password);
 
                                if ($user_id) {
-                                       $_SESSION["auth_module"] = strtolower(get_class($plugin));
+                                       $auth_module = strtolower(get_class($plugin));
                                        break;
                                }
                        }
 
                        if ($user_id && !$check_only) {
-                               @session_start();
+
+                               session_start();
+                               session_regenerate_id(true);
 
                                $_SESSION["uid"] = $user_id;
                                $_SESSION["version"] = VERSION_STATIC;
+                               $_SESSION["auth_module"] = $auth_module;
 
                                $pdo = DB::pdo();
                                $sth = $pdo->prepare("SELECT login,access_level,pwd_hash FROM ttrss_users
        }
 
        function logout_user() {
-               session_destroy();
+               @session_destroy();
                if (isset($_COOKIE[session_name()])) {
                   setcookie(session_name(), '', time()-42000, '/');
                }
+               session_commit();
        }
 
        function validate_csrf($csrf_token) {
                                }
 
                                if (!$_SESSION["uid"]) {
-                                       @session_destroy();
-                                       setcookie(session_name(), '', time()-42000, '/');
+                                       logout_user();
 
                                        render_login_form();
                                        exit;
                                "feed_debug_viewfeed" => __("Debug viewfeed()"),
                                "catchup_all" => __("Mark all feeds as read"),
                                "cat_toggle_collapse" => __("Un/collapse current category"),
-                               "toggle_combined_mode" => __("Toggle combined mode"),
-                               "toggle_cdm_expanded" => __("Toggle auto expand in combined mode")),
+                               "toggle_combined_mode" => __("Toggle combined mode")),
                        __("Go to") => array(
                                "goto_all" => __("All articles"),
                                "goto_fresh" => __("Fresh"),
                        "f *d" => "feed_debug_update",
                        "f *g" => "feed_debug_viewfeed",
                        "f *c" => "toggle_combined_mode",
-                       "f c" => "toggle_cdm_expanded",
                        "*q" => "catchup_all",
                        "x" => "cat_toggle_collapse",
        //                      "goto" => array(
                $data["num_feeds"] = (int) $num_feeds;
 
                $data['last_article_id'] = Article::getLastArticleId();
-               $data['cdm_expanded'] = get_pref('CDM_EXPANDED');
 
                $data['dep_ts'] = calculate_dep_timestamp();
                $data['reload_on_ts_change'] = !defined('_NO_RELOAD_ON_TS_CHANGE');
                return false;
        }
 
-       function sanitize($str, $force_remove_images = false, $owner = false, $site_url = false, $highlight_words = false, $article_id = false) {
-               if (!$owner) $owner = $_SESSION["uid"];
-
-               $res = trim($str); if (!$res) return '';
+       // check for locally cached (media) URLs and rewrite to local versions
+       // this is called separately after sanitize() and plugin render article hooks to allow
+       // plugins work on original source URLs used before caching
 
+       function rewrite_cached_urls($str) {
                $charset_hack = '<head>
                                <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
                        </head>';
 
-               $res = trim($res); if (!$res) return '';
-
-               libxml_use_internal_errors(true);
+               $res = trim($str); if (!$res) return '';
 
                $doc = new DOMDocument();
                $doc->loadHTML($charset_hack . $res);
                $xpath = new DOMXPath($doc);
 
-               $rewrite_base_url = $site_url ? $site_url : get_self_url_prefix();
+               $entries = $xpath->query('(//img[@src]|//video[@poster]|//video/source[@src]|//audio/source[@src])');
 
-               $entries = $xpath->query('(//a[@href]|//img[@src]|//video/source[@src]|//audio/source[@src])');
+               $need_saving = false;
 
                foreach ($entries as $entry) {
 
-                       if ($entry->hasAttribute('href')) {
-                               $entry->setAttribute('href',
-                                       rewrite_relative_url($rewrite_base_url, $entry->getAttribute('href')));
-
-                               $entry->setAttribute('rel', 'noopener noreferrer');
-                       }
+                       if ($entry->hasAttribute('src') || $entry->hasAttribute('poster')) {
 
-                       if ($entry->hasAttribute('src')) {
-                               $src = rewrite_relative_url($rewrite_base_url, $entry->getAttribute('src'));
+                               // should be already absolutized because this is called after sanitize()
+                               $src = $entry->hasAttribute('poster') ? $entry->getAttribute('poster') : $entry->getAttribute('src');
                                $cached_filename = CACHE_DIR . '/images/' . sha1($src);
 
                                if (file_exists($cached_filename)) {
 
                                        $src = get_self_url_prefix() . '/public.php?op=cached_url&hash=' . sha1($src) . $suffix;
 
-                                       if ($entry->hasAttribute('srcset')) {
-                                               $entry->removeAttribute('srcset');
-                                       }
+                                       if ($entry->hasAttribute('poster'))
+                                               $entry->setAttribute('poster', $src);
+                                       else
+                                               $entry->setAttribute('src', $src);
 
-                                       if ($entry->hasAttribute('sizes')) {
-                                               $entry->removeAttribute('sizes');
-                                       }
+                                       $need_saving = true;
                                }
+                       }
+               }
+
+               if ($need_saving) {
+                       $doc->removeChild($doc->firstChild); //remove doctype
+                       $res = $doc->saveHTML();
+               }
+
+               return $res;
+       }
+
+       function sanitize($str, $force_remove_images = false, $owner = false, $site_url = false, $highlight_words = false, $article_id = false) {
+               if (!$owner) $owner = $_SESSION["uid"];
+
+               $res = trim($str); if (!$res) return '';
+
+               $charset_hack = '<head>
+                               <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+                       </head>';
+
+               $res = trim($res); if (!$res) return '';
+
+               libxml_use_internal_errors(true);
+
+               $doc = new DOMDocument();
+               $doc->loadHTML($charset_hack . $res);
+               $xpath = new DOMXPath($doc);
+
+               $rewrite_base_url = $site_url ? $site_url : get_self_url_prefix();
+
+               $entries = $xpath->query('(//a[@href]|//img[@src]|//video/source[@src]|//audio/source[@src])');
+
+               foreach ($entries as $entry) {
+
+                       if ($entry->hasAttribute('href')) {
+                               $entry->setAttribute('href',
+                                       rewrite_relative_url($rewrite_base_url, $entry->getAttribute('href')));
+
+                               $entry->setAttribute('rel', 'noopener noreferrer');
+                       }
+
+                       if ($entry->hasAttribute('src')) {
+                               $src = rewrite_relative_url($rewrite_base_url, $entry->getAttribute('src'));
+
+                               // cache stuff has gone to rewrite_cached_urls()
 
                                $entry->setAttribute('src', $src);
                        }
                                                }
                                        }
                                }
+                       }
 
-                               if (($owner && get_pref("STRIP_IMAGES", $owner)) ||
-                                       $force_remove_images || $_SESSION["bw_limit"]) {
+                       if ($entry->hasAttribute('src') &&
+                                       ($owner && get_pref("STRIP_IMAGES", $owner)) || $force_remove_images || $_SESSION["bw_limit"]) {
 
-                                       $p = $doc->createElement('p');
+                               $p = $doc->createElement('p');
 
-                                       $a = $doc->createElement('a');
-                                       $a->setAttribute('href', $entry->getAttribute('src'));
+                               $a = $doc->createElement('a');
+                               $a->setAttribute('href', $entry->getAttribute('src'));
 
-                                       $a->appendChild(new DOMText($entry->getAttribute('src')));
-                                       $a->setAttribute('target', '_blank');
-                                       $a->setAttribute('rel', 'noopener noreferrer');
+                               $a->appendChild(new DOMText($entry->getAttribute('src')));
+                               $a->setAttribute('target', '_blank');
+                               $a->setAttribute('rel', 'noopener noreferrer');
 
-                                       $p->appendChild($a);
+                               $p->appendChild($a);
+
+                               if ($entry->nodeName == 'source') {
+
+                                       if ($entry->parentNode && $entry->parentNode->parentNode)
+                                               $entry->parentNode->parentNode->replaceChild($p, $entry->parentNode);
+
+                               } else if ($entry->nodeName == 'img') {
+
+                                       if ($entry->parentNode)
+                                               $entry->parentNode->replaceChild($p, $entry);
 
-                                       $entry->parentNode->replaceChild($p, $entry);
                                }
                        }
 
                $sth = $pdo->prepare("SELECT access_key FROM ttrss_access_keys
                                WHERE feed_id = ? AND is_cat = ?
                                AND owner_uid = ?");
-               $sth->execute([$feed_id, (int)$is_cat, $owner_uid]);
+               $sth->execute([$feed_id, $is_cat, $owner_uid]);
 
                if ($row = $sth->fetch()) {
                        return $row["access_key"];
                                        (access_key, feed_id, is_cat, owner_uid)
                                        VALUES (?, ?, ?, ?)");
 
-                       $sth->execute([$key, $feed_id, (int)$is_cat, $owner_uid]);
+                       $sth->execute([$key, $feed_id, $is_cat, $owner_uid]);
 
                        return $key;
                }
                should be loaded systemwide in config.php */
        function send_local_file($filename) {
                if (file_exists($filename)) {
+
+                       if (is_writable($filename)) touch($filename);
+
                        $tmppluginhost = new PluginHost();
 
                        $tmppluginhost->load(PLUGINS, PluginHost::KIND_SYSTEM);